;Assembly flag
Debug=0
;******************************************************************************
;	File name:
;		EMRRA-Refinary_SX-III_proto_Master_097Gz.SRC(Baud rate:9600 with Dummy byte)
;       Authors: Systems Research,Inc.,Yoshio Tsuruoka
;       Written: 06/20/2000 to 05/05/2002 for SX28AC
;		 05/05/2002 ~ 05/14/2002 for SX52BD
;			
;		 12/25/2007 ~ 12/30/2007 for SX52DemoBoard
;		 01/02/2008 ~ 01/02/2008 for SX48ProtoBoard(Master)
;		 02/15/2008 ~ 02/15/2008 for SX48Proto-III_Master+USB-MOD3C
;
;	Purpose:
;		PPG redirect command prefix is '@'
;	Hardware components:
;		SX52BD/PQF AB0004AC(Scenix)
;		MAX233A(Maxim)
;		24LC64(Microchip)
;		PPG-20 on FIX-20(D.S.Technology)
;	Development Tools:
;		SXKey52.exe (Version 1.20 for Rev E/F)
;		SX-Key Rev E/F(Parallax)
;	Execution result:(Hyperterm image)
;		#ON 51		..........Input from PC to turn on LED(Black)
;		#@READ		..........Read data from PPG
;		#@12345		..........Write data to PPG
;		
;
;	Based on the programs as follows:
;		7)SX52Demo-Commander_Rev091Dz.SRC
;		6)SX52Demo-Commander_Rev075Az.src(05/05/2002-05/07/2002)
;		5)PPG-Emulator_051c.SRC(05/02/2000-05/13/2000)
;		4)CmdRedirector_Sample_07a.SRC(04/30/2000-05/02/2000)
;       	3)MultiCmdBuff_Sample_3a.SRC(04/27/00-04/27/00)
;		2)SingleCmdBuff_Sample1a.SRC(04/23/00-04/23/00)
; 		1)Sxdemo2L.src(Original)      
;       		Authors: Parallax Inc., Craig Webb
;       		Written: 97/03/10 to 98/6/08
;	Revision rule:
;		Revision code,e.g 010a,is not reset even though file name is changed.
;
;	Revision History:
;
;
;
;
;
;
;

;*****************************************************************************************
; 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.
;*****************************************************************************************
;SX28
SX48_52					;uncommented rev0.01Aa
;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 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
    ENDIF
  ENDIF
		freq	50_000_000
ELSE  					;SASM Directives
  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   
    ENDIF
  ENDIF
ENDIF
		id	'SX52Cmd'			;
		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
  noexpand
	bank	\1
	IFDEF SX48_52
	  IFDEF SX48_52_ES
	    IF \1 & %00010000		;SX48BD/ES and SX52BD/ES (engineering sample) bank instruction
  expand
		setb	fsr.4		;modifies FSR bits 5,6 and 7. FSR.4 needs to be set by software.
  noexpand
	    ENDIF
	  ELSE
	    IF \1 & %10000000		;SX48BD and SX52BD (production release) bank instruction 
  expand
		setb	fsr.7		;modifies FSR bits 4,5 and 6. FSR.7 needs to be set by software.
  noexpand
	    ELSE
  expand
		clrb	fsr.7
  noexpand
	    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
  noexpand
	IFDEF SX48_52
  expand
		mov	w,#\1		;loads the M register correctly for the SX48BD and SX52BD
		mov	m,w
  noexpand
	ELSE
  expand
		mov	m,#\1		;loads the M register correctly for the SX18AC, SX20AC
					;and SX28AC
  noexpand
	ENDIF
	endm


;****** Assembler directives
; uses: SX28AC, 2 pages of program memory, 8 banks of RAM, high speed osc.
;       operating in turbo mode, with 8-level stack & extended option reg.
;                
;		DEVICE  SX28L,OSCXTMAX
;		DEVICE  turbo,stackx_optionx
;		ID      'PPG2-CMD'		;program ID label
;		RESET   reset_entry             ;set reset/boot address
;		FREQ	50000000
		WATCH	cmd_buff,5,ZSTR
		WATCH	arg1_buff,9,ZSTR
		WATCH	arg2_buff,9,ZSTR
		WATCH	arg3_buff,9,ZSTR
;
		WATCH	con_buff,15,ZSTR

;******************************* Program Variables ***************************
;
; Port Assignment: Bit variables

_frRA	=	$05
_frRB	=	$06
_frRC	=	$07
_frRD	=	$08
_frRE	=	$09

_READ_LVL_MODE	=	$0D
_READ_PLP_MODE	=	$0E
_READ_DIR_MODE	=	$0F

_WRITE_LVL_MODE	=	$1D
_WRITE_PLP_MODE	=	$1E
_WRITE_DIR_MODE	=	$1F

;;;;;;;;;;;;;;;;
IFDEF SX48_52
;;;;;;;;;;;;;;;;
sda		EQU     RA.0                    ;UART transmit output from PC
scl        	EQU     RA.1                    ;UART transmit output to PC

;rx0_pin		EQU     RA.2                    ;(Red)
;tx0_pin         EQU     RA.3                    ;(Green)
;rx1_pin         EQU     RA.4                    ;(Green) UART receive input from PC
;tx1_pin         EQU     RA.5                    ;(Red) UART transmit output to PC
buzz_pin  	EQU     RA.6                    ;buzzer output
;led_pin         EQU     RA.7                    ;LED output
;
rb0_pin		EQU	RB.0			;DSW bit0 input
rb1_pin		EQU	RB.1			;DSW bit1 input
rb2_pin		EQU	RB.2			;DSW bit2 input
led_pin		EQU	RB.3			;DSW bit3 input
rb4_pin	        EQU     RB.4                    ;
rb5_pin	        EQU     RB.5                    ;
rb6_pin         EQU     RB.6                    ;
rb7_pin         EQU     RB.7                    ;
;
;
;#############################################################################
; Rev 096Aa
rx0_pin		EQU     RB.4          	;SX48 UART receive input from USB-MOD3C
tx0_pin         EQU     RB.5           	;SX48 UART transmit output to USB-MOD3C
rx1_pin         EQU     RB.6            ;SX48 UART receive input from PPG
tx1_pin         EQU     RB.7            ;SX48 UART transmit output to PPG
;#############################################################################
; 

;
rc0_pin         EQU     RC.0                    ;
rc1_pin	        EQU     RC.1                    ;
rc2_pin		EQU     RC.2                    ;
rc3_pin		EQU     RC.3                    ;
rc4_pin		EQU     RC.4                    ;
rc5_pin     	EQU     RC.5                    ;
rc6_pin		EQU     RC.6                    ;
rc7_pin     	EQU     RC.7                    ;
;
ppg_freq_pin	EQU     RD.0                    ;
celsius_in_pin	EQU     RD.1                    ;
celsius_out_pin	EQU     RD.2                    ;
fan_freq_pin	EQU     RD.3                    ;
;
rd4_pin		EQU     RD.4                    ;
rd5_pin     	EQU     RD.5                    ;
rd6_pin		EQU     RD.6                    ;
rd7_pin     	EQU     RD.7                    ;

re0_pin         EQU     RE.0                    ;
re1_pin	        EQU     RE.1                    ;
re2_pin		EQU     RE.2                    ;
re3_pin		EQU     RE.3                    ;
re4_pin		EQU     RE.4                    ;
re5_pin     	EQU     RE.5                    ;
re6_pin		EQU     RE.6                    ;
re7_pin     	EQU     RE.7                    ;

;-----------------------------------
; M Signal with SX48_Slave
;-----------------------------------
M_D0_slv_pin		=	RE.0
M_D1_slv_pin		=	RE.1
M_D2_slv_pin		=	RE.2
M_D3_slv_pin		=	RE.3
M_D4_slv_pin		=	RE.4
M_D5_slv_pin		=	RE.5
M_STRB_to_sx_pin	=	RE.6	;STRB Master ---> Slave
M_ACK_frm_sx_pin	=	RE.7	; ACK Master <--- Slave
M_STRB_frm_sx_pin	=	RE.7	;STRB Master <--- Slave
M_ACK_to_sx_pin		=	RE.6	; ACK Master ---> Slave

M_bus_mx_TX_DIR	=	%1_0_000000	;<D7:ACK><D6:STRB><D5~D0:M_bus>
M_bus_mx_RX_DIR	=	%1_0_111111


;-----------------------------------
; Read/Write with SX48_Slave
;-----------------------------------
RW_D0_slv_pin		=	RE.0
RW_D1_slv_pin		=	RE.1
RW_D2_slv_pin		=	RE.2
RW_D3_slv_pin		=	RE.3

RW_STRB_to_ta_pin	=	RE.4	;STRB Master ---> the target
RW_ACK_frm_ta_pin	=	RE.5	; ACK Master <--- the target
RW_STRB_frm_ta_pin	=	RE.5	;STRB Master <--- the target
RW_ACK_to_ta_pin	=	RE.4	; ACK Master ---> the target

RW_read_write_pin	=	RE.6	;0:Read 1:Write
RW_bus_sel_pin		=	RE.7	;0:M	1:RegReadWrite

RW_bus_mx_TX_DIR	=	%00_10_0000	;upper nibble to be fixed
RW_bus_mx_RX_DIR	=	%00_10_1111

;-----------------------------------
; Preamble with SX48_Slave
;-----------------------------------
PREA_BIT_to_slv_pin	=	RE.0
PREA_STRB_to_slv_pin	=	RE.1
PREA_ACK_frm_slv_pin	=	RE.2
PREA_Void_3_slv_pin	=	RE.3
PREA_Void_4_slv_pin	=	RE.4
PREA_Void_5_slv_pin	=	RE.5
PREA_Void_6_slv_pin	=	RE.6
PREA_Void_7_slv_pin	=	RE.7


READY_BIT_frm_slv_pin	=	RE.0
READY_ACK_to_slv_pin	=	RE.1

;///////////////////////// For SX28 /////////////////////////////
ELSE
rx0_pin         EQU     RA.0                    ;UART receive input from PC
tx0_pin         EQU     RA.1                    ;UART transmit output to PC
buzz_pin        EQU     RA.2                    ;buzzer output
led_pin         EQU     RA.3                    ;LED output
;
bit0_pin	EQU	RB.0			;DSW bit0 input
bit1_pin	EQU	RB.1			;DSW bit1 input
bit2_pin	EQU	RB.2			;DSW bit2 input
bit3_pin	EQU	RB.3			;DSW bit3 input
scl	        EQU     RB.4                    ;
sda	        EQU     RB.5                    ;
rx1_pin         EQU     RB.6                    ;UART receive input from PPG
tx1_pin         EQU     RB.7                    ;UART transmit output to PPG
;
ry1_pin         EQU     RC.0                    ;Relay1 coil output
ry2_pin	        EQU     RC.1                    ;Relay2 coil output
ry3_pin		EQU     RC.2                    ;Relay3 coil output
ry4_pin		EQU     RC.3                    ;Relay4 coil output
sw1_pin		EQU     RC.4                    ;Relay1 contact input
sw2_pin     	EQU     RC.5                    ;Relay2 contact input
sw3_pin		EQU     RC.6                    ;Relay3 contact input
sw4_pin     	EQU     RC.7                    ;Relay4 contact input
ENDIF
;
CR		EQU	$0D
SPACE		EQU	$20
;
;
data_000h	EQU	0			;$000~$0FF
data_100h	EQU	1			;$100~$1FF
data_200h	EQU	2			;$200~$2FF
data_300h	EQU	3			;$300~$3FF	
data_400h	EQU	4			;$400~$4FF	
data_500h	EQU	5			;$500~$5FF
data_600h	EQU	6			;$600~$6FF
data_700h	EQU	7			;$700~$7FF
data_800h	EQU	8			;$800~$8FF
data_900h	EQU	9			;$900~$9FF
data_A00h	EQU	$0A			;$A00~$AFF
data_B00h	EQU	$0B			;$B00~$BFF
data_C00h	EQU	$0C			;$C00~$CFF
data_D00h	EQU	$0D			;$D00~$DFF
data_E00h	EQU	$0E			;$E00~$EFF
data_F00h	EQU	$0F			;$F00~$FFF
void	= 0
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Message Category Definition
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
msg_category_0	=	data_E00h
msg_category_1	=	void
msg_category_2	=	void
msg_category_3	=	void
msg_category_4	=	void
msg_category_5	=	void
msg_category_6	=	void
msg_category_7	=	void
;
;
;*****************************************************************************************
; 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
;global_org	=	$08
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                       ;start of program registers
global           =       $                       ;main bank
;
;global_reg8	ds	1
;global_reg9	ds	1
global_reg10	ds	1
global_reg11	ds	1
global_reg12	ds	1
global_reg13	ds	1
global_reg14	ds	1
global_reg15	ds	1


