-
Notifications
You must be signed in to change notification settings - Fork 0
/
DeviceFamily20.cs
242 lines (188 loc) · 8.11 KB
/
DeviceFamily20.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
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;
}
}
}