// ================================
// unicode and S-JIS code conversion module
//		(c) 2022	1YEN Toru
//
//
//		2022/08/06	ver.1.00
//			unicode <-> S-JIS code conversion module
//			8x8 dot Japanese font module
//
// ================================
romsiz	8*1024
asm		"mcoc_irom_8k.mif"
#asm		"mcoc_irom.mem"
#asm		"mcoc_irom.dat2",bit16,list
incl	"mcoc115.incl"
incl	"mcvm_lib_wire_h.incl"
# ================================
# string macros
def		prog_name,"code_conv"
def		prog_vers,"1.00"
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		i2c_slv_adr,0x08				// i2c: slave address
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_cln,0x3a					// colon ':' code
equ		usc_id_code,0x7573				// usc: id code
# variables
equ		va,ramtop
equ		i2c_cmd,va						// i2c: received command
equ		va,va+2
equ		i2c_dat,va						// i2c: received word data
equ		va,va+2
equ		i2c_cnt,va						// i2c: received byte count
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
// ================================

// 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

// unisji unit check
ldwi	r7,unsjctl
ldw		r0,[r7]
andi	r0,unsj_unsj
bne		st_found_unsj
ldwi	r1,lab_str_err_unsj
jalwr7	print
st_found_unsj:

// fontjp unit check
ldwi	r7,fnjpctl
ldbiu	r0,fnjp_ktc
stw		[r7],r0
ldw		r1,[r7]
ldbiu	r2,0
stw		[r7],r2
cmp		r0,r1
beq		st_found_fnjp
ldwi	r1,lab_str_err_fnjp
jalwr7	print
st_found_fnjp:

// stwser setting: SRAR enable, set slave address
ldbiu	r0,stws_srae
ldwi	r7,stwsctl
stw		[r7],r0
ldbiu	r0,i2c_slv_adr
ldwi	r7,stwsadr
stw		[r7],r0

// interrupt setting
ldc		iv,lab_mcvm_wire_isr
seie

// send RDY
ldwi	r1,lab_str_msg_rdy
jalwr7	print

#@$(s)// ********************************
#@$(s)// for simulation
#@$(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

// 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
push	r1
ldwi	r1,lbuf
jalwr7	print
pop		r1
jalwr7	print
bra		no_data

// ERROR: syntax
err_syntx:
ldwi	r1,lab_str_err_syntx
jalwr7	print
bra		no_data

no_data:

// ================================
// end of loop
bra		loop


// ================================
// moscovium wire library
// ================================
// ================================
// start condition event
mcvm_wire_onstar:
// nothing to do
rtnw

// ================================
// receive address byte event
mcvm_wire_onadrb:
// read or write?
andi	r0,stws_adrr
beq		mwona_write

// read access
ldwi	r7,i2c_cmd
ldw		r1,[r7]
cmpi	r1,0
beq		mwona_uni2sjis
cmpi	r1,1
beq		mwona_sjis2uni
cmpi	r1,2
beq		mwona_font0
cmpi	r1,3
beq		mwona_font1
cmpi	r1,4
beq		mwona_font2
cmpi	r1,5
beq		mwona_font3
cmpi	r1,7
beq		mwona_fdobl
cmpi	r1,8
beq		mwona_idcod
// reserved registers
ldbiu	r0,0
bra		mwona_send

// i2c_cmd=uni2sjis: read unsjsjis register, send back to the master
mwona_uni2sjis:
// check BSY=0
ldwi	r7,unsjctl
ldw		r0,[r7]
andi	r0,unsj_bsy
ldbiu	r0,0
bne		mwona_send						// r0=0x0000 (not ready)
// check unsjunic register
ldwi	r7,unsjunic
ldw		r0,[r7]
cmpi	r0,0x80
blo		mwona_send						// r0=(7 bit ASCII)
// read unsjsjis register
ldwi	r7,unsjsjis
ldw		r0,[r7]
mov		r0,r0
bne		mwona_send						// r0=(valid)
subi	r0,1
bra		mwona_send						// r0=0xffff (error)

// i2c_cmd=sjis2uni: read unsjunic register, send back to the master
mwona_sjis2uni:
// check BSY=0
ldwi	r7,unsjctl
ldw		r0,[r7]
andi	r0,unsj_bsy
ldbiu	r0,0
bne		mwona_send						// r0=0x0000 (not ready)
// read unsjunic register
ldwi	r7,unsjunic
ldw		r0,[r7]
mov		r0,r0
bne		mwona_send						// r0=(valid)
subi	r0,1
bra		mwona_send						// r0=0xffff (error)

// i2c_cmd=font0~3: read fnjpdatX register, send back to the master
mwona_font0:
ldwi	r7,fnjpdata
ldw		r0,[r7]
bra		mwona_send

mwona_font1:
ldwi	r7,fnjpdatb
ldw		r0,[r7]
bra		mwona_send

