// ================================
// ADCX122 unit test and evaluation
//		(c) 2023	1YEN Toru
//
//
//		2024/01/27	ver.1.02
//			corresponding to accuracy evaluation for ADCX122 unit
//			add: "daco", "eval" command
//
//		2024/01/20	ver.1.00
//
// ================================
def		target,"moscovium"
#def		target,"tennessine"
asm		"mcoc_irom.mem",$(target)
#asm		"mcoc_irom.dat2",bit16,list,$(target)
incl	"mcoc115.incl"
$(target_mn)incl	"mcvm_remv_mcr_word.incl"
$(target_ts)incl	"tnsn_mcr_word.incl"
incl	"mcvm_lib_wire_h.incl"
# ================================
# string macros
def		prog_name,"test_adcx"
def		prog_vers,"1.02"
def		s,"#"							// simulation="" / real fpga="#"
# constants
equ		max_lbuf,64						// size of lbuf
equ		baud,9600						// baud rate
equ		uart_baud,fcpu/baud-1			// uartbaud setting
equ		stws_baud,fcpu/400000-1			// i2c: clock speed
$(s)// ********************************
$(s)equ		stws_baud,fcpu/400000/3-1	// i2c: clock speed for sim
$(s)// ********************************
equ		i2c_mcp4725,0x60				// i2c: MCP4725 slave address
equ		chr_lf,0x0a						// lf code
equ		chr_cr,0x0d						// cr code
equ		chr_cma,0x2c					// comma ',' code
equ		chr_mns,0x2d					// minus '-' code
equ		dac_WAIT,10						// dac: stabilization time [ms]
# variables
equ		va,ramtop
equ		acc_adr,va						// address to access (16 bit)
equ		va,va+2
equ		acc_dat,va						// data for access (16 bit)
equ		va,va+2
equ		dac_wr,va						// dac: dac write data [lsb]/4096
equ		va,va+2
equ		adc_rd0,va						// adc: adc read data #0 [lsb]/4096
equ		va,va+2
equ		adc_rd1,va						// adc: adc read data #1 [lsb]/4096
equ		va,va+2
equ		evl_idx,va						// evl: index counter
equ		va,va+2
equ		evl_anlg0,va					// evl: analog data #0 [lsb]/4096
equ		va,va+2
equ		evl_anlg1,va					// evl: analog data #1 [lsb]/4096
equ		va,va+2
equ		static_va,va
# array variables
equ		lbuf,va							// receive data buffer
equ		va,va+max_lbuf
equ		array_va,va
# ================================


// ================================
// setup
// ================================

// ================================		// general 8 bit Tennessine codes
// uart setting: RXE, TXE, baud rate
ldwi	r7,uartbaud
ldwi	r0,uart_baud
stw		[r7],r0
ldwi	r7,uartctl
ldbiu	r0,uart_rxe|uart_txe
stw		[r7],r0

// check Tennessine core
srbk	sreg_bk_3
movfc	r0,sr
andi	r0,sreg_bk_3
cmpi	r0,sreg_bk_0
srbk	sreg_bk_0
$(target_ts)beq		target_cpu_ok
$(target_mn)bne		target_cpu_ok
// ERROR: not target CPU=$(target), halt
ldc		sp,iome_botm
ldbiu	r1,chr_mns
jalwr7	print_chr
$(s)// ********************************
$(s)ldwi	r0,simfail
$(s)ldwi	r7,simfnsh
$(s)stw		[r7],r0
$(s)// ********************************
pause
// ================================		// target cpu codes from here
target_cpu_ok:


// stop if cpu2 for dual core cpu edition
movfc	r0,sr
lsrwi	r0,sreg_b_id0
andi	r0,sreg_id_2>>sreg_b_id0
beq		pcnt+2
pause

// set sp to the bottom of ram area
ldwi	r7,idrgramt						// idrg: ram top addr.
ldw		r7,[r7]
ldwi	r6,idrgrams						// idrg: ram size
ldw		r6,[r6]
addw	r7,r6
movtc	sp,r7

// clear variables
ldwi	r7,ramtop
ldwi	r1,static_va
ldbiu	r0,0
st_clrvar:
stw		[r7],r0
addwi	r7,2
cmpw	r7,r1
blo		st_clrvar

// check multiply instruction
ldbiu	r0,255
muluw	r0,r0
ldwi	r1,255*255
cmp		r0,r1
beq		has_mult
// ERROR: no multiply instruction
ldwi	r1,lab_str_err_no_mult
jalwr7	print
$(s)// ********************************
$(s)ldwi	r0,simfail
$(s)ldwi	r7,simfnsh
$(s)stw		[r7],r0
$(s)// ********************************
pause
has_mult:

// check timled5 unit
ldwi	r7,tledpsc
ldw		r0,[r7]
cmpi	r0,0
bne		has_timled5
// ERROR: no timled5 unit
ldwi	r1,lab_str_err_no_timled5
jalwr7	print
$(s)// ********************************
$(s)ldwi	r0,simfail
$(s)ldwi	r7,simfnsh
$(s)stw		[r7],r0
$(s)// ********************************
pause
has_timled5:

// timled5 setting
ldwi	r7,tledctl
ldbiu	r0,tled_led2|tled_led1
stw		[r7],r0

// check adcx122 unit
ldwi	r7,adcxctl
ldw		r0,[r7]
andi	r0,adcx_bsy
bne		has_adcx122
// ERROR: no adcx122 unit
ldwi	r1,lab_str_err_no_adcx122
jalwr7	print
$(s)// ********************************
$(s)ldwi	r0,simfail
$(s)ldwi	r7,simfnsh
$(s)stw		[r7],r0
$(s)// ********************************
pause
has_adcx122:

// stwser setting: clock speed
ldwi	r7,stwmbaud
ldwi	r0,stws_baud
stw		[r7],r0

// send RDY
ldwi	r1,lab_str_msg_rdy
jalwr7	print

$(s)// ********************************
$(s)// for simulation
#0$(s)// cancel time out
#0$(s)ldwi	r7,simctrl
#0$(s)ldbiu	r0,simc_noto
#0$(s)stw		[r7],r0
$(s)// setup dummy slave
$(s)ldbiu	r0,i2c_mcp4725
$(s)ldwi	r7,stwsadr
$(s)stw		[r7],r0
$(s)// command test
$(s)ldwi	r6,lab_sim_str_cmnd
$(s)sim_cmnd_loop2:
$(s)ldwi	r7,lbuf
$(s)sim_cmnd_loop:
$(s)ldb		r0,[r6]
$(s)addwi	r6,1
$(s)stb		[r7],r0
$(s)addwi	r7,1
$(s)cmpi	r0,0
$(s)bne		sim_cmnd_loop
$(s)pushw	r6
$(s)jalwr7	sim_cmnd
$(s)// skip nil, check end mark (*)
$(s)popw	r6
$(s)sim_loop_1:
$(s)ldb		r0,[r6]
$(s)addwi	r6,1
$(s)cmpi	r0,0
$(s)beq		sim_loop_1
$(s)subwi	r6,1
$(s)cmpi	r0,0x2a						// asterisk(*)
$(s)bne		sim_cmnd_loop2
$(s)bra		sim_cmnd_end
$(s)sim_str_cmnd:
$(s)dats	"xwr,41,01af\0"				// cfg1: default mode
$(s)dats	"xwr,49,0010\0"				// seq0: channel #4 (ain0) only
$(s)dats	"xwr,41,21af\0"				// cfg1: continuous sequence mode
$(s)dats	"eval\0"
$(s)dats	"*"							// end mark
$(s)dats	"who\0"
$(s)dats	"help\0"
$(s)dats	"daco,2048\0"
$(s)dats	"xwr,40,14\0"				// cfg0: channel #4 (ain0)
$(s)dats	"xwr,41,11af\0"				// cfg1: single conversion
$(s)dats	"xwr,41,41af\0"				// cfg1: simultenious conversion
$(s)dats	"xrd,14\0"					// conversion data channel #4 (ain0)
$(s)dats	"xrd,1c\0"					// conversion data channel #12 (ain1)
$(s)dats	"xrd,40\0"					// cfg0:
$(s)dats	"xrd,41\0"					// cfg1:
$(s)dats	"xrd,42\0"					// cfg2:
$(s)dats	"rd,f174\0"					// adcxain0
$(s)dats	"rd,f176\0"					// adcxain1
$(s)dats	"*"							// end mark
$(s)sim_cmnd_end:
$(s)ldbiu	r0,0
$(s)// simulation finish
$(s)cmpi	r0,0
$(s)beq		pcnt+6
$(s)ldwi	r0,simfail
$(s)bra		pcnt+4
$(s)ldwi	r0,simpass
$(s)ldwi	r7,simfnsh
$(s)stw		[r7],r0
$(s)bra		pcnt-2
$(s)// ********************************