g_temp          =	global_reg10            ;temporary storage
g_byte          =	global_reg11           	;temporary UART/I2C shift reg.
g_arg_cnt	=	global_reg12		;argument counter
g_number_low 	=	global_reg13            ;low byte of rec'd value
g_number_high  	=	global_reg14            ;high byte of rec'd value
global_flags    =	global_reg15            ;program flags register
;
g_got_hex       EQU     global_flags.0          ;=1 if hex value after command
g_read_write_flag  	EQU     global_flags.1          ;0:READ 1:WRITE
g_flag_void_2  	EQU     global_flags.2          ;     
g_flag_void_3  	EQU     global_flags.3          ;     
g_rx0_flag     	EQU	global_flags.4		;signals when a byte is received
g_rx1_flag	equ	global_flags.5
g_sx_fnc_err	equ	global_flags.6		;=1 if sx_function err occurs
g_ppg_sel_flag	equ	global_flags.7		;=1 if cmd prefix='@'

;Multiplexed Definitions
g_sx_fnc_num    =	global_reg10   
g_M_reg		=	global_reg12

;##########################################
; Virtual Debugging Multiplex Definitions
;##########################################

RD_reg_X	=	global_reg10	;$0A
;
; For Freq Counter
;
fan_freq_pin_X	=	RD_reg_X.0

fan_freq_curr_X	=	global_reg11	;$0B
fan_freq_acc_X	=	global_reg12	;$0C
fan_int_cnt_X	=	global_reg13	;$0D

;
; For Temperature measuring
;
celsius_in_pin_X	EQU     RD_reg_X.1                    ;
celsius_out_pin_X	EQU     RD_reg_X.2                    ;
;
port_buff_X       =      global_reg11	;$0B     ;buffer - used by all
adc0_X            =      global_reg12	;$0C     ;adc0 - value
adc0_count_X      =      global_reg13	;$0D     ;     - real-time count
adc0_acc_X        =      global_reg14	;$0E     ;     - accumulator

ppg_freq_pin_X	=	RD_reg_X.0
ppg_freq_curr_X	=	global_reg11	;$0B
ppg_freq_acc_X	=	global_reg12	;$0C
ppg_int_cnt_X	=	global_reg13	;$0D
			


;Flags
freq_flags_X	=	global_reg15	;$0F
;
fan_detect_low_X	=	freq_flags_X.0
fan_freq_trigg_X	=	freq_flags_X.1
;
ppg_freq_trigg_X	=	freq_flags_X.0
ppg_detect_pre_low_X	=	freq_flags_X.1
ppg_detect_period_low_X	=	freq_flags_X.3


;****** Register definitions (bank 0)
;

	;*********************************************************************************
	; Bank 0
	;*********************************************************************************
		org     bank0_org
bank0		=	$
                       ;
	;*********************************************************************************
	; Bank 1
	;*********************************************************************************
		org	bank1_org
bank1		=	$
main	        =       $                       ;main bank
;
beep_cnt_low	ds	1
beep_cnt_high	ds 	1
beep_pre_low	ds	1
beep_pre_high	ds	1
beep_on_low	ds	1
beep_on_high	ds	1
beep_off_low	ds	1
beep_off_high	ds	1

beep_flags	ds	1
beep_enabled	=	beep_flags.0		;controls run/stop
beep_stat	=	beep_flags.1		;take note if 

msec_cnt	ds	1
msec_flags	ds	1
msec_start_flag	=	msec_flags.0

	;*********************************************************************************
	; Bank 2
	;*********************************************************************************
		org     bank2_org                     ;bank2 variables
bank2		=	$
serial          =       $                       ;UART bank
;
tx0_high         ds      1                      ;hi byte to transmit(COM0)
tx0_low          ds      1                      ;low byte to transmit
tx0_count        ds      1                      ;number of bits sent
tx0_divide       ds      1                      ;xmit timing (/16) counter
rx0_count        ds      1                    	;number of bits received
rx0_divide       ds      1                      ;receive timing counter
rx0_byte         ds      1                      ;buffer for incoming byte
;
tx1_high         ds      1                      ;hi byte to transmit(COM1)
tx1_low          ds      1                      ;low byte to transmit
tx1_count        ds      1                      ;number of bits sent
tx1_divide       ds      1                      ;xmit timing (/16) counter
rx1_count        ds      1                      ;number of bits received
rx1_divide       ds      1                      ;receive timing counter
rx1_byte         ds      1                      ;buffer for incoming byte
; The following three values determine the UART baud rate.
; *** 9600 baud
baud_bit        =       5                       ;for 9600 baud
start_delay     =       32+16+1                  ; "    "     "
int_period      =       163                     ; "    "     "
;
	;*********************************************************************************
	; Bank 3
	;*********************************************************************************
		org     bank3_org                     ;bank3 variables
bank3		=	$
I2C             =     	$                       ;I2C bank
;
data            DS      1                       ;data byte from/for R/W
address_low     DS      1                       ;lower byte of 16 bits address
address_high	DS	1			;higher byte of 16 bits address
count           DS      1                       ;bit count for R/W
delay           DS      1                       ;timing delay for write cycle
byte_count      DS      1                       ;number of bytes in R/W
num_bytes       DS      1                       ;number of byte to view at once
save_addr       DS      1                       ;backup location for address
erase_cnt	DS	1
;
in_bit          EQU     g_byte.0               	;bit to receive on I2C
out_bit         EQU     g_byte.7                ;bit to transmit on I2C 
;
control_r       =       10100001b               ;control byte: read E2PROM
control_w       =       10100000b               ;control byte: write E2PROM
portsetup_r     =       01101111b               ;Port B config: read bit
portsetup_w     =       01001111b               ;Port B config: write bit
eeprom_size     =       128                     ;storage space of EEPROM
;
t_all           =       62                      ;bit cycle delay (62=5 usec)

	;*********************************************************************************
	; Bank 4
	;*********************************************************************************
		org     bank4_org		;bank4 variables
bank4		=	$
clock		=	$                       ;clock bank
;
time_base_low	DS	1			;time base delay (low byte)
time_base_high	DS	1			;time base delay (high byte)
msec0_low	DS	1			;millisecond count0 (low)
msec0_high	DS	1			;millisecond count0 (high)
msec1_low	ds	1			;millisecond count1 (low)
msec1_high	ds	1			;millisecond count1 (high)
blink_cnt_low	ds	1			;general down counter (low)
blink_cnt_high	ds	1
;
blink_pre_low	ds	1
blink_pre_high	ds	1
blink_on_low	ds	1
blink_on_high	ds	1
blink_off_low	ds	1
blink_off_high	ds	1
blink_flags	ds	1
blink_enabled	=	blink_flags.0		;controls run/stop
blink_led_stat	=	blink_flags.1		;take note if LED is on or off


;
			tick_low		=	80		;instruction count for
			tick_high		=	195		; 50MHz xtal, turbo, prescaler=1

;
	
	;*********************************************************************************
	; Bank 5
	;*********************************************************************************
		org	bank5_org
bank5		=	$
calc		=	$			;bank calc
calc_reg0	ds	1	;
calc_reg1	ds	1	;
calc_reg2	ds	1	;
calc_reg3	ds	1	;
calc_reg4	ds	1	;
calc_reg5	ds	1	;
calc_reg6	ds	1	;
calc_reg7	ds	1	;
calc_reg8	ds	1	;
calc_reg9	ds	1	;
calc_reg10	ds	1	;
calc_reg11	ds	1	;
calc_reg12	ds	1	;
calc_reg13	ds	1	;
calc_reg14	ds	1	;
calc_reg15	ds	1	;

; Definition for asc_to_bin	
result_low	=	calc_reg0
result_high	=	calc_reg1
temp0_low	=	calc_reg2
temp0_high	=	calc_reg3
temp1_low	=	calc_reg4
temp1_high	=	calc_reg5
asc_ptr		=	calc_reg6
asc_len		=	calc_reg7
data_type	=	calc_reg8
cnv_char	=	calc_reg9
swap_hex	=	calc_reg10
rl_cnt		=	calc_reg11

; Definition for bin_to_asc 
quotient_low	=	calc_reg0
quotient_high	=	calc_reg1	
remainder_low	=	calc_reg2	
remainder_high	=	calc_reg3	
value_low	=	calc_reg4	
value_high	=	calc_reg5	

; Definition for divide16 
quotient_low	=	calc_reg0
quotient_high	=	calc_reg1	
remainder_low	=	calc_reg2	
remainder_high	=	calc_reg3	
dividend_low	=	calc_reg4	
dividend_high	=	calc_reg5	
divisor_low	=	calc_reg6	
divisor_high	=	calc_reg7	
shift_counter	=	calc_reg8
shift_byte	=	calc_reg9

; Definition for SX Function Call

sx_flags	=	calc_reg15
ON_OFF_flag	=	sx_flags.0

; Definition for 8bit_to_asciiHex 
nibble_low	=	calc_reg0
nibble_high	=	calc_reg1	
temp0_low	=	calc_reg2	
temp0_high	=	calc_reg3	
value_low	=	calc_reg4	
value_high	=	calc_reg5	
nibble_flags	=	calc_reg15
add_offset_flag	=	nibble_flags.0

	;*********************************************************************************
	; Bank 6
	;*********************************************************************************
		org	bank6_org
bank6		=	$
command		=	$			;command bank 6
rsv_sum		=	16
rsv_ref_cnt	ds	1
add_times	ds	1
rsv_len		ds	1
rsv_base	ds	1
rsv_ptr		ds	1
cmd_ptr		ds	1
cmd_len		ds	1
cmd_buff	ds	9			;9 digits:999,999,999

;

	;*********************************************************************************
	; Bank 7
	;*********************************************************************************
		org	bank7_org		;argument1 bank 7
bank7		=	$
argument1	=	$
arg1_char	ds	1
arg1_low	ds	1
arg1_high	ds	1
arg1_ptr	ds	1
arg1_len	ds	1
arg1_buff	ds	11
;

IFDEF SX48_52
	;*********************************************************************************
	; Bank 8
	;*********************************************************************************
		org	$80			;argument2 bank 8
bank8		=	$
argument2	=	$
arg2_char	ds	1
arg2_low	ds	1
arg2_high	ds	1
arg2_ptr	ds	1
arg2_len	ds	1
arg2_buff	ds	11
;
	;*********************************************************************************
	; Bank 9
	;*********************************************************************************
		org	$90	;bank 9 address on SX52

bank9		=	$
argument3	=	$
arg3_char	ds	1
arg3_low	ds	1
arg3_high	ds	1
arg3_ptr	ds	1
arg3_len	ds	1
arg3_buff	ds	11
;


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

bankA		=	$
general		=	$
string_ptr	ds	1
cmd_arg_num	ds	1
cmd_delim0	ds	1	;'OUT<cmd_delim0>$55<cmd_delim1>$1F'
cmd_delim1	ds	1
cmd_delim2	ds	1	;'WRITE<cmd_delim0>$55<cmd_delim1>$1F<cmd_delim2>0'


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

bankB		=	$
M_signal_ReadWrite	=	$
reg_B0	ds	1
reg_B1	ds	1
reg_B2	ds	1
reg_B3	ds	1
reg_B4	ds	1
reg_B5	ds	1
reg_B6	ds	1
reg_B7	ds	1
reg_B8	ds	1
reg_B9	ds	1
reg_BA	ds	1
reg_BB	ds	1
reg_BC	ds	1
reg_BD	ds	1
reg_BE	ds	1
reg_BF	ds	1
;;;;;;;;;;;;;;;
; M_signal
;;;;;;;;;;;;;;;
M_num		=	reg_B0
M_result	=	reg_B1
M_zero_bit_ptn	=	reg_B3


;;;;;;;;;;;;;;;;;;
; Read/Write
;;;;;;;;;;;;;;;;;;
RW_tx_upper_nibble_log	=	reg_B0
RW_tx_lower_nibble_log	=	reg_B1
RW_rx_upper_nibble_log	=	reg_B2
RW_rx_lower_nibble_log	=	reg_B3
RW_tx_upper_nibble_phy	=	reg_B4
RW_tx_lower_nibble_phy	=	reg_B5
RW_rx_upper_nibble_phy	=	reg_B6
RW_rx_lower_nibble_phy	=	reg_B7

RW_arg_cnt		=	reg_B8
RW_arg_ptr		=	reg_B9
RW_arg1			=	reg_BA		
RW_arg2			=	reg_BB		
RW_arg3			=	reg_BC		
RW_read_val		=	reg_BD
RW_temp			=	reg_BE
RW_session_cnt		=	reg_BF	

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

