;*****************************************************************************************
; Copyright © [01/26/1999] Scenix Semiconductor, Inc. All rights reserved.
;
; Scenix Semiconductor, Inc. assumes no responsibility or liability for
; the use of this [product, application, software, any of these products].
; Scenix Semiconductor conveys no license, implicitly or otherwise, under
; any intellectual property rights.
; Information contained in this publication regarding (e.g.: application,
; implementation) and the like is intended through suggestion only and may
; be superseded by updates. Scenix Semiconductor makes no representation
; or warranties with respect to the accuracy or use of these information,
; or infringement of patents arising from such use or otherwise.
;*****************************************************************************************
; 
; Filename:	SPI DEMOM.SRC	
;
; Revision:	1.02
;
; Part:		SX28AC datecode 9929AA
; Freq:		50Mhz
; Compiled using Parallax SX-Key software v1.07 and SASM 1.40
;
; Date Written: 07.21.98
;
; Last Revised: 11.29.99
;
; Program Description:
;
;
;	SPI DEMO provides an example of data transfer between two 
;       SX microcontrollers through the SPI data bus using two SPI VPs.
;	SPI DEMO consists of two programs - SPI DEMOM.SRC and SPI DEMOS.SRC, 
;	which correspond to the SPI Master and SPI Slave sides accordingly.
;       The are 4 signal lines that connect the Master to the Slave:
;
;		Master-Out-Slave-In		MOSI signal line
;		Master-In-Slave_Out		MISO signal line
;		Serial Clock			SCLK signal line
;		Slave Select			SS signal line
;
;	The Slave Select (SS) Line from Master to Slave signals the 
;	latter to start sending/receiving data. The word length is set 
;	to 16 bits in this demo (VP permits 1 to 16 bits). 
;
;	SPI virtual perphirals perform shifting in and out at 
;	the same time, as most hardware SPI implemetations do. 
;
;	The demo works as follows:
;       - Assuming that Slave has been initialized prior to Master,
;	  the Master sends The Predefined Word 256 times.
;       - The Slave SX is configured to perform the loopback function, 
;	  that is, every time Slave sends to the Master whatever it has 
;	  received from the Master during the previous transmission.
;       - After the initial 256 transmissions Master switches into 
;	  the loopback mode.
;	- The data transfer of The Predefined Word can be easily observed 
;         with the help of oscilloscope. 
;
;	SPI clock period for this demo is 900 nsec - maximum clock 
;	rate supported	by the SPIS (SPI Slave VP).
;	
;	Data transfer from Master side is triggered by RTCC interrupt with
;	a period of 25.6 microseconds.
;
;
;	Connect two SX devices together as shown below to test the demo.
;	Use an oscilloscope to verify the correct data transfer.
;									
;	SX 1		RB.0----SCLK----------RB.0 		SX 2
;  SPI DEMOM.SRC	RB.1----MOSI----------RB.2  	   SPI DEMOS.SRC
;      MASTER		RB.2----MISO----------RB.1     	        SLAVE
;			RB.3----SS------------RB.3
;
;
;=======================================================================
;
;	For documentation regarding the SPIM (SPI Master) Virtual Peripheral 
;	consult the SPIM.SRC file or the SPI application note available at
;	www.scenix.com
;
;
;=======================================================================
;
; Revision History:
;	1.0  - 07.21.98	- Core SPI code implemted on SX
;	1.01 - 08.12.99	- Tested and improved SPI VP to ensure transfer integrity
;	1.02 - 08.12.99 - Updated source with new VP template and tested using SASM
;			  Also moved the global variables into banked memory
;*****************************************************************************************

;*****************************************************************************************
; Target SX
; Uncomment one of the following lines to choose the SX18AC, SX20AC, SX28AC, SX48BD/ES,
; SX48BD, SX52BD/ES or SX52BD. For SX48BD/ES and SX52BD/ES, uncomment both defines,
; SX48_52 and SX48_52_ES.
;*****************************************************************************************
;SX18_20
SX28
;SX48_52
;SX48_52_ES

;*****************************************************************************************
; Assembler Used
; Uncomment the following line if using the Parallax SX-Key assembler. SASM assembler
; enabled by default.
;*****************************************************************************************
;SX_Key

	;*********************************************************************************
	; Assembler directives:
	;	high speed external osc, turbo mode, 8-level stack, and extended option reg.
	;
	;	SX18/20/28 - 4 pages of program memory and 8 banks of RAM enabled by default.
	;	SX48/52 - 8 pages of program memory and 16 banks of RAM enabled by default.
	;                
	;*********************************************************************************

IFDEF SX_Key 				;SX-Key Directives
  IFDEF SX18_20				;SX18AC or SX20AC device directives for SX-Key
		device	SX18L,oscxt4,turbo,stackx_optionx
  ENDIF
  IFDEF SX28				;SX28AC device directives for SX-Key		
		device	SX28L,oscxt4,turbo,stackx_optionx
  ENDIF
  IFDEF SX48_52_ES			;SX48BD/ES or SX52BD/ES device directives for SX-Key
		device	oschs,turbo,stackx,optionx
  ELSE
    IFDEF SX48_52			;SX48/52/BD device directives for SX-Key
		device	oschs2,stackx_optionx
    ENDIF
  ENDIF
		freq	50_000_000
ELSE  					;SASM Directives
  IFDEF SX18_20				;SX18AC or SX20AC device directives for SASM
		device	SX18,oschs2,turbo,stackx,optionx
  ENDIF
  IFDEF SX28				;SX28AC device directives for SASM
		device	SX28,oschs2,turbo,stackx,optionx
  ENDIF
  IFDEF SX48_52_ES			;SX48BD/ES or SX52BD/ES device directives for SASM
		device	SX52,oschs,turbo,stackx,optionx
  ELSE
    IFDEF SX48_52			;SX48BD or SX52BD device directives for SASM
		device	SX52,oschs2,stackx,optionx   
    ENDIF
  ENDIF
ENDIF
		id	'SPIDEMOM'
		reset	reset_entry		; set reset vector

;*****************************************************************************************
; Macros
;*****************************************************************************************

	;*********************************************************************************
	; Macro: _bank
	; Sets the bank appropriately for all revisions of SX.
	;
	; This is required since the bank instruction has only a 3-bit operand, it cannot
	; be used to access all 16 banks of the SX48/52. For this reason FSR.4 (for SX48/52BD/ES)
	; or FSR.7 (SX48/52bd production release) needs to be set appropriately, depending
	; on the bank address being accessed. This macro fixes this.
	;
	; So, instead of using the bank instruction to switch between banks, use _bank instead.
	; 
	;*********************************************************************************
_bank	macro	1
	bank	\1

	IFDEF SX48_52
	  IFDEF SX48_52_ES
	    IF \1 & %00010000		;SX48BD/ES and SX52BD/ES (engineering sample) bank instruction
		setb	fsr.4		;modifies FSR bits 5,6 and 7. FSR.4 needs to be set by software.
	    ENDIF
	  ELSE
	    IF \1 & %10000000		;SX48BD and SX52BD (production release) bank instruction 
		setb	fsr.7		;modifies FSR bits 4,5 and 6. FSR.7 needs to be set by software.
	    ELSE
		clrb	fsr.7
	    ENDIF
	  ENDIF
	ENDIF
	endm

	;*********************************************************************************
	; Macro: _mode
	; Sets the MODE register appropriately for all revisions of SX.
	;
	; This is required since the MODE (or MOV M,#) instruction has only a 4-bit operand. 
	; The SX18/20/28AC use only 4 bits of the MODE register, however the SX48/52BD have 
	; the added ability of reading or writing some of the MODE registers, and therefore use
	; 5-bits of the MODE register. The  MOV M,W instruction modifies all 8-bits of the 
	; MODE register, so this instruction must be used on the SX48/52BD to make sure the MODE
	; register is written with the correct value. This macro fixes this.
	;
	; So, instead of using the MODE or MOV M,# instructions to load the M register, use
	;  _mode instead.
	; 
	;*********************************************************************************
_mode	macro	1
	IFDEF SX48_52
		mov	w,#\1		;loads the M register correctly for the SX48BD and SX52BD
		mov	m,w
	ELSE
		mov	m,#\1		;loads the M register correctly for the SX18AC, SX20AC
					;and SX28AC
	ENDIF
	endm

;*****************************************************************************************
; Data Memory address definitions
; These definitions ensure the proper address is used for banks 0 - 7 for 2K SX devices
; (SX18/20/28) and 4K SX devices (SX48/52). 
;*****************************************************************************************
IFDEF SX48_52

global_org	=	$0A
bank0_org	=	$00
bank1_org	=	$10
bank2_org	=	$20
bank3_org	=	$30
bank4_org	=	$40
bank5_org	=	$50
bank6_org	=	$60
bank7_org	=	$70

ELSE

global_org	=	$08
bank0_org	=	$10
bank1_org	=	$30
bank2_org	=	$50
bank3_org	=	$70
bank4_org	=	$90
bank5_org	=	$B0
bank6_org	=	$D0
bank7_org	=	$F0

ENDIF
;*****************************************************************************************
; Global Register definitions
; NOTE: Global data memory starts at $0A on SX48/52 and $08 on SX18/20/28.
;*****************************************************************************************
		org     global_org

sys_timer_rate		equ	global_org+1		;RTCC reload value for MAIN program			

;*****************************************************************************************
; RAM Bank Register definitions
;*****************************************************************************************

	;*********************************************************************************
	; Bank 0
	;*********************************************************************************
		org     bank0_org

bank0		=	$


	;*********************************************************************************
	; Bank 1
	;*********************************************************************************
		org     bank1_org

bank1			=	$
SPIM_BANK		=	$

;SPIM control data
spim_demo_cmd		ds	1		;SPIM_CMD for DEMO

spim_cmd		ds	1		;SPIM command byte
	fast_ON		equ	spim_cmd.4	;set to 1 for SPIM mode is used
	master_ON	equ	spim_cmd.5	;set to 1 if MASTER
	rising_ON	equ	spim_cmd.6	;set to 1 if RISING
	transmit_ON	equ	spim_cmd.7	;set to 1 if TRANSMIT

spim_clk_mask		ds	1		;defines SPI Clock pin
spim_portb_mask		ds	1		;PortB direction register image

;SPIM status data
spim_status		ds	1		;SPIM status byte
	spim_cmd_error	equ	spim_status.4	;error - unsupported comand
	
;SPIS I/O buffer
spim_msb		ds	1		;I/O data buffer
spim_lsb		ds	1
spim_demo_data_MSB	ds	1		;predefined data for SPI transfer to Slave		
spim_demo_data_LSB	ds	1

;SPIS private data

spim_shift_counter	ds	1		;I/O shift counter

spim_bits_total		ds	1		;number of bits to transfer
spim_shifts_init	ds	1		;number of bits for initial shift
	
spim_rate		ds	1		;clock rate factor
spim_rate_counter	ds	1		;clock rate delay counter

	;*********************************************************************************
	; Bank 2 - Used to store demo variables
	;*********************************************************************************
		org     bank2_org
bank2		=	$
DEMO_VARS	=	$

demo_rate		ds	1		;SPIM_RATE for DEMO
demo_init_cycles	ds 	1		;numder of initial cycles when SPIM
						;sends to Slave prederfined SPI_DEMO_DATA
demo_init_counter	ds	1		;counter of initial cycles

	;*********************************************************************************
	; Bank 3
	;*********************************************************************************
		org     bank3_org
bank3		=	$

	;*********************************************************************************
	; Bank 4
	;*********************************************************************************
		org     bank4_org
bank4		=	$

	;*********************************************************************************
	; Bank 5
	;*********************************************************************************
		org     bank5_org
bank5		=	$

	;*********************************************************************************
	; Bank 6
	;*********************************************************************************
		org     bank6_org
bank6		=	$

	;*********************************************************************************
	; Bank 7
	;*********************************************************************************
		org     bank7_org
bank7		=	$

IFDEF SX48_52
	;*********************************************************************************
	; Bank 8
	;*********************************************************************************
		org	$80	;bank 8 address on SX52
bank8		=	$

	;*********************************************************************************
	; Bank 9
	;*********************************************************************************
		org	$90	;bank 9 address on SX52
bank9		=	$

	;*********************************************************************************
	; Bank A
	;*********************************************************************************
		org	$A0	;bank A address on SX52
bankA		=	$

	;*********************************************************************************
	; Bank B
	;*********************************************************************************
		org	$B0	;bank B address on SX52
bankB		=	$

	;*********************************************************************************
	; Bank C
	;*********************************************************************************
		org	$C0	;bank C address on SX52
bankC		=	$

	;*********************************************************************************
	; Bank D
	;*********************************************************************************
		org	$D0	;bank D address on SX52
bankD		=	$

	;*********************************************************************************
	; Bank E
	;*********************************************************************************
		org	$E0	;bank E address on SX52
bankE		=	$

	;*********************************************************************************
	; Bank F
	;*********************************************************************************
		org	$F0	;bank F address on SX52

bankF		=	$

ENDIF
;*****************************************************************************************
; Port Assignment
;*****************************************************************************************

RA_latch	equ	%00000000		;SX18/20/28/48/52 port A latch init
RA_DDIR		equ	%11111111		;SX18/20/28/48/52 port A DDIR value
RA_LVL		equ	%00000000		;SX18/20/28/48/52 port A LVL value
RA_PLP		equ	%11111111		;SX18/20/28/48/52 port A PLP value

RB_latch	equ	%00000000		;SX18/20/28/48/52 port B latch init
RB_DDIR		equ	%11110100		;SX18/20/28/48/52 port B DDIR value
RB_ST		equ	%11111111		;SX18/20/28/48/52 port B ST value
RB_LVL		equ	%00000000		;SX18/20/28/48/52 port B LVL value
RB_PLP		equ	%11111111		;SX18/20/28/48/52 port B PLP value

RC_latch	equ	%00000000		;SX18/20/28/48/52 port C latch init
RC_DDIR		equ	%11111010		;SX18/20/28/48/52 port C DDIR value
RC_ST		equ	%11111111		;SX18/20/28/48/52 port C ST value
RC_LVL		equ	%00000000		;SX18/20/28/48/52 port C LVL value
RC_PLP		equ	%11111111		;SX18/20/28/48/52 port C PLP value
		
IFDEF SX48_52	;SX48BD/52BD Port initialization values
RD_latch	equ	%00000000		;SX48/52 port D latch init
RD_DDIR		equ	%11111111		;SX48/52 port D DDIR value
RD_ST		equ	%11111111		;SX48/52 port D ST value
RD_LVL		equ	%00000000		;SX48/52 port D LVL value
RD_PLP		equ	%11111111		;SX48/52 port D PLP value

RE_latch	equ	%00000000		;SX48/52 port E latch init
RE_DDIR		equ	%11111111		;SX48/52 port E DDIR value
RE_ST		equ	%11111111		;SX48/52 port E ST value
RE_LVL		equ	%00000000		;SX48/52 port E LVL value
RE_PLP		equ	%11111111		;SX48/52 port E PLP value
ENDIF
	;*********************************************************************************
	; Pin Definitions
	;*********************************************************************************
; Change the I/O pin assignments to suit your application

spim_port		=	rb		;SPI port for clock pin

spim_clk_pin		=	spim_port.0	;SPI clock line
spim_out_pin		=	spim_port.1	;master_in slave_out line
spim_in_pin		=	spim_port.2	;master_out slave_in line 
spim_MCU_cs_pin		=	spim_port.3	;slave select/slave request micro


;*****************************************************************************************
; Program constants
;*****************************************************************************************


IFDEF SX48_52
	;*********************************************************************************
	; SX48BD/52BD Mode addresses
	; *On SX48BD/52BD, most registers addressed via mode are read and write, with the
	; exception of CMP and WKPND which do an exchange with W.
	;*********************************************************************************
; Timer (read) addresses
TCPL_R		equ	$02		;Read Timer Capture register low byte
TCPH_R		equ	$02		;Read Timer Capture register high byte
TR2CML_R	equ	$02		;Read Timer R2 low byte
TR2CMH_R	equ	$03		;Read Timer R2 high byte
TR1CML_R	equ	$04		;Read Timer R1 low byte
TR1CMH_R	equ	$05 		;Read Timer R1 high byte
TCNTB_R		equ	$06		;Read Timer control register B
TCNTA_R		equ	$07		;Read Timer control register A

; Exchange addresses
CMP		equ	$08		;Exchange Comparator enable/status register with W
WKPND		equ	$09		;Exchange MIWU/RB Interrupts pending with W

; Port setup (read) addresses
WKED_R		equ	$0A		;Read MIWU/RB Interrupt edge setup, 0 = falling, 1 = rising
WKEN_R		equ	$0B		;Read MIWU/RB Interrupt edge setup, 0 = enabled, 1 = disabled
ST_R		equ	$0C		;Read Port Schmitt Trigger setup, 0 = enabled, 1 = disabled
LVL_R		equ	$0D		;Read Port Schmitt Trigger setup, 0 = enabled, 1 = disabled
PLP_R		equ	$0E		;Read Port Schmitt Trigger setup, 0 = enabled, 1 = disabled
DDIR_R		equ	$0F		;Read Port Direction

; Timer (write) addresses
TR2CML_W	equ	$12		;Write Timer R2 low byte
TR2CMH_W	equ	$13		;Write Timer R2 high byte
TR1CML_W	equ	$14		;Write Timer R1 low byte
TR1CMH_W	equ	$15 		;Write Timer R1 high byte
TCNTB_W		equ	$16		;Write Timer control register B
TCNTA_W		equ	$17		;Write Timer control register A

; Port setup (write) addresses
WKED_W		equ	$1A		;Write MIWU/RB Interrupt edge setup, 0 = falling, 1 = rising
WKEN_W		equ	$1B		;Write MIWU/RB Interrupt edge setup, 0 = enabled, 1 = disabled
ST_W		equ	$1C		;Write Port Schmitt Trigger setup, 0 = enabled, 1 = disabled
LVL_W		equ	$1D		;Write Port Schmitt Trigger setup, 0 = enabled, 1 = disabled
PLP_W		equ	$1E		;Write Port Schmitt Trigger setup, 0 = enabled, 1 = disabled
DDIR_W		equ	$1F		;Write Port Direction

ELSE

	;*********************************************************************************
	; SX18AC/20AC/28AC Mode addresses
	; *On SX18/20/28, all registers addressed via mode are write only, with the exception of
	; CMP and WKPND which do an exchange with W.
	;*********************************************************************************
; Exchange addresses
CMP		equ	$08		;Exchange Comparator enable/status register with W
WKPND		equ	$09		;Exchange MIWU/RB Interrupts pending with W

; Port setup (read) addresses
WKED_W		equ	$0A		;Write MIWU/RB Interrupt edge setup, 0 = falling, 1 = rising
WKEN_W		equ	$0B		;Write MIWU/RB Interrupt edge setup, 0 = enabled, 1 = disabled
ST_W		equ	$0C		;Write Port Schmitt Trigger setup, 0 = enabled, 1 = disabled
LVL_W		equ	$0D		;Write Port Schmitt Trigger setup, 0 = enabled, 1 = disabled
PLP_W		equ	$0E		;Write Port Schmitt Trigger setup, 0 = enabled, 1 = disabled
DDIR_W		equ	$0F		;Write Port Direction
ENDIF

;*****************************************************************************************
; Interrupt Service Routine
;*****************************************************************************************
; Note: The interrupt code must always originate at address $0.
;
; Interrupt Frequency = (Cycle Frequency / -(retiw value))  For example:
; With a retiw value of -217 and an oscillator frequency of 50MHz, this
; code runs every 4.34us.
;*****************************************************************************************
		org     $0
interrupt					;3

	;*********************************************************************************
	; Virtual Peripheral:  SPI Master
	;
	;	Input variable(s): spim_cmd, spim_demo_data_msb, spim_demo_data_LSB, spim_rate
	;			spim_clk,mask
	;	Output variable(s): spim_out_pin, spim_clk_pin, spim_MCU_cs_pin
	;	Variable(s) affected: spim_rate_counter, spim_shift_counter, spim_bits_total
	;	Flag(s) affected: spim_status flags
	;*********************************************************************************
spim_execute		_bank	SPIM_BANK			;set SPIM RAM bank
			snb	master_ON
			jb	fast_ON,spim_cmd_proc		;begin decoding SPIM_CMD
			setb	spim_cmd_error			;unsupported command
	
spim_exit		clr	spim_cmd			;SPIM exit
			jmp	spim_done
;decode SPIM_CMD 
spim_cmd_proc		
			mov	spim_msb,spim_demo_data_MSB	;initialize I/O buffer
			mov	spim_lsb,spim_demo_data_LSB

			sb	rising_ON			;set the SPI_CLK polarity
			clrb	spim_clk_pin
			snb	rising_ON
			setb	spim_clk_pin

			mov	w,spim_cmd			;set number of bits to transfer	
			and	w,#$0f				;decode four LSBits of SPIM_CMD
			mov	spim_bits_total,w	
			test	spim_bits_total
			snz
			mov	spim_bits_total,#$10

			mov	spim_shift_counter,spim_bits_total ;set shift bit counter
			mov	spim_shifts_init,#$10
			sub	spim_shifts_init,spim_bits_total   ;set initial shifts counter

			call	spim_SS_set			;activate user defined SS lines

			test	spim_shifts_init		;initial shift needed? 
			jz	:spim

;prepare data for transfer
:set_bit_position	clc					;initial shift for the data < 16 bit long
			rl	spim_lsb
			rl	spim_msb
			djnz	spim_shifts_init,:set_bit_position

;data transfer
:spim			test	spim_shift_counter	
			jz	:spim_execute_exit
;shift bit out
			mov	spim_rate_counter,spim_rate	;define transfer rate
			djnz	spim_rate_counter,$		;in shift data out cycle

			movb	spim_out_pin,spim_msb.7		;shift data out
			xor	spim_port,spim_clk_mask		;change SPI Clock state
			dec	spim_shift_counter	
			rl	spim_lsb
			rl	spim_msb
;shift bit in
			mov	spim_rate_counter,spim_rate	;define transfer rate
			djnz	spim_rate_counter,$		;in shift data in cycle

			movb	spim_lsb.0,spim_in_pin

			xor	spim_port,spim_clk_mask		;change SPI clock state
			jmp	:spim

:spim_execute_exit	call	spim_SS_reset			;disable SS
			clr	spim_cmd			;SPIM exit
	
spim_done
	;*********************************************************************************
	; Set Interrupt Rate
	;*********************************************************************************
			mov	w,sys_timer_rate	; Set RTCC overflow rate
			retiw	

;*****************************************************************************************
; End of the Interrupt Service Routine
;*****************************************************************************************

;*****************************************************************************************
; SPI Subroutines
;*****************************************************************************************

;user defined subroutines to generate SPI SS signal
spim_SS_set		clrb	spim_MCU_cs_pin		;set MCU__SS active (low)
			ret

spim_SS_reset		setb	spim_MCU_cs_pin		;set MCU__SS passive (high)
			ret

;*****************************************************************************************
; RESET VECTOR 
;*****************************************************************************************

	;*********************************************************************************
	; Program execution begins here on power-up or after a reset
	;*********************************************************************************
reset_entry		
	;*********************************************************************************
	; Initialise all port configuration
	;*********************************************************************************
		_mode	ST_W			;point MODE to write ST register
		mov     w,#RB_ST            	;Setup RB Schmitt Trigger, 0 = enabled, 1 = disabled
		mov	!rb,w		
		mov     w,#RC_ST            	;Setup RC Schmitt Trigger, 0 = enabled, 1 = disabled
		mov	!rc,w	
IFDEF SX48_52
		mov     w,#RD_ST            	;Setup RD Schmitt Trigger, 0 = enabled, 1 = disabled
		mov	!rd,w		
		mov     w,#RE_ST            	;Setup RE Schmitt Trigger, 0 = enabled, 1 = disabled
		mov	!re,w		
ENDIF
		_mode	LVL_W			;point MODE to write LVL register
		mov     w,#RA_LVL            	;Setup RA CMOS or TTL levels, 0 = TTL, 1 = CMOS
		mov	!ra,w		 
		mov     w,#RB_LVL            	;Setup RB CMOS or TTL levels, 0 = TTL, 1 = CMOS
		mov	!rb,w		
		mov     w,#RC_LVL            	;Setup RC CMOS or TTL levels, 0 = TTL, 1 = CMOS
		mov	!rc,w	
IFDEF SX48_52
		mov     w,#RD_LVL            	;Setup RD CMOS or TTL levels, 0 = TTL, 1 = CMOS
		mov	!rd,w		
		mov     w,#RE_LVL            	;Setup RE CMOS or TTL levels, 0 = TTL, 1 = CMOS
		mov	!re,w		
ENDIF
		_mode	PLP_W			;point MODE to write PLP register
		mov     w,#RA_PLP            	;Setup RA Weak Pull-up, 0 = enabled, 1 = disabled
		mov	!ra,w		 
		mov     w,#RB_PLP            	;Setup RB Weak Pull-up, 0 = enabled, 1 = disabled
		mov	!rb,w		
		mov     w,#RC_PLP            	;Setup RC Weak Pull-up, 0 = enabled, 1 = disabled
		mov	!rc,w	
IFDEF SX48_52
		mov     w,#RD_PLP            	;Setup RD Weak Pull-up, 0 = enabled, 1 = disabled
		mov	!rd,w		
		mov     w,#RE_PLP            	;Setup RE Weak Pull-up, 0 = enabled, 1 = disabled
		mov	!re,w		
ENDIF
		_mode	DDIR_W			;point MODE to write DDIR register
		mov	w,#RA_DDIR		;Setup RA Direction register, 0 = output, 1 = input		
		mov	!ra,w	
		mov	w,#RB_DDIR		;Setup RB Direction register, 0 = output, 1 = input
		mov	!rb,w			
		mov	w,#RC_DDIR		;Setup RC Direction register, 0 = output, 1 = input
		mov	!rc,w			
IFDEF SX48_52
		mov	w,#RD_DDIR		;Setup RD Direction register, 0 = output, 1 = input
		mov	!rd,w			
		mov	w,#RE_DDIR		;Setup RE Direction register, 0 = output, 1 = input
		mov	!re,w			
ENDIF
		mov     w,#RA_latch          	;Initialize RA data latch
		mov     ra,w		
		mov     w,#RB_latch         	;Initialize RB data latch
		mov     rb,w		
		mov     w,#RC_latch          	;Initialize RC data latch
		mov     rc,w		
IFDEF SX48_52
		mov     w,#RD_latch         	;Initialize RD data latch
		mov     rd,w			
		mov     w,#RE_latch         	;Initialize RE data latch
		mov     re,w			
ENDIF


	;*********************************************************************************
	; Clear all Data RAM locations
	;*********************************************************************************
IFDEF SX48_52   				;SX48/52 RAM clear routine
		mov	w,#$0a			;reset all ram starting at $0A
		mov	fsr,w
:zero_ram	clr	ind			;clear using indirect addressing
		incsz	fsr			;repeat until done
		jmp	:zero_ram

		_bank	bank0			;clear bank 0 registers
		clr	$10
		clr	$11
		clr	$12
		clr	$13
		clr	$14
		clr	$15
		clr	$16
		clr	$17
		clr	$18
		clr	$19
		clr	$1a
		clr	$1b
		clr	$1c
		clr	$1d
		clr	$1e
		clr	$1f

ELSE     					;SX18/20/28 RAM clear routine
		clr	fsr			;reset all ram banks
:zero_ram	sb	fsr.4			;are we on low half of bank?
		setb	fsr.3			;If so, don't touch regs 0-7
		clr	ind			;clear using indirect addressing
		incsz	fsr			;repeat until done
		jmp	:zero_ram
ENDIF
	;*********************************************************************************
	; Initialize program/VP registers
	;*********************************************************************************
			_bank	SPIM_BANK			;SPI_bank initialization

;Set configuration bytes for PortB and SPI Clock line
			mov	spim_clk_mask,#$01		;SPI Clock line mask for SPI Port	
			mov	spim_portb_mask,#$04		;PortB data direction byte  

;Set DEMO control data
			mov	sys_timer_rate,#-80		;set system timer to 25.6 usec
			_bank	DEMO_VARS
			mov	demo_init_cycles,#$ff		;set number of initial cycles to 255

;set SPIM control data
			mov	demo_rate,#$3			;set SPI Clock period 900ns	
	
			_bank	SPIM_BANK			
			mov	spim_demo_cmd,#$f0		;Set SPIM_CMD to SEND RISING 16 BIT
;			mov	spim_demo_cmd,#$bc		;Set SPIM_CMD to SEND FALLING 12 BIT

			mov	spim_demo_data_MSB,#$55		;define the data to transfer		
			mov	spim_demo_data_LSB,#$55		

;initialise SPIM
			_bank	DEMO_VARS
			mov	w,demo_rate
			_bank	SPIM_BANK
			mov	spim_rate,w			;set SPI Clock rate to 900 nsec

	;*********************************************************************************
	; Setup and enable RTCC interrupt, WREG register, RTCC/WDT prescaler
	;*********************************************************************************

RTCC_ON		=	%10000000	;Enables RTCC at address $01 (RTW hi)
					;*WREG at address $01 (RTW lo) by default
RTCC_ID		=	%01000000	;Disables RTCC edge interrupt (RTE_IE hi)
					;*RTCC edge interrupt (RTE_IE lo) enabled by default
RTCC_INC_EXT	=	%00100000	;Sets RTCC increment on RTCC pin transition (RTS hi)
					;*RTCC increment on internal instruction (RTS lo) is default
RTCC_FE		=	%00010000	;Sets RTCC to increment on falling edge (RTE_ES hi)
					;*RTCC to increment on rising edge (RTE_ES lo) is default
RTCC_PS_ON	=	%00000000	;Assigns prescaler to RTCC (PSA lo)
RTCC_PS_OFF	=	%00001000	;Assigns prescaler to RTCC (PSA lo)
PS_000		=	%00000000	;RTCC = 1:2, WDT = 1:1
PS_001		=	%00000001	;RTCC = 1:4, WDT = 1:2
PS_010		=	%00000010	;RTCC = 1:8, WDT = 1:4
PS_011		=	%00000011	;RTCC = 1:16, WDT = 1:8
PS_100		=	%00000100	;RTCC = 1:32, WDT = 1:16
PS_101		=	%00000101	;RTCC = 1:64, WDT = 1:32
PS_110		=	%00000110	;RTCC = 1:128, WDT = 1:64
PS_111		=	%00000111	;RTCC = 1:256, WDT = 1:128

			mov	w,#PS_011	;setup option register
			mov	!option,w

;*****************************************************************************************
; MAIN PROGRAM CODE 
;*****************************************************************************************

	;*********************************************************************************
	; Main
	;*********************************************************************************
main		
;start data transfer, SPIM will be called from RTCC interrupt handler on every RTCC interrupt		 		
;initial 255 cycles when spim_demo_data are sent to Slave

			_bank	DEMO_VARS
			mov	demo_init_counter,demo_init_cycles	;spim_init_counter to $ff

:spim_transfer_start	_bank	SPIM_BANK
			test	spim_cmd				;wait for SPIM to be ready 
			jnz	:spim_transfer_start			;for next transfer
			mov	spim_cmd,spim_demo_cmd
			_bank	DEMO_VARS
			djnz	demo_init_counter,:spim_transfer_start

;initial 255 cycles finished
	;*********************************************************************************
	; Main Program Loop
	;*********************************************************************************

			_bank	SPIM_BANK
main_master		test	spim_cmd				;SPIM VP access loop		
			jnz	main_master

			mov	spim_cmd,spim_demo_cmd		
			jmp	main_master


;*****************************************************************************************
END			;End of program code
;*****************************************************************************************