// ================================
// loop
// ================================
loop:

// ================================
// serial monitor handling
// check uartctl.RAVL
ldwi	r7,uartctl
ldw		r0,[r7]
andi	r0,uart_ravl|uart_brdf
beq		no_data
jalwr7	get_line
$(s)// ********************************
$(s)sim_cmnd:
$(s)// ********************************

// check "xrd," command
ldwi	r1,lbuf
ldwi	r2,lab_str_cmd_xrd
ldbiu	r5,4
jalwr7	strncmp
cmpwi	r0,0
bne		xrd_notid
// ================================
// xrd,<adr_hex2>
// <adr_hex2>
ldwi	r1,lbuf+4
jalwr7	xtoi
ldwi	r7,acc_adr
stw		[r7],r0

// DRPE=1
ldwi	r7,adcxctl
ldbiu	r0,adcx_drpe
stw		[r7],r0
// polling until BSY=0
ldw		r0,[r7]
andi	r0,adcx_bsy
bne		pcnt-6

// xread from <adr_hex2>
ldwi	r7,adcxadrr
ldwi	r0,acc_adr
ldw		r0,[r0]
stw		[r7],r0
ldwi	r7,adcxctl
ldw		r0,[r7]
andi	r0,adcx_bsy
bne		pcnt-6
ldwi	r7,adcxdatr
ldw		r0,[r7]
ldwi	r7,acc_dat
stw		[r7],r0

// DRPE=0
ldwi	r7,adcxctl
ldbiu	r0,0
stw		[r7],r0

// response
ldwi	r1,lab_str_msg_xread
jalwr7	print
pushw	r1
// acc_adr
ldwi	r7,acc_adr
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
pushw	r1
// acc_dat
ldwi	r7,acc_dat
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
bra		no_data
xrd_notid:

// check "xwr," command
ldwi	r1,lbuf
ldwi	r2,lab_str_cmd_xwr
ldbiu	r5,4
jalwr7	strncmp
cmpi	r0,0
bne		xwr_notid
// ================================
// xwr,<adr_hex2>,<dat_hex4>
// <adr_hex2>
ldwi	r1,lbuf+4
jalwr7	xtoi
ldwi	r7,acc_adr
stw		[r7],r0
// ,
ldb		r0,[r1]
cmpi	r0,chr_cma
bne		err_syntx
// <dat_hex4>
addwi	r1,1
jalwr7	xtoi
ldwi	r7,acc_dat
stw		[r7],r0

// DRPE=1
ldwi	r7,adcxctl
ldbiu	r0,adcx_drpe
stw		[r7],r0
// polling until BSY=0
ldw		r0,[r7]
andi	r0,adcx_bsy
bne		pcnt-6

// xwrite <dat_hex4> to <adr_hex2>
ldwi	r7,adcxadrw
ldwi	r0,acc_adr
ldw		r0,[r0]
stw		[r7],r0
ldwi	r7,adcxdatw
ldwi	r0,acc_dat
ldw		r0,[r0]
stw		[r7],r0
ldwi	r7,adcxctl
ldw		r0,[r7]
andi	r0,adcx_bsy
bne		pcnt-6

// DRPE=0
ldwi	r7,adcxctl
ldbiu	r0,0
stw		[r7],r0

// response
ldwi	r1,lab_str_msg_xwrite
jalwr7	print
pushw	r1
// acc_adr
ldwi	r7,acc_adr
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
pushw	r1
// acc_dat
ldwi	r7,acc_dat
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
bra		no_data
xwr_notid:

// check "rd," command
ldwi	r1,lbuf
ldwi	r2,lab_str_cmd_rd
ldbiu	r5,3
jalwr7	strncmp
cmpwi	r0,0
bne		rd_notid
// ================================
// rd,<adr_hex4>
// <adr_hex4>
ldwi	r1,lbuf+3
jalwr7	xtoi
ldwi	r7,acc_adr
stw		[r7],r0

