diff --git a/M5StackCommon/Core2ToughCommon.cs b/M5StackCommon/Core2ToughCommon.cs
new file mode 100644
index 00000000..7eff1edc
--- /dev/null
+++ b/M5StackCommon/Core2ToughCommon.cs
@@ -0,0 +1,476 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#if M5CORE2 || TOUGH
+
+#if M5CORE2
+using Iot.Device.Ft6xx6x;
+using nanoFramework.M5Core2;
+#elif TOUGH
+using Iot.Device.Chs6540;
+using nanoFramework.Tough;
+#endif
+using Iot.Device.Axp192;
+using Iot.Device.Rtc;
+using nanoFramework.Hardware.Esp32;
+using nanoFramework.Runtime.Native;
+using System;
+using System.Device.Adc;
+using System.Device.I2c;
+using System.Device.Gpio;
+using UnitsNet;
+using System.Threading;
+using nanoFramework.Runtime.Events;
+
+namespace nanoFramework.M5Stack
+{
+#if M5CORE2
+ public static partial class M5Core2
+#elif TOUGH
+ public static partial class Tough
+#endif
+ {
+ private const int TouchPinInterrupt = 39;
+ private static Pcf8563 _rtc;
+ private static Axp192 _power;
+ private static bool _powerLed;
+#if M5CORE2
+ private static Ft6xx6x _touchController;
+ private static bool _vibrate;
+#elif TOUGH
+ private static Chs6540 _touchController;
+ private static bool _backLight;
+#endif
+ private static Thread _callbackThread;
+ private static CancellationTokenSource _cancelThread;
+ private static CancellationTokenSource _startThread;
+ private static Point _lastPoint;
+
+ ///
+ /// Touch event handler for the touch event.
+ ///
+ /// The sender object.
+ /// The touch event argument.
+ public delegate void TouchEventHandler(object sender, TouchEventArgs e);
+
+ ///
+ /// Touch event handler.
+ ///
+ public static event TouchEventHandler TouchEvent;
+
+ ///
+#if M5CORE2
+ /// Gets the power management of the M5Core2.
+#elif TOUGH
+ /// Gets the power management of the Tough.
+#endif
+ ///
+ /// Please make sure to read the documentation before adjusting any element.
+ public static Axp192 Power { get => _power; }
+
+ ///
+ /// Gets the real time clock.
+ ///
+ public static Pcf8563 ReatTimeClock
+ {
+ get => _rtc;
+ }
+
+#if M5CORE2
+
+ ///
+ /// Sets on or off the Power LED.
+ ///
+ public static bool PowerLed
+ {
+ get => _powerLed;
+ set
+ {
+ _powerLed = value;
+
+ if (_powerLed)
+ {
+ // turn ON by setting duty cycle to 100%
+ _power.Pwm1DutyCycleSetting1 = 10;
+ _power.Pwm1DutyCycleSetting2 = 10;
+ }
+ else
+ {
+ // tuen OFF by setting duty cycle to 0%
+ _power.Pwm1DutyCycleSetting1 = 0;
+ _power.Pwm1DutyCycleSetting2 = 0;
+ }
+ }
+ }
+
+ ///
+ /// Vibrate the M5Core2 when true.
+ ///
+ public static bool Vibrate
+ {
+ get => _vibrate;
+ set
+ {
+ _vibrate = value;
+ _power.EnableLDO3(_vibrate);
+ }
+ }
+
+ ///
+ /// Gets the touch controller.
+ ///
+ public static Ft6xx6x TouchController
+ {
+ get
+ {
+ if (_touchController == null)
+ {
+ InitializeScreen();
+ }
+
+ return _touchController;
+ }
+ }
+
+#elif TOUGH
+ ///
+ /// Gets the touch controller.
+ ///
+ public static Chs6540 TouchController
+ {
+ get
+ {
+ if (_touchController == null)
+ {
+ InitializeScreen();
+ }
+
+ return _touchController;
+ }
+ }
+#endif
+
+ ///
+ /// Gets the screen.
+ ///
+ /// The memory allocation.
+ /// The screen initialization takes a little bit of time, if you need the screen consider using it as early as possible in your code.
+ public static void InitializeScreen(int memoryBitMapAllocation = Screen.DefaultMemoryAllocationBitmap)
+ {
+ // If the screen is not needed, it's not going to be created
+ // Note: initialization may take a little bit of time
+ if (_screen == null)
+ {
+ _screen = new(memoryBitMapAllocation);
+ Console.Font = Resource.GetFont(Resource.FontResources.consolas_regular_16);
+#if M5CORE2
+ _touchController = new(I2cDevice.Create(new I2cConnectionSettings(1, Ft6xx6x.DefaultI2cAddress)));
+#elif TOUGH
+ _touchController = new(I2cDevice.Create(new I2cConnectionSettings(1, Chs6540.DefaultI2cAddress)));
+#endif
+ _touchController.SetInterruptMode(false);
+ _lastPoint = new();
+ _cancelThread = new();
+ _startThread = new();
+ _callbackThread = new(ThreadTouchCallback);
+ _callbackThread.Start();
+ _gpio.OpenPin(TouchPinInterrupt, PinMode.Input);
+ _gpio.RegisterCallbackForPinValueChangedEvent(TouchPinInterrupt, PinEventTypes.Rising | PinEventTypes.Falling, TouchCallback);
+ }
+ }
+
+ private static void TouchCallback(object sender, PinValueChangedEventArgs pinValueChangedEventArgs)
+ {
+ if (pinValueChangedEventArgs.ChangeType == PinEventTypes.Falling)
+ {
+ _cancelThread = new();
+ _startThread.Cancel();
+ }
+ else
+ {
+ _startThread = new();
+ _cancelThread.Cancel();
+ var point = _touchController.GetPoint(true);
+ if ((_lastPoint.X != point.X) && (_lastPoint.Y != point.Y))
+ {
+ _lastPoint = point;
+ var touchCategory = CheckIfInButtons(point.X, point.Y, TouchEventCategory.Unknown) | TouchEventCategory.LiftUp;
+ TouchEvent?.Invoke(_touchController, new TouchEventArgs() { TimeStamp = DateTime.UtcNow, EventCategory = EventCategory.Touch, TouchEventCategory = touchCategory, X = point.X, Y = point.Y, Id = point.TouchId });
+ }
+ }
+ }
+
+ private static void ThreadTouchCallback()
+ {
+ start:
+ while (!_startThread.IsCancellationRequested)
+ {
+ _startThread.Token.WaitHandle.WaitOne(1000, true);
+ }
+
+ int touchNumber;
+ TouchEventCategory touchCategory;
+ do
+ {
+ touchNumber = _touchController.GetNumberPoints();
+ if (touchNumber == 1)
+ {
+ var point = _touchController.GetPoint(true);
+ _lastPoint = point;
+ touchCategory = CheckIfInButtons(point.X, point.Y, TouchEventCategory.Unknown);
+ touchCategory = point.Event == Event.Contact ? touchCategory | TouchEventCategory.Moving : touchCategory;
+ TouchEvent?.Invoke(_touchController, new TouchEventArgs() { TimeStamp = DateTime.UtcNow, EventCategory = EventCategory.Touch, TouchEventCategory = touchCategory, X = point.X, Y = point.Y, Id = point.TouchId });
+ }
+ else if (touchNumber == 2)
+ {
+ var dp = _touchController.GetDoublePoints();
+ touchCategory = CheckIfInButtons(dp.Point1.X, dp.Point1.Y, TouchEventCategory.DoubleTouch);
+ touchCategory = dp.Point1.Event == Event.Contact ? touchCategory | TouchEventCategory.Moving : touchCategory;
+ TouchEvent?.Invoke(_touchController, new TouchEventArgs() { TimeStamp = DateTime.UtcNow, EventCategory = EventCategory.Touch, TouchEventCategory = touchCategory, X = dp.Point1.X, Y = dp.Point1.Y, Id = dp.Point1.TouchId });
+ touchCategory = CheckIfInButtons(dp.Point2.X, dp.Point2.Y, TouchEventCategory.DoubleTouch);
+ touchCategory = dp.Point2.Event == Event.Contact ? touchCategory | TouchEventCategory.Moving : touchCategory;
+ TouchEvent?.Invoke(_touchController, new TouchEventArgs() { TimeStamp = DateTime.UtcNow, EventCategory = EventCategory.Touch, TouchEventCategory = touchCategory, X = dp.Point2.X, Y = dp.Point2.Y, Id = dp.Point2.TouchId });
+ }
+
+ // This is necessary to give time to the touch sensor
+ // In theory, the wait should be calculated with the period
+ _cancelThread.Token.WaitHandle.WaitOne(10, true);
+ } while (!_cancelThread.IsCancellationRequested);
+
+ // If both token are cancelled, we exit. This is in case this won't become static and will have a dispose.
+ // Now, with the current logic, it will always run.
+ if (!(_cancelThread.IsCancellationRequested && _startThread.IsCancellationRequested))
+ {
+ goto start;
+ }
+ }
+
+ private static TouchEventCategory CheckIfInButtons(int x, int y, TouchEventCategory touchCategory)
+ {
+ // Positions of the buttons on the X axis
+ const int XLeft = 83;
+ const int XMiddle = 182;
+ const int XRight = 271;
+ // On the Y one (same for all
+ const int YButtons = 263;
+ // The delta in pixel for the button size
+ const int DeltaPixel = 24;
+ // Check if we are in Y
+ if ((y <= YButtons + DeltaPixel) && (y >= YButtons - DeltaPixel))
+ {
+ if ((x <= XLeft + DeltaPixel) && (x >= XLeft - DeltaPixel))
+ {
+ touchCategory |= TouchEventCategory.LeftButton;
+ }
+ else if ((x <= XMiddle + DeltaPixel) && (x >= XMiddle - DeltaPixel))
+ {
+ touchCategory |= TouchEventCategory.MiddleButton;
+ }
+ else if ((x <= XRight + DeltaPixel) && (x >= XRight - DeltaPixel))
+ {
+ touchCategory |= TouchEventCategory.RightButton;
+ }
+ }
+
+ return touchCategory;
+ }
+
+#if M5CORE2
+ static M5Core2()
+#elif TOUGH
+ static Tough()
+#endif
+ {
+ // Setup first the I2C bus
+ Configuration.SetPinFunction(22, DeviceFunction.I2C1_CLOCK);
+ Configuration.SetPinFunction(21, DeviceFunction.I2C1_DATA);
+
+ // Create the energy management device
+ I2cDevice i2c = new(new I2cConnectionSettings(1, Axp192.I2cDefaultAddress));
+ _power = new(i2c);
+
+ // Configuration common for M5Core2 and M5Tough
+
+ // VBUS-IPSOUT Pass-Through Management
+ _power.SetVbusSettings(false, false, VholdVoltage.V4_0, true, VbusCurrentLimit.MilliAmper500);
+ // Set Power off voltage 3.0v
+ _power.VoffVoltage = VoffVoltage.V3_0;
+ // Enable bat detection
+ _power.SetShutdownBatteryDetectionControl(false, true, ShutdownBatteryPinFunction.HighResistance, false, ShutdownBatteryTiming.S2);
+ // Bat charge voltage to 4.2, Current 100MA
+ _power.SetChargingFunctions(true, ChargingVoltage.V4_2, ChargingCurrent.Current100mA, ChargingStopThreshold.Percent10);
+ // Enable RTC BAT charge
+ _power.SetBackupBatteryChargingControl(true, BackupBatteryCharingVoltage.V3_0, BackupBatteryChargingCurrent.MicroAmperes200);
+
+ // Set ADC all on
+ _power.AdcPinEnabled = AdcPinEnabled.All;
+ // Set ADC sample rate to 25Hz
+ _power.AdcFrequency = AdcFrequency.Frequency25Hz;
+ _power.AdcPinCurrent = AdcPinCurrent.MicroAmperes80;
+ _power.BatteryTemperatureMonitoring = true;
+ _power.AdcPinCurrentSetting = AdcPinCurrentSetting.AlwaysOn;
+
+ // GPIO0 is LDO
+ _power.Gpio0Behavior = Gpio0Behavior.LowNoiseLDO;
+ // GPIO0 LDO output 2.8V
+ _power.PinOutputVoltage = PinOutputVoltage.V2_8;
+ // Sets DCDC1 3350mV (ESP32 VDD)
+ _power.DcDc1Voltage = ElectricPotential.FromVolts(3.35);
+
+ // LCD and peripherals power supply
+ _power.LDO2OutputVoltage = ElectricPotential.FromVolts(3.3);
+ _power.EnableLDO2(true);
+
+ // GPIO2 enables the speaker
+ _power.Gpio2Behavior = Gpio12Behavior.MnosLeakOpenOutput;
+
+ // GPIO4 LCD reset (and also Touch controller reset on M5Core2)
+ _power.Gpio4Behavior = Gpio4Behavior.MnosLeakOpenOutput;
+
+ // Set temperature protection
+ _power.SetBatteryHighTemperatureThreshold(ElectricPotential.FromVolts(3.2256));
+
+ // This part of the code will handle the button behavior
+ _power.EnableButtonPressed(ButtonPressed.LongPressed | ButtonPressed.ShortPressed);
+ // 128ms power on, 4s power off
+ _power.SetButtonBehavior(LongPressTiming.S1, ShortPressTiming.Ms128, true, SignalDelayAfterPowerUp.Ms32, ShutdownTiming.S4);
+
+#if M5CORE2
+ // enable DCO and LDO outputs
+ _power.LdoDcPinsEnabled = LdoDcPinsEnabled.DcDc1 | LdoDcPinsEnabled.DcDc3 | LdoDcPinsEnabled.Ldo2 | LdoDcPinsEnabled.Ldo3;
+
+ // Sets the Vibrator voltage
+ _power.LDO3OutputVoltage = ElectricPotential.FromVolts(2.0);
+ // vibrator off
+ Vibrate = false;
+
+ // Sets the LCD backlight voltage to 2.8V
+ _power.DcDc3Voltage = ElectricPotential.FromVolts(2.8);
+
+ // GPIO1 set to PWM to control power LED
+ _power.Gpio1Behavior = Gpio12Behavior.PwmOutput;
+
+ // Switch on the power LED
+ PowerLed = true;
+
+ // battery = 360mAh
+ _power.ChargingCurrent = ChargingCurrent.Current360mA;
+
+#elif TOUGH
+ // PWM1 X
+ _power.Pwm1OutputFrequencySetting = 0;
+ // PWM1 Y1
+ _power.Pwm1DutyCycleSetting1 = 0xFF;
+ // PWM1 Y2
+ _power.Pwm1DutyCycleSetting2 = 0xFF;
+
+ // enable DCO and LDO outputs
+ _power.LdoDcPinsEnabled = LdoDcPinsEnabled.DcDc1 | LdoDcPinsEnabled.Ldo2 | LdoDcPinsEnabled.Ldo3;
+
+ // Sets the LCD backlight voltage to 3V
+ _power.LDO3OutputVoltage = ElectricPotential.FromVolts(3.0);
+
+ // GPIO1 is reset for Touch controller
+ _power.Gpio1Behavior = Gpio12Behavior.MnosLeakOpenOutput;
+
+#endif
+
+ // Setup SPI1
+ Configuration.SetPinFunction(23, DeviceFunction.SPI1_MOSI);
+ Configuration.SetPinFunction(38, DeviceFunction.SPI1_MISO);
+ Configuration.SetPinFunction(18, DeviceFunction.SPI1_CLOCK);
+
+ // Setup the screen with SP2 and SD Card
+ Configuration.SetPinFunction(23, DeviceFunction.SPI2_MOSI);
+ Configuration.SetPinFunction(38, DeviceFunction.SPI2_MISO);
+ Configuration.SetPinFunction(18, DeviceFunction.SPI2_CLOCK);
+
+ // Second serial port
+ Configuration.SetPinFunction(13, DeviceFunction.COM2_RX);
+ Configuration.SetPinFunction(14, DeviceFunction.COM2_TX);
+
+ // Setup second I2C bus (port A)
+ Configuration.SetPinFunction(33, DeviceFunction.I2C2_CLOCK);
+ Configuration.SetPinFunction(32, DeviceFunction.I2C2_DATA);
+ // The portA is the second I2C
+ _portANumber = 2;
+
+ // Setup the time if any
+ _rtc = new Pcf8563(I2cDevice.Create(new I2cConnectionSettings(1, Pcf8563.DefaultI2cAddress)));
+
+ DateTime dt;
+ var sysDtcore = DateTime.UtcNow;
+ try
+ {
+ dt = _rtc.DateTime;
+ if (sysDtcore < dt)
+ {
+ Rtc.SetSystemTime(dt);
+ }
+ }
+ catch (Exception)
+ {
+
+ if (sysDtcore.Year < 2021)
+ {
+ dt = new DateTime(2022, 05, 31, 00, 00, 00);
+ _rtc.DateTime = dt;
+ Rtc.SetSystemTime(dt);
+ }
+ }
+ }
+
+ ///
+ /// Gets an ADC channel
+ ///
+ /// The GPIO pin number
+ /// An AdcChannel
+ public static AdcChannel GetAdcGpio(int gpioNumber)
+ {
+ if (_adc == null)
+ {
+ _adc = new();
+ }
+
+ switch (gpioNumber)
+ {
+ case 35:
+ Configuration.SetPinFunction(11, DeviceFunction.ADC1_CH7);
+ return _adc.OpenChannel(7);
+ case 36:
+ Configuration.SetPinFunction(5, DeviceFunction.ADC1_CH0);
+ return _adc.OpenChannel(0);
+ case 32:
+ Configuration.SetPinFunction(32, DeviceFunction.ADC1_CH4);
+ return _adc.OpenChannel(4);
+ case 39:
+ Configuration.SetPinFunction(39, DeviceFunction.ADC1_CH3);
+ return _adc.OpenChannel(3);
+ case 0:
+ Configuration.SetPinFunction(0, DeviceFunction.ADC1_CH11);
+ return _adc.OpenChannel(11);
+ case 2:
+ Configuration.SetPinFunction(2, DeviceFunction.ADC1_CH12);
+ return _adc.OpenChannel(12);
+ case 4:
+ Configuration.SetPinFunction(4, DeviceFunction.ADC1_CH10);
+ return _adc.OpenChannel(10);
+ case 12:
+ Configuration.SetPinFunction(12, DeviceFunction.ADC1_CH15);
+ return _adc.OpenChannel(15);
+ case 15:
+ Configuration.SetPinFunction(15, DeviceFunction.ADC1_CH13);
+ return _adc.OpenChannel(13);
+ case 25:
+ Configuration.SetPinFunction(25, DeviceFunction.ADC1_CH18);
+ return _adc.OpenChannel(18);
+ case 27:
+ Configuration.SetPinFunction(26, DeviceFunction.ADC1_CH17);
+ return _adc.OpenChannel(17);
+ default:
+ throw new ArgumentException(nameof(gpioNumber));
+ }
+ }
+ }
+}
+#endif
diff --git a/M5StackCommon/M5StackCommon.projitems b/M5StackCommon/M5StackCommon.projitems
index 6b7a876c..c1fd2cc5 100644
--- a/M5StackCommon/M5StackCommon.projitems
+++ b/M5StackCommon/M5StackCommon.projitems
@@ -10,6 +10,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/M5StackCommon/Screen.cs b/M5StackCommon/Screen.cs
new file mode 100644
index 00000000..e4a31a4a
--- /dev/null
+++ b/M5StackCommon/Screen.cs
@@ -0,0 +1,120 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#if M5CORE2 || TOUGH
+using Iot.Device.Axp192;
+using nanoFramework.M5Stack;
+using nanoFramework.UI;
+using System.Device.Gpio;
+using System.Threading;
+using UnitsNet;
+
+namespace nanoFramework.M5Stack
+{
+ ///
+#if M5CORE2
+ /// M5Core2 screen class.
+#elif TOUGH
+ /// M5Tough screen class.
+#endif
+ ///
+ public class Screen : ScreenBase
+ {
+ ///
+ /// Default memory allocation
+ ///
+ public const int DefaultMemoryAllocationBitmap = 320 * 240 * 4;
+
+ private const byte DefaultScreenBrightness = 75;
+ private const int ChipSelect = 5;
+ private const int DataCommand = 15;
+ private const int Reset = -1;
+ private static Axp192 _power;
+ private static byte _brightness;
+ private static bool _isInitialized = false;
+
+ ///
+ /// Initializes the screen
+ ///
+ /// The memory allocation.
+ public Screen(int memoryBitMapAllocation = DefaultMemoryAllocationBitmap)
+ {
+ if (_isInitialized)
+ {
+ return;
+ }
+
+ // We're allocating enough memory for the full screen because these targets have PSRAM
+ MemoryAllocationBitmap = memoryBitMapAllocation;
+ // backligth is not controlled by the screen driver
+ BackLightPin = -1;
+
+#if M5CORE2
+ _power = M5Stack.M5Core2.Power;
+#elif TOUGH
+ _power = M5Stack.Tough.Power;
+#endif
+
+ // Reset screen
+ _power.Gpio4Value = PinValue.Low;
+ Thread.Sleep(100);
+ _power.Gpio4Value = PinValue.High;
+ Thread.Sleep(100);
+
+ // Create the screen
+ DisplayControl.Initialize(new SpiConfiguration(2, ChipSelect, DataCommand, Reset, BackLightPin), new ScreenConfiguration(0, 0, 320, 240), (uint)MemoryAllocationBitmap);
+
+ // set initial value for brightness
+ BrightnessPercentage = DefaultScreenBrightness;
+
+ // enable back-light
+ Enabled = true;
+
+ _isInitialized = true;
+ }
+
+ ///
+ /// Enables or disables the screen.
+ ///
+ /// to enable the screen, to disable it.
+ public static new bool Enabled
+ {
+ get => IsEnabled;
+
+ set
+ {
+ IsEnabled = value;
+
+#if M5CORE2
+ _power.EnableDCDC3(IsEnabled);
+#elif TOUGH
+ _power.EnableLDO3(IsEnabled);
+#endif
+ }
+ }
+
+ ///
+ /// Gets or sets the screen brightness.
+ ///
+ /// Brightness as percentage.
+ public static new byte BrightnessPercentage
+ {
+ get => _brightness;
+
+ set
+ {
+ // For M5Core2 and M5Tough, values from 2.5 to 3V are working fine
+ // 2.5 V = dark, 3.0 V full luminosity
+ _brightness = (byte)(value > 100 ? 100 : value);
+ var backLightVoltage = ElectricPotential.FromVolts(_brightness * 0.5 / 100.0 + 2.5);
+#if M5CORE2
+ _power.LDO3OutputVoltage = backLightVoltage;
+#elif TOUGH
+ _power.LDO3OutputVoltage = backLightVoltage;
+#endif
+ }
+ }
+ }
+}
+
+#endif
diff --git a/nanoFramework.M5Core2/TouchEventArgs.cs b/M5StackCommon/TouchEventArgs.cs
similarity index 91%
rename from nanoFramework.M5Core2/TouchEventArgs.cs
rename to M5StackCommon/TouchEventArgs.cs
index 04e00184..89806fe4 100644
--- a/nanoFramework.M5Core2/TouchEventArgs.cs
+++ b/M5StackCommon/TouchEventArgs.cs
@@ -1,10 +1,17 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+#if TOUGH || M5CORE2
using nanoFramework.Runtime.Events;
using System;
+#endif
+#if TOUGH
+namespace nanoFramework.Tough
+#elif M5CORE2
namespace nanoFramework.M5Core2
+#endif
+#if TOUGH || M5CORE2
{
///
/// Touch event arguments
@@ -42,3 +49,4 @@ public class TouchEventArgs : EventArgs
public DateTime TimeStamp { get; set; }
}
}
+#endif
\ No newline at end of file
diff --git a/nanoFramework.M5Core2/TouchEventCategory.cs b/M5StackCommon/TouchEventCategory.cs
similarity index 87%
rename from nanoFramework.M5Core2/TouchEventCategory.cs
rename to M5StackCommon/TouchEventCategory.cs
index 8c2c40a9..3520a8b4 100644
--- a/nanoFramework.M5Core2/TouchEventCategory.cs
+++ b/M5StackCommon/TouchEventCategory.cs
@@ -1,9 +1,16 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+#if TOUGH || M5CORE2
using System;
+#endif
+#if TOUGH
+namespace nanoFramework.Tough
+#elif M5CORE2
namespace nanoFramework.M5Core2
+#endif
+#if TOUGH || M5CORE2
{
///
/// Sub event touch catgory
@@ -33,3 +40,4 @@ public enum TouchEventCategory
LiftUp = 0b0010_0000,
}
}
+#endif
\ No newline at end of file
diff --git a/Tests/M5Core2TestApp/M5Core2TestApp.nfproj b/Tests/M5Core2TestApp/M5Core2TestApp.nfproj
index 0d4f42bb..582f73a8 100644
--- a/Tests/M5Core2TestApp/M5Core2TestApp.nfproj
+++ b/Tests/M5Core2TestApp/M5Core2TestApp.nfproj
@@ -172,4 +172,4 @@
-
\ No newline at end of file
+
diff --git a/Tests/M5Core2TestApp/packages.config b/Tests/M5Core2TestApp/packages.config
index 1efd9b3e..a9e3a29f 100644
--- a/Tests/M5Core2TestApp/packages.config
+++ b/Tests/M5Core2TestApp/packages.config
@@ -34,4 +34,4 @@
-
\ No newline at end of file
+
diff --git a/Tests/M5StickTestApp/M5StickTestApp.nfproj b/Tests/M5StickTestApp/M5StickTestApp.nfproj
index 2e3e7e39..416ebd4a 100644
--- a/Tests/M5StickTestApp/M5StickTestApp.nfproj
+++ b/Tests/M5StickTestApp/M5StickTestApp.nfproj
@@ -132,4 +132,4 @@
-
\ No newline at end of file
+
diff --git a/Tests/M5StickTestApp/packages.config b/Tests/M5StickTestApp/packages.config
index dbeddf95..98dfb796 100644
--- a/Tests/M5StickTestApp/packages.config
+++ b/Tests/M5StickTestApp/packages.config
@@ -24,4 +24,4 @@
-
\ No newline at end of file
+
diff --git a/Tests/ToughTestApp/Program.cs b/Tests/ToughTestApp/Program.cs
new file mode 100644
index 00000000..68fcfd8a
--- /dev/null
+++ b/Tests/ToughTestApp/Program.cs
@@ -0,0 +1,94 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using nanoFramework.Tough;
+using nanoFramework.M5Stack;
+using nanoFramework.Networking;
+using nanoFramework.Runtime.Native;
+using System;
+using System.Diagnostics;
+using System.Threading;
+using Console = nanoFramework.M5Stack.Console;
+
+Tough.InitializeScreen();
+
+Debug.WriteLine("Hello from Tough!");
+
+Console.WriteLine("Hello from Tough!");
+
+const string Ssid = "SSID";
+const string Password = "YourWifiPasswordHere";
+// Give 60 seconds to the wifi join to happen
+CancellationTokenSource cs = new(60000);
+var success = WifiNetworkHelper.ConnectDhcp(Ssid, Password, requiresDateTime: true, token: cs.Token);
+if (!success)
+{
+ // Something went wrong, you can get details with the ConnectionError property:
+ Debug.WriteLine($"Can't connect to the network, error: {WifiNetworkHelper.Status}");
+ if (WifiNetworkHelper.HelperException != null)
+ {
+ Debug.WriteLine($"ex: {WifiNetworkHelper.HelperException}");
+ }
+}
+
+Tough.TouchEvent += TouchEventCallback;
+
+Thread.Sleep(Timeout.Infinite);
+
+void TouchEventCallback(object sender, TouchEventArgs e)
+{
+ const string StrLB = "LEFT BUTTON PRESSED ";
+ const string StrMB = "MIDDLE BUTTON PRESSED ";
+ const string StrRB = "RIGHT BUTTON PRESSED ";
+ const string StrXY1 = "TOUCHED at X= ";
+ const string StrXY2 = ",Y= ";
+ const string StrID = ",Id= ";
+ const string StrDoubleTouch = "Double touch. ";
+ const string StrMove = "Moving... ";
+ const string StrLiftUp = "Lift up. ";
+
+ Debug.WriteLine($"Touch Panel Event Received Category= {e.EventCategory} Subcategory= {e.TouchEventCategory}");
+ Console.CursorLeft = 0;
+ Console.CursorTop = 0;
+
+ Debug.WriteLine(StrXY1 + e.X + StrXY2 + e.Y + StrID + e.Id);
+ Console.WriteLine(StrXY1 + e.X + StrXY2 + e.Y + StrID + e.Id + " ");
+
+ if ((e.TouchEventCategory & TouchEventCategory.LeftButton) == TouchEventCategory.LeftButton)
+ {
+ Debug.WriteLine(StrLB);
+ Console.WriteLine(StrLB);
+ }
+ else if ((e.TouchEventCategory & TouchEventCategory.MiddleButton) == TouchEventCategory.MiddleButton)
+ {
+ Debug.WriteLine(StrMB);
+ Console.WriteLine(StrMB);
+ }
+ else if ((e.TouchEventCategory & TouchEventCategory.RightButton) == TouchEventCategory.RightButton)
+ {
+ Debug.WriteLine(StrRB);
+ Console.WriteLine(StrRB);
+ }
+
+ if ((e.TouchEventCategory & TouchEventCategory.Moving) == TouchEventCategory.Moving)
+ {
+ Debug.WriteLine(StrMove);
+ Console.Write(StrMove);
+ }
+
+ if ((e.TouchEventCategory & TouchEventCategory.LiftUp) == TouchEventCategory.LiftUp)
+ {
+ Debug.WriteLine(StrLiftUp);
+ Console.Write(StrLiftUp);
+ }
+
+ if ((e.TouchEventCategory & TouchEventCategory.DoubleTouch) == TouchEventCategory.DoubleTouch)
+ {
+ Debug.WriteLine(StrDoubleTouch);
+ Console.Write(StrDoubleTouch);
+ }
+
+ Console.WriteLine(" ");
+ Console.WriteLine(" ");
+ Console.WriteLine(" ");
+}
diff --git a/Tests/ToughTestApp/Properties/AssemblyInfo.cs b/Tests/ToughTestApp/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..acaed75a
--- /dev/null
+++ b/Tests/ToughTestApp/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("CSharp.BlankApplication")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("CSharp.BlankApplication")]
+[assembly: AssemblyCopyright("Copyright © 2022")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Tests/ToughTestApp/ToughTestApp.nfproj b/Tests/ToughTestApp/ToughTestApp.nfproj
new file mode 100644
index 00000000..0a257085
--- /dev/null
+++ b/Tests/ToughTestApp/ToughTestApp.nfproj
@@ -0,0 +1,101 @@
+
+
+
+ $(MSBuildExtensionsPath)\nanoFramework\v1.0\
+
+
+
+ Debug
+ AnyCPU
+ {11A8DD76-328B-46DF-9F39-F559912D0360};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ f5bf3da4-b92e-46c6-a135-37e6a7e002a1
+ Exe
+ Properties
+ 512
+ ToughTestApp
+ ToughTestApp
+ v1.0
+
+
+
+
+
+
+
+
+ ..\..\packages\nanoFramework.Iot.Device.Axp192.1.1.74.7591\lib\Iot.Device.Axp192.dll
+
+
+ ..\..\packages\nanoFramework.Iot.Device.Chs6540.1.0.16\lib\Iot.Device.Chs6540.dll
+
+
+ ..\..\packages\nanoFramework.CoreLibrary.1.12.0\lib\mscorlib.dll
+
+
+ ..\..\packages\nanoFramework.Graphics.1.0.2\lib\nanoFramework.Graphics.dll
+
+
+ ..\..\packages\nanoFramework.ResourceManager.1.1.4\lib\nanoFramework.ResourceManager.dll
+
+
+ ..\..\packages\nanoFramework.Runtime.Events.1.10.0\lib\nanoFramework.Runtime.Events.dll
+
+
+ ..\..\packages\nanoFramework.Runtime.Native.1.5.4\lib\nanoFramework.Runtime.Native.dll
+
+
+ ..\..\packages\nanoFramework.System.Collections.1.4.0\lib\nanoFramework.System.Collections.dll
+
+
+ ..\..\packages\nanoFramework.System.Text.1.1.3\lib\nanoFramework.System.Text.dll
+
+
+ ..\..\packages\nanoFramework.System.Device.Adc.1.0.2\lib\System.Device.Adc.dll
+
+
+ ..\..\packages\nanoFramework.System.Device.Gpio.1.0.4\lib\System.Device.Gpio.dll
+
+
+ ..\..\packages\nanoFramework.System.Device.I2c.1.0.3\lib\System.Device.I2c.dll
+
+
+ ..\..\packages\nanoFramework.System.Device.Wifi.1.4.0.16\lib\System.Device.Wifi.dll
+
+
+ ..\..\packages\nanoFramework.System.IO.Ports.1.0.7.1\lib\System.IO.Ports.dll
+
+
+ ..\..\packages\nanoFramework.System.IO.Streams.1.0.0\lib\System.IO.Streams.dll
+
+
+ ..\..\packages\nanoFramework.System.Net.1.9.0.1\lib\System.Net.dll
+
+
+ ..\..\packages\nanoFramework.System.Threading.1.0.4\lib\System.Threading.dll
+
+
+ ..\..\packages\UnitsNet.nanoFramework.ElectricCurrent.4.132.0\lib\UnitsNet.ElectricCurrent.dll
+
+
+ ..\..\packages\UnitsNet.nanoFramework.ElectricPotential.4.132.0\lib\UnitsNet.ElectricPotential.dll
+
+
+ ..\..\packages\UnitsNet.nanoFramework.Power.4.132.0\lib\UnitsNet.Power.dll
+
+
+ ..\..\packages\UnitsNet.nanoFramework.Temperature.4.132.0\lib\UnitsNet.Temperature.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Tests/ToughTestApp/packages.config b/Tests/ToughTestApp/packages.config
new file mode 100644
index 00000000..a022cd18
--- /dev/null
+++ b/Tests/ToughTestApp/packages.config
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index bd2c1af5..99dc3862 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -79,6 +79,10 @@ steps:
- template: azure-pipelines-templates/class-lib-package.yml@templates
parameters:
nugetPackageName: 'nanoFramework.Fire'
+
+- template: azure-pipelines-templates/class-lib-package.yml@templates
+ parameters:
+ nugetPackageName: 'nanoFramework.Tough'
- template: azure-pipelines-templates/class-lib-publish.yml@templates
diff --git a/nanoFramework.AtomLite/AtomLite.cs b/nanoFramework.AtomLite/AtomLite.cs
index 7f68d945..a67c820a 100644
--- a/nanoFramework.AtomLite/AtomLite.cs
+++ b/nanoFramework.AtomLite/AtomLite.cs
@@ -34,9 +34,6 @@ static AtomLite()
// Setup first the I2C bus
Configuration.SetPinFunction(32, DeviceFunction.I2C1_CLOCK);
Configuration.SetPinFunction(26, DeviceFunction.I2C1_DATA);
-
- // Setup buttons
- _gpio = new();
}
}
}
diff --git a/nanoFramework.AtomMatrix/AtomMatrix.cs b/nanoFramework.AtomMatrix/AtomMatrix.cs
index 73141412..5d555ced 100644
--- a/nanoFramework.AtomMatrix/AtomMatrix.cs
+++ b/nanoFramework.AtomMatrix/AtomMatrix.cs
@@ -65,9 +65,6 @@ static AtomMatrix()
Configuration.SetPinFunction(33, DeviceFunction.SPI1_MISO);
Configuration.SetPinFunction(23, DeviceFunction.SPI1_CLOCK);
- // Setup buttons
- _gpio = new();
-
LedMatrix.Image.Clear();
}
}
diff --git a/nanoFramework.M5Core2/M5Core2.cs b/nanoFramework.M5Core2/M5Core2.cs
index d66d992b..8f63d67d 100644
--- a/nanoFramework.M5Core2/M5Core2.cs
+++ b/nanoFramework.M5Core2/M5Core2.cs
@@ -1,374 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using Iot.Device.Axp192;
-using Iot.Device.Ft6xx6x;
-using Iot.Device.Rtc;
-using nanoFramework.Hardware.Esp32;
-using nanoFramework.M5Core2;
-using nanoFramework.Runtime.Native;
-using System;
-using System.Device.Adc;
-using System.Device.I2c;
-using System.Device.Gpio;
-using UnitsNet;
-using System.Threading;
-using nanoFramework.Runtime.Events;
-
namespace nanoFramework.M5Stack
{
public static partial class M5Core2
{
- private const int TouchPinInterrupt = 39;
- private static Pcf8563 _rtc;
- private static Axp192 _power;
- private static bool _powerLed;
- private static bool _vibrate;
- private static Ft6xx6x _touchController;
- private static Thread _callbackThread;
- private static CancellationTokenSource _cancelThread;
- private static CancellationTokenSource _startThread;
- private static Point _lastPoint;
-
- ///
- /// Touch event handler for the touch event.
- ///
- /// The sender object.
- /// The touch event argument.
- public delegate void TouchEventHandler(object sender, TouchEventArgs e);
-
- ///
- /// Touch event handler.
- ///
- public static event TouchEventHandler TouchEvent;
-
- ///
- /// Gets the power management of the M5Core2.
- ///
- /// Please make sure to read the documentation before adjusting any element.
- public static Axp192 Power { get => _power; }
-
- ///
- /// Gets the real time clock.
- ///
- public static Pcf8563 ReatTimeClock
- {
- get => _rtc;
- }
-
- ///
- /// Sets on or off the Power Led.
- ///
- public static bool PowerLed
- {
- get => _powerLed;
- set
- {
- _powerLed = value;
- _power.EnableLDO2(_powerLed);
- }
- }
-
- ///
- /// Vibrate the M5Core2 when true.
- ///
- public static bool Vibrate
- {
- get => _vibrate;
- set
- {
- _vibrate = value;
- _power.EnableLDO3(_vibrate);
- }
- }
-
- ///
- /// Gets the touch controller.
- ///
- public static Ft6xx6x TouchController
- {
- get
- {
- if (_touchController == null)
- {
- InitializeScreen();
- }
-
- return _touchController;
- }
- }
-
- ///
- /// Gets the screen.
- ///
- /// The memory allocation.
- /// The screen initialization takes a little bit of time, if you need the screen consider using it as early as possible in your code.
- public static void InitializeScreen(int memoryBitMapAllocation = Screen.DefaultMemoryAllocationBitmap)
- {
- // If the screen is not needed, it's not going to be created
- // Note: initialization may take a little bit of time
- if (_screen == null)
- {
- _screen = new(memoryBitMapAllocation);
- Console.Font = Resource.GetFont(Resource.FontResources.consolas_regular_16);
- _touchController = new(I2cDevice.Create(new I2cConnectionSettings(1, Ft6xx6x.DefaultI2cAddress)));
- _touchController.SetInterruptMode(false);
- _lastPoint = new();
- _cancelThread = new();
- _startThread = new();
- _callbackThread = new(ThreadTouchCallback);
- _callbackThread.Start();
- _gpio.OpenPin(TouchPinInterrupt, PinMode.Input);
- _gpio.RegisterCallbackForPinValueChangedEvent(TouchPinInterrupt, PinEventTypes.Rising | PinEventTypes.Falling, TouchCallback);
- }
- }
-
- private static void TouchCallback(object sender, PinValueChangedEventArgs pinValueChangedEventArgs)
- {
- if (pinValueChangedEventArgs.ChangeType == PinEventTypes.Falling)
- {
- _cancelThread = new();
- _startThread.Cancel();
- }
- else
- {
- _startThread = new();
- _cancelThread.Cancel();
- var point = _touchController.GetPoint(true);
- if ((_lastPoint.X != point.X) && (_lastPoint.Y != point.Y))
- {
- _lastPoint = point;
- var touchCategory = CheckIfInButtons(point.X, point.Y, TouchEventCategory.Unknown) | TouchEventCategory.LiftUp;
- TouchEvent?.Invoke(_touchController, new TouchEventArgs() { TimeStamp = DateTime.UtcNow, EventCategory = EventCategory.Touch, TouchEventCategory = touchCategory, X = point.X, Y = point.Y, Id = point.TouchId });
- }
- }
- }
-
- private static void ThreadTouchCallback()
- {
- start:
- while (!_startThread.IsCancellationRequested)
- {
- _startThread.Token.WaitHandle.WaitOne(1000, true);
- }
-
- int touchNumber;
- TouchEventCategory touchCategory;
- do
- {
- touchNumber = _touchController.GetNumberPoints();
- if (touchNumber == 1)
- {
- var point = _touchController.GetPoint(true);
- _lastPoint = point;
- touchCategory = CheckIfInButtons(point.X, point.Y, TouchEventCategory.Unknown);
- touchCategory = point.Event == Event.Contact ? touchCategory | TouchEventCategory.Moving : touchCategory;
- TouchEvent?.Invoke(_touchController, new TouchEventArgs() { TimeStamp = DateTime.UtcNow, EventCategory = EventCategory.Touch, TouchEventCategory = touchCategory, X = point.X, Y = point.Y, Id = point.TouchId });
- }
- else if (touchNumber == 2)
- {
- var dp = _touchController.GetDoublePoints();
- touchCategory = CheckIfInButtons(dp.Point1.X, dp.Point1.Y, TouchEventCategory.DoubleTouch);
- touchCategory = dp.Point1.Event == Event.Contact ? touchCategory | TouchEventCategory.Moving : touchCategory;
- TouchEvent?.Invoke(_touchController, new TouchEventArgs() { TimeStamp = DateTime.UtcNow, EventCategory = EventCategory.Touch, TouchEventCategory = touchCategory, X = dp.Point1.X, Y = dp.Point1.Y, Id = dp.Point1.TouchId });
- touchCategory = CheckIfInButtons(dp.Point2.X, dp.Point2.Y, TouchEventCategory.DoubleTouch);
- touchCategory = dp.Point2.Event == Event.Contact ? touchCategory | TouchEventCategory.Moving : touchCategory;
- TouchEvent?.Invoke(_touchController, new TouchEventArgs() { TimeStamp = DateTime.UtcNow, EventCategory = EventCategory.Touch, TouchEventCategory = touchCategory, X = dp.Point2.X, Y = dp.Point2.Y, Id = dp.Point2.TouchId });
- }
-
- // This is necessary to give time to the touch sensor
- // In theory, the wait should be calculated with the period
- _cancelThread.Token.WaitHandle.WaitOne(10, true);
- } while (!_cancelThread.IsCancellationRequested);
-
- // If both token are cancelled, we exit. This is in case this won't become static and will have a dispose.
- // Now, with the current logic, it will always run.
- if (!(_cancelThread.IsCancellationRequested && _startThread.IsCancellationRequested))
- {
- goto start;
- }
- }
-
- private static TouchEventCategory CheckIfInButtons(int x, int y, TouchEventCategory touchCategory)
- {
- // Positions of the buttons on the X axis
- const int XLeft = 83;
- const int XMiddle = 182;
- const int XRight = 271;
- // On the Y one (same for all
- const int YButtons = 263;
- // The delta in pixel for the button size
- const int DeltaPixel = 24;
- // Check if we are in Y
- if ((y <= YButtons + DeltaPixel) && (y >= YButtons - DeltaPixel))
- {
- if ((x <= XLeft + DeltaPixel) && (x >= XLeft - DeltaPixel))
- {
- touchCategory |= TouchEventCategory.LeftButton;
- }
- else if ((x <= XMiddle + DeltaPixel) && (x >= XMiddle - DeltaPixel))
- {
- touchCategory |= TouchEventCategory.MiddleButton;
- }
- else if ((x <= XRight + DeltaPixel) && (x >= XRight - DeltaPixel))
- {
- touchCategory |= TouchEventCategory.RightButton;
- }
- }
-
- return touchCategory;
- }
-
- static M5Core2()
- {
- // Setup first the I2C bus
- Configuration.SetPinFunction(22, DeviceFunction.I2C1_CLOCK);
- Configuration.SetPinFunction(21, DeviceFunction.I2C1_DATA);
-
- // Create the energy management device
- I2cDevice i2c = new(new I2cConnectionSettings(1, Axp192.I2cDefaultAddress));
- _power = new(i2c);
-
- // Configuration for M5Core2
- // AXP Vbus limit off
- _power.SetVbusSettings(false, false, VholdVoltage.V4_0, true, VbusCurrentLimit.MilliAmper100);
- // AXP192 GPIO1 and 2:OD OUTPUT
- _power.Gpio1Behavior = Gpio12Behavior.MnosLeakOpenOutput;
- _power.Gpio2Behavior = Gpio12Behavior.MnosLeakOpenOutput;
- // Enable RTC BAT charge
- _power.SetBackupBatteryChargingControl(true, BackupBatteryCharingVoltage.V3_0, BackupBatteryChargingCurrent.MicroAmperes200);
- // Sets the ESP voltage
- _power.DcDc1Voltage = ElectricPotential.FromVolts(3.35);
- // Sets the LCD Voltage to 2.8V
- _power.DcDc3Voltage = ElectricPotential.FromVolts(2.8);
- // Sets the SD Card voltage
- _power.LDO2OutputVoltage = ElectricPotential.FromVolts(3.3);
- _power.EnableLDO2(true);
- // Sets the Vibrator voltage
- _power.LDO3OutputVoltage = ElectricPotential.FromVolts(2.0);
- // Bat charge voltage to 4.2, Current 100MA
- _power.SetChargingFunctions(true, ChargingVoltage.V4_2, ChargingCurrent.Current100mA, ChargingStopThreshold.Percent10);
- // Set ADC sample rate to 200hz
- _power.AdcFrequency = AdcFrequency.Frequency200Hz;
- _power.AdcPinCurrent = AdcPinCurrent.MicroAmperes80;
- _power.BatteryTemperatureMonitoring = true;
- _power.AdcPinCurrentSetting = AdcPinCurrentSetting.AlwaysOn;
- // Set ADC1 Enable
- _power.AdcPinEnabled = AdcPinEnabled.All;
- // Switch on the power led
- PowerLed = true;
- // Set GPIO4 as output (rest LCD)
- _power.Gpio4Behavior = Gpio4Behavior.MnosLeakOpenOutput;
- // 128ms power on, 4s power off
- _power.SetButtonBehavior(LongPressTiming.S1, ShortPressTiming.Ms128, true, SignalDelayAfterPowerUp.Ms64, ShutdownTiming.S10);
- // Set temperature protection
- _power.SetBatteryHighTemperatureThreshold(ElectricPotential.FromVolts(3.2256));
- // Enable bat detection
- _power.SetShutdownBatteryDetectionControl(false, true, ShutdownBatteryPinFunction.HighResistance, true, ShutdownBatteryTiming.S2);
- // Set Power off voltage 3.0v
- _power.VoffVoltage = VoffVoltage.V3_0;
- // This part of the code will handle the button behavior
- _power.EnableButtonPressed(ButtonPressed.LongPressed | ButtonPressed.ShortPressed);
- _power.SetButtonBehavior(LongPressTiming.S2, ShortPressTiming.Ms128, true, SignalDelayAfterPowerUp.Ms32, ShutdownTiming.S10);
-
- // Setup buttons
- _gpio = new();
-
- // Setup SPI1
- Configuration.SetPinFunction(23, DeviceFunction.SPI1_MOSI);
- Configuration.SetPinFunction(38, DeviceFunction.SPI1_MISO);
- Configuration.SetPinFunction(18, DeviceFunction.SPI1_CLOCK);
-
- // Setup the screen with SP2 and SD Card
- Configuration.SetPinFunction(23, DeviceFunction.SPI2_MOSI);
- Configuration.SetPinFunction(38, DeviceFunction.SPI2_MISO);
- Configuration.SetPinFunction(18, DeviceFunction.SPI2_CLOCK);
-
- // Second serial port
- Configuration.SetPinFunction(13, DeviceFunction.COM2_RX);
- Configuration.SetPinFunction(14, DeviceFunction.COM2_TX);
-
- // Setup second I2C bus (port A)
- Configuration.SetPinFunction(33, DeviceFunction.I2C2_CLOCK);
- Configuration.SetPinFunction(32, DeviceFunction.I2C2_DATA);
- // The portA is the second I2C
- _portANumber = 2;
-
- // Setup the time if any
- _rtc = new Pcf8563(I2cDevice.Create(new I2cConnectionSettings(1, Pcf8563.DefaultI2cAddress)));
-
- DateTime dt;
- var sysDtcore = DateTime.UtcNow;
- try
- {
- dt = _rtc.DateTime;
- if (sysDtcore < dt)
- {
- Rtc.SetSystemTime(dt);
- }
- }
- catch (Exception)
- {
-
- if (sysDtcore.Year < 2021)
- {
- dt = new DateTime(2021, 11, 03, 12, 00, 00);
- _rtc.DateTime = dt;
- Rtc.SetSystemTime(dt);
- }
- }
- }
-
- ///
- /// Gets an ADC channel
- ///
- /// The GPIO pin number
- /// An AdcChannel
- public static AdcChannel GetAdcGpio(int gpioNumber)
- {
- if (_adc == null)
- {
- _adc = new();
- }
-
- switch (gpioNumber)
- {
- case 35:
- Configuration.SetPinFunction(11, DeviceFunction.ADC1_CH7);
- return _adc.OpenChannel(7);
- case 36:
- Configuration.SetPinFunction(5, DeviceFunction.ADC1_CH0);
- return _adc.OpenChannel(0);
- case 32:
- Configuration.SetPinFunction(32, DeviceFunction.ADC1_CH4);
- return _adc.OpenChannel(4);
- case 39:
- Configuration.SetPinFunction(39, DeviceFunction.ADC1_CH3);
- return _adc.OpenChannel(3);
- case 0:
- Configuration.SetPinFunction(0, DeviceFunction.ADC1_CH11);
- return _adc.OpenChannel(11);
- case 2:
- Configuration.SetPinFunction(2, DeviceFunction.ADC1_CH12);
- return _adc.OpenChannel(12);
- case 4:
- Configuration.SetPinFunction(4, DeviceFunction.ADC1_CH10);
- return _adc.OpenChannel(10);
- case 12:
- Configuration.SetPinFunction(12, DeviceFunction.ADC1_CH15);
- return _adc.OpenChannel(15);
- case 15:
- Configuration.SetPinFunction(15, DeviceFunction.ADC1_CH13);
- return _adc.OpenChannel(13);
- case 25:
- Configuration.SetPinFunction(25, DeviceFunction.ADC1_CH18);
- return _adc.OpenChannel(18);
- case 27:
- Configuration.SetPinFunction(26, DeviceFunction.ADC1_CH17);
- return _adc.OpenChannel(17);
- default:
- throw new ArgumentException(nameof(gpioNumber));
- }
- }
}
}
diff --git a/nanoFramework.M5Core2/nanoFramework.M5Core2.nfproj b/nanoFramework.M5Core2/nanoFramework.M5Core2.nfproj
index d64ce35d..7c6e2873 100644
--- a/nanoFramework.M5Core2/nanoFramework.M5Core2.nfproj
+++ b/nanoFramework.M5Core2/nanoFramework.M5Core2.nfproj
@@ -20,7 +20,6 @@
-
@@ -28,8 +27,6 @@
True
Resource.resx
-
-
@@ -191,4 +188,4 @@
-
\ No newline at end of file
+
diff --git a/nanoFramework.M5Core2/packages.config b/nanoFramework.M5Core2/packages.config
index b79ce6e6..a8557dfc 100644
--- a/nanoFramework.M5Core2/packages.config
+++ b/nanoFramework.M5Core2/packages.config
@@ -34,4 +34,4 @@
-
\ No newline at end of file
+
diff --git a/nanoFramework.M5Stack.sln b/nanoFramework.M5Stack.sln
index 95a330a1..28c3a238 100644
--- a/nanoFramework.M5Stack.sln
+++ b/nanoFramework.M5Stack.sln
@@ -12,6 +12,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
nanoFramework.M5Core2.nuspec = nanoFramework.M5Core2.nuspec
nanoFramework.M5StickC.nuspec = nanoFramework.M5StickC.nuspec
nanoFramework.M5StickCPlus.nuspec = nanoFramework.M5StickCPlus.nuspec
+ nanoFramework.Tough.nuspec = nanoFramework.Tough.nuspec
NuGet.Config = NuGet.Config
version.json = version.json
EndProjectSection
@@ -52,13 +53,11 @@ Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "FireTestApp", "Tests\FireTe
EndProject
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "nanoFramework.Fire", "nanoFramework.Fire\nanoFramework.Fire.nfproj", "{2550D7FC-BBA7-4173-9071-8606DD600A2C}"
EndProject
+Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "nanoFramework.Tough", "nanoFramework.Tough\nanoFramework.Tough.nfproj", "{E867A53E-3849-4AD3-832E-92D126999074}"
+EndProject
+Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "ToughTestApp", "Tests\ToughTestApp\ToughTestApp.nfproj", "{F5BF3DA4-B92E-46C6-A135-37E6A7E002A1}"
+EndProject
Global
- GlobalSection(SharedMSBuildProjectFiles) = preSolution
- M5StackCommon\M5StackCommon.projitems*{00e23322-2401-4087-abae-24f90c8a0422}*SharedItemsImports = 13
- nanoFramework.M5StickCommon\nanoFramework.M5StickCommon.projitems*{1f49b255-573d-4d02-87da-08c4a95744b0}*SharedItemsImports = 13
- AtomCommon\AtomCommon.projitems*{79f09006-ab5d-4e3e-ad12-2efbee536ca9}*SharedItemsImports = 13
- nanoFramework.M5StackCore\nanoFramework.M5StackCore.projitems*{e2a94f3c-ee7f-4075-a98a-a19cabe82c0f}*SharedItemsImports = 13
- EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
@@ -142,6 +141,18 @@ Global
{2550D7FC-BBA7-4173-9071-8606DD600A2C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2550D7FC-BBA7-4173-9071-8606DD600A2C}.Release|Any CPU.Build.0 = Release|Any CPU
{2550D7FC-BBA7-4173-9071-8606DD600A2C}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {E867A53E-3849-4AD3-832E-92D126999074}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E867A53E-3849-4AD3-832E-92D126999074}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E867A53E-3849-4AD3-832E-92D126999074}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+ {E867A53E-3849-4AD3-832E-92D126999074}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E867A53E-3849-4AD3-832E-92D126999074}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E867A53E-3849-4AD3-832E-92D126999074}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {F5BF3DA4-B92E-46C6-A135-37E6A7E002A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F5BF3DA4-B92E-46C6-A135-37E6A7E002A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F5BF3DA4-B92E-46C6-A135-37E6A7E002A1}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+ {F5BF3DA4-B92E-46C6-A135-37E6A7E002A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F5BF3DA4-B92E-46C6-A135-37E6A7E002A1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F5BF3DA4-B92E-46C6-A135-37E6A7E002A1}.Release|Any CPU.Deploy.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -157,8 +168,15 @@ Global
{88F1D73A-1ADF-4444-A031-024E570945CC} = {5972CDE6-43B4-42F0-9276-6B70B7EF6437}
{79F09006-AB5D-4E3E-AD12-2EFBEE536CA9} = {FFF3F871-7600-480E-B378-95AD0F9FC0F1}
{5FF00F7C-8ED8-4468-9959-497CE8C5B1AF} = {5972CDE6-43B4-42F0-9276-6B70B7EF6437}
+ {F5BF3DA4-B92E-46C6-A135-37E6A7E002A1} = {5972CDE6-43B4-42F0-9276-6B70B7EF6437}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DD82D7FF-B798-48A4-8506-2FBA0001D32F}
EndGlobalSection
+ GlobalSection(SharedMSBuildProjectFiles) = preSolution
+ M5StackCommon\M5StackCommon.projitems*{00e23322-2401-4087-abae-24f90c8a0422}*SharedItemsImports = 13
+ nanoFramework.M5StickCommon\nanoFramework.M5StickCommon.projitems*{1f49b255-573d-4d02-87da-08c4a95744b0}*SharedItemsImports = 13
+ AtomCommon\AtomCommon.projitems*{79f09006-ab5d-4e3e-ad12-2efbee536ca9}*SharedItemsImports = 13
+ nanoFramework.M5StackCore\nanoFramework.M5StackCore.projitems*{e2a94f3c-ee7f-4075-a98a-a19cabe82c0f}*SharedItemsImports = 13
+ EndGlobalSection
EndGlobal
diff --git a/nanoFramework.M5StackCore/M5CoreBase.cs b/nanoFramework.M5StackCore/M5CoreBase.cs
index fcdb5dce..bb4edb50 100644
--- a/nanoFramework.M5StackCore/M5CoreBase.cs
+++ b/nanoFramework.M5StackCore/M5CoreBase.cs
@@ -1,8 +1,10 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+#if !TOUGH
using Iot.Device.Magnetometer;
using Iot.Device.Mpu6886;
+#endif
using System.Device.Adc;
using System.Device.Dac;
using System.Device.Gpio;
@@ -22,6 +24,11 @@ public static partial class M5Core2
/// Fire board
///
public static partial class Fire
+#elif TOUGH
+ ///
+ /// Tough board
+ ///
+ public static partial class Tough
#else
///
/// M5Stack board
@@ -29,8 +36,10 @@ public static partial class Fire
public static partial class M5Core
#endif
{
+#if !TOUGH
private static Bmm150 _bmm150;
private static Mpu6886AccelerometerGyroscope _mpu6886;
+#endif
private static GpioController _gpio;
private static DacChannel _dac1;
private static DacChannel _dac2;
@@ -39,6 +48,7 @@ public static partial class M5Core
private static AdcController _adc;
private static int _portANumber;
+#if !TOUGH
///
/// Gets the Magnetometer.
///
@@ -73,12 +83,23 @@ public static Mpu6886AccelerometerGyroscope AccelerometerGyroscope
}
}
+#endif
///
- /// Gets the main GPIO Controller.
+ /// Gets the main .
///
- public static GpioController GpioController => _gpio;
+ public static GpioController GpioController
+ {
+ get
+ {
+ if (_gpio is null)
+ {
+ _gpio = new();
+ }
+ return _gpio;
+ }
+ }
///
/// Gets DAC1 which is GPIO 25.
diff --git a/nanoFramework.M5StickC/nanoFramework.M5StickC.nfproj b/nanoFramework.M5StickC/nanoFramework.M5StickC.nfproj
index ddaa4bc4..43b85fda 100644
--- a/nanoFramework.M5StickC/nanoFramework.M5StickC.nfproj
+++ b/nanoFramework.M5StickC/nanoFramework.M5StickC.nfproj
@@ -152,4 +152,4 @@
-
\ No newline at end of file
+
diff --git a/nanoFramework.M5StickC/packages.config b/nanoFramework.M5StickC/packages.config
index 0c6e7ca5..4d4c265a 100644
--- a/nanoFramework.M5StickC/packages.config
+++ b/nanoFramework.M5StickC/packages.config
@@ -25,4 +25,4 @@
-
\ No newline at end of file
+
diff --git a/nanoFramework.M5StickCPlus/nanoFramework.M5StickCPlus.nfproj b/nanoFramework.M5StickCPlus/nanoFramework.M5StickCPlus.nfproj
index e80ebcd6..2e550807 100644
--- a/nanoFramework.M5StickCPlus/nanoFramework.M5StickCPlus.nfproj
+++ b/nanoFramework.M5StickCPlus/nanoFramework.M5StickCPlus.nfproj
@@ -163,4 +163,4 @@
-
\ No newline at end of file
+
diff --git a/nanoFramework.M5StickCPlus/packages.config b/nanoFramework.M5StickCPlus/packages.config
index 317f6672..035fa1d1 100644
--- a/nanoFramework.M5StickCPlus/packages.config
+++ b/nanoFramework.M5StickCPlus/packages.config
@@ -28,4 +28,4 @@
-
\ No newline at end of file
+
diff --git a/nanoFramework.M5StickCommon/M5StickCBase.cs b/nanoFramework.M5StickCommon/M5StickCBase.cs
index 56a3ca7f..6eafa052 100644
--- a/nanoFramework.M5StickCommon/M5StickCBase.cs
+++ b/nanoFramework.M5StickCommon/M5StickCBase.cs
@@ -180,9 +180,6 @@ static M5StickCPlus()
_power.EnableButtonPressed(ButtonPressed.LongPressed | ButtonPressed.ShortPressed);
_power.SetButtonBehavior(LongPressTiming.S2, ShortPressTiming.Ms128, true, SignalDelayAfterPowerUp.Ms32, ShutdownTiming.S10);
- // Setting up GPIO Controller for the buttons
- _gpio = new();
-
// Set the Grove port
Configuration.SetPinFunction(33, DeviceFunction.I2C2_CLOCK);
Configuration.SetPinFunction(32, DeviceFunction.I2C2_DATA);
diff --git a/nanoFramework.Tough.nuspec b/nanoFramework.Tough.nuspec
new file mode 100644
index 00000000..c92d5b17
--- /dev/null
+++ b/nanoFramework.Tough.nuspec
@@ -0,0 +1,45 @@
+
+
+
+ nanoFramework.Tough
+ $version$
+ nanoFramework.Tough
+ nanoframework
+ false
+ LICENSE.md
+
+
+ docs\README.md
+ false
+ https://github.com/nanoframework/nanoFramework.M5Stack
+ images\nf-logo.png
+
+ Copyright (c) .NET Foundation and Contributors
+ This package includes the nanoFramework.Tough assembly for .NET nanoFramework C# projects.
+ nanoFramework C# csharp netmf netnf m5stack Tough
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/nanoFramework.Tough/Properties/AssemblyInfo.cs b/nanoFramework.Tough/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..7801a8a9
--- /dev/null
+++ b/nanoFramework.Tough/Properties/AssemblyInfo.cs
@@ -0,0 +1,39 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("CSharp.TestApplication")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("CSharp.TestApplication")]
+[assembly: AssemblyCopyright("Copyright © 2022")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+
+/////////////////////////////////////////////////////////////////
+// This attribute is mandatory when building Interop libraries //
+// update this whenever the native assembly signature changes //
+[assembly: AssemblyNativeVersion("1.0.0.0")]
+/////////////////////////////////////////////////////////////////
diff --git a/nanoFramework.Tough/Resource.Designer.cs b/nanoFramework.Tough/Resource.Designer.cs
new file mode 100644
index 00000000..572e4ae4
--- /dev/null
+++ b/nanoFramework.Tough/Resource.Designer.cs
@@ -0,0 +1,38 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace nanoFramework.Tough
+{
+
+ internal partial class Resource
+ {
+ private static System.Resources.ResourceManager manager;
+ internal static System.Resources.ResourceManager ResourceManager
+ {
+ get
+ {
+ if ((Resource.manager == null))
+ {
+ Resource.manager = new System.Resources.ResourceManager("nanoFramework.Tough.Resource", typeof(Resource).Assembly);
+ }
+ return Resource.manager;
+ }
+ }
+ internal static nanoFramework.UI.Font GetFont(Resource.FontResources id)
+ {
+ return ((nanoFramework.UI.Font)(nanoFramework.Runtime.Native.ResourceUtility.GetObject(ResourceManager, id)));
+ }
+ [System.SerializableAttribute()]
+ internal enum FontResources : short
+ {
+ consolas_regular_16 = 10023,
+ }
+ }
+}
diff --git a/nanoFramework.Tough/Resource.resx b/nanoFramework.Tough/Resource.resx
new file mode 100644
index 00000000..848e7875
--- /dev/null
+++ b/nanoFramework.Tough/Resource.resx
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+ Resources\consolas_regular_16.tinyfnt;System.Byte[], mscorlib, Version=1.12.0.4, Culture=neutral, PublicKeyToken=c07d481e9758c731
+
+
\ No newline at end of file
diff --git a/nanoFramework.Tough/Resources/consolas_regular_16.tinyfnt b/nanoFramework.Tough/Resources/consolas_regular_16.tinyfnt
new file mode 100644
index 00000000..2331827a
Binary files /dev/null and b/nanoFramework.Tough/Resources/consolas_regular_16.tinyfnt differ
diff --git a/nanoFramework.M5Core2/Screen.cs b/nanoFramework.Tough/Screen.cs
similarity index 99%
rename from nanoFramework.M5Core2/Screen.cs
rename to nanoFramework.Tough/Screen.cs
index d67df78c..dfc9fe05 100644
--- a/nanoFramework.M5Core2/Screen.cs
+++ b/nanoFramework.Tough/Screen.cs
@@ -11,7 +11,7 @@
namespace nanoFramework.M5Stack
{
///
- /// M5Core2 screen class
+ /// M5Tough screen class
///
public class Screen : ScreenBase
{
diff --git a/nanoFramework.Tough/Tough.cs b/nanoFramework.Tough/Tough.cs
new file mode 100644
index 00000000..6f1e8f92
--- /dev/null
+++ b/nanoFramework.Tough/Tough.cs
@@ -0,0 +1,12 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace nanoFramework.M5Stack
+{
+ ///
+ /// Tough board
+ ///
+ public static partial class Tough
+ {
+ }
+}
diff --git a/nanoFramework.Tough/key.snk b/nanoFramework.Tough/key.snk
new file mode 100644
index 00000000..67c9bb0a
Binary files /dev/null and b/nanoFramework.Tough/key.snk differ
diff --git a/nanoFramework.Tough/nanoFramework.Tough.nfproj b/nanoFramework.Tough/nanoFramework.Tough.nfproj
new file mode 100644
index 00000000..2650ec50
--- /dev/null
+++ b/nanoFramework.Tough/nanoFramework.Tough.nfproj
@@ -0,0 +1,124 @@
+
+
+
+ $(MSBuildExtensionsPath)\nanoFramework\v1.0\
+
+
+
+ Debug
+ AnyCPU
+ {11A8DD76-328B-46DF-9F39-F559912D0360};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ e867a53e-3849-4ad3-832e-92d126999074
+ Library
+ Properties
+ 512
+ nanoFramework.Tough
+ nanoFramework.Tough
+ $(DefineConstants);TOUGH
+ bin\$(Configuration)\nanoFramework.Tough.xml
+ v1.0
+
+
+
+
+ True
+ True
+ Resource.resx
+
+
+
+
+
+
+ ..\packages\nanoFramework.Iot.Device.Axp192.1.1.74.7591\lib\Iot.Device.Axp192.dll
+
+
+ ..\packages\nanoFramework.Iot.Device.Chs6540.1.0.16\lib\Iot.Device.Chs6540.dll
+
+
+ ..\packages\nanoFramework.Iot.Device.Common.NumberHelper.1.1.1\lib\Iot.Device.Common.NumberHelper.dll
+
+
+ ..\packages\nanoFramework.Iot.Device.Rtc.1.1.72.29765\lib\Iot.Device.Rtc.dll
+
+
+ ..\packages\nanoFramework.CoreLibrary.1.12.0\lib\mscorlib.dll
+
+
+ ..\packages\nanoFramework.Graphics.1.0.2\lib\nanoFramework.Graphics.dll
+
+
+ ..\packages\nanoFramework.Hardware.Esp32.1.3.6\lib\nanoFramework.Hardware.Esp32.dll
+
+
+ ..\packages\nanoFramework.ResourceManager.1.1.4\lib\nanoFramework.ResourceManager.dll
+
+
+ ..\packages\nanoFramework.Runtime.Events.1.10.0\lib\nanoFramework.Runtime.Events.dll
+
+
+ ..\packages\nanoFramework.Runtime.Native.1.5.4\lib\nanoFramework.Runtime.Native.dll
+
+
+ ..\packages\nanoFramework.System.Collections.1.4.0\lib\nanoFramework.System.Collections.dll
+
+
+ ..\packages\nanoFramework.System.Text.1.1.3\lib\nanoFramework.System.Text.dll
+
+
+ ..\packages\nanoFramework.System.Device.Adc.1.0.2\lib\System.Device.Adc.dll
+
+
+ ..\packages\nanoFramework.System.Device.Dac.1.4.3\lib\System.Device.Dac.dll
+
+
+ ..\packages\nanoFramework.System.Device.Gpio.1.0.4\lib\System.Device.Gpio.dll
+
+
+ ..\packages\nanoFramework.System.Device.I2c.1.0.3\lib\System.Device.I2c.dll
+
+
+ ..\packages\nanoFramework.System.Device.Spi.1.2.1\lib\System.Device.Spi.dll
+
+
+ ..\packages\nanoFramework.System.IO.Ports.1.0.7.1\lib\System.IO.Ports.dll
+
+
+ ..\packages\nanoFramework.System.IO.Streams.1.0.0\lib\System.IO.Streams.dll
+
+
+ ..\packages\nanoFramework.System.Threading.1.0.4\lib\System.Threading.dll
+
+
+ ..\packages\UnitsNet.nanoFramework.ElectricCurrent.4.132.0\lib\UnitsNet.ElectricCurrent.dll
+
+
+ ..\packages\UnitsNet.nanoFramework.ElectricPotential.4.132.0\lib\UnitsNet.ElectricPotential.dll
+
+
+ ..\packages\UnitsNet.nanoFramework.Power.4.132.0\lib\UnitsNet.Power.dll
+
+
+ ..\packages\UnitsNet.nanoFramework.Temperature.4.132.0\lib\UnitsNet.Temperature.dll
+
+
+
+
+
+
+
+
+
+ nFResXFileCodeGenerator
+ Resource.Designer.cs
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/nanoFramework.Tough/packages.config b/nanoFramework.Tough/packages.config
new file mode 100644
index 00000000..a73853c4
--- /dev/null
+++ b/nanoFramework.Tough/packages.config
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file