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"
15 ; ------------------------------------------------------------------------
16 ; Header. Includes jump table
18 module_header _lynx_comlynx_ser
21 .byte $73, $65, $72 ; "ser"
22 .byte SER_API_VERSION ; Serial API version number
38 ;----------------------------------------------------------------------------
56 ;----------------------------------------------------------------------------
57 ; INSTALL: Is called after the driver is loaded into memory.
59 ; Must return an SER_ERR_xx code in a/x.
64 ;----------------------------------------------------------------------------
65 ; UNINSTALL: Is called before the driver is removed from memory.
66 ; No return code required (the driver is removed from memory on return).
71 ;----------------------------------------------------------------------------
72 ; CLOSE: Close the port and disable interrupts. Called without parameters.
73 ; Must return an SER_ERR_xx code in a/x.
77 ; Done, return an error code
82 ;----------------------------------------------------------------------------
83 ; OPEN: A pointer to a ser_params structure is passed in ptr1.
85 ; The Lynx has only two correct serial data formats:
86 ; 8 bits, parity mark, 1 stop bit
87 ; 8 bits, parity space, 1 stop bit
89 ; It also has two wrong formats;
90 ; 8 bits, even parity, 1 stop bit
91 ; 8 bits, odd parity, 1 stop bit
93 ; Unfortunately the parity bit includes itself in the calculation making
94 ; parity not compatible with the rest of the world.
96 ; We can only specify a few baud rates.
97 ; Lynx has two non-standard speeds 31250 and 62500 which are
98 ; frequently used in games.
100 ; The receiver will always read the parity and report parity errors.
102 ; Must return an SER_ERR_xx code in a/x.
113 ldy #SER_PARAMS::BAUDRATE
193 lda #<SER_ERR_BAUD_UNAVAIL
194 ldx #>SER_ERR_BAUD_UNAVAIL
202 ldx #TxOpenColl|ParEven
204 ldy #SER_PARAMS::DATABITS ; Databits
208 ldy #SER_PARAMS::STOPBITS ; Stopbits
212 ldy #SER_PARAMS::PARITY ; Parity
224 ldx #TxParEnable|TxOpenColl|ParEven
228 ldx #TxParEnable|TxOpenColl
233 ldy #SER_PARAMS::HANDSHAKE ; Handshake
239 ora #RxIntEnable|ResetErr
245 lda #<SER_ERR_INIT_FAILED
246 ldx #>SER_ERR_INIT_FAILED
249 ;----------------------------------------------------------------------------
250 ; GET: Will fetch a character from the receive buffer and store it into the
251 ; variable pointed to by ptr1. If no data is available, SER_ERR_NO_DATA is
258 lda #<SER_ERR_NO_DATA
259 ldx #>SER_ERR_NO_DATA
267 txa ; Return code = 0
270 ;----------------------------------------------------------------------------
271 ; PUT: Output character in A.
272 ; Must return an SER_ERR_xx code in a/x.
280 lda #<SER_ERR_OVERFLOW
281 ldx #>SER_ERR_OVERFLOW
294 ora #TxIntEnable|ResetErr
295 sta SERCTL ; Allow TX-IRQ to hang RX-IRQ
303 ;----------------------------------------------------------------------------
304 ; STATUS: Return the status in the variable pointed to by ptr1.
305 ; Must return an SER_ERR_xx code in a/x.
311 txa ; Return code = 0
314 ;----------------------------------------------------------------------------
315 ; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl
316 ; specific data in ptr1, and the ioctl code in A.
317 ; Must return an SER_ERR_xx code in a/x.
320 lda #<SER_ERR_INV_IOCTL
321 ldx #>SER_ERR_INV_IOCTL
324 ;----------------------------------------------------------------------------
325 ; IRQ: Called from the builtin runtime IRQ handler as a subroutine. All
326 ; registers are already saved, no parameters are passed, but the carry flag
327 ; is clear on entry. The routine must return with carry set if the interrupt
328 ; was handled, otherwise with carry clear.
330 ; Both the Tx and Rx interrupts are level sensitive instead of edge sensitive.
331 ; Due to this bug you have to disable the interrupt before clearing it.
334 lda INTSET ; Poll all pending interrupts
335 and #SERIAL_INTERRUPT
341 bmi @tx_irq ; Transmit in progress
344 and #RxParityErr|RxOverrun|RxFrameErr|RxBreak
346 tsb SerialStat ; Save error condition
349 stz TxPtrIn ; Break received - drop buffers
355 ora #RxIntEnable|ResetErr
362 ora #RxIntEnable|ResetErr
374 lda #SERIAL_INTERRUPT
383 ldx TxPtrOut ; Has all bytes been sent?
387 lda TxBuffer,x ; Send next byte
393 ora #TxIntEnable|ResetErr
395 lda #SERIAL_INTERRUPT
400 lda SERCTL ; All bytes sent
406 ora #RxIntEnable|ResetErr
409 lda #SERIAL_INTERRUPT