📄 vs1001.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 + -