forked from nanoframework/nanoFramework.IoT.Device
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Mcp3Base.cs
170 lines (153 loc) · 5.54 KB
/
Mcp3Base.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
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Buffers.Binary;
using System.Device.Spi;
namespace Iot.Device.Adc
{
// MCP3001
// Byte 1 0
// ==== ======== ========
// Req xxxxxxxx xxxxxxxx
// Resp xxNRRRRR RRRRRxxx
//
// MCP3002
// Byte 1 0
// ==== ======== ========
// Req 0SMC1xxx xxxxxxxx
// Resp 00xxxNRR RRRRRRRR
//
// MCP3004
// Byte 2 1 0
// ==== ======== ======== ========
// Req 0000000S MxCCxxxx xxxxxxxx
// Resp xxxxxxxx xxxxDNRR RRRRRRRR
//
// MCP3008
// Byte 2 1 0
// ==== ======== ======== ========
// Req 0000000S MCCCxxxx xxxxxxxx
// Resp xxxxxxxx xxxxDNRR RRRRRRRR
//
// MCP3201
// Byte 1 0
// ==== ======== ========
// Req xxxxxxxx xxxxxxxx
// Resp xxNRRRR RRRRRRRRx
//
// MCP3202
// Byte 2 1 0
// ==== ======== ======== ========
// Req 0000000S MC1xxxxx xxxxxxxx
// Resp xxxxxxxx xxxNRRRR RRRRRRRR
//
// MCP3204
// Byte 2 1 0
// ==== ======== ======== ========
// Req 00000SMx CCxxxxxx xxxxxxxx
// Resp xxxxxxxx xxDNRRRR RRRRRRRR
//
// MCP3208
// Byte 2 1 0
// ==== ======== ======== ========
// Req 00000SMC CCxxxxxx xxxxxxxx
// Resp xxxxxxxx xxDNRRRR RRRRRRRR
//
// MCP3301
// Byte 1 0
// ==== ======== ========
// Req xxxxxxxx xxxxxxxx
// Resp xxN-RRRR RRRRRRRR
//
// MCP3302
// Byte 2 1 0
// ==== ======== ======== ========
// Req 0000SMxC Cxxxxxxx xxxxxxxx
// Resp xxxxxxxx xDN-RRRR RRRRRRRR
//
// MCP3304
// Byte 2 1 0
// ==== ======== ======== ========
// Req 0000SMCC Cxxxxxxx xxxxxxxx
// Resp xxxxxxxx xDN-RRRR RRRRRRRR
//
// S = StartBit = 1
// C = Channel
// M = SingleEnded
// D = Delay
// N = Null Bit = 0
// R = Response
// - = Sign Bit
// x = Dont Care
//
/// <summary>
/// MCP family of ADC devices
/// </summary>
public abstract class Mcp3Base : IDisposable
{
/// <summary>
/// InputType: the type of pin connection
/// </summary>
protected enum InputType
{
/// <summary>The value is measured as the voltage on a single pin</summary>
SingleEnded = 0,
/// <summary>The value is the difference in voltage between two pins with the first pin being the positive one</summary>
Differential = 1,
/// <summary>The value is the difference in voltage between two pins with the second pin being the positive one</summary>
InvertedDifferential = 2
}
private SpiDevice _spiDevice;
/// <summary>
/// Constructs Mcp3Base instance
/// </summary>
/// <param name="spiDevice">Device used for SPI communication</param>
public Mcp3Base(SpiDevice spiDevice) => _spiDevice = spiDevice ?? throw new ArgumentNullException(nameof(spiDevice));
/// <summary>
/// Reads a value from the device
/// </summary>
/// <param name="adcRequest">A bit pattern to be sent to the ADC.</param>
/// <param name="adcResolutionBits">The number of bits in the returned value</param>
/// <param name="delayBits">The number of bits to be delayed between the request and the response being read.</param>
/// <returns>A value corresponding to a voltage level on the input pin described by the request.</returns>
protected int ReadInternal(int adcRequest, int adcResolutionBits, int delayBits)
{
int retval = 0;
int bufferSize;
// shift the request left to make space in the response for the number of bits in the
// response plus the conversion delay and plus 1 for a null bit.
adcRequest <<= (adcResolutionBits + delayBits + 1);
// calculate the buffer size... If there is a start bit in the range b16 -> b23 then the size of the buffer is 3 bytes otherwise 2 bytes
bufferSize = (adcRequest & 0x00FF0000) != 0 ? 3 : 2;
SpanByte requestBuffer = new byte[bufferSize];
SpanByte responseBuffer = new byte[bufferSize];
// take the resuest and put it in a byte array
for (int i = 0; i < bufferSize; i++)
{
requestBuffer[i] = (byte)(adcRequest >> (bufferSize - i - 1) * 8);
}
_spiDevice.TransferFullDuplex(requestBuffer, responseBuffer);
// transfer the response from the ADC into the return value
for (int i = 0; i < bufferSize; i++)
{
retval <<= 8;
retval += responseBuffer[i];
}
// test the response from the ADC to check that the null bit is actually 0
if ((retval & (1 << adcResolutionBits)) != 0)
{
throw new InvalidOperationException("Invalid data was read from the sensor");
}
// return the ADC response with any possible higer bits masked out
return retval & (int)((1L << adcResolutionBits) - 1);
}
/// <summary>
/// Disposes Mcp3Base instances
/// </summary>
public void Dispose()
{
_spiDevice?.Dispose();
_spiDevice = null!;
}
}
}