📄 ispcd-romv1.a51
字号:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; MSF routines
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
get_MSF_field:
acall get_data
mov toc_M,b
acall get_data
mov toc_S,a
mov toc_F,b
ret
print_MSF_field_lcd:
MOV DPTR,#LMESS5 ; Time
MOV A,#2
CALL LCD_PRINT
;Print_MSF_field_lcd:
mov a,toc_M
MOV POSITION,#5
CALL SHOW_DIG2
MOV A,toc_S
MOV POSITION,#8
CALL SHOW_DIG2
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; init ATA device routines..
;
; also detects the device during the process of initing it.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
init_ata_device:
acall CLR_SCREEN
MOV R5,#10
CALL LCD_DELAY
MOV DPTR,#LMESS3 ; Initing
MOV A,#1
CALL LCD_PRINT
; do hard reset..
;
; nb/ you have a wait a bit after pulling the reset back high. if you
; don't, then bsy flag will falsey pass. i haven't figured out a way
; yet to determine when the device controller is busy during hard reset
;
clr ATA_nRESET
acall delay_100000us
setb ATA_nRESET
mov r5,#2
acall delay
acall bsy_wait
;select device 0
;
;the device will now respond to commands now
;
acall get_devhead_register
; setb acc.4
clr acc.4 ;set device to 0
acall set_devhead_register
; test for device signature to determine if it's 'packet command' device
; if it's not a packet command, then it's probably a harddisk or
; something, and we can't continue.
;
; we have to check this inorder to know if we can issue the 'identify
; packet device' ATA command.
;
acall bsy_wait
acall get_cyl_low_register
cjne a,#14h,init_device_s_error
acall get_cyl_high_register
cjne a,#0ebh,init_device_s_error
sjmp init_device_s_done
init_device_s_error:
sjmp $
init_device_s_done:
; running self diagonistics..
; nb/ this is the first ATA command we send
;
mov a,#90h
acall set_cmd_register
acall bsy_wait
acall get_error_register
jb acc.0,init_device_c1
sjmp $
init_device_c1:
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ATAPI identify packet device
;
; this ATA/ATAPI command is mandatory for CDROM (and like) devices, as it
; will enable the DRDY flag. without this command, we won't be able to
; issue any commands (ATA or packet).
;
; nb/ older ATA standards, DRDY goes high immediately after BSY goes low
; during reset. .. not so for CDROM devices ;)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
print_device_ansi_lcd:
acall get_data
xch a,b
acall wdata
mov a,b
acall wdata
djnz r6,print_device_ansi_lcd
ret
identify_packet_device:
Call CLR_SCREEN
MOV R5,#10
CALL LCD_DELAY
MOV DPTR,#LMESS6 ; Identifying
MOV A,#1
CALL LCD_PRINT
MOV A,#0C0H
CALL WCOM
mov a,#2h ;set byte count registers
acall set_cyl_high_register ;maximum transfer length = 0200h
clr a ;nb/ on the few devices i've tested, this
acall set_cyl_low_register ;cmd automatically sets these registers.
;but i'll set it for consistency ;)
mov a,#0a1h
acall set_cmd_register
acall wait_irq
; get general config word
;
acall get_data
jb acc.0,identify_packet_device_c2
jb acc.1,identify_packet_device_c2
mov packet_size,#6
sjmp identify_packet_device_c3
identify_packet_device_c2:
jb acc.0,identify_packet_device_c3
jnb acc.1,identify_packet_device_c3
mov packet_size,#8
identify_packet_device_c3:
; skip next 26 words
;
mov r7,#26
acall skip_device_fields
; get model number
;
mov r6,#20
acall print_device_ansi_lcd
acall skip_rest_of_packet
acall bsy_drdy_wait
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
do_packet_cmd:
; clr packet table
;
mov r0,#packet_tab
mov r7,#16
init_pck_l:
mov @r0,#0
inc r0
djnz r7,init_pck_l
; send packet command
;
acall ndrq_wait
mov a,#0a0h
acall set_cmd_register
ret
send_packet:
acall drq_wait
mov r0,#packet_tab
mov r7,packet_size
send_packet_l:
mov a,@r0
inc r0
push acc
mov a,@r0
inc r0
mov b,a
pop acc
acall set_data
djnz r7,send_packet_l
acall wait_irq
acall get_status_register
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; test unit ready ATAPI command
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
test_unit_ready_cmd:
acall do_packet_cmd
acall send_packet
clr c
jnb STATUS_REG_ERR,test_unit_ready_d
ret
test_unit_ready_d:
setb c
ret
;
wait_for_ready_state:
call CLR_SCREEN
MOV R5,#10
CALL LCD_DELAY
MOV DPTR,#LMESS9 ; Insert Audio CD
MOV A,#1
CALL LCD_PRINT
MOV DPTR,#LMESS10 ; Waiting.......
MOV A,#2
CALL LCD_PRINT
wait_for_ready_state_restart:
jnb EJECT_CD,check_cd_o
mov r2,#1
;
wait_for_ready_state_l:
acall delay_100000us
acall delay_100000us
acall delay_100000us
acall delay_100000us
acall delay_100000us
acall test_unit_ready_cmd
jnc wait_for_ready_state_restart
dec r2
cjne r2,#0,wait_for_ready_state_l
ret
check_cd_o:
acall stop_play_cmd
call CLR_SCREEN
MOV R5,#10
CALL LCD_DELAY
MOV DPTR,#LMESS11 ; Open Door
MOV A,#1
CALL LCD_PRINT
MOV DPTR,#LMESS12 ; Wait....
MOV A,#2
CALL LCD_PRINT
acall do_packet_cmd
mov packet_cmd,#11011b
mov packet_4,#02h
acall send_packet
mov r5,#1
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; read sub channel cmd
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
read_subchan_cmd:
mov a,#0ffh ;set byte counter register
acall set_cyl_low_register ;(set it to full on.. it doesn't matter coz
acall set_cyl_high_register ;DRQ controls the feed)
acall do_packet_cmd
mov packet_cmd,#42h
mov packet_1,#00000010b ;MSF=1
mov packet_2,#01000000b ;SubQ=1
mov packet_3,#01h ;format=01 (current position)
mov packet_7,#0ffh ;allocation length
mov packet_8,#0ffh ;(set it to full on)
acall send_packet
jb STATUS_REG_ERR,read_subchan_cmd_e
jb STATUS_REG_DRQ,read_subchan_cmd_r
ret
read_subchan_cmd_e:
mov audio_status,#0ffh
ret
;
;read sub-channel header
;
read_subchan_cmd_r:
acall get_data ;get audio status
mov audio_status,b
acall get_data ;sub channel data length (will be zero).. ignore
acall get_data ;format code, ADR, cntl (ignore)
acall get_data
mov current_track,a
read_cmd:
cjne a,end_track,calc_next_track_1
sjmp calc_next_track_2
calc_next_track_1:
jc calc_next_track_2
mov a,start_track
calc_next_track_2:
mov next_track,a
MOV R5,#10
CALL LCD_DELAY
MOV DPTR,#LMESS13 ; Playing Track
MOV A,#1
CALL LCD_PRINT
mov a,current_track
MOV POSITION,#14
CALL SHOW_DIG1
; skip absolute address pos
acall get_MSF_field
; CALL LCD_PRINT
MOV A,#0C0H
CALL WCOM
; acall lcd_home2
acall get_MSF_field
acall print_MSF_field_lcd
acall skip_rest_of_packet
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Table of Contents command
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
read_toc_cmd:
CALL CLR_SCREEN
MOV R5,#10
CALL LCD_DELAY
MOV DPTR,#LMESS15 ; Reading TOC
MOV A,#1
CALL LCD_PRINT
mov a,#0ffh ;set byte counter register
acall set_cyl_low_register ;(set it to full on.. it doesn't matter coz
acall set_cyl_high_register ;DRQ controls the feed)
acall do_packet_cmd
mov packet_cmd,#43h
mov packet_1,#00000010b ;MSF=1
mov packet_7,#0ffh ;allocation length
mov packet_8,#0ffh ;(again, set it to full on)
acall send_packet
jb STATUS_REG_ERR,read_toc_cmd_e
jb STATUS_REG_DRQ,read_toc_cmd_r
setb c
ret
read_toc_cmd_e:
clr c
ret
; read header
;
read_toc_cmd_r:
acall get_data ;data length
acall get_data ;get track limits
mov start_track,a
mov end_track,b
MOV R5,#10
CALL LCD_DELAY
MOV DPTR,#LMESS14 ; Track Range
MOV A,#2
CALL LCD_PRINT
mov a,start_track
MOV POSITION,#11
CALL SHOW_DIG2
mov a,end_track
MOV POSITION,#14
CALL SHOW_DIG2
MOV a,end_track ;
inc a ; Save Last Track & Plus One
mov over_track,a ;
;
; read track descriptors
;
read_toc_cmd_l2:
acall get_data ;skip ADR and control fields
acall get_data ;get track number
mov toc_track,a
acall get_MSF_field
; if start track, then record start position
;
mov a,toc_track
cjne a,start_track,read_toc_cmd_i0
mov start_M,toc_M
mov start_S,toc_S
mov start_F,toc_F
read_toc_cmd_i0:
;if the last track, then record as end position
;
cjne a,#0aah,read_toc_cmd_i1
mov end_M,toc_M
mov end_S,toc_S
mov end_F,toc_F
read_toc_cmd_i1:
;if next track, then record next position
;
cjne a,next_track,read_toc_cmd_i2
mov next_M,toc_M
mov next_S,toc_S
mov next_F,toc_F
read_toc_cmd_i2:
acall bsy_wait
jb STATUS_REG_DRQ,read_toc_cmd_l2
setb c
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; stop/play command
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
stop_play_cmd:
acall do_packet_cmd
mov packet_cmd,#4eh
acall send_packet
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; play MSF cd cmd
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
play_entire_cd_cmd:
call CLR_SCREEN
MOV R5,#10
CALL LCD_DELAY
MOV DPTR,#LMESS13 ; Playing Track
MOV A,#1
CALL LCD_PRINT
mov a,next_track
MOV POSITION,#14
CALL SHOW_DIG1
acall do_packet_cmd
mov packet_cmd,#47h
mov packet_3,start_M
mov packet_4,start_S
mov packet_5,start_F
mov packet_6,end_M
mov packet_7,end_S
mov packet_8,end_F
acall send_packet
jnb STATUS_REG_ERR,play_audio_cmd_d
clr c
ret
play_audio_cmd_d:
setb c
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; program entry point
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
start:
mov sp,#STACK_START
CLR LCD_EN
mov next_track,#1
mov toc_M_next,#0
mov toc_S_next,#0
mov toc_F_next,#0
acall set_LCD ; Init & Set LCD to 4bit
mov r5,#2
acall delay
start_over:
acall init_ata_device
acall identify_packet_device
mov r5,#1
acall delay
; SETB ATA_INTRQ
main_loop:
acall wait_for_ready_state
acall read_toc_cmd
jnc main_loop
play_cd:
jnb PLAY_KEY,main_play
jnb EJECT_CD,unload_cd
jmp play_cd
main_play:
mov r5,#1
CALL CLR_SCREEN
acall play_entire_cd_cmd ;orignal play cd
jnc main_loop
mov r5,#1
acall delay
CALL CLR_SCREEN
play_loop:
acall read_subchan_cmd
mov a,audio_status
cjne a,#11h,play_stopped ;if at end then loop
mov a,toc_M
cjne a,toc_M_next,play_loop_end_cmp
mov a,toc_S
cjne a,toc_S_next,play_loop_end_cmp
mov a,toc_F
cjne a,toc_F_next,play_loop_end_cmp
sjmp play_stopped
play_loop_end_cmp:
mov toc_M_next,toc_M
mov toc_S_next,toc_S
mov toc_F_next,toc_F
acall delay_100000us
;
jnb NEXT_TRK,play_next_track ;
jnb EJECT_CD,unload_cd ;
jnb Pause_key,Pause_cd
jnb STOP_KEY,stop_cd
jnb PREVIOUS_TRK,play_previous_track ;
sjmp play_loop
stop_cd:
acall stop_play_cmd
mov next_track,#1
sjmp main_loop
play_stopped:
mov next_track,#1
sjmp play_normal
play_previous_track:
mov a,next_track
dec a
cjne a,#0,play_track_a
mov next_track,end_track
sjmp play_normal
play_track_a:
mov next_track,a
sjmp play_normal
play_next_track:
mov a,next_track
inc a
cjne a,over_track,play_track_a
mov next_track,#1
sjmp play_normal
play_normal:
acall stop_play_cmd
acall read_toc_cmd
jnc main_loop
mov start_M,next_M
mov start_S,next_S
mov start_F,next_F
sjmp main_play
unload_cd:
acall stop_play_cmd
call CLR_SCREEN
MOV R5,#10
CALL LCD_DELAY
MOV DPTR,#LMESS11 ; Open Door
MOV A,#1
CALL LCD_PRINT
MOV DPTR,#LMESS12 ; Wait....
MOV A,#2
CALL LCD_PRINT
acall do_packet_cmd
mov packet_cmd,#11101011b
mov packet_4,#02h
acall send_packet
mov next_track,#1
jmp main_loop
Pause_cd:
mov r5,#10
CALL LCD_DELAY
MOV DPTR,#LMESS13A ; Pause CD
MOV A,#1
CALL LCD_PRINT
mov a,next_track
MOV POSITION,#12
CALL SHOW_DIG1
acall do_packet_cmd
mov packet_cmd,#4bh
mov packet_8,#00h
acall send_packet
acall delay_100000us
acall delay_100000us
Pause_Loop:
jnb Pause_key,resume_cd
jmp Pause_loop
Resume_cd:
acall do_packet_cmd
mov packet_cmd,#4bh
mov packet_8,#01h
acall send_packet
jmp Play_loop_end_cmp
; 0123456789012345
LMESS1: DB " CD-Rom Player ",0
LMESS2: DB " Version 5.0 ",0
;
LMESS3: DB "Initing ",0
LMESS4: DB " ",0
;
LMESS5: DB "Time : ",0
;
LMESS6: DB " Identifying ",0
;
LMESS7: DB " Close Door ",0
LMESS8: DB " Waiting... ",0
;
LMESS9: DB " Reading CD ",0
LMESS10: DB " Waiting... ",0
;
LMESS11: DB " Open Door ",0
LMESS12: DB " Waiting... ",0
;
LMESS13: DB "Playing Track ",0
;
LMESS13A: DB "Pause Track ",0
;
LMESS14: DB "TrackRange - ",0
;
LMESS15: DB "Reading TOC ",0
;
LMESS16: DB " Please Insert ",0
LMESS17: DB " Audio CD ",0
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -