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

📄 vs1001.asm

📁 使用AVR单片机M162制做的MP3,这是整机的代码.可做参考.
💻 ASM
字号:
/* ***********************************************************************
**
**  Copyright (C) 2002  Jesper Hansen <jesperh@telia.com> and 
**			Romuald Bialy (MIS) <romek_b@o2.pl>.
**
**
**  Yampp-7/USB - low level support library
**
**
*************************************************************************
**
**   This file is part of the yampp system.
**
**  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.
**
*************************************************************************
**
**  Revision History
**
**  when         what  who	why
**
**  2002-09-22   1.0   MIS      initial public release
**
*********************************************************************** */

#define __ASSEMBLER__ 1
#define __SFR_OFFSET 0
#include <avr/io.h>


//
// VS1001 I/O pins
//

	#define MP3_PORT	PORTB
	#define BSYNC_PORT	PORTB    
	#define RESET_PORT	PORTB
	#define DREQ_PORT	PORTD

	#define MP3_PIN		PB3	// MP3 control bit
	#define	BSYNC_PIN	PB2	// BSYNC signal
	#define RESET_PIN	PB1	// RESET (also for CF card)
	#define DREQ_PIN	PD0	// DREQ signal

//
// VS1001 commands
//
#define VS1001_READ	0x03
#define VS1001_WRITE	0x02

//
// VS1001 registers
//
#define VS1001_MODE	0x00
#define VS1001_STATUS	0x01
#define VS1001_INTFCTLH	0x02
#define VS1001_CLOCKF	0x03
#define VS1001_PLAYTIME	0x04
#define VS1001_AUDATA	0x05
#define VS1001_VOLUME	0x0B


	.section	.text

.extern delay10

//
// local functions
//
;						r24			r22
; void startSCI(u08 mode, u08 address)
startSCI:
		cbi	MP3_PORT,MP3_PIN		; activate VS1001 Chip Select
		rcall	spi_tx_rx			; send the mode (READ or WRITE)
		mov	r24,r22				; get address
		rjmp	spi_tx_rx			; send address

; void endSCI(void)
endSCI:
 		sbi 	MP3_PORT, MP3_PIN		; set CS hi
;		clr	r25				; do a 
;		ldi	r24,5				; 10 uS
		rjmp	delay10				; delay


spi_tx_rx:
		out 	SPDR, r24			; send over SPI
vspi1:	sbis 	SPSR,SPIF			; while flag is clear
 		rjmp 	vspi1				; wait for SPI
 		in 	r24, SPDR			; and get input data
		ret					; done


//
// global functions
//

;						r24
;void vs1001_send_data(u08 data)
	.global vs1001_send_data
vs1001_send_data:	
		cli
 		sbi		BSYNC_PORT,BSYNC_PIN	; start BSYNC
		out 	SPDR, r24				; send over SPI
		nop
		nop
		nop
 		cbi		BSYNC_PORT,BSYNC_PIN	; stop BSYNC
vssd1:	sbis 	SPSR,SPIF				; while flag is clear
 		rjmp 	vssd1					; wait for SPI
		sei
 		ret
 



;						r24		
;u16 vs1001_read(u08 address)
	.global vs1001_read
vs1001_read:
		mov	r22,r24				; address in r22
		ldi	r24,VS1001_READ
		rcall 	startSCI			; start SCI communication

  		clr	r24
 		rcall	spi_tx_rx			; get a byte
		mov	r23,r24
		
  		clr	r24
 		rcall	spi_tx_rx			; get a byte
		mov	r22,r24

  		rcall	endSCI
  		
  		movw	r24,r22				; get back word
  		ret


;						r24			r23/r22
;void vs1001_write(u08 address, u16 data)
	.global vs1001_write

vs1001_write:
		mov	r18,r22				; save register
		mov	r22,r24				; address in r22
		ldi	r24,VS1001_WRITE
		rcall 	startSCI			; start SCI communication

  		mov	r24,r23				; get hi byte
 		rcall	spi_tx_rx			; send it
  		mov	r24,r18				; get lo byte
 		rcall	spi_tx_rx			; send it

  		rjmp	endSCI




#ifdef VS1001_READ_MULTIPLE

;					r24			r22			r21/r20
;void vs1001_readmultiple(u08 address, u08 count, u16 *pData)
	.global vs1001_readmultiple

vs1001_readmultiple:
		mov	r18,r22				; count in r18
		mov	r22,r24				; save address
		
		movw 	r30,r20				; pData in Z

		ldi	r24,VS1001_READ
		rcall 	startSCI			; start SCI communication
 
vs_rd1:
  		clr	r24
 		rcall	spi_tx_rx			; send NULL and get input data
 		std	Z+1,r24				; store in *pData+1
 		rcall	spi_tx_rx			; send NULL and get input data
 		st	Z,r24				; store in *pData
  		adiw 	r30,2				; bump pointer
		dec	r18				; dec loop count
		brne	vs_rd1 				; and do again
 
 		rjmp	endSCI

#endif

#ifdef VS1001_WRITE_MULTIPLE

;					r24			r22			r21/r20
;void vs1001_writemultiple(u08 address, u08 count, u16 *pData)
	.global vs1001_writemultiple

vs1001_writemultiple:
		mov	r18,r22				; count in r18
		mov	r22,r24				; save address
		
		mov 	r31,r21				; pData in Z
		mov 	r30,r20

		ldi	r24,VS1001_READ
		rcall 	vs1001_startSCI			; start SCI communication
vs_wr1:
  		ldd	r24,Z+1				; get hi byte
 		rcall	spi_tx_rx			; send it
  		ld	r24,Z				; get lo byte
 		rcall	spi_tx_rx			; send it
  		adiw 	r30,2				; bump pointer
		dec	r18				; dec loop count
		brne	vs_wr1 				; and do again
 
 		rjmp	endSCI
#endif



	
; send a 32 byte block of data to the VS1001 	
; using the SPI port. 							

;					r25/r24
;void vs1001_send32(char *pData);

	.global vs1001_send32

vs1001_send32:
		mov 	r31,r25				; transfer input pointer to Z
		mov 	r30,r24
 		ldi	r25,32				; init loop counter
vs32_2:
		ld 	r24,Z+				; get a byte and inc pointer
		rcall	vs1001_send_data
	
 		dec	r25				; dec loop counter
 		brne	vs32_2				; loop if not zero
 		ret
 


;					r25/r24
; void vs1001_nulls(u16 nNulls)
	.global vs1001_nulls
	
vs1001_nulls:
		movw	r30,r24	
vs1001_nulls_2:		
		clr	r24		
		rcall	vs1001_send_data
		sbiw	r30,1
		brne	vs1001_nulls_2
		ret

;			r24		r22		
;void vs1001_setvolume(u08 volume, s08 balance)
	.global vs1001_setvolume
vs1001_setvolume:
		mov	r0,r22				; save balance value
		mov	r23,r24				; r23 = left volume
		sbrs	r0,7				; skip if balance < 0
		add	r23,r0				; add balance value

		neg	r0				; negate balance (signed value)
		mov	r22,r24				; r22 = right volume
		sbrs	r0,7				; skip if balance < 0
		add	r22,r0				; add balance value

		ldi	r24,11				; volume register
		rjmp	vs1001_write



;void vs1001_init_io(void)
	.global	vs1001_init_io
vs1001_init_io:
	
	; setup BSYNC
	
	cbi	BSYNC_PORT, BSYNC_PIN		; output low
	sbi	BSYNC_PORT-1, BSYNC_PIN		; pin is output for BSYNC

	; set the MP3/ChipSelect pin hi
	sbi	MP3_PORT, MP3_PIN 		; output hi (deselect MP3)
	sbi	MP3_PORT-1, MP3_PIN		; pin output for xCS

#ifdef YAMPP7
	; set the RESET pin hi
	sbi	RESET_PORT, RESET_PIN 		; output hi 
	sbi	RESET_PORT-1, RESET_PIN		; pin output
#endif

	; setup serial data I/O pins
	sbi	DDRB, PB5			; set MOSI a output
	sbi	DDRB, PB4			; SS must be output for Master mode to work

	sbi	PORTB, PB6			; activate pull-up on MISO line 
	cbi	PORTB, PB7			; set SCK lo
	sbi	DDRB,  PB7			; set SCK as output


	; setup serial data interface 
	; select clock phase positive going in middle of data
	; master mode
	; enable SPI
	; speed is CPUclock/2

	ldi		r24,(1<<MSTR) | (1<<SPE);	; Master Mode, Enable SPI, fCPU/4 clock
	out		SPCR,r24

	ldi		r24,1				; double speed bit
 	out		SPSR,r24
	
	in	r24,SPSR				; clear status
	ret




.comm vs1001_xtalcomp,2			; compensation value for the VS1001 xtal

;					r24
;void vs1001_reset(void)
	
	.global	vs1001_reset
	
vs1001_reset:

		ldi	r25,8
		clr	r24
		rcall	vs1001_nulls
		
		ldi	r24,VS1001_MODE
		clr	r23
		ldi	r22,4			; RESET value
		rcall	vs1001_write
				
		rcall	delay10			; 10us delay
w_dreq:
		sbis	DREQ_PORT-2,DREQ_PIN	;  wait for DREQ
		rjmp	w_dreq	

		clr	r25
		ldi	r24,32;
		rcall	vs1001_nulls

		; set CLOCKF to compensate for a non 24,576 MHz x-tal
		ldi	r24,VS1001_CLOCKF
		lds	r23,vs1001_xtalcomp+1		
		lds	r22,vs1001_xtalcomp		
		rcall	vs1001_write
		
		; force VS1001 doubler
		ldi	r24,VS1001_INTFCTLH
		ldi	r23,0x80
		ldi	r22,0x08
		rcall	vs1001_write

		ret		



;				   r25/r24
; void vs1001_setcomp(u16 comp)
.global vs1001_setcomp
vs1001_setcomp:
		sts	vs1001_xtalcomp,r24
		sts	vs1001_xtalcomp+1,r25
		ret

⌨️ 快捷键说明

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