.f:rom: http://people.ece.cornell.edu/land/courses/ece4760/FinalProjects/s2011/yl478_clt67/yl478_clt67/yl478_clt67_files/displaycontrol/mp3_VS1011E.c
/* Functions for VS1011E-L MP3 decoder
modified from the VS1033D decoder demo at http://frank.circleofcurrent.com/musicclock/
we changed the functions so that playback will not block in a while loop, but the
VS_playfile function is called repeatedly from main.c
We also changed the values that are written into the registers of the VS1011E-L
Our SPI speeds are also different as we are using a 16 MHz clock for the microcontroller
as compared to the demo's 8 MHz clocked microcontroller.
This file is free software; you can redistribute it and/or modify
it under the terms of either the GNU General Public License version 2
or the GNU Lesser General Public License version 2.1, both as
published by the Free Software Foundation.
*/
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <stdio.h>
#include "fatfs/ff.h"
#include "fatfs/diskio.h"
#include "uart.h"
#include "SDcard_audio.h"
typedef enum {
MP3_REG_MODE = 0x00,
MP3_REG_CLOCKF = 0x03,
MP3_REG_VOL = 0x0B,
} mp3_register_t;
//wait for the decoder to be ready
inline void mp3_waitReady(uint8_t cnt) {
for(uint8_t i = 0; i < cnt; i++)
{
_delay_us(10);
if (bit_is_clear(MP3_PORTINPUT, MP3_PIN_DREQ)) break;
}
loop_until_bit_is_set(MP3_PORTINPUT, MP3_PIN_DREQ);
}
inline uint8_t mp3_spi(uint8_t data)
{
SPDR = data; // send
loop_until_bit_is_set(SPSR, SPIF); // wait until sent
return SPDR; // get reply
}
//write data in to register addr
void mp3_writeReg(mp3_register_t addr, uint16_t data) {
spi_slow();
MP3_PORTOUTPUT &= ~_BV(MP3_PIN_CS); // select
mp3_spi(0b00000010); // write command
mp3_spi(addr); // send address
mp3_spi((data & 0xFF00) >> 8); // send data MSB first
mp3_spi(data & 0x00FF);
MP3_PORTOUTPUT |= _BV(MP3_PIN_CS); // deselect
spi_fast();
mp3_waitReady(10);
}
//send a packet of MP3 data from the buffer on the microcontroller to the VS1011E-L
void mp3_playPacket(uint8_t* buffer, uint8_t length) {
spi_slow();
loop_until_bit_is_set(MP3_PORTINPUT, MP3_PIN_DREQ); // wait for ready
MP3_PORTOUTPUT &= ~_BV(MP3_PIN_DCS); // select
for (uint8_t i = 0; i < length; i++)
{
mp3_spi(buffer[i]);
}
MP3_PORTOUTPUT |= _BV(MP3_PIN_DCS); // deselect
spi_fast();
}
//play the file
mp3_playStatus_t VS_playfile(FIL* file) {
uint8_t buff[32];
UINT read;
//fprintf(stdout,"VS DREQ %d\r\n", MP3_PORTINPUT & _BV(MP3_PIN_DREQ));
if (MP3_PORTINPUT & _BV(MP3_PIN_DREQ)) {
f_read(file, buff, 32, &read); // read the file
mp3_playPacket(buff, read); // play the sound
if (read != 32) return PLAYSTATUS_ENDOFFILE;
} else return PLAYSTATUS_BUSY;
return PLAYSTATUS_OK;
}
//initialize the VS-1011E-L by writing settings to its registers
void init_VS() {
spi_slow();
// DREQ is input, no pull-up
MP3_PORTOUTPUT &= ~_BV(MP3_PIN_DREQ);
_delay_ms(100); // slight delay, let VS1011 finish boot initialization
MP3_PORTOUTPUT |= _BV(MP3_PIN_RST); // bring out of reset, get ready
mp3_waitReady(10);
mp3_writeReg(MP3_REG_MODE, 0b0000100000000010); // the mode setting for the decoder
mp3_writeReg(MP3_REG_CLOCKF, 0x9800); // this is 12.288MHz XTALI with clock doubler
mp3_writeReg(MP3_REG_VOL, 0); // attenuation = 0 for maximum volume
}
No comments:
Post a Comment