bankC		=	$
analog		=	$
;
port_buff       ds      1                       ;buffer - used by all
pwm0            ds      1                       ;pwm0 - value
pwm0_acc        ds      1                       ;     - accumulator
pwm1            ds      1                       ;pwm1 - value
pwm1_acc        ds      1                       ;     - accumulator
adc0            ds      1                       ;adc0 - value
adc0_count      ds      1                       ;     - real-time count
adc0_acc        ds      1                       ;     - accumulator
adc1            ds      1                       ;adc1 - value
;adc1_count     ds      1                       ;     - real-time count
adc1_acc        ds      1                       ;     - accumulator
;



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

bankD		=	$
freq_counter	=	$
;
fan_freq_curr	ds	1
fan_freq_acc	ds	1
fan_int_cnt	ds	1


ppg_freq_curr	ds	1
ppg_freq_acc	ds	1
ppg_int_cnt	ds	1

freq_flags	ds	1
fan_freq_trigg	=	freq_flags.0
fan_detect_low	=	freq_flags.1
ppg_freq_trigg	=	freq_flags.2
ppg_detect_pre_low	=	freq_flags.3
ppg_detect_period_low	=	freq_flags.4



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

bankE		=	$


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

bankF		=	$
console_buff	=	$
con_buff_ptr	ds	1

con_buff	ds	15


ENDIF

;*************************** INTERRUPT VECTOR ******************************
		ORG     0                       ;interrupt always at 0h
		JMP	interrupt		;interrupt vector
initialize_params
		_BANK	clock
		mov	blink_on_low,#$4F
		mov	blink_on_high,#$1
		mov	blink_off_low,#$4F
		mov	blink_off_high,#$1

		mov	blink_pre_low,#$4F
		mov	blink_pre_high,#$1
		clr	blink_cnt_low
		clr	blink_cnt_high

		setb	blink_enabled
		
		_BANK	main
		mov	beep_on_low,#$4F
		mov	beep_on_high,#$1
		mov	beep_off_low,#$4F
		mov	beep_off_high,#$1

		mov	beep_pre_low,#$4F
		mov	beep_pre_high,#$1
		clr	beep_cnt_low
		clr	beep_cnt_high

		setb	beep_enabled		

		RETP

Setup_delay_body
		jmp	:delay0			;3 clock * 20 ns = 60 ns
:delay0		jmp	:delay1			;3
:delay1		jmp	:delay2			;3
:delay2		jmp	:delay3			;3
:delay3		jmp	:delay4			;3
:delay4		jmp	:delay5			;3
:delay5		jmp	:delay6			;3
:delay6
		RETP				;3
;
Bus_delay_body  
		MOV     W,#t_all                ;get timing for delay loop
:custom         MOV     g_temp,W                ;save it
:loop           DJNZ    g_temp,:loop            ;do delay
		RETP                            ;# Bus_delay #

;
msec_delay
		_bank	main
		mov	msec_cnt,W
		setb	msec_start_flag
:wait	
		jb	msec_start_flag,:wait	;wait for start_flag reset
		RETP


;
;***************************** PROGRAM DATA ********************************
;
;
;;;;;;;Resrved Command Reference Table;;;;;;;;;
;+0:command length
;+1~+8:command string_ptr
;+9:function number(See bellow)

;
offset_rsv_len	=	$00
offset_rsv_cmd	=	$01
offset_func_num	=	$09
offset_next_cmd	=	$0A
;
;Rev >0.96Ac
func_OUT_num	=	0
func_IN_num	=	1
func_VER_num	=	2
func_SETB_num	=	3
func_CLRB_num	=	4
func_TESTB_num	=	5
func_M_num	=	6
func_READ_num	=	7
func_WRITE_num	=	8

;
rsv_sum		=	9
;

_rsv_ref_table
;Rev>0.96Ac	    <LEN> <RESERVED_NAME>   <FUNCTION #>
;           Offset     +0 +1                +9 	
_out		dw	3,'OUT'  ,0,0,0,0,0,func_OUT_num   	;3+5 < 9
_in		dw	2,'IN' ,0,0,0,0,0,0,func_IN_num    	;2+6 < 9
_ver		dw	3,'VER'  ,0,0,0,0,0,func_VER_num   	;3+5 < 9
_setb		dw	4,'SETB'   ,0,0,0,0,func_SETB_num  	;4+4 < 9
_clrb		dw	4,'CLRB'   ,0,0,0,0,func_CLRB_num  	;4+4 < 9
_testb		dw	5,'TESTB'    ,0,0,0,func_TESTB_num 	;5+3 < 9
_read		dw	4,'READ'   ,0,0,0,0,func_READ_num   	;4+4 < 9
_write		dw	5,'WRITE'    ,0,0,0,func_WRITE_num   	;5+3 < 9


;
;
;**************************** INTERRUPT CODE *******************************
;
;
interrupt					;beginning of interrupt code
		jmp	UART
;

;***** Virtual Peripheral: PPG Frequency Counter :by Yoshio Tsuruoka
;//ppg_freq_curr	ds	1
;//ppg_freq_acc	ds	1
;//ppg_int_cnt	ds	1

;//freq_flags	ds	1

;//ppg_freq_trigg		=	freq_flags.2
;//ppg_detect_pre_low		=	freq_flags.3
;//ppg_detect_period_low	=	freq_flags.4

ppg_freq_counter

		_BANK	freq_counter

ppg_freq_cnt
		jb	ppg_freq_trigg,:ppg_freq_cnt_busy	;if triggered,goto freq cnt
		jb	ppg_detect_pre_low,:ppg_wait_pin_high0	;if flag set,wait 'HIGH'
		jb	ppg_freq_pin,:exit_ppg_freq_cnt	;if the pin 'HIGH',exit to wait for 'LOW'

		setb	ppg_detect_pre_low			;preamble 'LOW' dertected
		jmp	:exit_ppg_freq_cnt			;jump to the exit

:ppg_wait_pin_high0
		jnb	ppg_freq_pin,:exit_ppg_freq_cnt	;if the pin 'LOW',exit

		clrb	ppg_detect_pre_low			;preamble 'LOW' ends
		setb	ppg_freq_trigg
		jmp	:exit_ppg_freq_cnt			;jump to the exit

;;;;;;;;;;;;;;;;;;;;;;;;
:ppg_freq_cnt_busy
;;;;;;;;;;;;;;;;;;;;;;;;
		jb	ppg_detect_period_low,:ppg_wait_pin_high1	;if flag set,wait 'HIGH'

;ppg_wait_period_low

		inc	ppg_int_cnt
		cjne	ppg_int_cnt,#5,:done_ppg_freq_cnt

		inc	ppg_freq_acc
		clr	ppg_int_cnt
		
		jb	ppg_freq_pin,:exit_ppg_freq_cnt

		setb	ppg_detect_period_low
		jmp	:done_ppg_freq_cnt

:ppg_wait_pin_high1
		jb	ppg_freq_pin,:ppg_freq_cnt_fin	;if 'HIGH',finish count

		inc	ppg_int_cnt
		cjne	ppg_int_cnt,#5,:done_ppg_freq_cnt

		inc	ppg_freq_acc
		clr	ppg_int_cnt
		jmp	:done_ppg_freq_cnt

:ppg_freq_cnt_fin
		nop
		;break
		mov	ppg_freq_curr,ppg_freq_acc	;update	
		clr	ppg_freq_acc			;clear work areas
		clr	ppg_int_cnt
		clrb	ppg_detect_pre_low			;reset flags
		clrb	ppg_freq_trigg
		clrb	ppg_detect_period_low

:done_ppg_freq_cnt
:exit_ppg_freq_cnt


;***** Virtual Peripheral: Frequency Counters :by Yoshio Tsuruoka

		_BANK	freq_counter
fan_freq_cnt
		jb	fan_freq_trigg,:freq_cnt_busy	;if triggered,goto freq cnt

		jb	fan_detect_low,:wait_pin_high	;if flag set,wait 'HIGH'

		jb	fan_freq_pin,:exit_fan_freq_cnt	;if the pin 'HIGH',exit

		setb	fan_detect_low		;set flag if fa_freq_pin 'LOW'
		
		jmp	:exit_fan_freq_cnt

:wait_pin_high
		;break
		jnb	fan_freq_pin,:exit_fan_freq_cnt	;if the pin 'LOW',exit
		clrb	fan_detect_low			;reset
		setb	fan_freq_trigg
		jmp	:exit_fan_freq_cnt		;exit

:freq_cnt_busy
		jnb	fan_freq_pin,:freq_cnt_fin	;if 'LOW',finish count
		inc	fan_int_cnt
		cjne	fan_int_cnt,#2,:done_fan_freq_cnt

		inc	fan_freq_acc

		clr	fan_int_cnt
		jmp	:done_fan_freq_cnt

:freq_cnt_fin
		;break
		mov	fan_freq_curr,fan_freq_acc	;update
		;break
		clr	fan_freq_acc			;clear work areas
		clr	fan_int_cnt

		clrb	fan_detect_low			;reset flags
		clrb	fan_freq_trigg



:done_fan_freq_cnt
:exit_fan_freq_cnt
		
		;jmp done_int

;***** Virtual Peripheral: Bitstream Analog to Digital Converters
;
; These routines allow an 8-bit value to be calculated which corresponds
; directly (within noise variation limits) with the voltage (0-5V) present
; at the respective adc port input pins. These routines are timing critical
; and must be placed before any variable-execution-rate code (like the UART,
; for example). The currently enabled routine (version A) has been optimized
; for size and speed, and RAM register usage, however a fixed execution rate,
; yet slightly larger/slower routine (version B) is provided in commented
; (disabled) form to simplify building other timing-critical virtual
; peripheral combinations (i.e. that require fixed rate preceeding code).
;    Note: if version B is selected, version A must be disabled (commented)
;
;       Input variable(s) : adc0,adc0_acc,adc0_count,adc1,adc1_acc,adc1_count
;       Output variable(s) : pwm port pins
;       Variable(s) affected : port_buff, pwm0_acc, pwm1_acc
;       Flag(s) affected : none
;	Size (version A) : 9 bytes + 7 bytes (per pwm)
;			   + 2 bytes shared with adc code (see below)
;	Size (version B) : 6 bytes + 10 bytes (per pwm)
;			   + 2 bytes shared with pwm code (see below)
;       Timing (turbo)
;		version A : 2 cycles shared with pwm code (see below) +
;			   (a) [>99% of time] 11 cycles + 4 cycles (per adc)
;			   (b) [<1% of time] 9 cycles + 7 cycles (per adc)
;		version B : 6 cycles + 10 cycles (per adc)
;			    + 2 cycles shared with pwm code (see below)
;
;*** If the PWM routines are removed, the following 2 instructions must
;*** be enabled (uncommented) for the ADC routine to function properly:

;//celsius_in_pin	EQU     RD.1                    ;
;//celsius_out_pin	EQU     RD.2                    ;


ad_converter
		_BANK    analog                  ;switch to adc/pwm bank
		clr     port_buff               ;clear pwm/adc port buffer

:adcs           mov     w,<<RD                  ;get current status of adc's
						;celsius_in_pin <=== celsius_in_pin
		not     w                       ;complement inputs to outputs
		and     w,#%0000_0100            ;keep only celsius_in_pin
		or      port_buff,w             ;store new value into buffer
:update_RD	mov     RD,port_buff            ;update cap. discharge pins

;
; VERSION A - smaller, quicker but with variable execution rate
;
:adc0           sb      port_buff.2             ;check if adc0 triggered?
		INCSZ   adc0_acc                ;if so, increment accumulator
		INC     adc0_acc                ; and prevent overflowing
		DEC     adc0_acc                ; by skipping second 'INC'

		INC     adc0_count              ;adjust adc0 timing count
		JNZ     :done_adcs              ;if not done, jump ahead
:update_adc0
		;break
		;clr	adc0		;for debug
		MOV     adc0,adc0_acc           ;samples ready, update adc0
:clear_adc0	
		CLR     adc0_acc                ; reset adc0 accumulator
;
; <end of version A>
;
; VERSION B - fixed execution rate
;
;*** The "adc1_count" register definition in the analog bank definition 
;*** section must be enabled (uncommented) for this routine to work properly
;
;:adc0		sb	port_buff.4		;check if adc0 triggered
;		INCSZ   adc0_acc                ;if so, increment accumulator
;		INC     adc0_acc                ; and prevent overflowing
;		DEC     adc0_acc                ; by skipping second 'INC'
;		mov	w,adc0_acc		;load W from accumulator
;		inc	adc0_count		;adjust adc0 timing count
;		snz				;are we done taking reading?
;		mov	adc0,w			;if so, update adc0
;		snz				;
;		clr	adc0_acc		;if so, reset accumulator
;
;:adc1		sb	port_buff.6		;check if adc1 triggered
;		INCSZ   adc1_acc                ;if so, increment accumulator
;		INC     adc1_acc                ; and prevent overflowing
;		DEC     adc1_acc                ; by skipping second 'INC'
;		mov	w,adc1_acc		;load W from accumulator
;		inc	adc1_count		;adjust adc1 timing count
;		snz				;are we done taking reading?
;		mov	adc1,w			;if so, update adc1
;		snz				;
;		clr	adc1_acc		;if so, reset accumulator
;
; <end of version B>
;

:done_adcs


;
;**** Virtual Peripheral: Universal Asynchronous Receiver Transmitter (UART)
;			
;
UART
		_bank    serial                  ;switch to serial register bank
UART_com0
:transmit0
		clrb    tx0_divide.baud_bit     ;clear xmit timing count flag
		inc     tx0_divide              ;only execute the transmit routine
		STZ                             ;set zero flag for test
		SNB     tx0_divide.baud_bit     ; every 2^baud_bit interrupt
		test    tx0_count               ;are we sending?
		JZ      :receive0               ;if not, go to :receive
		clc                             ;yes, ready stop bit
		rr      tx0_high                ; and shift to next bit
		rr      tx0_low                 ;
		dec     tx0_count               ;decrement bit counter
		movb    tx0_pin,/tx0_low.6       ;output next bit
		;movb	RB.0,/tx0_low.6		;tx0_pin status by Red pb LED
;
:receive0 
	        movb    C,rx0_pin               ;get current rx bit
;
		jnb	g_ppg_sel_flag,:redirect_to_ppg	
		movb	tx1_pin,C		;rediret rx0_pin status to ppg

:redirect_to_ppg
		;movb	RB.1,c			;rx0_pin status by Green pb LED
		test    rx0_count               ;currently receiving byte?
		jnz     :rx0_bit                ;if so, jump ahead
		mov     W,#9                    ;in case start, ready 9 bits
		sc                              ;skip ahead if not start bit
		mov     rx0_count,W             ;it is, so renew bit count
		mov     rx0_divide,#start_delay ;ready 1.5 bit periods
:rx0_bit        djnz    rx0_divide,:rx0_done    ;middle of next bit?
		setb    rx0_divide.baud_bit     ;yes, ready 1 bit period
		dec     rx0_count               ;last bit?
		sz                              ;if not
		rr      rx0_byte                ;  then save bit
		snz                             ;if so
		setb    g_rx0_flag              ;  then set flag
:rx0_done
		;jmp	@UART_done		;skip UART_com1 int process

UART_com1
:transmit1
		clrb    tx1_divide.baud_bit     ;clear xmit timing count flag
		inc     tx1_divide              ;only execute the transmit routine
		STZ                             ;set zero flag for test
		SNB     tx1_divide.baud_bit     ; every 2^baud_bit interrupt
		test    tx1_count               ;are we sending?
		JZ      :receive1               ;if not, go to :receive
		clc                             ;yes, ready stop bit
		rr      tx1_high                ; and shift to next bit
		rr      tx1_low                 ;
		dec     tx1_count               ;decrement bit counter
		movb    tx1_pin,/tx1_low.6      ;output next bit
		;movb	RB.2,/tx1_low.6		;tx1_pin status by Blue pb LED
;
:receive1 
	        movb    C,rx1_pin               ;get current rx bit
		;movb	RB.3,C			;rx1_pin status by Black pb LED
		;movb	RB.6,C			;for oscilloscope
;
		jnb	g_ppg_sel_flag,:skip_tx0_echo	;REV 0.11B
		movb	tx0_pin,C			;ra.3=tx0_pin so tx0_pin=rx1_pin
:skip_tx0_echo
		test    rx1_count               ;currently receiving byte?
		jnz     :rx1_bit                 ;if so, jump ahead
		mov     W,#9                    ;in case start, ready 9 bits
		sc                              ;skip ahead if not start bit
		mov     rx1_count,W             ;it is, so renew bit count
		mov     rx1_divide,#start_delay ;ready 1.5 bit periods
:rx1_bit        djnz    rx1_divide,:rxdone1     ;middle of next bit?
		setb    rx1_divide.baud_bit     ;yes, ready 1 bit period
		dec     rx1_count               ;last bit?
		sz                              ;if not
		rr      rx1_byte                ;  then save bit
		snz                             ;if so
		setb    g_rx1_flag              ;  then set flag
:rxdone1

UART_done
;
;****** Virtual Peripheral: Time Clock
;
;	tick_low		=	80		;instruction count for
;	tick_high		=	195		; 50MHz xtal, turbo, prescaler=1
;
;	1ms=1,000,000ns
;	50,000cyc=1,000,000ns/20ns/cyc
;	50,000cyc=256cyc*195+80		;50,000=49920+80
;
		_BANK	clock			;select clock register bank
		MOV	W,#int_period		;load period between interrupts
		ADD	time_base_low,W		;add it to time base
		SNC				;skip ahead if no underflow
		INC	time_base_high		;yes overflow, adjust high byte
		MOV	W,#tick_high		;check for 1 msec click
		MOV	W,time_base_high-W	;Is high byte above or equal?
		MOV	W,#tick_low		;load instr. count low byte
		SNZ				;If hi byte equal, skip ahead
		MOV	W,time_base_low-W	;check low byte vs. time base
		SC				;skip ahead if low
		JMP	done_int		;If not, end interrupt
:got_tick	CLR	time_base_high		;Yes, adjust time_base reg.'s
		SUB	time_base_low,#tick_low	; leaving time remainder
		inc	msec0_low		;update system clock(msec cnt)
		snz				;
		inc	msec0_high
		snz
		inc	msec1_low
		snz
		inc	msec1_high

;/////////////////////////////////////////////
; LED control every 1 msec
:blink
		_bank	clock
		inc	blink_cnt_low
		snz
		inc	blink_cnt_high
		
		cjne	blink_cnt_low,blink_pre_low,:done_blink
		cjne	blink_cnt_high,blink_pre_high,:done_blink
; 
		jnb	led_pin,:set_led_on		;if led_pin is 'L',set led on
:set_led_off	
		snb	blink_enabled
		clrb	led_pin				;LED off
		mov	blink_pre_low,blink_off_low	;initialize preset counter
		mov	blink_pre_high,blink_off_high
		jmp	:reset_cnt
:set_led_on
		snb	blink_enabled
		setb	led_pin				;LED on
		mov	blink_pre_low,blink_on_low	;initialize preset counter
		mov	blink_pre_high,blink_on_high
:reset_cnt		
		clr	blink_cnt_low
		clr	blink_cnt_high	
:done_blink


msec_update
		_bank	main
		sb	msec_start_flag		;if msec_start_flag is off,
		jmp	done_int		;	get out of int
		djnz	msec_cnt,done_int
		clrb	msec_start_flag		;announce msec_delay done

done_int					;interrupt routines complete

;//////////////////////////////////////////////////////////////////////////////////
; Maximum interrupt length = 21 (timers:2) + 12 (PWMs:2) + 23 (ADCs:2) + 37 (UART)
;				+ 18 (clock) + 8 (switch) + (12) (PBs) + 10 (leds)
;				+ 4 (next two instr.) + 6 (RTCC interrupt processing)
;			   = 163 cycles  (must be =< int_period)
;//////////////////////////////////////////////////////////////////////////////////

		mov     W,#-int_period          ;interrupt every 'int_period' clocks
		RETIW                           ;exit interrupt
;
;******	End of interrupt sequence
;
;************************** RESET ENTRY POINT *****************************
;
reset_entry
;
		PAGE	start			;Set page bits and then
		JMP	start			; jump to start of code
		nop
;
;
;

;***************************** SUBROUTINES *********************************
;
		ORG     200h
;
;------------------------------------------------
; Terminal Subroutine - Get byte from console
;------------------------------------------------
Get_byte_from_con
:wait
		_BANK	serial			;re-select serial bank
		jnb     g_rx0_flag,:wait	;wait till byte is received
		clrb    g_rx0_flag              ;reset the receive flag
		mov     g_byte,rx0_byte         ;store byte (copy using W)
						; & fall through to echo char back
		mov	W,g_byte
;		snb	g_sx_sel_flag
		sb	g_ppg_sel_flag
		call	Send_byte_to_con	;echobacked in real
		snb	g_ppg_sel_flag
		call	Send_byte_to_ppg

		call	Uppercase		;cached in Uppercase
		cje	g_byte,#$0D,:buff_exit	;ignore it if char is <CR>
;
:debug0
		mov	W,g_arg_cnt		;branch upon W
		jmp	PC+W
		jmp	:cache_in_cmd		;if arg_cnt=0
		jmp	:cache_in_arg1		;if arg_cnt=1
		jmp	:cache_in_arg2		;if arg_cnt=2
		jmp	:cache_in_arg3		;if arg_cnt=3

:cache_in_cmd
		cje	g_byte,#' ',:next_buff	;if ' '(SPACE) then skip to prepare for next

		_BANK	command
		mov	FSR,cmd_ptr
		mov	IND,g_byte		;store it

		_BANK	general
		mov	cmd_arg_num,#0		;real arg count if stored

		_BANK	command
		inc	cmd_len
		inc	cmd_ptr			;next storing pointer
		jmp	:buff_exit

:cache_in_arg1
		cje	g_byte,#' ',:next_buff	;if ' '(SPACE) or '.'(PERIOD) then next buffer
		cje	g_byte,#'.',:next_buff	; '.' is bit delimiter

		_BANK	argument1
		mov	FSR,arg1_ptr
		mov	IND,g_byte		;store it

		_BANK	general
		mov	cmd_arg_num,#1		;real arg count if stored

		_BANK	argument1		
		inc	arg1_len
		inc	arg1_ptr		;next storing pointer
		jmp	:buff_exit

:cache_in_arg2
		cje	g_byte,#' ',:next_buff	;if ' '(SPACE) or '.'(PERIOD) then next buffer

		_BANK	argument2
		mov	FSR,arg2_ptr
		mov	IND,g_byte		;store it

		_BANK	general
		mov	cmd_arg_num,#2		;real arg count if stored

		_BANK	argument2		
		;//mov	g_arg_cnt,#2		;
		inc	arg2_len
		inc	arg2_ptr		;next storing pointer
		jmp	:buff_exit

:cache_in_arg3
		cje	g_byte,#' ',:next_buff	;if ' '(SPACE) or '.'(PERIOD) then next buffer

		_BANK	argument3
		mov	FSR,arg3_ptr
		mov	IND,g_byte		;store it

		_BANK	general
		mov	cmd_arg_num,#3		;real arg count if stored

		_BANK	argument3		
		;//mov	g_arg_cnt,#3		;
		inc	arg3_len
		inc	arg3_ptr		;next storing pointer
		jmp	:buff_exit

:next_buff
		cje	g_arg_cnt,#0,:skip_store_delimiter1	; cmd only such as 'VER'

:store_delimiter1
		_BANK	general
		mov	cmd_delim1,g_byte

:skip_store_delimiter1
		inc	g_arg_cnt
;
:buff_exit
		inc	FSR			;clear next byte
		clr	IND

		RETP
;		mov	W,g_byte		;restore W for echo back
;
						;# Get_byte_from_con #
;
;------------------------------------------------
; Terminal Subroutine - Get byte from PPG
;------------------------------------------------
Get_byte_from_ppg
:wait		_BANK	serial			;re-select serial bank
		jnb     g_rx1_flag,:wait	;wait till byte is received
		clrb    g_rx1_flag              ;reset the receive flag
		mov     g_byte,rx1_byte         ;store byte (copy using W)
						; & fall through to echo char back
		_bank	argument2
		mov	FSR,arg2_ptr
		mov	IND,g_byte		;store it
		inc	arg2_ptr		;next storing pointer
		mov	W,g_byte		;restore W for echo back
		jmp	Send_byte_to_con	;# Get_byte_from_ppg #
;
;------------------------------------------------
; Terminal Subroutine - Get Command from Console
;------------------------------------------------
Get_cmd_line_from_con
		_BANK	console_buff
		mov	con_buff_ptr,#con_buff
		mov	FSR,con_buff_ptr
:zero_buff
		clr	IND
		inc	FSR
		cjne	FSR,#0,:zero_buff

		mov	con_buff_ptr,#con_buff
		mov	FSR,con_buff_ptr	;for 1st byte
		mov	IND,g_byte		
		inc	con_buff_ptr
:cr
	       	call    Get_byte_from_con       ;get a byte via serial port
		_BANK	console_buff
		mov	FSR,con_buff_ptr
		cse	con_buff_ptr,#$FF	;overrun limiter
		mov	IND,g_byte
		cse	con_buff_ptr,#$FF	;overrun limiter
		inc	con_buff_ptr
		
	        cjne    g_byte,#13,:cr          ;loop until it's a <cr>
		mov	FSR,con_buff_ptr
		mov	IND,#0
		RETP                            ;# Get_cmd_line_from_con #
