I’m trying to use a VS1053 breakout board from sparkfun to play mp3s. I’m having some trouble getting this all to work though. I’ve copied the VS1002 class from the Embedded Master SDK and used the same method of sending data as in the MP3Example class but I don’t get audio. The method to send a sine wave works, but sending an mp3 file doesn’t.
I had tried a number of mp3 files at different bitrates but none of them would play back. After some testing I found that changing the value the chip is initialized with from 0x800 to 0xC00 allowed me to hear a 16kbps mp3 clearly and would play through to the end. When I try a 128kbps mp3 I’ll get anywhere from 1-4 seconds of audio, and then it cuts off and I’ll get a low clicking type noise until data is finished being sent to the chip.
I’ve tried adapting the VS1053 class from the ChipworkX SDK but I’m very new to this type of programming and not very familiar with this hardware so I’m not really sure what I need to change to get it to work with this board. Here’s my modified VS1002 class as well as the code I’m using to play a file.
private const int BufferLength = 2048;
static byte[] Buffer = new byte[BufferLength];
private static void PlayMusic()
{
Directory.SetCurrentDirectory(@"\USB0\Test");
var FileName = "440Hz_44100Hz_16bit_30sec.mp3";
VS1002.Initialize();
using (var file = File.Open(FileName, FileMode.Open, FileAccess.Read))
{
var read = 0;
do
{
read = file.Read(Buffer, 0, BufferLength);
VS1002.SendData(Buffer);
} while (read > 0);
}
}
public static class VS1002
{
static private SPI.Configuration conf = new SPI.Configuration(Cpu.Pin.GPIO_NONE, false, 0, 0, false, true, 3000, SPI.SPI_module.SPI1);
static private SPI mySPI;
static private OutputPort SCI;
static private OutputPort SDI;
static private OutputPort RESET;
static private InputPort DREQ;
static private bool isInitialized = false;
static private byte[] block = new byte[32];
static private byte SPIWriteReadByte(byte ch)
{
byte[] CH = new byte[1];
byte[] CH1 = new byte[1];
CH[0] = ch;
mySPI.WriteRead(CH, CH1);
return CH1[0];
}
static public void SCI_Write(Byte address, UInt16 data)
{
SCI.Write(false);
Thread.Sleep(10);
SPIWriteReadByte(0x02);
SPIWriteReadByte(address);
SPIWriteReadByte((byte)(data >> 8));
SPIWriteReadByte((byte)data);
SCI.Write(true);
}
static public UInt16 SCI_Read(byte address)
{
UInt16 temp;
SCI.Write(false);
Thread.Sleep(10);
SPIWriteReadByte(0x03);
SPIWriteReadByte(address);
temp = SPIWriteReadByte(0);
temp <<= 8;
temp += SPIWriteReadByte(0);
SCI.Write(true);
return temp;
}
// Let VS1002 sends Sine Wave for testing purposes.
static public void SendSineWaveP(Byte pitch)
{
SCI_Write(0, 0x0c20);
SDI.Write(false);
Thread.Sleep(10);
SPIWriteReadByte(0x53);
SPIWriteReadByte(0xEF);
SPIWriteReadByte(0x6E);
SPIWriteReadByte(pitch);
SPIWriteReadByte(0);
SPIWriteReadByte(0);
SPIWriteReadByte(0);
SPIWriteReadByte(0);
SDI.Write(true);
Thread.Sleep(10);
}
public static void Shutdown()
{
SCI.Dispose();
SDI.Dispose();
RESET.Dispose();
DREQ.Dispose();
mySPI.Dispose();
isInitialized = false;
}
public static void Initialize()
{
// Initialize Pins
if (isInitialized)
Shutdown();
mySPI = new SPI(conf);
SCI = new OutputPort(USBizi.Pins.E38x, false);
SDI = new OutputPort(USBizi.Pins.E43x, false);
RESET = new OutputPort(USBizi.Pins.E37x, false);
DREQ = new InputPort(USBizi.Pins.E36x, false, Port.ResistorMode.PullUp);
isInitialized = true;
////
RESET.Write(false);
SCI.Write(true);
SDI.Write(true);
Thread.Sleep(100);
// delay 100ms
RESET.Write(true);
while (DREQ.Read() == false) ;
Thread.Sleep(100);
////SCI_Write(0x00, 0x800);
SCI_Write(0x00, 0xC00);
SCI_Write(0x3, 0x98 << 8);
Thread.Sleep(300);
SCI_Write(0xB, 0x4B << 8 | 0x4B); // volume
Thread.Sleep(300);
if (SCI_Read(0xB) != (0x4B << 8 | 0x4B))
{
throw new Exception("Failed to initialize VS1002 encoder");
}
}
public static void SendData(byte[] data)
{
Int32 size = data.Length - data.Length % 32;
SDI.Write(false);
for (int i = 0; i < size; i += 32)
{
while (DREQ.Read() == false) ; // wait till done
Array.Copy(data, i, block, 0, 32);
mySPI.Write(block);
}
SDI.Write(true);
}
}