6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Sep 21, 2024 5:21 am

All times are UTC




Post new topic Reply to topic  [ 13 posts ] 
Author Message
 Post subject: Serial fun with the 6551
PostPosted: Sun Jun 28, 2015 2:01 pm 
Offline
User avatar

Joined: Sun May 03, 2015 7:07 pm
Posts: 42
Location: London, UK
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?


Attachments:
test_03f_acia.txt [14.18 KiB]
Downloaded 227 times

_________________
All my stuff
Top
 Profile  
Reply with quote  
PostPosted: Sun Jun 28, 2015 3:32 pm 
Offline

Joined: Mon May 25, 2015 1:12 pm
Posts: 92
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.


Top
 Profile  
Reply with quote  
PostPosted: Sun Jun 28, 2015 4:07 pm 
Offline
User avatar

Joined: Sun May 03, 2015 7:07 pm
Posts: 42
Location: London, UK
DigitalDunc wrote:
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.


DigitalDunc wrote:
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.

_________________
All my stuff


Top
 Profile  
Reply with quote  
PostPosted: Sun Jun 28, 2015 5:56 pm 
Offline
User avatar

Joined: Sun May 03, 2015 7:07 pm
Posts: 42
Location: London, UK
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)?

_________________
All my stuff


Top
 Profile  
Reply with quote  
PostPosted: Sun Jun 28, 2015 6:17 pm 
Offline
User avatar

Joined: Tue Mar 05, 2013 4:31 am
Posts: 1382
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.

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


Top
 Profile  
Reply with quote  
PostPosted: Sun Jun 28, 2015 10:25 pm 
Offline
User avatar

Joined: Sun May 03, 2015 7:07 pm
Posts: 42
Location: London, UK
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:
Quote:
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?

_________________
All my stuff


Top
 Profile  
Reply with quote  
PostPosted: Sun Jun 28, 2015 10:36 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8510
Location: Southern California
With a very quick look, the only thing that jumps out that's actually wrong is:
Code:
        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:
        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:
        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:
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.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 29, 2015 2:55 am 
Offline
User avatar

Joined: Tue Mar 05, 2013 4:31 am
Posts: 1382
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.

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


Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 29, 2015 6:29 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8390
Location: Midwestern USA
floobydust wrote:
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.

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


Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 29, 2015 7:58 am 
Offline
User avatar

Joined: Sun May 03, 2015 7:07 pm
Posts: 42
Location: London, UK
@GARTHWILSON

Good catch with the #. I caught it too last nite when I got it to work
Code:
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.

_________________
All my stuff


Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 29, 2015 8:41 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8510
Location: Southern California
lenzjo wrote:
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.

Quote:
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.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 29, 2015 11:02 am 
Offline
User avatar

Joined: Sun May 03, 2015 7:07 pm
Posts: 42
Location: London, UK
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.

_________________
All my stuff


Top
 Profile  
Reply with quote  
PostPosted: Wed Jul 01, 2015 8:00 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8390
Location: Midwestern USA
GARTHWILSON wrote:
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.

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


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 13 posts ] 

All times are UTC


Who is online

Users browsing this forum: Google [Bot] and 10 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: