?? isr.asi
字號:
;interrupt service routines; MP3 Player, Interrupt Service Routines, 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 pm2_cout, 0x0030.equ pm2_phex, 0x0034.equ pm2_pstr, 0x0038.equ pm2_pint8, 0x0050.equ pm2_newline, 0x0048 .org 0x2000 ljmp 0x3040 ;in case someone calls here... .org 0x2003 ;int0 interrupt ljmp int0_isr .org 0x200B ;timer0 interrupt (not used) reti .org 0x2013 ;int1 interrupt ljmp int1_isr .org 0x201B ;timer1 interrupt (timer1 needed for baud rate) reti .org 0x2023 ;uart interrupt ljmp uart_isr .org 0x202B ljmp timer2_isr ;timer2 interrupt .org 0x202E ajmp phex1 ;0x202E ajmp cout ;0x2030 ajmp cin ;0x2032 ajmp phex ;0x2034 ajmp phex16 ;0x2036 ajmp pstr ;0x2038 ajmp newline ;0x203A ajmp init_uart ;0x203C ajmp timer_setup ;0x203E ajmp add_new_event ;0x2040 ajmp flush ;0x2042; these symbols are grabbed from "drivers.asm" by the asi2asm script.; These interrupt routines really are part of the device drivers, but; they need to be in this separate file, so that can be included in; both code banks. You never know when an interrupt may happen, and; that means we need to have an identical copy of the interrupt service; routines in both banks. This "need_equ" is a simple kludge so that; these routines can use the variables from the drivers, and the equates; will automatically update if the memory is rearranged inside of; drivers.asm..need_equ debug drivers.asm.need_equ play_req_tail drivers.asm.need_equ play_req_head drivers.asm.need_equ play_req_size drivers.asm.need_equ play_req drivers.asm.need_equ num_blks_played drivers.asm.need_equ rx_buffer drivers.asm.need_equ rx_buf_head drivers.asm.need_equ rx_buf_tail drivers.asm.need_equ tx_buffer drivers.asm.need_equ tx_buf_head drivers.asm.need_equ tx_buf_tail drivers.asm.need_equ tx_intr_expected drivers.asm.need_equ cout_timeout drivers.asm.need_equ event_queue drivers.asm.need_equ event_queue_size drivers.asm.need_equ event_queue_head drivers.asm.need_equ event_queue_tail drivers.asm.need_equ hc165_load_pin drivers.asm.need_equ hc165_data_pin drivers.asm.need_equ hc165_clk_pin drivers.asm.need_equ pb_state_next drivers.asm.need_equ pb_state_play drivers.asm.need_equ pb_state_prev drivers.asm.need_equ pb_state_rand drivers.asm.need_equ pb_count_v_up drivers.asm.need_equ pb_count_v_dn drivers.asm.need_equ sw_timer_tick drivers.asm.need_equ sw_timer drivers.asm.need_equ clock_tick drivers.asm.need_equ sw_timer_mask drivers.asm.need_equ ide_timeout_count drivers.asm; registers implemented in the DRAM, IDE, and DMA controller.equ dram_page_cfg, 0xFF00.equ ide_data, 0xFF60.equ ide_err, 0xFF62.equ ide_sec_cnt, 0xFF64.equ ide_sector, 0xFF66.equ ide_cyl_lsb, 0xFF68.equ ide_cyl_msb, 0xFF6A.equ ide_head, 0xFF6C.equ ide_command, 0xFF6E.equ ide_status, 0xFF6E.equ ide_control, 0xFF7C.equ ide_astatus, 0xFF7C.equ ide_rst_bit, 0xFF40.equ ide_data_buf_msb, 0xFF43.equ dma_ide_dest, 0xFF22.equ dma_ide_count, 0xFF24.equ irq_dma_ide_ack,0xFF5C.equ dma_ide_go, 0xFF58.equ irq_ident, 0xFF50.equ irq_mask, 0xFF51.equ dma_mp3_src, 0xFF28.equ dma_mp3_count, 0xFF2A.equ dma_mp3_go, 0xFF59.equ irq_dma_mp3_ack,0xFF5D.equ irq_memcpy_ack, 0xFF5E;*****************************************************************;** **;** Serial Port **;** **;*****************************************************************uart_isr: push psw push acc jb ri, recv jb ti, xmit pop acc pop psw retirecv: clr ri mov a, rx_buf_head inc a cjne a, rx_buf_tail, recv_ok mov a, sbuf ;no space in the rx buffer... discard char pop acc pop psw retirecv_ok:mov rx_buf_head, a push dpl push dph mov dph, #rx_buffer >> 8 mov dpl, a mov a, sbuf movx @dptr, a pop dph pop dpl pop acc pop psw retixmit: clr ti mov a, tx_buf_tail cjne a, tx_buf_head, xmit_ok ;check for buffer empty ;If we got here, there is no data waiting to transmit. The ;uart won't generate more interrupts, so the cout routine had ;better check set ti. tx_buf_head is loaded with zero to that ;cout will know to set ti. clr tx_intr_expected pop acc pop psw retixmit_ok:inc a mov tx_buf_tail, a ;update tx_buf_tail while it's still in Acc. push dpl push dph mov dph, #tx_buffer >> 8 mov dpl, a movx a, @dptr mov sbuf, a pop dph pop dpl setb tx_intr_expected pop psw reticout: push psw xch a, r0 ;put char to send into r0 push acc ;keep r0 on stack mov cout_timeout, #150cout_wt:clr es ;1 jnb tx_intr_expected, cout_kickstart ;2 check if not transmittingcout2: mov a, tx_buf_head ;1 inc a ;1 cjne a, tx_buf_tail, cout4 ;2 check if buffer full setb es ;1 djnz cout_timeout, cout_wt ;2 ;if we get here, we've waited too long and something is wrong, ;so we'll reset the transmit queue and start overcout_kickstart: setb ti ;set ti in software since buffer is empty setb tx_intr_expected mov tx_buf_tail, #0 mov a, #1cout4: mov tx_buf_head, a ;update tx_buf_head push dph push dpl mov dph, #tx_buffer >> 8 mov dpl, a mov a, r0 movx @dptr, a pop dpl pop dph setb es mov r0, a ;restore r0 value and Acc pop acc xch a, r0 pop psw retflush: ; there should probably be a timeout of some sort jb tx_intr_expected, flush ret;Get a character from the receive buffer. C=0 if char recv, C=1 if nonecin: clr es mov a, rx_buf_tail cjne a, rx_buf_head, cin_ok ;check if buffer empty clr a setb es setb c retcin_ok: inc a mov rx_buf_tail, a push dpl push dph mov dpl, a mov dph, #rx_buffer >> 8 movx a, @dptr pop dph pop dpl setb es clr c ret; Highly code efficient resursive call phex contributed; by Alexander B. Alexandrov <abalex@cbr.spb.ru>phex: acall phex_bphex_b: swap a ;SWAP A will be twice => A unchangedphex1: push acc anl a, #15 add a, #0x90 ; acc is 0x9X, where X is hex digit da a ; if A to F, C=1 and lower four bits are 0..5 addc a, #0x40 da a acall cout pop acc retnewline:push acc ;print one newline mov a, #13 lcall cout mov a, #10 lcall cout pop acc retphex16: push acc mov a, dph acall phex mov a, dpl acall phex pop acc retpstr: clr a movc a, @a+dptr inc dptr jz pstr2 lcall cout sjmp pstrpstr2: ret .equ baud_const, 254 ;19200 baud at 7.3728 MHz cyrstalinit_uart: mov r0, #0 djnz r0, * ;brief delay, in case sbuf not empty djnz r0, * clr ea orl pcon, #10000000b ;set double baud rate anl tmod, #00001111b ;clear all timer1 bits in tmod orl tmod, #00100000b ;set timer1 as 8 bit auto reload clr tr1 ;make sure timer1 isn't running clr tf1 mov a, #baud_const mov th1, a ;set timer1 rate mov tl1, a mov scon, #01010000b ;config serial port (ri and ti cleared) mov tx_buf_head, #0 ;set up transmit buffer as empty mov tx_buf_tail, #0 setb tr1 ;start timer1 clr tx_intr_expected ;and no tx interrupt expected setb es ;enable serial port interrupt setb ea ;also turn on interrupts in general ret;*****************************************************************;** **;** MP3 Playback (STA013) **;** **;***************************************************************** ;when we get here, the STA013 chip is ready for more dataint0_mp3_dma: clr a mov dptr, #irq_dma_mp3_ack movx @dptr, a ;clear previous interrupt mov a, play_req_tail cjne a, play_req_head, play_next_req mov a, #255 mov play_req_tail, a ;no play requests pending mov play_req_head, a pop acc pop dph pop dpl pop psw retiplay_next_req: inc a cjne a, #play_req_size, play_next_req2 clr aplay_next_req2: mov play_req_tail, a rl a rl a add a, #play_req & 255 mov dpl, a clr a addc a, #play_req >> 8 mov dph, a ;now DPTR points to pending request movx a, @dptr mov r2, a ;read block to play into r2/r3
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -