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