The code as it stands is …
public delegate void OnMeasurementB(ADS1256 sender, int Measurement);
public class ADS1256 : GTM.Module
{
#region Enumerations
#region Commands
// define the command bytes (see table 24 on page 32 in the PDS
private enum Command : byte
{
// Completes SYNC and Exits Standby Mode
WAKEUP = 0x00,
// Read Data
RDATA = 0x01,
// Read Data Continuously
RDATAC = 0x03,
// Stop Read Data Continuously
SDATAC = 0x0F,
// Read from REG rrr
RREG = 0x10,
// Write to REG rrr
WREG = 0x50,
// Offset and Gain Self-Calibration
SELFCAL = 0xF0,
// Offset Self-Calibration
SELFOCAL = 0xF1,
// Gain Self-Calibration
SELFGCAL = 0xF2,
// System Offset Calibration
SYSOCAL = 0xF3,
// System Gain Calibration
SYSGCAL = 0xF4,
// Synchronize the A/D Conversion
SYNC = 0xFC,
// Begin Standby Mode
STANDBY = 0xFD,
// Reset to Power-Up Values
RESET = 0xFE,
// Completes SYNC and Exits Standby Mode
WAKEUP2 = 0xFF,
}
#endregion
#region Registers
// define the ADS1256 registers
private enum Register : byte
{
// STATUS REGISTER (ADDRESS 00h)
STATUS = 0x00,
// Input Multiplexer Control Register (Address 01h)
MUX = 0x01,
// A/D Control Register (Address 02h)
ADCON = 0x02,
// A/D Data Rate (Address 03h)
DRATE = 0x03,
// GPIO Control Register (Address 04H)
IO = 0x04,
// Offset Calibration Byte 0, least significant byte (Address 05h)
OFC0 = 0x05,
// Offset Calibration Byte 1 (Address 06h)
OFC1 = 0x06,
// Offset Calibration Byte 2, most significant byte (Address 07h)
OFC2 = 0x07,
// Full−scale Calibration Byte 0, least significant byte (Address 08h)
FSC0 = 0x08,
// Full−scale Calibration Byte 1 (Address 09h)
FSC1 = 0x09,
// Full−scale Calibration Byte 2, most significant byte (Address 0Ah)
FSC2 = 0x0A,
}
#endregion
#region Multiplexer
public enum MultplexPositive : byte
{
AIN0 = (0x0000 << 4),
AIN1 = (0x0001 << 4),
AIN2 = (0x0002 << 4),
AIN3 = (0x0003 << 4),
AIN4 = (0x0004 << 4),
AIN5 = (0x0005 << 4),
AIN6 = (0x0006 << 4),
AIN7 = (0x0007 << 4),
AINCOM = (0x0008 << 4),
}
// define multiplexer codes
public enum MultiplexNegative : byte
{
AIN0 = 0,
AIN1,
AIN2,
AIN3,
AIN4,
AIN5,
AIN6,
AIN7,
AINCOM,
}
#endregion
#region Gains
// define gain codes
public enum Gain : byte
{
Gain_01 = 0x00,
Gain_02 = 0x01,
Gain_04 = 0x02,
Gain_08 = 0x03,
Gain_16 = 0x04,
Gain_32 = 0x05,
Gain_64 = 0x06,
}
#endregion
#region Sample Rates
// define sample rates
public enum SampleRate : byte
{
Rate_30000 = 0xF0,
Rate_15000 = 0xE0,
Rate_7500 = 0xD0,
Rate_3750 = 0xC0,
Rate_2000 = 0xB0,
Rate_1000 = 0xA1,
Rate_500 = 0x92,
Rate_100 = 0x82,
Rate_60 = 0x72,
Rate_50 = 0x63,
Rate_30 = 0x53,
Rate_25 = 0x43,
Rate_15 = 0x33,
Rate_10 = 0x23,
Rate_5 = 0x13,
Rate_2Point5 = 0x03,
}
#endregion
#endregion
private Gain g_Gain = Gain.Gain_01;
// Used for reading the data conversion
byte[] conversionBuffer = new byte[3];
private byte[] _oneByte = new byte[1];
private byte[] _threeByte = new byte[3];
//private byte[] MultiplexChannels = new byte[7];
private GTI.Spi _spi;
private GTI.DigitalOutput reset;
private GTI.DigitalOutput testOP;
private GTI.InterruptInput dReady;
private bool _sleepAfterSend = true;
private int _sleeptime = 1;
// This will hold the configuration for each of the required channels
private GTI.SpiConfiguration spiConfig;
Socket socket;
public ADS1256(int socketNumber)
{
socket = Socket.GetSocket(socketNumber, true, this, null);
socket.EnsureTypeIsSupported('S', this);
socket.ReservePin(Socket.Pin.Three, this); // dReady
socket.ReservePin(Socket.Pin.Four, this); // Reset
socket.ReservePin(Socket.Pin.Five, this); // Spare
socket.ReservePin(Socket.Pin.Six, this);
this.dReady = GTI.InterruptInputFactory.Create(socket, Socket.Pin.Three, GTI.GlitchFilterMode.On, GTI.ResistorMode.Disabled, GTI.InterruptMode.FallingEdge, this);
this.reset = GTI.DigitalOutputFactory.Create(socket, Socket.Pin.Four, true, this);
this.testOP = GTI.DigitalOutputFactory.Create(socket, Socket.Pin.Five, true, this);
this.spiConfig = new GTI.SpiConfiguration(false, 0, 0, false, true, 4000);
_spi = GTI.SpiFactory.Create(this.socket, this.spiConfig, GTI.SpiSharing.Shared, this.socket, Socket.Pin.Six, this);
Initialise();
this.dReady.Interrupt += dReady_Interrupt;
}
private void Initialise()
{
DigitalReset(); // <---- Only used to trigger logic analyser.
SPIReset(); // <----- Reset the device
SendCommand(Command.SDATAC); // Stop Read Data Continuously
WriteRegister(Register.STATUS, 0x02); //WREG - STATUS - Enable buffer
WriteRegister(Register.ADCON, 0x00); //WREG - ADCON - default PGA = 1
WriteRegister(Register.DRATE, (byte)SampleRate.Rate_5);
WriteRegister(Register.MUX, 0x18);
SendCommand(Command.SYNC);
SendCommand(Command.WAKEUP);
}
#region Interrupt
int result;
void dReady_Interrupt(GTI.InterruptInput sender, bool value)
{
WriteRegister(Register.MUX, 0x18);
SendCommand(Command.SYNC);
SendCommand(Command.WAKEUP);
result = ReadData();
OnMeasurementB(this, result);
}
public void GotReading()
{
testOP.Write(false);
testOP.Write(true);
}
public event OnMeasurementB MeasurementComplete;
protected virtual void OnMeasurementB(ADS1256 sender, int record)
{
if (MeasurementComplete != null)
MeasurementComplete(sender, record);
}
#endregion
#region Reset Methods
public void DigitalReset()
{
reset.Write(false);
reset.Write(true);
}
/// <summary>
/// SPIReset issues a Reset on the SPI Bus to the device.
/// </summary>
public void SPIReset()
{
SendCommand(Command.RESET);
}
#endregion
#region SPI Communication Methods
private void SendCommand(Command command)
{
_oneByte[0] = (byte)command;
_spi.Write(_oneByte);
}
private void WriteRegister(Register register, byte data)
{
_threeByte[0] = (byte)((byte)Command.WREG | (byte)register);
_threeByte[1] = 0x00;
_threeByte[2] = data;
_spi.Write(_threeByte);
}
#region Read Methods
private int ReadData()
{
_oneByte[0] = (byte)Command.RDATA;
_spi.Write(_oneByte);
//if (_sleepAfterSend) Thread.Sleep(_sleeptime);
_oneByte[0] = 0x00;
_spi.WriteRead(_oneByte, conversionBuffer);
return ((conversionBuffer[0] << 16) & (conversionBuffer[1] << 8) & conversionBuffer[2]);
}
#endregion
#region Write Methods
private byte[] ReadRegister(Register register, byte number)
{
Command command;
byte[] data = new byte[number];
command = Command.RREG | (Command)register;
_oneByte[0] = (byte)command;
_spi.WriteRead(_oneByte, data);
return data;
}
public int ReadDeviceID()
{
byte[] data;
data = ReadRegister(Register.STATUS, 1);
return data[0];
}
#endregion
#endregion
}
Since my original post I have made some headway but it is painfully slow. I discovered that if I use the digital output to reset the module I always end up with 30K sps no matter what. With the Reset pin to tied to 3.3V I am able to almost configure the module. I say ‘almost’ as the data rate adopts the new value after cycling the power sometimes, other times I get a random value less than the 30K.
Measurement values are always returned as 0 but as I have problems with the simple task of setting data rate etc I need to resolve these first. The module has a builtin crystal of 7.68Mhz so the t-values in the datasheet are all in the low microsecond range but it does seem to be a timing issue I think.