// ================================
// Logiscope for MCOC115 (Moscovium)
//		(c) 2021	1YEN Toru
//
//
//		2022/10/29	ver.1.06
//			fixed: loga8ch unit check
//
//		2022/07/31	ver.1.04
//			MIF size 8K byte
//			corresponding to "idrg" command
//
//		2022/06/25	ver.1.02
//			corresponding to "ana" command
//			corresponding to "rd*" and "wr*" command
//			corresponding to "vcdo" command
//			need: MULC16 and DIVC32 co-processor
//
//		2021/05/29	ver.1.00
//
// ================================
romsiz	8*1024
asm		"mcoc_irom_8k.mif"
#asm		"mcoc_irom.mif"
#asm		"mcoc_irom.mem"
#asm		"mcoc_irom.dat2",bit16,list
incl	"mcoc115.incl"
# ================================
# string macros
def		prog_name,"logiscope"
def		prog_vers,"1.06"
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		chr_lf,0x0a						// lf code
equ		chr_cr,0x0d						// cr code
equ		chr_spc,0x20					// space ' ' code
equ		chr_cma,0x2c					// comma ',' code
equ		chr_mns,0x2d					// minus '-' code
equ		max_vcdo,4096					// vcdo: size of vcdo buffer
# variables
equ		va,ramtop
equ		vcdc_cmsk_hex,va				// vcdc: cmsk_hex
equ		va,va+2
equ		vcdc_tmsk_hex,va				// vcdc: tmsk_hex
equ		va,va+2
equ		vcdc_tcnd_hex,va				// vcdc: tcnd_hex
equ		va,va+2
equ		vcdc_capture_ms,va				// vcdc: capture_ms
equ		va,va+2
equ		vcdo_chn_hex,va					// vcdo: chn_hex
equ		va,va+2
equ		vcdo_trig,va					// vcdo: vcdo_trig
equ		va,va+2
equ		vcdo_smpl_us,va					// vcdo: smpl_us
equ		va,va+2
equ		vcdo_time_us,va					// vcdo: time_us
equ		va,va+2
equ		vcdo_chn_num,va					// vcdo: channel count
equ		va,va+2
equ		vcdo_chn_trg,va					// vcdo: trigger channel
equ		va,va+2
equ		vcdo_ptr,va						// vcdo: pointer to vcdo_buf
equ		va,va+2
equ		vcdo_usec,va					// vcdo: capture end time [us]
equ		va,va+2
equ		ana_dpin,va						// ana: pwm pin number
equ		va,va+2
equ		ana_duty,va						// ana: pwm duty 0~255
equ		va,va+2
equ		acc_siz,va						// acc: access size
equ		va,va+2
equ		acc_adr,va						// acc: access address
equ		va,va+4
equ		acc_dat,va						// acc: access data
equ		va,va+4
equ		static_va,va
# array variables
equ		lbuf,va							// receive data buffer
equ		va,va+max_lbuf
equ		vcdo_buf,va						// vcdo: data buffer
equ		va,va+max_vcdo
equ		array_va,va
# ================================

// ================================
// setup
// ================================

// stop if cpu2 for dual core cpu edition
movfc	r0,sr
lsfti	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]
add		r7,r6
movtc	sp,r7

// clear variables
ldwi	r7,ramtop
ldwi	r1,static_va
ldbiu	r0,0
st_clrvar:
stw		[r7],r0
addi	r7,2
cmp		r7,r1
blo		st_clrvar

// 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

// adc setting:
ldwi	r7,adcctl
ldbiu	r0,adc_adce
stw		[r7],r0
ldw		r0,[r7]
andi	r0,adc_adce
beq		adc_init_end					// WARNING: no adc124 found
// polling ardy flag
ldw		r0,[r7]
andi	r0,adc_ardy
beq		pcnt-6
adc_init_end:

// pwm timer setting (about 490Hz, duty 0~255)
ldwi	r7,timprd0
ldwi	r0,255-1
stw		[r7],r0
addi	r7,0x10
stw		[r7],r0
ldwi	r7,timpsc0
ldwi	r0,2048*24/255
$(s)// ********************************
$(s)ldwi	r0,0
$(s)// ********************************
stw		[r7],r0
addi	r7,0x10
stw		[r7],r0
ldwi	r7,timctl0
ldwi	r0,timr_ocma_1|timr_ocmb_1|timr_cnte
stw		[r7],r0
addi	r7,0x10
stw		[r7],r0

// check mulc16 and divc32
ldbiu	r0,1
mov		r1,r0
mulu	r0,r1
cmpi	r0,1
beq		chk_mul_pass
ldwi	r1,lab_str_err_no_mul
jalwr7	print
chk_mul_pass:
ldbiu	r0,1
mov		r1,r0
divu	r0,r1
cmpi	r0,1
beq		chk_div_pass
ldwi	r1,lab_str_err_no_div
jalwr7	print
chk_div_pass:

