As I can’t play with micropython:
https://community.brainpad.com/t/install-micropython/191
I play with vs1503 mp3 decoder, but I have a problem with spi exception:
#### Exception System.InvalidOperationException - CLR_E_INVALID_OPERATION (1) ####
#### Message:
#### GHIElectronics.TinyCLR.Devices.Spi.Provider.SpiControllerApiWrapper::SetActiveSettings [IP: 0000] ####
#### GHIElectronics.TinyCLR.Devices.Spi.SpiController::SetActive [IP: 000b] ####
#### GHIElectronics.TinyCLR.Devices.Spi.SpiDevice::TransferFullDuplex [IP: 000e] ####
#### GHIElectronics.TinyCLR.Devices.Spi.SpiDevice::TransferFullDuplex [IP: 000e] ####
#### TinyCLRApplicationVs1503.Vs1503B::GetRegister [IP: 002c] ####
#### TinyCLRApplicationVs1503.Vs1503B::ClearBitInRegister [IP: 0018] ####
#### TinyCLRApplicationVs1503.Vs1503B::StopSin [IP: 0058] ####
Exception levée : 'System.InvalidOperationException' dans GHIElectronics.TinyCLR.Devices.Spi.dll
Une exception non gérée du type 'System.InvalidOperationException' s'est produite dans GHIElectronics.TinyCLR.Devices.Spi.dll
My (relative simple) code is :
using System;
using System.Threading;
using GHIElectronics.TinyCLR.Devices.Gpio;
using GHIElectronics.TinyCLR.Devices.Spi;
// ReSharper disable UnusedMethodReturnValue.Global
// ReSharper disable UnusedMember.Global
// ReSharper disable MemberCanBePrivate.Global
namespace TinyCLRApplicationVs1503
{
public class Vs1503B
{
private readonly SpiDevice _sci;
private readonly SpiDevice _sdi;
private readonly GpioPin _dataRequested;
readonly byte[] _sciBufferRead = new byte[4];
readonly byte[] _sciBufferWrite = new byte[4];
readonly byte[] _sdiTestBufferRead = new byte[8];
readonly byte[] _sdiTestBufferWrite = new byte[8];
private const byte Read = 0x3;
private const byte Write = 0x2;
public enum Register : byte
{
Mode = 0x0,
Status = 0x1,
Bass = 0x2,
Clock = 0x3,
DecodeTime = 0x4,
AuData = 0x5,
WRam = 0x6,
WRamAddr = 0x7,
HeaderData0 = 0x8,
HeaderData1 = 0x9,
ApplicationStartAddress = 0xA,
Volume = 0xB
}
public enum Bit
{
SetMaskTest = 5,
SetMaskReset = 2,
}
private DateTime _timeOutOrigin;
public TimeSpan TimeOut = TimeSpan.FromMilliseconds(200);
public Vs1503B(string spiBuses, int xcs, int dcs, int dataRequested)
{
var ctl = SpiController.FromName(spiBuses);
SpiConnectionSettings sciSettings = new SpiConnectionSettings()
{
ChipSelectType = SpiChipSelectType.Gpio,
ChipSelectLine = xcs,
ClockFrequency = 4_000_000,
DataBitLength = 8,
ChipSelectSetupTime = TimeSpan.FromMilliseconds(1),
Mode = SpiMode.Mode0
};
_sci = ctl.GetDevice(sciSettings);
SpiConnectionSettings sdiSettings = new SpiConnectionSettings()
{
ChipSelectType = SpiChipSelectType.Gpio,
ChipSelectLine = dcs,
ClockFrequency = 4_000_000,
DataBitLength = 8,
ChipSelectSetupTime = TimeSpan.FromMilliseconds(1),
Mode = SpiMode.Mode0
};
_sdi = ctl.GetDevice(sdiSettings);
var gpioCtl = GpioController.GetDefault();
_dataRequested = gpioCtl.OpenPin(dataRequested);
_dataRequested.SetDriveMode(GpioPinDriveMode.Input);
Initialization();
}
private void Initialization()
{
SetRegister(Register.Mode, 0x4800);
SoftReset();
}
private void SoftReset()
{
SetBitInRegister(Register.Mode, Bit.SetMaskReset);
WaitDataRequest();
}
public ushort GetRegister(Register register)
{
_sciBufferWrite[0] = Read;
_sciBufferWrite[1] = (byte)register;
_sciBufferWrite[2] = 0;
_sciBufferWrite[3] = 0;
_sci.TransferFullDuplex(_sciBufferWrite, _sciBufferRead);
WaitDataRequest();
return (ushort)(_sciBufferRead[2] << 8 | _sciBufferRead[3]);
}
public void SetRegister(Register register, ushort value)
{
_sciBufferWrite[0] = Write;
_sciBufferWrite[1] = (byte)register;
_sciBufferWrite[2] = (byte)(value >> 8);
_sciBufferWrite[3] = (byte)(value & 0xff);
_sci.TransferFullDuplex(_sciBufferWrite, _sciBufferRead);
WaitDataRequest();
}
public void SetBitInRegister(Register register, Bit bit)
{
if (bit < 0 || (int)bit > 32) return;
var value = GetRegister(register);
var mask = (1 << (int)bit);
var newValue = (ushort)(value | mask);
SetRegister(register, newValue);
}
public void ClearBitInRegister(Register register, Bit bit)
{
if (bit < 0 || (int)bit > 32) return;
var value = GetRegister(register);
var mask = (ushort)(~(1 << (int)bit));
var newValue = (ushort)(value & mask);
SetRegister(register, newValue);
}
public bool WaitDataRequest()
{
_timeOutOrigin = DateTime.Now;
while (_dataRequested.Read() == GpioPinValue.Low)
{
if ((DateTime.Now - _timeOutOrigin) > TimeOut) return false;
}
return true;
}
public bool CheckDataReady()
{
return _dataRequested.Read() == GpioPinValue.High;
}
public void StartSin()
{
SetBitInRegister(Register.Mode, Bit.SetMaskTest);
_sdiTestBufferWrite[0] = 0x53;
_sdiTestBufferWrite[1] = 0xef;
_sdiTestBufferWrite[2] = 0x6e;
_sdiTestBufferWrite[3] = 0xe5;
for (int i = 4; i < 8; i++)
_sdiTestBufferWrite[i] = 0x00;
_sdi.TransferFullDuplex(_sdiTestBufferWrite, _sdiTestBufferRead);
WaitDataRequest();
}
public void StopSin()
{
_sdiTestBufferWrite[0] = 0x45;
_sdiTestBufferWrite[1] = 0x78;
_sdiTestBufferWrite[2] = 0x69;
_sdiTestBufferWrite[3] = 0x74;
for (int i = 4; i < 8; i++)
_sdiTestBufferWrite[i] = 0x00;
_sdi.TransferFullDuplex(_sdiTestBufferWrite, _sdiTestBufferRead);
WaitDataRequest();
Thread.Sleep(2);
ClearBitInRegister(Register.Mode, Bit.SetMaskTest);
}
}
}
and my program:
static void Main()
{
var vs1503B = new Vs1503B(FEZPandaIII.SpiBus.Spi1, FEZPandaIII.GpioPin.D7, FEZPandaIII.GpioPin.D6, FEZPandaIII.GpioPin.D3);
Debug.WriteLine($"Mode: 0x{vs1503B.GetRegister(Vs1503B.Register.Mode):X4}");
Debug.WriteLine($"Status: 0x{vs1503B.GetRegister(Vs1503B.Register.Status):X4}");
Debug.WriteLine($"Volume: 0x{vs1503B.GetRegister(Vs1503B.Register.Volume):X4}");
Debug.WriteLine($"Mode: 0x{vs1503B.GetRegister(Vs1503B.Register.Mode):X4}");
while (true)
{
vs1503B.StartSin();
Thread.Sleep(1000);
vs1503B.StopSin();
Thread.Sleep(1000);
Thread.Sleep(20);
}
}
Is it a bug in spi Library, or an error I have done ? I tried to see with logic analyzer, but all seems correct and it gives me no clue.