// read from <adr_hex4>
ldwi	r7,acc_adr
ldw		r7,[r7]
ldw		r0,[r7]
ldwi	r7,acc_dat
stw		[r7],r0

// response
ldwi	r1,lab_str_msg_read
jalwr7	print
pushw	r1
// acc_adr
ldwi	r7,acc_adr
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
pushw	r1
// acc_dat
ldwi	r7,acc_dat
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
bra		no_data
rd_notid:

// check "wr," command
ldwi	r1,lbuf
ldwi	r2,lab_str_cmd_wr
ldbiu	r5,3
jalwr7	strncmp
cmpi	r0,0
bne		wr_notid
// ================================
// wr,<adr_hex4>,<dat_hex4>
// <adr_hex4>
ldwi	r1,lbuf+3
jalwr7	xtoi
ldwi	r7,acc_adr
stw		[r7],r0
// ,
ldb		r0,[r1]
cmpi	r0,chr_cma
bne		err_syntx
// <dat_hex4>
addwi	r1,1
jalwr7	xtoi
ldwi	r7,acc_dat
stw		[r7],r0

// write <dat_hex4> to <adr_hex4>
ldwi	r7,acc_dat
ldw		r0,[r7]
ldwi	r7,acc_adr
ldw		r7,[r7]
stw		[r7],r0

// response
ldwi	r1,lab_str_msg_write
jalwr7	print
pushw	r1
// acc_adr
ldwi	r7,acc_adr
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
pushw	r1
// acc_dat
ldwi	r7,acc_dat
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
bra		no_data
wr_notid:

// check "daco," command
ldwi	r1,lbuf
ldwi	r2,lab_str_cmd_daco
ldbiu	r5,5
jalwr7	strncmp
cmpi	r0,0
bne		daco_notid
// ================================
// daco,<digt_0_4095>
ldwi	r1,lbuf+5
// <digt_0_4095>
jalwr7	atoi
ldwi	r1,0x0fff
andw	r0,r1

// dac write
ldwi	r7,dac_wr
stw		[r7],r0
movw	r1,r0
jalwr7	dac_write
cmpi	r0,0
bne		daco_err

// delay dac_WAIT
ldwi	r1,dac_WAIT
jalwr7	delay

// adc read (12 bit data)
ldwi	r7,adcxain0
ldw		r0,[r7]
lsrwi	r0,4
ldwi	r7,adc_rd0
stw		[r7],r0
ldwi	r7,adcxain1
ldw		r0,[r7]
lsrwi	r0,4
ldwi	r7,adc_rd1
stw		[r7],r0

// response
bra		daco_ok
daco_err:
// ERROR:
ldwi	r1,lab_str_err_daco
jalwr7	print
bra		no_data

daco_ok:
# "OK: daco="
ldwi	r1,lab_str_msg_daco
jalwr7	print
pushw	r1
# dac_wr
ldwi	r7,dac_wr
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
pushw	r1
# adc_rd
ldwi	r7,adc_rd0
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
pushw	r1
ldwi	r7,adc_rd1
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
bra		no_data
daco_notid:

// check "eval" command
ldwi	r1,lbuf
ldwi	r2,lab_str_cmd_eval
ldbiu	r5,4
jalwr7	strncmp
cmpi	r0,0
bne		eval_notid
// ================================
// eval
jalwr7	eval_adcx

// response
cmpi	r0,0
beq		eval_ok
// ERROR:
ldwi	r1,lab_str_err_eval
jalwr7	print
bra		no_data

eval_ok:
ldwi	r1,lab_str_msg_eval
jalwr7	print
bra		no_data
eval_notid:

// check "who" command
ldwi	r1,lbuf
ldwi	r2,lab_str_cmd_who
jalwr7	strcmp
cmpi	r0,0
bne		who_notid
// ================================
// who
// response
ldwi	r1,lab_str_msg_who
jalwr7	print
bra		no_data
who_notid:

// check "help" command
ldwi	r1,lbuf
ldwi	r2,lab_str_cmd_help
jalwr7	strcmp
cmpi	r0,0
bne		help_notid
// ================================
// help
// response
ldwi	r1,lab_str_msg_help
jalwr7	print_lst
bra		no_data
help_notid:

// ================================
// ignore empty line
ldwi	r1,lbuf
ldb		r0,[r1]
cmpi	r0,0
beq		no_data
// ================================
// ERROR: unsupported command
ldwi	r1,lab_str_err_unspt
jalwr7	print
pushw	r1
ldwi	r1,lbuf
jalwr7	print
popw	r1
jalwr7	print
bra		no_data

// ERROR: syntax
err_syntx:
ldwi	r1,lab_str_err_syntx
jalwr7	print
bra		no_data

// end of command interpretation
no_data:


// ================================
// analog to pwm for on board led
ldwi	r7,tledintc
ldw		r0,[r7]
andi	r0,tled_loff
beq		a2p_endif
// clear loff
stw		[r7],r0
// ain0 to led1
ldwi	r7,adcxain0
ldw		r0,[r7]
// led1=(((~ain0)>>8)**2)>>8
cendw	r0
not		r0
andwi	r0,0xff
muluw	r0,r0
cendw	r0
andwi	r0,0xff
// set led1 pwm duty
ldwi	r7,tleddty1
$(s)// ********************************
$(s)andi	r0,0xf0
$(s)// ********************************
stw		[r7],r0
// ain1 to led2
ldwi	r7,adcxain1
ldw		r0,[r7]
// led2=(((~ain1)>>8)**2)>>8
cendw	r0
not		r0
andwi	r0,0xff
muluw	r0,r0
cendw	r0
andwi	r0,0xff
// set led2 pwm duty
ldwi	r7,tleddty2
$(s)// ********************************
$(s)andi	r0,0xf0
$(s)// ********************************
stw		[r7],r0
a2p_endif:


// ================================
// end of loop
$(s)// ********************************
$(s)ldwi	r1,lab_sim_str_delim
$(s)jalwr7	print
$(s)rtnw
$(s)sim_str_delim:
$(s)dats	"--------\r\n\0"
$(s)// ********************************
bra		loop


// ================================
// evaluate adcx122
//	return: r0 (error, or not)
// ================================
eval_adcx:
// for (idx=0; idx<4096; idx++)
ldbiu	r0,0
ldwi	r7,evl_idx
stw		[r7],r0
// {
evl_loop:
// dac12_write (idx);
movw	r1,r0
jalwr7	dac_write
cmpi	r0,0
bne		evl_return

// delay (dac12_WAIT);
ldwi	r1,dac_WAIT
jalwr7	delay

// anlg=adc_read ();
// adc read (12 bit data)
ldwi	r7,adcxain0
ldw		r0,[r7]
lsrwi	r0,4
ldwi	r7,evl_anlg0
stw		[r7],r0
ldwi	r7,adcxain1
ldw		r0,[r7]
lsrwi	r0,4
ldwi	r7,evl_anlg1
stw		[r7],r0

// sprintf (lbuf,"%d,%d",idx,anlg);
// Serial.println (lbuf);
ldwi	r1,lab_str_msg_eval_data
jalwr7	print
pushw	r1
# idx
ldwi	r7,evl_idx
ldw		r1,[r7]
jalwr7	print_dec4
popw	r1
jalwr7	print
pushw	r1
# anlg
ldwi	r7,evl_anlg0
ldw		r1,[r7]
jalwr7	print_dec4
popw	r1
jalwr7	print
pushw	r1
ldwi	r7,evl_anlg1
ldw		r1,[r7]
jalwr7	print_dec4
popw	r1
jalwr7	print
// }
// end of loop
ldwi	r7,evl_idx
ldw		r0,[r7]
addwi	r0,1
$(s)// ********************************
$(s)ldwi	r7,0x0400-1
$(s)addw	r0,r7
$(s)ldwi	r7,evl_idx
$(s)// ********************************
stw		[r7],r0
ldwi	r1,4096
cmpw	r0,r1
blo		evl_loop

// return
ldbiu	r0,0							// rtncode=ErrNo
evl_return:
rtnw

// ================================
// dac write ; disturbed r1,r2,r7
//	param: r1=12 bit data
//	return: r0 (error, or not)
// ================================
dac_write:
// I2C send: S [ADR,W] [r1>>8] [r1&0xff] P
// make i2c frame
movfc	r7,sp
subwi	r7,2*4
movtc	sp,r7
// S [ADR,W]
ldwi	r0,wire_send|wire_star|(i2c_mcp4725<<1)|wire_adrw
stw		[r7],r0
addwi	r7,2
// [r1>>8]
movw	r0,r1
#lsfti	r0,-8
cendw	r0
andi	r0,0xff
ldwi	r2,wire_send
addw	r0,r2
stw		[r7],r0
addwi	r7,2
// [r1&0xff]
movw	r0,r1
andi	r0,0xff
addw	r0,r2
stw		[r7],r0
addwi	r7,2
// P
ldbiu	r0,wire_stop
stw		[r7],r0

// i2c communication
movfc	r1,sp
jalwr7	mcvm_wire
// destroy i2c frame
movfc	r7,sp
addwi	r7,2*4
movtc	sp,r7
// check status
cmpi	r0,0
beq		dwr_endif
// ERROR:
addwi	r0,0x10							// wire errcod + offset 0x10
dwr_endif:
rtnw


// ================================
// baud rate detection ; disturbed none
//	return: r0=new baud rate detected
// ================================
det_baud:
pushwm	r1,r2,r3,r4,r5,r6,r7
ldwi	r7,uartctl
ldw		r0,[r7]
stw		[r7],r0							// clear brdf
andi	r0,uart_brdf
beq		dbr_not_brdf
// detected
ldwi	r7,uartbres
ldw		r0,[r7]
ldwi	r7,uartbaud
ldw		r3,[r7]
// margin
movw	r2,r3
lsrwi	r2,6
// r3=abs (r3 - r0)
$(s)// ********************************
$(s)lslwi	r3,1
$(s)// ********************************
subw	r3,r0
bpl		dbr_plus
negw	r3
dbr_plus:
cmpw	r3,r2
blo		dbr_not_brdf
// update uartbaud
stw		[r7],r0
// message
ldwi	r1,lab_dbr_str_msg_det
jalwr7	print
pushw	r1
ldwi	r7,uartbaud
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
ldwi	r7,uartbres
ldw		r0,[r7]
bra		dbr_not_brdf+2
// return
dbr_not_brdf:
ldbiu	r0,0
popwm	r7,r6,r5,r4,r3,r2,r1
rtnw

dbr_str_msg_det:
dats	"OK: new baud rate detected: uartbaud=0x\0\r\n\0"

// ================================
// get line from uart ; disturbed r0,r5~r7
// ================================
get_line:
ldwi	r7,uartrdat
ldwi	r6,uartctl
ldwi	r5,lbuf
gl_loop:
// check baud rate detection
jalwr0	det_baud
// polling until RAVL=1
ldw		r0,[r6]
andi	r0,uart_ravl
beq		gl_loop
// get byte
ldw		r0,[r7]
stb		[r5],r0
addwi	r5,1
// LF code check
cmpi	r0,chr_lf
beq		gl_got
// size check
ldwi	r0,lbuf+max_lbuf-1
cmpw	r5,r0
blo		gl_loop
// got line
gl_got:
// string terminate
ldbiu	r0,0
subwi	r5,1
stb		[r5],r0
// check CR code
subwi	r5,1
ldb		r0,[r5]
cmpi	r0,chr_cr
bne		gl_notcr
ldbiu	r0,0
stb		[r5],r0
gl_notcr:
rtnw

// ================================
// print r1 ; disturbed r0~r2,r6,r7
// ================================
print:
ldwi	r7,uarttdat
ldwi	r6,uartctl
pr_loop:
// get 1 byte
ldb		r2,[r1]
addwi	r1,1
cmpi	r2,0
beq		pr_finish
$(s)// ********************************
$(s)ldwi	r7,princhr
$(s)stw		[r7],r2
$(s)bra		pr_loop
$(s)// ********************************
// polling uartctl.TFUL=0
pr_poll:
ldw		r0,[r6]
andi	r0,uart_tful
bne		pr_poll
// send data
stw		[r7],r2
bra		pr_loop
pr_finish:
rtnw

// ================================
// print_lst r1 ; disturbed r0~r2,r6,r7
// ================================
print_lst:
jalwr7	print
ldb		r0,[r1]
cmpi	r0,0
bne		print_lst
rtnw