// 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)// 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)addi	r6,1
$(s)stb		[r7],r0
$(s)addi	r7,1
$(s)mov		r0,r0
$(s)bne		sim_cmnd_loop
$(s)pushw	r6
$(s)jalwr7	sim_cmnd
$(s)// skip nil, check end mark (*)
$(s)popw	r6
$(s)ldb		r0,[r6]
$(s)addi	r6,1
$(s)cmpi	r0,0
$(s)beq		pcnt-8
$(s)subi	r6,1
$(s)cmpi	r0,0x2a		// asterisk(*)
$(s)bne		sim_cmnd_loop2
$(s)bra		sim_cmnd_end
$(s)sim_str_cmnd:
$(s)dats	"idrg\0"
$(s)dats	"*"		// end mark
$(s)dats	"vcdc,1,1,1,1\0"
$(s)dats	"vcdo,9,1,0,60\0"
$(s)dats	"ana,1,192\0"
$(s)dats	"wr2,f000,1e3c5a69\0"
$(s)dats	"rd4,f000\0"
$(s)# vcdc,<cmsk_hex>,<tmsk_hex>,<tcnd_hex>,<capture_ms>
$(s)# vcdo,<chn_hex>,<trig>,<smpl_us>,<time_us>\r\n"
$(s)sim_cmnd_end:
$(s)ldbiu	r0,0
$(s)// simulation finish
$(s)mov		r0,r0
$(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
beq		no_data
jalwr7	get_line
$(s)// ********************************
$(s)sim_cmnd:
$(s)// ********************************

// check "vcdc," command
ldwi	r1,lbuf
ldwi	r2,lab_str_cmd_vcdc
ldbiu	r5,5
jalwr7	strncmp
mov		r0,r0
bne		vcdc_notid
// ================================
// vcdc,<cmsk_hex>,<tmsk_hex>,<tcnd_hex>,<capture_ms>
ldwi	r1,lbuf
// <cmsk_hex>
addi	r1,5
jalwr7	xtoi
ldwi	r7,vcdc_cmsk_hex
stw		[r7],r0
ldb		r0,[r1]
cmpi	r0,chr_cma
bne		err_syntx
// <tmsk_hex>
addi	r1,1
jalwr7	xtoi
ldwi	r7,vcdc_tmsk_hex
stw		[r7],r0
ldb		r0,[r1]
cmpi	r0,chr_cma
bne		err_syntx
// <tcnd_hex>
addi	r1,1
jalwr7	xtoi
ldwi	r7,vcdc_tcnd_hex
stw		[r7],r0
ldb		r0,[r1]
cmpi	r0,chr_cma
bne		err_syntx
// <capture_ms>
addi	r1,1
jalwr7	atoi
ldwi	r7,vcdc_capture_ms
stw		[r7],r0

// capture data
jalwr7	logiana
// check return code
mov		r0,r0
bne		no_data

// response
// check status
ldwi	r7,logactl
ldw		r0,[r7]
andi	r0,loga_davl|loga_tavl
bne		vcdc_ok
// WARNING: canceled
ldwi	r1,lab_str_vcdc_wrn
jalwr7	print
bra		no_data

vcdc_ok:
// send header
ldwi	r1,lab_str_vcdc_head
jalwr7	print
// send captured data
vcdc_loop:
// tick
ldwi	r7,logactck
ldw		r1,[r7]
jalwr7	print_hex
// comma ','
ldbiu	r1,chr_cma
jalwr7	print_chr
// data
ldwi	r7,logacdat
ldw		r1,[r7]
cendw	r1
ldbiu	r3,2
jalwr7	print_hex+2
// CR+LF
ldwi	r1,lab_str_crlf
jalwr7	print
// until logactl.TAVL=0
ldwi	r7,logactl
ldw		r0,[r7]
andi	r0,loga_tavl
bne		vcdc_loop
// send "END"
ldwi	r1,lab_str_vcdc_end
jalwr7	print
bra		no_data
vcdc_notid:

// check "vcdo," command
ldwi	r1,lbuf
ldwi	r2,lab_str_cmd_vcdo
ldbiu	r5,5
jalwr7	strncmp
mov		r0,r0
bne		vcdo_notid
// ================================
// vcdo,<chn_hex>,<trig>,<smpl_us>,<time_us>
ldwi	r1,lbuf
// <chn_hex>
addi	r1,5
jalwr7	xtoi
andi	r0,0x0f
beq		err_syntx
ldwi	r7,vcdo_chn_hex
stw		[r7],r0
ldb		r0,[r1]
cmpi	r0,chr_cma
bne		err_syntx
// <trig>
addi	r1,1
ldb		r0,[r1]
cmpi	r0,chr_mns
ldbiu	r0,0
bne		pcnt+4
addi	r0,1
addi	r1,1
pushw	r0
jalwr7	atoi
popw	r7
mov		r7,r7
beq		pcnt+2
neg		r0
ldwi	r7,vcdo_trig
stw		[r7],r0
ldb		r0,[r1]
cmpi	r0,chr_cma
bne		err_syntx
// <smpl_us>
addi	r1,1
jalwr7	atoi
ldwi	r7,vcdo_smpl_us
stw		[r7],r0
ldb		r0,[r1]
cmpi	r0,chr_cma
bne		err_syntx
// <time_us>
addi	r1,1
jalwr7	atoi
ldwi	r7,vcdo_time_us
stw		[r7],r0

// channel count, trigger channel
ldwi	r7,vcdo_chn_hex
ldw		r0,[r7]
ldwi	r7,lab_vcdo_chn_tab
lsfti	r0,2
add		r7,r0
ldw		r0,[r7]
addi	r7,2
ldw		r1,[r7]
ldwi	r7,vcdo_chn_num
stw		[r7],r0
ldwi	r7,vcdo_chn_trg
stw		[r7],r1
bra		vcdo_jump_tab
// <chn_hex> to <chn_num>,<chn_trg> table
vcdo_chn_tab:							// <chn_hex>
datw	0,0								// 0x0
datw	1,0								// 0x1
datw	1,1								// 0x2
datw	2,0								// 0x3
datw	1,2								// 0x4
datw	2,0								// 0x5
datw	2,1								// 0x6
datw	3,0								// 0x7
datw	1,3								// 0x8
datw	2,0								// 0x9
datw	2,1								// 0xa
datw	3,0								// 0xb
datw	2,2								// 0xc
datw	3,0								// 0xd
datw	3,1								// 0xe
datw	4,0								// 0xf
vcdo_jump_tab:
// check: vcdo_smpl_us>vcdo_chn_num
ldwi	r7,vcdo_chn_num
ldw		r0,[r7]
ldwi	r7,vcdo_smpl_us
ldw		r1,[r7]
cmp		r0,r1
blo		vcdo_ok_smpl_us
// WARNING: vcdo_smpl_us=vcdo_chn_num + 1
addi	r0,1
stw		[r7],r0
vcdo_ok_smpl_us:
// capture data
jalwr7	oscillo
ldwi	r7,vcdo_ptr
stw		[r7],r6
$(s)// ********************************
$(s)ldwi	r7,prinhex
$(s)stb		[r7],r0
$(s)// ********************************

// response
// check status
mov		r0,r0
beq		vcdo_ok
// ERROR:
pushw	r0
ldwi	r1,lab_str_err_vcdo
jalwr7	print
popw	r0
pushw	r1
mov		r1,r0
jalwr7	print_hex
popw	r1
jalwr7	print
bra		no_data

vcdo_ok:
// send header
ldwi	r1,lab_str_vcdo_head
jalwr7	print
pushw	r1
# <chn_num>
ldwi	r7,vcdo_chn_num
ldw		r1,[r7]
jalwr7	print_dec
popw	r1
jalwr7	print
pushw	r1
# <trig>
ldwi	r7,vcdo_trig
ldw		r1,[r7]
jalwr7	print_dec
popw	r1
jalwr7	print
pushw	r1
# <smpl_us>
ldwi	r7,vcdo_smpl_us
ldw		r1,[r7]
jalwr7	print_dec
popw	r1
jalwr7	print

// send captured data
// r6=read pointer
ldwi	r6,vcdo_buf
vcdo_loop:
// r2=<chn_hex>
ldwi	r7,vcdo_chn_hex
ldw		r2,[r7]
# send data each channel
rept	4
// channel $(repti)
lsfti	r2,-1
bcc		vcdo_skip_chn$(repti)
// data
ldw		r1,[r6]
addi	r6,2
pushwm	r6,r2
lsfti	r1,4
ldbiu	r3,3
jalwr7	print_hex+2
popw	r2
pushw	r2
mov		r2,r2
beq		vcdo_skip_cma$(repti)
ldbiu	r1,chr_cma
jalwr7	print_chr
vcdo_skip_cma$(repti):
popwm	r2,r6
vcdo_skip_chn$(repti):
endr
// CR+LF
pushw	r6
ldwi	r1,lab_str_crlf
jalwr7	print
popw	r6

// end of loop
ldwi	r7,vcdo_ptr
ldw		r0,[r7]
cmp		r6,r0
blo		vcdo_loop

// send "END"
ldwi	r1,lab_str_vcdo_end
jalwr7	print
bra		no_data
vcdo_notid:

// check "ana," command
ldwi	r1,lbuf
ldwi	r2,lab_str_cmd_ana
ldbiu	r5,4
jalwr7	strncmp
mov		r0,r0
bne		ana_notid
// ================================
// ana,<dpin>,<level_0_255>
ldwi	r1,lbuf
// <dpin>
addi	r1,4
jalwr7	atoi
ldwi	r7,ana_dpin
stw		[r7],r0
ldb		r0,[r1]
cmpi	r0,chr_cma
bne		err_syntx
// <level_0_255>
addi	r1,1
jalwr7	atoi
cmpi	r0,255
blo		pcnt+2
ldbiu	r0,255
ldwi	r7,ana_duty
stw		[r7],r0
// set duty
ldwi	r7,ana_dpin
ldw		r0,[r7]
ldwi	r7,ana_duty
ldw		r1,[r7]
ana_ch_0:
cmpi	r0,0
bne		ana_ch_1
ldwi	r7,timcma0
stw		[r7],r1
bra		ana_ch_e

ana_ch_1:
cmpi	r0,1
bne		ana_ch_2
ldwi	r7,timcmb0
stw		[r7],r1
bra		ana_ch_e

ana_ch_2:
cmpi	r0,2
bne		ana_ch_3
ldwi	r7,timcma1
stw		[r7],r1
bra		ana_ch_e

ana_ch_3:
cmpi	r0,3
bne		ana_ch_e
ldwi	r7,timcmb1
stw		[r7],r1

ana_ch_e:
// response
ldwi	r1,lab_str_msg_ana
jalwr7	print
pushw	r1
ldwi	r7,ana_dpin
ldw		r1,[r7]
jalwr7	print_dec
popw	r1
jalwr7	print
pushw	r1
ldwi	r7,ana_duty
ldw		r1,[r7]
jalwr7	print_dec
popw	r1
jalwr7	print
bra		no_data
ana_notid:

// check "rd[124]" command
ldwi	r1,lbuf
ldwi	r2,lab_str_cmd_rd
ldbiu	r5,2
jalwr7	strncmp
mov		r0,r0
bne		rd_notid
ldb		r0,[r1]
cmpi	r0,0a1
beq		rd_siz_ok
cmpi	r0,0a2
beq		rd_siz_ok
cmpi	r0,0a4
bne		rd_notid
rd_siz_ok:
addi	r1,1
ldwi	r7,acc_siz
stw		[r7],r0
// check comma(,)
ldb		r0,[r1]
cmpi	r0,chr_cma
bne		rd_notid
addi	r1,1
// ================================
// rd[124],<addr_hex6>
ldwi	r1,lbuf
// <addr_hex6>
addi	r1,4
jalwr7	xtol
ldwi	r7,acc_adr
stw		[r7],r3
addi	r7,2
stw		[r7],r0
// response
ldwi	r7,acc_siz
ldw		r1,[r7]
cmpi	r1,0a1
bne		rd_msg_2
rd_msg_1:
ldwi	r1,lab_str_msg_rd1
bra		rd_msg_e

rd_msg_2:
cmpi	r1,0a2
bne		rd_msg_4
ldwi	r1,lab_str_msg_rd2
bra		rd_msg_e

rd_msg_4:
ldwi	r1,lab_str_msg_rd4
bra		rd_msg_e
rd_msg_e:
jalwr7	print
pushw	r1
// print <addr_hex6>
ldwi	r7,acc_adr
ldw		r1,[r7]
jalwr7	print_hex
ldwi	r7,acc_adr+2
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
pushw	r1
// memory read
ldwi	r7,acc_adr
ldw		r0,[r7]
addi	r7,2
movtc	tr,r0
ldw		r0,[r7]
ldwi	r7,acc_siz
ldw		r1,[r7]
cmpi	r1,0a1
bne		rd_siz_2
rd_siz_1:
ldbx	r1,[r0]
lsfti	r1,8
ldbiu	r3,2
jalwr7	print_hex+2
bra		rd_siz_e

rd_siz_2:
cmpi	r1,0a2
bne		rd_siz_4
ldwx	r1,[r0]
jalwr7	print_hex
bra		rd_siz_e

rd_siz_4:
ldwx	r1,[r0]
addi	r0,2
pushw	r0
jalwr7	print_hex
popw	r0
ldwx	r1,[r0]
jalwr7	print_hex
bra		rd_siz_e

rd_siz_e:
popw	r1
jalwr7	print
bra		no_data
rd_notid:

// check "wr[124]" command
ldwi	r1,lbuf
ldwi	r2,lab_str_cmd_wr
ldbiu	r5,2
jalwr7	strncmp
mov		r0,r0
bne		wr_notid
ldb		r0,[r1]
cmpi	r0,0a1
beq		wr_siz_ok
cmpi	r0,0a2
beq		wr_siz_ok
cmpi	r0,0a4
bne		wr_notid
wr_siz_ok:
addi	r1,1
ldwi	r7,acc_siz
stw		[r7],r0
// check comma(,)
ldb		r0,[r1]
cmpi	r0,chr_cma
bne		wr_notid
addi	r1,1
// ================================
// wr[124],<addr_hex6>
ldwi	r1,lbuf
// <addr_hex6>
addi	r1,4
jalwr7	xtol
ldwi	r7,acc_adr
stw		[r7],r3
addi	r7,2
stw		[r7],r0
// check comma(,)
ldb		r0,[r1]
cmpi	r0,chr_cma
bne		err_syntx
addi	r1,1
// <data_hex*>
jalwr7	xtol
ldwi	r7,acc_dat
stw		[r7],r3
addi	r7,2
stw		[r7],r0
// response
ldwi	r7,acc_siz
ldw		r1,[r7]
cmpi	r1,0a1
bne		wr_msg_2
wr_msg_1:
ldwi	r1,lab_str_msg_wr1
bra		wr_msg_e

wr_msg_2:
cmpi	r1,0a2
bne		wr_msg_4
ldwi	r1,lab_str_msg_wr2
bra		wr_msg_e

wr_msg_4:
ldwi	r1,lab_str_msg_wr4
bra		wr_msg_e
wr_msg_e:
jalwr7	print
pushw	r1
// print <addr_hex6>
ldwi	r7,acc_adr
ldw		r1,[r7]
jalwr7	print_hex
ldwi	r7,acc_adr+2
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
pushw	r1
// memory write
ldwi	r7,acc_adr
ldw		r0,[r7]
addi	r7,2
movtc	tr,r0
ldw		r0,[r7]
ldwi	r7,acc_dat
ldw		r2,[r7]
addi	r7,2
ldw		r3,[r7]
ldwi	r7,acc_siz
ldw		r1,[r7]
cmpi	r1,0a1
bne		wr_siz_2
wr_siz_1:
stbx	[r0],r3
mov		r1,r3
lsfti	r1,8
ldbiu	r3,2
jalwr7	print_hex+2
bra		wr_siz_e

wr_siz_2:
cmpi	r1,0a2
bne		wr_siz_4
stwx	[r0],r3
mov		r1,r3
jalwr7	print_hex
bra		wr_siz_e

wr_siz_4:
stwx	[r0],r2
addi	r0,2
stwx	[r0],r3
pushw	r3
mov		r1,r2
jalwr7	print_hex
popw	r1
jalwr7	print_hex
bra		wr_siz_e

wr_siz_e:
popw	r1
jalwr7	print
bra		no_data
wr_notid:

// check "idrg" command
ldwi	r1,lbuf
ldwi	r2,lab_str_cmd_idrg
jalwr7	strcmp
mov		r0,r0
bne		idrg_notid
// ================================
// idrg
cmd_idrg:
// response
ldwi	r1,lab_str_msg_idrg
// idreg, idrgcode
jalwr7	print
ldcl	sr,sreg_bk_1
ldwi	r1,idrgcode
ldw		r1,[r1]
jalwr7	print_hex
ldcl	sr,sreg_bk_0
// idreg, idrgvers
jalwr7	print
ldcl	sr,sreg_bk_1
ldwi	r1,idrgvers
ldw		r1,[r1]
jalwr7	print_hex
ldcl	sr,sreg_bk_0
// idreg, idrgfcpu
jalwr7	print
ldcl	sr,sreg_bk_1
ldwi	r1,idrgfcpu
ldw		r1,[r1]
jalwr7	print_hex
ldcl	sr,sreg_bk_0
// idreg, idrgedit
jalwr7	print
ldcl	sr,sreg_bk_1
ldwi	r1,idrgedit
ldw		r1,[r1]
jalwr7	print_hex
ldwi	r1,chr_spc
jalwr7	print_chr
ldwi	r1,idrgedit
ldw		r1,[r1]
lsfti	r1,-8
jalwr7	print_chr
ldwi	r1,idrgedit
ldw		r1,[r1]
andi	r1,0xff
jalwr7	print_chr
ldcl	sr,sreg_bk_0
// idreg, idrgromt
jalwr7	print
ldcl	sr,sreg_bk_1
ldwi	r1,idrgromt
ldw		r1,[r1]
jalwr7	print_hex
ldcl	sr,sreg_bk_0
// idreg, idrgroms
jalwr7	print
ldcl	sr,sreg_bk_1
ldwi	r1,idrgroms
ldw		r1,[r1]
jalwr7	print_hex
ldcl	sr,sreg_bk_0
// idreg, idrgramt
jalwr7	print
ldcl	sr,sreg_bk_1
ldwi	r1,idrgramt
ldw		r1,[r1]
jalwr7	print_hex
ldcl	sr,sreg_bk_0
// idreg, idrgrams
jalwr7	print
ldcl	sr,sreg_bk_1
ldwi	r1,idrgrams
ldw		r1,[r1]
jalwr7	print_hex
ldcl	sr,sreg_bk_0
// OK:
jalwr7	print
bra		no_data
idrg_notid:

// check "who" command
ldwi	r1,lbuf
ldwi	r2,lab_str_cmd_who
jalwr7	strcmp
mov		r0,r0
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
mov		r0,r0
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]
mov		r0,r0
beq		no_data
// ================================
// ERROR: unsupported command
ldwi	r1,lab_str_err_unspt
jalwr7	print
ldwi	r1,lbuf
jalwr7	print
ldwi	r1,lab_str_crlf
jalwr7	print
bra		no_data

// ERROR: syntax
err_syntx:
ldwi	r1,lab_str_err_syntx
jalwr7	print
bra		no_data

no_data:
$(s)// ********************************
$(s)rtnw
$(s)// ********************************

// ================================
// end of loop
bra		loop


// ================================
// logic analyzer: capture waveform
// ================================
logiana:
// loga setting
// logamaxc=vcdc_capture_ms
ldwi	r7,vcdc_capture_ms
ldw		r0,r7
ldwi	r7,logamaxc
stw		[r7],r0
// logacmsk=vcdc_cmsk_hex
ldwi	r7,vcdc_cmsk_hex
ldw		r0,[r7]
ldwi	r7,logacmsk
stw		[r7],r0
// logatmsk=vcdc_tmsk_hex
ldwi	r7,vcdc_tmsk_hex
ldw		r0,[r7]
ldwi	r7,logatmsk
stw		[r7],r0
// logatcnd=vcdc_tcnd_hex
ldwi	r7,vcdc_tcnd_hex
ldw		r0,[r7]
ldwi	r7,logatcnd
stw		[r7],r0
// start capture
ldwi	r7,logactl
ldbiu	r0,loga_sta
stw		[r7],r0
// check loga8ch unit
ldwi	r7,vcdc_cmsk_hex
ldw		r0,[r7]
mov		r0,r0
bne		la_ok_start
// ERROR: no loga8ch unit
ldwi	r1,lab_str_err_nologa
jalwr7	print
ldbiu	r0,1
bra		la_return

la_ok_start:
// polling until logactl.LAEF==1 || uartctl.RAVL==1
la_poll:
ldwi	r7,logactl
ldw		r0,[r7]
andi	r0,loga_laef
bne		la_break
ldwi	r7,uartctl
ldw		r0,[r7]
andi	r0,uart_ravl
beq		la_poll
// canceled, abort capture
ldwi	r7,logactl
ldbiu	r0,loga_frst|loga_abt
stw		[r7],r0
la_break:
ldbiu	r0,0
la_return:
rtnw


// ================================
// oscilloscope: capture waveform
//	return:
//		r0=0(no error) / >0(error code)
//		r6=pointer to the bottom of vcdo_buf
// ================================
oscillo:
// check adc124
ldwi	r7,adcctl
ldw		r0,[r7]
andi	r0,adc_ardy|adc_adce|adc_cenb
cmpi	r0,adc_ardy|adc_adce
beq		osc_adcok
// ERROR: no adc124
ldwi	r1,lab_str_err_noadc
jalwr7	print
ldbiu	r0,1
bra		osc_return
osc_adcok:
// wait trigger
// r1=<trig>, r2=adcdat<chn_trg>, r3=CENF mask
ldwi	r7,vcdo_trig
ldw		r1,[r7]
ldwi	r7,vcdo_chn_trg
ldw		r2,[r7]
ldbiu	r3,adc_cenf_0
lsft	r3,r2
ldwi	r7,adcdat0
lsfti	r2,1
add		r2,r7
// start adc
ldwi	r7,vcdo_smpl_us
ldw		r0,[r7]
ldwi	r7,adcperi
stw		[r7],r0
ldwi	r7,vcdo_chn_hex
ldw		r0,[r7]
ori		r0,adc_cenb
ldwi	r7,adcctl
stw		[r7],r0
// polling, 1st data
ldwi	r7,adcint
ldbiu	r0,adc_cenf_a
stw		[r7],r0							// flag clear
ldw		r0,[r7]
and		r0,r3
beq		pcnt-6
ldbiu	r0,adc_cenf_a
stw		[r7],r0							// flag clear
ldw		r4,[r2]
mov		r1,r1
beq		osc_trig_hit
// trigger loop
osc_trg_loop:
ldwi	r7,uartctl
ldw		r0,[r7]
andi	r0,uart_ravl
ldbiu	r0,2
bne		osc_break						// canceled
// polling
ldwi	r7,adcint
ldw		r0,[r7]
and		r0,r3
beq		pcnt-6
ldbiu	r0,adc_cenf_a
stw		[r7],r0							// flag clear
// check trigger; r4=previous data
ldw		r0,[r2]
pushw	r0
sub		r0,r4
mov		r4,r0
eor		r4,r1
popw	r4
bmi		osc_trg_loop
pushw	r4
mov		r0,r0
bpl		pcnt+2
neg		r0
mov		r4,r1
bpl		pcnt+2
neg		r4
cmp		r0,r4
popw	r4
blt		osc_trg_loop
osc_trig_hit:
ldbiu	r0,adc_cenf_a
stw		[r7],r0							// flag clear

// capture data
// set sytmctl[MCOE] bit
ldwi	r7,sytmctl
ldbiu	r0,0
stw		[r7],r0
ldbiu	r0,sytm_mcoe
stw		[r7],r0
// r4=adcdat0, r5=adcint, r6=write pointer to vcdo_buf
ldwi	r4,adcdat0
ldwi	r5,adcint
ldwi	r6,vcdo_buf
######## Do not change! this code is timing critical. ########
// r2=<chn_hex>, r3=<time_us>
ldwi	r7,vcdo_chn_hex
ldw		r2,[r7]
ldwi	r7,vcdo_time_us
ldw		r3,[r7]
osc_loop:
mov		r1,r2
# read data each channel
rept	4
// channel $(repti)
lsfti	r1,-1
bcc		osc_skip_chn$(repti)
// polling channel $(repti)
ldw		r0,[r5]
andi	r0,adc_cenf_$(repti)
beq		pcnt-6
ldbiu	r0,adc_cenf_a
stw		[r5],r0							// flag clear
// read data
ldbil	r4,adcdat$(repti)
ldw		r0,[r4]
$(s)// ********************************
$(s)movtc	tr,r0
$(s)// ********************************
stw		[r6],r0
addi	r6,2
mov		r1,r1
beq		osc_skip_chn3
osc_skip_chn$(repti):
endr

######## Do not change! this code is timing critical. ########
// check break condition
// RAVL
ldwi	r7,uartctl
ldw		r0,[r7]
andi	r0,uart_ravl
ldbiu	r0,2
bne		osc_break						// canceled
// <time_us>
ldwi	r7,sytmmcrl
ldw		r0,[r7]
#ldwi	r7,vcdo_time_us
#ldw		r1,[r7]
#cmp		r0,r1
mov		r3,r3
beq		pcnt+6
cmp		r0,r3
ldbiu	r0,0
bhs		osc_break
// buffer overflow
mov		r0,r6
addi	r0,2*4
ldwi	r1,vcdo_buf+max_vcdo
cmp		r0,r1
ldbiu	r0,0
bhs		osc_break

// end of loop
bra		osc_loop
osc_break:
pushw	r0

// capture finish time
ldwi	r7,sytmmcrl
ldw		r0,[r7]
$(s)// ********************************
$(s)ldwi	r7,prindec
$(s)stw		[r7],r0
$(s)// ********************************
ldwi	r7,vcdo_usec
stw		[r7],r0
// clear sytmctl[MCOE] bit
ldwi	r7,sytmctl
ldbiu	r0,0
stw		[r7],r0
// stop adc124
ldbiu	r0,0
ldwi	r7,adcctl
stw		[r7],r0

