Hello,
I’m developing an application the Colibri iMX6S where communicate with the Microchip MCP4922 DAC using SPI interface/protocol.
Everything works but I have an issue regarding the communication speed between the iMX6 and the DAC,
Since I need to write more than 10000 values in one second I need to achieve the best performances and here I have the issue: the speed seems to be lower to what I think it should be.
Infact since the DAC works with a 20 MHz frequency and iMX6 supports up to 23 MHz, it should be that writing 2 bytes for each value it should take normally 0,8 microseconds but I have measured instead that it takes normally 120 microsecons for each written value.
And this is a bottleneck for my application so please help me to understand how to speed up this communication.
Here is the configuration of the SPI communication;
private const float LSB = 1 / 4095;
public const int MAX_VALUE = 4095; //VOUT = InputCode*LSB/MAX_VAçLUE 4095
public const int MIN_VALUE = 0;
IntPtr spiHandle = IntPtr.Zero;
gpio.uIo ioCs = new gpio.uIo();
uint returnValue = 0;
public uint DeviceAddress;
bool bReverse_A_Reg;
bool bReverse_B_Reg;
bool bStarted;
public MCP4922()
{
spiHandle = spi.Spi_Init("SPI1"); ///< Init SPI library
if (spiHandle == IntPtr.Zero)
{
Program.cGlobals.cLogging.LogMessage("MCP4922 --> Error initializing the SPI Library");
}
spi.Spi_SetConfigInt(spiHandle, "SpiMode", 0, TdxCommon.ParamStorageType.StoreVolatile); ///< Set SPI on Mode 0
spi.Spi_SetConfigInt(spiHandle, "BitRateHz", 20*1000*1000, TdxCommon.ParamStorageType.StoreVolatile); ///< Set SPI clock 26000 Lhz
if (!spi.Spi_Open(spiHandle))
{
Program.cGlobals.cLogging.LogMessage("MCP4922 --> Failed to open SPI");
}
ioCs.number = 86;
ioCs.type = (ushort)gpio.tIoType.ioColibriPin;
spi.Spi_SetConfigInt(spiHandle, "ioCS", ioCs.GenericDefinition, TdxCommon.ParamStorageType.StoreVolatile); ///< Set Chip Select pin sodimm 86
spi.Spi_SetConfigInt(spiHandle, "BitsPerWord", 8, TdxCommon.ParamStorageType.StoreVolatile);
}
And here is the Write Subroutine (where I’ve put the code with Stopwatch to take the exact time for the value writing):
public void WriteRegister(int DACNumber, int BufferControl, int Gain, int Shutdown, int iValue)
{
//DACNumber=0 => Registro A - DACNumber=1 => Registro B
//BufferControl=0 => Unbuffered - BufferControl=1 => Buffered
//Gain=0 => VOUT = 2 * VREF * D/4096 - Gain=1 => VOUT = VREF * D/4096 dove D è il valore del registro D11-D0
//Shutdown=0 => Shutdown the selected DAC channel - Shutdown=1 => Active mode operation. VOUT is available
if (DACNumber==0 && bReverse_A_Reg)
iValue = MAX_VALUE - iValue;
if (DACNumber == 1 && bReverse_B_Reg)
iValue = MAX_VALUE - iValue;
uint bufferLenght = 2;
Byte[] DataToWrite = new Byte[bufferLenght];
int SetupValue = DACNumber * 8 + BufferControl * 4 + Gain * 2 + Shutdown;
DataToWrite[0] = (byte)(((iValue & 3840) >> 8) | (SetupValue * 16));
DataToWrite[1] = (byte)(iValue & 255);
try
{
unsafe
{
fixed (byte* for_Casting_Intptr_to_Byte = DataToWrite)
{
Stopwatch sw1 = new Stopwatch();
sw1.Start();
returnValue = spi.Spi_Write(spiHandle, (IntPtr)for_Casting_Intptr_to_Byte, bufferLenght);
if (returnValue == 0)
throw new Exception(); ///< If Write operation returns 0
long ticks = sw1.ElapsedTicks;
double ns = 1000000000.0 * (double)ticks / Stopwatch.Frequency;
double micros = ns / 1000.0;
double millis = micros / 1000.0;
sw1.Stop();
}
}
}
catch (Exception ex)
{
Program.cGlobals.cLogging.LogMessage("Scrittura Configurazione Fallita - Codice Errore: " + ex.Message);
}
}
I hope you can help me since without this improvement my application is not useful.
Thanks in advance