📄 simple_cdrom_controller.a51
字号:
; running self diagonistics..; nb/ this is the first ATA command we send; lcall lprint db 'Passed ATA self diagnositics?..',0 mov a,#90h acall set_cmd_register acall bsy_wait acall get_error_register jb acc.0,init_device_c1 acall print_no sjmp $init_device_c1: acall print_yes 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 ;);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;skip_device_fields: acall get_data djnz r7,skip_device_fields retprint_device_ansi: acall get_data xch a,b lcall writechar mov a,b lcall writechar djnz r7,print_device_ansi retidentify_packet_device: lcall lprint db 'Identifying ATAPI device:',13,10,0;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 jnb b.7,identify_packet_device_c0 jb b.6,identify_packet_device_c0 lcall lprint db 9,'Unit is an ATAPI device',13,10,0identify_packet_device_c0: jnb acc.7,identify_packet_device_c1 lcall lprint db 9,'Unit has removable media',13,10,0identify_packet_device_c1: lcall lprint db 9,'packet size (words): ',0 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 lcall prhex lcall prcrlf lcall lprint db 9,'type:',9,0 mov a,b anl a,#0fh lcall prhex lcall prcrlf; skip next 9 words; mov r7,#9 acall skip_device_fields; get serial number; lcall lprint db 9,'serial:',9,0 mov r7,#10 acall print_device_ansi lcall prcrlf; skip next 3 words; mov r7,#3 acall skip_device_fields; get firmware revision; lcall lprint db 9,'rev:',9,0 mov r7,#4 acall print_device_ansi lcall prcrlf; get model number; lcall lprint db 9,'model:',9,0 mov r7,#20 acall print_device_ansi lcall prcrlf; skip next 33 words; mov r7,#33 acall skip_device_fields; get major version; lcall lprint db 9,'major:',9,0 acall get_data xch a,b lcall prhex mov a,b lcall prhex lcall prcrlf; get major version; lcall lprint db 9,'minor:',9,0 acall get_data xch a,b lcall prhex mov a,b lcall prhex lcall prcrlf; skip next 46 words; mov r7,#46 acall skip_device_fields; get security word; lcall lprint db 9,'secure:',9,0 acall get_data xch a,b lcall prhex mov a,b lcall prhex lcall prcrlf acall skip_rest_of_packet acall bsy_drdy_wait lcall lprint db 'ATAPI device now has READY status.',13,10,0 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 retprint_packet_error: lcall lprint db '...Failed: ',0 acall get_error_register lcall prhex lcall prcrlf 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: lcall lprint db 'Waiting for Unit READY state (insert CD. if not inserted).',13,10,0 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: lcall lprint db 'Read TOC cmd..',13,10,0 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 retread_toc_cmd_e: acall print_packet_error clr c ret; read header;read_toc_cmd_r: acall get_data ;data length acall get_data ;get track limits mov start_track,a lcall lprint db 9,'Start Trk:',9,0 mov a,start_track lcall prhex lcall prcrlf lcall lprint db 9,'End Trk:',9,0 mov a,b lcall prhex lcall prcrlf; read track descriptors; lcall lprint db 9,'Tracks-',13,10 db 9,9,'ADR/Ctl',9,'Trk',9,'MSF',13,10 db 0read_toc_cmd_l2: lcall lprint db 9,9,0 acall get_data ;get ADR and control fields mov a,b lcall prhex mov a,#9 lcall writechar acall get_data ;get track number mov tmp0,a lcall prhex mov a,#9 lcall writechar acall get_MSF_field; 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: lcall lprint db 'Play Entire CD (Play Audio MSF cmd)..',13,10,0 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 acall print_packet_error clr c retplay_audio_cmd_d: setb c ret;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; read sub channel cmd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;read_subchan_cmd: lcall lprint db 'Read Sub-Channel cmd..',13,10,0 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 retread_subchan_cmd_e: acall print_packet_error ret;read sub-channel header;read_subchan_cmd_r: acall get_data ;get audio status lcall lprint db 9,'Audio Status:',9,0 mov a,b lcall prhex lcall prcrlf acall get_data ;sub channel data length (will be zero).. ignore acall get_data ;format code, ADR, cntl (ignore) lcall lprint ;track number, index number db 9,'Track number:',9,0 acall get_data lcall prhex lcall prcrlf lcall lprint ;absolete CDROM address db 9,'Abs address:',9,0 acall get_MSF_field lcall lprint ;relative CDROM address db 9,'Rel address:',9,0 acall get_MSF_field acall skip_rest_of_packet ret;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; stop/play command;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;stop_play_cmd: lcall lprint db 'Stop play cmd..',13,10,0 acall do_packet_cmd mov packet_cmd,#4eh acall send_packet jnb STATUS_REG_ERR,stop_play_cmd_d acall print_packet_errorstop_play_cmd_d: ret;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; program entry point;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;start: mov sp,#07fh ;set stack position lcall prcrlf lcall lprint db 'A Simple 8051 based ATAPI CDROM audio controller version 0,',13,10 db 'Copyright (C) 2000 Jason Nunn <jsno@downunder.net.au>',13,10, db 13,10 db 'This software comes under the GNU public license agreement.',13,10 db 'See the COPYING file in this distribution.',13,10 db 13,10 db 'If you use this code (or parts) of it, then please credit me.',13,10 db 0 acall init_ata_device acall identify_packet_device lcall lprint db 'Settling delay..',13,10,0 mov r5,#1 acall delaymain_loop: acall wait_for_ready_state acall read_toc_cmd jnc main_loop acall play_entire_cd_cmd jnc main_loop lcall lprint db 'Playing..',13,10,0play_loop: acall read_subchan_cmd lcall lprint db 'Hit "q" to stop play..',13,10,0 mov r5,#1 acall delay mov a,s1con ;read character jnb acc.0,play_loop anl s1con,#0feh mov a,s1buf anl a,#7fh cjne a,#'q',play_loop acall stop_play_cmd lcall lprint db 'Play has been stopped.. Program ended.',13,10,0 sjmp $end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -