So how does the SD card stuff work anyway?
#1
Posted 14 August 2011 - 10:09 PM
#2
Posted 16 August 2011 - 11:08 PM
#3
Posted 19 August 2011 - 01:46 AM
#4
Posted 21 August 2011 - 01:50 PM
#5
Posted 26 August 2011 - 02:33 AM
On the Netduino Plus the SD card sits on the SPI0 bus and the SPI1 bus is available to the user. But you say you are not using the Plus so what SD card solution are you using and on which interface? How have you got the chip select lines for the SD card and the VS1053 connected?
I'm using an adafruit wave shield. http://www.adafruit.com/products/94
I just have the DAC wires disconnected, so it's in effect just an SD Card shield.
Pin 10 is the SD Card chip select.
Pin 7 is the VS1053 command chip select (XCS)
Pin 6 is the VS1053 data chip select (XDS)
I also have DREQ and Reset from the VS1053 wired up. (along with the SPI pins 11, 12 & 13)
const Microsoft.SPOT.Hardware.Cpu.Pin XCSPin = Pins.GPIO_PIN_D7;
const Microsoft.SPOT.Hardware.Cpu.Pin XDCSPin = Pins.GPIO_PIN_D6;
const Microsoft.SPOT.Hardware.Cpu.Pin DREQPin = Pins.GPIO_PIN_D5;
const Microsoft.SPOT.Hardware.Cpu.Pin ResetPin = Pins.GPIO_PIN_D4;
I have simplified my code to this:
do
{
bytesRead = fs.Read(bufs[0], 0, bufsize);
spi.Write(bufs[0]);
} while (bytesRead == bufsize);
I know this would write bad stuff out at the end of the file, but I was just trying to get past the glitch in the audio so I was trying a simple test.
No matter the size for bufsize or the buffer size passed into the FileStream constructor, it sounds the same.
Thanks,
Chad
#6
Posted 26 September 2011 - 04:31 PM
I am also trying to create an MP3 player using Netduino with an MP3 shield+SD card.
http://www.sparkfun.com/products/10628
However, I can't seem to get the audio to come out. The shield works with my Arduino. When I port the code over to Netduino It did not work. Can you share your set up for the VS1053 (MODE, CLOCK, VOL, etc...)?
I have spent many long nights and weekends without any luck.
Regards,
Richard
I have been trying to get a VB1053 (an MP3 decoder) to play an MP3 file I'm loading off of an SD card on a Netduino (not the Plus). And while it "works" I get an audible clicking sound during playback that I'm guessing is because I'm talking to both the SD card and the VM1053 of the same SPI bus. Even when I try to make everything happen sequentially, (read bytes from SD card, play bytes, read more, play more, etc.) I get the same audio glitch. No matter what I set my buffer size to, the glitch is exactly the same, meaning if I buffer 1k or 20k it's exactly the same.
So, I'm just guessing, but it seems to me the StorageDevice's buffer is being filled asynchronously by the Netduino, and it's cutting into the SPI causing the glitch. Could this be true? Any other ideas/suggestions of what to do next?
I should note, I'm very very new at working with microcontrollers.
Thanks for any help,
Chad
#7
Posted 16 December 2011 - 10:00 PM
Hi Chad,
I am also trying to create an MP3 player using Netduino with an MP3 shield+SD card.
http://www.sparkfun.com/products/10628
However, I can't seem to get the audio to come out. The shield works with my Arduino. When I port the code over to Netduino It did not work. Can you share your set up for the VS1053 (MODE, CLOCK, VOL, etc...)?
I have spent many long nights and weekends without any luck.
Regards,
Richard
Hi, I am having the same issues. I was curious if you had managed to make yours work.
#8
Posted 20 December 2011 - 09:47 AM
Hi, I am having the same issues. I was curious if you had managed to make yours work.
if you still looking for an answer, here is the code i used:
vs1053 class (sparkfun's)
using System; using System.IO; using Microsoft.SPOT.Hardware; using System.Threading; using SecretLabs.NETMF.Hardware.NetduinoPlus; using System.Runtime.CompilerServices; namespace smg.Drivers.Music { public static class Vs1053 { // GPIO ports: static private OutputPort _reset; static private InterruptPort _dreq; const Cpu.Pin PinBsync = Pins.GPIO_PIN_D2; const Cpu.Pin PinDreq = Pins.GPIO_PIN_D3; const Cpu.Pin PinReset = Pins.GPIO_PIN_D6; // NOTE: This doesn't map to an actual pin const Cpu.Pin PinCs = Pins.GPIO_PIN_D9; // Define SPI Configuration for VS1053 MP3 decoder: static private readonly SPI.Configuration DataConfig = new SPI.Configuration(PinBsync, false, 0, 0, false, true, 3000, SPI.SPI_module.SPI1); static private readonly SPI.Configuration CmdConfig = new SPI.Configuration(PinCs, false, 0, 0, false, true, 3000, SPI.SPI_module.SPI1); static private SPI _spi; // Registers: const int RegisterSciMode = 0x00; const int RegisterSciVol = 0xFF; const int RegisterSciClockf = 0x03; public static readonly int BufferSize = 256; private const ushort SciMode = 0x880; // SM_SDINEW (default) + SM_EARSPEAKER_HI static private bool _isInitialized; static private readonly byte[] ReadBuffer = new byte[BufferSize]; static private readonly byte[] CmdBuffer = new byte[4]; static private readonly AutoResetEvent AutoResetEvent = new AutoResetEvent(false); private static bool _initialized; // Pins created succesfully when true private static int _duration = -1; // Duration of file playing (in seconds) private static int _position = -1; // Current Play Position (in seconds) private static object _source; // Filename or Resource Reference private static bool _busy = false; // Playing a file when true private static bool _pause = false; // Paused when true private static long _rawSize = -1; private static long _readSoFar = -1; private static int _bitrate = 0; private static int _mpegLayer = 0; private static bool _stop = false; private static int _lastPos = -1; static private byte[] block = new byte[32]; static private byte[] cmdBuffer = new byte[4]; private static bool _cancelMusic = false; public static event musicFinished onMusicFinished; public delegate void musicFinished(); public static bool CancelMusic { set { _cancelMusic = value; } get { return _cancelMusic; } } public static void Initialize() { if (_isInitialized) Shutdown(); _spi = new SPI(CmdConfig); _reset = new OutputPort(PinReset, true); _dreq = new InterruptPort(PinDreq, false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeBoth); _dreq.OnInterrupt += _dreq_OnInterrupt; _isInitialized = true; Reset(); CommandWrite(RegisterSciMode, SciMode | (1 << 2)); CommandWrite(RegisterSciClockf, 7 << 13); CommandWrite(RegisterSciVol, 0xFEFE); _spi.Config = DataConfig; } private static void _dreq_OnInterrupt(uint port, uint state, DateTime time) { if (state == 0) { AutoResetEvent.Set(); } else { AutoResetEvent.WaitOne(); } _dreq.ClearInterrupt(); } private static void Reset() { _reset.Write(false); Thread.Sleep(1); _reset.Write(true); Thread.Sleep(1); } static private void CommandWrite(byte address, ushort data) { CmdBuffer[0] = 0x02; CmdBuffer[1] = address; CmdBuffer[2] = (byte)(data >> 8); CmdBuffer[3] = (byte)data; _spi.Write(CmdBuffer); } static private ushort CommandRead(byte address) { CmdBuffer[0] = 0x03; CmdBuffer[1] = address; CmdBuffer[2] = 0; CmdBuffer[3] = 0; _spi.WriteRead(CmdBuffer, CmdBuffer, 2); ushort command = CmdBuffer[0]; if (command < 100) { throw new ArgumentOutOfRangeException("volume"); } //SetVolumePercent(volume, volume); return command; } public static void SetVolumePercent(int leftChannel, int rightChannel) { if (leftChannel < 0 || leftChannel > 100) throw new ArgumentOutOfRangeException("leftChannel"); if (rightChannel < 0 || rightChannel > 100) throw new ArgumentOutOfRangeException("rightChannel"); // TODO: Invert decibel value, divide by percent, call SetVolume(ushort leftChannel, ushort rightChannel) } public static void SetVolume(ushort bothChannels) { CommandWrite(RegisterSciVol, bothChannels); // TODO: This doesn't work outside the Initialize() method } public static void SetVolume(ushort leftChannel, ushort rightChannel) { SetVolume((ushort)(leftChannel * 256 + rightChannel)); // TODO: Verify no loss of fidelity } public static void SendData(FileStream fileStream) { var size = fileStream.Length - fileStream.Length % BufferSize; for (var i = 0; i < size; i += BufferSize) { fileStream.Read(ReadBuffer, 0, BufferSize); _spi.Write(ReadBuffer); while (_dreq.Read() == false) { Thread.Sleep(1); } if (_cancelMusic) { break; } } } public static void Shutdown() { if (!_isInitialized) return; Reset(); _spi.Dispose(); _reset.Dispose(); _dreq.Dispose(); _isInitialized = false; } [MethodImpl(MethodImplOptions.Synchronized)] public static void PlayLoop() { byte[] b; _cancelMusic = false; _busy = true; _stop = false; _readSoFar = 0; _lastPos = -1; if (_source is string) { FileStream iFile = new FileStream((string)_source, FileMode.Open, FileAccess.Read); _rawSize = iFile.Length; b = new byte[2 * 1024]; int count = iFile.Read(b, 0, b.Length); while (count > 0) { SendData(B); count = iFile.Read(b, 0, b.Length); if (_cancelMusic) { break; } } iFile.Close(); } else if (_source is byte[]) { b = (byte[])_source; _rawSize = b.Length; SendData(B); } _busy = false; _readSoFar = -1; _position = _duration; _bitrate = 0; _mpegLayer = 0; if (onMusicFinished!=null) { onMusicFinished(); } } [MethodImpl(MethodImplOptions.Synchronized)] public static void SendData(byte[] data) { int size = data.Length - data.Length % 32; //_spi.Config = dataConfig; for (int i = 0; i < size; i += 32) { while (_dreq.Read() == false) Thread.Sleep(1); // wait till done Array.Copy(data, i, block, 0, 32); _spi.Write(block); _readSoFar += 32; // We need to know how many bytes we've read to calculate header size to get duration while (_pause) Thread.Sleep(1); // Wait while paused } } public static string Filename { get { if (_source is string) return (string)_source; else return "Embedded Resource"; } set { _source = value; } } [MethodImpl(MethodImplOptions.Synchronized)] public static void Play() { new Thread(PlayLoop).Start(); } } }
and here how i use it
Vs1053.Initialize(); Vs1053.SetVolume(0xFEFE); Vs1053.Filename = "\\SD\test.mp3"; Vs1053.PlayLoop();
also i implemented two new thing
1-
Vs1053.onMusicFinished += new Vs1053.musicFinished(Vs1053_onMusicFinished);fires event when music finishes..(useful when threading music playback.. normally it is not async)
2-
Vs1053.CancelMusic = true;
this cancels music immediately , useful when you want to cancel and play next file..
0 user(s) are reading this topic
0 members, 0 guests, 0 anonymous users