;
;------------------------------------------------
; Terminal Subroutine - Get return value from PPG
;------------------------------------------------
Get_rtn_val_from_ppg
:wait
		call    Get_byte_from_ppg       ;get a byte via serial port
	        cjne    g_byte,#'>',:wait  	;loop until it's a '>'
		RETP                            ;# Get_rtn_val_from_ppg #
;
;------------------------------------------------
; Terminal Subroutine - Send byte to Console
;------------------------------------------------
Send_byte_to_con       
		_BANK    serial
:wait
  	        test    tx0_count             	;wait for not busy(COM0)
		jnz     :wait                  ;
		not     W                       ;ready bits (inverse logic)
		mov     tx0_high,W              ; store data byte
		setb    tx0_low.7               ; set up start bit
		mov     tx0_count,#10           ;1 start + 8 data + 1 stop bit
		RETP                            ;# Send_byte_to_con #
;
;------------------------------------------------
; Terminal Subroutine - Send byte to PPG
;------------------------------------------------
Send_byte_to_ppg
		_BANK    serial
:wait
		test    tx1_count               ;wait for not busy(COM1)
		jnz     :wait                   ;
		not     W                       ;ready bits (inverse logic)
		mov     tx1_high,W              ; store data byte
		setb    tx1_low.7               ; set up start bit
		mov     tx1_count,#10           ;1 start + 8 data + 1 stop bit
		RETP                            ;# Send_byte_to_ppg #
;
;------------------------------------------------
; Terminal Subroutine - Send hex byte (2 digits)
;------------------------------------------------
	
Send_hex
		mov	M,#msg_category_0			 
	       	mov     W,#_cr                  ;get <cr> with <lf>
		call    Send_string_to_con 	; and send it
:num_only
		mov     W,<>g_number_low        ;get first digit
		call    :digit                  ; and send it
		mov     W,g_number_low          ;load 2nd digit
:digit
		and     W,#$F                   ;read hex chr
		mov     g_temp,W                ; and store it temporarily
		mov     W,#_hex                 ;load hex table address
;               clc                             ;only needed if CARRYX used
		add     W,g_temp                ;calculate hex table offset
		mov     M,#msg_category_0       ; and go get the appropriate
		IREAD                           ; character with indirect

		mov	W,#_WRITE_DIR_MODE	;restore from msg mode
		mov	M,W
		jmp     Send_byte_to_con        ;go send hex character
						;# Send_hex #
;
;------------------------------------------------
; Terminal Subroutine - Send String to Console
;------------------------------------------------
Send_string_to_con
		_bank 	general
		mov     string_ptr,W         	;store string_ptr address
		mov	g_M_reg,M
:loop
	        mov	M,g_M_reg		;read next string_ptr character

		mov	W,string_ptr         		
		IREAD                           ; using the mode register
		test    W                       ;are we at the last char?
		snz                             ;if not=0, skip ahead
		jmp	:done
		call    Send_byte_to_con        ;not 0, so send character
		_bank	general
		inc	string_ptr

		jmp     :loop                   ;loop until done
:done
		mov	W,#_WRITE_DIR_MODE	;restore from msg mode
		mov	M,W

		RETP				;# Send_string_to_con #
;
;------------------------------------------------
; Terminal Subroutine - Make byte uppercase
;------------------------------------------------
Uppercase
	       	csae    g_byte,#'a'         	;if byte is lowercase, then skip ahead
		ret
		sub     g_byte,#'a'-'A'         ;change byte to uppercase
		RETP                            ;# Uppercase #
;
;
;
;
;******************************** I2C Subroutines *****************************
;
; I2C Subroutines Call Header
;
Bus_delay	;jmp	@Bus_delay_body
Erase_Mem	;jmp	Erase_Mem_body
I2C_read	;jmp 	I2C_read_body
I2C_write	;jmp	I2C_write_body
Read_bit	;jmp	Read_bit_body
Send_Stop	;jmp	Send_stop_body
Send_start	;jmp	Send_start_body
Set_address	;jmp	Set_address_body
Setup_delay	;jmp	@Setup_delay_body
Take_sample	;jmp	Take_sample_body
Write_bit	;jmp	Write_bit_body
Write_byte	;jmp	Write_byte_body
		RETP
;

; BODY


;
;************************** End of I2C Subroutines ****************************
;
;
;
;
;
;************************************************
;		Main 
;************************************************
;
start

		;jmp	@interrupt
		;jmp	skip_ready

;////////////////////////////////////////////////////////////////////////////
;READY_BIT_frm_slv_pin	=	RE.0
;READY_ACK_to_slv_pin	=	RE.1

READY_bus_mx_DIR	= %0000_0001

		mov	W,#_WRITE_DIR_MODE
		mov	M,W
		mov    	RE,#%0000_0000         	;must specify port before dir set
		mov     !RE,#READY_bus_mx_DIR

:wait_ready_BIT_ON_from_slv			;READY_BIT:Master <----- Slave
		nop
		jnb	READY_BIT_frm_slv_pin,:wait_ready_BIT_ON_from_slv

		setb	READY_ACK_to_slv_pin	;READY_ACK:Master ------> Slave

:wait_ready_BIT_OFF_from_slv			;READY_BIT:Master <----- Slave
		nop				
		jb	READY_BIT_frm_slv_pin,:wait_ready_BIT_OFF_from_slv

		clrb	READY_ACK_to_slv_pin	;READY_ACK:Master ------> Slave

;////////////////////////////////////////////////////////////////////////////
;
skip_ready
		mov      RA,#%0011_1100           ;initialize port RA
		mov     !RA,#%0001_0100           ;Set RA in/out directions

		mov      RB,#%1111_0000         ;initialize port RB
		mov     !RB,#%0101_0000         ;Set RB in/out directions

		mov      RC,#%0000_0000         ;initialize port RC
		mov     !RC,#%0000_0000         ;Set RC in/out directions

		mov      RD,#%0000_0000         ;initialize port RC
		mov     !RD,#%0000_1011         ;Set RD in/out directions

		mov	W,#_WRITE_LVL_MODE	;input level
		mov	M,W
		mov     !RD,#0                  ; to cmos on port RD

;RE dir.
		mov	W,#_WRITE_DIR_MODE	;directon
		mov	M,W
		mov    	RE,#%0000_0000         	;must specify port before dir set
		mov     !RE,#RW_bus_mx_TX_DIR

		mov	W,#$0F	;read directon
		mov	M,W
		mov     !RE,W
		
		mov	FSR,#M_signal_ReadWrite
:FF_fill_00
		mov	IND,#$FF
		inc	FSR
		cjne	FSR,#$C0,:FF_fill_00

;		break
;		swap 	$BF
;		swap	$BF

;######################################################
	IF debug=1

		clrb	g_read_write_flag	;0:READ mode
		call	@_sx_func_SX48_READ_WRITE

		break
		swap 	$BF
		swap	$BF

		mov	FSR,#M_signal_ReadWrite
:FF_fill_01
		mov	IND,#$FF
		inc	FSR
		cjne	FSR,#$C0,:FF_fill_01

		call	@_sx_func_SX48_READ_WRITE
:eternal_loop
		nop
		jmp	:eternal_loop
	ENDIF
;######################################################

		jmp	real_start




;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

real_start


;		mov	W,#$0a			;reset all ram starting at $0A
		mov	W,#$08			;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


		call	@initialize_params	;blink beep params

		mov     !OPTION,#%10011111      ;enable rtcc interrupt

; Terminal - main loop
;
terminal 
		clrb	g_ppg_sel_flag		;flags.6
;		setb	g_sx_sel_flag		;flags.7

		mov	W,#msg_category_0
		mov	M,W

		mov     W,#_opening_msg         ;send hello string_ptr
		call    Send_string_to_con
		
:loop
		mov	W,#msg_category_0
		mov	M,W
	        mov     W,#_prompt              ;send prompt string_ptr '#'
		call    Send_string_to_con
;
:skip_sx_prompt
		clr	g_arg_cnt		;clear argument counter
:clear_buffer_bank
		mov	FSR,#calc                ;reset all ram starting at calc bank
		mov	fsr,w
:zero_buf
		;clr	ind			;clear using indirect addressing
		inc	fsr
		cjne	fsr,#$90,:zero_buf

;zero_cmd_buff
		_BANK	command
		mov	cmd_ptr,#cmd_buff
		clr	cmd_len
;zero_arg1_buff
		_BANK	argument1		;init arg1 block register
		mov	arg1_ptr,#arg1_buff
		clr	arg1_len
;zero_arg2_buff
		_BANK	argument2		;init arg2 block register
		mov	arg2_ptr,#arg2_buff
		clr	arg2_len
;zero_arg3_buff
		_BANK	argument3		;init arg3 block register
		mov	arg3_ptr,#arg3_buff
		clr	arg3_len

		_BANK	general
		mov	cmd_delim1,#' '		;space

;
		clrb	g_ppg_sel_flag
;
		call    Get_byte_from_con   	;get command from con via COM0
		call    Uppercase               ; make it uppercase
:check_prefix
		cje	g_byte,#$00,:loop	;loop back
		cje	g_byte,#'@',:ppg	;following string_ptr over to PPG
		cje	g_byte,#$0D,:loop	;loop back
:sx
		clrb	g_ppg_sel_flag		; means SX mode
		call	Get_cmd_line_from_con

:parsing_start
		_BANK	command
		clr	rsv_ref_cnt		;clear reserved cmd ref counter

		clr	g_temp
		mov	rsv_base,#_rsv_ref_table	;init rsv_ptr by _rsv_ref_table addr

:compare_cmd_len_loop
		mov	W,#0			;get reserved cmd len		
		mov	M,W
		mov	W,#offset_rsv_len
		add	W,rsv_base		;W=rsv_base+ offset_len addr
		IREAD
		mov	rsv_len,W		;rsv_len=[length of reserved command]
		cjne	rsv_len,cmd_len,:next_cmd_len	;refer to next reserved cmd
;
		mov	cmd_ptr,#cmd_buff
		mov	FSR,cmd_ptr		;IND=*FSR => IND=[console cmd char]

		mov	rsv_ptr,rsv_base
		add	rsv_ptr,#offset_rsv_cmd	

:compare_cmd_char_loop

		mov	W,#0		
		mov	M,W
		mov	W,rsv_ptr
		IREAD				;W=reserved cmd char
		mov	g_temp,W			;g_temp=[rsv cmd char]
		cjne	g_temp,IND,:next_cmd_len	;		
		dec	rsv_len
		jz	:ready_for_sx_func_call
		inc	FSR			;IND=next console cmd char
		inc	rsv_ptr
		jmp	:compare_cmd_char_loop		

:next_cmd_len
		inc	rsv_ref_cnt	;next rsv_cmd
		cje	rsv_ref_cnt,#rsv_sum,:not_reserved
		add	rsv_base,#offset_next_cmd
		jmp	:compare_cmd_len_loop

:ready_for_sx_func_call
		mov	W,#0		
		mov	M,W
		mov	W,#offset_func_num
		add	W,rsv_base		;w=rsv_base+offset_func_num
		IREAD				;get function number in W
		mov	g_sx_fnc_num,W
		clrb	g_sx_fnc_err
		call	@sx_function
		sb	g_sx_fnc_err
		jmp	:sx_cmd_done
		

:not_reserved
		mov	W,#msg_category_0
		mov	M,W
	        mov     W,#_invalid_cmd        	;send error message ' ?Invalid command:'
		call    send_string_to_con

		call	@show_cmd_buff_ascend
		mov	W,#' '			;space delimiter
		call	@send_byte_to_con

		call	@show_arg1_buff_ascend

		_BANK	general
		mov	W,cmd_delim1
		call	@send_byte_to_con

		call	@show_arg2_buff_ascend
		
		_BANK	general
		mov	W,cmd_delim1
		call	@send_byte_to_con

		call	@show_arg3_buff_ascend

:sx_cmd_done

		nop
		jmp :loop

;
;;;;;;;;;;;;;;;;;;;;;;;;;;;
:ppg
;		clrb	g_sx_sel_flag		;PPG mode
		setb	g_ppg_sel_flag
:wait_prompt			
:wait_flag		
		_BANK	serial			;re-select serial bank
		jnb     g_rx1_flag,:wait_flag	;wait till byte is received
		clrb    g_rx1_flag              ;reset the receive flag
		mov     g_byte,rx1_byte         ;store byte (copy using W)
						; & fall through to echo char back
		cjne    g_byte,#'>',:wait_prompt  	;loop until it's a '>'
		clrb	g_ppg_sel_flag		; reset PPG mode
;		setb	g_sx_sel_flag		;restore to sx mode
		
		jmp	:skip_sx_prompt		


;
;********************************************************
; Page 2($400~$5FF)
;********************************************************
		ORG	400h

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Conversion Subroutine Jump Header Table
;
;Note:'__'prefix to func name means a subsub routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Conv_asciiArg_to_16bit
		jmp	_Conv_asciiArg_to_16bit
