*************************** BUFFER PROCESSING CODE ******************

***************************** EQU TABLE *****************************
* The following three values are application dependent
BASE	EQU	$0700000	; This is set according to the value in BAR
INIT	EQU	$0030300	; Initialization Routine
INT_VEC	EQU	$0031000	; Interrupt Vector for SCC1

* Commonly used Registers and Parameters
BAR	EQU	$0F2		; Base Address Register
SCR	EQU	$0F4		; System Control Register
GIMR	EQU	BASE+$0812	; Global Interrupt Mode Register
IPR	EQU	BASE+$0814	; Interrupt Pending Register
IMR	EQU	BASE+$0816	; Interrupt Mask Register
ISR	EQU	BASE+$0818	; In-Service Register
SIMODE	EQU	BASE+$08B4	; Serial Interface Mode Register
SCON1	EQU	BASE+$0882	; SCC1 Configuration Register
SCM1	EQU	BASE+$0884	; SCC1 Mode Register
SCCE1	EQU	BASE+$0888	; SCC1 Event Register
SCCM1	EQU	BASE+$088A	; SCC1 Mask Register
EN_SCC	EQU	$0C		; ENR and ENT bits in SCM

*** SCC1 Parameter Table ***
ST_BD	EQU	0		; Status and Control in BD
SS_BD	EQU	1		; Status in BD
LN_BD	EQU	2		; Data Length in BD
PT_BD	EQU	4		; Buffer pointer in BD
SZ_BD	EQU	$08		; Size of BD = 8 bytes
FCR_1	EQU	BASE+$0480	; RFCR and TFCR for SCC1
MRBLR_1	EQU	BASE+$0482	; Max Rx Buffer Length
RXBD_01	EQU	BASE+$0400	; RX BD 0 in SCC1
TXBD_01	EQU	BASE+$0440	; TX BD 0 in SCC1
READY	EQU	$07		; Ready bit in the 1st byte of TX BD
EMPTY	EQU	$07		; Empty bit in the 1st byte of RX BD
WRAP	EQU	$05		; Wrap bit in the 1st byte of BD

* The followings are application dependent, for this example
RXBF_01	EQU	$030000		; Address of the first RX buffer
TXBF_01	EQU	$030080		; Address of the first TX buffer
BD_CNT	EQU	$08		; Number of BDs used
SZ_BF	EQU	$10		; Size of buffer = 16 bytes
N_DATA	EQU	6		; Number of data to be sent in a buffer

* SCC1 HDLC Parameters
CMSKL_1	EQU	BASE+$04A0	; CRC Mask Low
CMSKH_1	EQU	BASE+$04A2	; CRC Mask High
DISFC_1	EQU	BASE+$04A8	; Discard Frame Counter
CRCEC_1	EQU	BASE+$04AA	; CRC Error Counter
ABTSC_1	EQU	BASE+$04AC	; Abort Sequence Counter
NMARC_1	EQU	BASE+$04AE	; Nonmatching Address Receive Counter
RETRC_1	EQU	BASE+$04B0	; Frame Retransmission Counter
MFLR_1	EQU	BASE+$04B2	; Max Frame Length Register
HMASK_1	EQU	BASE+$04B6	; User-Defined Frame Address Mask

******************** Typical M68302 Initialization Code *****************
* Register Initialized values in ADS board before execution
* USP=00080000 ISP=000040000 (Stack pointer not used)

	ORG	INIT		; PC=00030300

	MOVE.W	#$2700,SR	; SR=2700, mask off interrupts

* Set Base Address = $700000
* Now all 68302 on-chip peripherals begin at address $700xxx
	MOVE.W	#$0700,BAR	; BAR=0700

* Set System Control Register
	MOVE.L	#0,SCR		; Nothing special for this example

*** Setups for interrupt ***
	MOVE.W	#$0A0,GIMR	; Normal mode, v7-v5=3
	MOVE.W	#0,IMR	; Mask off all for now
	MOVE.W	#$FFFF,IPR	; Clear IPR

*** Set up Serial Interface Connection ***
* Set up PACNT, PBCNT, etc., ignore for this example, only SCC1 is used
* Select Serial Interface Mode: normal operation, NMSI mode
	MOVE.W	#0,SIMODE	; Same as default after reset

*** SCC1 Initialization ***
* Interrupt Vector: SCC1 interrupt handler is at INT_VEC=$31000
* v7-v5=3, v4-v0=$0d => vector=$6d => Execption vector = ($6d<<2) = $2b4
	MOVE.L #INT_VEC,$02B4

* Determine Configuration
* Use Baud Rate Generator for transmit and receive, Rate is 130kbps.
	MOVE.W	#$07E,SCON1

* Select SCC Mode
* HDLC, Loopback mode, CRC16, RTS* negate between frames, NRZ mode.
	MOVE.W	#$10,SCM1

* Set up Parameter RAM
	MOVE.W	#0,FCR_1	; Clear RFCR and TFCR
	MOVE.W	#$08,MRBLR_1	; Max Buffer Length = 8
	MOVE.W	#$F0B8,CMSKL_1	; 16 bit CRC
	MOVE.W	#$070,MFLR_1	; Max Frame Length = $70 bytes
	MOVE.W	#0,HMASK_1	; Do not check address
	MOVE.W	#0,DISFC_1	; Clear the counter
	MOVE.W	#0,CRCEC_1	; Clear the counter
	MOVE.W	#0,ABTSC_1	; Clear the counter
	MOVE.W	#0,NMARC_1	; Clear the counter
	MOVE.W	#0,RETRC_1	; Clear the counter

* Clear Event Register
	MOVE.B	#$FF,SCCE1

* Determine Maskable Interrupt Events by setting SCCM
* Allow the following interrupt: TXE, RFX, TXB, and RFB
	MOVE.B	#$1B,SCCM1

* Clear M68000 data registers
	CLR.L	D0
	CLR.L	D1
	CLR.L	D2
	CLR.L	D3
	CLR.L	D4
	CLR.L	D5

*** Prepare Buffer Descriptors ***
* SCC1 Rx Buffer Descriptors Initialization values before execution:
* 00700400 D000 0000 0003 0000 D000 0000 0003 0010
* 00700410 D000 0000 0003 0020 D000 0000 0003 0030
* 00700420 D000 0000 0003 0040 D000 0000 0003 0050
* 00700430 D000 0000 0003 0060 F000 0000 0003 0070

	LEA.L	RXBD_01,A0	; A0 points to the first RXBD of SCC1
	LEA.L	RXBF_01,A1	; A1 points to the first buffer
	MOVE.W	#$D000,D1	; D1 is used for setting the status of BD
*				  Empty=1, External=1, Interrupt=1
	MOVE.W	#$F000,D2	; D2 is for the last BD, Wrap=1
	MOVE.B	#BD_CNT,D3	; # of BD used = 8
	SUBQ.B	#2,D3

SetRXBD	MOVE.W	D1,ST_BD(A0)	; Set Control and Status Bits
	MOVE.W	#0,LN_BD(A0)	; Langth=0
	MOVE.L	A1,PT_BD(A0)	; Set buffer poiner
	ADDQ.L	#SZ_BD,A0	; Next BD
	ADDA.L	#SZ_BF,A1	; Next BF
	DBRA	D3,SetRXBD
* Set the last BD
	MOVE.W	D2,ST_BD(A0)	; Wrap=1
	MOVE.W	#0,LN_BD(A0)	; Length=0
	MOVE.L	A1,PT_BD(A0)	; Buffer Pointer

* SCC1 Tx Buffer Descriptors Initialization values before execution:			* 00700440 5C00 0000 0003 0080 5C00 0000 0003 0090
* 00700450 5C00 0000 0003 00A0 5C00 0000 0003 00B0
* 00700460 5C00 0000 0003 00C0 5C00 0000 0003 00D0
* 00700470 5C00 0000 0003 00E0 7C00 0000 0003 00F0
	LEA.L	TXBD_01,A0	; A0 points to the first TXBD of SCC1
	LEA.L	TXBF_01,A1	; A1 points to the first buffer
	MOVE.W	#$5C00,D1	; D1 is used for setting the status of BD
*				 Ready=0, External=1, Interrupt=1,
*				 Last=1, TxCRC=1
	MOVE.W	#$7C00,D2	; D2 is for the last BD, Wrap=1
	MOVE.L	#BD_CNT,D3	; # of BD used = 8
	SUBQ.B	#$2,D3		; Count from 6 to 0

SetTXBD	MOVE.W	D1,ST_BD(A0)	; Set Control and Status Bits
	MOVE.W	#0,LN_BD(A0)	; Langth=0
	MOVE.L	A1,PT_BD(A0)	; Set buffer poiner
	ADDQ.L	#SZ_BD,A0	; Next BD
	ADDA.L	#SZ_BF,A1	; Next BF		
	DBRA	D3,SetTXBD
* Set the last BD
	MOVE.W	D2,ST_BD(A0)	; Wrap=1
	MOVE.W	#0,LN_BD(A0)	; Length=0
	MOVE.L	A1,PT_BD(A0)	; Buffer Pointer

*** Prepare Tx Buffers: In this example each frame fits into one buffer ***
* 00030080 0001 0203 0405 0607 0809 0A0B 0C0D 0E0F
* 00030090 0001 0203 0405 0607 0809 0A0B 0C0D 0E0F
* . . . 
* 000300F0 0001 0203 0405 0607 0809 0A0B 0C0D 0E0F
	LEA.L	TXBF_01,A0	; A1 points to the first buffer
	MOVE.L	#SZ_BD,D1	; D1 is used to count the BD
	SUBQ.B	#1,D1	
NxtBF	CLR.L	D2		; D2 is used as content and counter of BF
NxtBT	MOVE.B	D2,(A0)+
	ADDQ.B	#$1,D2
	CMPI.B	#SZ_BF,D2	; Number of data in a buffer is 16
	BLT	NxtBT		; Next Byte
	DBRA	D1,NxtBF	; Next Buffer

*** Now ready to go ***
*** Set IMR and Enable SCC1 ***
	MOVE.W	#$2000,IMR	; Allow SCC1 interrupt only
	MOVE.W	#$2000,SR	; Unmask interrupts
	ORI.W	#EN_SCC,SCM1	; ENT=ENR=1
	JMP	MAIN		; Go to Main routine for Tx and Rx

**************************** Main Routine *********************************
* Set up BD pointers
MAIN	LEA.L	TXBD_01,A1	; A1 = CTD pointer
	LEA.L	TXBD_01,A2	; A2 = NTD pointer
	LEA.L	RXBD_01,A3	; A3 = PRD pointer

* The following is an infinite loop that prepares data to be sent
* when a Tx BD is available to be used.
	CLR.L	D3		; D3 is used to count Tx frames transmitted
*				  in the loop

TxReady	BTST.B	#READY,(A2)	; Test Ready Bit
	BNE.B	TxReady		; If Ready=0, the BD has been sent
Confirm	CMPI.W	#$0,LN_BD(A2)	; test NTD->datalength
	BNE.B	Confirm		; If length=0, the BD has been confirmed
* Set TXBD if it is to be changed, e.g.,
*	ORI.W	#$5C00,ST_BD(A2)
* Mask off interrupt for the following operations
	MOVE.W	#$2700,SR
	MOVE.W	#N_DATA,LN_BD(A2)	; Set datalength to 6
	BSET.B	#READY,ST_BD(A2)	; Set Ready bit
	ADDQ.L	#1,D3		; Inc Tx frame count
	BTST.B	#WRAP,ST_BD(A2)	; Test Wrap bit
	BNE.B	WrapIt		; If Wrap=1, wrap it
	ADDQ.W	#SZ_BD,A2	; Move NTD to next BD
	BRA.B	Umask
WrapIt	LEA.L	TXBD_01,A2	; Wrap back to the first TX BD
Umask	MOVE.W	#$2000,SR	; Unmask interrupt
	JMP	TxReady

***************** SCC1 Interrupt handler ***************************

	ORG	INT_VEC		; Interrupt Vector for SCC1
* Check events: Handle RX then TX then Errors
	CLR.L	D1		; Clear D1
	MOVE.B	SCCE1,D1	; SCCE1 => D1
	MOVE.L	D1,D2		; SCCE1 => D2
	ANDI.W	#9,D2		; Are RXF or RXB set?
	CMPI.W	#0,D2		; If they are set
	BNE.B	RX_INT		; Handle receiver's interrupt
CK_TX	MOVE.L	D1,D2		; SCCE1 => D2
	ANDI.W	#$12,D2		; Are TXF or TXB set?
	CMPI.W	#0,D2		; If they are set
	BNE.B	TX_INT		; Handle Transmitter's interrupt
* The handling of other events, e.g., CTS, CD IDL, BSY, is left to
* the users as desired.

OthrINT	MOVE.W	#$2000,ISR	; Clear SCC1 bit in ISR
	RTE

************* Receiver potion of SCC1 interrupt routine *************
* This routine handles received (non-empty) BD: set data length = 0,
* clear status bits, set empty = 1, and update PRD
 
* Clear the identified events as soon as possible, so as not to lost
* events occur during the interrupt handling
RX_INT	MOVE.B	#9,SCCE1	; Clear RXF and RXB in SCCE1

* While Not-Empty continue to process the next Rx BD, Else Exit.

NxtPRD	BTST.B	#EMPTY,ST_BD(A3)	; Test PRD->Empty Bit
	BNE.B	EXIT_RX			; Don't need to process if the
*					  Rx BD is still empty.

*** Check status in RXBD for erratic events ***
* If status bits are all 0 then continue, else SHUTDOWN the receiving
* process.  This in turn shuts down the whole program, since all of
* Rx BDs will soon be unavailable (all BDs Empty=0).  Thus, the 
* status of this BD will be saved for examination later.

	CMPI.B	#0,SS_BD(A3)	; Check status bits
	BNE.B	EXIT_RX
* Status bits are all 0
	CLR.W	LN_BD(A3)	; data length = 0
	CLR.B	SS_BD(A3)	; Clear out all status bits
	BSET.B	#EMPTY,ST_BD(A3)	; Empty = 1
	BTST.B	#WRAP,ST_BD(A3)	; Test Wrap bit
	BNE.B	Wrap_R		; 
	ADDQ.W	#SZ_BD,A3	; Increment PRD to next BD
	BRA.B	NxtPRD		; Back to while loop
Wrap_R	LEA.L	RXBD_01,A3	; Wrap back to the first Rx BD
	BRA.B	NxtPRD		; Back to the while loop
EXIT_RX	JMP	CK_TX		; Exit receiver potion of the handler
	 
************* Confirmer potion of SCC1 interrupt routine *************
* This routine handles transmitted (Not-ready) BD: set data length = 0,
* clear status bits, set ready = 1, and update CTD.
 
* Same as the Rx Interrupt handler, the first thing to do is to
* clear the identified events

TX_INT	MOVE.B	#$12,SCCE1	; Clear TXF and TXB in SCCE1

* While Not-Ready continue to process the next Rx BD, Else Exit.
* The Ready bit should be cleared by the CP 

NxtCTD	BTST.B	#READY,ST_BD(A1)	; Test PRD->Ready Bit
	BNE.B	EXIT_TX			; Don't need to process if the
*					  Tx BD is Ready.

* Check data length, length must be > 0 to continue the confirming process
	CMPI.W	#0,LN_BD(A1)	; Test CTD->data length
	BEQ.B	EXIT_TX
	CLR.W	LN_BD(A1)	; data length = 0
 
*** Check status in TXBD for erratic events ***
* If status bits are all 0 then continue, else SHUTDOWN the confirming
* process.  This in turn shuts down the whole program, since soon
* none of the Rx BDs will be available (all BDs Empty=0).  Thus, the 
* status of this BD will be saved for examination later.

	CMPI.B	#0,SS_BD(A1)	; Check status bits
	BNE.B	EXIT_TX
* Status bits are all 0
	CLR.B	SS_BD(A1)	; Clear out all status bits
	BTST.B	#WRAP,ST_BD(A1)	; Test Wrap bit
	BNE.B	Wrap_T		; 
	ADDQ.W	#SZ_BD,A1	; Increment CTD to next BD
	BRA.B	NxtCTD		; Back to while loop
Wrap_T	LEA.L	TXBD_01,A1	; Wrap back to the first Tx BD
	BRA.B	NxtCTD		; Back to the while loop
EXIT_TX	JMP	OthrINT		; Exit confirmer potion of the handler
*   Back to the main handler, that handle the rest of the events

*********************** Data after transmission **********************
* 00030000 0001 0203 0405 141A xxxx xxxx xxxx xxxx # Receiver Buffer 0
* 00030010 0001 0203 0405 141A xxxx xxxx xxxx xxxx # Receiver Buffer 1
* 00030020 0001 0203 0405 141A xxxx xxxx xxxx xxxx # Receiver Buffer 2
* 00030030 0001 0203 0405 141A xxxx xxxx xxxx xxxx # Receiver Buffer 3
* 00030040 0001 0203 0405 141A xxxx xxxx xxxx xxxx # Receiver Buffer 4
* 00030050 0001 0203 0405 141A xxxx xxxx xxxx xxxx # Receiver Buffer 5
* 00030060 0001 0203 0405 141A xxxx xxxx xxxx xxxx # Receiver Buffer 6
* 00030070 0001 0203 0405 141A xxxx xxxx xxxx xxxx # Receiver Buffer 7
* 00030080 0001 0203 0405 0607 0809 0A0B 0C0D 0E0F # Transmit Buffer
* Notice that 141A is the 16-bit CRC

	END

