diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Datasheet/Mma7660fc.pdf b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Datasheet/Mma7660fc.pdf
new file mode 100644
index 0000000000..0d6947bae6
Binary files /dev/null and b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Datasheet/Mma7660fc.pdf differ
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Mma7660fc.Addresses.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Mma7660fc.Addresses.cs
new file mode 100644
index 0000000000..b1a035ee4b
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Mma7660fc.Addresses.cs
@@ -0,0 +1,20 @@
+namespace Meadow.Foundation.Sensors.Motion
+{
+ public partial class Mma7660fc
+ {
+ ///
+ /// Valid addresses for the sensor.
+ ///
+ public enum Addresses : byte
+ {
+ ///
+ /// Bus address 0x4C
+ ///
+ Address_0x4c = 0x4C,
+ ///
+ /// Bus address 0x4C
+ ///
+ Default = Address_0x4c
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Mma7660fc.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Mma7660fc.Enums.cs
new file mode 100644
index 0000000000..f82a1f9068
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Mma7660fc.Enums.cs
@@ -0,0 +1,121 @@
+namespace Meadow.Foundation.Sensors.Motion
+{
+ public partial class Mma7660fc
+ {
+ ///
+ /// Sensor power mode
+ ///
+ public enum SensorPowerMode : byte
+ {
+ ///
+ /// Device is in standby mode
+ ///
+ Standby = 0,
+ ///
+ /// Device is active
+ ///
+ Active = 1,
+ }
+
+ ///
+ /// Represents the number samples per second
+ ///
+ public enum SampleRate : byte
+ {
+ ///
+ /// 120 samples per second
+ ///
+ _120 = 0,
+ ///
+ /// 64 sample per second
+ ///
+ _64 = 1,
+ ///
+ /// 32 samples per second
+ ///
+ _32 =2,
+ ///
+ /// 16 samples per second
+ ///
+ _16 = 3,
+ ///
+ /// 8 samples per second
+ ///
+ _8 = 4,
+ ///
+ /// 4 samples per second
+ ///
+ _4 = 5,
+ ///
+ /// 2 samples per second
+ ///
+ _2 = 6,
+ ///
+ /// 1 samples per second
+ ///
+ _1 = 7,
+ }
+
+ ///
+ /// Direction/orientation of the device
+ /// UP/DOWN/LEFT/RIGHT
+ ///
+ public enum DirectionType : byte
+ {
+ ///
+ /// Direction unknown
+ ///
+ Unknown = 0,
+ ///
+ /// Device oriented up
+ ///
+ Up = 0b00011000,
+ ///
+ /// Device oriented down
+ ///
+ Down = 0b00010100,
+ ///
+ /// Device oriented right
+ ///
+ Right = 0b00001000,
+ ///
+ /// Device oriented left
+ ///
+ Left = 0b00000100,
+ }
+
+ ///
+ /// Is device face down or face up
+ ///
+ public enum OrientationType : byte
+ {
+ ///
+ /// Orientation unknown
+ ///
+ Unknown = 0,
+ ///
+ /// Device is face up (on back)
+ ///
+ Back = 0b00000010,
+ ///
+ /// Device is face down (on front)
+ ///
+ Front = 0b00000001,
+ }
+
+ ///
+ /// Device Tilt status
+ ///
+ public enum Tilt : byte
+ {
+ ///
+ /// Has the device been shaken
+ ///
+ Shake = 0b10000000,
+ ///
+ /// Has the device been tapped
+ ///
+ Tap = 0b00100000,
+ }
+ }
+}
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Mma7660fc.Registers.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Mma7660fc.Registers.cs
new file mode 100644
index 0000000000..48fb0b5be4
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Mma7660fc.Registers.cs
@@ -0,0 +1,15 @@
+namespace Meadow.Foundation.Sensors.Motion
+{
+ public partial class Mma7660fc
+ {
+ public enum Registers : byte
+ {
+ XOUT = 0x00,
+ YOUT = 0x01,
+ ZOUT = 0x02,
+ TILT = 0x03,
+ Mode = 0x07,
+ SleepRate = 0x08
+ }
+ }
+}
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Mma7660fc.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Mma7660fc.cs
new file mode 100644
index 0000000000..0b419055e3
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Mma7660fc.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Threading.Tasks;
+using Meadow.Hardware;
+using Meadow.Peripherals.Sensors.Motion;
+using Meadow.Units;
+
+namespace Meadow.Foundation.Sensors.Motion
+{
+ ///
+ /// Represents Mma7660fc 3-axis acclerometer
+ ///
+ public partial class Mma7660fc : ByteCommsSensorBase, IAccelerometer
+ {
+ ///
+ /// Raised when new acceleration data is processed
+ ///
+ public event EventHandler> Acceleration3DUpdated = delegate { };
+
+ ///
+ /// Current Acceleration3d value
+ ///
+ public Acceleration3D? Acceleration3D => Conditions;
+
+ public DirectionType Direction { get; set; } = DirectionType.Unknown;
+ public OrientationType Orientation { get; set; } = OrientationType.Unknown;
+
+ ///
+ /// Create a new instance of the Mma7660fc communicating over the I2C interface.
+ ///
+ /// Address of the I2C sensor
+ /// I2C bus
+ public Mma7660fc(II2cBus i2cBus, Addresses address = Addresses.Default)
+ : this(i2cBus, (byte)address)
+ {
+ }
+
+ ///
+ /// Create a new instance of the Mma7660fc communicating over the I2C interface.
+ ///
+ /// Address of the I2C sensor
+ /// I2C bus
+ public Mma7660fc(II2cBus i2cBus, byte address)
+ : base(i2cBus, address)
+ {
+ Initialize();
+ }
+
+ void Initialize()
+ {
+ SetMode(SensorPowerMode.Standby);
+ SetSampleRate(SampleRate._32);
+ SetMode(SensorPowerMode.Active);
+ }
+
+ void SetMode(SensorPowerMode mode)
+ {
+ Peripheral.WriteRegister((byte)Registers.Mode, (byte)mode);
+ }
+
+ ///
+ /// Set sample rate in samples per second
+ ///
+ /// sample rate
+ public void SetSampleRate(SampleRate rate)
+ {
+ Peripheral.WriteRegister((byte)Registers.SleepRate, (byte)rate);
+ }
+
+ ///
+ /// Read sensor data from registers
+ ///
+ ///
+ protected override Task ReadSensor()
+ {
+ return Task.Run(() =>
+ {
+ Direction = (DirectionType)(Peripheral.ReadRegister((byte)Registers.TILT) & 0x1C);
+
+ Orientation = (OrientationType)(Peripheral.ReadRegister((byte)Registers.TILT) & 0x03);
+
+ int xAccel, yAccel, zAccel;
+ byte x, y, z;
+
+ //Signed byte 6-bit 2’s complement data with allowable range of +31 to -32
+ //[5] is 0 if the g direction is positive, 1 if the g direction is negative.
+ do
+ {
+ x = Peripheral.ReadRegister((byte)Registers.XOUT);
+ }
+ //ensure bit 6 isn't set - if so, it means there was a read/write collision ... try again
+ while (x >= 64);
+
+ //check bit 5 and flip to negative
+ if ((x & (1 << 5)) != 0) xAccel = x - 64;
+ else xAccel = x;
+
+ do
+ {
+ y = Peripheral.ReadRegister((byte)Registers.YOUT);
+ }
+ //ensure bit 6 isn't set - if so, it means there was a read/write collision ... try again
+ while (y >= 64);
+
+ if ((y & (1 << 5)) != 0) yAccel = y - 64;
+ else yAccel = y;
+
+ do
+ {
+ z = Peripheral.ReadRegister((byte)Registers.ZOUT);
+ }
+ //ensure bit 6 isn't set - if so, it means there was a read/write collision ... try again
+ while (y >= 64);
+
+ if ((z & (1 << 5)) != 0) zAccel = z - 64;
+ else zAccel = z;
+
+ return new Acceleration3D(
+ new Acceleration(xAccel * 3.0 / 64.0, Acceleration.UnitType.Gravity),
+ new Acceleration(yAccel * 3.0 / 64.0, Acceleration.UnitType.Gravity),
+ new Acceleration(zAccel * 3.0 / 64.0, Acceleration.UnitType.Gravity)
+ );
+ });
+ }
+
+ ///
+ /// Raise event and notify subscribers
+ ///
+ /// Acceleration3d data
+ protected override void RaiseEventsAndNotify(IChangeResult changeResult)
+ {
+ Acceleration3DUpdated?.Invoke(this, changeResult);
+ base.RaiseEventsAndNotify(changeResult);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Sensors.Motion.Mma7660fc.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Sensors.Motion.Mma7660fc.csproj
new file mode 100644
index 0000000000..a9f0f23b0c
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc/Sensors.Motion.Mma7660fc.csproj
@@ -0,0 +1,22 @@
+
+
+ true
+ icon.png
+ Wilderness Labs, Inc
+ netstandard2.1
+ Library
+ Mma7660fc
+ Wilderness Labs, Inc
+ http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/
+ Meadow.Foundation.Sensors.Motion.Mma7660fc
+ https://github.com/WildernessLabs/Meadow.Foundation
+ Meadow.Foundation, Mma7660fc, Accelerometer, Motion
+ 0.1.0
+ false
+ Mma7660fc I2C 3-axis accelerometer
+
+
+
+
+
+
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Samples/Mma7660fc_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Samples/Mma7660fc_Sample/MeadowApp.cs
new file mode 100644
index 0000000000..343a594088
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Samples/Mma7660fc_Sample/MeadowApp.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Threading.Tasks;
+using Meadow;
+using Meadow.Devices;
+using Meadow.Foundation.Sensors.Motion;
+using Meadow.Units;
+using AU = Meadow.Units.Acceleration.UnitType;
+
+namespace Sensors.Motion.Mma7660fc_Sample
+{
+ public class MeadowApp : App
+ {
+ //
+
+ Mma7660fc sensor;
+
+ public MeadowApp()
+ {
+ Console.WriteLine("Initializing");
+
+ // create the sensor driver
+ sensor = new Mma7660fc(Device.CreateI2cBus());
+
+ // classical .NET events can also be used:
+ sensor.Updated += (sender, result) => {
+ Console.WriteLine($"Accel: [X:{result.New.X.MetersPerSecondSquared:N2}," +
+ $"Y:{result.New.Y.MetersPerSecondSquared:N2}," +
+ $"Z:{result.New.Z.MetersPerSecondSquared:N2} (m/s^2)]" +
+ $" Direction: {sensor.Direction}" +
+ $" Orientation: {sensor.Orientation}");
+ };
+
+ // Example that uses an IObersvable subscription to only be notified when the filter is satisfied
+ var consumer = Mma7660fc.CreateObserver(
+ handler: result => Console.WriteLine($"Observer: [x] changed by threshold; new [x]: X:{result.New.X:N2}, old: X:{result.Old?.X:N2}"),
+ // only notify if there's a greater than 0.5G change in the Z direction
+ filter: result => {
+ if (result.Old is { } old) { //c# 8 pattern match syntax. checks for !null and assigns var.
+ return ((result.New - old).Z > new Acceleration(0.5, AU.Gravity));
+ }
+ return false;
+ });
+ sensor.Subscribe(consumer);
+
+ //==== one-off read
+ ReadConditions().Wait();
+
+ // start updating
+ sensor.StartUpdating(TimeSpan.FromMilliseconds(1000));
+ }
+
+ protected async Task ReadConditions()
+ {
+ var result = await sensor.Read();
+ Console.WriteLine("Initial Readings:");
+ Console.WriteLine($"Accel: [X:{result.X.MetersPerSecondSquared:N2}," +
+ $"Y:{result.Y.MetersPerSecondSquared:N2}," +
+ $"Z:{result.Z.MetersPerSecondSquared:N2} (m/s^2)]");
+ }
+
+ //
+ }
+}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Samples/Mma7660fc_Sample/Mma7660fc_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Samples/Mma7660fc_Sample/Mma7660fc_Sample.csproj
new file mode 100644
index 0000000000..79a2715846
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Samples/Mma7660fc_Sample/Mma7660fc_Sample.csproj
@@ -0,0 +1,15 @@
+
+
+ https://github.com/WildernessLabs/Meadow.Foundation
+ Wilderness Labs, Inc
+ Wilderness Labs, Inc
+ true
+ netstandard2.1
+ Exe
+ App
+
+
+
+
+
+
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Samples/Mma7660fc_Sample/Program.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Samples/Mma7660fc_Sample/Program.cs
new file mode 100644
index 0000000000..ea43fb5b4e
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Samples/Mma7660fc_Sample/Program.cs
@@ -0,0 +1,17 @@
+using System.Threading;
+using Meadow;
+
+namespace Sensors.Motion.Mma7660fc_Sample
+{
+ class Program
+ {
+ static IApp app;
+
+ public static void Main(string[] args)
+ {
+ app = new MeadowApp();
+
+ Thread.Sleep(Timeout.Infinite);
+ }
+ }
+}
diff --git a/Source/Meadow.Foundation.sln b/Source/Meadow.Foundation.sln
index b05ddca287..f5b30f0c21 100644
--- a/Source/Meadow.Foundation.sln
+++ b/Source/Meadow.Foundation.sln
@@ -1044,9 +1044,17 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sensors.Weather.SwitchingRa
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SwitchingRainGauge_Sample", "Meadow.Foundation.Peripherals\Sensors.Weather.SwitchingRainGauge\Samples\SwitchingRainGauge_Sample\SwitchingRainGauge_Sample.csproj", "{AFCF1EBC-B7FC-445A-A8E5-AF3724DA8F78}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Meadow.Contracts", "..\..\Meadow.Contracts\Source\Meadow.Contracts\Meadow.Contracts.csproj", "{150569EE-4053-4097-98EE-A455287610B5}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Meadow.Contracts", "..\..\Meadow.Contracts\Source\Meadow.Contracts\Meadow.Contracts.csproj", "{150569EE-4053-4097-98EE-A455287610B5}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Meadow.Units", "..\..\Meadow.Units\Source\Meadow.Units\Meadow.Units.csproj", "{46394970-4495-408F-8A9C-31BEBC47E899}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Meadow.Units", "..\..\Meadow.Units\Source\Meadow.Units\Meadow.Units.csproj", "{46394970-4495-408F-8A9C-31BEBC47E899}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sensors.Motion.Mma7660fc", "Sensors.Motion.Mma7660fc", "{8C70DC80-3DD8-40F7-B781-CDF6D9F8EA42}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sensors.Motion.Mma7660fc", "Meadow.Foundation.Peripherals\Sensors.Motion.Mma7660fc\Driver\Sensors.Motion.Mma7660fc\Sensors.Motion.Mma7660fc.csproj", "{4924CFE6-44B7-4C9D-AE02-1DD2A63E37D9}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{9D13043C-8A59-461A-9A4D-3735D06CED77}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mma7660fc_Sample", "Meadow.Foundation.Peripherals\Sensors.Motion.Mma7660fc\Samples\Mma7660fc_Sample\Mma7660fc_Sample.csproj", "{A2F68D9C-A462-4E7A-A71C-CB773BBB5EED}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -2430,6 +2438,18 @@ Global
{46394970-4495-408F-8A9C-31BEBC47E899}.Debug|Any CPU.Build.0 = Debug|Any CPU
{46394970-4495-408F-8A9C-31BEBC47E899}.Release|Any CPU.ActiveCfg = Release|Any CPU
{46394970-4495-408F-8A9C-31BEBC47E899}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4924CFE6-44B7-4C9D-AE02-1DD2A63E37D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4924CFE6-44B7-4C9D-AE02-1DD2A63E37D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4924CFE6-44B7-4C9D-AE02-1DD2A63E37D9}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+ {4924CFE6-44B7-4C9D-AE02-1DD2A63E37D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4924CFE6-44B7-4C9D-AE02-1DD2A63E37D9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4924CFE6-44B7-4C9D-AE02-1DD2A63E37D9}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {A2F68D9C-A462-4E7A-A71C-CB773BBB5EED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A2F68D9C-A462-4E7A-A71C-CB773BBB5EED}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A2F68D9C-A462-4E7A-A71C-CB773BBB5EED}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+ {A2F68D9C-A462-4E7A-A71C-CB773BBB5EED}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A2F68D9C-A462-4E7A-A71C-CB773BBB5EED}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A2F68D9C-A462-4E7A-A71C-CB773BBB5EED}.Release|Any CPU.Deploy.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -2951,6 +2971,10 @@ Global
{AFCF1EBC-B7FC-445A-A8E5-AF3724DA8F78} = {A29C80C8-E116-4344-A49F-7E58529DC338}
{150569EE-4053-4097-98EE-A455287610B5} = {65C50059-6C22-43E9-88DE-AD73F7F108C8}
{46394970-4495-408F-8A9C-31BEBC47E899} = {65C50059-6C22-43E9-88DE-AD73F7F108C8}
+ {8C70DC80-3DD8-40F7-B781-CDF6D9F8EA42} = {64623FCA-6086-4F0A-A59D-2BF372EA38AA}
+ {4924CFE6-44B7-4C9D-AE02-1DD2A63E37D9} = {8C70DC80-3DD8-40F7-B781-CDF6D9F8EA42}
+ {9D13043C-8A59-461A-9A4D-3735D06CED77} = {8C70DC80-3DD8-40F7-B781-CDF6D9F8EA42}
+ {A2F68D9C-A462-4E7A-A71C-CB773BBB5EED} = {9D13043C-8A59-461A-9A4D-3735D06CED77}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {AF7CA16F-8C38-4546-87A2-5DAAF58A1520}