;
Conv_16bit_to_asciiDecimal_arg1
		jmp	_Conv_16bit_to_asciiDecimal_arg1
;
Conv_16bit_to_asciiDecimal_arg2
		jmp	_Conv_16bit_to_asciiDecimal_arg2
;
;-------------------------------------------------------
; Convert Subroutine -  ASCII to 16 Bit binary
;	INPUT	: calc::asc_ptr
;	OUTPUT	: calc::result_low|result_high
;	ERROR	: Set Carry Flag
;	

;-------------------------------------------------------
_Conv_asciiArg_to_16bit

		_BANK	calc
		clr	result_low		;clear 16 bits result buffer
		clr	result_high
		clr	temp0_low
		clr	temp0_high

		mov	FSR,asc_ptr
		mov	W,IND
		_BANK	calc	
		mov	data_type,w
		cje	data_type,#'$',__cnv_asciiHex_to_16bit
		cje	data_type,#'%',__cnv_asciiBinary_to_16bit
		jmp	__cnv_asciiDecimal_to_16bit

;ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
; Sub^2 Routine:Convert ASCII Binary to 16 bit Binary
;	'%0000_1111' ====> $0F
;ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
__cnv_asciiBinary_to_16bit
		_BANK	calc
		dec	asc_len			;if '%' only,goto exit
		jz	:err
:loop
		inc	asc_ptr			;point to next char
		mov	FSR,asc_ptr
		cje	IND,#'_',:under_score	;ingnore '_'(underscore)
		mov	W,IND			;get char

		_BANK	calc
		mov	cnv_char,W
		cjb	cnv_char,#'0',:err	;must be '0' or '1'
		cja	cnv_char,#'1',:err
		mov	W,cnv_char

		and	W,#$0F			;mask upper nibble
		_BANK	calc
		mov	cnv_char,W
		snb	cnv_char.0		;if bit set,execute next
		inc	result_low
		dec	asc_len
		jz	:done
		clc				;clear carry for rotate
		rl	result_low
		rl	result_high
		jmp	:loop

:under_score
		_BANK	calc
		dec	asc_len
		jz	:done
		jmp	:loop

:err
		stc				;Error Carry=1
		RETP
:done		
		clc				;Success Carry=0
		RETP				
						;# asc_to_bin2:cnv_bin_to_16bit #

;ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
; Sub^2 Routine:Convert ASCII Hexadecimal to 16 bit Binary
;	'$0F' ====> $0F
;ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
__cnv_asciiHex_to_16bit

		_BANK	calc
		stc
		dec	asc_len			;if '$' only,goto exit
		jz	:err
:loop
		inc	asc_ptr			;point to next char
		mov	FSR,asc_ptr
		cje	IND,#'_',:loop		;ingnore '_'(underscore)
		mov	W,IND			;get char
		_BANK	calc
		mov	cnv_char,W
		mov	W,<>cnv_char		;'A'=$41 <-> $14
		mov	swap_hex,W
		cjb	cnv_char,#'0',:err
		cjbe	cnv_char,#'9',:got
;		call	Uppercase
		cjb	cnv_char,#'A',:err
		cja	cnv_char,#'F',:err
		add	swap_hex,#$90		;$14+$90 = $A4
:got		mov	rl_cnt,#4
:shift		rl	swap_hex
		rl	result_low
		rl	result_high
		djnz	rl_cnt,:shift
		dec	asc_len
		jz	:done
		jmp	:loop

:err
		stc				;Error Carry=1
		RETP
:done		
		clc				;Success Carry=0
		RETP
						;# cnv_asciiHex_to_16bit #


;ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
; Sub^2 Routine:Convert ASCII Decimal to 16 bit Binary
;	'15' ====> $0F
;ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
__cnv_asciiDecimal_to_16bit

		_BANK	calc
:loop
		mov	FSR,asc_ptr
		mov	W,IND
		_BANK	calc
		mov	cnv_char,W
		cjb	cnv_char,#'0',:err	;must be digit
		cja	cnv_char,#'9',:err
		mov	W,cnv_char
		and	W,#$0F			;mask upper nibble e.g $31->$01
		
		;_BANK	calc
		add	result_low,W		;put into number
		snc				;if carry set,execute next
		inc	result_high		;must add carry to byte_high
		dec	asc_len			;end of char ?
		jz	:done			;yes,goto exit
		mov	temp0_low,result_low	;copy byte_low & high to buff_low & high
		mov	temp0_high,result_high
		mov	temp1_low,result_low	;copy byte_low & high to buff_low & high
		mov	temp1_high,result_high

		clc				;clear carry 
		rl	temp0_low		;x2
		rl	temp0_high
		rl	temp0_low		;x4
		rl	temp0_high
		rl	temp0_low		;get (byte x 8)
		rl	temp0_high		;temp0=temp0*8
		clc
		rl	temp1_low		;get (buff x 2)
		rl	temp1_high		;temp1=temp0*2
		add	temp0_low,temp1_low	;
		snc				;if carry set,increment byte_high
		inc	temp0_high
		add	temp0_high,temp1_high	;temp0+temp2=temp0*(8+2)
;
		mov	result_low,temp0_low	
		mov	result_high,temp0_high	;result=result*10
		inc	asc_ptr			;increment here 
		jmp	:loop
:err
		stc				;Error Carry=1
		RETP
:done
		clc				;Success Carry=0
		RETP				;# asc_to_bin2:cnv_dec_to_16bit #

;
;---------------------------------------------------------------------
; Convert Subroutine - 16 Bit binary to ASCII Decimal Using Arg1 Bank
;	INPUT	: ::
;	OUTPUT	: ::
;	ERROR	: No error
;---------------------------------------------------------------------
_Conv_16bit_to_asciiDecimal_arg1

		_BANK	argument1
		mov	arg1_ptr,#arg1_buff	;initialize pointer
		clr	arg1_len		;clear buffer_quotient
		_BANK	calc
		clr	quotient_low		;clear quotient
		clr	quotient_high
:loop
		stc
		sub	value_low,#10
		sc				;C=0 means borrow,execute next if C=0
		dec	value_high
		csne	value_high,#$ff
		jmp	:next_digit
		inc	quotient_low
		snz				;if Z=1,execute next
		inc	quotient_high
		jmp 	:loop
:next_digit
		add	value_low,#10		;restore value_low
		mov	remainder_low,value_low
		add	remainder_low,#'0'	;to ASCII
		mov	W,remainder_low
		_BANK	argument1
		mov	arg1_char,W
		mov	FSR,arg1_ptr
		inc	arg1_len
		mov	IND,arg1_char

		_BANK	calc
		test 	quotient_high		;continue,if not zero
		jnz	:continue
		test	quotient_low		;continue,if not zero
		jnz	:continue
		jmp	:exit			;if both of them equal to sero,exit
:continue
		_BANK	argument1
		inc	arg1_ptr
		_BANK	calc
		mov	value_low,quotient_low
		mov	value_high,quotient_high

		clr	quotient_low		;clear quotient for new division
		clr	quotient_high
		jmp	:loop
:exit
		nop
		RETP				;# bin_to_asc_using_arg1 #

;
;---------------------------------------------------------------------
; Convert Subroutine - 16 Bit binary to ASCII Decimal Using Arg2 Bank
;	INPUT	: ::
;	OUTPUT	: ::
;	ERROR	: No error
;---------------------------------------------------------------------
_Conv_16bit_to_asciiDecimal_arg2
		_BANK	argument2
		mov	arg2_ptr,#arg2_buff	;initialize pointer
		clr	arg2_len		;clear buffer_quotient
		_BANK	calc
		clr	quotient_low		;clear quotient
		clr	quotient_high

:loop		stc
		sub	value_low,#10
		sc				;C=0 means borrow,execute next if C=0
		dec	value_high
		csne	value_high,#$FF		;borrow ?
		jmp	:next_digit
		inc	quotient_low
		snz				;if Z=1,execute next
		inc	quotient_high
		jmp 	:loop

:next_digit	add	value_low,#10		;restore value_low
		mov	remainder_low,value_low
		add	remainder_low,#'0'	;to ASCII
		mov	W,remainder_low
		_BANK	argument2
		mov	arg2_char,W
		mov	FSR,arg2_ptr
		inc	arg2_len
		mov	IND,arg2_char

		_BANK	calc
		test 	quotient_high		;continue,if not zero
		jnz	:continue
		test	quotient_low		;continue,if not zero
		jnz	:continue
		jmp	:exit			;if both of them equal to sero,exit

:continue	_BANK	argument2
		inc	arg2_ptr
		_BANK	calc
		mov	value_low,quotient_low
		mov	value_high,quotient_high

		clr	quotient_low		;clear quotient for new division
		clr	quotient_high
		jmp	:loop

:exit		RETP				;# bin_to_asc_using_arg2 #



;****************** ARITHMETIC ROUTINES *************************
;
;-------------------------------------------------------------------		
; Arithmetic Subroutine - 16-bits Division
;-------------------------------------------------------------------
divide16
		clr	shift_counter		;assume not divideing by zero
		clc
:loop
		rl	divisor_low
		rl	divisor_high	
		inc	shift_counter
		jnc	:loop

; restore divisor so top bit is 1
		rr	divisor_high		;shift back right to get top bit 1
		rr	divisor_low
; counter has number of bits in quotient
		clr	quotient_low
		clr	quotient_high

:dloop
		test	shift_counter		;check counter
		jz	:done			;if counter=0,finish
		clc				;clear carry
		rl	quotient_low		;
		rl	quotient_high

:compare16
		cjb	dividend_high,divisor_high,:dloop1	;if dividend<divisor,jump
		cja	dividend_high,divisor_high,:exec_sub16
		cje	dividend_high,divisor_high,:compare_low	;

:compare_low
		cjb	dividend_low,divisor_low,:dloop1	;
:exec_sub16
		sub	dividend_high,divisor_high		; subtraction
		sub	dividend_low,divisor_low
		sc	
		dec	dividend_high
		clc
		inc	quotient_low		;quotient=quotient+1
		snc
		inc	quotient_high
:dloop1
		dec	shift_counter		;counter=counter-1
		clc				;clear carry for rr
		rr	divisor_high		;divisor=divisor/2
		rr	divisor_low
		jmp	:dloop

:done
		mov	remainder_low,dividend_low
		mov	remainder_high,dividend_high
		RETP				;# divide16 #


;
;********************************************************
; Page 3($600~$7FF)
;********************************************************
		ORG	600h
;
;--------------------------
; Show Parameters
;--------------------------
show_params
		mov	W,#msg_category_0
		mov	M,W
		mov	W,#_cr
		call	@send_string_to_con

		call 	show_arg1_buff_descend

		mov	W,#' '			;space delimiter
		call	@send_byte_to_con

		call	show_arg2_buff_descend

		mov	W,#$0D			;dummy byte
		call	@send_byte_to_con

		RETP

;--------------------------
; Show Command Buffer
;--------------------------
show_cmd_buff_ascend
		_BANK	command
		mov	cmd_ptr,#cmd_buff	;initialize pointer
:loop_cmd
		mov	FSR,cmd_ptr
		mov	W,IND
		call	@send_byte_to_con
		_BANK	command
		inc	cmd_ptr
		dec	cmd_len
		jnz	:loop_cmd
		RETP

;--------------------------
; Show Argument1 Buffer
;--------------------------
show_arg1_buff_ascend
		_BANK	argument1
		cje	arg1_len,#0,:exit	;if arg1_len=0 then exit
		mov	arg1_ptr,#arg1_buff	;initialize pointer
:loop_arg1
		mov	FSR,arg1_ptr
		mov	W,IND
		call	@send_byte_to_con
		_BANK	argument1
		inc	arg1_ptr
		dec	arg1_len
		jnz	:loop_arg1
:exit
		RETP

;--------------------------
; Show Argument2 Buffer
;--------------------------
show_arg2_buff_ascend
		_BANK	argument2
		cje	arg2_len,#0,:exit	;if arg2_len=0 then exit
		mov	arg2_ptr,#arg2_buff	;initialize pointer
:loop_arg2
		mov	FSR,arg2_ptr
		mov	W,IND
		call	@send_byte_to_con
		_BANK	argument2
		inc	arg2_ptr
		dec	arg2_len
		jnz	:loop_arg2
:exit
		RETP
;
;--------------------------
; Show Argument3 Buffer
;--------------------------
show_arg3_buff_ascend
		_BANK	argument3
		cje	arg3_len,#0,:exit	;if arg2_len=0 then exit
		mov	arg3_ptr,#arg3_buff	;initialize pointer
:loop_arg3
		mov	FSR,arg3_ptr
		mov	W,IND
		call	@send_byte_to_con
		_BANK	argument3
		inc	arg3_ptr
		dec	arg3_len
		jnz	:loop_arg3
:exit
		RETP
;


show_arg1_buff_descend
		_BANK	argument1
:loop_arg1
		mov	FSR,arg1_ptr
		mov	W,IND
		call	@send_byte_to_con
		_BANK	argument1
		dec	arg1_ptr
		dec	arg1_len
		jnz	:loop_arg1
		RETP

show_arg2_buff_descend
		_BANK	argument2
:loop_arg2
		mov	FSR,arg2_ptr
		mov	W,IND
		call	@send_byte_to_con
		_BANK	argument2
		dec	arg2_ptr
		dec	arg2_len
		jnz	:loop_arg2

		RETP
;
;********************************************************
; 		SX Function Call Entry
;********************************************************



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;	SX Function Call Jump Vector 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
sx_function

		mov	W,g_sx_fnc_num		
		jmp	PC+W
		jmp	sx_func_OUT	;fnc_nm=0
		jmp	sx_func_IN	;	1
		jmp	sx_func_VER	;	2	
		jmp	sx_func_SETB	;	3
		jmp	sx_func_CLRB	;	4
		jmp	sx_func_TESTB	;	5
		jmp	sx_func_M	;	6
		jmp	sx_func_READ	;	7
		jmp	sx_func_WRITE	;	8


;
;------------------------------------------------
; SX Function #0 - Write Byte to Local Port
;------------------------------------------------
sx_func_OUT
		_BANK	general
		cjne	cmd_arg_num,#2,sx_fnc_err

		call 	@Convert_Arguments_to_Hexadecimal
		snc				;if Carry=1 then goto sx_fnc_err
		jmp	sx_fnc_err

		_BANK	argument1
		mov	g_byte,arg1_low		;push in global
	
		_BANK	argument2
		mov	FSR,arg2_low		;FSR=port addr IND=port status
		mov	IND,g_byte		;write 8 bit pattern in IND
		jmp	sx_func_done		;
;
;------------------------------------------------
; SX Function #1 - Read Byte from Local Port
;------------------------------------------------
sx_func_IN
		_BANK	general
		cjne	cmd_arg_num,#1,sx_fnc_err

		call 	@Convert_Arguments_to_Hexadecimal
		snc				;if Carry=1 then goto sx_fnc_err
		jmp	sx_fnc_err

		_BANK	argument1
		mov	FSR,arg1_low
		mov	W,IND
		_BANK	calc
		mov	value_low,W
		mov	value_high,#0
;		call	@Conv_16bit_to_asciiDecimal_arg2
		call	@Conv_8bit_to_asciiHex_arg2
		mov	W,#msg_category_0
		mov	M,W
		mov	W,#_cr
		call	@send_string_to_con

		_BANK	argument2
:loop		mov	FSR,arg2_ptr
		mov	W,IND
		call	@send_byte_to_con	;using BANK serial
		_BANK	argument2		;so must switch bank
		dec	arg2_ptr
		dec	arg2_len
		jnz	:loop
		
		mov	W,#$0D			;dummy byte for timing ?
		call	@send_byte_to_con
		jmp	sx_func_done
;
;------------------------------------------------
; SX Function #2 - Get Version
;------------------------------------------------
sx_func_VER
		_BANK	general
		cjne	cmd_arg_num,#0,sx_fnc_err


		mov	W,#msg_category_0
		mov	M,W
		mov	W,#_opening_msg
		call	@send_string_to_con
		jmp	sx_func_done
;
;
;------------------------------------------------
; SX Function #3 - Set Bit
; SX Function #4 - Clear Bit
; SX Function #5 - Test Bit Status
;------------------------------------------------
sx_func_SETB
sx_func_CLRB
sx_func_TESTB
;
sx_func_SETB_CLRB_TESTB_common
		_BANK	general
		cjne	cmd_arg_num,#2,sx_fnc_err

		call 	@Convert_Arguments_to_Hexadecimal
		snc				;if Carry=1 then goto sx_fnc_err	
		jmp	sx_fnc_err

		_BANK	argument2
		mov	W,arg2_low		;get bit position
		_BANK	calc
		mov	shift_counter,W
		mov	g_byte,#%0000_0001
		test	shift_counter
		jz	:select_port

:shift_more	rl	g_byte
		dec	shift_counter
		jnz	:shift_more
	
:select_port	_BANK	argument1
		mov	W,arg1_low		;get port address
		mov	FSR,W
		cje	g_sx_fnc_num,#7,:setb
		cje	g_sx_fnc_num,#8,:clrb
		cje	g_sx_fnc_num,#9,:testb

:setb		or	IND,g_byte
		jmp	sx_func_done

:clrb		not	g_byte
		and	IND,g_byte
		jmp	sx_func_done

:testb		and	g_byte,IND
		jnz	:return_1

:return_0
		mov	W,#msg_category_0
		mov	M,W
		mov	W,#_zero
		call	@Send_string_to_con
		jmp	sx_func_done

:return_1
		mov	W,#msg_category_0
		mov	M,W
		mov	W,#_one
		call	@Send_string_to_con
		jmp	sx_func_done	


;------------------------------------------------
; SX Function #6 - M Signal 
;------------------------------------------------
sx_func_M
		JMP     sx_func_done            

;------------------------------------------------
; SX Function #7 - Read Data from Any SX48
;------------------------------------------------
sx_func_READ
		clrb	g_read_write_flag	;0:READ mode
		call	@_sx_func_SX48_READ_WRITE
		jmp     sx_func_done            

;
;------------------------------------------------
; SX Function #8 - Write Data to Any SX48
;------------------------------------------------
sx_func_WRITE
		setb	g_read_write_flag	;1:WRITE mode
		call	@_sx_func_SX48_READ_WRITE
		jmp	sx_func_done

;
;
; SX Function Call Exit
sx_fnc_err
		setb	g_sx_fnc_err
sx_func_done
		nop
		RETP
;
;
;
;
;********************************************************
; Page 4($800~$9FF)
;********************************************************
		org	$800

Conv_8bit_to_asciiHex_arg2
		jmp	_Conv_8bit_to_asciiHex_arg2
;
;---------------------------------------------------------------------
; Convert Subroutine - 8 Bit binary(value_low) to ASCII Hex Using Arg2 Bank
;	INPUT	:value_low
;	OUTPUT	:arg2_buffer
;---------------------------------------------------------------------
_Conv_8bit_to_asciiHex_arg2
		_BANK	argument2
		mov	arg2_ptr,#arg2_buff	;initialize pointer
		clr	arg2_len		;clear buffer

		_BANK	calc

		mov	temp0_low,#$30		;offset for 0-9
		mov	temp0_high,#$37		;offset for A-F


		mov	value_high,value_low	;backup the copy in value_high

		and	value_low,#$0F		;mask
		mov	nibble_low,value_low
		csae	nibble_low,#$0A		;if nibble==0-9 then
		clrb	add_offset_flag		; 	add $30		
		csb	nibble_low,#$0A		;if nibble==A-F then
		setb	add_offset_flag		;	add_offset_37h	

		mov	W,nibble_low	
		call	add_offset_to_be_ascii	;W=RetValue

		_BANK	argument2
		mov	arg2_char,W		;W is bank free
		mov	FSR,arg2_ptr
		inc	arg2_len
		mov	IND,arg2_char

		inc	arg2_ptr

		_BANK	calc
		mov	W,<>value_high		;nibble swap
		mov	value_high,W
		and	value_high,#$0F		;mask
		mov	nibble_high,value_high
		csae	nibble_high,#$0A
		clrb	add_offset_flag		;add $30		
		csb	nibble_high,#$0A
		setb	add_offset_flag		;add_offset_37h	

		mov	W,nibble_high	
		call	add_offset_to_be_ascii	;W=RetValue

		_BANK	argument2
		mov	arg2_char,W		;W is bank free
		mov	FSR,arg2_ptr
		inc	arg2_len
		mov	IND,arg2_char

:exit
		RETP				;# bin_to_asc_using_arg2 #

;
add_offset_to_be_ascii
		sb	add_offset_flag
		add	W,temp0_low
		snb	add_offset_flag
		add	W,temp0_high		
		RETP
;
;
;
;-------------------------------------------------------------
; Convert Subroutine - Ascii Arguments(1-2) to Hex
;	INPUT	:arg1_buff, arg2_buff
;	OUTPUT	:[arg1_low|arg1_hig], [harg1_low|arg1_high]
;	ERROR	: goto :err //Set g_sx_fnc_err Flag
;
;   Note:This routine is called by sx_func after arg count check successful
;--------------------------------------------------------------
Convert_Arguments_to_Hexadecimal
; convert argument1 ascii to 16 bit binary
:cnv_arg1
		clrb	g_got_hex

		_BANK	argument1		;mov asc_len,arg1_len
		cje	arg1_len,#0,:cnv_arg2	;if no parameter then goto arg2

		mov	W,arg1_len
		_BANK	calc
		mov	asc_len,W

		_BANK	argument1		;mov asc_ptr,#arg1_buff
		mov	W,#arg1_buff
		_BANK	calc
		mov	asc_ptr,W
;
		call	@Conv_asciiArg_to_16bit	;calc:result=ret_value
		snc				;if Carry=1 then goto :err
		jmp	:err


; 	store it in arg1 register bank		
		_BANK	calc			;argument1:arg1=calc:result
		mov	W,result_low
		_BANK	argument1
		mov	arg1_low,W
		mov	g_number_low,W		;copy to global

		_BANK	calc			
		mov	W,result_high
		_BANK	argument1
		mov	arg1_high,W
		mov	g_number_high,W		;		

		setb	g_got_hex

;//convert argument2 ascii to 16 bit binary
:cnv_arg2
		_BANK	argument2		;mov asc_len,arg2_len
		cje	arg2_len,#0,:exit	;no parameter ?

		mov	W,arg2_len
		_BANK	calc
		mov	asc_len,W

		_BANK	argument2		;mov asc_ptr,#arg1_buff
		mov	W,#arg2_buff
		_BANK	calc
		mov	asc_ptr,W
;
		call	@Conv_asciiArg_to_16bit	;calc:result=ret_value
		snc				;if Carry=1 then goto :err
		jmp	:err

; store convert result in arg2 register bank		
		_BANK	calc			;argument2:arg2=calc:result
		mov	W,result_low
		_BANK	argument2
		mov	arg2_low,W

		_BANK	calc			
		mov	W,result_high
		_BANK	argument2
		mov	arg2_high,W
		;jmp	:exit


;//convert argument3 ascii to 16 bit binary
:cnv_arg3
		_BANK	argument3		;mov asc_len,arg3_len
		cje	arg3_len,#0,:exit	;no parameter ?

		mov	W,arg3_len
		_BANK	calc
		mov	asc_len,W

		_BANK	argument3		;mov asc_ptr,#arg3_buff
		mov	W,#arg3_buff
		_BANK	calc
		mov	asc_ptr,W
;
		call	@Conv_asciiArg_to_16bit	;calc:result=ret_value
		snc				;if Carry=1 then goto :err
		jmp	:err

; store convert result in arg3 register bank		
		_BANK	calc			;argument3:arg3=calc:result
		mov	W,result_low
		_BANK	argument3
		mov	arg3_low,W

		_BANK	calc			
		mov	W,result_high
		_BANK	argument3
		mov	arg3_high,W
		jmp	:exit

:err
		stc
		RETP	
:exit
		clc
		RETP	
;
;********************************************************
; Page 5($A00~$BFF)
;********************************************************
		org	$A00

M_Signal_master_start


	
		_BANK	M_signal_ReadWrite

;//////////////////
;// Write M_num
;//////////////////

		mov    	RE,#%0000_0000         	;must specify port before dir set
		mov     !RE,#M_bus_mx_TX_DIR
		
		;mov	M_num,#$27
		;or	RE,M_num
	
		mov	W,RE			;get current RE bit pattern
		and	W,#%11_000000		;clear M_bits area
		mov	M_zero_bit_ptn,W
		mov	M_num,#$27		;set M_result
		or	M_num,M_zero_bit_ptn
		mov	RE,M_num

						;I have sent M_num	
		setb	M_STRB_to_sx_pin	;M_STRB:Master ------> Slave

:wait_ACK_ON_from_sx				;M_ACK:Master <----- Slave
		nop
		jnb	M_ACK_frm_sx_pin,:wait_ACK_ON_from_sx

		clrb	M_STRB_to_sx_pin	;M_STRB:Master ------> Slave

:wait_ACK_OFF_from_sx
		nop				;M_ACK:Master <----- Slave
		jb	M_ACK_frm_sx_pin,:wait_ACK_OFF_from_sx

;//////////////////
;// Read M_result
;//////////////////

		mov    	RE,#%0000_0000         	;must specify to avoid confusion
		mov     !RE,#M_bus_mx_RX_DIR

:wait_STRB_ON_from_sx
		nop				;M_STRB:Master <------ Slave
		jnb	M_STRB_frm_sx_pin,:wait_STRB_ON_from_sx


		mov	W,RE
		and	W,#%0011_1111		;mask to get M_result only
		mov	M_result,W		;store M_result 

		setb	M_ACK_to_sx_pin		;M_ACK:Master -----> Slave

:wait_STRB_OFF_from_sx
		nop				;M_STRB:Master <----- Slave
		jb	M_STRB_frm_sx_pin,:wait_STRB_OFF_from_sx

		clrb	M_ACK_to_sx_pin		;M_ACK:Master -----> Slave

:exit
		nop
		jmp	:exit

						;# M_Signal_master_start #

;
;
;
;--------------------------------------------
; SX48 Memory Read/Write
;--------------------------------------------
_sx_func_SX48_READ_WRITE

		mov	FSR,#M_signal_ReadWrite
:FF_fill_01
		mov	IND,#$FF
		inc	FSR
		cjne	FSR,#$BF,:FF_fill_01

		_BANK	M_signal_ReadWrite
		inc	RW_session_cnt

		;break
		call 	@Convert_Arguments_to_Hexadecimal
		snc				;if Carry=1 then goto sx_fnc_err
		jmp	:err

;copy 3 args from arg banks to M_signal_ReadWrite bank
		_BANK	argument1
		mov	W,arg1_low
		_BANK	M_signal_ReadWrite
		mov	RW_arg1,W

		_BANK	argument2
		mov	W,arg2_low
		_BANK	M_signal_ReadWrite
		mov	RW_arg2,W

		_BANK	argument3
		mov	W,arg3_low
		_BANK	M_signal_ReadWrite
		mov	RW_arg3,W

;branch into localSX48 or interSX48

		_BANK	general
		jb	g_read_write_flag,:write_branch		;if WRITE mode
		jmp	:read_branch				;	else READ mode

:read_branch
		cjbe	cmd_arg_num,#1,:__LocalSX48_read

		_BANK	M_signal_ReadWrite
		cje	RW_arg2,#0,:__LocalSX48_read
		jmp	:_InterSX48_ReadWrite			

:write_branch
		cjbe	cmd_arg_num,#2,:__LocalSX48_write

		_BANK	M_signal_ReadWrite
		cje	RW_arg3,#0,:__LocalSX48_write
		jmp	:_InterSX48_ReadWrite

;;;;;;;;;;;;;;;;;;;;;;;;;;
; Local Read/Write
;;;;;;;;;;;;;;;;;;;;;;;;;;
:__LocalSX48_write
		_BANK	argument1
		mov	g_byte,arg1_low		;push in global
	
		_BANK	argument2
		mov	FSR,arg2_low		;FSR=port addr IND=port status
		mov	IND,g_byte		;write 8 bit pattern in IND
		jmp	:exit		;

:__LocalSX48_read
		_BANK	argument1
		mov	FSR,arg1_low
		mov	W,IND
		_BANK	calc
		mov	value_low,W
		mov	value_high,#0
		call	@Conv_8bit_to_asciiHex_arg2
		mov	W,#msg_category_0
		mov	M,W
		mov	W,#_cr
		call	@send_string_to_con

		_BANK	argument2

:loop_send_byte_to_con
		mov	FSR,arg2_ptr
		mov	W,IND
		call	@send_byte_to_con	;using BANK serial
		_BANK	argument2		;so must switch bank
		dec	arg2_ptr
		dec	arg2_len
		jnz	:loop_send_byte_to_con
		
		mov	W,#$0D			;dummy byte for timing ?
		call	@send_byte_to_con
		jmp	:exit

;;;;;;;;;;;;;;;;;;;;;;;;;;
; InterSX48 ReadWrite
;;;;;;;;;;;;;;;;;;;;;;;;;;
:_InterSX48_ReadWrite

		_BANK	M_signal_ReadWrite

;///////////////////////////
;Communication Bus mode
;///////////////////////////

		setb	RW_bus_sel_pin		;set to Read/Write bus mode,not M_signal

		setb	RW_STRB_to_ta_pin	;RW_STRB:Master -----> the target

:wait_ACK_ON_from_ta_RW_bus			;RW_ACK:Master <----- the target
		nop
		jnb	RW_ACK_frm_ta_pin,:wait_ACK_ON_from_ta_RW_bus

		clrb	RW_STRB_to_ta_pin	;RW_STRB:Master -----> the target

:wait_ACK_OFF_from_ta_RW_bus			;RW_ACK:Master <----- the target
		nop
		jb	RW_ACK_frm_ta_pin,:wait_ACK_OFF_from_ta_RW_bus

;//////////////////
;Write/Read mode
;//////////////////

		clrb	RW_read_write_pin	;Read mode in default
		snb	g_read_write_flag	;if g_read_write_flag=1 then
		setb	RW_read_write_pin	;                    Write mode

		setb	RW_STRB_to_ta_pin	;RW_STRB:Master -----> the target

:wait_ACK_ON_from_ta_RW_mode			;RW_ACK:Master <----- the target
		nop
		jnb	RW_ACK_frm_ta_pin,:wait_ACK_ON_from_ta_RW_mode

		clrb	RW_STRB_to_ta_pin	;RW_STRB:Master -----> the target


:wait_ACK_OFF_from_ta_RW_mode		;RW_ACK:Master <----- the target
		nop
		jb	RW_ACK_frm_ta_pin,:wait_ACK_OFF_from_ta_RW_mode

;//////////////////
;number of arg
;//////////////////

		sb	RW_read_write_pin	; if 1 then skip next
		jmp	:set_arg_cnt_1		;
		mov	RW_arg_cnt,#2		;data+addr ,excludes sx_id

:set_arg_cnt_1
		snb	RW_read_write_pin	; if 0 then skip next
		jmp	:arg_cnt_set_exit
		mov	RW_arg_cnt,#1		;data only ,excludes sx_id
:arg_cnt_set_exit
		;break

;init arg pointer
		mov	RW_arg_ptr,#RW_arg1


;////////////////////////
; Transmit Byte Date
;////////////////////////
	
:transmit_next_byte
;
; Transmit Upper Nibble
;
		mov	W,#_WRITE_DIR_MODE
		mov	M,W
		mov     !RE,#RW_bus_mx_TX_DIR

		mov	FSR,Rw_arg_ptr
		mov	RW_temp,IND
		and	RW_temp,#%1111_0000

		clc
		rr	RW_temp
		rr	RW_temp
		rr	RW_temp
		rr	RW_temp
		mov	RW_tx_upper_nibble_log,RW_temp

		mov	W,RE
		and	W,#%1111_0000
		or	W,RW_temp
		mov	RE,W			;transmit upper nibble
		mov	RW_tx_upper_nibble_phy,RE

		mov	W,#_READ_DIR_MODE	;read directon
		mov	M,W
		mov     !RE,W

		nop				;read-modify-write consideration??
		nop
		nop

		setb	RW_STRB_to_ta_pin	;Strobe to the target SX48

:wait_upper_ACK_ON_from_ta			;RW_ACK:Master <----- the target
		nop
		jnb	RW_ACK_frm_ta_pin,:wait_upper_ACK_ON_from_ta
		clrb	RW_STRB_to_ta_pin	;RW_STRB:Master -----> the target

:wait_upper_ACK_OFF_from_ta			;RW_ACK:Master <----- the target
		nop
		jb	RW_ACK_frm_ta_pin,:wait_upper_ACK_OFF_from_ta
		

;
; Transmit Lower Nibble
;

		mov	RW_temp,IND
		and	RW_temp,#%0000_1111
		mov	RW_tx_lower_nibble_log,RW_temp

		mov	W,RE
		and	W,#%1111_0000
		or	W,RW_temp
		mov	RE,W			;transmit lower nibble
		mov	RW_tx_lower_nibble_phy,RE

;
		nop				;read-modify-write consideration??
		nop
		nop
;
		setb	RW_STRB_to_ta_pin	;RW_STRB:Master -----> the target

:wait_lower_ACK_ON_from_ta			;RW_ACK:Master <----- the target
		nop
		jnb	RW_ACK_frm_ta_pin,:wait_lower_ACK_ON_from_ta
		clrb	RW_STRB_to_ta_pin	;RW_STRB:Master -----> the target

:wait_lower_ACK_OFF_from_ta			;RW_ACK:Master <----- the target
		nop
		jb	RW_ACK_frm_ta_pin,:wait_lower_ACK_OFF_from_ta


		inc	RW_arg_ptr
		djnz	RW_arg_cnt,:transmit_next_byte

		dec	RW_arg_ptr

		snb	RW_read_write_pin	;skip next if 0:READ
		jmp	:exit			;exit when Write command


;////////////////////////
; Receive Byte Data
;////////////////////////

		mov	W,#_WRITE_DIR_MODE
		mov	M,W
		mov     !RE,#RW_bus_mx_RX_DIR

:wait_upper_STRB_ON_from_ta			;RW_STRB:Master <----- the target
		nop
		jnb	RW_STRB_frm_ta_pin,:wait_upper_STRB_ON_from_ta

		mov	RW_rx_upper_nibble_phy,RE
		mov	W,RE
		and	W,#%0000_1111	;mask
		mov	RW_read_val,W
		clc
		rl	RW_read_val
		rl	RW_read_val
		rl	RW_read_val
		rl	RW_read_val

		setb	RW_ACK_to_ta_pin	;RW_ACK:Master -----> the target

:wait_upper_STRB_OFF_from_ta			;RW_STRB:Master <----- the target
		nop
		jb	RW_STRB_frm_ta_pin,:wait_upper_STRB_OFF_from_ta

		clrb	RW_ACK_to_ta_pin	;RW_ACK:Master -----> the target

:wait_lower_STRB_ON_from_ta			;RW_STRB:Master <----- the target
		nop
		jnb	RW_STRB_frm_ta_pin,:wait_lower_STRB_ON_from_ta


		mov	RW_rx_lower_nibble_phy,RE
		mov	W,RE
		and	W,#%0000_1111		;mask
		or	RW_read_val,W		;final result(=Read Value)

		setb	RW_ACK_to_ta_pin	;RW_ACK:Master -----> the target

:wait_lower_STRB_OFF_from_ta			;RW_STRB:Master <----- the target
		nop
		jb	RW_STRB_frm_ta_pin,:wait_lower_STRB_OFF_from_ta

		clrb	RW_ACK_to_ta_pin	;RW_ACK:Master -----> the target

		;RETP
		;jmp	:CR

;////////////////////
; Console Out
;////////////////////

		;_BANK	argument1
		;mov	FSR,arg1_low

		mov	W,RW_read_val
		_BANK	calc
		mov	value_low,W
		mov	value_high,#0
		call	@Conv_8bit_to_asciiHex_arg2
		mov	W,#msg_category_0
		mov	M,W
		mov	W,#_cr
		call	@send_string_to_con

		_BANK	argument2

:loop_byte_to_con
		mov	FSR,arg2_ptr
		mov	W,IND
		call	@send_byte_to_con	;using BANK serial
		_BANK	argument2		;so must switch bank
		dec	arg2_ptr
		dec	arg2_len
		jnz	:loop_byte_to_con
:CR		
		mov	W,#$0D			;dummy byte for timing ?
		call	@send_byte_to_con
		jmp	:exit

:err
		setb	g_sx_fnc_err		
:exit
		clrb	g_sx_fnc_err
		RETP
						;# _sx_func_InterSX48_READ_WRITE #
		
;
;
;

				

;********************************************************
; Page 6($C00~$DFF)
;********************************************************
		org	$C00



;********************************************************
; Page 7($E00~$FFF)
;********************************************************
		org	$E00

;/////// PROGRAM DATA (CATEGORY 0) //////////////////////
; 
_opening_msg    dw      13,10,13,10,'EMRRA-Refinary_SX-III_Master_proto Rev 0.97Gz1d_WITH_SLAVE{@9600bps}'
_copyright	dw	13,10,'      Created by Systems Research,Inc.1999-2008'
_cr             DW      13,10,0
_prompt         dw      13,10,'>',0
_hex            dw      '0123456789ABCDEF'
_space          DW      ' ',0
_sample         DW      13,10,'Sample=',0
_view           DW      13,10,'Bytes stored:',0
_syntax_err	dw	13,10,7,'  SX Error:',0	;with BEEP
_invalid_cmd	dw	13,10,' ?Invalid command:',0
_zero		dw	13,10,'0',0
_one		dw	13,10,'1',0

;

		org	$F76			;if invaded into $F77,Degug Error!
		nop

;*****************************************
;F77~FFE MUST BE RESERVED FOR DEBUGGING.
;*****************************************
		END                             ;End of program code