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