mirror of
https://github.com/ckaczor/OneWireAPI.git
synced 2026-01-14 01:25:40 -05:00
243 lines
8.1 KiB
C#
243 lines
8.1 KiB
C#
namespace OneWireAPI
|
|
{
|
|
public class DeviceFamily20 : Device
|
|
{
|
|
private readonly byte[] _control = new byte[16];
|
|
|
|
public enum Range : byte
|
|
{
|
|
Range512 = 0x01,
|
|
Range256 = 0x00
|
|
}
|
|
|
|
public enum Resolution : byte
|
|
{
|
|
EightBits = 0x08,
|
|
SixteenBits = 0x00
|
|
}
|
|
|
|
public DeviceFamily20(Session session, short[] id)
|
|
: base(session, id)
|
|
{
|
|
}
|
|
|
|
public void Initialize()
|
|
{
|
|
const int startAddress = 0x8; // Starting data page address
|
|
const int endAddress = 0x11; // Ending data page address
|
|
|
|
// Setup the control page
|
|
for (var index = 0; index < 8; index += 2)
|
|
{
|
|
_control[index] = (byte) Resolution.EightBits;
|
|
_control[index + 1] = (byte) Range.Range512;
|
|
}
|
|
|
|
// Clear the alarm page
|
|
for (var index = 8; index < 16; index++)
|
|
{
|
|
_control[index] = 0;
|
|
}
|
|
|
|
// Data buffer to send over the network
|
|
var data = new byte[30];
|
|
|
|
// How many bytes of data to send
|
|
short dataCount = 0;
|
|
|
|
// Set the command into the data array
|
|
data[dataCount++] = 0x55;
|
|
|
|
// Set the starting address of the data to write
|
|
data[dataCount++] = startAddress & 0xFF;
|
|
data[dataCount++] = (startAddress >> 8) & 0xFF;
|
|
|
|
// Select and access the ID of the device we want to talk to
|
|
Adapter.Select(Id);
|
|
|
|
// Write to the data pages specified
|
|
for (var index = startAddress; index <= endAddress; index++)
|
|
{
|
|
// Copy the control data into our output buffer
|
|
data[dataCount++] = _control[index - startAddress];
|
|
|
|
// Add two bytes for the CRC results
|
|
data[dataCount++] = 0xFF;
|
|
data[dataCount++] = 0xFF;
|
|
|
|
// Add a byte for the control byte echo
|
|
data[dataCount++] = 0xFF;
|
|
|
|
// Send the block
|
|
Adapter.SendBlock(data, dataCount);
|
|
|
|
// If the check byte doesn't match then throw an exception
|
|
if (data[dataCount - 1] != _control[index - startAddress])
|
|
{
|
|
// Throw an exception
|
|
throw new OneWireException(OneWireException.ExceptionFunction.SendBlock, Id);
|
|
}
|
|
|
|
int calculatedCrc; // CRC we calculated from sent data
|
|
int sentCrc; // CRC retrieved from the device
|
|
|
|
// Calculate the CRC values
|
|
if (index == startAddress)
|
|
{
|
|
// Calculate the CRC16 of the data sent
|
|
calculatedCrc = Crc16.Calculate(data, 0, 3);
|
|
|
|
// Reconstruct the CRC sent by the device
|
|
sentCrc = data[dataCount - 2] << 8;
|
|
sentCrc |= data[dataCount - 3];
|
|
sentCrc ^= 0xFFFF;
|
|
}
|
|
else
|
|
{
|
|
// Calculate the CRC16 of the data sent
|
|
calculatedCrc = Crc16.Calculate(_control[index - startAddress], index);
|
|
|
|
// Reconstruct the CRC sent by the device
|
|
sentCrc = data[dataCount - 2] << 8;
|
|
sentCrc |= data[dataCount - 3];
|
|
sentCrc ^= 0xFFFF;
|
|
}
|
|
|
|
// If the CRC doesn't match then throw an exception
|
|
if (calculatedCrc != sentCrc)
|
|
{
|
|
// Throw a CRC exception
|
|
throw new OneWireException(OneWireException.ExceptionFunction.Crc, Id);
|
|
}
|
|
|
|
// Reset the byte count
|
|
dataCount = 0;
|
|
}
|
|
}
|
|
|
|
public double[] GetVoltages()
|
|
{
|
|
// Select and access the ID of the device we want to talk to
|
|
Adapter.Select(Id);
|
|
|
|
// Data buffer to send over the network
|
|
var data = new byte[30];
|
|
|
|
// How many bytes of data to send
|
|
short dataCount = 0;
|
|
|
|
// Set the convert command into the transmit buffer
|
|
data[dataCount++] = 0x3C;
|
|
|
|
// Set the input mask to get all channels
|
|
data[dataCount++] = 0x0F;
|
|
|
|
// Set the read-out control to leave things as they are
|
|
data[dataCount++] = 0x00;
|
|
|
|
// Add two bytes for the CRC results
|
|
data[dataCount++] = 0xFF;
|
|
data[dataCount++] = 0xFF;
|
|
|
|
// Send the data block
|
|
Adapter.SendBlock(data, dataCount);
|
|
|
|
// Calculate the CRC based on the transmit buffer
|
|
var calculatedCrc = Crc16.Calculate(data, 0, 2);
|
|
|
|
// Reconstruct the CRC sent by the device
|
|
var sentCrc = data[4] << 8;
|
|
sentCrc |= data[3];
|
|
sentCrc ^= 0xFFFF;
|
|
|
|
// If the CRC doesn't match then throw an exception
|
|
if (calculatedCrc != sentCrc)
|
|
{
|
|
// Throw a CRC exception
|
|
throw new OneWireException(OneWireException.ExceptionFunction.Crc, Id);
|
|
}
|
|
|
|
// Setup for for power delivery after the next byte
|
|
Adapter.SetLevel(TMEX.LevelOperation.Write, TMEX.LevelMode.StrongPullup, TMEX.LevelPrime.AfterNextByte);
|
|
|
|
var transmitByte = (short) ((dataCount - 1) & 0x1F);
|
|
|
|
try
|
|
{
|
|
// Send the byte and start strong pullup
|
|
Adapter.SendByte(transmitByte);
|
|
}
|
|
catch
|
|
{
|
|
// Stop the strong pullup
|
|
Adapter.SetLevel(TMEX.LevelOperation.Write, TMEX.LevelMode.Normal, TMEX.LevelPrime.Immediate);
|
|
|
|
// Re-throw the exception
|
|
throw;
|
|
}
|
|
|
|
// Sleep while the data is transfered
|
|
System.Threading.Thread.Sleep(6);
|
|
|
|
// Stop the strong pullup
|
|
Adapter.SetLevel(TMEX.LevelOperation.Write, TMEX.LevelMode.Normal, TMEX.LevelPrime.Immediate);
|
|
|
|
// Read data to see if the conversion is over
|
|
Adapter.ReadByte();
|
|
|
|
// Select and access the ID of the device we want to talk to
|
|
Adapter.Select(Id);
|
|
|
|
// Reinitialize the data count
|
|
dataCount = 0;
|
|
|
|
// Set the read command into the transmit buffer
|
|
data[dataCount++] = 0xAA;
|
|
|
|
// Set the address to get the conversion results
|
|
data[dataCount++] = 0x00;
|
|
data[dataCount++] = 0x00;
|
|
|
|
// Add 10 bytes to be read - 8 for the data and 2 for the CRC
|
|
for (var index = 0; index < 10; index++)
|
|
data[dataCount++] = 0xFF;
|
|
|
|
// Send the block to the device
|
|
Adapter.SendBlock(data, dataCount);
|
|
|
|
// Calculate the CRC of the transmitted data
|
|
calculatedCrc = Crc16.Calculate(data, 0, 10);
|
|
|
|
// Reconstruct the CRC sent by the device
|
|
sentCrc = data[dataCount - 1] << 8;
|
|
sentCrc |= data[dataCount - 2];
|
|
sentCrc ^= 0xFFFF;
|
|
|
|
// If the CRC doesn't match then throw an exception
|
|
if (calculatedCrc != sentCrc)
|
|
{
|
|
// Throw a CRC exception
|
|
throw new OneWireException(OneWireException.ExceptionFunction.Crc, Id);
|
|
}
|
|
|
|
// Voltage values to return
|
|
var voltages = new double[4];
|
|
|
|
// Convert the data into a double
|
|
for (var index = 3; index < 11; index += 2)
|
|
{
|
|
// Reconstruct the two bytes into the 16-bit values
|
|
var iVoltageReadout = ((data[index + 1] << 8) | data[index]) & 0x0000FFFF;
|
|
|
|
// Figure out the percentage of the top voltage is present
|
|
voltages[(index - 3) / 2] = iVoltageReadout / 65535.0;
|
|
|
|
// Apply the percentage to the maximum voltage range
|
|
voltages[(index - 3) / 2] *= ((_control[(index - 3) + 1] & 0x01) == 0x01 ? 5.12 : 2.56);
|
|
}
|
|
|
|
return voltages;
|
|
}
|
|
}
|
|
}
|