diff --git a/Hardware/Schematic_v1.pdf b/Hardware/Schematic_v1.pdf new file mode 100644 index 0000000..cbbed4f Binary files /dev/null and b/Hardware/Schematic_v1.pdf differ diff --git a/Hardware/Schematic_v2.c.pdf b/Hardware/Schematic_v2.c.pdf new file mode 100644 index 0000000..acfc7a7 Binary files /dev/null and b/Hardware/Schematic_v2.c.pdf differ diff --git a/Hardware/Schematic_v3.b.pdf b/Hardware/Schematic_v3.b.pdf new file mode 100644 index 0000000..56e24ca Binary files /dev/null and b/Hardware/Schematic_v3.b.pdf differ diff --git a/Source/Juego.sln b/Source/Juego.sln index eb02482..26c3c43 100644 --- a/Source/Juego.sln +++ b/Source/Juego.sln @@ -39,6 +39,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Meadow.Modbus", "..\..\Mead EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet", "..\..\MQTTnet\Source\MQTTnet\MQTTnet.csproj", "{20EC73F2-5F86-40DB-8FEA-4B60BFE3D7EA}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sensors.Motion.Bmi270", "..\..\Meadow.Foundation\Source\Meadow.Foundation.Peripherals\Sensors.Motion.Bmi270\Driver\Sensors.Motion.Bmi270.csproj", "{638A262A-E4F3-4D86-9E34-21717F928D79}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Audio.MicroAudio", "..\..\Meadow.Foundation\Source\Meadow.Foundation.Libraries_and_Frameworks\Audio.MicroAudio\Driver\Audio.MicroAudio.csproj", "{8E8CE3FA-D9D8-4912-A76D-F8017A7AEBC7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -135,6 +139,18 @@ Global {20EC73F2-5F86-40DB-8FEA-4B60BFE3D7EA}.Debug|Any CPU.Build.0 = Debug|Any CPU {20EC73F2-5F86-40DB-8FEA-4B60BFE3D7EA}.Release|Any CPU.ActiveCfg = Release|Any CPU {20EC73F2-5F86-40DB-8FEA-4B60BFE3D7EA}.Release|Any CPU.Build.0 = Release|Any CPU + {638A262A-E4F3-4D86-9E34-21717F928D79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {638A262A-E4F3-4D86-9E34-21717F928D79}.Debug|Any CPU.Build.0 = Debug|Any CPU + {638A262A-E4F3-4D86-9E34-21717F928D79}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {638A262A-E4F3-4D86-9E34-21717F928D79}.Release|Any CPU.ActiveCfg = Release|Any CPU + {638A262A-E4F3-4D86-9E34-21717F928D79}.Release|Any CPU.Build.0 = Release|Any CPU + {638A262A-E4F3-4D86-9E34-21717F928D79}.Release|Any CPU.Deploy.0 = Release|Any CPU + {8E8CE3FA-D9D8-4912-A76D-F8017A7AEBC7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8E8CE3FA-D9D8-4912-A76D-F8017A7AEBC7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8E8CE3FA-D9D8-4912-A76D-F8017A7AEBC7}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {8E8CE3FA-D9D8-4912-A76D-F8017A7AEBC7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8E8CE3FA-D9D8-4912-A76D-F8017A7AEBC7}.Release|Any CPU.Build.0 = Release|Any CPU + {8E8CE3FA-D9D8-4912-A76D-F8017A7AEBC7}.Release|Any CPU.Deploy.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -154,6 +170,8 @@ Global {7D611BC9-B5BF-424C-A03C-3FC7FA8E703A} = {FF570CB7-3F54-4049-A167-304A90098DB6} {D1FD4798-703D-4199-940C-4EDC516E88FC} = {FF570CB7-3F54-4049-A167-304A90098DB6} {20EC73F2-5F86-40DB-8FEA-4B60BFE3D7EA} = {FF570CB7-3F54-4049-A167-304A90098DB6} + {638A262A-E4F3-4D86-9E34-21717F928D79} = {FF570CB7-3F54-4049-A167-304A90098DB6} + {8E8CE3FA-D9D8-4912-A76D-F8017A7AEBC7} = {FF570CB7-3F54-4049-A167-304A90098DB6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {CB582CC6-C626-484E-9742-43FD65FE8158} diff --git a/Source/Juego/IJuegoHardware.cs b/Source/Juego/IJuegoHardware.cs index 5edf1fd..b3c0d39 100644 --- a/Source/Juego/IJuegoHardware.cs +++ b/Source/Juego/IJuegoHardware.cs @@ -1,18 +1,19 @@ using Meadow.Foundation.Audio; using Meadow.Foundation.Graphics; using Meadow.Foundation.Leds; +using Meadow.Foundation.Sensors.Accelerometers; using Meadow.Foundation.Sensors.Buttons; using Meadow.Hardware; namespace WildernessLabs.Hardware.Juego { /// - /// Represents the hardware interface for the Juego device. + /// Represents the hardware interface for the Juego device /// public interface IJuegoHardware { /// - /// Gets the graphics display interface. + /// Gets the graphics display interface /// public IGraphicsDisplay? Display { get; } @@ -74,9 +75,19 @@ public interface IJuegoHardware /// public PwmLed? BlinkyLed { get; } + /// + /// Gets the motion sensor + /// + public Bmi270? MotionSensor { get; } + /// /// Gets the display header connector /// public DisplayConnector DisplayHeader { get; } + + /// + /// Gets the Stemma QT I2C Qwiic connector + /// + public I2cConnector? Qwiic { get; } } } \ No newline at end of file diff --git a/Source/Juego/Juego.cs b/Source/Juego/Juego.cs index 82157c8..f8687e9 100644 --- a/Source/Juego/Juego.cs +++ b/Source/Juego/Juego.cs @@ -1,19 +1,24 @@ using Meadow; +using Meadow.Foundation.Audio; +using Meadow.Foundation.ICs.IOExpanders; using Meadow.Logging; using System; namespace WildernessLabs.Hardware.Juego { + /// + /// Juego hardware factory class for Juego v1, v2, and v3 hardware + /// public class Juego { private Juego() { } /// - /// Create an instance of the Juego class + /// Create an instance of the Juego class for the current hardware /// - public static IJuegoHardware Create() + public static IJuegoHardware? Create() { - IJuegoHardware hardware; + IJuegoHardware? hardware; Logger? logger = Resolver.Log; logger?.Debug("Initializing Juego..."); @@ -35,8 +40,48 @@ public static IJuegoHardware Create() } else if (device is IF7CoreComputeMeadowDevice { } ccm) { - logger?.Info("Instantiating Juego v2 hardware"); - hardware = new JuegoHardwareV2(ccm); + try + { + // hack for PWM init bug .... move back into the hardware classes once it's fixed + var leftSpeaker = new PiezoSpeaker(ccm.Pins.PB8); + var rightSpeaker = new PiezoSpeaker(ccm.Pins.PB9); + + var i2cBus = ccm.CreateI2cBus(busSpeed: Meadow.Hardware.I2cBusSpeed.FastPlus); + logger?.Info("I2C Bus instantiated"); + + var mcpVersion = new Mcp23008(i2cBus, address: 0x23); + + logger?.Trace("McpVersion up"); + var version = mcpVersion.ReadFromPorts(); + + logger?.Info($"Hardware version is {version}"); + + if (version >= JuegoHardwareV3.MinimumHardareVersion) + { + logger?.Info("Instantiating Juego v3 hardware"); + hardware = new JuegoHardwareV3(ccm, i2cBus) + { + Mcp_VersionInfo = mcpVersion, + LeftSpeaker = leftSpeaker, + RightSpeaker = rightSpeaker, + }; + } + else + { + logger?.Info("Instantiating Juego v2 hardware"); + hardware = new JuegoHardwareV2(ccm, i2cBus) + { + Mcp_VersionInfo = mcpVersion, + LeftSpeaker = leftSpeaker, + RightSpeaker = rightSpeaker, + }; + } + } + catch (Exception e) + { + logger?.Debug($"Failed to create McpVersion: {e.Message}"); + hardware = null; + } } else { diff --git a/Source/Juego/Juego.csproj b/Source/Juego/Juego.csproj index 50bf2ef..7118bff 100644 --- a/Source/Juego/Juego.csproj +++ b/Source/Juego/Juego.csproj @@ -25,7 +25,9 @@ + + diff --git a/Source/Juego/JuegoHardwareV1.cs b/Source/Juego/JuegoHardwareV1.cs index 4d2be9d..6f32413 100644 --- a/Source/Juego/JuegoHardwareV1.cs +++ b/Source/Juego/JuegoHardwareV1.cs @@ -3,6 +3,7 @@ using Meadow.Foundation.Displays; using Meadow.Foundation.Graphics; using Meadow.Foundation.Leds; +using Meadow.Foundation.Sensors.Accelerometers; using Meadow.Foundation.Sensors.Buttons; using Meadow.Foundation.Sensors.Hid; using Meadow.Hardware; @@ -11,39 +12,60 @@ namespace WildernessLabs.Hardware.Juego { + /// + /// Represents the hardware interface for the Juego v1 device + /// public class JuegoHardwareV1 : IJuegoHardware { + /// protected IF7FeatherMeadowDevice Device { get; } + /// public IGraphicsDisplay Display { get; } + /// protected ISpiBus SpiBus { get; } + /// public AnalogJoystick? AnalogJoystick { get; protected set; } + /// public PushButton? Right_UpButton { get; protected set; } + /// public PushButton? Right_DownButton { get; protected set; } + /// public PushButton? Right_LeftButton { get; protected set; } + /// public PushButton? Right_RightButton { get; protected set; } - + /// public PushButton? Left_UpButton => null; + /// public PushButton? Left_DownButton => null; + /// public PushButton? Left_LeftButton => null; + /// public PushButton? Left_RightButton => null; - + /// public PushButton? StartButton { get; protected set; } + /// public PushButton? SelectButton { get; protected set; } - + /// public PiezoSpeaker? LeftSpeaker { get; protected set; } + /// public PiezoSpeaker? RightSpeaker { get; protected set; } - + /// public PwmLed? BlinkyLed => null; - /// - /// Gets the display header connector on the Juego board - /// + /// + public Bmi270? MotionSensor => null; + + /// public DisplayConnector DisplayHeader => (DisplayConnector)Connectors[0]; + /// + public I2cConnector Qwiic => null; + + /// /// Collection of connectors on the Juego board /// @@ -54,7 +76,7 @@ public IConnector?[] Connectors if (_connectors == null) { _connectors = new IConnector[1]; - _connectors[1] = CreateDisplayConnector(); + _connectors[0] = CreateDisplayConnector(); } return _connectors; @@ -63,6 +85,9 @@ public IConnector?[] Connectors private IConnector?[]? _connectors; + /// + /// Create a new Juego hardware v1 object + /// public JuegoHardwareV1(IF7FeatherMeadowDevice device) { Device = device; diff --git a/Source/Juego/JuegoHardwareV2.cs b/Source/Juego/JuegoHardwareV2.cs index 887d5d7..ca2dd8d 100644 --- a/Source/Juego/JuegoHardwareV2.cs +++ b/Source/Juego/JuegoHardwareV2.cs @@ -4,61 +4,78 @@ using Meadow.Foundation.Graphics; using Meadow.Foundation.ICs.IOExpanders; using Meadow.Foundation.Leds; +using Meadow.Foundation.Sensors.Accelerometers; using Meadow.Foundation.Sensors.Buttons; using Meadow.Hardware; -using Meadow.Logging; using Meadow.Units; using System; using System.Threading; namespace WildernessLabs.Hardware.Juego { + /// + /// Represents the hardware interface for the Juego v2 device + /// public class JuegoHardwareV2 : IJuegoHardware { + /// protected IF7CoreComputeMeadowDevice Device { get; } + /// protected IDigitalInterruptPort McpInterrupt_1 { get; } - + /// protected IDigitalInterruptPort McpInterrupt_2 { get; } - + /// protected IDigitalOutputPort Mcp_Reset { get; } - + /// public IGraphicsDisplay Display { get; } - + /// public IDigitalOutputPort DisplayBacklightPort { get; } - + /// protected II2cBus I2cBus { get; } + /// protected ISpiBus SpiBus { get; } - + /// public Mcp23008 Mcp_1 { get; protected set; } + /// public Mcp23008 Mcp_2 { get; protected set; } - public Mcp23008 Mcp_VersionInfo { get; protected set; } - + /// + public Mcp23008 Mcp_VersionInfo { get; set; } + /// public PushButton? Right_UpButton { get; protected set; } + /// public PushButton? Right_DownButton { get; protected set; } + /// public PushButton? Right_LeftButton { get; protected set; } + /// public PushButton? Right_RightButton { get; protected set; } - + /// public PushButton? Left_UpButton { get; protected set; } + /// public PushButton? Left_DownButton { get; protected set; } + /// public PushButton? Left_LeftButton { get; protected set; } + /// public PushButton? Left_RightButton { get; protected set; } - + /// public PushButton? StartButton { get; protected set; } + /// public PushButton? SelectButton { get; protected set; } - - public PiezoSpeaker? LeftSpeaker { get; protected set; } - public PiezoSpeaker? RightSpeaker { get; protected set; } - + /// + public PiezoSpeaker? LeftSpeaker { get; set; } + /// + public PiezoSpeaker? RightSpeaker { get; set; } + /// public PwmLed? BlinkyLed { get; protected set; } + /// + public Bmi270? MotionSensor => null; - /// - /// Gets the display header connector on the Juego board - /// + /// public DisplayConnector DisplayHeader => (DisplayConnector)Connectors[0]; - /// - /// Collection of connectors on the Juego board - /// + /// + public I2cConnector? Qwiic => null; + + /// public IConnector?[] Connectors { get @@ -66,7 +83,7 @@ public IConnector?[] Connectors if (_connectors == null) { _connectors = new IConnector[1]; - _connectors[1] = CreateDisplayConnector(); + _connectors[0] = CreateDisplayConnector(); } return _connectors; @@ -75,40 +92,34 @@ public IConnector?[] Connectors private IConnector?[]? _connectors; - public JuegoHardwareV2(IF7CoreComputeMeadowDevice device) + /// + /// Create a new Juego hardware v2 object + /// + public JuegoHardwareV2(IF7CoreComputeMeadowDevice device, II2cBus i2cBus) { Device = device; + I2cBus = i2cBus; Resolver.Log.Info("Initialize hardware..."); // DEV NOTE: **ALWAYS** Set up PWMs first - Nuttx PWM driver will step on pin configs otherwise - try - { - LeftSpeaker = new PiezoSpeaker(device.Pins.PB8); //D03 - } - catch (Exception e) - { - Resolver.Log.Error($"Err Left Speaker: {e.Message}"); - } - - try - { - RightSpeaker = new PiezoSpeaker(device.Pins.PB9); //D04 - } - catch (Exception e) - { - Resolver.Log.Error($"Err Right Speaker: {e.Message}"); - } - - try - { - I2cBus = Device.CreateI2cBus(busSpeed: I2cBusSpeed.FastPlus); - Resolver.Log.Info("I2C initialized"); - } - catch (Exception e) - { - Resolver.Log.Error($"Err initializing I2C Bus: {e.Message}"); - } + /* try - code left intentionally, restore once the PWM bug is fixed + { + LeftSpeaker = new PiezoSpeaker(device.Pins.PB8); //D03 + } + catch (Exception e) + { + Resolver.Log.Error($"Err Left Speaker: {e.Message}"); + } + + try + { + RightSpeaker = new PiezoSpeaker(device.Pins.PB9); //D04 + } + catch (Exception e) + { + Resolver.Log.Error($"Err Right Speaker: {e.Message}"); + } */ try { @@ -133,16 +144,6 @@ public JuegoHardwareV2(IF7CoreComputeMeadowDevice device) Resolver.Log.Error($"Err MCP 2: {e.Message}"); } - try - { - Mcp_VersionInfo = new Mcp23008(I2cBus, 0x23); - Resolver.Log.Info("Mcp23008 version initialized"); - } - catch (Exception e) - { - Resolver.Log.Error($"Err MCP 3: {e.Message}"); - } - try { BlinkyLed = new PwmLed(device.Pins.D20, TypicalForwardVoltage.Green); diff --git a/Source/Juego/JuegoHardwareV3.cs b/Source/Juego/JuegoHardwareV3.cs new file mode 100644 index 0000000..cbae9f7 --- /dev/null +++ b/Source/Juego/JuegoHardwareV3.cs @@ -0,0 +1,284 @@ +using Meadow; +using Meadow.Foundation.Audio; +using Meadow.Foundation.Displays; +using Meadow.Foundation.Graphics; +using Meadow.Foundation.ICs.IOExpanders; +using Meadow.Foundation.Leds; +using Meadow.Foundation.Sensors.Accelerometers; +using Meadow.Foundation.Sensors.Buttons; +using Meadow.Hardware; +using Meadow.Units; +using System; +using System.Threading; + +namespace WildernessLabs.Hardware.Juego +{ + /// + /// Represents the hardware interface for the Juego v1 device + /// + public class JuegoHardwareV3 : IJuegoHardware + { + /// + /// The minimum hardware version for Juego v3 hardware + /// + public static int MinimumHardareVersion => 3; + + /// + protected IF7CoreComputeMeadowDevice Device { get; } + /// + protected IDigitalInterruptPort McpInterrupt_1 { get; } + /// + protected IDigitalInterruptPort McpInterrupt_2 { get; } + /// + protected IDigitalOutputPort Mcp_Reset { get; } + /// + public IGraphicsDisplay Display { get; } + /// + public IDigitalOutputPort DisplayBacklightPort { get; } + /// + protected II2cBus I2cBus { get; } + /// + protected ISpiBus SpiBus { get; } + /// + public Mcp23008 Mcp_1 { get; protected set; } + /// + public Mcp23008 Mcp_2 { get; protected set; } + /// + public Mcp23008 Mcp_VersionInfo { get; set; } + /// + public PushButton? Right_UpButton { get; protected set; } + /// + public PushButton? Right_DownButton { get; protected set; } + /// + public PushButton? Right_LeftButton { get; protected set; } + /// + public PushButton? Right_RightButton { get; protected set; } + /// + public PushButton? Left_UpButton { get; protected set; } + /// + public PushButton? Left_DownButton { get; protected set; } + /// + public PushButton? Left_LeftButton { get; protected set; } + /// + public PushButton? Left_RightButton { get; protected set; } + /// + public PushButton? StartButton { get; protected set; } + /// + public PushButton? SelectButton { get; protected set; } + /// + public PiezoSpeaker? LeftSpeaker { get; set; } + /// + public PiezoSpeaker? RightSpeaker { get; set; } + /// + public PwmLed? BlinkyLed { get; protected set; } + /// + public Bmi270? MotionSensor { get; protected set; } + + /// + public DisplayConnector DisplayHeader => (DisplayConnector)Connectors[0]; + + /// + public I2cConnector? Qwiic => (I2cConnector)Connectors[1]; + + /// + /// Collection of connectors on the Juego board + /// + public IConnector?[] Connectors + { + get + { + if (_connectors == null) + { + _connectors = new IConnector[2]; + _connectors[0] = CreateDisplayConnector(); + _connectors[1] = CreateQwiicConnector(); + } + + return _connectors; + } + } + + private IConnector?[]? _connectors; + + /// + /// Create a new Juego hardware v3 object + /// + public JuegoHardwareV3(IF7CoreComputeMeadowDevice device, II2cBus i2cBus) + { + Device = device; + I2cBus = i2cBus; + + Resolver.Log.Info("Initialize hardware..."); + + // DEV NOTE: **ALWAYS** Set up PWMs first - Nuttx PWM driver will step on pin configs otherwise + /* try // code left intentionally, restore once the PWM bug is fixed + { + LeftSpeaker = new PiezoSpeaker(device.Pins.PB8); //D03 + } + catch (Exception e) + { + Resolver.Log.Error($"Err Left Speaker: {e.Message}"); + } + + try + { + RightSpeaker = new PiezoSpeaker(device.Pins.PB9); //D04 + } + catch (Exception e) + { + Resolver.Log.Error($"Err Right Speaker: {e.Message}"); + } */ + + /* + try + { + I2cBus = Device.CreateI2cBus(busSpeed: I2cBusSpeed.FastPlus); + Resolver.Log.Info("I2C initialized"); + } + catch (Exception e) + { + Resolver.Log.Error($"Err initializing I2C Bus: {e.Message}"); + } + */ + + try + { + Mcp_Reset = Device.CreateDigitalOutputPort(Device.Pins.PA10, true); + McpInterrupt_1 = Device.CreateDigitalInterruptPort(Device.Pins.PD5, InterruptMode.EdgeRising); + Mcp_1 = new Mcp23008(I2cBus, 0x20, McpInterrupt_1, Mcp_Reset); + Resolver.Log.Info("Mcp23008 #1 initialized"); + } + catch (Exception e) + { + Resolver.Log.Error($"Err MCP 1: {e.Message}"); + } + + try + { + McpInterrupt_2 = Device.CreateDigitalInterruptPort(Device.Pins.PI11, InterruptMode.EdgeRising); + Mcp_2 = new Mcp23008(I2cBus, 0x21, McpInterrupt_2); + Resolver.Log.Info("Mcp23008 #2 initialized"); + } + catch (Exception e) + { + Resolver.Log.Error($"Err MCP 2: {e.Message}"); + } + + try + { + BlinkyLed = new PwmLed(device.Pins.D20, TypicalForwardVoltage.Green); + } + catch (Exception e) + { + Resolver.Log.Error($"Err BlinkyLed: {e.Message}"); + } + + try + { + var config = new SpiClockConfiguration(new Frequency(48000, Frequency.UnitType.Kilohertz), SpiClockConfiguration.Mode.Mode0); + SpiBus = Device.CreateSpiBus(Device.Pins.SPI5_SCK, Device.Pins.SPI5_COPI, Device.Pins.SPI5_CIPO, config); + } + catch (Exception e) + { + Resolver.Log.Error($"Err initializing SPI: {e.Message}"); + } + Resolver.Log.Info("SPI initialized"); + + if (Mcp_1 != null) + { + DisplayBacklightPort = Device.CreateDigitalOutputPort(Device.Pins.D05, true); + + var chipSelectPort = Mcp_1.CreateDigitalOutputPort(Mcp_1.Pins.GP5); + var dcPort = Mcp_1.CreateDigitalOutputPort(Mcp_1.Pins.GP6); + var resetPort = Mcp_1.CreateDigitalOutputPort(Mcp_1.Pins.GP7); + + Thread.Sleep(50); + + Display = new Ili9341( + spiBus: SpiBus, + chipSelectPort: chipSelectPort, + dataCommandPort: dcPort, + resetPort: resetPort, + width: 240, height: 320) + { + SpiBusSpeed = new Frequency(48000, Frequency.UnitType.Kilohertz), + }; + + ((Ili9341)Display).SetRotation(RotationType._270Degrees); + + Resolver.Log.Info("Display initialized"); + } + + try + { + Resolver.Log.Info("Instantiating motion sensor"); + MotionSensor = new Bmi270(I2cBus); + Resolver.Log.Info("Motion sensor up"); + } + catch (Exception ex) + { + Resolver.Log.Error($"Unable to create the BMI270 IMU: {ex.Message}"); + } + + if (Mcp_1 != null) + { + var upPort = Mcp_1.Pins.GP1.CreateDigitalInterruptPort(InterruptMode.EdgeBoth, ResistorMode.InternalPullUp); + var rightPort = Mcp_1.CreateDigitalInterruptPort(Mcp_1.Pins.GP2, InterruptMode.EdgeBoth, ResistorMode.InternalPullUp); + var downPort = Mcp_1.CreateDigitalInterruptPort(Mcp_1.Pins.GP3, InterruptMode.EdgeBoth, ResistorMode.InternalPullUp); + var leftPort = Mcp_1.CreateDigitalInterruptPort(Mcp_1.Pins.GP4, InterruptMode.EdgeBoth, ResistorMode.InternalPullUp); + + Left_UpButton = new PushButton(upPort); + Left_RightButton = new PushButton(rightPort); + Left_DownButton = new PushButton(downPort); + Left_LeftButton = new PushButton(leftPort); + } + + if (Mcp_2 != null) + { + var upPort = Mcp_2.CreateDigitalInterruptPort(Mcp_2.Pins.GP5, InterruptMode.EdgeBoth, ResistorMode.InternalPullUp); + var rightPort = Mcp_2.CreateDigitalInterruptPort(Mcp_2.Pins.GP4, InterruptMode.EdgeBoth, ResistorMode.InternalPullUp); + var downPort = Mcp_2.CreateDigitalInterruptPort(Mcp_2.Pins.GP3, InterruptMode.EdgeBoth, ResistorMode.InternalPullUp); + var leftPort = Mcp_2.CreateDigitalInterruptPort(Mcp_2.Pins.GP2, InterruptMode.EdgeBoth, ResistorMode.InternalPullUp); + var startPort = Mcp_2.CreateDigitalInterruptPort(Mcp_2.Pins.GP1, InterruptMode.EdgeBoth, ResistorMode.InternalPullUp); + var selectPort = Mcp_2.CreateDigitalInterruptPort(Mcp_2.Pins.GP0, InterruptMode.EdgeBoth, ResistorMode.InternalPullUp); + + Right_UpButton = new PushButton(upPort); + Right_RightButton = new PushButton(rightPort); + Right_DownButton = new PushButton(downPort); + Right_LeftButton = new PushButton(leftPort); + StartButton = new PushButton(startPort); + SelectButton = new PushButton(selectPort); + } + } + + internal DisplayConnector CreateDisplayConnector() + { + Resolver.Log.Trace("Creating display connector"); + + return new DisplayConnector( + "Display", + new PinMapping + { + new PinMapping.PinAlias(DisplayConnector.PinNames.CS, Mcp_1.Pins.GP5), + new PinMapping.PinAlias(DisplayConnector.PinNames.RST, Mcp_1.Pins.GP7), + new PinMapping.PinAlias(DisplayConnector.PinNames.DC, Mcp_1.Pins.GP6), + new PinMapping.PinAlias(DisplayConnector.PinNames.CLK, Device.Pins.SCK), + new PinMapping.PinAlias(DisplayConnector.PinNames.COPI, Device.Pins.COPI), + }); + } + + internal I2cConnector CreateQwiicConnector() + { + Resolver.Log.Trace("Creating Qwiic I2C connector"); + + return new I2cConnector( + "Qwiic", + new PinMapping + { + new PinMapping.PinAlias(I2cConnector.PinNames.SCL, Device.Pins.D08), + new PinMapping.PinAlias(I2cConnector.PinNames.SDA, Device.Pins.D07), + }, + new I2cBusMapping(Device, 1)); + } + } +} \ No newline at end of file diff --git a/Source/Juego_Demo/DisplayController.cs b/Source/Juego_Demo/DisplayController.cs index b7eccd1..2a32630 100644 --- a/Source/Juego_Demo/DisplayController.cs +++ b/Source/Juego_Demo/DisplayController.cs @@ -1,6 +1,6 @@ -using Meadow; -using Meadow.Foundation; +using Meadow.Foundation; using Meadow.Foundation.Graphics; +using Meadow.Units; namespace Juego_Demo { @@ -8,6 +8,17 @@ public class DisplayController { readonly MicroGraphics graphics; + public Acceleration3D? Acceleration3D + { + get => acceleration3D; + set + { + acceleration3D = value; + Update(); + } + } + Acceleration3D? acceleration3D = null; + public bool Right_UpButtonState { get => right_upButtonState; @@ -123,13 +134,11 @@ public bool SelectButtonState public DisplayController(IGraphicsDisplay display) { - Resolver.Log.Info("Display controller ctor"); - graphics = new MicroGraphics(display) { Rotation = RotationType._270Degrees, IgnoreOutOfBoundsPixels = true, - CurrentFont = new Font12x16() + CurrentFont = new Font12x20() }; graphics.Clear(Color.YellowGreen); @@ -161,35 +170,36 @@ public void Update() } } - void DrawStatus(string label, string value, Color color, int yPosition) - { - graphics.DrawText(x: 2, y: yPosition, label, color: color); - graphics.DrawText(x: 318, y: yPosition, value, alignmentH: HorizontalAlignment.Right, color: color); - } - void DrawDivider(Color color, int yPosition) - { - graphics.DrawLine(0, yPosition, graphics.Width, yPosition, color); - } void Draw() { - graphics.DrawText(x: 2, y: 0, "Hello Juego!", WildernessLabsColors.AzureBlue); - - DrawStatus("Up D-pad:", $"{(Left_UpButtonState ? "pressed" : "released")}", WildernessLabsColors.ChileanFire, 20); - DrawStatus("Down D-pad:", $"{(Left_DownButtonState ? "pressed" : "released")}", WildernessLabsColors.ChileanFire, 40); - DrawStatus("Left D-pad:", $"{(Left_LeftButtonState ? "pressed" : "released")}", WildernessLabsColors.ChileanFire, 60); - DrawStatus("Right D-pad:", $"{(Left_RightButtonState ? "pressed" : "released")}", WildernessLabsColors.ChileanFire, 80); - DrawDivider(WildernessLabsColors.AzureBlue, 98); - - DrawStatus("Up button:", $"{(Right_UpButtonState ? "pressed" : "released")}", WildernessLabsColors.ChileanFire, 100); - DrawStatus("Down button:", $"{(Right_DownButtonState ? "pressed" : "released")}", WildernessLabsColors.ChileanFire, 120); - DrawStatus("Left button:", $"{(Right_LeftButtonState ? "pressed" : "released")}", WildernessLabsColors.ChileanFire, 140); - DrawStatus("Right button:", $"{(Right_RightButtonState ? "pressed" : "released")}", WildernessLabsColors.ChileanFire, 160); - DrawDivider(WildernessLabsColors.AzureBlue, 178); - - DrawStatus("Select button:", $"{(SelectButtonState ? "pressed" : "released")}", WildernessLabsColors.ChileanFire, 180); - DrawStatus("Start button:", $"{(StartButtonState ? "pressed" : "released")}", WildernessLabsColors.ChileanFire, 200); + graphics.DrawText(x: graphics.Width / 2, y: 0, "Hello Juego!", WildernessLabsColors.AzureBlue, alignmentH: HorizontalAlignment.Center); + + //D-Pad + graphics.DrawRectangle(5, 100, 30, 30, WildernessLabsColors.DustyGray, Left_LeftButtonState); + graphics.DrawRectangle(65, 100, 30, 30, WildernessLabsColors.DustyGray, Left_RightButtonState); + graphics.DrawRectangle(35, 70, 30, 30, WildernessLabsColors.DustyGray, Left_UpButtonState); + graphics.DrawRectangle(35, 130, 30, 30, WildernessLabsColors.DustyGray, Left_DownButtonState); + graphics.DrawCircle(50, 115, 7, WildernessLabsColors.DustyGray, true); + + //Start and Select + graphics.DrawRoundedRectangle(graphics.Width / 2 - 35, 140, 30, 15, 4, WildernessLabsColors.ChileanFire, SelectButtonState); + graphics.DrawRoundedRectangle(graphics.Width / 2 + 5, 140, 30, 15, 4, WildernessLabsColors.ChileanFire, StartButtonState); + + //Buttons + graphics.DrawCircle(graphics.Width - 90, 115, 15, WildernessLabsColors.PearGreen, Right_LeftButtonState); + graphics.DrawCircle(graphics.Width - 20, 115, 15, WildernessLabsColors.PearGreen, Right_RightButtonState); + graphics.DrawCircle(graphics.Width - 55, 80, 15, WildernessLabsColors.PearGreen, Right_UpButtonState); + graphics.DrawCircle(graphics.Width - 55, 150, 15, WildernessLabsColors.PearGreen, Right_DownButtonState); + + //Motion + if (acceleration3D is { } accel) + { + graphics.DrawCircle(graphics.Width / 2, 200, 30, WildernessLabsColors.AzureBlue, false); + //radius is 30 .... new circle is 10 ... scale position via x & y + graphics.DrawCircle(graphics.Width / 2 + (int)(accel.X.Gravity * 20), 200 + (int)(accel.Y.Gravity * -20), 10, WildernessLabsColors.AzureBlue, true); + } } } } \ No newline at end of file diff --git a/Source/Juego_Demo/MeadowApp.cs b/Source/Juego_Demo/MeadowApp.cs index 782cdd5..65b5bd6 100644 --- a/Source/Juego_Demo/MeadowApp.cs +++ b/Source/Juego_Demo/MeadowApp.cs @@ -1,5 +1,6 @@ using Meadow; using Meadow.Devices; +using Meadow.Foundation.Audio; using Meadow.Units; using System; using System.Threading.Tasks; @@ -7,96 +8,110 @@ namespace Juego_Demo { - // Change F7FeatherV2 to F7FeatherV1 for V1.x boards public class MeadowApp : App { - private IJuegoHardware hardware; + private IJuegoHardware juego; private DisplayController displayController; + private MicroAudio audioLeft, audioRight; public override Task Initialize() { Resolver.Log.Info("Initialize"); - hardware = Juego.Create(); + juego = Juego.Create(); - if (hardware.Display is { } display) + if (juego.Display is { } display) { displayController = new DisplayController(display); } - if (hardware.Left_LeftButton is { } leftDpad) + //---- BMI270 Accel/IMU + if (juego.MotionSensor is { } bmi270) + { + Resolver.Log.Info("Found BMI270"); + bmi270.Updated += Bmi270Updated; + } + + if (juego.Left_LeftButton is { } leftDpad) { leftDpad.PressStarted += (s, e) => displayController.Left_LeftButtonState = true; leftDpad.PressEnded += (s, e) => displayController.Left_LeftButtonState = false; } - if (hardware.Left_RightButton is { } rightDpad) + if (juego.Left_RightButton is { } rightDpad) { rightDpad.PressStarted += (s, e) => displayController.Left_RightButtonState = true; rightDpad.PressEnded += (s, e) => displayController.Left_RightButtonState = false; } - if (hardware.Left_UpButton is { } upDpad) + if (juego.Left_UpButton is { } upDpad) { upDpad.PressStarted += (s, e) => displayController.Left_UpButtonState = true; upDpad.PressEnded += (s, e) => displayController.Left_UpButtonState = false; } - if (hardware.Left_DownButton is { } downDpad) + if (juego.Left_DownButton is { } downDpad) { downDpad.PressStarted += (s, e) => displayController.Left_DownButtonState = true; downDpad.PressEnded += (s, e) => displayController.Left_DownButtonState = false; } - if (hardware.Right_LeftButton is { } leftButton) + if (juego.Right_LeftButton is { } leftButton) { leftButton.PressStarted += (s, e) => displayController.Right_LeftButtonState = true; leftButton.PressEnded += (s, e) => displayController.Right_LeftButtonState = false; } - if (hardware.Right_RightButton is { } rightButton) + if (juego.Right_RightButton is { } rightButton) { rightButton.PressStarted += (s, e) => displayController.Right_RightButtonState = true; rightButton.PressEnded += (s, e) => displayController.Right_RightButtonState = false; } - if (hardware.Right_UpButton is { } upButton) + if (juego.Right_UpButton is { } upButton) { upButton.PressStarted += (s, e) => displayController.Right_UpButtonState = true; upButton.PressEnded += (s, e) => displayController.Right_UpButtonState = false; } - if (hardware.Right_DownButton is { } downButton) + if (juego.Right_DownButton is { } downButton) { downButton.PressStarted += (s, e) => displayController.Right_DownButtonState = true; downButton.PressEnded += (s, e) => displayController.Right_DownButtonState = false; } - if (hardware.SelectButton is { } selectButton) + if (juego.SelectButton is { } selectButton) { selectButton.PressStarted += (s, e) => displayController.SelectButtonState = true; selectButton.PressEnded += (s, e) => displayController.SelectButtonState = false; } - if (hardware.StartButton is { } startButton) + if (juego.StartButton is { } startButton) { startButton.PressStarted += (s, e) => displayController.StartButtonState = true; startButton.PressEnded += (s, e) => displayController.StartButtonState = false; } - return base.Initialize(); + audioLeft = new MicroAudio(juego.LeftSpeaker); + audioRight = new MicroAudio(juego.RightSpeaker); + + return Task.CompletedTask; } public async override Task Run() { Resolver.Log.Info("Run..."); - if (displayController != null) - { - displayController.Update(); - } + displayController?.Update(); + juego.MotionSensor?.StartUpdating(TimeSpan.FromMilliseconds(250)); - for (int i = 0; i < 5; i++) - { - Resolver.Log.Info("Playing tone"); - await hardware.LeftSpeaker.PlayTone(new Frequency(440), TimeSpan.FromMilliseconds(500)); - await hardware.RightSpeaker.PlayTone(new Frequency(540), TimeSpan.FromMilliseconds(500)); - } + await audioLeft.PlaySystemSound(SystemSoundEffect.PowerUp); + await audioRight.PlayGameSound(GameSoundEffect.LevelComplete); return; } + + private void Bmi270Updated(object sender, IChangeResult<(Acceleration3D? Acceleration3D, AngularVelocity3D? AngularVelocity3D, Temperature? Temperature)> e) + { + Resolver.Log.Info($"BMI270: X:{e.New.Acceleration3D.Value.X.Gravity:0.0}g, Y:{e.New.Acceleration3D.Value.Y.Gravity:0.0}g, Z:{e.New.Acceleration3D.Value.Z.Gravity:0.0}g"); + + if (displayController != null) + { + displayController.Acceleration3D = e.New.Acceleration3D; + } + } } } \ No newline at end of file