/
Amg8833.cs
136 lines (112 loc) · 3.69 KB
/
Amg8833.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
using Meadow.Hardware;
using System;
using System.Runtime.InteropServices;
using System.Threading;
namespace Meadow.Foundation.Sensors.Camera;
/// <summary>
/// Represents a Panasonic Grid-EYE infrared array sensor
/// </summary>
public partial class Amg8833 : II2cPeripheral
{
private II2cCommunications _i2cComms;
/// <summary>
/// The default I2C address for the peripheral
/// </summary>
public byte DefaultI2cAddress => (byte)Addresses.Default;
/// <summary>
/// Creates an instance of an AMG8833 sensor
/// </summary>
/// <param name="i2cBus"></param>
public Amg8833(II2cBus i2cBus)
{
_i2cComms = new I2cCommunications(i2cBus, (byte)Addresses.Default);
Initialize();
}
private void Initialize()
{
SetPowerMode(Modes.Normal);
WriteRegister(Registers.RST, Commands.RST_InitialReset);
DisableInterrupts();
WriteRegister(Registers.FPSC, Commands.FPS_Ten);
Thread.Sleep(Constants.StartupDelayMs);
}
private void SetPowerMode(Modes mode)
{
WriteRegister(Registers.PCTL, Modes.Normal);
}
private void DisableInterrupts()
{
WriteRegister(Registers.INTC, (byte)0x00);
}
/// <summary>
/// Reads the temperature of the on-board thermistor
/// </summary>
/// <returns></returns>
public Units.Temperature ReadThermistor()
{
// read 2 bytes
var raw = _i2cComms.ReadRegisterAsUShort((byte)Registers.TTHL);
// see the data sheet on this calculation
var converted = Convert12BitUShortToFloat(raw) * Constants.ThermistorConversion;
return new Units.Temperature(converted, Units.Temperature.UnitType.Celsius);
}
/// <summary>
/// Reads the raw sensor data into the provided buffer.
/// </summary>
/// <param name="buffer">A span of 64 16-but values</param>
public void ReadRawPixels(Span<short> buffer)
{
if (buffer.Length != Constants.PixelArraySize)
{
throw new ArgumentOutOfRangeException($"Expected a buffer of {Constants.PixelArraySize} shorts");
}
Span<byte> tx = stackalloc byte[1];
tx[0] = (byte)Registers.PIXEL_OFFSET;
_i2cComms.Write(tx);
var rx = MemoryMarshal.Cast<short, byte>(buffer);
_i2cComms.Read(rx);
}
/// <summary>
/// Reads the temperature of each pixel in the sensor
/// </summary>
/// <returns></returns>
public Units.Temperature[] ReadPixels()
{
var temps = new Units.Temperature[Constants.PixelArraySize];
Span<short> raw = stackalloc short[Constants.PixelArraySize];
ReadRawPixels(raw);
for (var i = 0; i < raw.Length; i++)
{
var r = Convert12BitUShortToFloat((ushort)raw[i]) * Constants.PixelTempConversion;
temps[i] = new Units.Temperature(r, Units.Temperature.UnitType.Celsius);
}
return temps;
}
private float Convert12BitUShortToFloat(ushort s)
{
// take 11 bits of value
var absolute = s & 0x7ff;
// apply any negative
if ((absolute & 0x800) != 0)
{
return 0 - (float)absolute;
}
return absolute;
}
private void EnableInterrupts(InterruptModes mode)
{
WriteRegister(Registers.INTC, (byte)(0x01 | (byte)mode));
}
private void WriteRegister(Registers register, byte value)
{
_i2cComms.WriteRegister((byte)register, value);
}
private void WriteRegister(Registers register, Modes mode)
{
WriteRegister(register, (byte)mode);
}
private void WriteRegister(Registers register, Commands command)
{
WriteRegister(register, (byte)command);
}
}