
;LCD Port
rs		reg	p3.7
rw		reg	p3.6
en		reg 	p3.4
LCD_data_bus	reg	p2

;Key Port
key_play		reg	p0.7	;   
key_next		reg	p0.6	; eject		  stop
key_previous	reg	p0.5	;		
key_pause		reg	p0.4	; 	previous	  play	next
key_stop		reg	p0.3	;  
key_eject		reg	p0.2	;
key_mode		reg	p0.1	; modee		  pause

flag_pause	reg	20h.0	;"1"暫停中
flag_stop		reg	20h.1	;"1"停止中
flag_eject		reg	20h.2	;"1"門開啟中
flag_ready		reg	20h.3	;"1"準備好可撥放
flag_play		reg	20h.4	;"1"播放中
flag_return	reg	f0	;"1"重複撥放
flag_return_1	reg	21h.1	;;"1"重複撥放同一首

playing_track	equ 	08h
end_track		equ	09h
length_M		equ	0ah
length_S		equ	0bh
IR_DATA	equ	0ch
DR_DATA	equ	0dh
bcd_track		equ	0eh	;bcd 碼
bcd_end		equ	0fh	;bcd 碼
track_num_1	equ	10h
track_num_2	equ	11h
end_track_1	equ	12h
end_track_2	equ	13h
bcd_m		equ	14h
bcd_s		equ	15h
bcd_m_1		equ	16h
bcd_m_2		equ	17h
bcd_s_1		equ	18h
bcd_s_2		equ	19h
total_m		equ	1ah
total_s		equ	1bh

	org	00h			;
	jmp	start			;


;=====================================
;===========   串列接收副程式   ==========
;=====================================
get_data:					;
	acall	uart_wait			;
	mov	end_track,a		;
	acall	uart_wait			;
	mov	length_M,a		;
	acall	uart_wait			;
	mov	length_S,a			;
	acall	uart_wait			;
	mov	total_m,a			;
	jnb	ri,$			;	
	clr	ri			;
	mov	a,sbuf			;
	mov	total_s,a			;
	ret				;
uart_wait:					;
	jnb	ri,uart_wait		;	
	clr	ri			;
	mov	a,sbuf			;
	ret

;	mov	r4,#1			;
;	mov 	r7,#1 			;
;	acall 	delay_5ms 		;
;=====================================
;============    按鍵副程式 1  ============
;=====================================
next_key:					;
	jnb     	key_next,$ 		;
	jb	flag_eject,scan_key_loop	;
	mov	a,playing_track		;
	inc	a			;
	inc	end_track			;
	cjne	a,end_track,next_2		;
	mov	playing_track,#0		;
next_2:					;
	dec	end_track			;
	inc	playing_track		;
	mov	dptr,#string_next		;
	acall	print_line			;	
	acall	print_track		;
	acall	return_1			;
	jnb	key_pause	,scan_key_loop	;
	jmp	start_loop_1		;
previous_key:				;
	jnb     	key_previous,$ 		;
	jb	flag_eject,scan_key_loop	;
	djnz	playing_track,previous_2	;	
	mov	playing_track,end_track	;
previous_2:				;
	mov	dptr,#string_previous	;
	acall	print_line			;
	acall	print_track		;
	acall	return_1			;
	jnb	key_pause	,scan_key_loop	;
	jmp	start_loop_1		;
return_one:
	setb	flag_return_1		;
	mov	a,#0			;	
	mov	b,#0ch			;
	acall	GotoXY			;
	mov	dptr,#string_return_1		;	
	acall	PrintString			;
	ret				;
	
;=====================================
;===========   按鍵掃描副程式   ===========
;=====================================
eject_key_1:				;
	jmp	eject_key			;
scan_key:					;
	jnb	key_play,play_key		;
	jnb	key_next,next_key		;
	jnb	key_previous,previous_key	;
	jnb	key_pause	,pause_key	;
	jnb	key_stop,stop_key		;
	jnb	key_eject,eject_key_1	;
	jnb	key_mode,mode_key	;
	jnb	key_play,play_key		;
	ret				;

scan_key_loop:				;
	jnb	key_play,play_key		;
	jnb	key_next,next_key		;	
	jnb	key_previous,previous_key	;
	jnb	key_pause	,pause_key	;
	jnb	key_stop,stop_key		;
	jnb	key_eject,eject_key_1	;	
	jnb	key_mode,mode_key	;
	jmp	scan_key_loop		;
;=====================================
;============    按鍵副程式 2  ============
;=====================================
return_1: 					;
	jb	flag_return_1,return_one
	jnb	flag_return,non_return	;
	mov	a,#0			;
	mov	b,#0ch			;
	acall	GotoXY			;	
	mov	dptr,#string_return		;
	acall	PrintString			;
	ret				;
mode_key:				;
	jnb     	key_mode,$ 		;
	jb	flag_pause,scan_key_loop	;
	jb	flag_stop,scan_key_loop	;
	jb	flag_eject,scan_key_loop	;
	jbc	flag_return,return_one	;
	jbc	flag_return_1,non_return	;
	setb	flag_return		;
	acall	return_1			;
	ret				;

non_return:				;
	mov	a,#0			;	
	mov	b,#0ch			;
	acall	GotoXY			;
	mov	dptr,#string_no_return	;	
	acall	PrintString			;
	ret				;
play_key:					;
	jnb     	key_play,$ 		;
	jb	flag_stop,play_key_jump	;
	jb	flag_play,scan_key		;
	jb	flag_pause,resume_cmd	;	
	jb	flag_eject,close_cmd		;
play_key_jump:				;
	jmp	start_loop_1		;
pause_key:				;
	jnb     	key_pause,$ 		;	
	jb	flag_play,pause_cmd		;
	jb	flag_pause,resume_cmd	;
	jb	flag_stop,scan_key_loop	;
	jb	flag_eject,scan_key_loop	;
stop_key:					;
	jnb     	key_stop,$ 		;
	jb	flag_play,stop_cmd		;
	jb	flag_pause,stop_cmd	;
	jb	flag_stop,scan_key_loop	;
	jb	flag_eject,scan_key_loop	;

eject_key:					;
	jnb     	key_eject,$ 		;
	jb	flag_play,eject_cmd_jump	;
	jb	flag_pause,eject_cmd_jump	;
	jb	flag_stop,eject_cmd_jump	;
	jb	flag_eject,close_cmd
eject_cmd_jump:				;
	jmp	eject_cmd			;
;=====================================
;=============    按鍵程式   =============
;=====================================
;發送指令 & 改變旗標
;

play_cmd:					;
	mov	a,playing_track		;
	orl	a,#80H			;
	mov	sbuf,a			;
	acall	tram_wait			;
	mov	a,playing_track		;
	acall	get_data			;
	mov	sbuf,#00000001b		;
	acall	tram_wait			;
	mov	dptr,#string_play		;
	acall	print_line			;
	acall	print_track		;
	acall	return_1			;
	mov	20h,#00011000b		;
	ret				;

close_cmd:				;
	mov	sbuf,#00100000b		;
	acall	tram_wait			;
	clr	flag_eject			;
	mov	sp,#4fh			;
	jmp	start_loop			;
resume_cmd:				;
	mov	sbuf,#00000100b		;
	acall	tram_wait			;
	mov	a,#1			;
	mov	b,#0bh			;
	acall	GotoXY			;
	mov	dptr,#string_resume		;
	acall	PrintString			;
	mov	20h,#00011000b		;
	ret				;
pause_cmd:				;
	mov	sbuf,#00000010b		;
	acall	tram_wait			;
	mov	a,#1			;
	mov	b,#0bh			;
	acall	GotoXY			;
	mov	dptr,#string_pause		;
	acall	PrintString			;
	mov	20h,#00001001b		;
	jmp	scan_key_loop		;
stop_cmd:				;
	mov	sbuf,#00001000b		;
	acall	tram_wait			;
	mov	dptr,#string_stop		;
	acall	print_line			;
	mov	a,#1h			;
	mov	b,#0dh			;
	acall	GotoXY			;
	acall	print_end_track		;
	mov	a,#0			;
	mov	b,#0bh			;
	acall	GotoXY			;
	acall	print_total_time		;
	mov	20h,#00001010b		;
	mov	playing_track,#1		;
	jmp	scan_key_loop		;
eject_cmd:				;	
	mov	sbuf,#00010000b		;
	acall	tram_wait			;
	mov	dptr,#string_eject		;
	acall	print_line			;
	mov	20h,#00000100b		;
	mov	playing_track,#1		;
	jmp	scan_key_loop		;


;=====================================
;==========   傳送等待副程式   ============
;=====================================

tram_wait:					;
	jbc	ti,tram_ok			;
	jmp	tram_wait			;
tram_ok:					;
	ret				;

;=====================================
;========   串列傳輸初始化副程式   ========
;=====================================
Initial_UART:				;
	mov	tmod,#20h		;
	mov	th1,#0fdh			;傳輸速率 9600 bps
	setb	tr1			;致能 timer 1
	mov	scon,#50h			;設定串列傳輸 mode 1
	setb	ea			;致能中斷源
	setb	es			;致能串列埠
	ret				;


;=====================================
;========   LCD 模組初始化副程式   ========
;=====================================
Initial_LCD:	;
	mov	r4,#1			;
	mov	r7,#4			;
	acall	delay_5ms		;
	mov	IR_DATA,#00111000b 	;
	acall 	Write_IR		     	;
	mov	r4,#1			;
	mov 	r7,#2		    	;
	acall 	delay_5ms 		;
	mov 	IR_DATA,#00111000b 	;
	acall 	Write_IR 			;
	mov	r4,#1			;
	mov 	r7,#1 			;
	acall 	delay_5ms 		;
	mov 	IR_DATA,#00111000b	;
	acall 	Write_IR 			;
	mov 	IR_DATA,#00001000b 	;
	acall 	Write_IR 			;
	mov 	IR_DATA,#00000001b 	;
	acall 	Write_IR 			;
	mov 	IR_DATA , #00000110b 	;
	acall 	Write_IR 			;
	mov 	IR_DATA,#00001100b 	;
	acall 	Write_IR 			;
	ret 				;


;=====================================
;========= 檢查忙碌旗標 BF 副程式 ========
;=====================================
CheckBF:	;
	Push 	a			;
wait:					;
	Clr	rs			;rs=0
	Setb	rw			;r/w=0
	Setb 	en 			;en=1
	Mov	a,LCD_data_bus		;取行
	Clr	en 			;en=0
	Jb	acc.7,wait			;判斷BF旗標(ACC.7)是否為0,若
					;BF=l則表示LCD正在忙繼續等待直到
					;BF=0為止,CPU才可寫資料給LCD
	mov 	r7,#0			;
	djnz 	r7,$			;DELAY
	pop 	a			;BF已經為0,可以離開副程式
	ret				;

;================================================
;============  寫資料到IR暫存器副程式   ==============
;================================================
Write_IR:					;
	acall	CheckBF			;檢查BF旗標
	clr	rs			;RS=0
	clr	rw			;R/W
	setb	en			;E=1
	nop				;延時
	mov	LCD_data_bus,IR_DATA 	;將指令碼或位址送給LED模組
	nop				;延時
	clr	en			;E=0
	mov	r7,#0			;
	djnz	r7,$			;Delay
	ret				;

;===============================================
;============  寫資料到DR暫存器副程式   ============
;===============================================

Write_DR:				;
	acall	CheckBF			;檢查BF旗標
	setb 	rs			;RS=1
	clr	rw			;R/W=0
	setb 	en 			;E=l
	nop				;延時
	mov 	LCD_data_bus,DR_DATA	;將資料送給LCD模組
	nop				;延時
	clr 	en 			;E=0
	mov	r7,#0			;
	djnz 	r7,$			;Delay
	ret

;==============================================
;============   顯示資料到行(a)字(b)位置   ===========
;==============================================
GotoXY:	;
	push 	a			;
	anl	b,#00011111b		;
	cjne 	a,#0,Line1			;
	mov 	a,b			;
	add 	a ,#80h			;設定RAM的位置是由00h+(b)開始
	mov 	IR_DATA,a		;也就是由第一行的第b個字開始
	acall	Write_IR			;顯示字元
	pop 	a			;
	ret				;
Line1:					;
	mov 	a,b			;
	add 	a,#11000000b		;設定RAM的位置是由40h+(b)開始
	mov	IR_DATA,a 		;也就是由第二行的第b個字開始
	acall	Write_IR 			;顯示字元
	pop 	a			;
	ret				;

;==================================================
;=================   寫一個字串至 LCD 顯示  ============
;==================================================
PrintString:				;
	push 	a			;
PrintLoop:				;
	clr	a			;
	movc 	a,@a+dptr		;將dptr起的字元逐一送至LCD顯示
	cjne 	a,#'$',next_string 		;直至遇到結束符號"$"才結束
	jmp 	EndPrint			;
next_string:					;
	mov 	DR_DATA,a 		;
	acall	Write_DR			;
	inc 	dptr			;
	jmp 	PrintLoop			;
EndPrint:					;
	pop 	a			;
	inc 	dptr			;
	ret				;


;========================================
;================   LCD字串顯示  ===========
;========================================

print_line:	;
	mov	a,#0h			;
	mov	b,#0h			;
print_line2:				;
	acall	GotoXY			;
	acall	PrintString			;
	inc	a			;
	cjne	a,#2,print_line2		;
	ret
;========================================
;================   LCD 字串   ==============
;========================================
string_start:	db	'  Read CD ...   $'	;
		db	'Please Wait...^^$'	;

string_stop:	db	'Total Time   :  $'	;
		db	' Total Track    $'	;

string_play:	db	'Track   /       $'	;
		db	'Time   :        $'	;

string_next:	db	'Track   /      $'	;
		db	'   Next Track   $'	;

string_previous:	db	'Track   /      $'	;
		db	' Previous Track $'	;

string_eject:	db	'CD-ROM is open !$';
		db	'Please Wait...^^$'	;

string_pause:	db	'Pause$'		;

string_resume:	db	'     $'		;

string_return	db	'R-A $'		;

string_return_1	db	'R-1 $'		;

string_no_return	db	'    $'		;


;========================================
;=========   把track.time轉成ascii副程式   ========
;========================================
print_track:				;
	mov	a,#0			;
	mov	b,#6			;
	acall	GotoXY			;
	mov	a,playing_track		;
	acall	hex_2_bcd		;
	mov	bcd_track,a		;
	acall	ascii_code		;
	mov	track_num_1,b		;
	mov	track_num_2,a		;
	mov	DR_DATA,track_num_2	;
	acall	Write_DR			;
	mov	DR_DATA,track_num_1	;
	acall	Write_DR			;
	mov	DR_DATA,#2fh		;
	acall	Write_DR			;
print_end_track:				;
	mov	a,end_track		;
	acall	hex_2_bcd		;
	mov	bcd_end,a			;
	acall	ascii_code		;
	mov	end_track_1,b		;
	mov	end_track_2,a		;
	mov	DR_DATA,end_track_2	;
	acall	Write_DR			;
	mov	DR_DATA,end_track_1	;
	acall	Write_DR			;
	ret				;

print_total_time:				;
	mov	a,total_m			;
	acall	hex_2_bcd		;
	mov	bcd_m,a			;
	acall	ascii_code		;
	mov	bcd_m_1,b		;
	mov	bcd_m_2,a		;
	mov	DR_DATA,bcd_m_2	;
	acall	Write_DR			;
	mov	DR_DATA,bcd_m_1	;
	acall	Write_DR			;
	mov	DR_DATA,#3ah		;
	acall	Write_DR			;
	mov	a,total_s			;
	acall	hex_2_bcd		;
	mov	bcd_s,a			;
	acall	ascii_code		;
	mov	bcd_s_1,b		;
	mov	bcd_s_2,a			;
	mov	DR_DATA,bcd_s_2		;
	acall	Write_DR			;
	mov	DR_DATA,bcd_s_1		;
	acall	Write_DR			;
	ret				;
print_time:					;
	mov	a,length_M		;
	acall	hex_2_bcd		;
	mov	bcd_m,a			;
	acall	ascii_code		;
	mov	bcd_m_1,b		;
	mov	bcd_m_2,a		;
	mov	DR_DATA,bcd_m_2	;
	acall	Write_DR			;
	mov	DR_DATA,bcd_m_1	;
	acall	Write_DR			;
	mov	DR_DATA,#3ah		;
	acall	Write_DR			;
	mov	a,length_S			;
	acall	hex_2_bcd		;
	mov	bcd_s,a			;
	acall	ascii_code		;
	mov	bcd_s_1,b		;
	mov	bcd_s_2,a			;
	mov	DR_DATA,bcd_s_2		;
	acall	Write_DR			;
	mov	DR_DATA,bcd_s_1		;
	acall	Write_DR			;
	ret				;

ascii_code:				;
	mov	r0,a			;
	anl	a,#0fh			;
	orl	a,#30h			;
	mov	b,a			;

	mov	a,r0			;
	swap	a			;
	anl	a,#0fh			;
	orl	a,#30h			;
	ret				;

hex_2_bcd:				;
	mov	b,a			;
	anl	a,#0fh			;
	da	a			;
	xch	a,b			;
	swap	a			;
	anl	a,#0fh			;
	cjne	a,#0h,bcd_2_bcd_l		;
	xch	a,b			;
	jmp	bcd_2_bcd_end		;
bcd_2_bcd_l:				;
	xch	a,b			;
bcd_2_bcd_2:				;
	add	a,#16h			;
	da	a			;
	djnz	b,bcd_2_bcd_2		;
bcd_2_bcd_end:				;
	ret				;

;========================================
;================   延遲副程式   ============
;========================================
delay_1s:					;延時 r4 * 1s
	mov	r7,#0d5h			;
delay_5ms:				;延時 r7 * 5ms
	mov   	r6,#0afh			;
delay_loop:				;
	acall	scan_key			;
	nop				;
	nop				;
	nop				;
	nop				;
	nop				;
	djnz  	r6,delay_loop		;
	djnz  	r7,delay_5ms		;
	djnz  	r4,delay_1s		;
	ret				;

;=====================================
;==============    主程式    ==============
;=====================================

start:					;
	mov	sp,#4fh			;
	acall	Initial_UART		;
	acall	Initial_LCD		;
	clr	flag_return		;
	clr	flag_return_1		;

start_loop:				;
	mov	20h,#01000010b		;
	mov	dptr,#string_start		;
	acall	print_line			;
	acall	get_data			;
	setb	flag_ready			;
	mov	dptr,#string_stop		;
	acall	print_line			;
	mov	a,#1h			;
	mov	b,#0dh			;
	acall	GotoXY			;
	acall	print_end_track		;
	mov	a,#0h			;
	mov	b,#0bh			;
	acall	GotoXY			;
	acall	print_total_time		;
	mov	playing_track,#1		;	
	mov	r4,#5			;
	acall	delay_1s			;
start_loop_1:				;
	acall	play_cmd			;
	mov	sp,#4fh			;
count_down:				;
	mov	a,#1			;
	mov	b,#5			;
	acall	GotoXY			;
	acall	print_time			;
	mov	r4,#1			;
	acall	delay_1s			;
	dec	length_S			;
	mov	a,length_S			;
	cjne	a,#-1,count_down		;
	mov	length_S,#59		;
	dec	length_M			;
	mov	a,length_M		;
	cjne	a,#-1,count_down		;
	mov	a,playing_track		;
	jb	flag_return_1,start_loop_1	;
	cjne	a,end_track,next_track	;
	jb	flag_return,next_track_1	;
	jmp	stop_cmd			;
next_track:				;
	inc	playing_track		;
	jmp	start_loop_1		;
next_track_1:				;
	mov	playing_track,#1		;
	jmp	start_loop_1		;


	end				;