// check error code
popw	r0
mov		r0,r0
bne		osc_return

// check: (vcdo_ptr - vcdo_buf)/2/vcdo_chn_num=vcdo_usec/vcdo_smpl_us
// (vcdo_ptr - vcdo_buf)
mov		r0,r6
ldwi	r1,vcdo_buf
sub		r0,r1
// (vcdo_ptr - vcdo_buf)/2/vcdo_chn_num
ldwi	r7,vcdo_chn_num
ldw		r1,[r7]
lsfti	r1,1
divu	r0,r1
$(s)// ********************************
$(s)ldwi	r7,prindec
$(s)stw		[r7],r0
$(s)// ********************************
// (vcdo_ptr - vcdo_buf)/2/vcdo_chn_num*vcdo_smpl_us
ldwi	r7,vcdo_smpl_us
ldw		r1,[r7]
mulu	r0,r1
$(s)// ********************************
$(s)ldwi	r7,prindec
$(s)stw		[r7],r0
$(s)// ********************************
// abs ((vcdo_ptr - vcdo_buf)/2/vcdo_chn_num*vcdo_smpl_us - vcdo_usec)
ldwi	r7,vcdo_usec
ldw		r1,[r7]
sub		r0,r1
bpl		pcnt+2
neg		r0
$(s)// ********************************
$(s)ldwi	r7,prindec
$(s)stw		[r7],r0
$(s)// ********************************
// abs ((vcdo_ptr - vcdo_buf)/2/vcdo_chn_num*vcdo_smpl_us - vcdo_usec)
//		<vcdo_chn_num + 2
ldwi	r7,vcdo_chn_num
ldw		r1,[r7]
addi	r1,2
cmp		r0,r1
bhs		pcnt+4
ldbiu	r0,0
bra		pcnt+2
ori		r0,0x80

// return
osc_return:
rtnw


// ================================
// get line from uart ; disturbed r0,r5~r7
// ================================
get_line:
ldwi	r7,uartrdat
ldwi	r6,uartctl
ldwi	r5,lbuf
gl_loop:
// polling until RAVL=1
ldw		r0,[r6]
andi	r0,uart_ravl
beq		gl_loop
// get byte
ldw		r0,[r7]
stb		[r5],r0
addi	r5,1
// LF code check
cmpi	r0,chr_lf
beq		gl_got
// size check
ldwi	r0,lbuf+max_lbuf-1
cmp		r5,r0
blo		gl_loop
// got line
gl_got:
// string terminate
ldbiu	r0,0
subi	r5,1
stb		[r5],r0
// check CR code
subi	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]
addi	r1,1
mov		r2,r2
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]
mov		r0,r0
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,2
$(s)bne		pcnt+6
$(s)lsfti	r1,-8
$(s)stb		[r7],r1
$(s)bra		pcnt+8
$(s)cmpi	r3,3
$(s)bne		pcnt+2
$(s)lsfti	r1,-4
$(s)stw		[r7],r1
$(s)rtnw
$(s)// ********************************
ldwi	r7,uarttdat
ldwi	r6,uartctl
ldwi	r5,lab_ph_hexdig
ph_loop:
// print nibble
mov		r0,r1
mov		r4,r5
lsfti	r0,-12
andi	r0,0x0f
add		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
lsfti	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 decimal r1 ; disturbed r0~r4,r6,r7
// ================================
print_dec:
#$(s)// ********************************
#$(s)ldwi	r7,prindec
#$(s)stw		[r7],r1
#$(s)rtnw
#$(s)// ********************************
mov		r1,r1
bne		pdc_not_0
// 0
ldbiu	r1,0a0
jalwr7	print_chr
bra		pdc_fin

pdc_not_0:
// for each r0=10000, ~, 10, 1
ldwi	r6,lab_pdc_tab
ldbiu	r3,true							// omit leading zero flag
pdc_loop:
ldw		r0,[r6]
mov		r0,r0
beq		pdc_fin
// r2=r1/r0
ldbiu	r2,0
pdc_div:
sub		r1,r0
blo		pcnt+4
addi	r2,1
bra		pdc_div

// omit leading zero
mov		r3,r3
beq		pcnt+4
mov		r2,r2
beq		pdc_omit
// print 1 digit
addi	r2,0a0
pushwm	r0,r1,r7
mov		r1,r2
jalwr7	print_chr
popwm	r7,r1,r0
ldbiu	r3,false
pdc_omit:
// add back r1; loop
add		r1,r0
addi	r6,2
bra		pdc_loop

pdc_fin:
rtnw

pdc_tab:
datw	10000
datw	1000
datw	100
datw	10
datw	1
datw	0

// ================================
// string compare: r0=strcmp (r1,r2) ; disturbed r1~r4
// ================================
strcmp:
ldb		r3,[r1]
addi	r1,1
ldb		r4,[r2]
addi	r2,1
mov		r0,r3
sub		r0,r4
bne		sc_finish
// check nil code
mov		r3,r3
beq		sc_finish
mov		r4,r4
bne		strcmp
sc_finish:
rtnw

