⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pm2_mp3.asm

📁 A MP3 Player Source Code, Enjoy it!
💻 ASM
📖 第 1 页 / 共 5 页
字号:
	mov	a, #(((eflash+1) >> 8) & 255)
	cjne	a, dph, erall2
	clr	c
	ret
erall_err:
	setb	c
	ret





;finds the next header in the external memory.
;  Input DPTR=point to start search (only MSB used)
;  Output DPTR=location of next module
;    C=set if a header found, C=clear if no more headers
find:	mov	dpl, #0
	clr	a
	movc	a, @a+dptr
	cjne	a, #0xA5, find3
	inc	dptr
	clr	a
	movc	a, @a+dptr
	cjne	a, #0xE5, find3
	inc	dptr
	clr	a
	movc	a, @a+dptr
	cjne	a, #0xE0, find3
	inc	dptr
	clr	a
	movc	a, @a+dptr
	cjne	a, #0xA5, find3
	mov	dpl, #0			;found one here!
	setb	c
	ret
find3:	mov	a, #(emem >> 8)
	cjne	a, dph, find4		;did we just check the end
	clr	c
	ret
find4:	inc	dph			;keep on searching
	sjmp	find




;************************************
;To make PAULMON2 able to write to other
;types of memory than RAM and flash rom,
;modify this "smart_wr" routine.  This
;code doesn't accept any inputs other
;that the address (dptr) and value (acc),
;so this routine must know which types
;of memory are in what address ranges
;************************************


;Write to Flash ROM or ordinary RAM.  Carry bit will indicate
;if the value was successfully written, C=1 if not written.


smart_wr:
	push	acc
	push	b
	mov	b, a
	;there is a flash rom, but is this address in it?
	mov	a, dph
	cjne	a, #(eflash >> 8), isfl3
	sjmp	wr_flash
isfl3:	jnc	wr_ram
	cjne	a, #(bflash >> 8), isfl4
	sjmp	wr_flash
isfl4:	jnc	wr_flash
	;sjmp	wr_ram

wr_ram: mov	a, b
	movx	@dptr, a	;write the value to memory
	clr	a
	movc	a, @a+dptr	;read it back from code memory
	clr	c
	subb	a, b
	jz	smwrok
	movx	a, @dptr	;read it back from data memory
	clr	c
	subb	a, b
	jz	smwrok
smwrbad:setb	c
	sjmp	smwrxit
smwrok: clr	c
smwrxit:pop	b
	pop	acc
	ret

wr_flash:
	mov	a, b
	lcall	prgm
	pop	b
	pop	acc
	ret




;---------------------------------------------------------;
;							  ;
;	Power-On initialization code and such...	  ;
;							  ;
;---------------------------------------------------------;

;first the hardware has to get initialized.

intr_return:
	reti

poweron:

	;set low power OTP eprom mode for philips 87C52
	mov	0xA2, #255

	clr	a
	mov	ie, a		;all interrupts off
	mov	ip, a
	mov	psw, #psw_init
	;clear any interrupt status, just in case the user put
	;"ljmp 0" inside their interrupt service code.
	acall	intr_return
	acall	intr_return
	cpl	a
	mov	p0, a
	mov	p1, a
	mov	p2, a
	mov	p3, a
	mov	sp, #stack
	acall	set_bank0
	acall	rst_devices

;initialize the serial port
	mov	a, #baud_const
	mov	th1, a
	mov	tl1, a
	mov	tmod, #0x21	;set timer #1 for 8 bit auto-reload
	mov	pcon, #0x80	;configure built-in uart
	mov	scon, #0x52
	setb	tr1		;start the baud rate timer

;now print out the nice welcome message

welcome:
	mov	r0, #24
welcm2: lcall	newline
	djnz	r0, welcm2
	mov	dptr, #logon1
	lcall	pcstr
	lcall	dir

;check for the user to press "S" to avoid auto-startup.
;allow a 1/2 second timeout, and accept and 'S' that's
;already in sbuf

; 0.5 seconds is 307200 instruction cycles at 7.3728 MHz
; 307200 = 256 * 240 * 5

aabort0:
	mov	r0, #0
aabort1:
	mov	r1, #240
aabort2:
	jnb	ri, aabort3
	clr	ri
	mov	a, sbuf
	lcall	upper
	cjne	a, #'S', aabort0 ;begin another 1/2 wait if not 'S'
	sjmp	stcode5		;don't do startup code if 'S'
aabort3:nop
	djnz	r1, aabort2
	djnz	r0, aabort1


stcode: mov	dptr, #bmem	 ;search for startup routines
stcode2:lcall	find
	jnc	stcode5
	mov	dpl, #4
	clr	a
	movc	a, @a+dptr
	cjne	a, #253, stcode4	;only startup code if matches B
	push	dph
	mov	a, #(stcode3 & 255)
	push	acc
	mov	a, #(stcode3 >> 8)
	push	acc
	mov	dpl, #64
	clr	a
	jmp	@a+dptr		;jump to the startup code
stcode3:pop	dph		;hopefully it'll return to here
stcode4:inc	dph
	mov	a, dph
	cjne	a, #((emem+1) >> 8) & 255, stcode2
stcode5:			;now we've executed all of 'em


warm_boot:
	clr	a
	mov	ie, a		;all interrupts off
	mov	ip, a
	acall	intr_return
	acall	intr_return
	mov	psw, #psw_init
	mov	sp, #stack
	acall	set_bank0
	mov	r0, #250
wb_ti:	jb	ti, wb_ti2
	nop
	djnz	r0, wb_ti
wb_ti2:
	mov	a, #baud_const	;initialize the serial port
	mov	th1, a
	mov	tl1, a
	mov	tmod, #0x21	;set timer #1 for 8 bit auto-reload
	mov	pcon, #0x80	;configure built-in uart
	mov	scon, #0x52
	setb	tr1		;start the baud rate timer

	mov	r6, #(pgm & 255)
	mov	r7, #(pgm >> 8)
	ljmp	menu












;---------------------------------------------------------;
;							  ;
;     More subroutines, but less frequent used, so	  ;
;     they're down here in the second 2k page.		  ;
;							  ;
;---------------------------------------------------------;



;this twisted bit of code looks for escape sequences for
;up, down, left, right, pageup, and pagedown, as well
;as ordinary escape and ordinary characters.  Escape
;sequences are required to arrive with each character
;nearly back-to-back to the others, otherwise the characters
;are treated as ordinary user keystroaks.  cin_filter
;returns a single byte when it sees the multi-byte escape
;sequence, as shown here.

; return value	 key	      escape sequence
;   11 (^K)	 up	      1B 5B 41
;   10 (^J)	 down	      1B 5B 42
;   21 (^U)	 right	      1B 5B 43
;    8 (^H)	 left	      1B 5B 44
;   25 (^Y)	 page up      1B 5B 35 7E
;   26 (^Z)	 page down    1B 5B 36 7E

.equ	esc_char, 27

cin_filter:
	jnb	ri, cinf1
	lcall	cin
	cjne	a, #esc_char, cinf_end
	;if esc was already in sbuf, just ignore it
cinf1:	lcall	cin
	cjne	a, #esc_char, cinf_end
cinf2:	acall	cinf_wait
	jb	ri, cinf4
	mov	a, #esc_char
	ret			;an ordinary ESC

cinf4:	;if we get here, it's a control code, since a character
	;was received shortly after receiving an ESC character
	lcall	cin
	cjne	a, #'[', cinf_consume
	acall	cinf_wait
	jnb	ri, cin_filter
	lcall	cin
cinf5a: cjne	a, #'A', cinf5b
	mov	a, #11
	ret
cinf5b: cjne	a, #'B', cinf5c
	mov	a, #10
	ret
cinf5c: cjne	a, #'C', cinf5d
	mov	a, #21
	ret
cinf5d: cjne	a, #'D', cinf5e
	mov	a, #8
	ret
cinf5e: cjne	a, #0x35, cinf5f
	sjmp	cinf8
cinf5f: cjne	a, #0x36, cinf5g
	sjmp	cinf8
cinf5g: sjmp	cinf_consume		;unknown escape sequence

cinf8:	;when we get here, we've got the sequence for pageup/pagedown
	;but there's one more incoming byte to check...
	push	acc
	acall	cinf_wait
	jnb	ri, cinf_restart
	lcall	cin
	cjne	a, #0x7E, cinf_notpg
	pop	acc
	add	a, #228
cinf_end: ret
cinf_restart:
	pop	acc
	sjmp	cin_filter
cinf_notpg:
	pop	acc
;unrecognized escape... eat up everything that's left coming in
;quickly, then begin looking again
cinf_consume:
	acall	cinf_wait
	jnb	ri, cin_filter
	lcall	cin
	cjne	a, #esc_char, cinf_consume
	sjmp	cinf2

;this thing waits for a character to be received for approx
;4 character transmit time periods.  It returns immedately
;or after the entire wait time.	 It does not remove the character
;from the buffer, so ri should be checked to see if something
;actually did show up while it was waiting
	.equ	char_delay, 4		;number of char xmit times to wait
cinf_wait:
	mov	a, r2
	push	acc
	mov	r2, #char_delay*5
cinfw2: mov	a, th0
cinfw3: jb	ri, cinfw4
	inc	a
	jnz	cinfw3
	djnz	r2, cinfw2
cinfw4: pop	acc
	mov	r2, a
	ret




pint8u: ;prints the unsigned 8 bit value in Acc in base 10
	push	b
	push	acc
	sjmp	pint8b

pint8:	;prints the signed 8 bit value in Acc in base 10
	push	b
	push	acc
	jnb	acc.7, pint8b
	mov	a, #'-'
	lcall	cout
	pop	acc
	push	acc
	cpl	a
	add	a, #1
pint8b: mov	b, #100
	div	ab
	setb	f0
	jz	pint8c
	clr	f0
	add	a, #'0'
	lcall	cout
pint8c: mov	a, b
	mov	b, #10
	div	ab
	jnb	f0, pint8d
	jz	pint8e
pint8d: add	a, #'0'
	lcall	cout
pint8e: mov	a, b
	add	a, #'0'
	lcall	cout
	pop	acc
	pop	b
	ret



	;print 16 bit unsigned integer in DPTR, using base 10.
pint16u:	;warning, destroys r2, r3, r4, r5, psw.5
	push	acc
	mov	a, r0
	push	acc
	clr	psw.5
	mov	r2, dpl
	mov	r3, dph

pint16a:mov	r4, #16		;ten-thousands digit
	mov	r5, #39
	acall	pint16x
	jz	pint16b
	add	a, #'0'
	lcall	cout
	setb	psw.5

pint16b:mov	r4, #232	;thousands digit
	mov	r5, #3
	acall	pint16x
	jnz	pint16c
	jnb	psw.5, pint16d
pint16c:add	a, #'0'
	lcall	cout
	setb	psw.5

pint16d:mov	r4, #100	;hundreds digit
	mov	r5, #0
	acall	pint16x
	jnz	pint16e
	jnb	psw.5, pint16f
pint16e:add	a, #'0'
	lcall	cout
	setb	psw.5

pint16f:mov	a, r2		;tens digit
	mov	r3, b
	mov	b, #10
	div	ab
	jnz	pint16g
	jnb	psw.5, pint16h
pint16g:add	a, #'0'
	lcall	cout

pint16h:mov	a, b		;and finally the ones digit
	mov	b, r3
	add	a, #'0'
	lcall	cout

	pop	acc
	mov	r0, a
	pop	acc
	ret

