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

📄 vs1001.c

📁 Yet Another MP3 Player source code. It can be usefull as reference source for any project.
💻 C
字号:
/*
  Copyright (C) 2001 Jesper Hansen <jesperh@telia.com>.

  Rewritten by:	Nikolai Vorontsov <nickviz@mail.be>

  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.
*/

#include <io.h>
#include <progmem.h>
#include <interrupt.h>

#include "vs1001.h"
#include "delay.h"
#include "uart.h"


//****************************************************************************
//**
//** Init and helper functions
//**
//****************************************************************************

// setup I/O pins and directions for communicating with the VS1001
void vs1001_init_io(void)
{
	u08 dummy;

	// 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

	// set the /Reset pin hi
//	sbi( RESET_PORT-1, RESET_PIN); 		// pin output
//	sbi( RESET_PORT,   RESET_PIN); 		// output hi

	// setup serial data interface :
	// clock = f/4
	// select clock phase positive going in middle of data
	// master mode
	// enable SPI

	// 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

	cbi(PORTB, PB7);					// set SCK lo
	sbi(DDRB, PB7);						// set SCK as output

	outp((1<<MSTR) | (1<<SPE), SPCR);	// 2 MHz clock
//	outp((1<<MSTR) | (1<<SPE) | (1<<SPR0), SPCR); // 0,5 MHz clock

	dummy = inp(SPSR);					// clear status
}


// reset the VS1001
void vs1001_reset(bool bLoud)
{
	delay10(2000);						// wait 20 mS
	vs1001_write(VS1001_MODE, 0x0004);	// set SW reset bit
	delay10us();						// wait 10 uS

	loop_until_bit_is_set(DREQ_PORT - 2, DREQ_PIN); // wait for DREQ
	vs1001_nulls(32);

	// set CLOCKF to compensate for a non 24,576 MHz x-tal
	vs1001_write(VS1001_CLOCKF, F_VS1001);
	vs1001_write(VS1001_MODE, 0x0080 * (bLoud == true));	// set sound enchance bit
	vs1001_nulls(32);
}


// send a number of zero's to the VS1001
void vs1001_nulls(u16 nNulls)
{
	while (nNulls--)
		vs1001_send_data(0);
}


//
// read a word from the VS1001 Control registers
//
u16 vs1001_read(u08 address)
{
	cli();
	cbi(MP3_PORT, MP3_PIN);			// xCS lo

	outp(VS1001_READ, SPDR);
	loop_until_bit_is_set(SPSR, SPIF);    

	outp(address, SPDR);
	loop_until_bit_is_set(SPSR, SPIF);    

	outp(0x00, SPDR);
	loop_until_bit_is_set(SPSR, SPIF);    

	union u16convert Data;
	Data.bytes.high = inp(SPDR);

	outp(0x00, SPDR);
	loop_until_bit_is_set(SPSR, SPIF);    

	Data.bytes.low = inp(SPDR);

	sbi( MP3_PORT, MP3_PIN);		// xCS hi
	sei();

	//this is absolutely neccessary!
	delay10us(); // wait 10 microseconds after sending data to control port
	
	return Data.value;
}


//
// write word to the VS1001 Control registers
//
void vs1001_write(u08 address, u16 data)
{
	cli();
	cbi(MP3_PORT, MP3_PIN);			// xCS lo

	outp(VS1001_WRITE, SPDR);
	loop_until_bit_is_set(SPSR, SPIF);    

	outp(address, SPDR);
	loop_until_bit_is_set(SPSR, SPIF);    

	union u16convert Data;
	Data.value = data;
	outp(Data.bytes.high, SPDR);
	loop_until_bit_is_set(SPSR, SPIF);    
	
	outp(Data.bytes.low, SPDR);
	loop_until_bit_is_set(SPSR, SPIF);    
	
	sbi(MP3_PORT, MP3_PIN);			// xCS hi
	sei();

	//this is absolutely neccessary!
	delay10us(); // wait 10 microseconds after sending data to control port
}


/****************************************************************************
**
** MPEG Data Stream
**
****************************************************************************/

//
// send a byte to the VS1001 MPEG stream
//
void vs1001_send_data(u08 b)
{
	cli();
	sbi(BSYNC_PORT, BSYNC_PIN);		 	// byte sync hi

	outp(b, SPDR);						// send data

	asm volatile("nop");				// have to wait till first bit passed
	asm volatile("nop");				// ~8/2MHz -> 4 ticks -> 4 NOPs
	asm volatile("nop");				// 3 NOPs are not enough!
	asm volatile("nop");

	cbi(BSYNC_PORT, BSYNC_PIN);			// byte sync lo

	loop_until_bit_is_set(SPSR, SPIF);	// wait for data to be sent
	sei();
}


//
// send a burst of 32 data bytes to the VS1001 MPEG stream
//
void vs1001_send_32(u08 *p)
{
	register u08 i;
	
	cli();
	sbi(MP3_PORT, MP3_PIN);				// xCS hi
	sbi(BSYNC_PORT, BSYNC_PIN); 		// byte sync hi
	for (i = 0; i < 32; i++)
	{
///		sbi(BSYNC_PORT, BSYNC_PIN);		// byte sync hi
		outp(*p++, SPDR);				// send data
///		asm volatile("nop");
///		asm volatile("nop");
///		asm volatile("nop");
///		asm volatile("nop");
///		cbi(BSYNC_PORT, BSYNC_PIN);		// byte sync lo

		loop_until_bit_is_set(SPSR, SPIF); // wait for data to be sent
	}
	cbi(BSYNC_PORT, BSYNC_PIN); 		// byte sync lo
	sei();
}


// Set the VS1001 volume
void vs1001_setvolume(u08 left, u08 right)
{
	union u16convert Data;
	Data.bytes.high = left;
	Data.bytes.low = right;
	vs1001_write(VS1001_VOLUME, Data.value);
}


#ifdef VS1001_READ_MULTIPLE
//
// read one or more word(s) from the VS1001 Control registers
//
void vs1001_read(u08 address, u16 count, u16 *pData)
{
	cli();
	cbi(MP3_PORT, MP3_PIN);	// xCS lo

	outp(VS1001_READ, SPDR);
	loop_until_bit_is_set(SPSR, SPIF);    

	outp(address, SPDR);
	loop_until_bit_is_set(SPSR, SPIF);    

	while (count--)
	{
		outp(0x00, SPDR);
		loop_until_bit_is_set(SPSR, SPIF);    
		*pData = ((u16)inp(SPDR)) << 8;

		outp(0x00, SPDR);
		loop_until_bit_is_set(SPSR, SPIF);    
		*pData |= inp(SPDR);

		pData++;
	}

	sbi( MP3_PORT, MP3_PIN);	// xCS hi
	sei();

	//this is absolutely neccessary!
	delay10us(); // wait 10 microseconds after sending data to control port
}
#endif

#ifdef VS1001_WRITE_MULTIPLE
//
// write one or more word(s) to the VS1001 Control registers
//
void vs1001_write(u08 address, u16 count, u16 *pData)
{
	cli();
	cbi(MP3_PORT, MP3_PIN);			// xCS lo

	outp(VS1001_WRITE, SPDR);
	loop_until_bit_is_set(SPSR, SPIF);    

	outp(address, SPDR);
	loop_until_bit_is_set(SPSR, SPIF);    

	while (count--)
	{
		outp((u08)((*pData) >> 8), SPDR);
		loop_until_bit_is_set(SPSR, SPIF);    
		
		outp((u08)(*pData), SPDR);
		loop_until_bit_is_set(SPSR, SPIF);    
	
		pData++;
	}

	sbi(MP3_PORT, MP3_PIN);			// xCS hi
	sei();

	//this is absolutely neccessary!
	delay10us(); // wait 10 microseconds after sending data to control port
}

#endif

⌨️ 快捷键说明

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