// ================================
// string n compare: r0=strncmp (r1,r2,r5) ; disturbed r1~r5
// ================================
strncmp:
ldb		r3,[r1]
addi	r1,1
ldb		r4,[r2]
addi	r2,1
mov		r0,r3
sub		r0,r4
bne		snc_finish
// check n character
subi	r5,1
beq		snc_finish
// check nil code
mov		r3,r3
beq		snc_finish
mov		r4,r4
bne		strncmp
snc_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
mov		r3,r0
lsfti	r3,3
add		r0,r0
add		r0,r3
add		r0,r2
// loop
addi	r1,1
bra		atoi+2
a2i_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
lsfti	r0,4
add		r0,r2
// loop
addi	r1,1
bra		xtoi+2
x2i_finish:
rtnw

// ================================
// hexadecimal to long: r3:r0=xtol (r1) ; disturbed r1,r2,r4
// ================================
xtol:
ldbiu	r0,0
ldbiu	r3,0
// r2=[r1]-'0'
ldb		r2,[r1]
subi	r2,0a0
blo		x2l_finish						// [r1]<'0'
cmpi	r2,10
blo		x2l_next						// [r1]<='9'
subi	r2,(0aA-0x20)-0a0-10
blo		x2l_finish						// [r1]<'A'
cmpi	r2,16
blo		x2l_next						// [r1]<='F'
subi	r2,0aa-(0aA-0x20)
blo		x2l_finish						// [r1]<'a'
cmpi	r2,16
bhs		x2l_finish						// [r1]>'f'
x2l_next:
// r3:r0=(r3:r0<<4)+r2
mov		r4,r0
lsfti	r4,-12
lsfti	r3,4
add		r3,r4
lsfti	r0,4
add		r0,r2
// loop
addi	r1,1
bra		xtol+4
x2l_finish:
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+ vcdc,<cmsk_hex>,<tmsk_hex>,<tcnd_hex>,<capture_ms>\r\n"
dats	"OK+ vcdo,<chn_hex>,<trig>,<smpl_us>,<time_us>\r\n"
dats	"OK+ ana,<dpin>,<level_0_255>\r\n"
dats	"OK+ rd1,<addr_hex6>\r\n"
dats	"OK+ wr1,<addr_hex6>,<data_hex2>\r\n"
dats	"OK+ rd2,<addr_hex6>\r\n"
dats	"OK+ wr2,<addr_hex6>,<data_hex4>\r\n"
dats	"OK+ rd4,<addr_hex6>\r\n"
dats	"OK+ wr4,<addr_hex6>,<data_hex8>\r\n"
dats	"OK+ idrg\r\n"
dats	"OK+ who\r\n"
dats	"OK: help\r\n\0\0"
str_msg_ana:
dats	"OK: analogWrite(\0, \0)\r\n\0"
str_msg_rd1:
dats	"OK: read byte(\0)=0x\0\r\n\0"
str_msg_rd2:
dats	"OK: read word(\0)=0x\0\r\n\0"
str_msg_rd4:
dats	"OK: read long(\0)=0x\0\r\n\0"
str_msg_wr1:
dats	"OK: write byte(\0)=0x\0\r\n\0"
str_msg_wr2:
dats	"OK: write word(\0)=0x\0\r\n\0"
str_msg_wr4:
dats	"OK: write long(\0)=0x\0\r\n\0"
str_msg_idrg:							// must be even characters
dats	"OK+ id code: \0\r\n"
dats	"OK+ version: \0\r\n"
dats	"OK+ fcpu kHz:\0\r\n"
dats	"OK+ edition: \0\r\n"
dats	"OK+ rom top: \0\r\n"
dats	"OK+ rom size:\0\r\n"
dats	"OK+ ram top: \0\r\n"
dats	"OK+ ram size:\0\r\n"
dats	"OK: idrg\r\n\0"
str_err_unspt:
dats	"ERR: unsupported command: \0"
str_err_syntx:
dats	"ERR: syntax\r\n\0"
str_err_no_mul:
dats	"ERR: no mulc16\r\n\0"
str_err_no_div:
dats	"ERR: no divc32\r\n\0"
str_err_nologa:
dats	"ERR: no loga8ch unit found.\r\n\0"
str_err_noadc:
dats	"ERR: no adc124 unit found.\r\n\0"
str_err_vcdo:
dats	"ERR: vcdo 0x\0\r\n\0"
str_cmd_vcdc:
dats	"vcdc,\0"
str_cmd_vcdo:
dats	"vcdo,\0"
str_cmd_ana:
dats	"ana,\0"
str_cmd_rd:
dats	"rd\0"
str_cmd_wr:
dats	"wr\0"
str_cmd_idrg:
dats	"idrg\0"
str_cmd_who:
dats	"who\0"
str_cmd_help:
dats	"help\0"
str_crlf:
dats	"\r\n\0"
str_vcdc_head:
dats	"VCDC,24000000\r\n\0"
str_vcdc_end:
str_vcdo_end:
dats	"END\r\n\0"
str_vcdc_wrn:
dats	"WRN: canceled\r\n\0"
str_vcdo_head:
dats	"VCDO,\0,\0,\0,3300,4095\r\n\0"

