diff --git a/.github/workflows/develop-ci.yml b/.github/workflows/develop-ci.yml
index 857fa04..ba0cb20 100644
--- a/.github/workflows/develop-ci.yml
+++ b/.github/workflows/develop-ci.yml
@@ -71,7 +71,7 @@ jobs:
uses: actions/setup-dotnet@v1
with:
dotnet-version:
- 8.0.x
+ 9.0.200
- name: Build Meadow.ProjectLab
- run: dotnet build -c Release Meadow.ProjectLab/Source/Meadow.ProjectLab.sln
+ run: dotnet build -c Release Meadow.ProjectLab/Source/Meadow.ProjectLab.slnx
diff --git a/Source/Meadow.ProjectLab.sln b/Source/Meadow.ProjectLab.sln
deleted file mode 100644
index b052338..0000000
--- a/Source/Meadow.ProjectLab.sln
+++ /dev/null
@@ -1,218 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.3.32929.385
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Meadow.ProjectLab", "Meadow.ProjectLab\Meadow.ProjectLab.csproj", "{A263ECD8-AA98-4E1C-B404-EC360584362B}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProjectLab_Demo", "ProjectLab_Demo\ProjectLab_Demo.csproj", "{C9A1FF4C-7210-4EA6-874E-44BE198B2790}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_External", "_External", "{580CAC8F-38C5-4DEA-AAEA-415F5D08982B}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Meadow.Foundation.Core", "..\..\Meadow.Foundation\Source\Meadow.Foundation.Core\Meadow.Foundation.Core.csproj", "{37AAB07A-1F40-4660-97A5-D24890ED7F27}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Meadow.Contracts", "..\..\Meadow.Contracts\Source\Meadow.Contracts\Meadow.Contracts.csproj", "{5FA51D52-0F2C-460A-B0E7-3168A11A1CF0}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Displays.TftSpi", "..\..\Meadow.Foundation\Source\Meadow.Foundation.Peripherals\Displays.TftSpi\Driver\Displays.TftSpi.csproj", "{2ECCF2AC-44A7-436E-A832-E2A370C3317D}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICs.IOExpanders.Mcp23xxx", "..\..\Meadow.Foundation\Source\Meadow.Foundation.Peripherals\ICs.IOExpanders.Mcp23xxx\Driver\ICs.IOExpanders.Mcp23xxx.csproj", "{FD0FF1E2-C933-4CFD-84A3-6F4F72C7F048}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sensors.Atmospheric.Bme68x", "..\..\Meadow.Foundation\Source\Meadow.Foundation.Peripherals\Sensors.Atmospheric.Bme68x\Driver\Sensors.Atmospheric.Bme68x.csproj", "{F0217A3C-41FC-49A0-8481-64853464D5AB}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sensors.Light.Bh1750", "..\..\Meadow.Foundation\Source\Meadow.Foundation.Peripherals\Sensors.Light.Bh1750\Driver\Sensors.Light.Bh1750.csproj", "{CD675B1D-BC88-4DB5-AF45-8079435F52CA}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sensors.Motion.Bmi270", "..\..\Meadow.Foundation\Source\Meadow.Foundation.Peripherals\Sensors.Motion.Bmi270\Driver\Sensors.Motion.Bmi270.csproj", "{95770BEF-6864-493C-A8DA-660D3AC582A0}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Graphics.MicroGraphics", "..\..\Meadow.Foundation\Source\Meadow.Foundation.Libraries_and_Frameworks\Graphics.MicroGraphics\Driver\Graphics.MicroGraphics.csproj", "{DB4C8FC0-18A8-4735-933B-D1FCE59FC1E3}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Meadow.Modbus", "..\..\Meadow.Modbus\src\Meadow.Modbus\Meadow.Modbus.csproj", "{2D1FC26C-C80D-42E8-92BD-25BE517AC663}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Meadow.Core", "..\..\Meadow.Core\Source\Meadow.Core\Meadow.Core.csproj", "{18EE7297-3E8D-4B94-B6E3-319991927D58}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Meadow.Logging", "..\..\Meadow.Logging\Source\Meadow.Logging\lib\Meadow.Logging.csproj", "{E56BD47C-4997-4831-833C-EA35C83F89B7}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Meadow.Units", "..\..\Meadow.Units\Source\Meadow.Units\Meadow.Units.csproj", "{35B3DDB4-71EF-4A68-B242-982C71126F3E}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Meadow.F7", "..\..\Meadow.Core\Source\implementations\f7\Meadow.F7\Meadow.F7.csproj", "{EF2050F4-6422-4AB2-BF60-9E5428E474AF}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Audio.MicroAudio", "..\..\Meadow.Foundation\Source\Meadow.Foundation.Libraries_and_Frameworks\Audio.MicroAudio\Driver\Audio.MicroAudio.csproj", "{12C58A2F-9D0E-417F-B138-BA25B166C56B}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet", "..\..\MQTTnet\Source\MQTTnet\MQTTnet.csproj", "{B51B10FB-6577-4C06-B7B2-82D2ACCB31B2}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICs.IOExpanders.Sc16is7x2", "..\..\Meadow.Foundation\Source\Meadow.Foundation.Peripherals\ICs.IOExpanders.Sc16is7x2\Driver\ICs.IOExpanders.Sc16is7x2.csproj", "{20AFC6E4-46E9-4CBB-A8E2-69BF4CD2039C}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sensors.Hid.Xpt2046", "..\..\Meadow.Foundation\Source\Meadow.Foundation.Peripherals\Sensors.Hid.Xpt2046\Driver\Sensors.Hid.Xpt2046.csproj", "{6089ABC8-BCBB-4B81-BC6A-D6B4963E5BD2}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Graphics.MicroLayout", "..\..\Meadow.Foundation\Source\Meadow.Foundation.Libraries_and_Frameworks\Graphics.MicroLayout\Driver\Graphics.MicroLayout.csproj", "{04A557DE-8136-4AE9-88F0-159D4AB085B8}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serialization.MicroJson", "..\..\Meadow.Foundation\Source\Meadow.Foundation.Libraries_and_Frameworks\Serialization.MicroJson\Driver\Serialization.MicroJson.csproj", "{888F0CDA-2D29-49F2-AF31-898998B3D8F4}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICs.IOExpanders.Pca9685", "..\..\Meadow.Foundation\Source\Meadow.Foundation.Peripherals\ICs.IOExpanders.Pca9685\Driver\ICs.IOExpanders.Pca9685.csproj", "{2040BA52-DC2C-C963-CC0E-D0FE5DAACAF8}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sensors.Atmospheric.Ahtx0", "..\..\Meadow.Foundation\Source\Meadow.Foundation.Peripherals\Sensors.Atmospheric.Ahtx0\Driver\Sensors.Atmospheric.Ahtx0.csproj", "{DE9E4A5B-9DCE-14C0-16EA-9170EDB186A6}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {A263ECD8-AA98-4E1C-B404-EC360584362B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {A263ECD8-AA98-4E1C-B404-EC360584362B}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {A263ECD8-AA98-4E1C-B404-EC360584362B}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
- {A263ECD8-AA98-4E1C-B404-EC360584362B}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {A263ECD8-AA98-4E1C-B404-EC360584362B}.Release|Any CPU.Build.0 = Release|Any CPU
- {A263ECD8-AA98-4E1C-B404-EC360584362B}.Release|Any CPU.Deploy.0 = Release|Any CPU
- {C9A1FF4C-7210-4EA6-874E-44BE198B2790}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {C9A1FF4C-7210-4EA6-874E-44BE198B2790}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {C9A1FF4C-7210-4EA6-874E-44BE198B2790}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
- {C9A1FF4C-7210-4EA6-874E-44BE198B2790}.Release|Any CPU.ActiveCfg = Debug|Any CPU
- {C9A1FF4C-7210-4EA6-874E-44BE198B2790}.Release|Any CPU.Build.0 = Debug|Any CPU
- {C9A1FF4C-7210-4EA6-874E-44BE198B2790}.Release|Any CPU.Deploy.0 = Debug|Any CPU
- {37AAB07A-1F40-4660-97A5-D24890ED7F27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {37AAB07A-1F40-4660-97A5-D24890ED7F27}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {37AAB07A-1F40-4660-97A5-D24890ED7F27}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
- {37AAB07A-1F40-4660-97A5-D24890ED7F27}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {37AAB07A-1F40-4660-97A5-D24890ED7F27}.Release|Any CPU.Build.0 = Release|Any CPU
- {37AAB07A-1F40-4660-97A5-D24890ED7F27}.Release|Any CPU.Deploy.0 = Release|Any CPU
- {5FA51D52-0F2C-460A-B0E7-3168A11A1CF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {5FA51D52-0F2C-460A-B0E7-3168A11A1CF0}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {5FA51D52-0F2C-460A-B0E7-3168A11A1CF0}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
- {5FA51D52-0F2C-460A-B0E7-3168A11A1CF0}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {5FA51D52-0F2C-460A-B0E7-3168A11A1CF0}.Release|Any CPU.Build.0 = Release|Any CPU
- {5FA51D52-0F2C-460A-B0E7-3168A11A1CF0}.Release|Any CPU.Deploy.0 = Release|Any CPU
- {2ECCF2AC-44A7-436E-A832-E2A370C3317D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {2ECCF2AC-44A7-436E-A832-E2A370C3317D}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {2ECCF2AC-44A7-436E-A832-E2A370C3317D}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
- {2ECCF2AC-44A7-436E-A832-E2A370C3317D}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {2ECCF2AC-44A7-436E-A832-E2A370C3317D}.Release|Any CPU.Build.0 = Release|Any CPU
- {2ECCF2AC-44A7-436E-A832-E2A370C3317D}.Release|Any CPU.Deploy.0 = Release|Any CPU
- {FD0FF1E2-C933-4CFD-84A3-6F4F72C7F048}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {FD0FF1E2-C933-4CFD-84A3-6F4F72C7F048}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {FD0FF1E2-C933-4CFD-84A3-6F4F72C7F048}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
- {FD0FF1E2-C933-4CFD-84A3-6F4F72C7F048}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {FD0FF1E2-C933-4CFD-84A3-6F4F72C7F048}.Release|Any CPU.Build.0 = Release|Any CPU
- {FD0FF1E2-C933-4CFD-84A3-6F4F72C7F048}.Release|Any CPU.Deploy.0 = Release|Any CPU
- {F0217A3C-41FC-49A0-8481-64853464D5AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {F0217A3C-41FC-49A0-8481-64853464D5AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {F0217A3C-41FC-49A0-8481-64853464D5AB}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
- {F0217A3C-41FC-49A0-8481-64853464D5AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {F0217A3C-41FC-49A0-8481-64853464D5AB}.Release|Any CPU.Build.0 = Release|Any CPU
- {F0217A3C-41FC-49A0-8481-64853464D5AB}.Release|Any CPU.Deploy.0 = Release|Any CPU
- {CD675B1D-BC88-4DB5-AF45-8079435F52CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {CD675B1D-BC88-4DB5-AF45-8079435F52CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {CD675B1D-BC88-4DB5-AF45-8079435F52CA}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
- {CD675B1D-BC88-4DB5-AF45-8079435F52CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {CD675B1D-BC88-4DB5-AF45-8079435F52CA}.Release|Any CPU.Build.0 = Release|Any CPU
- {CD675B1D-BC88-4DB5-AF45-8079435F52CA}.Release|Any CPU.Deploy.0 = Release|Any CPU
- {95770BEF-6864-493C-A8DA-660D3AC582A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {95770BEF-6864-493C-A8DA-660D3AC582A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {95770BEF-6864-493C-A8DA-660D3AC582A0}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
- {95770BEF-6864-493C-A8DA-660D3AC582A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {95770BEF-6864-493C-A8DA-660D3AC582A0}.Release|Any CPU.Build.0 = Release|Any CPU
- {95770BEF-6864-493C-A8DA-660D3AC582A0}.Release|Any CPU.Deploy.0 = Release|Any CPU
- {DB4C8FC0-18A8-4735-933B-D1FCE59FC1E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {DB4C8FC0-18A8-4735-933B-D1FCE59FC1E3}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {DB4C8FC0-18A8-4735-933B-D1FCE59FC1E3}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
- {DB4C8FC0-18A8-4735-933B-D1FCE59FC1E3}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {DB4C8FC0-18A8-4735-933B-D1FCE59FC1E3}.Release|Any CPU.Build.0 = Release|Any CPU
- {DB4C8FC0-18A8-4735-933B-D1FCE59FC1E3}.Release|Any CPU.Deploy.0 = Release|Any CPU
- {2D1FC26C-C80D-42E8-92BD-25BE517AC663}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {2D1FC26C-C80D-42E8-92BD-25BE517AC663}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {2D1FC26C-C80D-42E8-92BD-25BE517AC663}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {2D1FC26C-C80D-42E8-92BD-25BE517AC663}.Release|Any CPU.Build.0 = Release|Any CPU
- {18EE7297-3E8D-4B94-B6E3-319991927D58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {18EE7297-3E8D-4B94-B6E3-319991927D58}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {18EE7297-3E8D-4B94-B6E3-319991927D58}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
- {18EE7297-3E8D-4B94-B6E3-319991927D58}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {18EE7297-3E8D-4B94-B6E3-319991927D58}.Release|Any CPU.Build.0 = Release|Any CPU
- {18EE7297-3E8D-4B94-B6E3-319991927D58}.Release|Any CPU.Deploy.0 = Release|Any CPU
- {E56BD47C-4997-4831-833C-EA35C83F89B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {E56BD47C-4997-4831-833C-EA35C83F89B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {E56BD47C-4997-4831-833C-EA35C83F89B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {E56BD47C-4997-4831-833C-EA35C83F89B7}.Release|Any CPU.Build.0 = Release|Any CPU
- {35B3DDB4-71EF-4A68-B242-982C71126F3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {35B3DDB4-71EF-4A68-B242-982C71126F3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {35B3DDB4-71EF-4A68-B242-982C71126F3E}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
- {35B3DDB4-71EF-4A68-B242-982C71126F3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {35B3DDB4-71EF-4A68-B242-982C71126F3E}.Release|Any CPU.Build.0 = Release|Any CPU
- {35B3DDB4-71EF-4A68-B242-982C71126F3E}.Release|Any CPU.Deploy.0 = Release|Any CPU
- {EF2050F4-6422-4AB2-BF60-9E5428E474AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {EF2050F4-6422-4AB2-BF60-9E5428E474AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {EF2050F4-6422-4AB2-BF60-9E5428E474AF}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
- {EF2050F4-6422-4AB2-BF60-9E5428E474AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {EF2050F4-6422-4AB2-BF60-9E5428E474AF}.Release|Any CPU.Build.0 = Release|Any CPU
- {EF2050F4-6422-4AB2-BF60-9E5428E474AF}.Release|Any CPU.Deploy.0 = Release|Any CPU
- {12C58A2F-9D0E-417F-B138-BA25B166C56B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {12C58A2F-9D0E-417F-B138-BA25B166C56B}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {12C58A2F-9D0E-417F-B138-BA25B166C56B}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
- {12C58A2F-9D0E-417F-B138-BA25B166C56B}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {12C58A2F-9D0E-417F-B138-BA25B166C56B}.Release|Any CPU.Build.0 = Release|Any CPU
- {12C58A2F-9D0E-417F-B138-BA25B166C56B}.Release|Any CPU.Deploy.0 = Release|Any CPU
- {B51B10FB-6577-4C06-B7B2-82D2ACCB31B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {B51B10FB-6577-4C06-B7B2-82D2ACCB31B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {B51B10FB-6577-4C06-B7B2-82D2ACCB31B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {B51B10FB-6577-4C06-B7B2-82D2ACCB31B2}.Release|Any CPU.Build.0 = Release|Any CPU
- {20AFC6E4-46E9-4CBB-A8E2-69BF4CD2039C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {20AFC6E4-46E9-4CBB-A8E2-69BF4CD2039C}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {20AFC6E4-46E9-4CBB-A8E2-69BF4CD2039C}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
- {20AFC6E4-46E9-4CBB-A8E2-69BF4CD2039C}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {20AFC6E4-46E9-4CBB-A8E2-69BF4CD2039C}.Release|Any CPU.Build.0 = Release|Any CPU
- {20AFC6E4-46E9-4CBB-A8E2-69BF4CD2039C}.Release|Any CPU.Deploy.0 = Release|Any CPU
- {6089ABC8-BCBB-4B81-BC6A-D6B4963E5BD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {6089ABC8-BCBB-4B81-BC6A-D6B4963E5BD2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {6089ABC8-BCBB-4B81-BC6A-D6B4963E5BD2}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
- {6089ABC8-BCBB-4B81-BC6A-D6B4963E5BD2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {6089ABC8-BCBB-4B81-BC6A-D6B4963E5BD2}.Release|Any CPU.Build.0 = Release|Any CPU
- {6089ABC8-BCBB-4B81-BC6A-D6B4963E5BD2}.Release|Any CPU.Deploy.0 = Release|Any CPU
- {04A557DE-8136-4AE9-88F0-159D4AB085B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {04A557DE-8136-4AE9-88F0-159D4AB085B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {04A557DE-8136-4AE9-88F0-159D4AB085B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {04A557DE-8136-4AE9-88F0-159D4AB085B8}.Release|Any CPU.Build.0 = Release|Any CPU
- {888F0CDA-2D29-49F2-AF31-898998B3D8F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {888F0CDA-2D29-49F2-AF31-898998B3D8F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {888F0CDA-2D29-49F2-AF31-898998B3D8F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {888F0CDA-2D29-49F2-AF31-898998B3D8F4}.Release|Any CPU.Build.0 = Release|Any CPU
- {2040BA52-DC2C-C963-CC0E-D0FE5DAACAF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {2040BA52-DC2C-C963-CC0E-D0FE5DAACAF8}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {2040BA52-DC2C-C963-CC0E-D0FE5DAACAF8}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
- {2040BA52-DC2C-C963-CC0E-D0FE5DAACAF8}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {2040BA52-DC2C-C963-CC0E-D0FE5DAACAF8}.Release|Any CPU.Build.0 = Release|Any CPU
- {2040BA52-DC2C-C963-CC0E-D0FE5DAACAF8}.Release|Any CPU.Deploy.0 = Release|Any CPU
- {DE9E4A5B-9DCE-14C0-16EA-9170EDB186A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {DE9E4A5B-9DCE-14C0-16EA-9170EDB186A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {DE9E4A5B-9DCE-14C0-16EA-9170EDB186A6}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
- {DE9E4A5B-9DCE-14C0-16EA-9170EDB186A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {DE9E4A5B-9DCE-14C0-16EA-9170EDB186A6}.Release|Any CPU.Build.0 = Release|Any CPU
- {DE9E4A5B-9DCE-14C0-16EA-9170EDB186A6}.Release|Any CPU.Deploy.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(NestedProjects) = preSolution
- {37AAB07A-1F40-4660-97A5-D24890ED7F27} = {580CAC8F-38C5-4DEA-AAEA-415F5D08982B}
- {5FA51D52-0F2C-460A-B0E7-3168A11A1CF0} = {580CAC8F-38C5-4DEA-AAEA-415F5D08982B}
- {2ECCF2AC-44A7-436E-A832-E2A370C3317D} = {580CAC8F-38C5-4DEA-AAEA-415F5D08982B}
- {FD0FF1E2-C933-4CFD-84A3-6F4F72C7F048} = {580CAC8F-38C5-4DEA-AAEA-415F5D08982B}
- {F0217A3C-41FC-49A0-8481-64853464D5AB} = {580CAC8F-38C5-4DEA-AAEA-415F5D08982B}
- {CD675B1D-BC88-4DB5-AF45-8079435F52CA} = {580CAC8F-38C5-4DEA-AAEA-415F5D08982B}
- {95770BEF-6864-493C-A8DA-660D3AC582A0} = {580CAC8F-38C5-4DEA-AAEA-415F5D08982B}
- {DB4C8FC0-18A8-4735-933B-D1FCE59FC1E3} = {580CAC8F-38C5-4DEA-AAEA-415F5D08982B}
- {2D1FC26C-C80D-42E8-92BD-25BE517AC663} = {580CAC8F-38C5-4DEA-AAEA-415F5D08982B}
- {18EE7297-3E8D-4B94-B6E3-319991927D58} = {580CAC8F-38C5-4DEA-AAEA-415F5D08982B}
- {E56BD47C-4997-4831-833C-EA35C83F89B7} = {580CAC8F-38C5-4DEA-AAEA-415F5D08982B}
- {35B3DDB4-71EF-4A68-B242-982C71126F3E} = {580CAC8F-38C5-4DEA-AAEA-415F5D08982B}
- {EF2050F4-6422-4AB2-BF60-9E5428E474AF} = {580CAC8F-38C5-4DEA-AAEA-415F5D08982B}
- {12C58A2F-9D0E-417F-B138-BA25B166C56B} = {580CAC8F-38C5-4DEA-AAEA-415F5D08982B}
- {B51B10FB-6577-4C06-B7B2-82D2ACCB31B2} = {580CAC8F-38C5-4DEA-AAEA-415F5D08982B}
- {20AFC6E4-46E9-4CBB-A8E2-69BF4CD2039C} = {580CAC8F-38C5-4DEA-AAEA-415F5D08982B}
- {6089ABC8-BCBB-4B81-BC6A-D6B4963E5BD2} = {580CAC8F-38C5-4DEA-AAEA-415F5D08982B}
- {04A557DE-8136-4AE9-88F0-159D4AB085B8} = {580CAC8F-38C5-4DEA-AAEA-415F5D08982B}
- {888F0CDA-2D29-49F2-AF31-898998B3D8F4} = {580CAC8F-38C5-4DEA-AAEA-415F5D08982B}
- {2040BA52-DC2C-C963-CC0E-D0FE5DAACAF8} = {580CAC8F-38C5-4DEA-AAEA-415F5D08982B}
- {DE9E4A5B-9DCE-14C0-16EA-9170EDB186A6} = {580CAC8F-38C5-4DEA-AAEA-415F5D08982B}
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {C1A24E3C-F7F9-4EB3-8A7F-5C6AB7C2A43D}
- EndGlobalSection
-EndGlobal
diff --git a/Source/Meadow.ProjectLab.slnx b/Source/Meadow.ProjectLab.slnx
new file mode 100644
index 0000000..e8d82b3
--- /dev/null
+++ b/Source/Meadow.ProjectLab.slnx
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Source/Meadow.ProjectLab/ConnectorProviderV3.cs b/Source/Meadow.ProjectLab/ConnectorProviderV3.cs
index 6e7b8f6..3bc39f0 100644
--- a/Source/Meadow.ProjectLab/ConnectorProviderV3.cs
+++ b/Source/Meadow.ProjectLab/ConnectorProviderV3.cs
@@ -7,9 +7,17 @@ namespace Meadow.Devices;
internal class ConnectorProviderV3 : IConnectorProvider
{
+ private ProjectLabRs485Connector? _rs485Connector;
+
public Rs485Connector GetRs485UartConnector(ProjectLabHardwareBase projLab)
{
- throw new PlatformNotSupportedException("RS485 is not supported on hardware revisions before 3.e");
+ if (_rs485Connector == null)
+ {
+ // create it with no parameters - it will throw only if a client tries to actually use it
+ _rs485Connector = new ProjectLabRs485Connector();
+ }
+
+ return _rs485Connector;
}
public ModbusRtuClient GetModbusRtuClient(ProjectLabHardwareBase projLab, int baudRate = 19200, int dataBits = 8, Parity parity = Parity.None, StopBits stopBits = StopBits.One)
diff --git a/Source/Meadow.ProjectLab/ConnectorProviderV3e.cs b/Source/Meadow.ProjectLab/ConnectorProviderV3e.cs
index ea0ca6e..beeb4bc 100644
--- a/Source/Meadow.ProjectLab/ConnectorProviderV3e.cs
+++ b/Source/Meadow.ProjectLab/ConnectorProviderV3e.cs
@@ -22,20 +22,22 @@ public ConnectorProviderV3e(ProjectLabHardwareBase projLab, II2cBus i2CBus)
}
catch (Exception ex)
{
- Resolver.Log.Error($"Unable to connect to UART expander: {ex.Message}", Constants.LogGroup);
+ Resolver.Log.Warn($"Unable to connect to UART expander: {ex.Message}", Constants.LogGroup);
}
}
public Rs485Connector GetRs485UartConnector(ProjectLabHardwareBase projLab)
{
if (Resolver.Device is not F7CoreComputeV2) throw new NotSupportedException();
- if (_uartExpander == null)
- {
- throw new NotSupportedException("No UART expander detected");
- }
lock (_rs485SyncRoot)
{
+ if (_uartExpander == null)
+ {
+ // create it with no parameters - it will throw only if a client tries to actually use it
+ _rs485Connector = new ProjectLabRs485Connector();
+ }
+
if (_rs485Connector == null)
{
_rs485Connector = new ProjectLabRs485Connector(_uartExpander, _uartExpander.PortB);
diff --git a/Source/Meadow.ProjectLab/ProjectLab.cs b/Source/Meadow.ProjectLab/ProjectLab.cs
index 8b86836..eb06f91 100644
--- a/Source/Meadow.ProjectLab/ProjectLab.cs
+++ b/Source/Meadow.ProjectLab/ProjectLab.cs
@@ -13,18 +13,41 @@ public abstract class ProjectLabFeatherApp : App
-/// A base class for F7 Core Compute-based, Project Lab-targeted applications
+/// A base class for F7 Core Compute (v4 and earlier)-based, Project Lab-targeted applications
///
public abstract class ProjectLabCoreComputeApp : App
{
}
+///
+/// A base class for F7 Core Compute (v5)-based, Project Lab-targeted applications
+///
+public abstract class ProjectLabV5App : App
+{
+}
+
+///
+/// Represents Project Lab hardware and exposes its peripherals
+///
+public class ProjectLabV5 : ProjectLab
+{
+ protected override IPin GetMcpResetPin(IF7CoreComputeMeadowDevice ccm)
+ {
+ return ccm.Pins.PH10;
+ }
+}
+
///
/// Represents Project Lab hardware and exposes its peripherals
///
public class ProjectLab : IMeadowAppEmbeddedHardwareProvider
{
- private ProjectLab() { }
+ protected ProjectLab() { }
+
+ protected virtual IPin GetMcpResetPin(IF7CoreComputeMeadowDevice ccm)
+ {
+ return ccm.Pins.PB4; // this is where it is on the 4.e
+ }
///
/// Create an instance of the ProjectLab class
@@ -72,6 +95,7 @@ public IProjectLabHardware Create(IMeadowDevice device)
mcpInterrupt = device.CreateDigitalInterruptPort(f.Pins.D09, InterruptMode.EdgeRising, ResistorMode.InternalPullDown);
mcpReset = device.CreateDigitalOutputPort(f.Pins.D14);
+ logger?.Info("creating Mcp_1 at 0x20");
mcp = new Mcp23008(i2cBus, address: 0x20, mcpInterrupt, mcpReset);
logger?.Trace("Mcp_1 up");
@@ -87,7 +111,9 @@ public IProjectLabHardware Create(IMeadowDevice device)
{
try
{
- mcpReset = device.CreateDigitalOutputPort(c.Pins.PA10);
+ var reset = GetMcpResetPin(c);
+ Resolver.Log.Info($"Using MCP reset pin {reset.Name}");
+ mcpReset = device.CreateDigitalOutputPort(reset);
mcp = new Mcp23008(i2cBus, address: 0x27, resetPort: mcpReset);
diff --git a/Source/Meadow.ProjectLab/ProjectLabHardwareV3.cs b/Source/Meadow.ProjectLab/ProjectLabHardwareV3.cs
index 91ed990..8bf6417 100644
--- a/Source/Meadow.ProjectLab/ProjectLabHardwareV3.cs
+++ b/Source/Meadow.ProjectLab/ProjectLabHardwareV3.cs
@@ -133,12 +133,12 @@ internal ProjectLabHardwareV3(IF7CoreComputeMeadowDevice device, II2cBus i2cBus)
if (RevisionNumber < 15) // before 3.e
{
- Logger?.Trace("Hardware is 3.d or earlier");
+ Logger?.Trace($"HW Revision: {RevisionNumber} Hardware is 3.d or earlier");
_connectors = new ConnectorProviderV3();
}
else
{
- Logger?.Trace("Hardware is 3.e or later");
+ Logger?.Trace($"HW Revision: {RevisionNumber} Hardware is 3.e or later");
_connectors = new ConnectorProviderV3e(this, i2cBus);
}
}
diff --git a/Source/Meadow.ProjectLab/ProjectLabHardwareV5.cs b/Source/Meadow.ProjectLab/ProjectLabHardwareV5.cs
index 666e643..2c4f4ce 100644
--- a/Source/Meadow.ProjectLab/ProjectLabHardwareV5.cs
+++ b/Source/Meadow.ProjectLab/ProjectLabHardwareV5.cs
@@ -397,9 +397,9 @@ internal override DisplayConnector CreateDisplayConnector()
nameof(Display),
new PinMapping
{
- new PinMapping.PinAlias(DisplayConnector.PinNames.DISPLAY_CS, _device.Pins.PB15),
+ new PinMapping.PinAlias(DisplayConnector.PinNames.DISPLAY_CS, _device.Pins.PB4),
new PinMapping.PinAlias(DisplayConnector.PinNames.DISPLAY_RST, _device.Pins.PB8),
- new PinMapping.PinAlias(DisplayConnector.PinNames.DISPLAY_DC, _device.Pins.PB14),
+ new PinMapping.PinAlias(DisplayConnector.PinNames.DISPLAY_DC, _device.Pins.PI11),
new PinMapping.PinAlias(DisplayConnector.PinNames.DISPLAY_CLK, _device.Pins.SPI5_SCK),
new PinMapping.PinAlias(DisplayConnector.PinNames.DISPLAY_COPI, _device.Pins.SPI5_COPI),
new PinMapping.PinAlias(DisplayConnector.PinNames.DISPLAY_LED, Mcp_1.Pins.GP5),
diff --git a/Source/Meadow.ProjectLab/ProjectLabRs485Connector.cs b/Source/Meadow.ProjectLab/ProjectLabRs485Connector.cs
index ef2ff75..030b9e6 100644
--- a/Source/Meadow.ProjectLab/ProjectLabRs485Connector.cs
+++ b/Source/Meadow.ProjectLab/ProjectLabRs485Connector.cs
@@ -7,11 +7,17 @@ namespace Meadow.Devices;
public class ProjectLabRs485Connector : Rs485Connector
{
- private readonly Sc16is752 _expander;
+ private readonly Sc16is752? _expander;
private ISerialPort? _serialPort;
private ModbusRtuClient? _modbusClient;
private ModbusRtuServer? _modbusServer;
+ internal ProjectLabRs485Connector()
+ : base("Unsupported hardware", new SerialPortName("null", "null", null))
+ {
+
+ }
+
internal ProjectLabRs485Connector(Sc16is752 expander, SerialPortName portName)
: base("RS485", portName)
{
@@ -23,6 +29,12 @@ internal ProjectLabRs485Connector(Sc16is752 expander, SerialPortName portName)
///
public override ISerialPort CreateSerialPort(int baudRate = 9600, int dataBits = 8, Parity parity = Parity.None, StopBits stopBits = StopBits.One, int readBufferSize = 1024)
{
+ if (_expander == null)
+ {
+ throw new NotSupportedException("No UART expander detected");
+ }
+
+ Resolver.Log.Info("Creating RS485 serial port...");
_serialPort = _expander.PortB.CreateRs485SerialPort(baudRate, dataBits, parity, stopBits);
return _serialPort;
}
@@ -30,6 +42,11 @@ public override ISerialPort CreateSerialPort(int baudRate = 9600, int dataBits =
///
public override IModbusBusClient CreateModbusBusRtuClient(int baudRate = 19200, int dataBits = 8, Parity parity = Parity.None, StopBits stopBits = StopBits.One)
{
+ if (_expander == null)
+ {
+ throw new NotSupportedException("No UART expander detected");
+ }
+
Resolver.Log.Info("Creating Modbus RTU client...");
lock (_expander)
{
@@ -55,6 +72,11 @@ public override IModbusBusClient CreateModbusBusRtuClient(int baudRate = 19200,
///
public override IModbusServer CreateModbusBusRtuServer(int baudRate = 19200, int dataBits = 8, Parity parity = Parity.None, StopBits stopBits = StopBits.One)
{
+ if (_expander == null)
+ {
+ throw new NotSupportedException("No UART expander detected");
+ }
+
Resolver.Log.Info("Creating Modbus RTU server...");
lock (_expander)
{
diff --git a/Source/ProjectLab_Demo/MeadowApp.cs b/Source/ProjectLab_Demo/MeadowApp.cs
index 3ab8b9c..37eb9b1 100644
--- a/Source/ProjectLab_Demo/MeadowApp.cs
+++ b/Source/ProjectLab_Demo/MeadowApp.cs
@@ -10,7 +10,8 @@ namespace ProjectLab_Demo;
// Change to ProjectLabFeatherApp for Project Lab V1 or V2
// Change to ProjectLabCoreComputeApp for Project Lab V3+
-public class MeadowApp : ProjectLabCoreComputeApp
+// public class MeadowApp : ProjectLabCoreComputeApp // <-- this is for V3/v4
+public class MeadowApp : ProjectLabV5App // this is for v5+
{
private DisplayController? displayController;