2 ; Serial driver for the Atari Lynx ComLynx port.
4 ; Karri Kaksonen, 17.09.2009
8 .include "zeropage.inc"
9 .include "ser-kernel.inc"
10 .include "ser-error.inc"
12 ; ------------------------------------------------------------------------
13 ; Header. Includes jump table
18 .byte $73, $65, $72 ; "ser"
19 .byte SER_API_VERSION ; Serial API version number
32 ;----------------------------------------------------------------------------
50 ;----------------------------------------------------------------------------
51 ; INSTALL: Is called after the driver is loaded into memory.
53 ; Must return an SER_ERR_xx code in a/x.
58 ;----------------------------------------------------------------------------
59 ; UNINSTALL: Is called before the driver is removed from memory.
60 ; No return code required (the driver is removed from memory on return).
65 ;----------------------------------------------------------------------------
66 ; CLOSE: Close the port and disable interrupts. Called without parameters.
67 ; Must return an SER_ERR_xx code in a/x.
71 ; Done, return an error code
76 ;----------------------------------------------------------------------------
77 ; OPEN: A pointer to a ser_params structure is passed in ptr1.
79 ; The Lynx has only two correct serial data formats:
80 ; 8 bits, parity mark, 1 stop bit
81 ; 8 bits, parity space, 1 stop bit
83 ; It also has two wrong formats;
84 ; 8 bits, even parity, 1 stop bit
85 ; 8 bits, odd parity, 1 stop bit
87 ; Unfortunately the parity bit includes itself in the calculation making
88 ; parity not compatible with the rest of the world.
90 ; We can only specify a few baud rates.
91 ; Lynx has two non-standard speeds 31250 and 62500 which are
92 ; frequently used in games.
94 ; The receiver will always read the parity and report parity errors.
96 ; Must return an SER_ERR_xx code in a/x.
107 ldy #SER_PARAMS::BAUDRATE
187 lda #<SER_ERR_BAUD_UNAVAIL
188 ldx #>SER_ERR_BAUD_UNAVAIL
196 ldx #TxOpenColl|ParEven
198 ldy #SER_PARAMS::DATABITS ; Databits
202 ldy #SER_PARAMS::STOPBITS ; Stopbits
206 ldy #SER_PARAMS::PARITY ; Parity
218 ldx #TxParEnable|TxOpenColl|ParEven
222 ldx #TxParEnable|TxOpenColl
227 ldy #SER_PARAMS::HANDSHAKE ; Handshake
233 ora #RxIntEnable|ResetErr
239 lda #<SER_ERR_INIT_FAILED
240 ldx #>SER_ERR_INIT_FAILED
243 ;----------------------------------------------------------------------------
244 ; GET: Will fetch a character from the receive buffer and store it into the
245 ; variable pointed to by ptr1. If no data is available, SER_ERR_NO_DATA is
252 lda #<SER_ERR_NO_DATA
253 ldx #>SER_ERR_NO_DATA
261 txa ; Return code = 0
264 ;----------------------------------------------------------------------------
265 ; PUT: Output character in A.
266 ; Must return an SER_ERR_xx code in a/x.
274 lda #<SER_ERR_OVERFLOW
275 ldx #>SER_ERR_OVERFLOW
288 ora #TxIntEnable|ResetErr
289 sta SERCTL ; Allow TX-IRQ to hang RX-IRQ
297 ;----------------------------------------------------------------------------
298 ; STATUS: Return the status in the variable pointed to by ptr1.
299 ; Must return an SER_ERR_xx code in a/x.
305 txa ; Return code = 0
308 ;----------------------------------------------------------------------------
309 ; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl
310 ; specific data in ptr1, and the ioctl code in A.
311 ; Must return an SER_ERR_xx code in a/x.
314 lda #<SER_ERR_INV_IOCTL
315 ldx #>SER_ERR_INV_IOCTL
318 ;----------------------------------------------------------------------------
319 ; IRQ: Called from the builtin runtime IRQ handler as a subroutine. All
320 ; registers are already saved, no parameters are passed, but the carry flag
321 ; is clear on entry. The routine must return with carry set if the interrupt
322 ; was handled, otherwise with carry clear.
324 ; Both the Tx and Rx interrupts are level sensitive instead of edge sensitive.
325 ; Due to this bug you have to disable the interrupt before clearing it.
328 lda INTSET ; Poll all pending interrupts
329 and #SERIAL_INTERRUPT
335 bmi @tx_irq ; Transmit in progress
338 and #RxParityErr|RxOverrun|RxFrameErr|RxBreak
340 tsb SerialStat ; Save error condition
343 stz TxPtrIn ; Break received - drop buffers
349 ora #RxIntEnable|ResetErr
356 ora #RxIntEnable|ResetErr
368 lda #SERIAL_INTERRUPT
377 ldx TxPtrOut ; Has all bytes been sent?
381 lda TxBuffer,x ; Send next byte
387 ora #TxIntEnable|ResetErr
389 lda #SERIAL_INTERRUPT
394 lda SERCTL ; All bytes sent
400 ora #RxIntEnable|ResetErr
403 lda #SERIAL_INTERRUPT