// ================================
// SPI-TFT (ST7735R) KANJI print utility
//		(c) 2021	1YEN Toru
//
//
//		2021/10/23	ver.1.00
//
// ================================
asm		"mcoc_irom.mif"
#asm		"mcoc_irom.mem"
#asm		"mcoc_irom.dat2",bit16,list
incl	"mcoc115.incl"
# ================================
# string macros
def		prog_name,"tft_kprint"
def		prog_vers,"1.00"
def		s,"#"							// simulation="" / real fpga="#"
# constants
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_pct,0x25					// percent '%' code
equ		chr_cma,0x2c					// comma ',' code
equ		chr_mns,0x2d					// minus '-' code
equ		chr_dot,0x2e					// period '.' code
equ		chr_cln,0x3a					// colon ':' code
equ		spi_ss,0x80						// spi: ss pin
equ		spi_sck,0x40					// spi: sck pin
equ		spi_mosi,0x20					// spi: mosi pin
equ		spi_miso,spi_mosi				// spi: miso pin (bi-direction)
equ		spi_max,8						// spi: buffer size
equ		tft_dcx,0x10					// tft: d/cx pin
equ		tft_res,0x08					// tft: reset pin
equ		tft_siz_h,128					// tft: horizontal size [dot]
equ		tft_siz_v,160					// tft: vertical size [dot]
equ		tft_wid,tft_siz_h/8				// tft: horizontal size [character]
equ		tft_hei,tft_siz_v/8				// tft: vertical size [character]
equ		tft_pix_max,64					// tft: tft_putpix() buffer size
equ		tft_opt_store,0					// tft: tft_putpix() option command
equ		tft_opt_init,1
equ		tft_opt_flush,2
# variables
equ		va,ramtop
equ		tft_prn_lx,va					// tft: cursor x
equ		va,va+2
equ		tft_prn_ly,va					// tft: cursor y
equ		va,va+2
equ		tft_prn_fg,va					// tft: foreground color
equ		va,va+2
equ		tft_prn_bg,va					// tft: background color
equ		va,va+2
equ		tft_2x2,va						// tft: draw 2x2 font
equ		va,va+2
equ		tft_get_ptr,va					// tft: 0=from UART8N1 / 0!=[ptr]
equ		va,va+2
equ		pix_ptr,va						// tft: pointer to pix_buf[]
equ		va,va+2
equ		is_nl,va						// tft: tft_upd_curs local
equ		va,va+2
equ		static_va,va
# array variables
equ		spi_buf,va						// spi: transfer buffer
equ		va,va+spi_max
equ		pix_buf,va						// tft: tft_putpix() buffer
equ		va,va+2*tft_pix_max
equ		array_va,va
# ================================
# user macros
macro	spi_ss_0
// ss=0
ldbiu	r0,spi_ss
stw		[r6],r0
endm

macro	spi_ss_1
// ss=1
ldbiu	r0,spi_ss
stw		[r7],r0
endm

macro	spi_sck_0
// sck=0
ldbiu	r0,spi_sck
stw		[r6],r0
endm

macro	spi_sck_1
// sck=1
ldbiu	r0,spi_sck
stw		[r7],r0
endm

macro	spi_mosi_o
// mosi
ldbiu	r0,spi_mosi
lsfti	r1,1
bcs		pcnt+4
stw		[r6],r0							// clear
bra		pcnt+2
stw		[r7],r0							// set
endm

macro	tft_dcx_0
// d/cx=0
ldbiu	r0,tft_dcx
stw		[r6],r0
endm

macro	tft_dcx_1
// d/cx=1
ldbiu	r0,tft_dcx
stw		[r7],r0
endm

macro	tft_res_0
// reset=0
ldwi	r6,porclr
ldbiu	r0,tft_res
stw		[r6],r0
endm

macro	tft_res_1
// reset=1
ldwi	r7,porset
ldbiu	r0,tft_res
stw		[r7],r0
endm
# ================================

// ================================
// 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

// initial value
ldwi	r7,tft_prn_fg
ldwi	r0,0xffff						// white
stw		[r7],r0

// port setting
ldbiu	r0,spi_ss
ldwi	r7,porset
stw		[r7],r0
ldwi	r7,pordir
ldw		r0,[r7]
andi	r0,~(spi_ss|spi_sck|spi_mosi|tft_dcx|tft_res)
stw		[r7],r0

// tim0: 1kHz inverted pwm output
ldwi	r7,timprd0
ldbiu	r0,255-1
stw		[r7],r0
ldwi	r7,timpsc0
ldwi	r0,fcpu/1000/255-1
stw		[r7],r0
ldwi	r7,timcma0
ldbiu	r0,0xff
stw		[r7],r0
ldwi	r7,timctl0
ldbiu	r0,timr_ocma_2|timr_cnte
stw		[r7],r0

// 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

// init spi-tft
jalwr7	tft_init
tst_skip:

// check mulc16
ldbiu	r0,1
mov		r1,r0
mulu	r0,r1
cmpi	r0,1
beq		chk_mul_pass
ldwi	r1,lab_str_err_no_mul
jalwr7	tft_kprint
// halt
pause
bra		pcnt-4
chk_mul_pass:

// credit
ldwi	r1,lab_str_msg_credit
jalwr7	tft_kprint

$(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:
jalwr7	get_chr
// check control code?
cmpi	r0,0x20
bhs		mlp_not_ctrl
// control code
ldwi	r7,lab_mlp_jmp_tab
add		r7,r0
add		r7,r0
ldw		r7,[r7]
jalw	r7
bra		loop

mlp_jmp_tab:
datw	lab_ctrl_00
datw	lab_ctrl_01
datw	lab_ctrl_02
datw	lab_ctrl_03
datw	lab_ctrl_04
datw	lab_ctrl_05
datw	lab_ctrl_06
datw	lab_ctrl_07
datw	lab_ctrl_08
datw	lab_ctrl_09
datw	lab_ctrl_0a
datw	lab_ctrl_0b
datw	lab_ctrl_0c
datw	lab_ctrl_0d
datw	lab_ctrl_0e
datw	lab_ctrl_0f
datw	lab_ctrl_10
datw	lab_ctrl_11
datw	lab_ctrl_12
datw	lab_ctrl_13
datw	lab_ctrl_14
datw	lab_ctrl_15
datw	lab_ctrl_16
datw	lab_ctrl_17
datw	lab_ctrl_18
datw	lab_ctrl_19
datw	lab_ctrl_1a
datw	lab_ctrl_1b
datw	lab_ctrl_1c
datw	lab_ctrl_1d
datw	lab_ctrl_1e
datw	lab_ctrl_1f

mlp_not_ctrl:
// check S-JIS code?
ldwi	r7,fnjpcod
lsfti	r0,8
pushw	r0
stw		[r7],r0
ldwi	r7,fnjpctl
ldw		r0,[r7]
andi	r0,fnjp_sjs1
beq		mlp_not_sjis
// get next byte
jalwr7	get_chr
popw	r1
add		r0,r1
ldwi	r7,fnjpcod
stw		[r7],r0
mlp_not_sjis:
// print 1 character
jalwr7	tft_kprint_chr

// ================================
// end of loop
bra		loop


// ================================
// control code
// ================================
// CR(\x0d, \r) code; return
ctrl_0d:
ldwi	r7,tft_prn_lx
ldbiu	r0,0
stw		[r7],r0
rtnw

// LF(\x0a, \n) code; line feed
ctrl_0a:
ldwi	r7,tft_prn_ly
ldw		r0,[r7]
addi	r0,1
stw		[r7],r0
ldbiu	r1,true
jalwr7	tft_upd_curs
rtnw

// VT(\x0b, \v) code; cursor up
ctrl_0b:
ldwi	r7,tft_prn_ly
ldw		r0,[r7]
subi	r0,1
stw		[r7],r0
ldbiu	r1,false
jalwr7	tft_upd_curs
rtnw

// BS(\x08, \b) code; cursor left
ctrl_08:
ldwi	r7,tft_prn_lx
ldw		r0,[r7]
subi	r0,1
stw		[r7],r0
ldbiu	r1,false
jalwr7	tft_upd_curs
rtnw

// HT(\x09, \t) code; cursor right
ctrl_09:
ldwi	r7,tft_prn_lx
ldw		r0,[r7]
addi	r0,1
stw		[r7],r0
ldbiu	r1,false
jalwr7	tft_upd_curs
rtnw

// FF(\x0c, \f) code; clear screen
ctrl_0c:
// clear screen (box fill)
ldbiu	r0,0
pushw	r0
pushw	r0
ldwi	r0,tft_siz_h-1
pushw	r0
ldwi	r0,tft_siz_v-1
pushw	r0
ldwi	r7,tft_prn_bg
ldw		r0,[r7]
pushw	r0
jalwr7	tft_boxf
movfc	r0,sp
addi	r0,2*5
movtc	sp,r0
// reset variables
ldbiu	r0,0
ldwi	r7,tft_prn_lx
stw		[r7],r0
ldwi	r7,tft_prn_ly
stw		[r7],r0
rtnw

// SO(\x0e) code; 1x1 font
ctrl_0e:
ldwi	r7,tft_2x2
ldbiu	r0,0
stw		[r7],r0
rtnw

// SI(\x0f) code; 2x2 font
ctrl_0f:
ldwi	r7,tft_2x2
ldbiu	r0,1
stw		[r7],r0
rtnw

// \x10 code; set cursor x
ctrl_10:
jalwr7	tft_get_chr
ldwi	r1,tft_wid
cmp		r0,r1
blo		pcnt+2
ldbiu	r0,0
ldwi	r7,tft_prn_lx
stw		[r7],r0
rtnw

// \x11 code; set cursor y
ctrl_11:
jalwr7	tft_get_chr
ldwi	r1,tft_hei
cmp		r0,r1
blo		pcnt+2
ldbiu	r0,0
ldwi	r7,tft_prn_ly
stw		[r7],r0
rtnw

// \x12 code; set foreground color
ctrl_12:
jalwr7	tft_get_chr
mov		r1,r0
jalwr7	tft_get_chr
lsfti	r1,8
add		r0,r1
ldwi	r7,tft_prn_fg
stw		[r7],r0
rtnw

// \x13 code; set background color
ctrl_13:
jalwr7	tft_get_chr
mov		r1,r0
jalwr7	tft_get_chr
lsfti	r1,8
add		r0,r1
ldwi	r7,tft_prn_bg
stw		[r7],r0
rtnw

// \x14 code; set affine transformation
ctrl_14:
jalwr7	tft_get_chr
ldwi	r7,fnjpctl
andi	r0,fnjp_inv|fnjp_flp_h|fnjp_flp_v|fnjp_rot_3
stw		[r7],r0
rtnw

// \x15 code; wait *10[ms]
ctrl_15:
jalwr7	tft_get_chr
// r1=r0*10
ldbiu	r1,10
mulu	r1,r0
jalwr7	delay
rtnw

// \x16 code; set pwm duty (backlight led intensity)
ctrl_16:
jalwr7	tft_get_chr
ldwi	r7,timcma0
stw		[r7],r0
rtnw

// not defined, ignore
ctrl_00:
ctrl_01:
ctrl_02:
ctrl_03:
ctrl_04:
ctrl_05:
ctrl_06:
ctrl_07:
ctrl_17:
ctrl_18:
ctrl_19:
ctrl_1a:
ctrl_1b:
ctrl_1c:
ctrl_1d:
ctrl_1e:
ctrl_1f:
rtnw

// ================================
// update cursor position ; disturbed r0,r1,r7
//	parameter:	r1=is_nl
// ================================
tft_upd_curs:
ldwi	r7,is_nl
stw		[r7],r1
//	if (tft_prn_lx>tft_SIZH/8 - 1)
ldwi	r7,tft_prn_lx
ldw		r0,[r7]
ldwi	r1,tft_wid
cmp		r0,r1
blo		tuc_wid_else
//	{
//		tft_prn_lx=0;
ldwi	r7,tft_prn_lx
ldbiu	r0,0
stw		[r7],r0
//		tft_prn_ly += 2;
ldwi	r7,tft_prn_ly
ldw		r0,[r7]
addi	r0,1
ldwi	r1,tft_2x2
ldw		r1,[r1]
mov		r1,r1
beq		pcnt+2
addi	r0,1
stw		[r7],r0
//		is_nl=true;
ldwi	r7,is_nl
ldbiu	r0,true
stw		[r7],r0
bra		tuc_wid_endi
//	}
tuc_wid_else:
//	else if (tft_prn_lx<0)
mov		r0,r0
bpl		tuc_wid_endi
//	{
//		tft_prn_lx=tft_SIZH/8 - 1;
subi	r1,1
ldwi	r7,tft_prn_lx
stw		[r7],r1
//		tft_prn_ly -= 2;
ldwi	r7,tft_prn_ly
ldw		r0,[r7]
subi	r0,1
stw		[r7],r0
//	}
tuc_wid_endi:

//	if (tft_prn_ly>tft_SIZV/8 - 2)
ldwi	r7,tft_prn_ly
ldw		r0,[r7]
ldwi	r1,tft_hei
cmp		r0,r1
blo		tuc_hei_else
//	{
//		tft_prn_ly=0;
ldwi	r7,tft_prn_ly
ldbiu	r0,0
stw		[r7],r0
//		tft_scrl_enb=true;
# SPI-TFT does not have hardware scroll function
//		is_nl=true;
ldwi	r7,is_nl
ldbiu	r0,1
stw		[r7],r0
bra		tuc_hei_endi
//	}
tuc_hei_else:
//	else if (tft_prn_ly<0)
mov		r0,r0
bpl		tuc_hei_endi
//	{
//		tft_prn_ly=tft_SIZV/8 - 2;
subi	r1,1
ldwi	r7,tft_prn_ly
stw		[r7],r1
//	}
tuc_hei_endi:
rtnw

// ================================
// software spi transfer ; disturbed r0~r3,r6,r7
//	mode 0, MSB first, 8 bit, r1 bytes
//	parameter:	r1=size of data, r2=pointer to tbuf[]
// ================================
spi_transfer:
ldwi	r7,porset
ldwi	r6,porclr
spi_ss_0
tft_dcx_0
mov		r3,r1
spt_loop:
ldb		r1,[r2]
addi	r2,1
lsfti	r1,8
// spi 8 bits transfer
rept	8
// spi bit $(reptr)
spi_mosi_o
spi_sck_1
spi_sck_0
endr
tft_dcx_1
// end of loop
subi	r3,1
bne		spt_loop
spi_ss_1
rtnw

// ================================
// tft ram write ; disturbed r0~r2,r5~r7
// ================================
tft_ram_write:
ldwi	r5,pix_ptr
ldw		r2,[r5]
mov		r2,r2
beq		trw_return
ldwi	r7,porset
ldwi	r6,porclr
// send pixel data
ldwi	r5,pix_buf
trw_loop:
ldw		r1,[r5]
addi	r5,2
// spi 16 bits transfer
rept	16
// spi bit $(reptr)
spi_mosi_o
spi_sck_1
spi_sck_0
endr
// end of loop
subi	r2,1
bne		trw_loop
trw_return:
rtnw

// ================================
// tft put pixel ; disturbed r0~r2,r5~r7
//	parameter:	r1=pixel, r0=option
// ================================
tft_putpix:
cmpi	r0,tft_opt_init
bne		tpx_not_init
// initialize
ldwi	r7,pix_ptr
ldbiu	r0,0
stw		[r7],r0
// send RAMWR command
ldwi	r7,porset
ldwi	r6,porclr
spi_ss_0
tft_dcx_0
ldbiu	r1,0x2c
lsfti	r1,8
// spi 8 bits transfer
rept	8
// spi bit $(reptr)
spi_mosi_o
spi_sck_1
spi_sck_0
endr
tft_dcx_1
rtnw

tpx_not_init:
cmpi	r0,tft_opt_flush
bne		tpx_not_flush
// flush pixel data
jalwr7	tft_ram_write
ldwi	r7,pix_ptr
ldbiu	r0,0
stw		[r7],r0
// exit RAMWR
ldwi	r7,porset
spi_ss_1
rtnw

tpx_not_flush:
// store pixel
ldwi	r7,pix_buf
ldwi	r0,pix_ptr
ldw		r0,[r0]
add		r7,r0
add		r7,r0
stw		[r7],r1
addi	r0,1
ldwi	r7,pix_ptr
stw		[r7],r0
cmpi	r0,tft_pix_max
blo		tpx_not_full
// flush pixel data
jalwr7	tft_ram_write
ldwi	r7,pix_ptr
ldbiu	r0,0
stw		[r7],r0
tpx_not_full:
rtnw

// ================================
// tft draw box fill ; disturbed r0~r4,r6,r7
//	parameter:
//		sp+10:	px1
//		sp+8:	py1
//		sp+6:	px2
//		sp+4:	py2
//		sp+2:	pix
//		sp+0:	caller address
// ================================
equ		tft_boxf_px1,10
equ		tft_boxf_py1,8
equ		tft_boxf_px2,6
equ		tft_boxf_py2,4
equ		tft_boxf_pix,2
tft_boxf:
// CASET
ldwi	r7,spi_buf
ldbiu	r0,0x2a
stb		[r7],r0
addi	r7,1
// px1
ldbiu	r6,tft_boxf_px1
ldwsp	r0,[r6]
mov		r1,r0
lsfti	r1,-8
stb		[r7],r1
addi	r7,1
stb		[r7],r0
addi	r7,1
// px2
ldbiu	r6,tft_boxf_px2
ldwsp	r0,[r6]
mov		r1,r0
lsfti	r1,-8
stb		[r7],r1
addi	r7,1
stb		[r7],r0
addi	r7,1
// spi
ldbiu	r1,5
ldwi	r2,spi_buf
jalwr7	spi_transfer
// RASET
ldwi	r7,spi_buf
ldbiu	r0,0x2b
stb		[r7],r0
addi	r7,1
// py1
ldbiu	r6,tft_boxf_py1
ldwsp	r0,[r6]
mov		r1,r0
lsfti	r1,-8
stb		[r7],r1
addi	r7,1
stb		[r7],r0
addi	r7,1
// py2
ldbiu	r6,tft_boxf_py2
ldwsp	r0,[r6]
mov		r1,r0
lsfti	r1,-8
stb		[r7],r1
addi	r7,1
stb		[r7],r0
addi	r7,1
// spi
ldbiu	r1,5
ldwi	r2,spi_buf
jalwr7	spi_transfer
// calculate box square
ldbiu	r6,tft_boxf_px1
ldwsp	r0,[r6]
ldbiu	r6,tft_boxf_px2
ldwsp	r1,[r6]
sub		r1,r0
addi	r1,1
ldbiu	r6,tft_boxf_py1
ldwsp	r0,[r6]
ldbiu	r6,tft_boxf_py2
ldwsp	r2,[r6]
sub		r2,r0
addi	r2,1
mulu	r1,r2
mov		r3,r1
// put pixel
ldbiu	r0,tft_opt_init
jalwr7	tft_putpix
ldbiu	r6,tft_boxf_pix
ldwsp	r4,[r6]
tbf_loop:
mov		r1,r4
ldbiu	r0,tft_opt_store
jalwr7	tft_putpix
subi	r3,1
bne		tbf_loop
ldbiu	r0,tft_opt_flush
jalwr7	tft_putpix
rtnw

// ================================
// tft KANJI print 1 character ; disturbed r0~r7
//		and update cursor position
//	parameter:	set fnjpcod to character code to print
//		tft_2x2=0(normal size) / 1(2x2 size)
// ================================
tft_kprint_chr:
ldwi	r7,tft_2x2
ldw		r4,[r7]
// adjust cursor position
jalwr7	tft_upd_curs
// CASET
ldwi	r7,spi_buf
ldbiu	r0,0x2a
stb		[r7],r0
addi	r7,1
// px1
ldwi	r6,tft_prn_lx
ldw		r0,[r6]
lsfti	r0,3
mov		r1,r0
lsfti	r1,-8
stb		[r7],r1
addi	r7,1
stb		[r7],r0
addi	r7,1
// px2
addi	r0,7
mov		r4,r4
beq		pcnt+2
addi	r0,8
ldwi	r1,tft_siz_h
cmp		r0,r1
blo		pcnt+4
ldwi	r0,tft_siz_h-1
mov		r1,r0
lsfti	r1,-8
stb		[r7],r1
addi	r7,1
stb		[r7],r0
addi	r7,1
// spi
ldbiu	r1,5
ldwi	r2,spi_buf
jalwr7	spi_transfer
// RASET
ldwi	r7,spi_buf
ldbiu	r0,0x2b
stb		[r7],r0
addi	r7,1
// py1
ldwi	r6,tft_prn_ly
ldw		r0,[r6]
lsfti	r0,3
mov		r1,r0
lsfti	r1,-8
stb		[r7],r1
addi	r7,1
stb		[r7],r0
addi	r7,1
// py2
addi	r0,7
mov		r4,r4
beq		pcnt+2
addi	r0,8
ldwi	r1,tft_siz_v
cmp		r0,r1
blo		pcnt+4
ldwi	r0,tft_siz_v-1
mov		r1,r0
lsfti	r1,-8
stb		[r7],r1
addi	r7,1
stb		[r7],r0
addi	r7,1
// spi
ldbiu	r1,5
ldwi	r2,spi_buf
jalwr7	spi_transfer
// put pixel
ldbiu	r0,tft_opt_init
jalwr7	tft_putpix
ldbiu	r3,0
tpc_loop2:
// get font data
mov		r2,r3
mov		r4,r4
beq		pcnt+2
lsfti	r2,-1
ldwi	r7,fnjpdata
add		r7,r2
ldb		r0,[r7]
// draw 2x2?
pushw	r4
mov		r4,r4
beq		tpc_else_2x2
// 2x2 size
ldbiu	r4,16
ldwi	r7,fnjpdbl
stw		[r7],r0
ldw		r0,[r7]
bra		tpc_endi_2x2
tpc_else_2x2:
// 1x1 size
ldbiu	r4,8
lsfti	r0,8
tpc_endi_2x2:
// loop
tpc_loop1:
lsfti	r0,1
pushw	r0
bcc		pcnt+6
ldwi	r7,tft_prn_fg
bra		pcnt+4
ldwi	r7,tft_prn_bg
ldw		r1,[r7]
ldbiu	r0,tft_opt_store
jalwr7	tft_putpix
popw	r0
// end of loop1
subi	r4,1
bne		tpc_loop1
// end of loop2
addi	r3,1
popw	r4
mov		r4,r4
bne		tpc_yes_2x2
cmpi	r3,8
blo		tpc_loop2
bra		tpc_break

tpc_yes_2x2:
cmpi	r3,16
blo		tpc_loop2

tpc_break:
ldbiu	r0,tft_opt_flush
jalwr7	tft_putpix

tpc_return:
// update cursor position
ldwi	r7,tft_prn_lx
ldw		r0,[r7]
addi	r0,1
mov		r4,r4
beq		pcnt+2
addi	r0,1
stw		[r7],r0
rtnw

// ================================
// tft KANJI print ; disturbed r0~r7
//	parameter:	r1=pointer to print string
// ================================
tft_kprint:
tkp_loop:
ldb		r0,[r1]
addi	r1,1
mov		r0,r0
beq		tkp_return
// check control code?
cmpi	r0,0x20
bhs		tkp_not_ctrl
// control code
ldwi	r7,tft_get_ptr
stw		[r7],r1
ldwi	r7,lab_mlp_jmp_tab
add		r7,r0
add		r7,r0
ldw		r7,[r7]
jalw	r7
ldwi	r7,tft_get_ptr
ldw		r1,[r7]
bra		tkp_loop

tkp_not_ctrl:
// ASCII or S-JIS code
lsfti	r0,8
ldwi	r7,fnjpcod
stw		[r7],r0
ldwi	r7,fnjpctl
ldw		r2,[r7]
andi	r2,fnjp_sjs1
beq		tkp_not_sjis
// S-JIS code, read 2nd byte
ldb		r2,[r1]
addi	r1,1
add		r0,r2
ldwi	r7,fnjpcod
stw		[r7],r0
tkp_not_sjis:
// print 1 character
pushw	r1
jalwr7	tft_kprint_chr
popw	r1
bra		tkp_loop

tkp_return:
ldwi	r7,tft_get_ptr
ldbiu	r0,0
stw		[r7],r0
rtnw

// ================================
// tft initialize ; disturbed r0~r7
// ================================
tft_init:
// reset st7735r
tft_res_0
ldbiu	r1,1
jalwr7	delay
tft_res_1
ldbiu	r1,120
jalwr7	delay
// init st7735r register
ldwi	r5,lab_tft_init_reg
tin_loop:
ldb		r1,[r5]
addi	r5,1
mov		r2,r5
cmpi	r1,0xff
beq		tin_break
add		r5,r1
mov		r1,r1
beq		tin_loop
jalwr7	spi_transfer
// delay
ldb		r1,[r5]
addi	r5,1
jalwr7	delay
bra		tin_loop
tin_break:
// clear screen (box fill)
ldbiu	r0,0
pushw	r0
pushw	r0
ldwi	r0,tft_siz_h-1
pushw	r0
ldwi	r0,tft_siz_v-1
pushw	r0
ldwi	r7,tft_prn_bg
ldw		r0,[r7]
pushw	r0
jalwr7	tft_boxf
movfc	r0,sp
addi	r0,2*5
movtc	sp,r0
rtnw

// tft (st7735r) initialization data
//		<ndat>, <data1>~<data<ndat>>, <delay_ms>
tft_init_reg:
// SWRESET
datb	1,0x01,120
// SLPOUT
datb	1,0x11,120
// FRMCTR1
datb	4,0xb1,0x01,0x2c,0x2d,0
// FRMCTR2
datb	4,0xb2,0x01,0x2c,0x2d,0
// FRMCTR3
datb	7,0xb3,0x01,0x2c,0x2d,0x01,0x2c,0x2d,0
// INVCTR
datb	2,0xb4,0x07,0
// PWCTR1
datb	4,0xc0,0xa2,0x02,0x84,0
// PWCTR2
datb	2,0xc1,0xc5,0
// PWCTR3
datb	3,0xc2,0x0a,0x00,0
// PWCTR4
datb	3,0xc3,0x8a,0x2a,0
// PWCTR5
datb	3,0xc4,0x8a,0xee,0
// VMCTR1
datb	2,0xc5,0x0e,0
// MADCTL
datb	2,0x36,0xc8,0
// COLMOD
datb	2,0x3a,0x05,0

// CASET
datb	5,0x2a,0x00,0x00,0x00,0x7f,0
// RASET
datb	5,0x2b,0x00,0x00,0x00,0x9f,0

// NORON
datb	1,0x13,0
// DISPON
datb	1,0x29,120
// end of sequence
datb	0xff

// ================================
// tft get character ; disturbed r7
//		tft_get_ptr: 0=from UART8N1 / 0!=[tft_get_ptr]
//	return:		r0=received 1 byte data
// ================================
tft_get_chr:
ldwi	r7,tft_get_ptr
ldw		r0,[r7]
mov		r0,r0
bne		tgc_from_ptr
// from UART8N1
jmpr7	get_chr

tgc_from_ptr:
addi	r0,1
stw		[r7],r0
subi	r0,1
ldb		r0,[r0]
rtnw


// ================================
// get character ; disturbed r7
//	return:		r0=received 1 byte data
// ================================
get_chr:
// polling RAVL flag
ldwi	r7,uartctl
ldw		r0,[r7]
andi	r0,uart_ravl
beq		pcnt-6
// get data
ldwi	r7,uartrdat
ldw		r0,[r7]
rtnw

// ================================
// delay r1 [ms] ; disturbed r0,r7,sytmctl[MLOE]
// ================================
delay:
// 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]
cmp		r0,r1
blo		dly_loop
rtnw


// ================================
// c string data
// ================================
str_msg_credit:
dats	"\x0c\r\n$(prog_name)\r\n ver.$(prog_vers)\r\n\0"
str_err_no_mul:
dats	"\x0c\r\nERR: no mulc16\r\nhalted\0"

