diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Driver/Controls/Circle.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Driver/Controls/Circle.cs
index dff34de8e5..f13cc1fba4 100644
--- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Driver/Controls/Circle.cs
+++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Driver/Controls/Circle.cs
@@ -1,17 +1,13 @@
namespace Meadow.Foundation.Graphics.MicroLayout;
-public struct Coordinate2D
-{
- public int X { get; set; }
- public int Y { get; set; }
-}
-
///
/// Represents a circle in the user interface.
///
public class Circle : ThemedControl
{
- private Color _foreColor;
+ private Color foreColor;
+ private Point center;
+ private int radius;
///
/// Gets or sets a value indicating whether the Circle is filled with the foreground color.
@@ -25,7 +21,7 @@ public class Circle : ThemedControl
/// The Y coordinate of the circles's center.
/// The radius of the circle.
public Circle(int centerX, int centerY, int radius)
- : base(centerX - radius, centerY - radius, radius * 2, radius * 2)
+ : this(new Point(centerX, centerY), radius)
{
}
@@ -34,9 +30,11 @@ public Circle(int centerX, int centerY, int radius)
///
/// The coordinate of the circles's center.
/// The radius of the circle.
- public Circle(Coordinate2D center, int radius)
+ public Circle(Point center, int radius)
: base(center.X - radius, center.Y - radius, radius * 2, radius * 2)
{
+ this.center = center;
+ this.radius = radius;
}
///
@@ -56,8 +54,8 @@ public override void ApplyTheme(DisplayTheme theme)
///
public Color ForeColor
{
- get => _foreColor;
- set => SetInvalidatingProperty(ref _foreColor, value);
+ get => foreColor;
+ set => SetInvalidatingProperty(ref foreColor, value);
}
///
@@ -65,14 +63,14 @@ public Color ForeColor
///
public int Radius
{
- get => Width / 2;
+ get => radius;
set
{
- // keep centered
- var coeff = (value > Radius) ? -1 : 1;
- var offset = value - Radius;
-
- Width = value * 2;
+ radius = value;
+ Left = center.X - radius;
+ Width = radius * 2;
+ Top = center.Y - radius;
+ Height = radius * 2;
}
}
@@ -84,10 +82,7 @@ protected override void OnDraw(MicroGraphics graphics)
{
if (ForeColor != Color.Transparent)
{
- var radius = (Right - Left) / 2;
- var centerX = Left + radius;
- var centerY = Top + radius;
- graphics.DrawCircle(centerX, centerY, radius, ForeColor, IsFilled);
+ graphics.DrawCircle(center.X, center.Y, radius, ForeColor, IsFilled);
}
}
}
diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Driver/Controls/Crosshair.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Driver/Controls/Crosshair.cs
new file mode 100644
index 0000000000..cbf2162691
--- /dev/null
+++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Driver/Controls/Crosshair.cs
@@ -0,0 +1,52 @@
+namespace Meadow.Foundation.Graphics.MicroLayout;
+
+///
+/// Represents a circle in the user interface.
+///
+public class Crosshair : ThemedControl
+{
+ private Color _foreColor = Color.Black;
+ private int _lineWidth;
+
+ ///
+ /// Initializes a new instance of the class with the specified dimensions and center point.
+ ///
+ /// The X coordinate of the crosshair's center.
+ /// The Y coordinate of the crosshair's center.
+ /// The with and height of the crosshair.
+ /// The line width of the crosshair
+ public Crosshair(int centerX, int centerY, int size = 20, int linewidth = 3)
+ : base(centerX, centerY, size, size)
+ {
+ _lineWidth = linewidth;
+ }
+
+ ///
+ public override void ApplyTheme(DisplayTheme theme)
+ {
+ if (theme != null)
+ {
+ if (theme.ForegroundColor != null) this.ForeColor = theme.ForegroundColor.Value;
+ }
+ }
+
+ ///
+ /// Gets or sets the foreground color of the Crosshair.
+ ///
+ public Color ForeColor
+ {
+ get => _foreColor;
+ set => SetInvalidatingProperty(ref _foreColor, value);
+ }
+
+ ///
+ protected override void OnDraw(MicroGraphics graphics)
+ {
+ if (ForeColor != Color.Transparent)
+ {
+ // position is the center of the crosshair
+ graphics.DrawRectangle(Left - Width / 2, Top - _lineWidth / 2, Width, _lineWidth, ForeColor, true);
+ graphics.DrawRectangle(Left - _lineWidth / 2, Top - Height / 2, _lineWidth, Height, ForeColor, true);
+ }
+ }
+}
diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Driver/DisplayScreen.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Driver/DisplayScreen.cs
index f364ee6468..c453ee6e1f 100644
--- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Driver/DisplayScreen.cs
+++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Driver/DisplayScreen.cs
@@ -12,9 +12,13 @@ public class DisplayScreen
{
private readonly IPixelDisplay _display;
private readonly MicroGraphics _graphics;
- private readonly ITouchScreen? _touchScreen;
private bool _updateInProgress = false;
+ ///
+ /// Gets the Touchscreen associated with the display screen
+ ///
+ public ITouchScreen? TouchScreen { get; }
+
///
/// Gets the collection of controls on the display screen.
///
@@ -56,12 +60,12 @@ public DisplayScreen(IPixelDisplay physicalDisplay, RotationType rotation = Rota
_graphics.Rotation = rotation;
- _touchScreen = touchScreen;
+ TouchScreen = touchScreen;
- if (_touchScreen != null)
+ if (TouchScreen != null)
{
- _touchScreen.TouchDown += _touchScreen_TouchDown;
- _touchScreen.TouchUp += _touchScreen_TouchUp;
+ TouchScreen.TouchDown += _touchScreen_TouchDown;
+ TouchScreen.TouchUp += _touchScreen_TouchUp;
}
if (theme?.Font != null)
@@ -81,24 +85,31 @@ public DisplayScreen(IPixelDisplay physicalDisplay, RotationType rotation = Rota
}
}
- private void _touchScreen_TouchUp(int x, int y)
+ private void _touchScreen_TouchUp(ITouchScreen source, TouchPoint point)
{
- lock (Controls.SyncRoot)
+ if (Monitor.TryEnter(Controls.SyncRoot, 100))
{
- foreach (var control in Controls)
+ try
{
- if (control is IClickableControl c)
+ foreach (var control in Controls)
{
- if (control.Contains(x, y))
+ if (control is IClickableControl c)
{
- c.Pressed = false;
+ if (control.Contains(point.ScreenX, point.ScreenY))
+ {
+ c.Pressed = false;
+ }
}
}
}
+ finally
+ {
+ Monitor.Exit(Controls.SyncRoot);
+ }
}
}
- private void _touchScreen_TouchDown(int x, int y)
+ private void _touchScreen_TouchDown(ITouchScreen source, TouchPoint point)
{
lock (Controls.SyncRoot)
{
@@ -106,7 +117,7 @@ private void _touchScreen_TouchDown(int x, int y)
{
if (control is IClickableControl c)
{
- if (control.Contains(x, y))
+ if (control.Contains(point.ScreenX, point.ScreenY))
{
c.Pressed = true;
}
diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Samples/Ili9488Charts_Sample/Ili9488Charts_Sample.csproj b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Samples/Ili9488Charts_Sample/Ili9488Charts_Sample.csproj
index 95c0965525..26b8a6655d 100644
--- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Samples/Ili9488Charts_Sample/Ili9488Charts_Sample.csproj
+++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Samples/Ili9488Charts_Sample/Ili9488Charts_Sample.csproj
@@ -15,10 +15,4 @@
-
-
- PreserveNewest
-
-
-
diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Samples/Ili9488Charts_Sample/libmpsse.dll b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Samples/Ili9488Charts_Sample/libmpsse.dll
deleted file mode 100644
index a3d19379e8..0000000000
Binary files a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Samples/Ili9488Charts_Sample/libmpsse.dll and /dev/null differ
diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Samples/MAX7219_Sample/MAX7219_Sample.csproj b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Samples/MAX7219_Sample/MAX7219_Sample.csproj
index f10c615d58..8d8e294c89 100644
--- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Samples/MAX7219_Sample/MAX7219_Sample.csproj
+++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Samples/MAX7219_Sample/MAX7219_Sample.csproj
@@ -2,7 +2,7 @@
Exe
- net7.0
+ net7.0-windows
enable
enable
@@ -15,10 +15,4 @@
-
-
- PreserveNewest
-
-
-
diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Samples/MAX7219_Sample/libmpsse.dll b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Samples/MAX7219_Sample/libmpsse.dll
deleted file mode 100644
index a3d19379e8..0000000000
Binary files a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Samples/MAX7219_Sample/libmpsse.dll and /dev/null differ
diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Gtk/Driver/Gtk.cs b/Source/Meadow.Foundation.Peripherals/Displays.Gtk/Driver/Gtk.cs
index 4e55c7b192..1b6ede763e 100644
--- a/Source/Meadow.Foundation.Peripherals/Displays.Gtk/Driver/Gtk.cs
+++ b/Source/Meadow.Foundation.Peripherals/Displays.Gtk/Driver/Gtk.cs
@@ -12,18 +12,14 @@ namespace Meadow.Foundation.Displays;
///
public class GtkDisplay : IPixelDisplay, ITouchScreen
{
- ///
- /// Event fired when the display gets a mouse down
- ///
+ ///
public event Hardware.TouchEventHandler TouchDown = default!;
- ///
- /// Event fired when the display gets a mouse up
- ///
+ ///
public event Hardware.TouchEventHandler TouchUp = default!;
- ///
- /// Event fired when the display gets a mouse click
- ///
+ ///
public event Hardware.TouchEventHandler TouchClick = default!;
+ ///
+ public event Hardware.TouchEventHandler TouchMoved = default!;
private Window _window = default!;
private IPixelBuffer _pixelBuffer = default!;
@@ -34,6 +30,9 @@ public class GtkDisplay : IPixelDisplay, ITouchScreen
private EventWaitHandle ShowComplete { get; } = new EventWaitHandle(true, EventResetMode.ManualReset);
+ ///
+ public RotationType Rotation => RotationType.Normal;
+
///
public IPixelBuffer PixelBuffer => _pixelBuffer;
@@ -49,6 +48,9 @@ public class GtkDisplay : IPixelDisplay, ITouchScreen
///
public ColorMode SupportedColorModes => ColorMode.Format24bppRgb888 | ColorMode.Format16bppRgb565 | ColorMode.Format32bppRgba8888;
+ ///
+ public bool IsTouched { get; private set; }
+
static GtkDisplay()
{
Application.Init();
@@ -108,15 +110,15 @@ private void Initialize(int width, int height, ColorMode mode)
private void RaiseTouchDown(double x, double y)
{
_leftButtonState = true;
- TouchDown?.Invoke((int)x, (int)y);
+ TouchDown?.Invoke(this, TouchPoint.FromScreenData((int)x, (int)y, 0, (int)x, (int)y, 0));
}
private void RaiseTouchUp(double x, double y)
{
- TouchUp?.Invoke((int)x, (int)y);
+ TouchUp?.Invoke(this, TouchPoint.FromScreenData((int)x, (int)y, 0, (int)x, (int)y, 0));
if (_leftButtonState)
{
- TouchClick?.Invoke((int)x, (int)y);
+ TouchClick?.Invoke(this, TouchPoint.FromScreenData((int)x, (int)y, 0, (int)x, (int)y, 0));
}
_leftButtonState = false;
@@ -133,9 +135,11 @@ private void WindowWidgetEvent(object o, WidgetEventArgs args)
{
case Gdk.ModifierType.None:
RaiseTouchDown(b.X, b.Y);
+ IsTouched = true;
break;
case Gdk.ModifierType.Button1Mask:
RaiseTouchUp(b.X, b.Y);
+ IsTouched = false;
break;
}
break;
diff --git a/Source/Meadow.Foundation.Peripherals/Displays.WinForms/Driver/WinForms.cs b/Source/Meadow.Foundation.Peripherals/Displays.WinForms/Driver/WinForms.cs
index 453b13dd21..89ae850c3f 100644
--- a/Source/Meadow.Foundation.Peripherals/Displays.WinForms/Driver/WinForms.cs
+++ b/Source/Meadow.Foundation.Peripherals/Displays.WinForms/Driver/WinForms.cs
@@ -8,21 +8,20 @@ namespace Meadow.Foundation.Displays;
///
public class WinFormsDisplay : Form, IPixelDisplay, ITouchScreen
{
- ///
- /// Event fired when the display gets a mouse down
- ///
- public event TouchEventHandler TouchDown = default!;
- ///
- /// Event fired when the display gets a mouse up
- ///
- public event TouchEventHandler TouchUp = default!;
- ///
- /// Event fired when the display gets a mouse click
- ///
- public event TouchEventHandler TouchClick = default!;
+ ///
+ public event TouchEventHandler? TouchDown = default!;
+ ///
+ public event TouchEventHandler? TouchUp = default!;
+ ///
+ public event TouchEventHandler? TouchClick = default!;
+ ///
+ public event TouchEventHandler? TouchMoved = default!;
private readonly WinFormsPixelBuffer _buffer;
+ ///
+ public RotationType Rotation => RotationType.Normal;
+
///
public ColorMode ColorMode => PixelBuffer.ColorMode;
@@ -32,6 +31,9 @@ public class WinFormsDisplay : Form, IPixelDisplay, ITouchScreen
///
public ColorMode SupportedColorModes => ColorMode.Format24bppRgb888;
+ ///
+ public bool IsTouched { get; private set; }
+
///
/// Create a new WinFormsDisplay
///
@@ -64,21 +66,23 @@ protected override void Dispose(bool disposing)
///
protected override void OnMouseDown(MouseEventArgs e)
{
- TouchDown?.Invoke(e.X, e.Y);
+ TouchDown?.Invoke(this, TouchPoint.FromScreenData(e.X, e.Y, 0, e.X, e.Y, 0));
+ IsTouched = true;
base.OnMouseDown(e);
}
///
protected override void OnMouseUp(MouseEventArgs e)
{
- TouchUp?.Invoke(e.X, e.Y);
+ TouchUp?.Invoke(this, TouchPoint.FromScreenData(e.X, e.Y, 0, e.X, e.Y, 0));
+ IsTouched = false;
base.OnMouseUp(e);
}
///
protected override void OnClick(EventArgs e)
{
- TouchClick?.Invoke(-1, -1);
+ TouchClick?.Invoke(this, TouchPoint.FromScreenData(-1, -1, 0, -1, -1, 0));
base.OnClick(e);
}
diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ftxxxx/Samples/Ft232h_Sample/Ft232h_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ftxxxx/Samples/Ft232h_Sample/Ft232h_Sample.csproj
index 0f8aa6074a..2f1fbbc706 100644
--- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ftxxxx/Samples/Ft232h_Sample/Ft232h_Sample.csproj
+++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ftxxxx/Samples/Ft232h_Sample/Ft232h_Sample.csproj
@@ -7,12 +7,6 @@
enable
-
-
- PreserveNewest
-
-
-
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Tsc2004/Samples/Tsc2004_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Tsc2004/Samples/Tsc2004_Sample/MeadowApp.cs
index 76eacf5dcd..e5e8df8d99 100644
--- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Tsc2004/Samples/Tsc2004_Sample/MeadowApp.cs
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Tsc2004/Samples/Tsc2004_Sample/MeadowApp.cs
@@ -7,13 +7,13 @@
using System.Threading;
using System.Threading.Tasks;
-namespace Bbq10Keyboard_Sample
+namespace Tsc2004_Sample
{
public class MeadowApp : App
{
//
- Tsc2004 touchScreen;
+ private Tsc2004 touchScreen;
public override Task Initialize()
{
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Tsc2004/Samples/Tsc2004_Sample/Tsc2004_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Tsc2004/Samples/Tsc2004_Sample/Tsc2004_Sample.csproj
index 60c6a684d5..ec3c2ddc26 100644
--- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Tsc2004/Samples/Tsc2004_Sample/Tsc2004_Sample.csproj
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Tsc2004/Samples/Tsc2004_Sample/Tsc2004_Sample.csproj
@@ -9,9 +9,4 @@
-
-
- Always
-
-
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Tsc2004/Samples/Tsc2004_Sample/meadow.config.yaml b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Tsc2004/Samples/Tsc2004_Sample/meadow.config.yaml
deleted file mode 100644
index 32363cb69c..0000000000
--- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Tsc2004/Samples/Tsc2004_Sample/meadow.config.yaml
+++ /dev/null
@@ -1,2 +0,0 @@
-MonoControl:
- Options: --jit
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Xpt2046/Datasheet/XPT2046.pdf b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Xpt2046/Datasheet/XPT2046.pdf
new file mode 100644
index 0000000000..f625c06d33
Binary files /dev/null and b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Xpt2046/Datasheet/XPT2046.pdf differ
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Xpt2046/Driver/Sensors.Hid.Xpt2046.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Xpt2046/Driver/Sensors.Hid.Xpt2046.csproj
new file mode 100644
index 0000000000..7d68887bdc
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Xpt2046/Driver/Sensors.Hid.Xpt2046.csproj
@@ -0,0 +1,25 @@
+
+
+ 1.8.0
+ enable
+ 10.0
+ Apache-2.0
+ true
+ icon.png
+ Wilderness Labs, Inc
+ netstandard2.1
+ Library
+ Xpt2046
+ Wilderness Labs, Inc
+ http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/
+ Meadow.Foundation.Sensors.Hid.Xpt2046
+ https://github.com/WildernessLabs/Meadow.Foundation
+ Meadow.Foundation,touch,screen,display,capacitive,XPT2046
+ true
+ Xpt2046 SPI, 4-wire resistive touch screen controller
+
+
+
+
+
+
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Xpt2046/Driver/Xpt2046.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Xpt2046/Driver/Xpt2046.Enums.cs
new file mode 100644
index 0000000000..4695a3b457
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Xpt2046/Driver/Xpt2046.Enums.cs
@@ -0,0 +1,26 @@
+using System;
+
+namespace Meadow.Foundation.Sensors.Hid;
+
+public partial class Xpt2046
+{
+ private enum Mode
+ {
+ Bits_12 = 0,
+ Bits_8 = 8
+ }
+
+ private enum VoltageReference
+ {
+ SingleEnded = 0,
+ Differential = 4
+ }
+
+ [Flags]
+ private enum PowerState
+ {
+ PowerDown = 0,
+ Adc = 1,
+ Reference = 2,
+ }
+}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Xpt2046/Driver/Xpt2046.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Xpt2046/Driver/Xpt2046.cs
new file mode 100644
index 0000000000..98bc62514a
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Xpt2046/Driver/Xpt2046.cs
@@ -0,0 +1,242 @@
+using Meadow.Hardware;
+using Meadow.Peripherals.Displays;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+
+namespace Meadow.Foundation.Sensors.Hid
+{
+ ///
+ /// Represents an XPT2046 4-wire touch screen controller
+ ///
+ public partial class Xpt2046 : ICalibratableTouchscreen
+ {
+ ///
+ public event TouchEventHandler? TouchDown = null;
+ ///
+ public event TouchEventHandler? TouchUp = null;
+ ///
+ public event TouchEventHandler? TouchClick = null;
+ ///
+ public event TouchEventHandler? TouchMoved = null;
+
+ private const int SamplePeriodMilliseconds = 100;
+ private const byte StartBit = 0x80;
+
+ private readonly ISpiBus spiBus;
+ private readonly IDigitalInterruptPort touchInterrupt;
+ private readonly IDigitalOutputPort? chipSelect = null;
+ private Timer sampleTimer;
+ private bool isSampling = false;
+ private bool firstTouch = true;
+ private TouchPoint? lastTouchPosition;
+ private TouchPoint? penultimatePosition;
+ private float mX, mY, cX, cY; // linear calibration coefficeints
+
+ ///
+ public RotationType Rotation { get; }
+ ///
+ public bool IsCalibrated { get; private set; }
+
+ ///
+ public bool IsTouched => isSampling;
+
+ ///
+ /// Creates an instance of an Xpt2046
+ ///
+ /// The ISpiBus connected to the touchscreen controller
+ /// The interrupt port connected to the touchscreen controller
+ /// The chip select port for the touchscreen controller
+ /// The touchscreen rotation (not the display rotation)
+ public Xpt2046(
+ ISpiBus spiBus,
+ IDigitalInterruptPort touchInterrupt,
+ IDigitalOutputPort? chipSelect,
+ RotationType rotation = RotationType.Normal)
+ {
+ sampleTimer = new Timer(SampleTimerProc, null, -1, -1);
+
+ this.spiBus = spiBus;
+ this.touchInterrupt = touchInterrupt;
+ this.chipSelect = chipSelect;
+ Rotation = rotation;
+
+ touchInterrupt.Changed += OnTouchInterrupt;
+ }
+
+ private TouchPoint ConvertRawToTouchPoint(ushort rawX, ushort rawY, ushort rawZ)
+ {
+ int x, y;
+
+ // rotate
+ switch (Rotation)
+ {
+ case RotationType._90Degrees:
+ x = 4095 - rawY;
+ y = rawX;
+ break;
+ case RotationType._180Degrees:
+ x = 4095 - rawX;
+ y = 4095 - rawY;
+ break;
+ case RotationType._270Degrees:
+ x = rawY;
+ y = 4095 - rawX;
+ break;
+ default:
+ x = rawX;
+ y = rawY;
+ break;
+ }
+
+ if (!IsCalibrated)
+ {
+ return TouchPoint.FromRawData(x, y, rawZ);
+ }
+
+ // scale for calibration
+ var scaledX = ((x * mX) + cX);
+ var scaledY = ((y * mY) + cY);
+
+ return TouchPoint.FromScreenData((int)scaledX, (int)scaledY, rawZ, rawX, rawY, rawZ);
+ }
+
+ private void OnTouchInterrupt(object sender, DigitalPortResult e)
+ {
+ // high is not touched, low is touched
+ if (!isSampling)
+ {
+ sampleTimer.Change(0, -1);
+ }
+ }
+
+ private void SampleTimerProc(object o)
+ {
+ if (touchInterrupt.State)
+ {
+ // the actual "last" reading for up is often garbage, so go back one before that if we have it
+ if (penultimatePosition != null)
+ {
+ TouchUp?.Invoke(this, penultimatePosition.Value);
+ }
+ else if (lastTouchPosition != null)
+ {
+ TouchUp?.Invoke(this, lastTouchPosition.Value);
+ }
+ isSampling = false;
+ firstTouch = true;
+ lastTouchPosition = null;
+ penultimatePosition = null;
+ return;
+ }
+
+ isSampling = true;
+
+ var z = ReadZ();
+ var x = ReadX();
+ var y = ReadY();
+ EnableIrq();
+
+ var position = ConvertRawToTouchPoint(x, y, z);
+
+ try
+ {
+ if (firstTouch)
+ {
+ firstTouch = false;
+ lastTouchPosition = position;
+ if (lastTouchPosition != null)
+ {
+ TouchDown?.Invoke(this, lastTouchPosition.Value);
+ }
+ }
+ else
+ {
+ if (!position.Equals(lastTouchPosition))
+ {
+ penultimatePosition = lastTouchPosition;
+ lastTouchPosition = position;
+ if (lastTouchPosition != null)
+ {
+ TouchMoved?.Invoke(this, lastTouchPosition.Value);
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Resolver.Log.Warn($"Touchscreen event handler error: {ex.Message}");
+ // ignore any unhandled handler exceptions
+ }
+
+ sampleTimer.Change(SamplePeriodMilliseconds, -1);
+ }
+
+ private ushort ReadX()
+ {
+ return ReadChannel(Channel.X);
+ }
+
+ private ushort ReadY()
+ {
+ return ReadChannel(Channel.Y);
+ }
+
+ private ushort ReadZ()
+ {
+ return ReadChannel(Channel.Z2);
+ }
+
+ private void EnableIrq()
+ {
+ ReadChannel(Channel.Temp, PowerState.PowerDown);
+ }
+
+ private ushort ReadChannel(Channel channel, PowerState postSamplePowerState = PowerState.Adc, Mode mode = Mode.Bits_12, VoltageReference vref = VoltageReference.Differential)
+ {
+ Span txBuffer = stackalloc byte[3];
+ Span rxBuffer = stackalloc byte[3];
+
+ txBuffer[0] = (byte)(StartBit | (byte)channel | (byte)mode | (byte)vref | (byte)postSamplePowerState);
+
+ spiBus.Exchange(chipSelect, txBuffer, rxBuffer);
+
+ return (ushort)((rxBuffer[1] >> 3) << 8 | (rxBuffer[2] >> 3));
+ }
+
+ ///
+ public void SetCalibrationData(IEnumerable data)
+ {
+ var points = data.ToArray();
+ if (points.Length != 2) { throw new ArgumentException("This touchscreen requires exactly 2 calibration points"); }
+
+ // basic point validation
+ if (points[1].RawX - points[0].RawX == 0 ||
+ points[1].RawY - points[0].RawY == 0 ||
+ points[1].ScreenX - points[0].ScreenX == 0 ||
+ points[1].ScreenY - points[0].ScreenY == 0)
+ {
+ throw new ArgumentOutOfRangeException("Invalid calibration data");
+ }
+
+ // simple 2-point linear calibration (fine for small screens)
+
+ mX = (points[1].ScreenX - points[0].ScreenX) / (float)(points[1].RawX - points[0].RawX);
+ cX = points[0].ScreenX - (points[0].RawX * mX);
+ mY = (points[1].ScreenY - points[0].ScreenY) / (float)(points[1].RawY - points[0].RawY);
+ cY = points[0].ScreenY - (points[0].RawY * mY);
+
+ IsCalibrated = true;
+ }
+
+ private enum Channel : byte
+ {
+ Temp = 0x00,
+ X = 1 << 4,
+ Z1 = 3 << 4,
+ Z2 = 4 << 4,
+ Y = 5 << 4,
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Xpt2046/Samples/Xpt2046_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Xpt2046/Samples/Xpt2046_Sample/MeadowApp.cs
new file mode 100644
index 0000000000..cd3a949a1a
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Xpt2046/Samples/Xpt2046_Sample/MeadowApp.cs
@@ -0,0 +1,38 @@
+using Meadow;
+using Meadow.Devices;
+using Meadow.Foundation.Sensors.Hid;
+using Meadow.Hardware;
+using System.Threading.Tasks;
+
+namespace Xpt2046_Sample
+{
+ public class MeadowApp : App
+ {
+ //
+
+ private Xpt2046 touchScreen;
+
+ public override Task Initialize()
+ {
+ Resolver.Log.Info("Initialize...");
+
+ var i2cBus = Device.CreateI2cBus(I2cBusSpeed.Fast);
+
+ touchScreen = new Xpt2046(
+ Device.CreateSpiBus(),
+ Device.Pins.D04.CreateDigitalInterruptPort(InterruptMode.EdgeFalling, ResistorMode.InternalPullUp),
+ Device.Pins.D05.CreateDigitalOutputPort(true));
+
+ touchScreen.TouchDown += TouchScreen_TouchDown;
+
+ return Task.CompletedTask;
+ }
+
+ private void TouchScreen_TouchDown(ITouchScreen sender, TouchPoint point)
+ {
+ Resolver.Log.Info($"Touch at location: X:{point.ScreenX}, Y:{point.ScreenY}");
+ }
+
+ //
+ }
+}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Xpt2046/Samples/Xpt2046_Sample/Xpt2046_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Xpt2046/Samples/Xpt2046_Sample/Xpt2046_Sample.csproj
new file mode 100644
index 0000000000..daf355f523
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Xpt2046/Samples/Xpt2046_Sample/Xpt2046_Sample.csproj
@@ -0,0 +1,12 @@
+
+
+ netstandard2.1
+ true
+ Library
+ App
+
+
+
+
+
+
diff --git a/Source/Meadow.Foundation.sln b/Source/Meadow.Foundation.sln
index 4523e93c07..eb2f244f49 100644
--- a/Source/Meadow.Foundation.sln
+++ b/Source/Meadow.Foundation.sln
@@ -1055,6 +1055,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sw18AB_Sample", "Meadow.Fou
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sht4x_Sample", "Meadow.Foundation.Peripherals\Sensors.Atmospheric.Sht4x\Samples\Sht4x_Sample\Sht4x_Sample.csproj", "{831C87F3-4925-4311-83A4-C07CE4CD109E}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet", "..\..\MQTTnet\Source\MQTTnet\MQTTnet.csproj", "{810BF526-53F8-4DFB-A32A-A67CB5FFF785}"
+EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sensors.Light.AnalogLightSensor_Sample", "Meadow.Foundation.Core.Samples\Sensors.Light.AnalogLightSensor_Sample\Sensors.Light.AnalogLightSensor_Sample.csproj", "{5A2538C7-D110-4DFB-A77B-C328CDDF7848}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Thermistor", "Thermistor", "{FF251CAE-8D0B-45E2-BAA4-FE2991D527F7}"
@@ -1115,10 +1117,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Meadow.Modbus", "..\..\Mead
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Meadow.F7", "..\..\Meadow.Core\source\implementations\f7\Meadow.F7\Meadow.F7.csproj", "{404AAC33-B6F1-4EA3-A246-FD9D8A95E93F}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Ft232h", "Ft232h", "{4E0052C2-559D-4509-9C42-C6451B1F1FFC}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{67B5150B-2FDE-4EA8-93EE-8BB31D5D7789}"
+EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WinForms", "WinForms", "{BBF136B7-361C-4FC2-AACA-6B6ED79BDCF1}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Displays.WinForms", "Meadow.Foundation.Peripherals\Displays.WinForms\Driver\Displays.WinForms.csproj", "{2DFB37A0-07FE-479F-8B30-D2B5F7E209D2}"
+EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Gtk", "Gtk", "{14ACE12B-5B23-4FF3-B3C2-BFECB21064A6}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Displays.Gtk", "Meadow.Foundation.Peripherals\Displays.Gtk\Driver\Displays.Gtk.csproj", "{768E2B04-FBE8-4464-B5DE-F5AA010E9D33}"
+EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Epd5in65f_Sample", "Meadow.Foundation.Peripherals\Displays.ePaperWaveShare\Samples\Epd5in65f_Sample\Epd5in65f_Sample.csproj", "{16A387A9-80AA-4080-85F6-10F53D6EC99E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Pmsa003i", "Pmsa003i", "{AD6DD7B6-B896-44B9-904E-9330C2C842C7}"
@@ -1443,19 +1453,19 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{FC2E
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pct2075_Sample", "Meadow.Foundation.Peripherals\Sensors.Temperature.Pct2075\Samples\Pct2075_Sample\Pct2075_Sample.csproj", "{2B29B1A8-8903-4335-A5CC-6FFBD9069C2D}"
EndProject
-Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "Displays.WinForms", "Meadow.Foundation.Peripherals\Displays.WinForms\Driver\Displays.WinForms.csproj", "{FAE78BFF-B2D4-4AAD-9E45-A52A4AB6AC28}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Touchscreen", "Touchscreen", "{B773E1A0-FA17-4D5A-BAF9-29CA3CF00789}"
EndProject
-Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "Displays.Gtk", "Meadow.Foundation.Peripherals\Displays.Gtk\Driver\Displays.Gtk.csproj", "{07DE237C-5288-4577-9443-D2B7D43D3775}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Xpt2046", "Xpt2046", "{FB71B923-4A40-4C68-BEA9-846A57813ED2}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Ftxxxx", "Ftxxxx", "{FB4CEFDD-BEE3-4858-8A53-D92C4D1B6297}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sensors.Hid.Xpt2046", "Meadow.Foundation.Peripherals\Sensors.Hid.Xpt2046\Driver\Sensors.Hid.Xpt2046.csproj", "{C399419B-04D5-40A2-9501-F21DEDAF3EC6}"
EndProject
-Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "MQTTnet", "..\..\MQTTnet\Source\MQTTnet\MQTTnet.csproj", "{6768E5DB-C1BA-43FB-A7FF-668982CF3CC6}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICs.IOExpanders.Ftxxxx", "Meadow.Foundation.Peripherals\ICs.IOExpanders.Ftxxxx\Driver\ICs.IOExpanders.Ftxxxx.csproj", "{5D1417F3-5B31-4560-9943-DF5F74FA14C0}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{5DCA2786-ED9A-47E9-8A07-6F3FF2B73A53}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ft232h_Sample", "Meadow.Foundation.Peripherals\ICs.IOExpanders.Ftxxxx\Samples\Ft232h_Sample\Ft232h_Sample.csproj", "{0189CCB2-916B-4448-BC3B-665736BB8806}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICs.IOExpanders.Ftxxxx", "Meadow.Foundation.Peripherals\ICs.IOExpanders.Ftxxxx\Driver\ICs.IOExpanders.Ftxxxx.csproj", "{D0167772-53C1-4ECB-A486-E36D354FC887}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{927B2E17-5220-45B0-B1D7-0BB92A430E68}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ft232h_Sample", "Meadow.Foundation.Peripherals\ICs.IOExpanders.Ftxxxx\Samples\Ft232h_Sample\Ft232h_Sample.csproj", "{BE8B85B9-5FC3-439F-86A8-4D4E028B9DC3}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Xpt2046_Sample", "Meadow.Foundation.Peripherals\Sensors.Hid.Xpt2046\Samples\Xpt2046_Sample\Xpt2046_Sample.csproj", "{0592DDD2-FBEE-45DC-9DB0-191EF38FE12C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -2865,6 +2875,10 @@ Global
{831C87F3-4925-4311-83A4-C07CE4CD109E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{831C87F3-4925-4311-83A4-C07CE4CD109E}.Release|Any CPU.Build.0 = Release|Any CPU
{831C87F3-4925-4311-83A4-C07CE4CD109E}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {810BF526-53F8-4DFB-A32A-A67CB5FFF785}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {810BF526-53F8-4DFB-A32A-A67CB5FFF785}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {810BF526-53F8-4DFB-A32A-A67CB5FFF785}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {810BF526-53F8-4DFB-A32A-A67CB5FFF785}.Release|Any CPU.Build.0 = Release|Any CPU
{5A2538C7-D110-4DFB-A77B-C328CDDF7848}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5A2538C7-D110-4DFB-A77B-C328CDDF7848}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5A2538C7-D110-4DFB-A77B-C328CDDF7848}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
@@ -2969,6 +2983,14 @@ Global
{404AAC33-B6F1-4EA3-A246-FD9D8A95E93F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{404AAC33-B6F1-4EA3-A246-FD9D8A95E93F}.Release|Any CPU.Build.0 = Release|Any CPU
{404AAC33-B6F1-4EA3-A246-FD9D8A95E93F}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {2DFB37A0-07FE-479F-8B30-D2B5F7E209D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2DFB37A0-07FE-479F-8B30-D2B5F7E209D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2DFB37A0-07FE-479F-8B30-D2B5F7E209D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2DFB37A0-07FE-479F-8B30-D2B5F7E209D2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {768E2B04-FBE8-4464-B5DE-F5AA010E9D33}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {768E2B04-FBE8-4464-B5DE-F5AA010E9D33}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {768E2B04-FBE8-4464-B5DE-F5AA010E9D33}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {768E2B04-FBE8-4464-B5DE-F5AA010E9D33}.Release|Any CPU.Build.0 = Release|Any CPU
{16A387A9-80AA-4080-85F6-10F53D6EC99E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{16A387A9-80AA-4080-85F6-10F53D6EC99E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{16A387A9-80AA-4080-85F6-10F53D6EC99E}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
@@ -3499,26 +3521,28 @@ Global
{2B29B1A8-8903-4335-A5CC-6FFBD9069C2D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2B29B1A8-8903-4335-A5CC-6FFBD9069C2D}.Release|Any CPU.Build.0 = Release|Any CPU
{2B29B1A8-8903-4335-A5CC-6FFBD9069C2D}.Release|Any CPU.Deploy.0 = Release|Any CPU
- {FAE78BFF-B2D4-4AAD-9E45-A52A4AB6AC28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {FAE78BFF-B2D4-4AAD-9E45-A52A4AB6AC28}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {FAE78BFF-B2D4-4AAD-9E45-A52A4AB6AC28}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {FAE78BFF-B2D4-4AAD-9E45-A52A4AB6AC28}.Release|Any CPU.Build.0 = Release|Any CPU
- {07DE237C-5288-4577-9443-D2B7D43D3775}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {07DE237C-5288-4577-9443-D2B7D43D3775}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {07DE237C-5288-4577-9443-D2B7D43D3775}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {07DE237C-5288-4577-9443-D2B7D43D3775}.Release|Any CPU.Build.0 = Release|Any CPU
- {6768E5DB-C1BA-43FB-A7FF-668982CF3CC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {6768E5DB-C1BA-43FB-A7FF-668982CF3CC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {6768E5DB-C1BA-43FB-A7FF-668982CF3CC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {6768E5DB-C1BA-43FB-A7FF-668982CF3CC6}.Release|Any CPU.Build.0 = Release|Any CPU
- {D0167772-53C1-4ECB-A486-E36D354FC887}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {D0167772-53C1-4ECB-A486-E36D354FC887}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {D0167772-53C1-4ECB-A486-E36D354FC887}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {D0167772-53C1-4ECB-A486-E36D354FC887}.Release|Any CPU.Build.0 = Release|Any CPU
- {BE8B85B9-5FC3-439F-86A8-4D4E028B9DC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {BE8B85B9-5FC3-439F-86A8-4D4E028B9DC3}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {BE8B85B9-5FC3-439F-86A8-4D4E028B9DC3}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {BE8B85B9-5FC3-439F-86A8-4D4E028B9DC3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C399419B-04D5-40A2-9501-F21DEDAF3EC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C399419B-04D5-40A2-9501-F21DEDAF3EC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C399419B-04D5-40A2-9501-F21DEDAF3EC6}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+ {C399419B-04D5-40A2-9501-F21DEDAF3EC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C399419B-04D5-40A2-9501-F21DEDAF3EC6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C399419B-04D5-40A2-9501-F21DEDAF3EC6}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {5D1417F3-5B31-4560-9943-DF5F74FA14C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5D1417F3-5B31-4560-9943-DF5F74FA14C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5D1417F3-5B31-4560-9943-DF5F74FA14C0}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+ {5D1417F3-5B31-4560-9943-DF5F74FA14C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5D1417F3-5B31-4560-9943-DF5F74FA14C0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5D1417F3-5B31-4560-9943-DF5F74FA14C0}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {0189CCB2-916B-4448-BC3B-665736BB8806}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0189CCB2-916B-4448-BC3B-665736BB8806}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0189CCB2-916B-4448-BC3B-665736BB8806}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0189CCB2-916B-4448-BC3B-665736BB8806}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0592DDD2-FBEE-45DC-9DB0-191EF38FE12C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0592DDD2-FBEE-45DC-9DB0-191EF38FE12C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0592DDD2-FBEE-45DC-9DB0-191EF38FE12C}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+ {0592DDD2-FBEE-45DC-9DB0-191EF38FE12C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0592DDD2-FBEE-45DC-9DB0-191EF38FE12C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0592DDD2-FBEE-45DC-9DB0-191EF38FE12C}.Release|Any CPU.Deploy.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -3912,7 +3936,7 @@ Global
{6AF2F8E5-423F-4EF7-9AB6-1978792598B7} = {8FB70D12-1111-480B-B64C-B8EB65977F58}
{BD5FABCC-4C2A-4DA6-A506-7152C72D29E7} = {8FB70D12-1111-480B-B64C-B8EB65977F58}
{598D3695-BEB7-4BD7-AE6A-C296F36265E7} = {0BB488AA-E23E-4697-BBD9-4A17B21BFCD7}
- {372B055D-2279-47D2-B1A8-AB1E5670202F} = {818BF624-10A7-45B2-9BEE-4C411CD9CA06}
+ {372B055D-2279-47D2-B1A8-AB1E5670202F} = {B773E1A0-FA17-4D5A-BAF9-29CA3CF00789}
{8908AAA5-53DD-4526-AAF8-01308F1316EF} = {372B055D-2279-47D2-B1A8-AB1E5670202F}
{B167E0C6-F2D8-4B4F-B814-578B72B083BE} = {372B055D-2279-47D2-B1A8-AB1E5670202F}
{C6D1270C-92AB-4FE2-BE93-29DD52F97AD4} = {B167E0C6-F2D8-4B4F-B814-578B72B083BE}
@@ -4045,6 +4069,7 @@ Global
{BBC875BB-E04F-4F9E-A7CC-023B0B1D2BC4} = {5F4B9D7E-81B4-4562-BEDC-3499A8DDE648}
{3102742F-8C87-4C84-B257-1A49DDB3D6BD} = {5F4B9D7E-81B4-4562-BEDC-3499A8DDE648}
{831C87F3-4925-4311-83A4-C07CE4CD109E} = {4657A98F-6D05-48EB-864D-E3D0DCA658C5}
+ {810BF526-53F8-4DFB-A32A-A67CB5FFF785} = {65C50059-6C22-43E9-88DE-AD73F7F108C8}
{5A2538C7-D110-4DFB-A77B-C328CDDF7848} = {7EBB4434-F29C-4316-BEDC-F28F07CE4AC8}
{FF251CAE-8D0B-45E2-BAA4-FE2991D527F7} = {DBC6C89D-A932-4F99-9382-7405A0045988}
{CB8A3C9C-C1EA-4877-ABFC-76DF58FA7BA6} = {FF251CAE-8D0B-45E2-BAA4-FE2991D527F7}
@@ -4075,8 +4100,12 @@ Global
{E718B06A-FEAF-4E11-9344-E81272E214AA} = {F9B62A9D-4DDC-4646-9B43-06D471E0F82C}
{DD749A41-50A3-4DB4-A84F-4372BDFCB742} = {65C50059-6C22-43E9-88DE-AD73F7F108C8}
{404AAC33-B6F1-4EA3-A246-FD9D8A95E93F} = {65C50059-6C22-43E9-88DE-AD73F7F108C8}
+ {4E0052C2-559D-4509-9C42-C6451B1F1FFC} = {86B81B21-8C90-4A99-B113-FA71F8A6CD8D}
+ {67B5150B-2FDE-4EA8-93EE-8BB31D5D7789} = {4E0052C2-559D-4509-9C42-C6451B1F1FFC}
{BBF136B7-361C-4FC2-AACA-6B6ED79BDCF1} = {2B794146-DFEE-475A-B919-7D3ED48587B8}
+ {2DFB37A0-07FE-479F-8B30-D2B5F7E209D2} = {BBF136B7-361C-4FC2-AACA-6B6ED79BDCF1}
{14ACE12B-5B23-4FF3-B3C2-BFECB21064A6} = {2B794146-DFEE-475A-B919-7D3ED48587B8}
+ {768E2B04-FBE8-4464-B5DE-F5AA010E9D33} = {14ACE12B-5B23-4FF3-B3C2-BFECB21064A6}
{16A387A9-80AA-4080-85F6-10F53D6EC99E} = {7311794D-7D2F-47E8-A5B0-C216CBD64A13}
{AD6DD7B6-B896-44B9-904E-9330C2C842C7} = {78E463DA-0FA1-4AAE-A281-D3297C9388C9}
{A3F37EFB-9686-4074-9962-5F731C52D919} = {AD6DD7B6-B896-44B9-904E-9330C2C842C7}
@@ -4239,13 +4268,13 @@ Global
{3C999A94-227A-470F-935E-966E375E40BB} = {7471C6BF-1995-4E56-91E9-86DAAA46C386}
{FC2EEFA9-030B-4EF0-AFB7-1CC61876D1EE} = {7471C6BF-1995-4E56-91E9-86DAAA46C386}
{2B29B1A8-8903-4335-A5CC-6FFBD9069C2D} = {FC2EEFA9-030B-4EF0-AFB7-1CC61876D1EE}
- {FAE78BFF-B2D4-4AAD-9E45-A52A4AB6AC28} = {BBF136B7-361C-4FC2-AACA-6B6ED79BDCF1}
- {07DE237C-5288-4577-9443-D2B7D43D3775} = {14ACE12B-5B23-4FF3-B3C2-BFECB21064A6}
- {FB4CEFDD-BEE3-4858-8A53-D92C4D1B6297} = {86B81B21-8C90-4A99-B113-FA71F8A6CD8D}
- {6768E5DB-C1BA-43FB-A7FF-668982CF3CC6} = {65C50059-6C22-43E9-88DE-AD73F7F108C8}
- {5DCA2786-ED9A-47E9-8A07-6F3FF2B73A53} = {FB4CEFDD-BEE3-4858-8A53-D92C4D1B6297}
- {D0167772-53C1-4ECB-A486-E36D354FC887} = {FB4CEFDD-BEE3-4858-8A53-D92C4D1B6297}
- {BE8B85B9-5FC3-439F-86A8-4D4E028B9DC3} = {5DCA2786-ED9A-47E9-8A07-6F3FF2B73A53}
+ {B773E1A0-FA17-4D5A-BAF9-29CA3CF00789} = {818BF624-10A7-45B2-9BEE-4C411CD9CA06}
+ {FB71B923-4A40-4C68-BEA9-846A57813ED2} = {B773E1A0-FA17-4D5A-BAF9-29CA3CF00789}
+ {C399419B-04D5-40A2-9501-F21DEDAF3EC6} = {FB71B923-4A40-4C68-BEA9-846A57813ED2}
+ {5D1417F3-5B31-4560-9943-DF5F74FA14C0} = {4E0052C2-559D-4509-9C42-C6451B1F1FFC}
+ {0189CCB2-916B-4448-BC3B-665736BB8806} = {67B5150B-2FDE-4EA8-93EE-8BB31D5D7789}
+ {927B2E17-5220-45B0-B1D7-0BB92A430E68} = {FB71B923-4A40-4C68-BEA9-846A57813ED2}
+ {0592DDD2-FBEE-45DC-9DB0-191EF38FE12C} = {927B2E17-5220-45B0-B1D7-0BB92A430E68}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {AF7CA16F-8C38-4546-87A2-5DAAF58A1520}