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
35 ;----------------------------------------------------------------------------
53 ;----------------------------------------------------------------------------
54 ; INSTALL: Is called after the driver is loaded into memory.
56 ; Must return an SER_ERR_xx code in a/x.
61 ;----------------------------------------------------------------------------
62 ; UNINSTALL: Is called before the driver is removed from memory.
63 ; No return code required (the driver is removed from memory on return).
68 ;----------------------------------------------------------------------------
69 ; CLOSE: Close the port and disable interrupts. Called without parameters.
70 ; Must return an SER_ERR_xx code in a/x.
74 ; Done, return an error code
79 ;----------------------------------------------------------------------------
80 ; OPEN: A pointer to a ser_params structure is passed in ptr1.
82 ; The Lynx has only two correct serial data formats:
83 ; 8 bits, parity mark, 1 stop bit
84 ; 8 bits, parity space, 1 stop bit
86 ; It also has two wrong formats;
87 ; 8 bits, even parity, 1 stop bit
88 ; 8 bits, odd parity, 1 stop bit
90 ; Unfortunately the parity bit includes itself in the calculation making
91 ; parity not compatible with the rest of the world.
93 ; We can only specify a few baud rates.
94 ; Lynx has two non-standard speeds 31250 and 62500 which are
95 ; frequently used in games.
97 ; The receiver will always read the parity and report parity errors.
99 ; Must return an SER_ERR_xx code in a/x.
110 ldy #SER_PARAMS::BAUDRATE
190 lda #<SER_ERR_BAUD_UNAVAIL
191 ldx #>SER_ERR_BAUD_UNAVAIL
199 ldx #TxOpenColl|ParEven
201 ldy #SER_PARAMS::DATABITS ; Databits
205 ldy #SER_PARAMS::STOPBITS ; Stopbits
209 ldy #SER_PARAMS::PARITY ; Parity
221 ldx #TxParEnable|TxOpenColl|ParEven
225 ldx #TxParEnable|TxOpenColl
230 ldy #SER_PARAMS::HANDSHAKE ; Handshake
236 ora #RxIntEnable|ResetErr
242 lda #<SER_ERR_INIT_FAILED
243 ldx #>SER_ERR_INIT_FAILED
246 ;----------------------------------------------------------------------------
247 ; GET: Will fetch a character from the receive buffer and store it into the
248 ; variable pointed to by ptr1. If no data is available, SER_ERR_NO_DATA is
255 lda #<SER_ERR_NO_DATA
256 ldx #>SER_ERR_NO_DATA
264 txa ; Return code = 0
267 ;----------------------------------------------------------------------------
268 ; PUT: Output character in A.
269 ; Must return an SER_ERR_xx code in a/x.
277 lda #<SER_ERR_OVERFLOW
278 ldx #>SER_ERR_OVERFLOW
291 ora #TxIntEnable|ResetErr
292 sta SERCTL ; Allow TX-IRQ to hang RX-IRQ
300 ;----------------------------------------------------------------------------
301 ; STATUS: Return the status in the variable pointed to by ptr1.
302 ; Must return an SER_ERR_xx code in a/x.
308 txa ; Return code = 0
311 ;----------------------------------------------------------------------------
312 ; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl
313 ; specific data in ptr1, and the ioctl code in A.
314 ; Must return an SER_ERR_xx code in a/x.
317 lda #<SER_ERR_INV_IOCTL
318 ldx #>SER_ERR_INV_IOCTL
321 ;----------------------------------------------------------------------------
322 ; IRQ: Called from the builtin runtime IRQ handler as a subroutine. All
323 ; registers are already saved, no parameters are passed, but the carry flag
324 ; is clear on entry. The routine must return with carry set if the interrupt
325 ; was handled, otherwise with carry clear.
327 ; Both the Tx and Rx interrupts are level sensitive instead of edge sensitive.
328 ; Due to this bug you have to disable the interrupt before clearing it.
331 lda INTSET ; Poll all pending interrupts
332 and #SERIAL_INTERRUPT
338 bmi @tx_irq ; Transmit in progress
341 and #RxParityErr|RxOverrun|RxFrameErr|RxBreak
343 tsb SerialStat ; Save error condition
346 stz TxPtrIn ; Break received - drop buffers
352 ora #RxIntEnable|ResetErr
359 ora #RxIntEnable|ResetErr
371 lda #SERIAL_INTERRUPT
380 ldx TxPtrOut ; Has all bytes been sent?
384 lda TxBuffer,x ; Send next byte
390 ora #TxIntEnable|ResetErr
392 lda #SERIAL_INTERRUPT
397 lda SERCTL ; All bytes sent
403 ora #RxIntEnable|ResetErr
406 lda #SERIAL_INTERRUPT