forked from nanoframework/nanoFramework.IoT.Device
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Mcp33xx.cs
83 lines (73 loc) · 4.73 KB
/
Mcp33xx.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
// 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.Device.Spi;
namespace Iot.Device.Adc
{
/// <summary>
/// MCP33XX family of Analog to Digital Converters
/// </summary>
public abstract class Mcp33xx : Mcp3xxx
{
/// <summary>
/// Constructs Mcp33xx instance
/// </summary>
/// <param name="spiDevice">Device used for SPI communication</param>
/// <param name="channelCount">Value representing the number of single ended input channels on the device.</param>
/// <param name="adcResolutionBits">The number of bits of resolution for the ADC.</param>
public Mcp33xx(SpiDevice spiDevice, byte channelCount, byte adcResolutionBits)
: base(spiDevice, channelCount, adcResolutionBits)
{
}
/// <summary>
/// Convert a signed value with a sign bit at a particular location to an int.
/// </summary>
/// <param name="signedValue">Signed value with a sign bit at a particular location</param>
/// <param name="signingBit">Bit number that contains the sign bit</param>
/// <returns>A value corresponding to the signed value sign extended into an int</returns>
// if the sign bit is set then extend the signing bit to create a signed integer
public static int SignExtend(int signedValue, int signingBit) => (signedValue >> signingBit) == 0 ? signedValue : signedValue - (2 << signingBit);
/// <summary>
/// Reads a value from the device using pseudo-differential inputs
/// </summary>
/// <param name="valueChannel">Channel which represents the signal (valid values: 0 to channelcount - 1).</param>
/// <param name="referenceChannel">Channel which represents the signal ground (valid values: 0 to channelcount - 1).</param>
/// <returns>A value corresponding to relative voltage level on specified device channels</returns>
public override int ReadPseudoDifferential(int valueChannel, int referenceChannel) => throw new NotSupportedException($"Mcp33xx device does not support {nameof(ReadPseudoDifferential)}.");
/// <summary>
/// Reads a 13 bit signed value from the device using differential inputs
/// </summary>
/// <remarks>
/// The value that is read respresents the difference between the voltage on the value channel and the voltage on the reference channel (valueChannel Reading - referenceChannel Reading).
/// If the valueChannel and the referenceChannel are part of the same channel pairing then the ADC converter will internally subtract the two values. If not then the subtraction is
/// performed in software which may mean that errors are introduced with rapidly changing signals.
/// </remarks>
/// <param name="valueChannel">Channel which represents the signal driving the value in a positive direction (valid values: 0 to channelcount - 1).</param>
/// <param name="referenceChannel">Channel which represents the signal driving the value in a negative direction (valid values: 0 to channelcount - 1).</param>
/// <returns>A 13 bit signed value corresponding to relative voltage level on specified device channels</returns>
public override int ReadDifferential(int valueChannel, int referenceChannel)
{
int retval;
CheckChannelRange(valueChannel, ChannelCount);
CheckChannelRange(referenceChannel, ChannelCount);
if (valueChannel == referenceChannel)
{
throw new ArgumentException(nameof(valueChannel), $"ADC differential channels must be different. {nameof(valueChannel)}: {valueChannel}; {nameof(referenceChannel)}: {referenceChannel}.");
}
// check if it is possible to use hardware differential because both input channels are in the same differential channel pairing
if (valueChannel / 2 == referenceChannel / 2)
{
// read a value from the ADC where the channel is the channel pairing
retval = ReadInternal(channel: valueChannel / 2, valueChannel > referenceChannel ? InputType.InvertedDifferential : InputType.Differential, adcResolutionBits: 13);
// convert 13 bit signed to 32 bit signed
retval = SignExtend(signedValue: retval, signingBit: 12);
}
else // otherwise just subtract two readings
{
retval = ReadInternal(valueChannel, InputType.SingleEnded, adcResolutionBits: 12) -
ReadInternal(referenceChannel, InputType.SingleEnded, adcResolutionBits: 12);
}
return retval;
}
}
}