;ok, it's a cpu hog and a nasty way to divide, but this code
;requires only 21 bytes!  Divides r2-r3 by r4-r5 and leaves
;quotient in r2-r3 and returns remainder in acc.  If Intel
;had made a proper divide, then this would be much easier.

pint16x:mov	r0, #0
pint16y:inc	r0
	clr	c
	mov	a, r2
	subb	a, r4
	mov	r2, a
	mov	a, r3
	subb	a, r5
	mov	r3, a
	jnc	pint16y
	dec	r0
	mov	a, r2
	add	a, r4
	mov	r2, a
	mov	a, r3
	addc	a, r5
	mov	r3, a
	mov	a, r0
	ret



;pcstr prints the compressed strings.  A dictionary of 128 words is
;stored in 4 bit packed binary format.	When pcstr finds a byte in
;a string with the high bit set, it prints the word from the dictionary.
;A few bytes have special functions and everything else prints as if
;it were an ordinary string.

; special codes for pcstr:
;    0 = end of string
;   13 = CR/LF
;   14 = CR/LF and end of string
;   31 = next word code should be capitalized

pcstr:	push	acc
	mov	a, r0
	push	acc
	mov	a, r1
	push	acc
	mov	a, r4
	push	acc
	setb	psw.1
	setb	psw.5
pcstr1: clr	a
	movc	a, @a+dptr
	inc	dptr
	jz	pcstr2
	jb	acc.7, decomp
	anl	a, #0x7F
pcstrs1:cjne	a, #13, pcstrs2
	lcall	newline
	setb	psw.1
	sjmp	pcstr1
pcstrs2:cjne	a, #31, pcstrs3
	clr	psw.5
	sjmp	pcstr1
pcstrs3:cjne	a, #14, pcstrs4
	lcall	newline
	sjmp	pcstr2
pcstrs4:
	clr	psw.1
	lcall	cout
	sjmp	pcstr1
pcstr2: pop	acc
	mov	r4, a
	pop	acc
	mov	r1, a
	pop	acc
	mov	r0, a
	pop	acc
	ret

;dcomp actually takes care of printing a word from the dictionary

; dptr = position in packed words table
; r4=0 if next nibble is low, r4=255 if next nibble is high

decomp: anl	a, #0x7F
	mov	r0, a		;r0 counts which word
	jb	psw.1, decomp1	;avoid leading space if first word
	lcall	space
decomp1:clr	psw.1
	push	dpl
	push	dph
	mov	dptr, #words
	mov	r4, #0
	mov	a, r0
	jz	dcomp3
	;here we must seek past all the words in the table
	;that come before the one we're supposed to print
	mov	r1, a
dcomp2: acall	get_next_nibble
	jnz	dcomp2
	;when we get here, a word has been skipped... keep doing
	;this until we're pointing to the correct one
	djnz	r1, dcomp2
dcomp3: ;now we're pointing to the correct word, so all we have
	;to do is print it out
	acall	get_next_nibble
	jz	dcomp_end
	cjne	a, #15, dcomp4
	;the character is one of the 12 least commonly used
	acall	get_next_nibble
	inc	a
	movc	a, @a+pc
	sjmp	dcomp5
	.db	"hfwgybxvkqjz"
dcomp4: ;the character is one of the 14 most commonly used
	inc	a
	movc	a, @a+pc
	sjmp	dcomp5
	.db	"etarnisolumpdc"
dcomp5: ;decide if it should be uppercase or lowercase
	mov	c, psw.5
	mov	acc.5, c
	setb	psw.5
	cjne	r0, #20, dcomp6
	clr	acc.5
dcomp6: cjne	r0, #12, dcomp7
	clr	acc.5
dcomp7: lcall	cout
	sjmp	dcomp3
dcomp_end:
	pop	dph
	pop	dpl
	ajmp	pcstr1

get_next_nibble:	;...and update dptr and r4, of course
	clr	a
	movc	a, @a+dptr
	cjne	r4, #0, gnn2

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -