*****************************************************************
*****************************************************************
*								*
*	FOO.ASM - sample C25 code for demonstrating C25SIM	*
*								*
*****************************************************************
*****************************************************************

DRR	.equ	0000h
TIMER   .equ	0002h
PERIOD  .equ	0003h
IMR     .equ	0004h
STRLEN	.equ	30
STACK_SIZE .equ 100	; This stack saves context during interrupts

*****************************************************************
* Labels and variables

	; Here are globally defined labels that will appear in FOO.MAP
	.globl	_startup
	.globl	_nada
	.globl	_idle_here

	; Globally defined interrupt handler labels
	.globl	tint
	.globl	rint

	; Here are global variables that will appear in FOO.MAP
	.globl	_i
	.bss	_i,1
	.globl	_k
	.bss	_k,1
	.globl	_L
	.bss	_L,1
	.globl	rstring
	.bss	rstring,STRLEN
	.globl	cptr
	.bss	cptr,1

	.bss	sys_stack,STACK_SIZE

*****************************************************************
* Reset and interrupt vectors, and code, begin here
*****************************************************************

	.asect "vectors",0

	; Reset and interrupt vectors
	B       _startup	; 0x0000
;	B	int0		; 0x0002
;	B	int1		; 0x0004
;	B	int2		; 0x0006
	.space  (018h-$)*16
	B	tint		; 0x0018
	B	rint		; 0x001A
;	B	xint		; 0x001C
;	B	traph		; 0x001E
 
*****************************************************************
* This is the main loop
	.text

_startup:
	lrlk	AR1,sys_stack	; Set up stack pointer

	ldpk	0
	lack	500		; set up a timed interrupt for every
	sacl	TIMER		; 500 processor cycles
	sacl	PERIOD
	lack	18h		; Enable timer and receive interrupts
	sacl	IMR
	eint			; Enable interrupts globally

	lrlk	ar0,rstring
	larp	ar0
	lack	0		; Fill rstring with zeroes
	rptk	STRLEN-1
	sacl	*+
	lalk	rstring		; Set cptr pointing to rstring
	sacl	cptr

	ldpk	_k
	lack	0
	sacl	_k		; Set _k and _L to zero
	sacl	_L

	lark	ar4,0		; Set AR4 and AR5 to zero
	lark	ar5,0
L1:
	larp	ar4		; Do some bit-reverse addressing
	lark	ar0,8
	mar	*br0+,ar5
	mar	*br0-,ar0

	call	_nada		; Call a subroutine

	ldpk	_i
	lack	0 		; Set _i to zero
	sacl	_i
	lark	ar0,9		; do loop L2 ten times
L2:
	lt	_i		; _k gets set to 17 * _i
	mpyk	17
	spl	_k
	lac	_i		; _i gets incremented
	addk	1
	sacl	_i

L3:
	banz	L2,*-		; end of L2 loop

	call	_test_idle

	b	L1

*****************************************************************
* A little do-nothing subroutine

_nada:	nop
	nop
	ret

*****************************************************************
* When _L reaches 15, idle until the next interrupt

_test_idle:
	lac	_L	; if _L = 15,
	subk	15
	bnz	skip_idle
	lack	1234h	; then set _k to an odd value
	sacl	_k
_idle_here:
	idle		; and idle until the next interrupt
skip_idle:
	ret

*******************************************************************
* Macros for context save and restore, used in interrupt handlers

isave	$MACRO
	larp	ar1
	sst1	*+	; status registers
	sst	*+
	sach	*+	; accumulator
	sacl	*+
	spm	0	; P register
	sph	*+
	spl	*+
	mpyk	1	; T register
	spl	*+
	rptk	7	; the entire hardware stack
	popd	*+
	sar	ar0,*+	; all the address registers
	sar	ar2,*+
	sar	ar3,*+
	sar	ar4,*+
	sar	ar5,*+
	sar	ar6,*+
	sar	ar7,*+
	$END

irestore	$MACRO
	larp	ar1
	mar	*-	; prepare to pop stuff
	lar	ar7,*-	; get address registers
	lar	ar6,*-
	lar	ar5,*-
	lar	ar4,*-
	lar	ar3,*-
	lar	ar2,*-
	lar	ar0,*-
	rptk	7	; the hardware stack
	pshd	*-
	mar	*-
	lt	*+	; low P register
	mpyk	1
	lt	*-	; T register
	mar	*-
	lph	*-	; high P register
	zals	*-	; accumulator
	addh	*-
	lst	*-	; status registers
	lst1	*
	$END

*****************************************************************
* The timer interrupt increments _L

tint:	isave
	larp	ar0
	lrlk	ar0,_L	; increment _L
	lac	*
	addk	1
	sacl	*
	irestore
	eint
	ret

*****************************************************************
* The receive interrupt fills rstring with data

rint:	isave
	ldpk	cptr
	lar	ar0,cptr	; get a pointer into rstring from cptr
	lark	ar2,DRR
	larp	ar2
	lac	*,ar0		; get data from receive buffer
	sacl	*+		; store it in rstring
	sar	ar0,cptr	; store incremented pointer in cptr
	bnz	rint2
	lrlk	ar0,rstring	; if recevied data was zero,
	larp	ar0
	lack	0		; fill rstring with zeroes
	rptk	STRLEN-1
	sacl	*+
	lalk	rstring		; set cptr to rstring again
	sacl	cptr
rint2:	irestore
	eint
	ret

	.end