// ================================
// print_hex r1 ; disturbed r0~r7
//		print r1 as 4 digits hexadecimal number
// ================================
print_hex:
ldbiu	r3,4
$(s)// ********************************
$(s)ldwi	r7,princtl
$(s)ldbiu	r0,prin_nld
$(s)stw		[r7],r0
$(s)ldwi	r7,prinhex
$(s)cmpi	r3,4
$(s)beq		ph_else
$(s)cendw	r1
$(s)stb		[r7],r1
$(s)bra		ph_endif
$(s)ph_else:
$(s)stw		[r7],r1
$(s)ph_endif:
$(s)rtnw
$(s)// ********************************
ldwi	r7,uarttdat
ldwi	r6,uartctl
ldwi	r5,lab_ph_hexdig
ph_loop:
// print nibble
movw	r0,r1
movw	r4,r5
cendw	r0
lsrwi	r0,4
andi	r0,0x0f
addw	r4,r0
ldb		r2,[r4]
// polling uartctl.TFUL=0
ph_poll:
ldw		r0,[r6]
andi	r0,uart_tful
bne		ph_poll
// send data
stw		[r7],r2
// loop
lslwi	r1,4
subi	r3,1
bne		ph_loop
rtnw

ph_hexdig:
dats	"0123456789abcdef"

// ================================
// print_chr r1 ; disturbed r0,r7
// ================================
print_chr:
$(s)// ********************************
$(s)ldwi	r7,princhr
$(s)stw		[r7],r1
$(s)rtnw
$(s)// ********************************
// polling uartctl.TFUL=0
ldwi	r7,uartctl
pc_poll:
ldw		r0,[r7]
andi	r0,uart_tful
bne		pc_poll
// send data
ldwi	r7,uarttdat
stw		[r7],r1
rtnw

// ================================
// print decimal4 r1 ; disturbed r0~r4,r6,r7
// ================================
print_dec4:
cmpwi	r1,0
bne		pdc_not_0
// 0
ldbiu	r1,0a0
jalwr7	print_chr
bra		pdc_fin

pdc_not_0:
// for each r0=1000, 100, 10, 1
ldwi	r6,lab_pdc_tab
ldbiu	r3,true							// omit leading zero flag
pdc_loop:
ldw		r0,[r6]
cmpwi	r0,0
beq		pdc_fin
// r2=r1/r0
ldbiu	r2,0
pdc_div:
subw	r1,r0
blo		pdc_div_endif
addwi	r2,1
bra		pdc_div
pdc_div_endif:

// omit leading zero
cmpi	r3,0
beq		pdc_not_omit
cmpwi	r2,0
beq		pdc_omit
pdc_not_omit:
// print 1 digit
addi	r2,0a0
pushwm	r0,r1,r7
movw	r1,r2
jalwr7	print_chr
popwm	r7,r1,r0
ldbiu	r3,false
pdc_omit:
// add back r1; loop
addw	r1,r0
addwi	r6,2
bra		pdc_loop

pdc_fin:
rtnw

pdc_tab:
datw	1000,100,10,1,0

// ================================
// string compare: r0=strcmp (r1,r2) ; disturbed r1~r4
// ================================
strcmp:
ldb		r3,[r1]
addwi	r1,1
ldb		r4,[r2]
addwi	r2,1
mov		r0,r3
sub		r0,r4
bne		sc_finish
// check nil code
cmpi	r3,0
beq		sc_finish
cmpi	r4,0
bne		strcmp
sc_finish:
rtnw

// ================================
// string n compare: r0=strncmp (r1,r2,r5) ; disturbed r1~r5
// ================================
strncmp:
ldb		r3,[r1]
addwi	r1,1
ldb		r4,[r2]
addwi	r2,1
mov		r0,r3
sub		r0,r4
bne		snc_finish
// check n character
subwi	r5,1
beq		snc_finish
// check nil code
cmpi	r3,0
beq		snc_finish
cmpi	r4,0
bne		strncmp
snc_finish:
rtnw

// ================================
// hexadecimal to integer: r0=xtoi (r1) ; disturbed r1,r2
// ================================
xtoi:
ldbiu	r0,0
// r2=[r1]-'0'
ldb		r2,[r1]
subi	r2,0a0
blo		x2i_finish						// [r1]<'0'
cmpi	r2,10
blo		x2i_next						// [r1]<='9'
subi	r2,(0aA-0x20)-0a0-10
blo		x2i_finish						// [r1]<'A'
cmpi	r2,16
blo		x2i_next						// [r1]<='F'
subi	r2,0aa-(0aA-0x20)
blo		x2i_finish						// [r1]<'a'
cmpi	r2,16
bhs		x2i_finish						// [r1]>'f'
x2i_next:
// r0=16*r0+r2
lslwi	r0,4
addw	r0,r2
// end of loop
addwi	r1,1
bra		xtoi+2
x2i_finish:
rtnw

// ================================
// ascii to integer: r0=atoi (r1)>=0 ; disturbed r1~r3
// ================================
atoi:
ldbiu	r0,0
// r2=[r1]-'0'
ldb		r2,[r1]
subi	r2,0a0
blo		a2i_finish
cmpi	r2,10
bhs		a2i_finish
// r0=10*r0+r2
movw	r3,r0
lslwi	r3,3
lslwi	r0,1
addw	r0,r3
addw	r0,r2
// end of loop
addwi	r1,1
bra		atoi+2
a2i_finish:
rtnw

// ================================
// delay r1 [ms] ; disturbed r0,r7,sytmctl[MLOE]
// ================================
delay:
$(s)// ********************************
$(s)ldbiu	r1,3
$(s)// ********************************
// sytmmil: set offset
ldwi	r7,sytmctl
ldw		r0,[r7]
andi	r0,~sytm_mloe
stw		[r7],r0
ori		r0,sytm_mloe
stw		[r7],r0
// wait r1 [ms]
ldwi	r7,sytmmill
dly_loop:
ldw		r0,[r7]
cmpw	r0,r1
blo		dly_loop
rtnw


// ================================
// c string data
// ================================
str_msg_who:
dats	"OK: $(prog_name) ver.$(prog_vers)\r\n\0"
str_msg_rdy:
dats	"RDY\r\n\0"
str_msg_help:
dats	"OK+ xrd,<adr_hex2>\r\n"
dats	"OK+ xwr,<adr_hex2>,<dat_hex4>\r\n"
dats	"OK+ rd,<adr_hex4>\r\n"
dats	"OK+ wr,<adr_hex4>,<dat_hex4>\r\n"
dats	"OK+ daco,<digt_0_4095>\r\n"
dats	"OK+ eval\r\n"
dats	"OK+ U\r\n"
dats	"OK+ who\r\n"
dats	"OK: help\r\n\0\0"
str_msg_xread:
dats	"OK: xread[0x\0]=0x\0\r\n\0"
str_msg_xwrite:
dats	"OK: xwrite[0x\0]=0x\0\r\n\0"
str_msg_read:
dats	"OK: read[0x\0]=0x\0\r\n\0"
str_msg_write:
dats	"OK: write[0x\0]=0x\0\r\n\0"
str_msg_daco:
dats	"OK: daco=0x\0 adc=0x\0, 0x\0 [lsb]\r\n\0"
str_msg_eval:
dats	"OK: eval finished\r\n\0"
str_msg_eval_data:
dats	"\0,\0,\0\r\n\0"
str_err_unspt:
dats	"ERR: unsupported command: \0\r\n\0"
str_err_syntx:
dats	"ERR: syntax\r\n\0"
str_err_no_mult:
dats	"ERR: no MUL* instruction, halted\r\n\0"
str_err_no_timled5:
dats	"ERR: no TIMLED5 unit, halted\r\n\0"
str_err_no_adcx122:
dats	"ERR: no ADCX122 unit, halted\r\n\0"
str_err_daco:
dats	"ERR: could not communicate mcp4725\r\n\0"
str_err_eval:
dats	"ERR: eval returns by error\r\n\0"
str_cmd_xrd:
dats	"xrd,\0"
str_cmd_xwr:
dats	"xwr,\0"
str_cmd_rd:
dats	"rd,\0"
str_cmd_wr:
dats	"wr,\0"
str_cmd_daco:
dats	"daco,\0"
str_cmd_eval:
dats	"eval\0"
str_cmd_who:
dats	"who\0"
str_cmd_help:
dats	"help\0"

# ================================
incl	"mcvm_lib_wire_m.incl"

