From: uz Date: Fri, 9 Mar 2012 10:48:59 +0000 (+0000) Subject: Added a new serial driver for the atmos. By Stefan Haubenthal. X-Git-Tag: V2.14~483 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=65a8da9fde2679c61bdf2ab4b715a8ff2e09a006;p=cc65 Added a new serial driver for the atmos. By Stefan Haubenthal. git-svn-id: svn://svn.cc65.org/cc65/trunk@5580 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- diff --git a/doc/atmos.sgml b/doc/atmos.sgml index 692977d6a..6b9755d4d 100644 --- a/doc/atmos.sgml +++ b/doc/atmos.sgml @@ -130,7 +130,16 @@ No mouse drivers are currently available for the Atmos. RS232 device drivers

-No serial drivers are currently available for the Atmos. + + + + Driver for the Telestrat integrated serial controller and the Atmos with a + serial add-on. + Note that because of the peculiarities of the 6551 chip together with the + use of the NMI, transmits are not interrupt driven, and the transceiver + blocks if the receiver asserts flow control because of a full buffer. + +

diff --git a/libsrc/Makefile b/libsrc/Makefile index fee9fbd2a..643a2f338 100644 --- a/libsrc/Makefile +++ b/libsrc/Makefile @@ -138,6 +138,7 @@ atmoslib: $(AR) a atmos.lib $$i/*.o || exit 1; \ done cp atmos/*.joy . + cp atmos/*.ser . cp atmos/*.tgi . if [ -d atmos/extra ]; then \ for i in atmos/extra/*.o; do \ diff --git a/libsrc/atmos/Makefile b/libsrc/atmos/Makefile index a36554132..5dd2ca158 100644 --- a/libsrc/atmos/Makefile +++ b/libsrc/atmos/Makefile @@ -79,7 +79,7 @@ JOYS = atmos-pase.joy MOUS = -SERS = +SERS = atmos-acia.ser TGIS = atmos-240-200-2.tgi diff --git a/libsrc/atmos/atmos-acia.s b/libsrc/atmos/atmos-acia.s new file mode 100644 index 000000000..c2b48c9fc --- /dev/null +++ b/libsrc/atmos/atmos-acia.s @@ -0,0 +1,374 @@ +; +; Serial driver for the Telestrat integrated serial controller and the +; Atmos with a serial add-on. +; +; Stefan Haubenthal, 2012-03-05 +; +; The driver is based on the cc65 rs232 module, which in turn is based on +; Craig Bruce device driver for the Switftlink/Turbo-232. +; +; SwiftLink/Turbo-232 v0.90 device driver, by Craig Bruce, 14-Apr-1998. +; +; This software is Public Domain. It is in Buddy assembler format. +; +; This device driver uses the SwiftLink RS-232 Serial Cartridge, available from +; Creative Micro Designs, Inc, and also supports the extensions of the Turbo232 +; Serial Cartridge. Both devices are based on the 6551 ACIA chip. It also +; supports the "hacked" SwiftLink with a 1.8432 MHz crystal. +; +; The code assumes that the kernal + I/O are in context. On the C128, call +; it from Bank 15. On the C64, don't flip out the Kernal unless a suitable +; NMI catcher is put into the RAM under then Kernal. For the SuperCPU, the +; interrupt handling assumes that the 65816 is in 6502-emulation mode. +; + + .include "zeropage.inc" + .include "ser-kernel.inc" + .include "ser-error.inc" + +; ------------------------------------------------------------------------ +; Header. Includes jump table + + .segment "JUMPTABLE" + + ; Driver signature + .byte $73, $65, $72 ; "ser" + .byte SER_API_VERSION ; Serial API version number + + ; Jump table. + .addr INSTALL + .addr UNINSTALL + .addr OPEN + .addr CLOSE + .addr GET + .addr PUT + .addr STATUS + .addr IOCTL + .addr IRQ + +;---------------------------------------------------------------------------- +; I/O definitions + +ACIA = $031C +ACIA_DATA = ACIA+0 ; Data register +ACIA_STATUS = ACIA+1 ; Status register +ACIA_CMD = ACIA+2 ; Command register +ACIA_CTRL = ACIA+3 ; Control register + +;---------------------------------------------------------------------------- +; Global variables + + .bss + +RecvHead: .res 1 ; Head of receive buffer +RecvTail: .res 1 ; Tail of receive buffer +RecvFreeCnt: .res 1 ; Number of bytes in receive buffer +SendHead: .res 1 ; Head of send buffer +SendTail: .res 1 ; Tail of send buffer +SendFreeCnt: .res 1 ; Number of bytes in send buffer + +Stopped: .res 1 ; Flow-stopped flag +RtsOff: .res 1 ; + +RecvBuf: .res 256 ; Receive buffers: 256 bytes +SendBuf: .res 256 ; Send buffers: 256 bytes + +Index: .res 1 ; I/O register index + + .rodata + + ; Tables used to translate RS232 params into register values +BaudTable: ; bit7 = 1 means setting is invalid + .byte $FF ; SER_BAUD_45_5 + .byte $01 ; SER_BAUD_50 + .byte $02 ; SER_BAUD_75 + .byte $03 ; SER_BAUD_110 + .byte $04 ; SER_BAUD_134_5 + .byte $05 ; SER_BAUD_150 + .byte $06 ; SER_BAUD_300 + .byte $07 ; SER_BAUD_600 + .byte $08 ; SER_BAUD_1200 + .byte $09 ; SER_BAUD_1800 + .byte $0A ; SER_BAUD_2400 + .byte $0B ; SER_BAUD_3600 + .byte $0C ; SER_BAUD_4800 + .byte $0D ; SER_BAUD_7200 + .byte $0E ; SER_BAUD_9600 + .byte $0F ; SER_BAUD_19200 + .byte $FF ; SER_BAUD_38400 + .byte $FF ; SER_BAUD_57600 + .byte $FF ; SER_BAUD_115200 + .byte $FF ; SER_BAUD_230400 +BitTable: + .byte $60 ; SER_BITS_5 + .byte $40 ; SER_BITS_6 + .byte $20 ; SER_BITS_7 + .byte $00 ; SER_BITS_8 +StopTable: + .byte $00 ; SER_STOP_1 + .byte $80 ; SER_STOP_2 +ParityTable: + .byte $00 ; SER_PAR_NONE + .byte $20 ; SER_PAR_ODD + .byte $60 ; SER_PAR_EVEN + .byte $A0 ; SER_PAR_MARK + .byte $E0 ; SER_PAR_SPACE + + .code + +;---------------------------------------------------------------------------- +; INSTALL: Is called after the driver is loaded into memory. If possible, +; check if the hardware is present. Must return an SER_ERR_xx code in a/x. +; +; Since we don't have to manage the IRQ vector on the Telestrat/Atmos, this is +; actually the same as: +; +; UNINSTALL: Is called before the driver is removed from memory. +; No return code required (the driver is removed from memory on return). +; +; and: +; +; CLOSE: Close the port and disable interrupts. Called without parameters. +; Must return an SER_ERR_xx code in a/x. + +INSTALL: +UNINSTALL: +CLOSE: + ldx Index ; Check for open port + beq :+ + + ; Deactivate DTR and disable 6551 interrupts + lda #%00001010 + sta ACIA_CMD,x + + ; Done, return an error code +: lda #SER_ERR_INIT_FAILED + rts + + ; Baud rate not available +InvBaud:lda #SER_ERR_BAUD_UNAVAIL + rts + +;---------------------------------------------------------------------------- +; GET: Will fetch a character from the receive buffer and store it into the +; variable pointed to by ptr1. If no data is available, SER_ERR_NO_DATA is +; returned. + +GET: + ldy SendFreeCnt ; Send data if necessary + iny ; Y == $FF? + beq :+ + lda #$00 ; TryHard = false + jsr TryToSend + + ; Check for buffer empty +: lda RecvFreeCnt ; (25) + cmp #$FF + bne :+ + lda #SER_ERR_NO_DATA + rts + + ; Check for flow stopped & enough free: release flow control +: ldy Stopped ; (34) + beq :+ + cmp #63 + bcc :+ + lda #$00 + sta Stopped + lda RtsOff + ora #%00001000 + sta ACIA_CMD + + ; Get byte from buffer +: ldy RecvHead ; (41) + lda RecvBuf,y + inc RecvHead + inc RecvFreeCnt + ldx #$00 ; (59) + sta (ptr1,x) + txa ; Return code = 0 + rts + +;---------------------------------------------------------------------------- +; PUT: Output character in A. +; Must return an SER_ERR_xx code in a/x. + +PUT: + ; Try to send + ldy SendFreeCnt + iny ; Y = $FF? + beq :+ + pha + lda #$00 ; TryHard = false + jsr TryToSend + pla + + ; Put byte into send buffer & send +: ldy SendFreeCnt + bne :+ + lda #SER_ERR_OVERFLOW + rts + +: ldy SendTail + sta SendBuf,y + inc SendTail + dec SendFreeCnt + lda #$FF ; TryHard = true + jsr TryToSend + lda #SER_ERR_INV_IOCTL + rts + +;---------------------------------------------------------------------------- +; IRQ: Called from the builtin runtime IRQ handler as a subroutine. All +; registers are already saved, no parameters are passed, but the carry flag +; is clear on entry. The routine must return with carry set if the interrupt +; was handled, otherwise with carry clear. + +IRQ: + ldx Index ; Check for open port + beq Done + lda ACIA_STATUS,x ; Check ACIA status for receive interrupt + and #$08 + beq Done ; Jump if no ACIA interrupt + lda ACIA_DATA,x ; Get byte from ACIA + ldy RecvFreeCnt ; Check if we have free space left + beq Flow ; Jump if no space in receive buffer + ldy RecvTail ; Load buffer pointer + sta RecvBuf,y ; Store received byte in buffer + inc RecvTail ; Increment buffer pointer + dec RecvFreeCnt ; Decrement free space counter + ldy RecvFreeCnt ; Check for buffer space low + cpy #33 + bcc Flow ; Assert flow control if buffer space low + rts ; Interrupt handled (carry already set) + + ; Assert flow control if buffer space too low +Flow: lda RtsOff + sta ACIA_CMD,x + sta Stopped + sec ; Interrupt handled +Done: rts + +;---------------------------------------------------------------------------- +; Try to send a byte. Internal routine. A = TryHard + +TryToSend: + sta tmp1 ; Remember tryHard flag +Again: lda SendFreeCnt + cmp #$FF + beq Quit ; Bail out + + ; Check for flow stopped + lda Stopped + bne Quit ; Bail out + + ; Check that ACIA is ready to send + lda ACIA_STATUS + and #$10 + bne Send + bit tmp1 ; Keep trying if must try hard + bmi Again +Quit: rts + + ; Send byte and try again +Send: ldy SendHead + lda SendBuf,y + sta ACIA_DATA + inc SendHead + inc SendFreeCnt + jmp Again