kernelthread wrote:
My suspicion would be you've set the TX FIFO trigger level so it only generates an interrupt when it's empty (MR0 bits 5,4 both zero). If you set it to generate an interrupt when the FIFO is half-empty, you should have plenty of time to refill it before the line goes idle.
Yes, I looked at that... and tried all options, I setup the FIFO size 16 bytes, didn't help. I've been going thru the code and counting clock cycles. The code is more than quick enough at 8MHz to be able to fill up the FIFO before a single character can be transmitted at 115.2K baud.
I guess I should add some code fragments here:
First, this puts data in the 128 byte circular buffer.
Code:
;Data Output A routine: puts the data in the A Reg into the xmit buffer, data in
; A Reg is preserved on exit. Transmit is IRQ driven/buffered with a size of 128 bytes.
;
CHROUT PHY ;Save Y Reg (3)
OUTCH LDY OCNT_A ;Get data output count in buffer (3)
BMI OUTCH ;Check against limit, loop back if full (2/3)
;
LDY OTAIL_A ;Get the buffer tail pointer (3)
STA OBUF_A,Y ;Place data in the buffer (5)
INC OTAIL_A ;Increment Tail pointer (5)
RMB7 OTAIL_A ;Strip off bit 7, 128 bytes only (5)
INC OCNT_A ;Increment data count (5)
;
LDY #%00000100 ;Get mask for xmit on (2)
STY UART_COMMAND_A ;Turn on xmit (4)
;
PLY ;Restore Y Reg (4)
RTS ;Return to caller (6)
;
Second, this is the ISR routine that takes buffer data and puts it into the Xmit FIFO:
Code:
; To take advantage of the onboard FIFO, we test the TxRDY bit in the Status Register.
; If the bit is set, then there is more room in the FIFO. The ISR routine here will
; attempt to fill the FIFO from the Output Buffer. This saves processing time in the
; ISR itself.
;
UARTA_XMT LDA OCNT_A ;Get output buffer count, any data to xmit? (3)
BEQ NODATA_A ;If zero, no data left, turn off xmit (2/3)
;
UARTA_XMTLP LDA UART_STATUS_A ;Get Status Register (4)
BIT #%00000100 ;Check TxRDY active (2)
BEQ REGEXT_A ;If TxRDY not set, FIFO is full, exit ISR (2/3)
;
LDY OHEAD_A ;Get the head pointer to buffer (3)
LDA OBUF_A,Y ;Get the next data (5)
STA UART_TRANSMIT_A ;Send the data to 28L92 (4)
INC OHEAD_A ;Increment head pointer (5)
RMB7 OHEAD_A ;Strip off bit 7, 128 bytes only (5)
DEC OCNT_A ;Decrement output buffer count (5)
BNE UARTA_XMTLP ;If more data, loop back to send it (2/3)
;
;No more buffer data to send, check SC28L92 TxEMT and disable transmit if empty.
; Note: If the TxEMT bit is set, then the FIFO is empty and all data has been sent.
;
NODATA_A LDA UART_STATUS_A ;Get Status Register (4)
BIT #%00001000 ;Check TxEMT empty (2)
BEQ REGEXT_A ;If TxEMT not set, more data exists (2/3)
;
LDY #%00001000 ;Else, get mask for xmit off (2)
STY UART_COMMAND_A ;Turn off xmit (4)
BRA REGEXT_A ;Exit IRQ handler (3)
;
BUFFUL_A LDY #%00000001 ;Get Mask for Buffer full (2)
STY UART_MISC ;Save into 28L92 Misc. Register (4)
;
REGEXT_A LDA UART_STATUS_A ;Get current Status Register A (4)
STA UART_SRT_A ;Save 28L92 Status Register for later use (3)
JMP (IRQRTVEC0) ;Return to Exit/ROM IRQ handler (6)
;
The code being loaded in the registers:
Code:
;Data commands are sent in reverse order from list. This list is the default initialization for
; the DUART as configured for use as a Console connected to either ExtraPutty(WIN) or Serial(OSX)
; The data here is copied to page $03 and is used to configure the DUART during boot up. The soft
; data can be changed and the core INIT_28L92 routine can be called to reconfigure the DUART.
; NOTE: the register offset data is not kept in soft config memory as the initialization
; sequence should not be changed!
;
; Both serial ports are configured at startup!
; - Port A is used as the console.
; - Port B is in idle mode.
;
INIT_DUART ;Start of DUART Initialization Data
.DB %00000011 ;Enable OP0/1 for RTS control Port A/B
.DB %00001010 ;Disable Receiver/Disable Transmitter B
.DB %00001001 ;Enable Receiver/Disable Transmitter A
.DB %00001111 ;Interrupt Mask Register setup
.DB %11100000 ;Aux Register setup for Counter/Timer
.DB %01001000 ;Counter/Timer Upper Preset
.DB %00000000 ;Counter/Timer Lower Preset
.DB %11001100 ;Baud Rate clock for Rcv/Xmt - 115.2K B
.DB %11001100 ;Baud Rate clock for Rcv/Xmt - 115.2K A
.DB %00110000 ;Reset Transmitter B
.DB %00100000 ;Reset Receiver B
.DB %00110000 ;Reset Transmitter A
.DB %00100000 ;Reset Receiver A
.DB %00000000 ;Interrupt Mask Register setup
.DB %11110000 ;Command Register A - disable Power Down
INIT_DUART_E ;End of DUART Initialization Data
;
.DB $FF ;Spare byte for offset to MR data
;
;Mode Register Data is defined separately. Using the loop routine above to send this data to
; the DUART does not work properly. See the description of the problem using Indexed addressing
; to load the DUART registers above. This data is also kept in soft config memory in page $03.
; Note that this data is also in reverse order for loading into MRs!
;
MR2_DAT_A .DB %00010111 ;Mode Register 2 data
MR1_DAT_A .DB %11010011 ;Mode Register 1 Data
MR0_DAT_A .DB %11001001 ;Mode Register 0 Data
;
MR2_DAT_B .DB %00010111 ;Mode Register 2 data
MR1_DAT_B .DB %11010011 ;Mode Register 1 Data
MR0_DAT_B .DB %11000001 ;Mode Register 0 Data
;
So, the config is setup with the FIFOs setup got 16 bytes, fill levels at the maximum for Receiver and Transmit. Watchdog is also setup for Receive, which doesn't appear to be an issue. It's just that transmit has the performance hit. Port B isn't being used at this point, but is in the configuration data and BIOS routines to support it.
Sad to say, but much my coding lately is done during consumption of a bottle of Rioja
It helps drown out background noise.