📄 old.asm
字号:
; MP3 Player, Main Program, http://www.pjrc.com/tech/mp3; Copyright (c) 2000, PJRC.COM, LLC; This program is free software; you can redistribute it and/or; modify it under the terms of the GNU General Public License; as published by the Free Software Foundation; either version 2; of the License, or (at your option) any later version.; This program is distributed in the hope that it will be useful,; but WITHOUT ANY WARRANTY; without even the implied warranty of; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the; GNU General Public License for more details.; You should have received a copy of the GNU General Public License; along with this program; if not, write to the Free Software; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.; As a specific exception to the GPL, the executable object code built; from this source code may be combined with hardware configuration data; files. A hardware configuration data file is a set of data that is; transmitted to an intergrated circuit that is not a general purpose; microprocessor or microcontroller, in order to establish its normal; operation. The process of combining the executable ojbect code built; from the GPL licensed source code with the hardware configuration data; shall be considered an aggregation of another work not based on the; Program. While the GPL does not restrict use of the program, any; use restriction associated with the hardware configuration data (for; example, that it only be used with particular hardware) shall apply; to the combined file which includes a copy of the hardware configuration; data.; Contact: paul@pjrc.com.equ location, 0xF000 ;where this program will exist.equ cout, 0x0030 ;Send Acc to serial port.equ cin, 0x0032 ;Get Acc from serial port.equ phex, 0x0034 ;Print Hex value of Acc.equ phex1, 0x002E.equ phex16, 0x0036 ;Print Hex value of DPTR.equ pstr, 0x0038 ;Print string pointed to by DPTR,.equ upper, 0x0040 ;Convert Acc to uppercase.equ pint8u, 0x004D ;print Acc at an integer, 0 to 255.equ pint8, 0x0050 ;print Acc at an integer, -128 to 127.equ pint16u, 0x0053 ;print DPTR as an integer, 0 to 65535.equ newline, 0x0048 ;print CR/LF (13 and 10).equ call_bank1, 0x0FE0.equ xdownload, 0x3040.equ sta013_init, 0x3043.equ shutdown, 0x3046.equ sta013_rd, 0x304C.equ sta013_wr, 0x304F;addresses for accessing the ide interface.equ ide_data, 0xFF10.equ ide_err, 0xFF11.equ ide_features, 0xFF11.equ ide_sec_cnt, 0xFF12.equ ide_sector, 0xFF13.equ ide_cyl_lsb, 0xFF14.equ ide_cyl_msb, 0xFF15.equ ide_head, 0xFF16.equ ide_command, 0xFF17.equ ide_status, 0xFF17.equ ide_control, 0xFF0E.equ ide_astatus, 0xFF0F.equ sector_buffer, 0xFC00 ;buffer is read only;IDE Command Constants. These should never change..equ ide_cmd_recal, 0x10.equ ide_cmd_read, 0x20.equ ide_cmd_write, 0x30.equ ide_cmd_init, 0x91.equ ide_cmd_id, 0xEC.equ ide_cmd_spindown, 0xE0.equ ide_cmd_spinup, 0xE1.equ ide_cmd_idle, 0xE1.equ ide_cmd_sleep, 0xE6.equ ide_cmd_set_features, 0xEF.equ ide_cmd_initparms, 0x91.equ status, 0x08 ;1 byte.equ sectors_per_cluster, 0x09 ;1 byte.equ button_state, 0x0A ;1 byte.equ state_quit, 0x0B ;1 byte.equ lba, 0x0C ;4 bytes.equ size, 0x10 ;4 bytes.equ partition_first_sector, 0x14 ;4 bytes.equ partition_size, 0x18 ;4 bytes.equ first_data_sector, 0x1C ;4 bytes.equ flags, 0x21.equ dir_position_sector, 0x22 ;1 byte, 0 to sectors_per_cluster-1.equ dir_position_offset, 0x23 ;1 byte, 0 to 15.equ dir_position_cluster, 0x24 ;4 bytes.equ root_dir_cluster, 0x28 ;4 bytes.equ cluster, 0x2C ;4 bytes.equ filename, 0x30 ;11 bytes.equ attrib, 0x3B ;1 byte.equ reserved_sector_count, 0x3C ;2 bytes.equ tmp_var, 0x3E ;4 bytes.equ state_next, 0x42 ;1 byte.equ state_prev, 0x43 ;1 byte.equ state_play, 0x44 ;1 byte.equ rand_number, 0x45 ;1 byte.equ rand_count, 0x46 ;1 byte.equ master_slave, 0x47 ;1 byte.equ stack, 0x50.equ playing_flag, 0x08.equ paused_flag, 0x09.equ next_flag, 0x0A.equ prev_flag, 0x0B.equ end_now_flag, 0x0C.equ mute_is_on, 0x0D.equ rand_mode_flag, 0x0E.org location.db 0xA5,0xE5,0xE0,0xA5 ;signiture bytes.db 35,255,0,0 ;id.db 0,0,0,0 ;reserved.db 0,0,0,0 ;reserved.db 0,0,0,0 ;reserved.db 0,0,0,0 ;reserved.db 0,0,0,0 ;user defined.db 255,255,255,255 ;length and checksum (255=unused).db "MP3 Player, Ver 0.1.3 (No SIMM)",0.org location+64 ;executable code begins herebegin: mov sp, #stack mov dptr, #mesg_welcome lcall pstr clr a mov flags, a mov state_quit, a mov state_play, a mov state_next, a mov state_prev, a acall read_buttons orl a, 0x10 mov button_state, a mov dptr, #mesg_xilinx_cfg lcall pstr mov dptr, #xdownload lcall call_bank1 jc error mov dptr, #mesg_ok lcall pstr mov dptr, #mesg_reset_ide lcall pstr acall ide_reset mov dptr, #mesg_sta013_cfg lcall pstr mov dptr, #sta013_init lcall call_bank1 jc error mov dptr, #mesg_ok lcall pstr setb mute_is_on ;new driver.asm starts with mute on mov r3, #20 ;set default volume to -20 dB mov r4, #0x46 mov dptr, #sta013_wr lcall call_bank1 ;write left attenuation mov r4, #0x48 mov dptr, #sta013_wr lcall call_bank1 ;write right attenuation mov dptr, #mesg_ide_init lcall pstr lcall ide_init lcall newline ajmp read_mbrerror: mov dptr, #mesg_error lcall pstr ajmp quitread_mbr: mov lba+3, #0 mov lba+2, #0 mov lba+1, #0 mov lba+0, #0 mov dptr, #mesg_read_mbr lcall pstr acall ide_read_sector lcall ide_drq lcall grab_data mov dptr, #sector_buffer + 0x1FE movx a, @dptr cjne a, #0x55, bad_mbr inc dptr movx a, @dptr cjne a, #0xAA, bad_mbr mov dptr, #sector_buffer + 0x1C2 movx a, @dptr acall is_fat32_type jnc found_partition acall print_unknown_type mov dptr, #sector_buffer + 0x1D2 movx a, @dptr acall is_fat32_type jnc found_partition acall print_unknown_type mov dptr, #sector_buffer + 0x1E2 movx a, @dptr acall is_fat32_type jnc found_partition acall print_unknown_type mov dptr, #sector_buffer + 0x1F2 movx a, @dptr acall is_fat32_type jnc found_partition acall print_unknown_type ajmp quitis_fat32_type: add a, #256 - 11 ;is it type 0B jz isf32b add a, #255 ;is it type 0C jz isf32b add a, #12 setb c retisf32b: clr c retbad_mbr: lcall print_sector_buffer lcall newline mov dptr, #mesg_bad_mbr lcall pstr ajmp quitprint_unknown_type: push acc mov dptr, #msg_unknown_partion_type lcall pstr pop acc lcall phex lcall newline retget_byte: movx a, @dptr inc dptr ret found_partition: inc dptr inc dptr inc dptr inc dptr acall get_byte mov partition_first_sector+0, a acall get_byte mov partition_first_sector+1, a acall get_byte mov partition_first_sector+2, a acall get_byte mov partition_first_sector+3, a acall get_byte mov partition_size+0, a acall get_byte mov partition_size+1, a acall get_byte mov partition_size+2, a acall get_byte mov partition_size+3, a mov dptr, #mesg_partition_at lcall pstr mov r0, #partition_first_sector acall phex32_at_r0 lcall newline ajmp read_vol_idbad_vol_id: lcall print_sector_buffer mov dptr, #mesg_bad_vol_id lcall pstr lcall print_sector_buffer ajmp quitread_vol_id: mov dptr, #mesg_read_vol_id lcall pstr mov lba+0, partition_first_sector+0 mov lba+1, partition_first_sector+1 mov lba+2, partition_first_sector+2 mov lba+3, partition_first_sector+3 acall ide_read_sector lcall ide_drq lcall grab_data ;acall print_sector_buffer mov dptr, #sector_buffer + 0x1FE movx a, @dptr cjne a, #0x55, bad_vol_id inc dptr movx a, @dptr cjne a, #0xAA, bad_vol_id mov dptr, #sector_buffer + 11 movx a, @dptr jnz bad_vol_id ;require 512 byte sector inc dptr movx a, @dptr cjne a, #2, bad_vol_id ;require 512 byte sector mov dptr, #sector_buffer + 16 movx a, @dptr cjne a, #2, bad_vol_id ;require BPB_NumFATs == 2 mov dptr, #mesg_vol_id_ok lcall pstr clr c mov dptr, #sector_buffer + 36 ;offset of BPB_FATSz32 movx a, @dptr rlc a mov r2, a ;r2 to r5 has BPB_FATSz32 * 2 inc dptr movx a, @dptr rlc a mov r3, a inc dptr movx a, @dptr rlc a mov r4, a inc dptr movx a, @dptr rlc a mov r5, a mov dptr, #mesg_sectors_for_fats lcall pstr mov r0, #2 acall phex32_at_r0 lcall newline mov dptr, #sector_buffer + 14 ;read BPB_RsvdSecCnt movx a, @dptr mov reserved_sector_count+0, a inc dptr movx a, @dptr mov reserved_sector_count+1, a mov dptr, #mesg_reserved_sectors lcall pstr mov a, reserved_sector_count+1 lcall phex mov a, reserved_sector_count+0 lcall phex lcall newline mov a, r2 ;add (BPB_FATSz32 * 2) add a, reserved_sector_count+0 ;to reserved_sector_count mov first_data_sector+0, a ;and store as first_data_sector mov a, r3 addc a, reserved_sector_count+1 mov first_data_sector+1, a mov a, r4 addc a, #0 mov first_data_sector+2, a mov a, r5 addc a, #0 mov first_data_sector+3, a mov a, first_data_sector+0 add a, partition_first_sector+0 mov first_data_sector+0, a mov a, first_data_sector+1 addc a, partition_first_sector+1 mov first_data_sector+1, a mov a, first_data_sector+2 addc a, partition_first_sector+2 mov first_data_sector+2, a mov a, first_data_sector+3 addc a, partition_first_sector+3 mov first_data_sector+3, a mov dptr, #mesg_first_data_sec lcall pstr mov r0, #first_data_sector acall phex32_at_r0 lcall newline mov dptr, #sector_buffer + 13 ;read BPB_SecPerClus movx a, @dptr mov sectors_per_cluster, a mov dptr, #mesg_sec_per_cluster lcall pstr mov a, sectors_per_cluster lcall phex lcall newline mov dptr, #sector_buffer + 44 ;read BPB_RootClus movx a, @dptr mov root_dir_cluster+0, a inc dptr movx a, @dptr mov root_dir_cluster+1, a inc dptr movx a, @dptr mov root_dir_cluster+2, a inc dptr movx a, @dptr mov root_dir_cluster+3, a mov dptr, #mesg_root_dir_at_cluster lcall pstr mov r0, #root_dir_cluster acall phex32_at_r0 lcall newline ajmp begin_player;*************************************************************;** **;** MP3 Player Main Code **;** **;*************************************************************begin_player: mov dptr, #mesg_begin lcall pstr clr next_flag clr prev_flag clr paused_flag ; begin with the first file in the root directory mov dir_position_cluster+0, root_dir_cluster+0 mov dir_position_cluster+1, root_dir_cluster+1 mov dir_position_cluster+2, root_dir_cluster+2 mov dir_position_cluster+3, root_dir_cluster+3 mov dir_position_sector, #0 mov dir_position_offset, #0traverse_dir: acall fat32_get_dir_info mov a, filename jz stop_playing ;acall print_filename acall is_mp3_file jnc trav_dir2 acall rand_stuff ;does random mode want us to skip forward? jc trav_dir2 acall play_filetrav_dir2: acall trav_direction jnc traverse_dirstop_playing: ;now what do we do? ;let's just start over again for now ajmp begin_playertrav_direction: jb prev_flag, trav_prevtrav_next: ajmp fat32_next_filetrav_prev: ajmp fat32_prev_file ;the main loop calls here to see if it ought to play the ;next track. If we're not in random mode, we'll always ;return C=0, so it'll play all the tracks in sequence. ;if we're in random play mode, we'll skip past files ;until rand_count == 0, and when generate a new ;rand_number and copy it to rand_count. The idea is that ;we'll always skip a random number of tracks, from 0 to ;254 tracks when in random mode.rand_stuff: jb rand_mode_flag, rand_s2 ;not in random mode, always play the next track clr c retrand_s2: dec rand_count mov a, rand_count jz rand_s3 setb c ;keep skipping until rand_count == 0 retrand_s3: ;now we generate a new rand_number and copy to ;rand_count, and of course let the track play mov a, rand_number jnz rand_nz cpl a mov rand_number, arand_nz:anl a, #10111000b mov c, p mov a, rand_number rlc a mov rand_number, a dec a mov rand_count, a clr c ret;*************************************************************;** **;** Play a File **;** **;*************************************************************play_file: ;print a message about the file mov dptr, #mesg_playing_file lcall pstr acall print_filename clr next_flag clr prev_flag clr paused_flag setb playing_flag ;find the first sector mov r2, cluster+0 mov r3, cluster+1 mov r4, cluster+2 mov r5, cluster+3 acall fat32_cluster_to_lba ;mov r0, #lba ;acall phex32_at_r0 ;lcall newline acall bytes_to_sectors ;mov size+2, #0 ;for testing, only play first ;mov size+1, #0 ;64k of the file ;mov size+0, #128 ;now "lba" has the first sector number and "size" has the ;number of sectors to play. In an ideal world, we'd play ;all the sectors within this cluster and call ;"fat32_next_cluster" to get the next cluster's "lba", and ;keep doing that until we've played "size" sectors. ;unfortunately, we can't afford to call "fat32_next_cluster" ;while we're playing a file, because it reads a sector and ;that will take too much time, because we have only one ;sector of buffering without the DRAM. ;the approach is to just assume that all the clusters for ;the file are in sequential order. This means the user ;must run defrag. Kinda sad, because if we could buffer ;a cluster or two (or 32 megs!) there'd be plenty of time ;to call "fat32_next_cluster", which would also work with ;buffered sectors in most cases. I gotta get that DRAM ;controller integrated into the FPGA design! acall ide_read_sector acall inc_lbamainloop: lcall ide_drq lcall grab_data mov dptr, #0xFF31 movx @dptr, a ;clear the address counter mov dptr, #0xFF37 movx @dptr, a ;clear interrupt bit mov dptr, #0xFF33 movx @dptr, a ;begin data xfer jnb mute_is_on, main_next acall turn_mute_offmain_next: acall dec_size jc main_exit jb next_flag, main_exit jb prev_flag, main_exit jb paused_flag, pause_loopmain_reenter: ;clr paused_flag acall ide_read_sector acall inc_lba acall check_buttonsmainwait: mov status, #8 acall wait jb p3.2, mainwait mov status, #9 mov dptr, #0xFF37 movx @dptr, a ;ack the interrupt bit sjmp mainloopmain_exit: mov status, #10 acall wait jb p3.2, main_exit mov status, #11 mov dptr, #0xFF37 movx @dptr, a ;ack the interrupt bit lcall newline retpause_loop: ;clr playing_flag ;setb paused_flag acall check_buttons jb next_flag, main_reenter jb prev_flag, main_reenter jb playing_flag, main_reenter jnb paused_flag, main_reenter acall wait sjmp pause_loopinc_lba: mov a, lba add a, #1 mov lba, a mov a, lba+1 addc a, #0 mov lba+1, a mov a, lba+2 addc a, #0 mov lba+2, a mov a, lba+3 addc a, #0 mov lba+3, a ret ;decrement the size count, and return C=1 if zerodec_size: clr c mov a, size+0 subb a, #1 mov size+0, a mov a, size+1 subb a, #0 mov size+1, a mov a, size+2 subb a, #0 mov size+2, a jnz dec_size2 mov a, size+0 jnz dec_size2 mov a, size+1 jnz dec_size2 setb c retdec_size2: clr c retturn_mute_off: mov r0, #100 ;brief delay, to transfer enough djnz r0, * ;mp3 data to get the sta013 to mov r4, #20 ;move from "init" to "decode" mode mov r3, #0 mov dptr, #sta013_wr lcall call_bank1 ;mute off mov r4, #114 mov r3, #1 mov dptr, #sta013_wr lcall call_bank1 ;start playing clr mute_is_on retwait: jb ri, keypress retkeypress: lcall cin lcall upper lcall cout mov r2, acheck_quit: mov dptr, #str_quit mov r0, #state_quit acall lexer jnc check_next ajmp quit retcheck_next: mov dptr, #str_next
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -