📄 final_target.a51
字号:
jb STATUS_REG_BSY,drq_wait jb STATUS_REG_DRQ,drq_wait ret;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; main routines;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; misc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;terminate_with_error: setb F_ERROR sjmp $; clocks data out of buffer until all done (DRQ goes low);skip_rest_of_packet: acall get_status_register jnb STATUS_REG_DRQ,skip_rest_of_packet_d acall get_data sjmp skip_rest_of_packetskip_rest_of_packet_d: ret;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; init ATA device routines..;; also detects the device during the process of initing it.;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;init_ata_device:; 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 clr ATA_DATA_LS.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_doneinit_device_s_error: ajmp terminate_with_errorinit_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 ajmp terminate_with_errorinit_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 ;);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;identify_packet_device:;identify device cmd; 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 clr a jb acc.0,identify_packet_device_c2 jb acc.1,identify_packet_device_c2 mov a,#6identify_packet_device_c2: jb acc.0,identify_packet_device_c3 jnb acc.1,identify_packet_device_c3 mov a,#8identify_packet_device_c3: mov packet_size,a acall skip_rest_of_packet acall bsy_drdy_wait ret;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;do_packet_cmd:; clr packet table; mov r0,#packet_tab mov r7,#16init_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 retsend_packet: acall drq_wait mov r0,#packet_tab mov r7,#packet_sizesend_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 jnb STATUS_REG_ERR,test_unit_ready_d clr c rettest_unit_ready_d: setb c retwait_for_ready_state: mov r2,#2wait_for_ready_state_l: mov r5,#1 acall delay acall test_unit_ready_cmd jnc wait_for_ready_state_l dec r2 cjne r2,#0,wait_for_ready_state_l ret;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Table of Contents command;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;read_toc_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,#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_DRQ,read_toc_cmd_rread_toc_cmd_e: ajmp terminate_with_error; read header;read_toc_cmd_r: acall get_data ;data length acall get_data ;get track limits mov start_track,a; read track descriptors;read_toc_cmd_l2: acall get_data ;get ADR and control fields acall get_data ;get track number mov tmp0,a acall get_data mov tmp1,b acall get_data mov tmp2,a mov tmp3,b; if start track, then record start position; mov a,tmp0 cjne a,start_track,read_toc_cmd_i0 mov start_M,tmp1 mov start_S,tmp2 mov start_F,tmp3read_toc_cmd_i0:;if the last track, then record as end position; cjne a,#0aah,read_toc_cmd_i1 mov end_M,tmp1 mov end_S,tmp2 mov end_F,tmp3read_toc_cmd_i1: acall bsy_wait jb STATUS_REG_DRQ,read_toc_cmd_l2 setb c ret;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; play MSF cd cmd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;play_entire_cd_cmd: 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 ajmp terminate_with_errorplay_audio_cmd_d: ret;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; read sub channel cmd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;read_subchan_cmd: mov a,#04h ;set byte counter register acall set_cyl_low_register ;= 4 bytes acall set_cyl_high_register ; 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_8,#04h ;allocation length (4 bytes) acall send_packet jb STATUS_REG_DRQ,read_subchan_cmd_rread_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 skip_rest_of_packet ret;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; program entry point;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;start: mov sp,#STACK_START ;set stack positionstart_over: clr F_ERROR clr F_PLAYING acall init_ata_device acall identify_packet_device setb F_PLAYING mov r5,#1 acall delaymain_loop: acall wait_for_ready_state acall read_toc_cmd acall play_entire_cd_cmdplay_loop: mov c,play_blink mov F_PLAYING,c jnc play_loop_c1 clr play_blink sjmp play_loop_c2play_loop_c1: setb play_blinkplay_loop_c2: mov r5,#1 acall delay acall read_subchan_cmd mov a,audio_status cjne a,#11h,play_loop_end ;if playing, then loop, else start over sjmp play_loopplay_loop_end: clr F_PLAYING sjmp main_loopend
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -