OK, I finally got my board working again. I'm embarrassed to admit how long it took due to a stupid coding error on my part.
Anyway, I have built a small daughter card for my SBC that uses the infamous 65C51 (confirmed bug).
I started noticing it was dropping characters so I did a little research and found some code on here that puts a delay into the transmit method.
It works...mostly.
I'd say it went from 60% working to 85%.
Typing "this is a long line" yields something like "this isa lng line". Close, but no cigar.
So, my question is, should I just keep tweaking with the delay routine until I get it right or is there a bullet proof method already known by everyone?
FWIW, my machine is currently running at 1 MHz. (I took it down from 4 MHz until the dust settles).
mon.asm
Code:
;-------------------------------------------------------------------------------
; Main RESET Vector (ROM Startup)
;-------------------------------------------------------------------------------
.segment "CODE"
.org $8000
NMI_vec:
IRQ_vec:
RES_vec:
JSR INITS
LDY #0
@LOOP:
LDA MSG, Y
BEQ MAIN
JSR ACIA_ECHO
INY
JMP @LOOP
;-------------------------------------------------------------------------------
; MAIN Loop
;-------------------------------------------------------------------------------
MAIN:
INC VIA_PORTA
JSR ACIA_READ
JSR ACIA_ECHO
JMP MAIN
;-------------------------------------------------------------------------------
; System Initialization
;-------------------------------------------------------------------------------
INITS:
CLD ; Clear decimal arithmetic mode.
CLI ; Clear interrupts
JSR VIA_INIT ; Initialize onboard VIA
JSR ACIA_INIT ; Initialize ACIA
RTS
MSG:
.byte "Welcome to Potpourri6502", CR, LF, $00
;-------------------------------------------------------------------------------
; Startup Vectors
;-------------------------------------------------------------------------------
.segment "VECTORS"
.word NMI_vec ; NMI Vector
.word RES_vec ; RESET Vector
.word IRQ_vec ; IRQ Vector
acia.asm
Code:
;-------------------------------------------------------------------------------
; Register Locations
; TODO Move $5800 to config file? Is it worth it?
;-------------------------------------------------------------------------------
ACIA := $5800
ACIA_CTRL := ACIA + 3
ACIA_CMD := ACIA + 2
ACIA_SR := ACIA + 1
ACIA_RX := ACIA
ACIA_TX := ACIA
;-------------------------------------------------------------------------------
; Name: ACIA_INIT
; Desc: Configures base setup
; 19200,N,8,1
; Destroys: Nothing
;-------------------------------------------------------------------------------
.byte "ACIA" ; Tag this segment. Remove to save four bytes.
ACIA_INIT:
PHA ; Push A to stack
LDA #$1F ; %0001 1111 = 19200 Baud
; External receiver
; 8 bit words
; 1 stop bit
STA ACIA_CTRL
LDA #$0B ; %0000 1011 = Receiver odd parity check
; Parity mode disabled
; Receiver normal mode
; RTSB Low, trans int disabled
; IRQB disabled
; Data terminal ready (DTRB low)
STA ACIA_CMD
PLA ; Restore A
RTS
;-------------------------------------------------------------------------------
; Name: ACIA_ECHO
; Desc: Sends data to serial port
; Destroys: A
; Note: TODO - Add fix for 65C51 transmit bug
; It was recommended to use ~521 microseconds
; (or a little more) delay.
;-------------------------------------------------------------------------------
ACIA_ECHO:
PHA ; Push A to stack
LDA #$10 ; 16, %00010000
ACIA_TX_FULL:
BIT ACIA_SR ; Wait for TDRE bit = 1
BEQ ACIA_TX_FULL
PLA ; Pull A from stack
STA ACIA_TX ; Send A
JSR DELAY_6551
RTS
;-------------------------------------------------------------------------------
; Name: ACIA_READ
; Desc: Reads data from serial port and return in A
; Destroys: A
; Note: Probably not compatible with EhBASIC because it is
; blocking
;-------------------------------------------------------------------------------
ACIA_READ:
LDA #$08
ACIA_RX_FULL:
BIT ACIA_SR ; Check to see if the buffer is full
BEQ ACIA_RX_FULL
LDA ACIA_RX
RTS
; Latest WDC 65C51 has a bug - Xmit bit in status register is stuck on
; IRQ driven transmit is not possible as a result - interrupts are endlessly triggered
; Polled I/O mode also doesn't work as the Xmit bit is polled - delay routine is the only option
; The following delay routine kills time to allow W65C51 to complete a character transmit
; 0.523 milliseconds required loop time for 19,200 baud rate
; MINIDLY routine takes 524 clock cycles to complete - X Reg is used for the count loop
; Y Reg is loaded with the CPU clock rate in MHz (whole increments only) and used as a multiplier
;
DELAY_6551:
PHY ;Save Y Reg
PHX ;Save X Reg
DELAY_LOOP:
; LDY #2 ;Get delay value (clock rate in MHz 2 clock cycles)
LDY #1 ;Get delay value (clock rate in MHz 1 clock cycles)
MINIDLY:
LDX #$68 ;Seed X reg
DELAY_1:
DEX ;Decrement low index
BNE DELAY_1 ;Loop back until done
DEY ;Decrease by one
BNE MINIDLY ;Loop until done
PLX ;Restore X Reg
PLY ;Restore Y Reg
DELAY_DONE:
RTS ;Delay done, return
PS, not sure why my code blocks are uneven. They are fine in my text editor...
Thanks!!!