mwona_font2:
ldwi	r7,fnjpdatc
ldw		r0,[r7]
bra		mwona_send

mwona_font3:
ldwi	r7,fnjpdatd
ldw		r0,[r7]
bra		mwona_send

// i2c_cmd=fdobl: read fnjpdbl register, send back to the master
mwona_fdobl:
ldwi	r7,fnjpdbl
ldw		r0,[r7]
bra		mwona_send

// i2c_cmd=idcod: send back id code
mwona_idcod:
ldwi	r0,usc_id_code
bra		mwona_send

mwona_send:
// slave send word (r0)
// polling STAF=1
ldwi	r6,stwsctl
ldw		r1,[r6]
andi	r1,stws_staf
beq		pcnt-6
// send low byte
ldwi	r7,stwsdats
mov		r1,r0
andi	r1,0xff
stw		[r7],r1
// polling STAF=1
ldw		r1,[r6]
andi	r1,stws_staf
beq		pcnt-6
// send high byte
ldwi	r7,stwsdats
lsfti	r0,-8
stw		[r7],r0
bra		mwona_return

// write access
mwona_write:
// clear command
ldwi	r0,-1
ldwi	r7,i2c_cmd
stw		[r7],r0
// clear data count
ldwi	r0,0
ldwi	r7,i2c_cnt
stw		[r7],r0
// clear data
ldwi	r7,i2c_dat
stw		[r7],r0
bra		mwona_return

mwona_return:
rtnw

// ================================
// receive data event
mcvm_wire_onrecv:
// check command byte
ldwi	r7,i2c_cmd
ldw		r1,[r7]
mov		r1,r1
bpl		mwonw_normal

// command byte
andi	r0,0xff							// addr=0x00~0xff
stw		[r7],r0
bra		mwonr_return

mwonw_normal:
// SMBus word write
ldwi	r7,i2c_cnt
ldw		r1,[r7]
addi	r1,1
stw		[r7],r1
cmpi	r1,1
beq		mwonr_bcnt_1
cmpi	r1,2
beq		mwonr_bcnt_2
bra		mwonr_return

mwonr_bcnt_1:
// lower byte
ldwi	r7,i2c_dat+1
stb		[r7],r0
bra		mwonr_return

mwonr_bcnt_2:
// higher byte
ldwi	r7,i2c_dat
stb		[r7],r0
ldw		r0,[r7]
// handling i2c_cmd
ldwi	r7,i2c_cmd
ldw		r1,[r7]
cmpi	r1,0
beq		mwonr_uni2sjis
cmpi	r1,1
beq		mwonr_sjis2uni
cmpi	r1,6
beq		mwonr_fctrl
cmpi	r1,7
beq		mwonr_fdobl
// reserved or read only registers, ignore
bra		mwonr_return

// i2c_cmd=uni2sjis: write unsjunic register, kick conversion
mwonr_uni2sjis:
ldwi	r7,unsjctl
ldw		r1,[r7]
andi	r1,unsj_bsy
bne		mwonr_return					// UNISJI unit busy, ignore
// write unsjunic register
ldwi	r7,unsjunic
stw		[r7],r0
bra		mwonr_return

// i2c_cmd=sjis2uni: write unsjsjis, fnjpcod register, kick conversion
mwonr_sjis2uni:
ldwi	r7,unsjctl
ldw		r1,[r7]
andi	r1,unsj_bsy
bne		mwonr_return					// UNISJI unit busy, ignore
// write unsjsjis register
ldwi	r7,unsjsjis
stw		[r7],r0
// write fnjpcod register
ldwi	r7,fnjpcod
stw		[r7],r0
bra		mwonr_return

// i2c_cmd=fctrl: write fnjpctl register, r0&0x1f
mwonr_fctrl:
// write fnjpctl register
ldwi	r7,fnjpctl
andi	r0,0x1f
stw		[r7],r0
bra		mwonr_return

// i2c_cmd=fdobl: write fnjpdbl register
mwonr_fdobl:
// write fnjpdbl register
ldwi	r7,fnjpdbl
stw		[r7],r0
bra		mwonr_return

mwonr_return:
rtnw

// ================================
// stop condition event
mcvm_wire_onstop:
// nothing to do
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,4
$(s)beq		pcnt+6
$(s)lsfti	r1,-8
$(s)stb		[r7],r1
$(s)bra		pcnt+2
$(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

// ================================
// 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

// ================================
// 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+ who\r\n"
dats	"OK: help\r\n\0\0"
str_msg_msg:
dats	"OK: message write to i/o register\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_unsj:
dats	"ERR: UNISJI unit not found.\r\n\0"
str_err_fnjp:
dats	"ERR: FONTJP unit not found.\r\n\0"
str_cmd_who:
dats	"who\0"
str_cmd_help:
dats	"help\0"

# ================================
incl	"mcvm_lib_wire_s.incl"

