mirror of
https://github.com/antoinevignau/source.git
synced 2025-01-01 15:30:02 +00:00
568 lines
11 KiB
ArmAsm
568 lines
11 KiB
ArmAsm
Z8530 SCC Samples
|
|
ref. file Z8530_SCCsamples.zip
|
|
|
|
After downloading, unzip using WinZIP or a similar
|
|
utility.
|
|
|
|
Resulting file is Z8530ROUTNS.SHK
|
|
|
|
After transferring Z8530ROUTNS.SHK to your Apple IIgs,
|
|
unShrink using GS.ShrinkIt ("GSHK", "ShrinkIt.GS", ...).
|
|
|
|
|
|
|
|
|
|
The enclosed file will show you how to access the Z8530 Serial Communications
|
|
controller in the Apple IIgs, without "breaking" the system in any way. These
|
|
routines are taken from a working development version of Warp Six BBS version
|
|
9.0, a shareware program. Currently version 8.9.1 is released; version 9.0 is
|
|
still under development. Warp Six is copyright, but the enclosed routines are
|
|
dedicated to the public domain, so you can use them in any way you wish.
|
|
|
|
The code is well commented, so read it and enjoy it. It's in Merlin 16+
|
|
format.
|
|
|
|
You will also want a copy of the Zilog Z8030/Z8530 SCC Technical Manual,
|
|
published by Zilog. Here are some of their phone numbers from the back of
|
|
that same manual. Some of these may have changed, so if you can't get
|
|
through, try directory assistance at (area code) 555-1212:
|
|
|
|
Toronto, Canada (416) 673-0634
|
|
Campbell, CA, USA (408) 370-8120
|
|
Dallas, TX, USA (214) 987-9987
|
|
|
|
Munich, Germany 49-89-672-045
|
|
Tokyo, Japan 81-3-587-0528
|
|
Kowloon, Hong Kong 852-7238979
|
|
Maidenhead, UK 44-628-392-00
|
|
|
|
Note: should you find any problems with the source code, please let me know;
|
|
however, take note that I don't warrant they are bullet-proof.
|
|
---
|
|
GEnie: J.FERR CompuServe: 73057,2455 | Jim Ferr, 26-95 DeCarie Circle
|
|
Internet: 73057.2455@compuserve.com | Etobicoke, Ontario M9B 3J5 CANADA
|
|
|
|
____________
|
|
|
|
* Sample IIGS source code by Jim Ferr.
|
|
* I hereby place this code in the public domain.
|
|
* March 19, 1992.
|
|
|
|
* Apple IIgs Z8530 registers and constants
|
|
|
|
GSCMDB = $C038
|
|
GSCMDA = $C039
|
|
GSDATAB = $C03A
|
|
|
|
GSDATAA = $C03B
|
|
|
|
WR11A = %11010000 ;init wr11 in Ch A
|
|
WR11B = %01010000 ;init wr11 in Ch B
|
|
;crystal not used by Ch B
|
|
;3.6864MHz external crystal
|
|
;Rx/Tx clock source = BRG
|
|
;TRxC is an input (tied to cts)
|
|
;bits 1 and 0 insignificant
|
|
|
|
RESETCHA = %11010001 ;constant to reset Ch A
|
|
RESETCHB = %01010001 ;constant to reset Ch B
|
|
|
|
* This little routine intercepts the Interrupt
|
|
* Manager vector at $E1/0010 or wherever it may
|
|
* be in the future, pointing it to our IRQIN
|
|
* routine. We save the original manager's address
|
|
* so we can pass interrupts that aren't ours to
|
|
* the slow-poke firmware.
|
|
|
|
XC
|
|
XC
|
|
|
|
ALLOCATE SEI
|
|
CLC ;go to native mode
|
|
XCE
|
|
REP #$30 ;with 16-bit registers
|
|
MX %00
|
|
|
|
PEA $0000 ;push long
|
|
PEA $0000
|
|
PEA $0004 ;Interrupt Manager refnum
|
|
|
|
LDX #$1103 ;GetVector
|
|
JSL $E10000
|
|
|
|
PLA ;save orgmgr address
|
|
STA ORGMGR
|
|
PLA
|
|
STA ORGMGR+2
|
|
|
|
PEA $0004 ;Interrupt Manager refnum
|
|
PEA $0000 ;bank zero
|
|
PEA #IRQIN ;our manager address
|
|
|
|
LDX #$1003 ;SetVector
|
|
JSL $E10000
|
|
|
|
SEC ;emulation mode
|
|
XCE
|
|
SEP #$30 ;with 8-bit registers
|
|
MX %11
|
|
CLI
|
|
RTS
|
|
|
|
XC OFF
|
|
XC
|
|
XC ; set to full 65816 opcodes
|
|
|
|
MX %11 ; set Merlin 16+ to 8-bit mode
|
|
|
|
* Data carrier detect flag for main program
|
|
|
|
DCDSTATE DS 1 ;flag. Non-zero means no DCD.
|
|
|
|
* Default baud rate
|
|
|
|
BAUD DFB 7 ;1=300, 2=1200, 3=2400
|
|
;4=4800, 5=9600, 6=19200
|
|
;7=38400, 8=57600.
|
|
|
|
* Interrupt Manager
|
|
*
|
|
* Here is where we get the irqs and steal ours from
|
|
* the teeth of the firmware, as it were. If the irq
|
|
* isn't ours, we exit to the firmware. If it is ours,
|
|
* we process it and RTI (Return from interrupt).
|
|
|
|
LST ON
|
|
IRQIN CLC ;emulation or native mode?
|
|
LST OFF
|
|
XCE ;enter native mode
|
|
BCC :NATIVE ;was already in native mode
|
|
|
|
* Emulation mode entry
|
|
|
|
SEC ;was in emulation mode, so
|
|
XCE ;lets go back to it.
|
|
|
|
PHP ;save status for firmware
|
|
PHA ;save registers
|
|
PHX
|
|
PHY
|
|
|
|
LDA #$FF
|
|
STA :FIRST ;first time through flag
|
|
STA :EMULATE ;emulation mode flag
|
|
BRA :IRQTEST ;check if our irq
|
|
|
|
* Native mode entry
|
|
|
|
:NATIVE PHP ;save status for firmware
|
|
REP #$30 ;16-bit mode
|
|
MX %00
|
|
|
|
PHA ;save all registers
|
|
PHX
|
|
PHY
|
|
PHB ;save DBR
|
|
|
|
PEA $0000
|
|
PLB ;switch in data bank zero
|
|
PLB ;pull 16 bits
|
|
|
|
SEP #$30 ;8-bit mode
|
|
MX %11
|
|
|
|
LDA #$FF
|
|
STA :FIRST ;first time through flag
|
|
STZ :EMULATE ;kill emulation mode flag
|
|
;fall through to :IRQTEST
|
|
|
|
* Test if irq pending on SCC Channel B
|
|
|
|
:IRQTEST LDX #3
|
|
STX GSCMDA
|
|
LDA GSCMDA ;read rr3 ch A ip bits
|
|
AND #%00000101 ;check for Rx and ext/stat
|
|
;in Ch B only.
|
|
BNE :GETINT
|
|
JMP :EXIT
|
|
|
|
:GETINT STZ :FIRST ;is definitely our irq
|
|
LDX #2
|
|
STX GSCMDB
|
|
LDA GSCMDB ;get vector from rr2B
|
|
|
|
AND #%01110000 ;examine bits 6-5-4
|
|
|
|
CMP #%00100000 ;Rx?
|
|
BEQ :RX
|
|
|
|
CMP #%01100000 ;special?
|
|
BEQ :SPECIAL
|
|
;if not, must be exint.
|
|
|
|
* Handle external status interrupts
|
|
|
|
:EXINT LDA #%00010000 ;reset exint pending
|
|
STA GSCMDB
|
|
|
|
LDA GSCMDB
|
|
|
|
* The two lines below are commented out because this
|
|
* driver assumes carrier detect is in GPi.
|
|
|
|
* AND #%00100000 ;get CTS/HSKi bit
|
|
* EOR #%00100000 ;flip the CTS/HSKi bit
|
|
|
|
AND #%00001000 ;get DCD/GPi bit
|
|
EOR #%00001000 ;flip the DCD/GPi bit
|
|
|
|
STA DCDSTATE ;non-zero means offline
|
|
BRA :IRQTEST
|
|
|
|
* Special condition (error)
|
|
|
|
:SPECIAL LDX #1 ;rr1
|
|
STX GSCMDB
|
|
LDA GSCMDB
|
|
TAX
|
|
AND #%01000000 ;framing error?
|
|
BNE :BAD
|
|
TXA
|
|
AND #%00100000 ;overrun? (latched)
|
|
BEQ :BAD
|
|
|
|
LDA #%00110000 ;error reset command
|
|
STA GSCMDB ;to clear latched error.
|
|
BRA :IRQTEST
|
|
|
|
:BAD LDA GSDATAB ;eat bad character!
|
|
BRA :IRQTEST
|
|
|
|
* Get received character
|
|
|
|
:RX LDA GSDATAB ;get good char
|
|
|
|
*** STUFF DELETED (BUFFER THE CHARACTER)
|
|
|
|
BRA :IRQTEST ;test for more!
|
|
|
|
:FIRST DS 1 ;flag for first time thru
|
|
|
|
:EMULATE DS 1 ;flag/ were we in emulation
|
|
;mode or native mode.
|
|
|
|
* The ONLY exit (from IRQIN)
|
|
|
|
:EXIT BIT :EMULATE
|
|
BPL :EXIT3
|
|
|
|
* Emulation mode; irq exit routine
|
|
|
|
:EXIT1 BIT :FIRST ;first time through?
|
|
BMI :EXIT2 ;if so, not our irq
|
|
PLY
|
|
PLX
|
|
PLA
|
|
PLP ;restore status
|
|
RTI ;was ours.
|
|
|
|
:EXIT2 PLY
|
|
PLX
|
|
PLA
|
|
PLP
|
|
BRA :JUMP ;go to the firmware
|
|
|
|
* Native mode, irq exit routine
|
|
|
|
:EXIT3 BIT :FIRST ;first time through?
|
|
BMI :EXIT4 ;if so, not our irq
|
|
|
|
REP #$30 ;16-bit mode
|
|
MX %00
|
|
PLB ;restore data bank register
|
|
PLY ;restore Y
|
|
PLX ;restore X
|
|
PLA ;restore A
|
|
PLP ;restore original status
|
|
RTI ;return from interrupt
|
|
|
|
:EXIT4 REP #$30 ;16-bit mode
|
|
PLB ;restore data bank register
|
|
PLY ;restore Y
|
|
PLX ;restore X
|
|
PLA ;restore A
|
|
PLP ;restore original status
|
|
MX %11
|
|
|
|
* JML to firmware's handler (and let it worry about
|
|
* this interrupt.)
|
|
|
|
:JUMP DFB $5C ;JML
|
|
LST ON
|
|
ORGMGR DS 4 ;to original manager address
|
|
LST OFF
|
|
|
|
* This routine removes our intercept of the vector
|
|
* and restores the original firmware vector.
|
|
|
|
REMOVE SEI
|
|
JSR DISABLE ;disable modem port!
|
|
;and put it back in state
|
|
;the serial port firmware
|
|
;can handle.
|
|
CLC
|
|
XCE
|
|
REP #$30 ;full 16-bit mode
|
|
|
|
PEA $0004 ;Interrupt Manager refnum
|
|
LDA ORGMGR+2
|
|
PHA
|
|
LDA ORGMGR ;original manager address
|
|
PHA
|
|
|
|
LDX #$1003 ;SetVector
|
|
JSL $E10000
|
|
|
|
SEC ;emulation mode
|
|
XCE
|
|
SEP #$30
|
|
MX %11
|
|
CLI
|
|
RTS
|
|
|
|
* INITGS: initialize the Modem Port
|
|
* (Channel B is modem port, A is printer port)
|
|
|
|
INITGS SEI
|
|
|
|
LDA GSCMDB ;hit rr0 once to sync up
|
|
|
|
LDX #9 ;wr9
|
|
LDA #RESETCHB ;load constant to reset Ch B
|
|
;for Ch A, use RESETCHA
|
|
STX GSCMDB
|
|
STA GSCMDB
|
|
NOP ;SCC needs 11 pclck to recover
|
|
|
|
LDX #4 ;wr4
|
|
LDA #%01000100 ;X16 clock mode,
|
|
STX GSCMDB ;1 stop bit, no parity
|
|
STA GSCMDB ;could be 1.5 or 2 stop bits
|
|
;1.5 set bits 3,2 to 1,0
|
|
;2 set bits 3,2 to 1,1
|
|
LDX #3 ;wr3
|
|
LDA #%11000000 ;8 data bits, receiver disabled
|
|
STX GSCMDB ;could be 7 or 6 or 5 data bits
|
|
STA GSCMDB ;for 8 bits, bits 7,6 = 1,1
|
|
|
|
LDX #5 ;wr5
|
|
LDA #%01100010 ;DTR enabled 0=/HIGH, 8 data bits
|
|
STX GSCMDB ;no BRK, xmit disabled, no SDLC
|
|
STA GSCMDB ;RTS *MUST* be disabled, no crc
|
|
LDX #11 ;wr11
|
|
LDA #WR11B ;load constant to write
|
|
;use #WR11A for channel A
|
|
STX GSCMDB
|
|
STA GSCMDB
|
|
JSR TIMECON ;set up wr12 and wr13
|
|
;to set baud rate.
|
|
LDX #14 ;wr14
|
|
LDA #%00000000 ;null cmd, no loopback
|
|
STX GSCMDB ;no echo, /DTR follows wr5
|
|
STA GSCMDB ;BRG source is XTAL or RTxC
|
|
|
|
* Enables
|
|
|
|
ORA #%00000001 ;enable baud rate gen
|
|
LDX #14 ;wr14
|
|
STX GSCMDB
|
|
STA GSCMDB ;write value
|
|
|
|
LDA #%11000001 ;8 data bits, Rx enable
|
|
LDX #3
|
|
STX GSCMDB
|
|
STA GSCMDB ;write value
|
|
|
|
LDA #%01101010 ;DTR enabled; Tx enable
|
|
LDX #5
|
|
STX GSCMDB
|
|
STA GSCMDB ;write value
|
|
|
|
* Enable Interrupts
|
|
|
|
LDX #15 ;wr15
|
|
|
|
* The next line is commented out. This driver wants
|
|
* interrupts when GPi changes state, ie. the user
|
|
* on the BBS may have hung up. You can write a 0
|
|
* to this register if you don't need any external
|
|
* status interrupts. Then in the IRQIN routine you
|
|
* won't need handling for overruns; they won't be
|
|
* latched. See the Zilog Tech Ref. for details.
|
|
|
|
* LDA #%00100000 ;allow ext. int. on CTS/HSKi
|
|
|
|
LDA #%00001000 ;allow ext. int. on DCD/GPi
|
|
|
|
STX GSCMDB
|
|
STA GSCMDB
|
|
|
|
LDX #0
|
|
LDA #%00010000 ;reset ext. stat. ints.
|
|
STX GSCMDB
|
|
STA GSCMDB ;write it twice
|
|
|
|
STX GSCMDB
|
|
STA GSCMDB
|
|
|
|
LDX #1 ;wr1
|
|
LDA #%00010001 ;Wait Request disabled
|
|
STX GSCMDB ;allow IRQs on Rx all & ext. stat
|
|
STA GSCMDB ;No transmit interrupts (b1)
|
|
|
|
LDX #9 ;re-write wr9
|
|
LDA #%00011001 ;set Master Interrupt Enable
|
|
STX GSCMDB ;this value gives us vector
|
|
STA GSCMDB ;information with each irq,
|
|
;in vector bits 6-5-4,
|
|
;also including status.
|
|
|
|
* The vector bits are not used by firmware and IIGS
|
|
* TechNote #18. But they make irq handling easier.
|
|
|
|
;(See IRQIN routine.)
|
|
CLI
|
|
RTS ;we're done!
|
|
|
|
|
|
* DISABLE: ensure serial port IRQ's turned off
|
|
* (DTR unaffected; use HANGUP or GSDTR)
|
|
* This routine puts the port in normal firmware
|
|
* state, with no interrupts possible.
|
|
|
|
DISABLE SEI
|
|
LDA #%00000010 ;disable MIE temporarily
|
|
LDX #9
|
|
STX GSCMDB
|
|
STA GSCMDB
|
|
|
|
* Interrupt Status
|
|
|
|
LDX #1 ;wr1
|
|
LDA #%00000000 ;no DMA, no interrupts
|
|
STX GSCMDB
|
|
STA GSCMDB
|
|
|
|
LDA GSDATAB ;eat any character waiting
|
|
|
|
LDX #0 ;wr0
|
|
LDA #%00010000 ;clear any ext ints
|
|
STX GSCMDB
|
|
STA GSCMDB
|
|
|
|
STX GSCMDB ;write it twice
|
|
STA GSCMDB
|
|
|
|
LDA #%00001010 ;reset MIE for firmware use
|
|
LDX #9
|
|
STX GSCMDB
|
|
STA GSCMDB
|
|
|
|
CLI
|
|
RTS
|
|
|
|
* TIMECON: Set time constant bytes in wr12 & wr13
|
|
* (In other words, set the baud rate.)
|
|
|
|
TIMECON LDY BAUD
|
|
LDA #12
|
|
STA GSCMDB
|
|
LDA BAUDL-1,Y ;load time constant low
|
|
STA GSCMDB
|
|
|
|
LDA #13
|
|
STA GSCMDB
|
|
LDA BAUDH-1,Y ;load time constant high
|
|
STA GSCMDB
|
|
RTS
|
|
|
|
* Table of values for different baud rates. There is
|
|
* a low byte and a high byte table.
|
|
|
|
BAUDL DFB 126 ;300 bps (1)
|
|
DFB 94 ;1200 (2)
|
|
DFB 46 ;2400 (3)
|
|
DFB 22 ;4800 (4)
|
|
DFB 10 ;9600 (5)
|
|
DFB 4 ;19200 (6)
|
|
DFB 1 ;38400 (7)
|
|
DFB 0 ;57600 (8)
|
|
|
|
BAUDH DFB 1 ;300 bps (1)
|
|
DFB 0 ;1200 (2)
|
|
DFB 0 ;2400 (3)
|
|
DFB 0 ;4800 (4)
|
|
DFB 0 ;9600 (5)
|
|
DFB 0 ;19200 (6)
|
|
DFB 0 ;38400 (7)
|
|
DFB 0 ;57600 (8)
|
|
|
|
* DOBAUD: Set baud rate without resetting entire 8530
|
|
* (Stop clock, set time constant, restart clock)
|
|
|
|
DOBAUD SEI
|
|
LDA #0 ;disable BRG (stop clock)
|
|
LDX #14 ;wr14
|
|
STX GSCMDB
|
|
STA GSCMDB ;write it
|
|
|
|
JSR TIMECON ;set time constant bytes
|
|
|
|
LDA #%00000001 ;re-enable BRG
|
|
LDX #14
|
|
STX GSCMDB
|
|
STA GSCMDB
|
|
|
|
:EXIT CLI
|
|
RTS
|
|
|
|
* MOUT: send character in A to modem, regardless of
|
|
* carrier state. Preserves all registers.
|
|
|
|
MOUT STA :TEMPA
|
|
STX :TEMPX
|
|
|
|
:SEND LDA GSCMDB ;rr0
|
|
|
|
TAX
|
|
AND #%00000100 ;test bit 2 (hardware handshaking)
|
|
BEQ :SEND
|
|
TXA
|
|
AND #%00100000 ;test bit 5 (ready to send?)
|
|
BEQ :SEND
|
|
|
|
:EXIT0 LDA :TEMPA ;get char to send
|
|
STA GSDATAB ;send the character
|
|
|
|
:EXIT LDX :TEMPX
|
|
LDA :TEMPA
|
|
RTS
|
|
|
|
:TEMPA DS 1
|
|
:TEMPX DS 1
|
|
|
|
* Code for checking if data in buffer deleted
|
|
|
|
* CLRMBUF: clear mbuf.
|
|
|
|
CLRMBUF SEI
|
|
|
|
** stuff deleted (fix buffer pointers)
|
|
|
|
LDA GSDATAB ensure no data in SCC
|
|
LDA GSDATAB by reading data 3 times
|
|
LDA GSDATAB (it has a 3 byte fifo)
|
|
|
|
:EXIT CLI
|
|
RTS
|