├── .gitattributes ├── .gitignore ├── .vs └── config │ └── applicationhost.config ├── Examples ├── Assets │ ├── LockScreenLogo.scale-200.png │ ├── SplashScreen.scale-200.png │ ├── Square150x150Logo.scale-200.png │ ├── Square44x44Logo.scale-200.png │ ├── Square44x44Logo.targetsize-24_altform-unplated.png │ ├── StoreLogo.png │ └── Wide310x150Logo.scale-200.png ├── LED Matrix Adavnced Examples.csproj ├── LED Matrix Adavnced Examples_TemporaryKey.pfx ├── LedBiColourMatrix.cs ├── LedMonoMatrix.cs ├── LedMonoMatrixSPI.cs ├── LedMonoPanelSPI.cs ├── Package.appxmanifest ├── Properties │ ├── AssemblyInfo.cs │ └── Default.rd.xml ├── StartupTask.cs └── project.json ├── Glovebox.Graphics Library.sln ├── Glovebox.Graphics ├── Components │ ├── LED8x8Matrix.cs │ └── SevenSegmentDisplay.cs ├── Drivers │ ├── Ht16K33.cs │ ├── Ht16K33BiColor.cs │ ├── ILedDriver.cs │ ├── LedDriver.cs │ └── MAX7219.cs ├── FrameBase.cs ├── Glovebox.Graphics.csproj ├── Grid │ ├── Grid8x8.cs │ └── GridBase.cs ├── Nuget │ ├── CreateNugetPackage.bat │ └── Glovebox.Graphics.dll.nuspec ├── Pixel.cs ├── Properties │ ├── AssemblyInfo.cs │ └── LightLibrary.rd.xml ├── SevenSegmentDisplay │ └── SevenSegmentDisplayBase.cs ├── Util.cs └── project.json ├── HelloWorld ├── Assets │ ├── LockScreenLogo.scale-200.png │ ├── SplashScreen.scale-200.png │ ├── Square150x150Logo.scale-200.png │ ├── Square44x44Logo.scale-200.png │ ├── Square44x44Logo.targetsize-24_altform-unplated.png │ ├── StoreLogo.png │ └── Wide310x150Logo.scale-200.png ├── LED Matrix HelloWorld Sample.csproj ├── LED Matrix HelloWorld Sample_TemporaryKey.pfx ├── Package.appxmanifest ├── Properties │ ├── AssemblyInfo.cs │ └── Default.rd.xml ├── StartupTask.cs └── project.json ├── README.md └── Seven Segment Display Sample ├── Assets ├── LockScreenLogo.scale-200.png ├── SplashScreen.scale-200.png ├── Square150x150Logo.scale-200.png ├── Square44x44Logo.scale-200.png ├── Square44x44Logo.targetsize-24_altform-unplated.png ├── StoreLogo.png └── Wide310x150Logo.scale-200.png ├── Package.appxmanifest ├── Properties ├── AssemblyInfo.cs └── Default.rd.xml ├── Seven Segment Display Sample.csproj ├── Seven Segment Display Sample_TemporaryKey.pfx ├── StartupTask.cs └── project.json /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | #*.suo 6 | #*.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | build/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | 26 | # MSTest test Results 27 | [Tt]est[Rr]esult*/ 28 | [Bb]uild[Ll]og.* 29 | 30 | # NUNIT 31 | *.VisualState.xml 32 | TestResult.xml 33 | 34 | # Build Results of an ATL Project 35 | [Dd]ebugPS/ 36 | [Rr]eleasePS/ 37 | dlldata.c 38 | 39 | # DNX 40 | #project.lock.json 41 | artifacts/ 42 | 43 | *_i.c 44 | *_p.c 45 | *_i.h 46 | *.ilk 47 | *.meta 48 | *.obj 49 | *.pch 50 | *.pdb 51 | *.pgc 52 | *.pgd 53 | *.rsp 54 | *.sbr 55 | *.tlb 56 | *.tli 57 | *.tlh 58 | *.tmp 59 | *.tmp_proj 60 | *.log 61 | *.vspscc 62 | *.vssscc 63 | .builds 64 | *.pidb 65 | *.svclog 66 | *.scc 67 | 68 | # Chutzpah Test files 69 | _Chutzpah* 70 | 71 | # Visual C++ cache files 72 | ipch/ 73 | *.aps 74 | *.ncb 75 | *.opensdf 76 | *.sdf 77 | *.cachefile 78 | 79 | # Visual Studio profiler 80 | *.psess 81 | *.vsp 82 | *.vspx 83 | 84 | # TFS 2012 Local Workspace 85 | $tf/ 86 | 87 | # Guidance Automation Toolkit 88 | *.gpState 89 | 90 | # ReSharper is a .NET coding add-in 91 | _ReSharper*/ 92 | *.[Rr]e[Ss]harper 93 | *.DotSettings.user 94 | 95 | # JustCode is a .NET coding add-in 96 | .JustCode 97 | 98 | # TeamCity is a build add-in 99 | _TeamCity* 100 | 101 | # DotCover is a Code Coverage Tool 102 | *.dotCover 103 | 104 | # NCrunch 105 | _NCrunch_* 106 | .*crunch*.local.xml 107 | 108 | # MightyMoose 109 | *.mm.* 110 | AutoTest.Net/ 111 | 112 | # Web workbench (sass) 113 | .sass-cache/ 114 | 115 | # Installshield output folder 116 | [Ee]xpress/ 117 | 118 | # DocProject is a documentation generator add-in 119 | DocProject/buildhelp/ 120 | DocProject/Help/*.HxT 121 | DocProject/Help/*.HxC 122 | DocProject/Help/*.hhc 123 | DocProject/Help/*.hhk 124 | DocProject/Help/*.hhp 125 | DocProject/Help/Html2 126 | DocProject/Help/html 127 | 128 | # Click-Once directory 129 | publish/ 130 | 131 | # Publish Web Output 132 | *.[Pp]ublish.xml 133 | *.azurePubxml 134 | ## TODO: Comment the next line if you want to checkin your 135 | ## web deploy settings but do note that will include unencrypted 136 | ## passwords 137 | #*.pubxml 138 | 139 | *.publishproj 140 | 141 | # NuGet Packages 142 | *.nupkg 143 | # The packages folder can be ignored because of Package Restore 144 | **/packages/* 145 | # except build/, which is used as an MSBuild target. 146 | !**/packages/build/ 147 | # Uncomment if necessary however generally it will be regenerated when needed 148 | #!**/packages/repositories.config 149 | 150 | # Windows Azure Build Output 151 | csx/ 152 | *.build.csdef 153 | 154 | # Windows Store app package directory 155 | AppPackages/ 156 | 157 | # Visual Studio cache files 158 | # files ending in .cache can be ignored 159 | *.[Cc]ache 160 | # but keep track of directories ending in .cache 161 | !*.[Cc]ache/ 162 | 163 | # Others 164 | ClientBin/ 165 | [Ss]tyle[Cc]op.* 166 | ~$* 167 | *~ 168 | *.dbmdl 169 | *.dbproj.schemaview 170 | #*.pfx 171 | *.publishsettings 172 | node_modules/ 173 | orleans.codegen.cs 174 | 175 | # RIA/Silverlight projects 176 | Generated_Code/ 177 | 178 | # Backup & report files from converting an old project file 179 | # to a newer Visual Studio version. Backup files are not needed, 180 | # because we have git ;-) 181 | _UpgradeReport_Files/ 182 | Backup*/ 183 | UpgradeLog*.XML 184 | UpgradeLog*.htm 185 | 186 | # SQL Server files 187 | *.mdf 188 | *.ldf 189 | 190 | # Business Intelligence projects 191 | *.rdl.data 192 | *.bim.layout 193 | *.bim_*.settings 194 | 195 | # Microsoft Fakes 196 | FakesAssemblies/ 197 | 198 | # Node.js Tools for Visual Studio 199 | .ntvs_analysis.dat 200 | 201 | # Visual Studio 6 build log 202 | *.plg 203 | 204 | # Visual Studio 6 workspace options file 205 | *.opt 206 | 207 | # LightSwitch generated files 208 | GeneratedArtifacts/ 209 | _Pvt_Extensions/ 210 | ModelManifest.xml 211 | -------------------------------------------------------------------------------- /Examples/Assets/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloveboxes/Windows-IoT-Core-Graphics-Library/5ca0d0a85950fdb729678b82eb7518bde7ef7c54/Examples/Assets/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /Examples/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloveboxes/Windows-IoT-Core-Graphics-Library/5ca0d0a85950fdb729678b82eb7518bde7ef7c54/Examples/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /Examples/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloveboxes/Windows-IoT-Core-Graphics-Library/5ca0d0a85950fdb729678b82eb7518bde7ef7c54/Examples/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /Examples/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloveboxes/Windows-IoT-Core-Graphics-Library/5ca0d0a85950fdb729678b82eb7518bde7ef7c54/Examples/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /Examples/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloveboxes/Windows-IoT-Core-Graphics-Library/5ca0d0a85950fdb729678b82eb7518bde7ef7c54/Examples/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /Examples/Assets/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloveboxes/Windows-IoT-Core-Graphics-Library/5ca0d0a85950fdb729678b82eb7518bde7ef7c54/Examples/Assets/StoreLogo.png -------------------------------------------------------------------------------- /Examples/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloveboxes/Windows-IoT-Core-Graphics-Library/5ca0d0a85950fdb729678b82eb7518bde7ef7c54/Examples/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /Examples/LED Matrix Adavnced Examples.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x86 7 | {872E4D7B-1D1B-4D5B-A36E-5A98108A489F} 8 | winmdobj 9 | Properties 10 | LedHost 11 | LedHost 12 | en-US 13 | UAP 14 | 10.0.10240.0 15 | 10.0.10240.0 16 | 14 17 | true 18 | 512 19 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 20 | false 21 | LED Matrix Adavnced Examples_TemporaryKey.pfx 22 | true 23 | true 24 | 30CC407B4CBAF7CA736D95FC5273C72D38342805 25 | 26 | 27 | true 28 | bin\ARM\Debug\ 29 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 30 | ;2008 31 | full 32 | ARM 33 | false 34 | prompt 35 | true 36 | 37 | 38 | bin\ARM\Release\ 39 | TRACE;NETFX_CORE;WINDOWS_UWP 40 | true 41 | ;2008 42 | pdbonly 43 | ARM 44 | false 45 | prompt 46 | true 47 | true 48 | 49 | 50 | true 51 | bin\x64\Debug\ 52 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 53 | ;2008 54 | full 55 | x64 56 | false 57 | prompt 58 | true 59 | 60 | 61 | bin\x64\Release\ 62 | TRACE;NETFX_CORE;WINDOWS_UWP 63 | true 64 | ;2008 65 | pdbonly 66 | x64 67 | false 68 | prompt 69 | true 70 | true 71 | 72 | 73 | true 74 | bin\x86\Debug\ 75 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 76 | ;2008 77 | full 78 | x86 79 | false 80 | prompt 81 | true 82 | 83 | 84 | bin\x86\Release\ 85 | TRACE;NETFX_CORE;WINDOWS_UWP 86 | true 87 | ;2008 88 | pdbonly 89 | x86 90 | false 91 | prompt 92 | true 93 | true 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | Designer 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | {6b7bcbab-4c1a-4e90-9f9b-31b233f90370} 126 | Glovebox.Graphics 127 | 128 | 129 | 130 | 14.0 131 | 132 | 133 | 140 | -------------------------------------------------------------------------------- /Examples/LED Matrix Adavnced Examples_TemporaryKey.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloveboxes/Windows-IoT-Core-Graphics-Library/5ca0d0a85950fdb729678b82eb7518bde7ef7c54/Examples/LED Matrix Adavnced Examples_TemporaryKey.pfx -------------------------------------------------------------------------------- /Examples/LedBiColourMatrix.cs: -------------------------------------------------------------------------------- 1 | using Glovebox.Graphics; 2 | using Glovebox.Graphics.Components; 3 | using Glovebox.Graphics.Drivers; 4 | using Glovebox.Graphics.Grid; 5 | using System; 6 | using System.Threading.Tasks; 7 | 8 | namespace LedHost { 9 | public sealed class LedBiColourMatrix { 10 | 11 | public async void Start() { 12 | 13 | Pixel[] palette = new Pixel[] { BiColour.Red, BiColour.Green, BiColour.Yellow }; 14 | 15 | 16 | var driver = new Ht16K33BiColor(new byte[] { 0x71 }, Ht16K33BiColor.Rotate.D90); 17 | LED8x8Matrix matrix = new LED8x8Matrix(driver); 18 | 19 | matrix.SetBrightness(6); 20 | 21 | while (true) { 22 | 23 | matrix.FrameClear(); 24 | matrix.ScrollStringInFromRight("Hello World 2015", 60, new Pixel[] { BiColour.Red, BiColour.Green, BiColour.Yellow }); 25 | 26 | matrix.FrameClear(); 27 | matrix.ScrollStringInFromLeft("Hello World 2015", 100, palette); 28 | 29 | //continue; 30 | 31 | for (ushort p = 0; p < matrix.PanelsPerFrame; p++) { 32 | matrix.DrawSymbol(Grid8x8.Symbols.Block, BiColour.Red, p); 33 | matrix.FrameDraw(); 34 | await Task.Delay(100); 35 | } 36 | 37 | 38 | for (int p = 0; p < matrix.Length; p++) { 39 | matrix.FrameSet(BiColour.Green, p); 40 | matrix.FrameSet(BiColour.Green, matrix.Length - 1 - p); 41 | 42 | matrix.FrameDraw(); 43 | await Task.Delay(2); 44 | 45 | matrix.FrameSet(Led.Off, p); 46 | matrix.FrameSet(Led.Off, matrix.Length - 1 - p); 47 | 48 | matrix.FrameDraw(); 49 | await Task.Delay(2); 50 | } 51 | 52 | 53 | for (int c = 0; c < matrix.ColumnsPerFrame; c = c + 2) { 54 | matrix.ColumnDrawLine(c); 55 | matrix.FrameDraw(); 56 | await Task.Delay(100); 57 | } 58 | 59 | 60 | for (int r = 0; r < matrix.RowsPerPanel; r = r + 2) { 61 | matrix.RowDrawLine(r, BiColour.Yellow); 62 | matrix.FrameDraw(); 63 | await Task.Delay(100); 64 | } 65 | 66 | await Task.Delay(1000); 67 | 68 | for (ushort i = 0; i < matrix.PanelsPerFrame; i++) { 69 | matrix.DrawLetter(i.ToString()[0], BiColour.Green, i); 70 | } 71 | 72 | matrix.FrameDraw(); 73 | await Task.Delay(1000); 74 | 75 | for (int r = 0; r < matrix.RowsPerPanel * 2; r++) { 76 | matrix.FrameRollDown(); 77 | matrix.FrameDraw(); 78 | await Task.Delay(100); 79 | } 80 | 81 | for (int r = 0; r < matrix.RowsPerPanel * 2; r++) { 82 | matrix.FrameRollUp(); 83 | matrix.FrameDraw(); 84 | await Task.Delay(100); 85 | } 86 | 87 | for (int c = 0; c < matrix.ColumnsPerFrame * 1; c++) { 88 | matrix.FrameRollRight(); 89 | matrix.FrameDraw(); 90 | await Task.Delay(100); 91 | } 92 | 93 | for (int c = 0; c < matrix.ColumnsPerFrame * 1; c++) { 94 | matrix.FrameRollLeft(); 95 | matrix.FrameDraw(); 96 | await Task.Delay(50); 97 | } 98 | 99 | matrix.DrawString("Wow, such colour :)", palette, 200, 0); 100 | matrix.FrameClear(); 101 | 102 | for (int i = 0; i < matrix.RowsPerPanel; i++) { 103 | matrix.DrawBox(i, i, matrix.ColumnsPerFrame - (i * 2), matrix.RowsPerPanel - (i * 2), Led.On); 104 | matrix.FrameDraw(); 105 | await Task.Delay(100); 106 | } 107 | 108 | for (byte l = 0; l < 2; l++) { 109 | matrix.SetFrameState(LedDriver.Display.Off); 110 | await Task.Delay(250); 111 | matrix.SetFrameState(LedDriver.Display.On); 112 | await Task.Delay(250); 113 | } 114 | 115 | 116 | 117 | matrix.FrameClear(); 118 | 119 | for (int r = 0; r < 4; r++) { 120 | for (int i = 0; i < matrix.RowsPerPanel; i++) { 121 | matrix.RowDrawLine(i, i - 0, matrix.ColumnsPerFrame - i - 1, palette[i % palette.Length]); 122 | matrix.FrameDraw(); 123 | await Task.Delay(50); 124 | } 125 | 126 | 127 | for (int i = 0; i < matrix.RowsPerPanel; i++) { 128 | matrix.RowDrawLine(i, i - 0, matrix.ColumnsPerFrame - i - 1, Led.Off); 129 | matrix.FrameDraw(); 130 | await Task.Delay(50); 131 | } 132 | } 133 | 134 | await Task.Delay(250); 135 | matrix.FrameClear(); 136 | 137 | 138 | for (int i = 0; i < matrix.fontSimple.Length; i = i + matrix.PanelsPerFrame) { 139 | for (int p = 0; p < matrix.PanelsPerFrame; p++) { 140 | if (p + i >= matrix.fontSimple.Length) { break; } 141 | matrix.DrawBitmap(matrix.fontSimple[p + i], palette[i % palette.Length], (p + i) % matrix.PanelsPerFrame); 142 | } 143 | matrix.FrameDraw(); 144 | await Task.Delay(150 * matrix.PanelsPerFrame); 145 | } 146 | 147 | foreach (Grid8x8.Symbols sym in Enum.GetValues(typeof(Grid8x8.Symbols))) { 148 | for (int p = 0; p < matrix.PanelsPerFrame; p++) { 149 | matrix.DrawSymbol(sym, palette[p % palette.Length], p); 150 | } 151 | matrix.FrameDraw(); 152 | await Task.Delay(150 * matrix.PanelsPerFrame); 153 | } 154 | } 155 | } 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /Examples/LedMonoMatrix.cs: -------------------------------------------------------------------------------- 1 | using Glovebox.Graphics; 2 | using Glovebox.Graphics.Components; 3 | using Glovebox.Graphics.Drivers; 4 | using Glovebox.Graphics.Grid; 5 | using System; 6 | using System.Threading.Tasks; 7 | 8 | namespace LedHost { 9 | public sealed class LedMonoMatrix { 10 | 11 | public async void Start() { 12 | var driver = new Ht16K33(new byte[] { 0x70, 0x72 }, Ht16K33.Rotate.None); 13 | 14 | LED8x8Matrix matrix = new LED8x8Matrix(driver); 15 | 16 | matrix.SetBrightness(2); 17 | 18 | while (true) { 19 | 20 | matrix.FrameClear(); 21 | 22 | for (int i = 0; i < matrix.fontSimple.Length; i = i + matrix.PanelsPerFrame) { 23 | for (int p = 0; p < matrix.PanelsPerFrame; p++) { 24 | if (p + i >= matrix.fontSimple.Length) { break; } 25 | matrix.DrawBitmap(matrix.fontSimple[p + i], Led.On, (p + i) % matrix.PanelsPerFrame); 26 | } 27 | matrix.FrameDraw(); 28 | await Task.Delay(100 * matrix.PanelsPerFrame); 29 | } 30 | 31 | foreach (Grid8x8.Symbols sym in Enum.GetValues(typeof(Grid8x8.Symbols))) { 32 | for (int p = 0; p < matrix.PanelsPerFrame; p++) { 33 | matrix.DrawSymbol(sym, p); 34 | } 35 | matrix.FrameDraw(); 36 | await Task.Delay(100 * matrix.PanelsPerFrame); 37 | } 38 | 39 | matrix.FrameClear(); 40 | matrix.ScrollStringInFromRight("Hello World 2015", 100); 41 | 42 | matrix.FrameClear(); 43 | matrix.ScrollStringInFromLeft("Hello World 2015", 100); 44 | 45 | //continue; 46 | 47 | for (ushort p = 0; p < matrix.PanelsPerFrame; p++) { 48 | matrix.DrawSymbol(Grid8x8.Symbols.Block, p); 49 | matrix.FrameDraw(); 50 | await Task.Delay(100); 51 | } 52 | 53 | 54 | for (int p = 0; p < matrix.Length; p++) { 55 | matrix.FrameSet(Led.On, p); 56 | matrix.FrameSet(Led.On, matrix.Length - 1 - p); 57 | 58 | matrix.FrameDraw(); 59 | await Task.Delay(2); 60 | 61 | matrix.FrameSet(Led.Off, p); 62 | matrix.FrameSet(Led.Off, matrix.Length - 1 - p); 63 | 64 | matrix.FrameDraw(); 65 | await Task.Delay(2); 66 | } 67 | 68 | 69 | for (int c = 0; c < matrix.ColumnsPerFrame; c = c + 2) { 70 | matrix.ColumnDrawLine(c); 71 | matrix.FrameDraw(); 72 | await Task.Delay(100); 73 | } 74 | 75 | 76 | for (int r = 0; r < matrix.RowsPerPanel; r = r + 2) { 77 | matrix.RowDrawLine(r); 78 | matrix.FrameDraw(); 79 | await Task.Delay(100); 80 | } 81 | 82 | await Task.Delay(1000); 83 | 84 | for (ushort i = 0; i < matrix.PanelsPerFrame; i++) { 85 | matrix.DrawLetter(i.ToString()[0], i); 86 | } 87 | 88 | matrix.FrameDraw(); 89 | await Task.Delay(1000); 90 | 91 | for (int r = 0; r < matrix.RowsPerPanel * 2; r++) { 92 | matrix.FrameRollDown(); 93 | matrix.FrameDraw(); 94 | await Task.Delay(100); 95 | } 96 | 97 | for (int r = 0; r < matrix.RowsPerPanel * 2; r++) { 98 | matrix.FrameRollUp(); 99 | matrix.FrameDraw(); 100 | await Task.Delay(100); 101 | } 102 | 103 | for (int c = 0; c < matrix.ColumnsPerFrame * 1; c++) { 104 | matrix.FrameRollRight(); 105 | matrix.FrameDraw(); 106 | await Task.Delay(100); 107 | } 108 | 109 | for (int c = 0; c < matrix.ColumnsPerFrame * 1; c++) { 110 | matrix.FrameRollLeft(); 111 | matrix.FrameDraw(); 112 | await Task.Delay(100); 113 | } 114 | 115 | 116 | //await Task.Delay(1000); 117 | //continue; 118 | 119 | matrix.DrawString("ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890", 100, 0); 120 | matrix.FrameClear(); 121 | 122 | for (int i = 0; i < matrix.RowsPerPanel; i++) { 123 | matrix.DrawBox(i, i, matrix.ColumnsPerFrame - (i * 2), matrix.RowsPerPanel - (i * 2)); 124 | matrix.FrameDraw(); 125 | await Task.Delay(100); 126 | } 127 | 128 | for (byte l = 0; l < 2; l++) { 129 | matrix.SetFrameState(LedDriver.Display.Off); 130 | await Task.Delay(250); 131 | matrix.SetFrameState(LedDriver.Display.On); 132 | await Task.Delay(250); 133 | } 134 | 135 | 136 | 137 | matrix.FrameClear(); 138 | 139 | for (int r = 0; r < 2; r++) { 140 | for (int i = 0; i < matrix.RowsPerPanel; i++) { 141 | matrix.RowDrawLine(i, i - 0, matrix.ColumnsPerFrame - i - 1); 142 | matrix.FrameDraw(); 143 | await Task.Delay(50); 144 | } 145 | 146 | //for (byte l = 0; l < 6; l++) { 147 | // matrix.SetBrightness(l); 148 | // await Task.Delay(250); 149 | //} 150 | 151 | //matrix.SetBrightness(1); 152 | 153 | for (int i = 0; i < matrix.RowsPerPanel; i++) { 154 | matrix.RowDrawLine(i, i - 0, matrix.ColumnsPerFrame - i - 1, Led.Off); 155 | matrix.FrameDraw(); 156 | await Task.Delay(50); 157 | } 158 | } 159 | 160 | await Task.Delay(500); 161 | matrix.FrameClear(); 162 | 163 | matrix.ScrollStringInFromRight("Hello World ", 100); 164 | matrix.FrameClear(); 165 | matrix.ScrollStringInFromLeft("Happy Birthday ", 100); 166 | 167 | 168 | 169 | } 170 | } 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /Examples/LedMonoMatrixSPI.cs: -------------------------------------------------------------------------------- 1 | using Glovebox.Graphics; 2 | using Glovebox.Graphics.Components; 3 | using Glovebox.Graphics.Drivers; 4 | using Glovebox.Graphics.Grid; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace LedHost { 12 | public sealed class LedMonoMatrixSPI { 13 | 14 | public async void Start() { 15 | 16 | var driver = new MAX7219(1, MAX7219.Rotate.D90, MAX7219.Transform.None, MAX7219.ChipSelect.CE0); 17 | 18 | LED8x8Matrix matrix = new LED8x8Matrix(driver); 19 | 20 | matrix.SetBrightness(2); 21 | 22 | while (true) { 23 | 24 | matrix.FrameClear(); 25 | matrix.ScrollStringInFromRight("Hello World 2015", 100); 26 | 27 | matrix.FrameClear(); 28 | matrix.ScrollStringInFromLeft("Hello World 2015", 100); 29 | 30 | //continue; 31 | 32 | for (ushort p = 0; p < matrix.PanelsPerFrame; p++) { 33 | matrix.DrawSymbol(Grid8x8.Symbols.Block, Led.On, p); 34 | matrix.FrameDraw(); 35 | await Task.Delay(100); 36 | } 37 | 38 | 39 | for (int p = 0; p < matrix.Length; p++) { 40 | matrix.FrameSet(Led.On, p); 41 | matrix.FrameSet(Led.On, matrix.Length - 1 - p); 42 | 43 | matrix.FrameDraw(); 44 | await Task.Delay(2); 45 | 46 | matrix.FrameSet(Led.Off, p); 47 | matrix.FrameSet(Led.Off, matrix.Length - 1 - p); 48 | 49 | matrix.FrameDraw(); 50 | await Task.Delay(2); 51 | } 52 | 53 | 54 | for (int c = 0; c < matrix.ColumnsPerFrame; c = c + 2) { 55 | matrix.ColumnDrawLine(c); 56 | matrix.FrameDraw(); 57 | await Task.Delay(100); 58 | } 59 | 60 | 61 | for (int r = 0; r < matrix.RowsPerPanel; r = r + 2) { 62 | matrix.RowDrawLine(r); 63 | matrix.FrameDraw(); 64 | await Task.Delay(100); 65 | } 66 | 67 | await Task.Delay(1000); 68 | 69 | for (ushort i = 0; i < matrix.PanelsPerFrame; i++) { 70 | matrix.DrawLetter(i.ToString()[0], Led.On, i); 71 | } 72 | 73 | matrix.FrameDraw(); 74 | await Task.Delay(1000); 75 | 76 | for (int r = 0; r < matrix.RowsPerPanel * 2; r++) { 77 | matrix.FrameRollDown(); 78 | matrix.FrameDraw(); 79 | await Task.Delay(100); 80 | } 81 | 82 | for (int r = 0; r < matrix.RowsPerPanel * 2; r++) { 83 | matrix.FrameRollUp(); 84 | matrix.FrameDraw(); 85 | await Task.Delay(100); 86 | } 87 | 88 | for (int c = 0; c < matrix.ColumnsPerFrame * 1; c++) { 89 | matrix.FrameRollRight(); 90 | matrix.FrameDraw(); 91 | await Task.Delay(100); 92 | } 93 | 94 | for (int c = 0; c < matrix.ColumnsPerFrame * 1; c++) { 95 | matrix.FrameRollLeft(); 96 | matrix.FrameDraw(); 97 | await Task.Delay(100); 98 | } 99 | 100 | 101 | //await Task.Delay(1000); 102 | //continue; 103 | 104 | matrix.DrawString("ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890", 100, 0); 105 | matrix.FrameClear(); 106 | 107 | for (int i = 0; i < matrix.RowsPerPanel; i++) { 108 | matrix.DrawBox(i, i, matrix.ColumnsPerFrame - (i * 2), matrix.RowsPerPanel - (i * 2), Led.On); 109 | matrix.FrameDraw(); 110 | await Task.Delay(100); 111 | } 112 | 113 | for (byte l = 0; l < 2; l++) { 114 | matrix.SetFrameState(LedDriver.Display.Off); 115 | await Task.Delay(250); 116 | matrix.SetFrameState(LedDriver.Display.On); 117 | await Task.Delay(250); 118 | } 119 | 120 | 121 | 122 | matrix.FrameClear(); 123 | 124 | for (int r = 0; r < 2; r++) { 125 | for (int i = 0; i < matrix.RowsPerPanel; i++) { 126 | matrix.RowDrawLine(i, i - 0, matrix.ColumnsPerFrame - i - 1); 127 | matrix.FrameDraw(); 128 | await Task.Delay(50); 129 | } 130 | 131 | //for (byte l = 0; l < 6; l++) { 132 | // matrix.SetBrightness(l); 133 | // await Task.Delay(250); 134 | //} 135 | 136 | //matrix.SetBrightness(1); 137 | 138 | for (int i = 0; i < matrix.RowsPerPanel; i++) { 139 | matrix.RowDrawLine(i, i - 0, matrix.ColumnsPerFrame - i - 1, Led.Off); 140 | matrix.FrameDraw(); 141 | await Task.Delay(50); 142 | } 143 | } 144 | 145 | await Task.Delay(500); 146 | matrix.FrameClear(); 147 | 148 | matrix.ScrollStringInFromRight("Hello World ", 100); 149 | matrix.FrameClear(); 150 | matrix.ScrollStringInFromLeft("Happy Birthday ", 100); 151 | 152 | 153 | for (int i = 0; i < matrix.fontSimple.Length; i = i + matrix.PanelsPerFrame) { 154 | for (int p = 0; p < matrix.PanelsPerFrame; p++) { 155 | if (p + i >= matrix.fontSimple.Length) { break; } 156 | matrix.DrawBitmap(matrix.fontSimple[p + i], Led.On, (p + i) % matrix.PanelsPerFrame); 157 | } 158 | matrix.FrameDraw(); 159 | await Task.Delay(100 * matrix.PanelsPerFrame); 160 | } 161 | 162 | foreach (Grid8x8.Symbols sym in Enum.GetValues(typeof(Grid8x8.Symbols))) { 163 | for (int p = 0; p < matrix.PanelsPerFrame; p++) { 164 | matrix.DrawSymbol(sym, Led.On, p); 165 | } 166 | matrix.FrameDraw(); 167 | await Task.Delay(100 * matrix.PanelsPerFrame); 168 | } 169 | } 170 | } 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /Examples/LedMonoPanelSPI.cs: -------------------------------------------------------------------------------- 1 | using Glovebox.Graphics; 2 | using Glovebox.Graphics.Components; 3 | using Glovebox.Graphics.Drivers; 4 | using Glovebox.Graphics.Grid; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace LedHost { 12 | public sealed class LedMonoPanelSPI { 13 | 14 | public async void Start() { 15 | 16 | var driver = new MAX7219(4, MAX7219.Rotate.None, MAX7219.Transform.HorizontalFlip, MAX7219.ChipSelect.CE1); 17 | 18 | LED8x8Matrix matrix = new LED8x8Matrix(driver); 19 | 20 | matrix.SetBrightness(2); 21 | 22 | while (true) { 23 | 24 | matrix.FrameClear(); 25 | matrix.ScrollStringInFromRight("Hello World 2015", 100); 26 | 27 | matrix.FrameClear(); 28 | matrix.ScrollStringInFromLeft("Hello World 2015", 100); 29 | 30 | //continue; 31 | 32 | for (ushort p = 0; p < matrix.PanelsPerFrame; p++) { 33 | matrix.DrawSymbol(Grid8x8.Symbols.Block, Led.On, p); 34 | matrix.FrameDraw(); 35 | await Task.Delay(100); 36 | } 37 | 38 | 39 | for (int p = 0; p < matrix.Length; p++) { 40 | matrix.FrameSet(Led.On, p); 41 | matrix.FrameSet(Led.On, matrix.Length - 1 - p); 42 | 43 | matrix.FrameDraw(); 44 | await Task.Delay(2); 45 | 46 | matrix.FrameSet(Led.Off, p); 47 | matrix.FrameSet(Led.Off, matrix.Length - 1 - p); 48 | 49 | matrix.FrameDraw(); 50 | await Task.Delay(2); 51 | } 52 | 53 | 54 | for (int c = 0; c < matrix.ColumnsPerFrame; c = c + 2) { 55 | matrix.ColumnDrawLine(c); 56 | matrix.FrameDraw(); 57 | await Task.Delay(100); 58 | } 59 | 60 | 61 | for (int r = 0; r < matrix.RowsPerPanel; r = r + 2) { 62 | matrix.RowDrawLine(r); 63 | matrix.FrameDraw(); 64 | await Task.Delay(100); 65 | } 66 | 67 | await Task.Delay(1000); 68 | 69 | for (ushort i = 0; i < matrix.PanelsPerFrame; i++) { 70 | matrix.DrawLetter(i.ToString()[0], Led.On, i); 71 | } 72 | 73 | matrix.FrameDraw(); 74 | await Task.Delay(1000); 75 | 76 | for (int r = 0; r < matrix.RowsPerPanel * 2; r++) { 77 | matrix.FrameRollDown(); 78 | matrix.FrameDraw(); 79 | await Task.Delay(100); 80 | } 81 | 82 | for (int r = 0; r < matrix.RowsPerPanel * 2; r++) { 83 | matrix.FrameRollUp(); 84 | matrix.FrameDraw(); 85 | await Task.Delay(100); 86 | } 87 | 88 | for (int c = 0; c < matrix.ColumnsPerFrame * 1; c++) { 89 | matrix.FrameRollRight(); 90 | matrix.FrameDraw(); 91 | await Task.Delay(100); 92 | } 93 | 94 | for (int c = 0; c < matrix.ColumnsPerFrame * 1; c++) { 95 | matrix.FrameRollLeft(); 96 | matrix.FrameDraw(); 97 | await Task.Delay(100); 98 | } 99 | 100 | 101 | //await Task.Delay(1000); 102 | //continue; 103 | 104 | matrix.DrawString("ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890", 100, 0); 105 | matrix.FrameClear(); 106 | 107 | for (int i = 0; i < matrix.RowsPerPanel; i++) { 108 | matrix.DrawBox(i, i, matrix.ColumnsPerFrame - (i * 2), matrix.RowsPerPanel - (i * 2), Led.On); 109 | matrix.FrameDraw(); 110 | await Task.Delay(100); 111 | } 112 | 113 | for (byte l = 0; l < 2; l++) { 114 | matrix.SetFrameState(LedDriver.Display.Off); 115 | await Task.Delay(250); 116 | matrix.SetFrameState(LedDriver.Display.On); 117 | await Task.Delay(250); 118 | } 119 | 120 | 121 | 122 | matrix.FrameClear(); 123 | 124 | for (int r = 0; r < 2; r++) { 125 | for (int i = 0; i < matrix.RowsPerPanel; i++) { 126 | matrix.RowDrawLine(i, i - 0, matrix.ColumnsPerFrame - i - 1); 127 | matrix.FrameDraw(); 128 | await Task.Delay(50); 129 | } 130 | 131 | //for (byte l = 0; l < 6; l++) { 132 | // matrix.SetBrightness(l); 133 | // await Task.Delay(250); 134 | //} 135 | 136 | //matrix.SetBrightness(1); 137 | 138 | for (int i = 0; i < matrix.RowsPerPanel; i++) { 139 | matrix.RowDrawLine(i, i - 0, matrix.ColumnsPerFrame - i - 1, Led.Off); 140 | matrix.FrameDraw(); 141 | await Task.Delay(50); 142 | } 143 | } 144 | 145 | await Task.Delay(500); 146 | matrix.FrameClear(); 147 | 148 | matrix.ScrollStringInFromRight("Hello World ", 100); 149 | matrix.FrameClear(); 150 | matrix.ScrollStringInFromLeft("Happy Birthday ", 100); 151 | 152 | 153 | for (int i = 0; i < matrix.fontSimple.Length; i = i + matrix.PanelsPerFrame) { 154 | for (int p = 0; p < matrix.PanelsPerFrame; p++) { 155 | if (p + i >= matrix.fontSimple.Length) { break; } 156 | matrix.DrawBitmap(matrix.fontSimple[p + i], Led.On, (p + i) % matrix.PanelsPerFrame); 157 | } 158 | matrix.FrameDraw(); 159 | await Task.Delay(100 * matrix.PanelsPerFrame); 160 | } 161 | 162 | foreach (Grid8x8.Symbols sym in Enum.GetValues(typeof(Grid8x8.Symbols))) { 163 | for (int p = 0; p < matrix.PanelsPerFrame; p++) { 164 | matrix.DrawSymbol(sym, Led.On, p); 165 | } 166 | matrix.FrameDraw(); 167 | await Task.Delay(100 * matrix.PanelsPerFrame); 168 | } 169 | } 170 | } 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /Examples/Package.appxmanifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | LedHost 7 | dglov 8 | Assets\StoreLogo.png 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Examples/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("LedHost")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("LedHost")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Version information for an assembly consists of the following four values: 18 | // 19 | // Major Version 20 | // Minor Version 21 | // Build Number 22 | // Revision 23 | // 24 | // You can specify all the values or you can default the Build and Revision Numbers 25 | // by using the '*' as shown below: 26 | // [assembly: AssemblyVersion("1.0.*")] 27 | [assembly: AssemblyVersion("1.0.0.0")] 28 | [assembly: AssemblyFileVersion("1.0.0.0")] 29 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /Examples/Properties/Default.rd.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Examples/StartupTask.cs: -------------------------------------------------------------------------------- 1 | using Glovebox.Graphics; 2 | using Glovebox.Graphics.Components; 3 | using Glovebox.Graphics.Drivers; 4 | using Glovebox.Graphics.Grid; 5 | using System; 6 | using System.Threading.Tasks; 7 | using Windows.ApplicationModel.Background; 8 | 9 | // The Background Application template is documented at http://go.microsoft.com/fwlink/?LinkID=533884&clcid=0x409 10 | 11 | namespace LedHost 12 | { 13 | public sealed class StartupTask : IBackgroundTask 14 | { 15 | 16 | BackgroundTaskDeferral _deferral; 17 | 18 | LedMonoMatrix monoMatrix = new LedMonoMatrix(); 19 | LedBiColourMatrix biColorMatrix = new LedBiColourMatrix(); 20 | LedMonoPanelSPI MonoSPIPanel = new LedMonoPanelSPI(); 21 | LedMonoMatrixSPI MonoSPIMatrix = new LedMonoMatrixSPI(); 22 | 23 | public void Run(IBackgroundTaskInstance taskInstance) 24 | { 25 | _deferral = taskInstance.GetDeferral(); 26 | 27 | monoMatrix.Start(); 28 | biColorMatrix.Start(); 29 | MonoSPIMatrix.Start(); 30 | // MonoSPIPanel.Start(); 31 | 32 | //Task.Delay(-1).Wait(); 33 | 34 | 35 | 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /Examples/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0" 4 | }, 5 | "frameworks": { 6 | "uap10.0": {} 7 | }, 8 | "runtimes": { 9 | "win10-arm": {}, 10 | "win10-arm-aot": {}, 11 | "win10-x86": {}, 12 | "win10-x86-aot": {}, 13 | "win10-x64": {}, 14 | "win10-x64-aot": {} 15 | } 16 | } -------------------------------------------------------------------------------- /Glovebox.Graphics Library.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.24720.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Glovebox.Graphics", "Glovebox.Graphics\Glovebox.Graphics.csproj", "{6B7BCBAB-4C1A-4E90-9F9B-31B233F90370}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LED Matrix Adavnced Examples", "Examples\LED Matrix Adavnced Examples.csproj", "{872E4D7B-1D1B-4D5B-A36E-5A98108A489F}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LED Matrix HelloWorld Sample", "HelloWorld\LED Matrix HelloWorld Sample.csproj", "{18B2C975-9740-47AC-9343-0C7F33CE5578}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Seven Segment Display Sample", "Seven Segment Display Sample\Seven Segment Display Sample.csproj", "{80A04812-AC5A-4FAF-8546-4DB9F9C92C95}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Debug|ARM = Debug|ARM 18 | Debug|x64 = Debug|x64 19 | Debug|x86 = Debug|x86 20 | Release|Any CPU = Release|Any CPU 21 | Release|ARM = Release|ARM 22 | Release|x64 = Release|x64 23 | Release|x86 = Release|x86 24 | EndGlobalSection 25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 26 | {6B7BCBAB-4C1A-4E90-9F9B-31B233F90370}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {6B7BCBAB-4C1A-4E90-9F9B-31B233F90370}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {6B7BCBAB-4C1A-4E90-9F9B-31B233F90370}.Debug|ARM.ActiveCfg = Debug|Any CPU 29 | {6B7BCBAB-4C1A-4E90-9F9B-31B233F90370}.Debug|ARM.Build.0 = Debug|Any CPU 30 | {6B7BCBAB-4C1A-4E90-9F9B-31B233F90370}.Debug|x64.ActiveCfg = Debug|x64 31 | {6B7BCBAB-4C1A-4E90-9F9B-31B233F90370}.Debug|x64.Build.0 = Debug|x64 32 | {6B7BCBAB-4C1A-4E90-9F9B-31B233F90370}.Debug|x86.ActiveCfg = Debug|x86 33 | {6B7BCBAB-4C1A-4E90-9F9B-31B233F90370}.Debug|x86.Build.0 = Debug|x86 34 | {6B7BCBAB-4C1A-4E90-9F9B-31B233F90370}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {6B7BCBAB-4C1A-4E90-9F9B-31B233F90370}.Release|Any CPU.Build.0 = Release|Any CPU 36 | {6B7BCBAB-4C1A-4E90-9F9B-31B233F90370}.Release|ARM.ActiveCfg = Release|Any CPU 37 | {6B7BCBAB-4C1A-4E90-9F9B-31B233F90370}.Release|ARM.Build.0 = Release|Any CPU 38 | {6B7BCBAB-4C1A-4E90-9F9B-31B233F90370}.Release|x64.ActiveCfg = Release|x64 39 | {6B7BCBAB-4C1A-4E90-9F9B-31B233F90370}.Release|x64.Build.0 = Release|x64 40 | {6B7BCBAB-4C1A-4E90-9F9B-31B233F90370}.Release|x86.ActiveCfg = Release|x86 41 | {6B7BCBAB-4C1A-4E90-9F9B-31B233F90370}.Release|x86.Build.0 = Release|x86 42 | {872E4D7B-1D1B-4D5B-A36E-5A98108A489F}.Debug|Any CPU.ActiveCfg = Debug|ARM 43 | {872E4D7B-1D1B-4D5B-A36E-5A98108A489F}.Debug|Any CPU.Build.0 = Debug|ARM 44 | {872E4D7B-1D1B-4D5B-A36E-5A98108A489F}.Debug|Any CPU.Deploy.0 = Debug|ARM 45 | {872E4D7B-1D1B-4D5B-A36E-5A98108A489F}.Debug|ARM.ActiveCfg = Debug|ARM 46 | {872E4D7B-1D1B-4D5B-A36E-5A98108A489F}.Debug|x64.ActiveCfg = Debug|x64 47 | {872E4D7B-1D1B-4D5B-A36E-5A98108A489F}.Debug|x64.Build.0 = Debug|x64 48 | {872E4D7B-1D1B-4D5B-A36E-5A98108A489F}.Debug|x64.Deploy.0 = Debug|x64 49 | {872E4D7B-1D1B-4D5B-A36E-5A98108A489F}.Debug|x86.ActiveCfg = Debug|x86 50 | {872E4D7B-1D1B-4D5B-A36E-5A98108A489F}.Debug|x86.Build.0 = Debug|x86 51 | {872E4D7B-1D1B-4D5B-A36E-5A98108A489F}.Debug|x86.Deploy.0 = Debug|x86 52 | {872E4D7B-1D1B-4D5B-A36E-5A98108A489F}.Release|Any CPU.ActiveCfg = Release|ARM 53 | {872E4D7B-1D1B-4D5B-A36E-5A98108A489F}.Release|ARM.ActiveCfg = Release|ARM 54 | {872E4D7B-1D1B-4D5B-A36E-5A98108A489F}.Release|ARM.Build.0 = Release|ARM 55 | {872E4D7B-1D1B-4D5B-A36E-5A98108A489F}.Release|ARM.Deploy.0 = Release|ARM 56 | {872E4D7B-1D1B-4D5B-A36E-5A98108A489F}.Release|x64.ActiveCfg = Release|x64 57 | {872E4D7B-1D1B-4D5B-A36E-5A98108A489F}.Release|x64.Build.0 = Release|x64 58 | {872E4D7B-1D1B-4D5B-A36E-5A98108A489F}.Release|x64.Deploy.0 = Release|x64 59 | {872E4D7B-1D1B-4D5B-A36E-5A98108A489F}.Release|x86.ActiveCfg = Release|x86 60 | {872E4D7B-1D1B-4D5B-A36E-5A98108A489F}.Release|x86.Build.0 = Release|x86 61 | {872E4D7B-1D1B-4D5B-A36E-5A98108A489F}.Release|x86.Deploy.0 = Release|x86 62 | {18B2C975-9740-47AC-9343-0C7F33CE5578}.Debug|Any CPU.ActiveCfg = Debug|ARM 63 | {18B2C975-9740-47AC-9343-0C7F33CE5578}.Debug|Any CPU.Build.0 = Debug|ARM 64 | {18B2C975-9740-47AC-9343-0C7F33CE5578}.Debug|Any CPU.Deploy.0 = Debug|ARM 65 | {18B2C975-9740-47AC-9343-0C7F33CE5578}.Debug|ARM.ActiveCfg = Debug|ARM 66 | {18B2C975-9740-47AC-9343-0C7F33CE5578}.Debug|ARM.Build.0 = Debug|ARM 67 | {18B2C975-9740-47AC-9343-0C7F33CE5578}.Debug|ARM.Deploy.0 = Debug|ARM 68 | {18B2C975-9740-47AC-9343-0C7F33CE5578}.Debug|x64.ActiveCfg = Debug|x64 69 | {18B2C975-9740-47AC-9343-0C7F33CE5578}.Debug|x64.Build.0 = Debug|x64 70 | {18B2C975-9740-47AC-9343-0C7F33CE5578}.Debug|x64.Deploy.0 = Debug|x64 71 | {18B2C975-9740-47AC-9343-0C7F33CE5578}.Debug|x86.ActiveCfg = Debug|x86 72 | {18B2C975-9740-47AC-9343-0C7F33CE5578}.Debug|x86.Build.0 = Debug|x86 73 | {18B2C975-9740-47AC-9343-0C7F33CE5578}.Debug|x86.Deploy.0 = Debug|x86 74 | {18B2C975-9740-47AC-9343-0C7F33CE5578}.Release|Any CPU.ActiveCfg = Release|ARM 75 | {18B2C975-9740-47AC-9343-0C7F33CE5578}.Release|ARM.ActiveCfg = Release|ARM 76 | {18B2C975-9740-47AC-9343-0C7F33CE5578}.Release|ARM.Build.0 = Release|ARM 77 | {18B2C975-9740-47AC-9343-0C7F33CE5578}.Release|ARM.Deploy.0 = Release|ARM 78 | {18B2C975-9740-47AC-9343-0C7F33CE5578}.Release|x64.ActiveCfg = Release|x64 79 | {18B2C975-9740-47AC-9343-0C7F33CE5578}.Release|x64.Build.0 = Release|x64 80 | {18B2C975-9740-47AC-9343-0C7F33CE5578}.Release|x64.Deploy.0 = Release|x64 81 | {18B2C975-9740-47AC-9343-0C7F33CE5578}.Release|x86.ActiveCfg = Release|x86 82 | {18B2C975-9740-47AC-9343-0C7F33CE5578}.Release|x86.Build.0 = Release|x86 83 | {18B2C975-9740-47AC-9343-0C7F33CE5578}.Release|x86.Deploy.0 = Release|x86 84 | {80A04812-AC5A-4FAF-8546-4DB9F9C92C95}.Debug|Any CPU.ActiveCfg = Debug|ARM 85 | {80A04812-AC5A-4FAF-8546-4DB9F9C92C95}.Debug|Any CPU.Build.0 = Debug|ARM 86 | {80A04812-AC5A-4FAF-8546-4DB9F9C92C95}.Debug|Any CPU.Deploy.0 = Debug|ARM 87 | {80A04812-AC5A-4FAF-8546-4DB9F9C92C95}.Debug|ARM.ActiveCfg = Debug|ARM 88 | {80A04812-AC5A-4FAF-8546-4DB9F9C92C95}.Debug|ARM.Build.0 = Debug|ARM 89 | {80A04812-AC5A-4FAF-8546-4DB9F9C92C95}.Debug|ARM.Deploy.0 = Debug|ARM 90 | {80A04812-AC5A-4FAF-8546-4DB9F9C92C95}.Debug|x64.ActiveCfg = Debug|x64 91 | {80A04812-AC5A-4FAF-8546-4DB9F9C92C95}.Debug|x64.Build.0 = Debug|x64 92 | {80A04812-AC5A-4FAF-8546-4DB9F9C92C95}.Debug|x64.Deploy.0 = Debug|x64 93 | {80A04812-AC5A-4FAF-8546-4DB9F9C92C95}.Debug|x86.ActiveCfg = Debug|x86 94 | {80A04812-AC5A-4FAF-8546-4DB9F9C92C95}.Debug|x86.Build.0 = Debug|x86 95 | {80A04812-AC5A-4FAF-8546-4DB9F9C92C95}.Debug|x86.Deploy.0 = Debug|x86 96 | {80A04812-AC5A-4FAF-8546-4DB9F9C92C95}.Release|Any CPU.ActiveCfg = Release|x86 97 | {80A04812-AC5A-4FAF-8546-4DB9F9C92C95}.Release|ARM.ActiveCfg = Release|ARM 98 | {80A04812-AC5A-4FAF-8546-4DB9F9C92C95}.Release|ARM.Build.0 = Release|ARM 99 | {80A04812-AC5A-4FAF-8546-4DB9F9C92C95}.Release|ARM.Deploy.0 = Release|ARM 100 | {80A04812-AC5A-4FAF-8546-4DB9F9C92C95}.Release|x64.ActiveCfg = Release|x64 101 | {80A04812-AC5A-4FAF-8546-4DB9F9C92C95}.Release|x64.Build.0 = Release|x64 102 | {80A04812-AC5A-4FAF-8546-4DB9F9C92C95}.Release|x64.Deploy.0 = Release|x64 103 | {80A04812-AC5A-4FAF-8546-4DB9F9C92C95}.Release|x86.ActiveCfg = Release|x86 104 | {80A04812-AC5A-4FAF-8546-4DB9F9C92C95}.Release|x86.Build.0 = Release|x86 105 | {80A04812-AC5A-4FAF-8546-4DB9F9C92C95}.Release|x86.Deploy.0 = Release|x86 106 | EndGlobalSection 107 | GlobalSection(SolutionProperties) = preSolution 108 | HideSolutionNode = FALSE 109 | EndGlobalSection 110 | EndGlobal 111 | -------------------------------------------------------------------------------- /Glovebox.Graphics/Components/LED8x8Matrix.cs: -------------------------------------------------------------------------------- 1 | using Glovebox.Graphics.Drivers; 2 | using Glovebox.Graphics.Grid; 3 | using System; 4 | 5 | namespace Glovebox.Graphics.Components { 6 | public class LED8x8Matrix : Grid8x8, ILedDriver { 7 | 8 | ILedDriver driver; 9 | 10 | public LED8x8Matrix(ILedDriver driver) : base("matrix", driver.PanelsPerFrame) { 11 | this.driver = driver; 12 | } 13 | 14 | public int PanelsPerFrame { 15 | get { 16 | return driver.PanelsPerFrame; 17 | } 18 | } 19 | 20 | public void SetBlinkRate(LedDriver.BlinkRate blinkrate) { 21 | driver.SetBlinkRate(blinkrate); 22 | } 23 | 24 | public void SetBrightness(byte level) { 25 | driver.SetBrightness(level); 26 | } 27 | 28 | public void SetFrameState(LedDriver.Display state) { 29 | driver.SetFrameState(state); 30 | } 31 | 32 | public void Write(ulong[] frame) 33 | { 34 | throw new NotImplementedException(); 35 | } 36 | 37 | public void Write(Pixel[] frame) { 38 | // never called - implementation is overridden 39 | throw new NotImplementedException(); 40 | } 41 | 42 | protected override void FrameDraw(Pixel[] frame) { 43 | driver.Write(frame); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Glovebox.Graphics/Components/SevenSegmentDisplay.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Glovebox.Graphics.Drivers; 3 | using Glovebox.Graphics.SevenSegmentDisplay; 4 | 5 | namespace Glovebox.Graphics.Components 6 | { 7 | public class SevenSegmentDisplay : SevenSegmentDisplayBase, ILedDriver 8 | { 9 | ILedDriver driver; 10 | 11 | public SevenSegmentDisplay(ILedDriver driver) : base("ssd", driver.PanelsPerFrame) 12 | { 13 | this.driver = driver; 14 | } 15 | 16 | public int PanelsPerFrame 17 | { 18 | get 19 | { 20 | return driver.PanelsPerFrame; 21 | } 22 | } 23 | 24 | public void SetBlinkRate(LedDriver.BlinkRate blinkrate) 25 | { 26 | driver.SetBlinkRate(blinkrate); 27 | } 28 | 29 | public void SetBrightness(byte level) 30 | { 31 | driver.SetBrightness(level); 32 | } 33 | 34 | public void SetFrameState(LedDriver.Display state) 35 | { 36 | driver.SetFrameState(state); 37 | } 38 | 39 | public void Write(ulong[] frame) 40 | { 41 | driver.Write(frame); 42 | } 43 | 44 | public void Write(Pixel[] frame) 45 | { 46 | driver.Write(frame); 47 | } 48 | 49 | 50 | protected override void FrameDraw(ulong[] frame) 51 | { 52 | driver.Write(frame); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Glovebox.Graphics/Drivers/Ht16K33.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Windows.Devices.Enumeration; 4 | using Windows.Devices.I2c; 5 | 6 | namespace Glovebox.Graphics.Drivers { 7 | 8 | /// 9 | /// Represents a I2C connection to a PCF8574 I/O Expander. 10 | /// 11 | /// See for more information. 12 | public class Ht16K33 : LedDriver, IDisposable, ILedDriver { 13 | #region Fields 14 | 15 | public int PanelsPerFrame { get; private set; } 16 | const uint bufferSize = 17; 17 | protected byte[] Frame = new byte[bufferSize]; 18 | protected ushort Columns { get; set; } 19 | protected ushort Rows { get; set; } 20 | 21 | protected I2cDevice[] i2cDevice; 22 | 23 | private const byte OSCILLATOR_ON = 0x21; 24 | private const byte OSCILLATOR_OFF = 0x20; 25 | 26 | private string I2cControllerName = "I2C1"; /* For Raspberry Pi 2, use I2C1 */ 27 | private byte[] I2CAddress; // = 0x70; 28 | 29 | 30 | private byte currentFrameState; 31 | private byte[] frameStates = { 0x81, 0x80 }; // on, off 32 | 33 | private byte currentBlinkrate = 0x00; // off 34 | private byte[] blinkRates = { 0x00, 0x02, 0x04, 0x06 }; //off, 2hz, 1hz, 0.5 hz for off, fast, medium, slow 35 | 36 | 37 | private byte brightness; 38 | 39 | public enum Rotate { 40 | None = 0, 41 | D90 = 1, 42 | D180 = 2, 43 | } 44 | protected Rotate rotate = Rotate.None; 45 | 46 | 47 | #endregion 48 | 49 | /// 50 | /// Initializes a new instance of the Ht16K33 I2C controller as found on the Adafriut Mini LED Matrix. 51 | /// 52 | /// On or Off - defaults to On 53 | /// Between 0 and 15 54 | /// Defaults to Off. Blink rates Fast = 2hz, Medium = 1hz, slow = 0.5hz 55 | public Ht16K33(byte[] I2CAddress = null, Rotate rotate = Rotate.None, Display frame = LedDriver.Display.On, byte brightness = 2, BlinkRate blinkrate = BlinkRate.Off, string I2cControllerName = "I2C1") { 56 | 57 | Columns = 8; 58 | Rows = 8; 59 | this.rotate = rotate; 60 | this.brightness = brightness; 61 | this.I2cControllerName = I2cControllerName; 62 | 63 | if (I2CAddress == null) { 64 | this.I2CAddress = new byte[] { 0x70 }; 65 | } 66 | else { 67 | this.I2CAddress = I2CAddress; 68 | } 69 | 70 | this.PanelsPerFrame = this.I2CAddress.Length; 71 | this.i2cDevice = new I2cDevice[PanelsPerFrame]; 72 | 73 | currentFrameState = frameStates[(byte)frame]; 74 | currentBlinkrate = blinkRates[(byte)blinkrate]; 75 | 76 | Initialize(); 77 | } 78 | 79 | private void Initialize() { 80 | for (int panel = 0; panel < PanelsPerFrame; panel++) { 81 | Task.Run(() => I2cConnect(panel)).Wait(); 82 | } 83 | InitPanels(); 84 | } 85 | 86 | private async Task I2cConnect(int panel) { 87 | try { 88 | var settings = new I2cConnectionSettings(I2CAddress[panel]); 89 | settings.BusSpeed = I2cBusSpeed.FastMode; 90 | 91 | string aqs = I2cDevice.GetDeviceSelector(I2cControllerName); /* Find the selector string for the I2C bus controller */ 92 | var dis = await DeviceInformation.FindAllAsync(aqs); /* Find the I2C bus controller device with our selector string */ 93 | i2cDevice[panel] = await I2cDevice.FromIdAsync(dis[0].Id, settings); /* Create an I2cDevice with our selected bus controller and I2C settings */ 94 | } 95 | catch (Exception e) { 96 | throw new Exception("ht16k33 initisation problem: " + e.Message); 97 | } 98 | } 99 | 100 | private void InitPanels() { 101 | WriteAll(new byte[] { OSCILLATOR_ON, 0x00 }); 102 | Write(0); // clear the screen 103 | UpdateFrameState(); 104 | SetBrightness(brightness); 105 | } 106 | 107 | public void SetBrightness(byte level) { 108 | if (level > 15) { level = 15; } 109 | WriteAll(new byte[] { (byte)(0xE0 | level), 0x00 }); 110 | } 111 | 112 | public void SetBlinkRate(BlinkRate blinkrate) { 113 | currentBlinkrate = blinkRates[(byte)blinkrate]; 114 | UpdateFrameState(); 115 | } 116 | 117 | public void SetFrameState(Display state) { 118 | currentFrameState = frameStates[(byte)state]; 119 | UpdateFrameState(); 120 | } 121 | 122 | public int GetNumberOfPanels() { 123 | return (int)PanelsPerFrame; 124 | } 125 | 126 | private void UpdateFrameState() { 127 | WriteAll(new byte[] { (byte)((byte)currentFrameState | (byte)this.currentBlinkrate), 0x00 }); 128 | } 129 | 130 | private void WriteAll(byte[] data) { 131 | for (int panel = 0; panel < PanelsPerFrame; panel++) { 132 | i2cDevice[panel].Write(data); 133 | } 134 | } 135 | 136 | // required for Interface but implementation is overridden below 137 | public void Write(ulong frameMap) { 138 | } 139 | 140 | public void Write(ulong[] input) { 141 | // perform any required display rotations 142 | for (int rotations = 0; rotations < (int)rotate; rotations++) { 143 | for (int panel = 0; panel < input.Length; panel++) { 144 | input[panel] = RotateAntiClockwise(input[panel]); 145 | } 146 | } 147 | 148 | for (int p = 0; p < input.Length; p++) { 149 | DrawBitmap(input[p]); 150 | i2cDevice[p].Write(Frame); 151 | } 152 | } 153 | 154 | public virtual void Write(Pixel[] frame) { 155 | ulong[] output = new ulong[PanelsPerFrame]; 156 | ulong pixelState = 0; 157 | 158 | for (int panels = 0; panels < PanelsPerFrame; panels++) { 159 | 160 | for (int i = panels * 64; i < 64 + (panels * 64); i++) { 161 | pixelState = frame[i].ColourValue > 0 ? 1UL : 0; 162 | pixelState = pixelState << i; 163 | output[panels] = output[panels] | pixelState; 164 | } 165 | } 166 | 167 | Write(output); 168 | } 169 | 170 | void IDisposable.Dispose() { 171 | for (int panel = 0; panel < PanelsPerFrame; panel++) { 172 | i2cDevice[panel].Dispose(); 173 | } 174 | } 175 | 176 | private void DrawBitmap(ulong bitmap) { 177 | for (ushort row = 0; row < Rows; row++) { 178 | Frame[row * 2 + 1] = FixBitOrder((byte)(bitmap >> (row * Columns))); 179 | } 180 | } 181 | 182 | // Fix bit order problem with the ht16K33 controller or Adafruit 8x8 matrix 183 | // Bits offset by 1, roll bits forward by 1, replace 8th bit with the 1st 184 | private byte FixBitOrder(byte b) { 185 | return (byte)(b >> 1 | (b << 7)); 186 | } 187 | 188 | protected ulong RotateAntiClockwise(ulong input) { 189 | ulong output = 0; 190 | byte row; 191 | 192 | for (int byteNumber = 0; byteNumber < 8; byteNumber++) { 193 | 194 | row = (byte)(input >> 8 * byteNumber); 195 | 196 | ulong mask = 0; //build the new column bit mask 197 | int bit = 0; // bit pointer/counter 198 | 199 | do { 200 | mask = mask << 8 | (byte)(row >> (bit++) & 1); 201 | } while (bit < 8); 202 | 203 | mask = mask << byteNumber; 204 | 205 | // merge in the new column bit mask 206 | output = output | mask; 207 | } 208 | return output; 209 | } 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /Glovebox.Graphics/Drivers/Ht16K33BiColor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Glovebox.Graphics.Drivers { 4 | 5 | /// 6 | /// Represents a I2C connection to a PCF8574 I/O Expander. 7 | /// 8 | /// See for more information. 9 | public class Ht16K33BiColor : Ht16K33, IDisposable, ILedDriver { 10 | 11 | /// 12 | /// Initializes a new instance of the Ht16K33 I2C controller as found on the Adafriut Mini LED Matrix. 13 | /// 14 | /// On or Off - defaults to On 15 | /// Between 0 and 15 16 | /// Defaults to Off. Blink rates Fast = 2hz, Medium = 1hz, slow = 0.5hz 17 | public Ht16K33BiColor(byte[] I2CAddress, Rotate rotate = Rotate.None, Display frame = LedDriver.Display.On, byte brightness = 0, BlinkRate blinkrate = BlinkRate.Off, string I2cControllerName="I2C1") 18 | : base(I2CAddress, rotate, frame, brightness, blinkrate, I2cControllerName) { } 19 | 20 | 21 | public void Write(ulong[] inputGreen, ulong[] inputRed) { 22 | 23 | // perform any required display rotations 24 | for (int rotations = 0; rotations < (int)rotate; rotations++) { 25 | for (int panel = 0; panel < inputGreen.Length; panel++) { 26 | inputGreen[panel] = RotateAntiClockwise(inputGreen[panel]); 27 | inputRed[panel] = RotateAntiClockwise(inputRed[panel]); 28 | } 29 | } 30 | 31 | 32 | for (int p = 0; p < inputGreen.Length; p++) { 33 | DrawBitmap(inputGreen[p], inputRed[p]); 34 | i2cDevice[p].Write(Frame); 35 | } 36 | } 37 | 38 | public override void Write(Pixel[] frame) { 39 | ulong[] outputGreen = new ulong[PanelsPerFrame]; 40 | ulong[] outputRed = new ulong[PanelsPerFrame]; 41 | ulong pixelStateGreen = 0; 42 | ulong pixelStateRed = 0; 43 | 44 | for (int panels = 0; panels < PanelsPerFrame; panels++) { 45 | 46 | for (int i = panels * 64; i < 64 + (panels * 64); i++) { 47 | 48 | switch (frame[i].ColourValue) { 49 | case 65280: // green 50 | pixelStateGreen = 1UL; 51 | pixelStateGreen = pixelStateGreen << i; 52 | outputGreen[panels] = outputGreen[panels] | pixelStateGreen; 53 | break; 54 | case 16711680: // red 55 | pixelStateRed = 1UL; 56 | pixelStateRed = pixelStateRed << i; 57 | outputRed[panels] = outputRed[panels] | pixelStateRed; 58 | break; 59 | case 16776960: //yellow 60 | pixelStateGreen = 1UL; 61 | pixelStateGreen = pixelStateGreen << i; 62 | outputGreen[panels] = outputGreen[panels] | pixelStateGreen; 63 | 64 | pixelStateRed = 1UL; 65 | pixelStateRed = pixelStateRed << i; 66 | outputRed[panels] = outputRed[panels] | pixelStateRed; 67 | 68 | break; 69 | } 70 | } 71 | } 72 | 73 | Write(outputGreen, outputRed); 74 | } 75 | 76 | private void DrawBitmap(ulong bitmapGreen, ulong bitmapRed) { 77 | for (ushort row = 0; row < Rows; row++) { 78 | Frame[row * 2 + 1] = 0x00; 79 | Frame[row * 2 + 1] = (byte)(bitmapGreen >> (row * Columns)); 80 | Frame[(row * 2 + 1) + 1] = 0x00; 81 | Frame[(row * 2 + 1) + 1] = (byte)(bitmapRed >> (row * Columns)); ; 82 | 83 | } 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Glovebox.Graphics/Drivers/ILedDriver.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Glovebox.Graphics.Drivers { 3 | public interface ILedDriver { 4 | int PanelsPerFrame { get; } 5 | void SetBlinkRate(LedDriver.BlinkRate blinkrate); 6 | void SetBrightness(byte level); 7 | void SetFrameState(LedDriver.Display state); 8 | void Write(Pixel[] frame); 9 | void Write(ulong[] frame); 10 | } 11 | } -------------------------------------------------------------------------------- /Glovebox.Graphics/Drivers/LedDriver.cs: -------------------------------------------------------------------------------- 1 | namespace Glovebox.Graphics.Drivers { 2 | public class LedDriver { 3 | 4 | public enum Display : byte { 5 | On, 6 | Off, 7 | } 8 | 9 | public enum BlinkRate : byte { 10 | Off, 11 | Fast, 12 | Medium, 13 | Slow, 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Glovebox.Graphics/Drivers/MAX7219.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Windows.Devices.Enumeration; 4 | using Windows.Devices.Spi; 5 | 6 | namespace Glovebox.Graphics.Drivers 7 | { 8 | public class MAX7219 : ILedDriver, IDisposable 9 | { 10 | 11 | private string SPIControllerName = "SPI0"; // Use SPI0 for RPi2 12 | 13 | private byte[] SendDataBytes; 14 | 15 | // http://datasheets.maximintegrated.com/en/ds/MAX7219-MAX7221.pdf 16 | 17 | private static readonly byte[] MODE_DECODE = { 0x09, 0x00 }; 18 | private static byte[] MODE_INTENSITY = { 0x0A, 0x02 }; 19 | private static readonly byte[] MODE_SCAN_LIMIT = { 0x0B, 0x07 }; 20 | private static readonly byte[] MODE_POWER_ON = { 0x0C, 0x01 }; 21 | private static readonly byte[] MODE_POWER_OFF = { 0x0C, 0x00 }; 22 | private static readonly byte[] MODE_TEST = { 0x0F, 0x00 }; 23 | private static readonly byte[] MODE_NOOP = { 0x00, 0x00 }; 24 | 25 | private SpiDevice SpiDisplay; 26 | 27 | public int PanelsPerFrame { get; private set; } 28 | 29 | public enum Rotate 30 | { 31 | None = 0, 32 | D90 = 1, 33 | D180 = 2, 34 | } 35 | 36 | public enum Transform 37 | { 38 | None, 39 | HorizontalFlip, 40 | } 41 | 42 | public enum ChipSelect 43 | { 44 | CE0 = 0, CE1 = 1 45 | } 46 | 47 | private ChipSelect chipSelect = ChipSelect.CE0; 48 | private Rotate rotate = Rotate.None; 49 | private Transform transform = Transform.None; 50 | 51 | 52 | public MAX7219(int numberOfPanels = 1, Rotate rotate = Rotate.None, Transform transform = Transform.None, ChipSelect chipSelect = ChipSelect.CE0, string SPIControllerName = "SPI0") 53 | { 54 | this.PanelsPerFrame = numberOfPanels < 0 ? 0 : numberOfPanels; 55 | this.rotate = rotate; 56 | this.transform = transform; 57 | this.chipSelect = chipSelect; 58 | this.SPIControllerName = SPIControllerName; 59 | 60 | SendDataBytes = new byte[2 * PanelsPerFrame]; 61 | 62 | Task.Run(() => InitSpi()).Wait(); 63 | InitDisplay(); 64 | } 65 | 66 | /// 67 | /// Initialize SPI. 68 | /// 69 | /// 70 | private async Task InitSpi() 71 | { 72 | try 73 | { 74 | var settings = new SpiConnectionSettings((int)chipSelect); 75 | settings.ClockFrequency = 10000000; 76 | settings.Mode = SpiMode.Mode0; 77 | settings.SharingMode = SpiSharingMode.Shared; 78 | 79 | string spiAqs = SpiDevice.GetDeviceSelector(SPIControllerName); /* Find the selector string for the SPI bus controller */ 80 | var devicesInfo = await DeviceInformation.FindAllAsync(spiAqs); /* Find the SPI bus controller device with our selector string */ 81 | SpiDisplay = await SpiDevice.FromIdAsync(devicesInfo[0].Id, settings); /* Create an SpiDevice with our bus controller and SPI settings */ 82 | } 83 | /* If initialization fails, display the exception and stop running */ 84 | catch (Exception ex) 85 | { 86 | throw new Exception("SPI Initialization Failed", ex); 87 | } 88 | } 89 | 90 | /// 91 | /// Initialize LED Display. Refer to the datasheet of MAX7219 92 | /// 93 | /// 94 | private void InitDisplay() 95 | { 96 | InitPanel(MODE_SCAN_LIMIT); 97 | InitPanel(MODE_DECODE); 98 | InitPanel(MODE_POWER_ON); 99 | InitPanel(MODE_TEST); 100 | InitPanel(MODE_INTENSITY); 101 | } 102 | 103 | private void InitPanel(byte[] control) 104 | { 105 | for (int p = 0; p < PanelsPerFrame * 2; p = p + 2) 106 | { 107 | SendDataBytes[p] = control[0]; 108 | SendDataBytes[p + 1] = control[1]; ; 109 | } 110 | SpiDisplay.Write(SendDataBytes); 111 | } 112 | 113 | public void SetBlinkRate(LedDriver.BlinkRate blinkrate) 114 | { 115 | 116 | } 117 | 118 | public void SetBrightness(byte level) 119 | { 120 | if (level >= 0 && level < 16) 121 | { 122 | MODE_INTENSITY[1] = level; 123 | InitPanel(MODE_INTENSITY); 124 | } 125 | } 126 | 127 | public void SetFrameState(LedDriver.Display state) 128 | { 129 | if (state == LedDriver.Display.On) { InitPanel(MODE_POWER_ON); } 130 | else { InitPanel(MODE_POWER_OFF); } 131 | } 132 | 133 | // required for Interface but implementation is overridden below 134 | public void Write(ulong frameMap) { } 135 | 136 | public void Write(ulong[] input) 137 | { 138 | byte row; 139 | 140 | if (input.Length>1 && rotate==0) 141 | Array.Reverse(input); 142 | 143 | // perform any required display rotations 144 | for (int rotations = 0; rotations < (int)rotate; rotations++) 145 | { 146 | for (int panel = 0; panel < input.Length; panel++) 147 | { 148 | input[panel] = RotateAntiClockwise(input[panel]); 149 | 150 | if (transform == Transform.HorizontalFlip) 151 | { 152 | input[panel] = HorizontalFlip(input[panel]); 153 | } 154 | } 155 | } 156 | 157 | for (int panel = 0; panel < input.Length; panel++) 158 | { 159 | if (transform == Transform.HorizontalFlip) 160 | { 161 | input[panel] = HorizontalFlip(input[panel]); 162 | } 163 | } 164 | 165 | 166 | for (int rowNumber = 0; rowNumber < 8; rowNumber++) 167 | { 168 | for (int panel = 0; panel < input.Length; panel++) 169 | { 170 | 171 | SendDataBytes[panel * 2] = (byte)(rowNumber + 1); // Address 172 | row = (byte)(input[input.Length - 1 - panel] >> 8 * rowNumber); 173 | SendDataBytes[(panel * 2) + 1] = row; 174 | 175 | SpiDisplay.Write(SendDataBytes); 176 | } 177 | } 178 | } 179 | 180 | public void Write(Pixel[] frame) 181 | { 182 | ulong[] output = new ulong[PanelsPerFrame]; 183 | ulong pixelState = 0; 184 | 185 | for (int panels = 0; panels < PanelsPerFrame; panels++) 186 | { 187 | 188 | for (int i = panels * 64; i < 64 + (panels * 64); i++) 189 | { 190 | pixelState = frame[i].ColourValue > 0 ? 1UL : 0; 191 | pixelState = pixelState << i; 192 | output[panels] = output[panels] | pixelState; 193 | } 194 | } 195 | 196 | Write(output); 197 | } 198 | 199 | private ulong RotateAntiClockwise(ulong input) 200 | { 201 | ulong output = 0; 202 | byte row; 203 | 204 | for (int byteNumber = 0; byteNumber < 8; byteNumber++) 205 | { 206 | 207 | row = (byte)(input >> 8 * byteNumber); 208 | 209 | ulong mask = 0; //build the new column bit mask 210 | int bit = 0; // bit pointer/counter 211 | 212 | do 213 | { 214 | mask = mask << 8 | (byte)(row >> (7 - bit++) & 1); 215 | } while (bit < 8); 216 | 217 | mask = mask << byteNumber; 218 | 219 | output = output | mask; // merge in the new column bit mask 220 | } 221 | return output; 222 | } 223 | 224 | 225 | private ulong HorizontalFlip(ulong input) 226 | { 227 | ulong output = 0; 228 | ulong newRow; 229 | 230 | byte row = 0; 231 | 232 | for (int byteNumber = 0; byteNumber < 8; byteNumber++) 233 | { 234 | row = (byte)(input >> 8 * byteNumber); 235 | newRow = (ulong)((ulong)row << ((7 - byteNumber) * 8)); 236 | output |= newRow; 237 | 238 | 239 | } 240 | return output; 241 | } 242 | 243 | public void Dispose() 244 | { 245 | SpiDisplay.Dispose(); 246 | } 247 | } 248 | } 249 | -------------------------------------------------------------------------------- /Glovebox.Graphics/FrameBase.cs: -------------------------------------------------------------------------------- 1 | namespace Glovebox.Graphics { 2 | 3 | 4 | /// 5 | /// Frame primatives - generic across Rings, Stips and Grids 6 | /// 7 | public class FrameBase { 8 | 9 | #region Pixel Colour Definitions 10 | 11 | /// 12 | /// NeoPixels run medium bright and cool on this palette 13 | /// 14 | public static Pixel[] PaletteWarmLowPower = new Pixel[] { 15 | Colour.WarmRed, 16 | Colour.WarmOrange, 17 | Colour.WarmYellow, 18 | Colour.WarmGreen, 19 | Colour.WarmBlue, 20 | Colour.WarmPurple, 21 | //Pixel.ColourLowPower.WarmIndigo 22 | }; 23 | 24 | /// 25 | /// NeoPixels run dim and cool on this palette 26 | /// 27 | public static Pixel[] PaletteCoolLowPower = new Pixel[] { 28 | Colour.CoolRed, 29 | Colour.CoolOrange, 30 | Colour.CoolYellow, 31 | Colour.CoolGreen, 32 | Colour.CoolBlue, 33 | Colour.CoolPurple, 34 | }; 35 | 36 | /// 37 | /// NeoPixels run bright but cool on this palette 38 | /// 39 | public static Pixel[] PaletteHotLowPower = new Pixel[] { 40 | Colour.HotRed, 41 | Colour.HotOrange, 42 | Colour.HotYellow, 43 | Colour.HotGreen, 44 | Colour.HotBlue, 45 | Colour.HotPurple, 46 | }; 47 | 48 | protected static Pixel[] PaletteFullColour = new Pixel[] 49 | { 50 | Colour.White, 51 | Colour.Black, 52 | Colour.Red, 53 | Colour.Orange, 54 | Colour.Yellow, 55 | Colour.Green, 56 | Colour.Purple, 57 | Colour.Blue, 58 | }; 59 | #endregion 60 | 61 | 62 | private readonly int pixelCount; 63 | 64 | public int Length { 65 | get { return pixelCount; } 66 | } 67 | 68 | 69 | public Pixel[] Frame { get; set; } 70 | 71 | private Pixel[] blinkFrame; 72 | public FrameBase(int _pixelCount) { 73 | pixelCount = _pixelCount; 74 | Frame = new Pixel[pixelCount]; 75 | 76 | //lazy initialise in the black/blank in the blink method 77 | blinkFrame = new Pixel[pixelCount]; 78 | 79 | // init frame to all black - specifically not null 80 | FrameClear(); 81 | } 82 | 83 | #region Primitive Frame Manipulation Methods 84 | public void FrameClear() { 85 | FrameSet(Colour.Black); 86 | } 87 | 88 | /// 89 | /// Fill entire frame with one colour 90 | /// 91 | /// 92 | public void FrameSet(Pixel pixel) { 93 | for (int i = 0; i < Frame.Length; i++) { 94 | Frame[i] = pixel; 95 | } 96 | } 97 | 98 | /// 99 | /// Fill entire frame with one colour 100 | /// 101 | /// 102 | public virtual void FrameSet(Pixel pixel, int position) { 103 | if (position < 0) { return; } 104 | 105 | Frame[position % Length] = pixel; 106 | } 107 | 108 | /// 109 | /// set specific frame pixels a colour - useful for letters on grids, patterns etc 110 | /// 111 | /// 112 | /// 113 | public void FrameSet(Pixel colour, int[] pixelPos) { 114 | for (int i = 0; i < pixelPos.Length; i++) { 115 | if (pixelPos[i] < 0 || pixelPos[i] >= Frame.Length) { continue; } 116 | Frame[pixelPos[i]] = colour; 117 | } 118 | } 119 | 120 | /// 121 | /// set specific frame pixels from a rolling palette of colours 122 | /// 123 | /// 124 | /// 125 | public void FrameSet(Pixel[] palette, int[] pixelPos) { 126 | for (int i = 0; i < pixelPos.Length; i++) { 127 | if (pixelPos[i] < 0 || pixelPos[i] >= Frame.Length) { continue; } 128 | Frame[pixelPos[i]] = palette[i % palette.Length]; 129 | } 130 | } 131 | 132 | 133 | /// 134 | /// fill frame pixels from a specified position and repeat 135 | /// 136 | /// 137 | /// 138 | /// 139 | public void FrameSet(Pixel pixel, int startPos, int repeat = 1) { 140 | if (startPos < 0 | repeat < 0) { return; } 141 | 142 | for (int i = startPos, r = 0; r < repeat; i++, r++) { 143 | Frame[i % Frame.Length] = pixel; 144 | } 145 | } 146 | 147 | /// 148 | /// fill frame pixels from a specified position and repeat from a palette of colours 149 | /// 150 | /// 151 | /// 152 | /// 153 | public void FrameSet(Pixel[] pixel, int startPos, int repeat = 1) { 154 | if (startPos < 0 | repeat < 0) { return; } 155 | 156 | for (int i = startPos, r = 0; r < repeat; i++, r++) { 157 | Frame[i % Frame.Length] = pixel[i % pixel.Length]; 158 | } 159 | } 160 | 161 | /// 162 | /// fill frame from a rolling pallet 163 | /// 164 | /// 165 | public void FrameSet(Pixel[] palette) { 166 | for (int i = 0; i < Frame.Length; i++) { 167 | Frame[i] = palette[i % palette.Length]; 168 | } 169 | } 170 | 171 | /// 172 | /// fill frame with blocks of colour from a palette 173 | /// 174 | /// 175 | public void FrameSetBlocks(Pixel[] palette) { 176 | if (palette == null || palette.Length == 0) { 177 | FrameClear(); 178 | } 179 | else if (palette.Length >= pixelCount) { 180 | FrameSet(palette); 181 | } 182 | else { 183 | var leftovers = pixelCount % palette.Length; 184 | int leftoversUsed = 0; 185 | int thisPixel = 0; 186 | uint baseBlockSize = (uint)(pixelCount / palette.Length); 187 | for (int i = 0; i < palette.Length; i++) { 188 | for (int j = 0; j < baseBlockSize; j++) { 189 | Frame[thisPixel] = palette[i]; 190 | thisPixel++; 191 | } 192 | if (leftoversUsed < leftovers) { 193 | Frame[thisPixel] = palette[i]; 194 | thisPixel++; 195 | leftoversUsed++; 196 | } 197 | } 198 | } 199 | } 200 | 201 | 202 | /// 203 | /// Swap specified pixels with wrap 204 | /// 205 | /// 206 | /// 207 | public void FramePixelSwap(int pixel1, int pixel2) { 208 | if (pixel1 < 0 | pixel2 < 0) { return; } 209 | 210 | Pixel temp = Frame[pixel2 % pixelCount]; 211 | Frame[pixel2 % pixelCount] = Frame[pixel1 % pixelCount]; 212 | Frame[pixel1 % pixelCount] = temp; 213 | } 214 | 215 | public void FramePixelForward(int pixelIndex, int stepSize = 1) { 216 | if (pixelIndex < 0 | stepSize < 0) { return; } 217 | 218 | if (pixelIndex >= Frame.Length) { return; } 219 | 220 | int length = Frame.Length; 221 | int newIndex = (pixelIndex + stepSize) % length; 222 | 223 | Pixel p = Frame[newIndex]; 224 | Frame[newIndex] = Frame[pixelIndex]; 225 | Frame[pixelIndex] = p; 226 | } 227 | 228 | 229 | /// 230 | /// Shift wrap forward a block of pixels by specified amount 231 | /// 232 | /// 233 | public void FrameShiftForward(int blockSize = 1) { 234 | if (blockSize < 0) { return; } 235 | 236 | blockSize = blockSize % Length; 237 | 238 | int i; 239 | Pixel[] temp = new Pixel[blockSize]; 240 | 241 | for (i = 0; i < blockSize; i++) { 242 | temp[i] = Frame[Frame.Length - blockSize + i]; 243 | } 244 | 245 | for (i = Frame.Length - 1; i >= blockSize; i--) { 246 | Frame[i] = Frame[i - blockSize]; 247 | } 248 | 249 | for (i = 0; i < blockSize; i++) { 250 | Frame[i] = temp[i]; 251 | } 252 | } 253 | 254 | /// 255 | /// Shift wrap forward a block of pixels by specified amount 256 | /// 257 | /// 258 | public void FrameShiftBack(int blockSize = 1) { 259 | if (blockSize < 0) { return; } 260 | 261 | blockSize = blockSize % Length; 262 | 263 | int i; 264 | Pixel[] temp = new Pixel[blockSize]; 265 | 266 | for (i = 0; i < blockSize; i++) { 267 | temp[i] = Frame[i]; 268 | } 269 | 270 | for (i = blockSize; i < Frame.Length; i++) { 271 | Frame[i - blockSize] = Frame[i]; 272 | } 273 | 274 | for (i = 0; i < blockSize; i++) { 275 | int p = Frame.Length - blockSize + i; 276 | Frame[p] = temp[i]; 277 | } 278 | } 279 | 280 | 281 | /// 282 | /// cycle the pixels moving them up by increment pixels 283 | /// 284 | /// number of positions to shift. Negative numbers backwards. If this is more than the number of LEDs, the result wraps 285 | public void FrameShift(int increment = 1) { 286 | if (increment > 0) { FrameShiftForward(increment); } 287 | else if (increment < 0) { FrameShiftBack(System.Math.Abs(increment)); } 288 | } 289 | 290 | /// 291 | /// Forces an update with the current contents of currentDisplay 292 | /// 293 | public void FrameDraw() { 294 | FrameDraw(Frame); 295 | } 296 | 297 | protected virtual void FrameDraw(Pixel[] frame) { 298 | } 299 | 300 | #endregion 301 | 302 | #region Higher Level Display Methods 303 | 304 | /// 305 | /// move a singel pixel around (or along) the ring (or strip) - always starts at position 0 306 | /// 307 | /// Colour of the pixel to show 308 | /// Number of whole cycles to rotate 309 | /// Delay between steps (ms) 310 | public void SpinColour(Pixel pixelColour, int cycles = 1, int stepDelay = 250) { 311 | SpinColourOnBackground(pixelColour, Colour.Black, cycles, stepDelay); 312 | } 313 | 314 | public void SpinColourOnBackground(Pixel pixelColour, Pixel backgroundColour, int cycles = 1, int stepDelay = 250) { 315 | if (cycles < 0 || stepDelay < 0) { return; } 316 | 317 | FrameSet(backgroundColour); 318 | FrameSet(pixelColour, new int[] { 0 }); 319 | 320 | FrameDraw(); 321 | 322 | for (int i = 0; i < cycles; i++) { 323 | for (int j = 0; j < pixelCount; j++) { 324 | FrameShift(); 325 | FrameDraw(); 326 | Util.Delay(stepDelay); 327 | } 328 | } 329 | } 330 | 331 | protected void Blink(int blinkDelay, int repeat) { 332 | if (blinkDelay < 0 || repeat < 0) { return; } 333 | 334 | if (blinkFrame[0] == null) { 335 | for (int i = 0; i < blinkFrame.Length; i++) { 336 | blinkFrame[i] = Colour.Black; 337 | } 338 | } 339 | 340 | for (int i = 0; i < repeat; i++) { 341 | Util.Delay(blinkDelay); 342 | FrameDraw(blinkFrame); 343 | Util.Delay(blinkDelay); 344 | FrameDraw(); 345 | } 346 | } 347 | #endregion 348 | 349 | 350 | /// 351 | /// pass a PixelColour enum and get the corresponding Pixel of that colour 352 | /// assumes that the colourList and the PixelColour enum are in sync 353 | /// 354 | /// PixelColour of the pixel required 355 | /// 356 | protected Pixel getPixel(PixelColour pixelColour) { 357 | return PaletteFullColour[(int)pixelColour]; 358 | } 359 | 360 | protected Pixel[] GetColourListFromColourSet(PixelColour[] colourSet) { 361 | var colourList = new Pixel[colourSet.Length]; 362 | for (int i = 0; i < colourSet.Length; i++) { 363 | colourList[i] = getPixel(colourSet[i]); 364 | } 365 | return colourList; 366 | } 367 | } 368 | } 369 | -------------------------------------------------------------------------------- /Glovebox.Graphics/Glovebox.Graphics.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {6B7BCBAB-4C1A-4E90-9F9B-31B233F90370} 8 | Library 9 | Properties 10 | Glovebox.Graphics 11 | Glovebox.Graphics 12 | en-US 13 | UAP 14 | 10.0.10240.0 15 | 10.0.10240.0 16 | 14 17 | 512 18 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 19 | 20 | 21 | AnyCPU 22 | true 23 | full 24 | false 25 | bin\Debug\ 26 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 27 | prompt 28 | 4 29 | 30 | 31 | AnyCPU 32 | pdbonly 33 | true 34 | bin\Release\ 35 | TRACE;NETFX_CORE;WINDOWS_UWP 36 | prompt 37 | 4 38 | 39 | 40 | ARM 41 | true 42 | bin\ARM\Debug\ 43 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 44 | ;2008 45 | full 46 | ARM 47 | false 48 | prompt 49 | false 50 | 51 | 52 | ARM 53 | bin\ARM\Release\ 54 | TRACE;NETFX_CORE;WINDOWS_UWP 55 | true 56 | ;2008 57 | pdbonly 58 | ARM 59 | false 60 | prompt 61 | 62 | 63 | x64 64 | true 65 | bin\x64\Debug\ 66 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 67 | ;2008 68 | full 69 | x64 70 | false 71 | prompt 72 | 73 | 74 | x64 75 | bin\x64\Release\ 76 | TRACE;NETFX_CORE;WINDOWS_UWP 77 | true 78 | ;2008 79 | pdbonly 80 | x64 81 | false 82 | prompt 83 | 84 | 85 | x86 86 | true 87 | bin\x86\Debug\ 88 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 89 | ;2008 90 | full 91 | x86 92 | false 93 | prompt 94 | 95 | 96 | x86 97 | bin\x86\Release\ 98 | TRACE;NETFX_CORE;WINDOWS_UWP 99 | true 100 | ;2008 101 | pdbonly 102 | x86 103 | false 104 | prompt 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | Windows IoT Extensions for the UWP 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 14.0 136 | 137 | 138 | 145 | -------------------------------------------------------------------------------- /Glovebox.Graphics/Grid/Grid8x8.cs: -------------------------------------------------------------------------------- 1 | using Glovebox.Graphics; 2 | 3 | namespace Glovebox.Graphics.Grid { 4 | public class Grid8x8 : GridBase { 5 | 6 | 7 | #region Font Definition 8 | public ulong[] fontSimple = new ulong[] { 9 | 0x0000000000000000, // space 10 | 0x0008000808080808, // ! 11 | 0x0000000000001414, // " 12 | 0x0014143E143E1414, // # 13 | 0x00143E543E153E14, // $ 14 | 0x0032220408102226, // % 15 | 0x002C122C0C12120C, // & 16 | 0x0000000000000808, // ' 17 | 0x0008040202020408, // ( 18 | 0x0002040808080402, // ) 19 | 0x00412A142A142A41, // * 20 | 0x000808083E080808, // + 21 | 0x0408080000000000, // , 22 | 0x000000003E000000, // - 23 | 0x0002000000000000, // . 24 | 0x0001020408102040, // / 25 | 0x001c22262a32221c, //0 26 | 0x003e080808080a0c, //1 27 | 0x003e04081020221c, //2 28 | 0x001c22201820221c, //3 29 | 0x0008083e0a020202, //4 30 | 0x001c2220201e023e, //5 31 | 0x001c22221e02023c, //6 32 | 0x000202040810203e, //7 33 | 0x001c22221c22221c, //8 34 | 0x002020203c22221c, //9 35 | 0x00000C0C000C0C00, // : 36 | 0x0004080800080800, // ; 37 | 0x0010080402040810, // < 38 | 0x0000003E003E0000, // = 39 | 0x0002040810080402, // > 40 | 0x000808081020221C, // ? 41 | 0x001C02122A32221C, // @ 42 | 0x002222223e22221c, //A 43 | 0x001e22221e22221e, //B 44 | 0x001c22020202221c, //C 45 | 0x001e22222222221e, //D 46 | 0x003e02021e02023e, //E 47 | 0x000202021e02023e, //F 48 | 0x001c22223a02221c, //G 49 | 0x002222223e222222, //H 50 | 0x003e08080808083e, //I 51 | 0x000608080808083e, //J 52 | 0x0022120a060a1222, //K 53 | 0x003e020202020202, //L 54 | 0x00222222222a3622, //M 55 | 0x002222322a262222, //N 56 | 0x001c22222222221c, //O 57 | 0x000202021e22221e, //P 58 | 0x002c122a2222221c, //Q 59 | 0x0022120a1e22221e, //R 60 | 0x001c22100804221c, //S 61 | 0x000808080808083e, //T 62 | 0x001c222222222222, //U 63 | 0x0008142222222222, //V 64 | 0x0022362a22222222, //W 65 | 0x0022221408142222, //X 66 | 0x0008080808142222, //Y 67 | 0x003e02040810203e, //Z 68 | 0x000E02020202020E, //[ 69 | 0x0020201008040202, // \ 70 | 0x000E08080808080E, //] 71 | 0x0000000000221408, // ^ 72 | 0x003E000000000000, // _ 73 | 0x0000000000001008, // ' 74 | 0x0012121E120C0000, // a 75 | 0x000E120E120E0000, // b 76 | 0x000C1202120C0000, // c 77 | 0x000E1212120E0000, // d 78 | 0x001E020E021E0000, // e 79 | 0x0002020E021E0000, // f 80 | 0x000C121A021C0000, // g 81 | 0x0012121E12120000, // h 82 | 0x001C0808081C0000, // i 83 | 0x000C121010100000, // j 84 | 0x00120A060A120000, // k 85 | 0x001E020202020000, // l 86 | 0x0022222A36220000, // m 87 | 0x0022322A26220000, // n 88 | 0x000C1212120C0000, // o 89 | 0x0002020E120E0000, // p 90 | 0x201C1212120C0000, // q 91 | 0x0012120E120E0000, // r 92 | 0x000E100C021C0000, // s 93 | 0x00080808081C0000, // t 94 | 0x000C121212120000, // u 95 | 0x0008142222220000, // v 96 | 0x0022362A22220000, // w 97 | 0x0022140814220000, // x 98 | 0x0008080814220000, // y 99 | 0x003E0408103E0000, // z 100 | 101 | }; 102 | 103 | #endregion 104 | 105 | public enum Symbols : ulong { 106 | Heart = 0x00081C3E7F7F3600, 107 | HappyFace = 0x3C4299A581A5423C, 108 | SadFace = 0x3C42A59981A5423C, 109 | Block = 0xffffffffffffffff, 110 | HourGlass = 0xFF7E3C18183C7EFF, 111 | UpArrow = 0x18181818FF7E3C18, 112 | DownArrow = 0x183C7EFF18181818, 113 | RightArrow = 0x103070FFFF703010, 114 | LeftArrow = 0x080C0EFFFF0E0C08, 115 | } 116 | 117 | public Grid8x8(string name, int panels = 1) 118 | : base(8, 8, panels) { 119 | } 120 | 121 | #region Scroll string primatives 122 | 123 | public void ScrollStringInFromRight(string characters) 124 | { 125 | ScrollStringInFromRight(characters, 0, Led.On); 126 | } 127 | 128 | public void ScrollStringInFromLeft(string characters) 129 | { 130 | ScrollStringInFromLeft(characters, 0, Led.On); 131 | } 132 | 133 | public void ScrollStringInFromRight(string characters, int pause) { 134 | ScrollStringInFromRight(characters, pause, Led.On); 135 | } 136 | 137 | public void ScrollStringInFromLeft(string characters, int pause) 138 | { 139 | ScrollStringInFromLeft(characters, pause, Led.On); 140 | } 141 | 142 | public void ScrollStringInFromRight(string characters, int pause, Pixel colour) { 143 | ScrollStringInFromRight(characters, pause, new Pixel[] { colour }); 144 | } 145 | 146 | public void ScrollStringInFromLeft(string characters, int pause, Pixel colour) { 147 | ScrollStringInFromLeft(characters, pause, new Pixel[] { colour }); 148 | } 149 | 150 | public void ScrollStringInFromRight(string characters, int pause, Pixel[] colour) { 151 | ushort cycleColour = 0; 152 | 153 | // loop through each chacter 154 | for (int ch = 0; ch < characters.Length; ch++) { 155 | 156 | char charactor = characters.Substring(ch, 1)[0]; 157 | if (charactor >= ' ' && charactor <= 'z') { 158 | ScrollBitmapInFromRight(fontSimple[charactor - 32], pause, colour[cycleColour % colour.Length]); 159 | cycleColour++; 160 | } 161 | } 162 | } 163 | 164 | public void ScrollStringInFromLeft(string characters, int pause, Pixel[] colour) { 165 | ushort cycleColour = 0; 166 | 167 | // loop through each chacter 168 | for (int ch = characters.Length - 1; ch >= 0; ch--) { 169 | 170 | char charactor = characters.Substring(ch, 1)[0]; 171 | if (charactor >= ' ' && charactor <= 'z') { 172 | ScrollBitmapInFromLeft(fontSimple[charactor - 32], pause, colour[cycleColour % colour.Length]); 173 | cycleColour++; 174 | } 175 | } 176 | } 177 | 178 | #endregion 179 | 180 | #region Scroll Character primatives 181 | 182 | public void ScrollCharacterFromRight(char charactor, int pause) { 183 | ScrollCharacterFromRight(charactor, pause, Led.On); 184 | } 185 | 186 | 187 | public void ScrollCharacterFromRight(char charactor, int pause, Pixel colour) { 188 | if (charactor >= ' ' && charactor <= 'z') { 189 | ScrollBitmapInFromRight(fontSimple[charactor - 32], pause, colour); 190 | } 191 | } 192 | 193 | public void ScrollCharacterFromLeft(char charactor, int pause) { 194 | ScrollCharacterFromLeft(charactor, pause, Led.On); 195 | } 196 | 197 | public void ScrollCharacterFromLeft(char charactor, int pause, Pixel colour) { 198 | if (charactor >= ' ' && charactor <= 'z') { 199 | ScrollBitmapInFromLeft(fontSimple[charactor - 32], pause, colour); 200 | } 201 | } 202 | 203 | #endregion 204 | 205 | #region Scroll symbol primatives 206 | 207 | public void ScrollSymbolInFromRight(Symbols sym, int pause) { 208 | ScrollBitmapInFromRight((ulong)sym, pause, Led.On); 209 | } 210 | 211 | public void ScrollSymbolInFromRight(Symbols sym, int pause, Pixel colour) { 212 | ScrollBitmapInFromRight((ulong)sym, pause, colour); 213 | } 214 | 215 | public void ScrollSymbolInFromLeft(Symbols sym, int pause) { 216 | ScrollBitmapInFromLeft((ulong)sym, pause, Led.On); 217 | } 218 | 219 | public void ScrollSymbolInFromLeft(Symbols sym, int pause, Pixel colour) { 220 | ScrollBitmapInFromLeft((ulong)sym, pause, colour); 221 | } 222 | 223 | public void ScrollSymbolInFromRight(Symbols[] sym, int pause, Pixel colour) { 224 | foreach (var item in sym) { 225 | ScrollBitmapInFromRight((ulong)item, pause, colour); 226 | } 227 | } 228 | 229 | public void ScrollSymbolInFromLeft(Symbols[] sym, int pause, Pixel colour) { 230 | foreach (var item in sym) { 231 | ScrollBitmapInFromLeft((ulong)item, pause, colour); 232 | } 233 | } 234 | 235 | public void ScrollSymbolInFromRight(Symbols[] sym, int pause, Pixel[] colourPalette) { 236 | ushort cycleColour = 0; 237 | foreach (var item in sym) { 238 | ScrollBitmapInFromRight((ulong)item, pause, colourPalette[cycleColour % colourPalette.Length]); 239 | cycleColour++; 240 | } 241 | } 242 | 243 | public void ScrollSymbolInFromLeft(Symbols[] sym, int pause, Pixel[] colourPalette) { 244 | ushort cycleColour = 0; 245 | foreach (var item in sym) { 246 | ScrollBitmapInFromLeft((ulong)item, pause, colourPalette[cycleColour % colourPalette.Length]); 247 | cycleColour++; 248 | } 249 | } 250 | 251 | #endregion 252 | 253 | #region Scroll Bitmaps left and right 254 | 255 | public virtual void ScrollBitmapInFromRight(ulong bitmap, int pause, Pixel colour) { 256 | int pos = 0; 257 | ulong mask; 258 | bool pixelFound = false; 259 | 260 | // space character ? 261 | if (bitmap == 0) 262 | { 263 | DrawShiftLeft(pause); 264 | DrawShiftLeft(pause); 265 | return; 266 | } 267 | 268 | // fetch vertical slice of character font 269 | for (int col = 0; col < ColumnsPerPanel; col++) { 270 | pixelFound = false; 271 | 272 | for (int row = 0; row < RowsPerPanel; row++) { 273 | mask = 1UL << row * ColumnsPerPanel + col; 274 | pos = ColumnsPerPanel + (row * ColumnsPerPanel) - 1; 275 | 276 | if ((bitmap & mask) != 0) { 277 | FrameSet(colour, (int)pos, (int)(NumberOfPanels - 1)); 278 | pixelFound = true; 279 | } 280 | } 281 | if (pixelFound) { 282 | DrawShiftLeft(pause); 283 | } 284 | } 285 | //blank character space 286 | DrawShiftLeft(pause); 287 | } 288 | 289 | private void DrawShiftLeft(int pause) 290 | { 291 | if (pause > 0) { 292 | FrameDraw(); 293 | Util.Delay(pause); 294 | } 295 | FrameShiftLeft(); 296 | } 297 | 298 | public virtual void ScrollBitmapInFromLeft(ulong bitmap, int pause, Pixel colour) { 299 | int pos = 0; 300 | ulong mask; 301 | bool pixelFound = false; 302 | 303 | 304 | // space character ? 305 | if (bitmap == 0) 306 | { 307 | DrawShiftRight(pause); 308 | DrawShiftRight(pause); 309 | return; 310 | } 311 | 312 | // fetch vertical slice of character font 313 | for (int col = (int)ColumnsPerPanel - 1; col >= 0; col--) { 314 | pixelFound = false; 315 | 316 | for (int row = 0; row < RowsPerPanel; row++) { 317 | mask = 1UL << row * ColumnsPerPanel + col; 318 | pos = (int)ColumnsPerPanel * row; 319 | 320 | if ((bitmap & mask) != 0) { 321 | FrameSet(colour, pos, 0); 322 | pixelFound = true; 323 | } 324 | } 325 | if (pixelFound) { 326 | DrawShiftRight(pause); 327 | } 328 | } 329 | //blank character space 330 | DrawShiftRight(pause); 331 | } 332 | 333 | private void DrawShiftRight(int pause) 334 | { 335 | if (pause > 0) 336 | { 337 | FrameDraw(); 338 | Util.Delay(pause); 339 | } 340 | FrameShiftRight(); 341 | } 342 | 343 | #endregion 344 | 345 | #region Draw Primatives 346 | 347 | 348 | public void DrawString(string characters, int pause, int panel = 0) { 349 | DrawString(characters, Led.On, pause, panel); 350 | } 351 | 352 | public void DrawString(string characters, Pixel colour, int pause, int panel = 0) { 353 | DrawString(characters, new Pixel[] { colour }, pause, panel); 354 | } 355 | 356 | public void DrawString(string characters, Pixel[] colour, int pause, int panel = 0) { 357 | ushort cycleColour = 0; 358 | char c; 359 | for (int i = 0; i < characters.Length; i++) { 360 | c = characters.Substring(i, 1)[0]; 361 | if (c >= ' ' && c <= 'z') { 362 | DrawLetter(c, colour[cycleColour % colour.Length], panel); 363 | FrameDraw(); 364 | Util.Delay(pause); 365 | cycleColour++; 366 | } 367 | } 368 | } 369 | 370 | public void DrawLetter(char character, int panel = 0) { 371 | DrawLetter(character, Led.On, panel); 372 | } 373 | 374 | public void DrawLetter(char character, Pixel colour, int panel = 0) { 375 | ulong letter = 0; 376 | 377 | if (character >= ' ' && character <= 'z') { 378 | //calc ascii offset 379 | byte charValue = (byte)(character - 32); 380 | letter = fontSimple[charValue]; 381 | } 382 | else { return; } 383 | 384 | DrawBitmap(letter, colour, panel); 385 | } 386 | 387 | public void DrawSymbol(Symbols[] sym, Pixel[] colour, int pause, int panel = 0) { 388 | ushort cycleColour = 0; 389 | foreach (var item in sym) { 390 | DrawBitmap((ulong)item, colour[cycleColour], panel); 391 | FrameDraw(); 392 | Util.Delay(pause); 393 | cycleColour++; 394 | } 395 | } 396 | 397 | public void DrawSymbol(Symbols sym, int panel = 0) { 398 | DrawBitmap((ulong)sym, Led.On, panel); 399 | } 400 | 401 | public void DrawSymbol(Symbols sym, Pixel colour, int panel = 0) { 402 | DrawBitmap((ulong)sym, colour, panel); 403 | } 404 | 405 | public virtual void DrawBitmap(ulong bitmap, Pixel colour, int panel = 0) { 406 | ulong mask; 407 | if (panel < 0 || panel >= NumberOfPanels) { return; } 408 | 409 | for (int pos = 0; pos < PixelsPerPanel; pos++) { 410 | 411 | mask = (ulong)1 << (int)pos; 412 | if ((bitmap & mask) == 0) { 413 | FrameSet(Colour.Black, (int)pos, panel); 414 | } 415 | else { 416 | FrameSet(colour, (int)pos, panel); 417 | } 418 | } 419 | } 420 | #endregion 421 | } 422 | } 423 | -------------------------------------------------------------------------------- /Glovebox.Graphics/Grid/GridBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Glovebox.Graphics.Grid { 4 | 5 | /// 6 | /// Grid Privatives, builds on Frame Primatives 7 | /// 8 | public class GridBase : FrameBase { 9 | public readonly int ColumnsPerPanel; 10 | public readonly int RowsPerPanel; 11 | public readonly int PixelsPerPanel; 12 | protected readonly int NumberOfPanels; 13 | public readonly int ColumnsPerFrame; 14 | public readonly int RowsPerFrame; 15 | 16 | 17 | 18 | public GridBase(int columnsPerPanel, int rowsPerPanel, int panelsPerFrame) 19 | : base(columnsPerPanel * rowsPerPanel * (panelsPerFrame = panelsPerFrame < 1 ? 1 : panelsPerFrame)) { 20 | 21 | if (columnsPerPanel < 0 || rowsPerPanel < 0 ) { 22 | throw new Exception("invalid columns, rows or panels specified"); 23 | } 24 | 25 | this.ColumnsPerPanel = columnsPerPanel; 26 | this.RowsPerPanel = rowsPerPanel; 27 | this.NumberOfPanels = panelsPerFrame; 28 | PixelsPerPanel = rowsPerPanel * columnsPerPanel; 29 | ColumnsPerFrame = columnsPerPanel * panelsPerFrame; 30 | RowsPerFrame = rowsPerPanel; // for now only support horizontal frame layout 31 | 32 | FrameClear(); 33 | } 34 | 35 | 36 | public ushort PointPostion(int row, int column) { 37 | if (row < 0 || column < 0) { return 0; } 38 | 39 | int currentPanel, rowOffset; 40 | 41 | column = (ushort)(column % ColumnsPerFrame); 42 | row = (ushort)(row % RowsPerPanel); 43 | 44 | currentPanel = column / ColumnsPerPanel; 45 | rowOffset = (row * ColumnsPerPanel) + (currentPanel * PixelsPerPanel); 46 | 47 | return (ushort)((column % ColumnsPerPanel) + rowOffset); 48 | } 49 | 50 | public void PointColour(int row, int column, Pixel pixel) { 51 | if (row < 0 || column < 0) { return; } 52 | 53 | ushort pixelNumber = PointPostion(row, column); 54 | Frame[pixelNumber] = pixel; 55 | } 56 | 57 | public override void FrameSet(Pixel pixel, int position) { 58 | if (position < 0) { return; } 59 | 60 | int currentRow = position / (int)(NumberOfPanels * ColumnsPerPanel); 61 | int currentColumn = position % (int)(NumberOfPanels * ColumnsPerPanel); 62 | Frame[PointPostion(currentRow, currentColumn)] = pixel; 63 | } 64 | 65 | public new void FrameSet(Pixel pixel, int position, int panel) { 66 | int pos = panel * (int)PixelsPerPanel + position; 67 | if (pos < 0 || pos >= Length) { return; } 68 | Frame[pos] = pixel; 69 | } 70 | 71 | public void ColumnRollRight(int rowIndex) { 72 | if (rowIndex < 0) { return; } 73 | 74 | rowIndex = (ushort)(rowIndex % RowsPerPanel); 75 | 76 | Pixel temp = Frame[PointPostion(rowIndex, ColumnsPerFrame - 1)]; 77 | 78 | for (int col = (int)(ColumnsPerFrame - 1); col > 0; col--) { 79 | Frame[PointPostion(rowIndex, col)] = Frame[PointPostion(rowIndex, (col - 1))]; 80 | } 81 | 82 | Frame[PointPostion(rowIndex, 0)] = temp; 83 | } 84 | 85 | public void ColumnRollLeft(int rowIndex) { 86 | if (rowIndex < 0) { return; } 87 | 88 | rowIndex = rowIndex % RowsPerPanel; 89 | 90 | Pixel temp = Frame[PointPostion(rowIndex, 0)]; 91 | 92 | for (int col = 1; col < ColumnsPerFrame; col++) { 93 | Frame[PointPostion(rowIndex, col - 1)] = Frame[PointPostion(rowIndex, col)]; 94 | } 95 | 96 | Frame[PointPostion(rowIndex, ColumnsPerFrame - 1)] = temp; 97 | } 98 | 99 | public void FrameRollDown() { 100 | for (int i = 0; i < ColumnsPerFrame; i++) { 101 | ColumnRollDown(i); 102 | } 103 | } 104 | 105 | public void FrameRollUp() { 106 | for (int i = 0; i < ColumnsPerFrame; i++) { 107 | ColumnRollUp(i); 108 | } 109 | } 110 | 111 | public void FrameRollRight() { 112 | for (int row = 0; row < RowsPerPanel; row++) { 113 | ColumnRollRight(row); 114 | } 115 | } 116 | 117 | public void FrameRollLeft() { 118 | for (int row = 0; row < RowsPerPanel; row++) { 119 | ColumnRollLeft(row); 120 | } 121 | } 122 | 123 | public void ColumnRightShift(int rowIndex) { 124 | if (rowIndex < 0) { return; } 125 | 126 | rowIndex = (ushort)(rowIndex % RowsPerPanel); 127 | 128 | for (int col = (int)(ColumnsPerFrame - 1); col > 0; col--) { 129 | Frame[PointPostion(rowIndex, col)] = Frame[PointPostion(rowIndex, col - 1)]; 130 | } 131 | 132 | Frame[PointPostion(rowIndex, 0)] = Colour.Black; 133 | } 134 | 135 | 136 | public void FrameShiftRight() { 137 | for (int i = 0; i < RowsPerPanel; i++) { 138 | ColumnRightShift(i); 139 | } 140 | } 141 | 142 | public void FrameShiftLeft() { 143 | for (int i = 0; i < RowsPerPanel; i++) { 144 | ColumnShiftLeft(i); 145 | } 146 | } 147 | 148 | /// 149 | /// Panel aware scroll left 150 | /// 151 | /// 152 | public void ColumnShiftLeft(int rowIndex) { 153 | if (rowIndex < 0) { return; } 154 | 155 | int currentPanel, source = 0, destination, rowOffset, destinationColumn; 156 | 157 | rowIndex = rowIndex % RowsPerPanel; 158 | 159 | for (int sourceColumn = 1; sourceColumn < ColumnsPerFrame; sourceColumn++) { 160 | 161 | currentPanel = sourceColumn / ColumnsPerPanel; 162 | rowOffset = (rowIndex * ColumnsPerPanel) + (currentPanel * PixelsPerPanel); 163 | source = (sourceColumn % ColumnsPerPanel) + rowOffset; 164 | 165 | destinationColumn = sourceColumn - 1; 166 | currentPanel = (destinationColumn) / ColumnsPerPanel; 167 | rowOffset = (rowIndex * ColumnsPerPanel) + (currentPanel * PixelsPerPanel); 168 | destination = (destinationColumn % ColumnsPerPanel) + rowOffset; 169 | 170 | Frame[destination] = Frame[source]; 171 | } 172 | 173 | Frame[source] = Colour.Black; 174 | } 175 | 176 | public void ColumnRollDown(int columnIndex) { 177 | if (columnIndex < 0) { return; } 178 | 179 | columnIndex = (ushort)(columnIndex % ColumnsPerFrame); 180 | 181 | Pixel temp = Frame[PointPostion(RowsPerPanel - 1, columnIndex)]; 182 | 183 | for (int row = (int)RowsPerPanel - 2; row >= 0; row--) { 184 | Frame[PointPostion(row + 1, columnIndex)] = Frame[PointPostion(row, columnIndex)]; 185 | } 186 | 187 | Frame[PointPostion(0, columnIndex)] = temp; 188 | } 189 | 190 | public void ColumnRollUp(int columnIndex) { 191 | if (columnIndex < 0) { return; } 192 | 193 | columnIndex = (ushort)(columnIndex % ColumnsPerFrame); 194 | 195 | Pixel temp = Frame[PointPostion(0, columnIndex)]; 196 | 197 | for (int row = 1; row < RowsPerPanel ; row++) { 198 | Frame[PointPostion(row - 1, columnIndex)] = Frame[PointPostion(row, columnIndex)]; 199 | } 200 | 201 | Frame[PointPostion(RowsPerPanel - 1, columnIndex)] = temp; 202 | } 203 | 204 | public void RowDrawLine(int rowIndex, int startColumnIndex, int endColumnIndex) { 205 | RowDrawLine(rowIndex, startColumnIndex, endColumnIndex, Led.On); 206 | } 207 | 208 | public void RowDrawLine(int rowIndex, int startColumnIndex, int endColumnIndex, Pixel pixel) { 209 | if (rowIndex < 0 || startColumnIndex < 0 || endColumnIndex < 0) { return; } 210 | 211 | if (startColumnIndex > endColumnIndex) { 212 | int temp = startColumnIndex; 213 | startColumnIndex = endColumnIndex; 214 | endColumnIndex = temp; 215 | } 216 | 217 | for (int col = startColumnIndex; col <= endColumnIndex; col++) { 218 | Frame[PointPostion(rowIndex, col)] = pixel; 219 | } 220 | } 221 | 222 | public void RowDrawLine(int rowIndex) { 223 | RowDrawLine(rowIndex, Led.On); 224 | } 225 | 226 | public void RowDrawLine(int rowIndex, Pixel pixel) { 227 | if (rowIndex < 0) { return; } 228 | 229 | for (int panel = 0; panel < NumberOfPanels; panel++) { 230 | for (int i = (panel * PixelsPerPanel) + rowIndex * ColumnsPerPanel; i < (panel * PixelsPerPanel) + rowIndex * ColumnsPerPanel + (ColumnsPerPanel); i++) { 231 | Frame[i] = pixel; 232 | } 233 | } 234 | } 235 | 236 | public void RowDrawLine(int rowIndex, Pixel[] pixel) { 237 | if (rowIndex < 0) { return; } 238 | 239 | for (int panel = 0; panel < NumberOfPanels; panel++) { 240 | for (int i = (panel * PixelsPerPanel) + rowIndex * ColumnsPerPanel; i < (panel * PixelsPerPanel) + rowIndex * ColumnsPerPanel + (ColumnsPerPanel); i++) { 241 | Frame[i] = pixel[i % pixel.Length]; 242 | } 243 | } 244 | } 245 | 246 | public void ColumnDrawLine(int columnIndex) { 247 | ColumnDrawLine(columnIndex, Led.On); 248 | } 249 | 250 | public void ColumnDrawLine(int columnIndex, Pixel pixel) { 251 | if (columnIndex < 0) { return; } 252 | 253 | for (int r = 0; r < RowsPerPanel; r++) { 254 | Frame[PointPostion(r, columnIndex)] = pixel; 255 | } 256 | } 257 | 258 | public void ColumnDrawLine(int columnIndex, Pixel[] pixel) { 259 | if (columnIndex < 0) { return; } 260 | 261 | for (int r = 0; r < RowsPerPanel; r++) { 262 | Frame[PointPostion(r, columnIndex)] = pixel[r % pixel.Length]; 263 | } 264 | } 265 | 266 | public void DrawBox(int startRow, int startColumn, int width, int depth) { 267 | DrawBox(startRow, startColumn, width, depth, Led.On); 268 | } 269 | 270 | 271 | public void DrawBox(int startRow, int startColumn, int width, int depth, Pixel pixel) { 272 | if (startRow < 0 || startColumn < 0 || width <= 0 || depth <= 0) { return; } 273 | 274 | RowDrawLine(startRow, startColumn, startRow + width - 1); 275 | RowDrawLine(startRow + depth - 1, startColumn, startRow + width - 1); 276 | for (int d = 1; d < depth - 1; d++) { 277 | Frame[PointPostion(startRow + d, startColumn)] = pixel; 278 | Frame[PointPostion(startRow + d, startColumn + width - 1)] = pixel; 279 | } 280 | } 281 | } 282 | } 283 | -------------------------------------------------------------------------------- /Glovebox.Graphics/Nuget/CreateNugetPackage.bat: -------------------------------------------------------------------------------- 1 | rem automate nuget process 2 | 3 | mkdir lib\uap10.0 4 | copy ..\bin\release\Glovebox.Graphics.dll lib\uap10.0 /y 5 | del *.nupkg 6 | \data\software\nuget\nuget pack Glovebox.Graphics.dll.nuspec 7 | del lib\uap10.0\*.* /q 8 | rmdir lib /s /q 9 | 10 | rem \data\software\nuget\nuget setApiKey your key 11 | rem \data\software\nuget\nuget push Glovebox.Graphics.1.0.7.nupkg 12 | 13 | -------------------------------------------------------------------------------- /Glovebox.Graphics/Nuget/Glovebox.Graphics.dll.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Glovebox.Graphics 5 | 1.0.8 6 | Dave Glover 7 | Windows 10 for Iot LED Matrix Graphics Library 8 | Dave Glover 9 | https://github.com/gloveboxes/Windows-10-for-IoT-Graphics-Library-for-LED-Matrices 10 | false 11 | This project makes it really easy to add LED Matrix graphics to your Windows 10 for IoT project running on Raspberry Pi 2 or the Minnow Max Board. 12 | 13 | The main graphics library includes a font set, symbols and support for drawing lines, boxes, dots plus support for scrolling text across multiple display panels for form a larger frame. 14 | 15 | The library includes three LED Matrix drivers and the library is designed to be extensible making it easy to add new LED drivers. 16 | 17 | The MAX7219 LED driver supports chaining and rotation of multiple LED Matrix display panels together over a single SPI line. These modules are cheap, readily available and a chain of four panels can be purchased on eBay for about $US6. 18 | 19 | The HT16K33 I2C driver supports two implementations. The Adafruit Mini 8x8 LED Matrix with I2C Backpack, and the Adafruit Bicolor LED Square Pixel Matrix with I2C Backpack. These can be chained and rotated together but each display panel must have a unique I2C address. 20 | 21 | Documentation: https://github.com/gloveboxes/Windows-10-for-IoT-Graphics-Library-for-LED-Matrices/blob/master/README.md 22 | 23 | Video: Taking photos and movies of LED matrices is difficult so hence I've dropped the light levels. There are 3 separate groups of LEDs running running on their own thread/task. 5 x MAX7219 chained LED 8x8 Matrices, 2 chained x Adafruit Mini 8x8 LED Matrices and 1 x Adafruit BiColor 8x8 LED Matrix. 24 | 25 | https://www.youtube.com/watch?v=EX7c_FDy1eA 26 | 27 | 28 | This project makes it really easy to add LED Matrix graphics to your Windows 10 for IoT project running on Raspberry Pi 2 or the Minnow Max Board. 29 | 30 | The main graphics library includes a font set, symbols and support for drawing lines, boxes, dots plus support for scrolling text across multiple display panels for form a larger frame. 31 | 32 | The library includes three LED Matrix drivers and the library is designed to be extensible making it easy to add new LED drivers. 33 | 34 | The MAX7219 LED driver supports chaining and rotation of multiple LED Matrix display panels together over a single SPI line. These modules are cheap, readily available and a chain of four panels can be purchased on eBay for about $US6. 35 | 36 | The HT16K33 I2C driver supports two implementations. The Adafruit Mini 8x8 LED Matrix with I2C Backpack, and the Adafruit Bicolor LED Square Pixel Matrix with I2C Backpack. These can be chained and rotated together but each display panel must have a unique I2C address. 37 | 38 | 39 | 40 | Update Log 41 | 1.0.8: Nuget packaging issue 42 | 1.0.7: Added horizontal flip transform to Max7219 driver. Added zero pause no framedraw to scroll string operators. 43 | 1.0.6: Fixed bug in ht16k33 driver null constructor issue 44 | 1.0.5: Pixel.Mono class renamed to Pixel.Led 45 | 46 | Future support 47 | 48 | I2C backpack for HD44780-compatible LCD modules 49 | - 16 x 2 LCD and 20 x 4 LCD Displays 50 | 51 | https://ngtq4a.bn1303.df.livefilestore.com/y3pnCkvgPns1m9j_6Y9YVBFqpWFB5jRwa75Eq740p3nRMNkQ5bCULFMV7R8ofEicQzloMzgZfYIZ5pYC_Vjy2Qb7XFD6UzKMWbq1GdidqzTcSBfHLqd1xBRo3lBp_ZcPQe-ICiLyaK_1Nt9GdFlUi3FdNIUPCa-2BaF0zEKed_7lSI/LEDMatrixNuget.JPG 52 | Copyright 2015 53 | IoT Windows10 Raspberry Minnowboard LED MATRIX MAX7219 HT16K33 Adafruit 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /Glovebox.Graphics/Pixel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | /// This code is provided as-is, without any warrenty, so use it at your own risk. 4 | /// You can freely use and modify this code. 5 | namespace Glovebox.Graphics { 6 | 7 | /// 8 | /// From http://www.w3schools.com/HTML/html_colornames.asp 9 | /// 10 | public enum PixelColour { 11 | White, 12 | Black, 13 | Red, 14 | Orange, 15 | Yellow, 16 | Green, 17 | Purple, 18 | Blue, 19 | } 20 | 21 | public static class Led { 22 | public static Pixel On = new Pixel((byte)0xFF, (byte)0x00, (byte)0x00); 23 | public static Pixel Off = new Pixel((byte)0x00, (byte)0x00, (byte)0x00); 24 | } 25 | 26 | public static class BiColour { 27 | public static Pixel Red = new Pixel((byte)0xFF, (byte)0x00, (byte)0x00); 28 | public static Pixel Green = new Pixel((byte)0x00, (byte)0xFF, (byte)0x00); 29 | public static Pixel Yellow = new Pixel((byte)0xFF, (byte)0xFF, (byte)0x00); 30 | } 31 | 32 | public static class Colour { 33 | public static Pixel White = new Pixel((byte)0xFF, (byte)0xFF, (byte)0xFF); 34 | public static Pixel Black = new Pixel((byte)0x00, (byte)0x00, (byte)0x00); 35 | 36 | public static Pixel Red = new Pixel((byte)0xFF, (byte)0x00, (byte)0x00); 37 | public static Pixel Orange = new Pixel((byte)0xFF, (byte)0xA5, (byte)0x00); 38 | public static Pixel Yellow = new Pixel((byte)0xFF, (byte)0xFF, (byte)0x00); 39 | public static Pixel Green = new Pixel((byte)0x00, (byte)0x80, (byte)0x00); 40 | public static Pixel Purple = new Pixel((byte)0x80, (byte)0x00, (byte)0x80); 41 | public static Pixel Blue = new Pixel((byte)0x00, (byte)0x00, (byte)0xFF); 42 | 43 | public static Pixel CoolRed = new Pixel(0x020000); 44 | public static Pixel CoolOrange = new Pixel(0x040200); 45 | public static Pixel CoolYellow = new Pixel(0x020200); 46 | public static Pixel CoolGreen = new Pixel(0x000200); 47 | public static Pixel CoolBlue = new Pixel(0x000002); 48 | public static Pixel CoolPurple = new Pixel(0x020002); 49 | 50 | public static Pixel WarmRed = new Pixel(0x080000); 51 | public static Pixel WarmOrange = new Pixel(0x080400); 52 | public static Pixel WarmYellow = new Pixel(0x090900); 53 | public static Pixel WarmGreen = new Pixel(0x000800); 54 | public static Pixel WarmBlue = new Pixel(0x000008); 55 | public static Pixel WarmPurple = new Pixel(0x080008); 56 | 57 | public static Pixel HotRed = new Pixel(0x160000); 58 | public static Pixel HotOrange = new Pixel(0x160800); 59 | public static Pixel HotYellow = new Pixel(0x161600); 60 | public static Pixel HotGreen = new Pixel(0x001600); 61 | public static Pixel HotBlue = new Pixel(0x000016); 62 | public static Pixel HotPurple = new Pixel(0x160016); 63 | } 64 | 65 | 66 | /// 67 | /// Class representing one pixel
68 | /// Highly inspired by frank26080115's NeoPixel class on NeoPixel-on-NetduinoPlus2 @ github 69 | ///
70 | public class Pixel { 71 | 72 | public int ColourValue { 73 | get { 74 | return this.Red << 16 | this.Green << 8 | this.Blue; 75 | } 76 | } 77 | 78 | /// 79 | /// Green, 0 to 255 80 | /// 81 | public byte Green { 82 | get; 83 | set; 84 | } 85 | 86 | /// 87 | /// Red, 0 to 255 88 | /// 89 | public byte Red { 90 | get; 91 | set; 92 | } 93 | 94 | /// 95 | /// Blue, 0 to 255 96 | /// 97 | public byte Blue { 98 | get; 99 | set; 100 | } 101 | 102 | /// 103 | /// Creates a new pixel, black 104 | /// 105 | public Pixel() 106 | : this((byte)0, (byte)0, (byte)0) { 107 | } 108 | 109 | /// 110 | /// Creates a new pixel with given color 111 | /// 112 | /// Initial red, 0 to 255 113 | /// Initial green, 0 to 255 114 | /// Initial blue, 0 to 255 115 | public Pixel(byte r, byte g, byte b) { 116 | this.Green = g; 117 | this.Red = r; 118 | this.Blue = b; 119 | } 120 | 121 | /// 122 | /// Creates a new pixel with given color 123 | /// 124 | /// Initial red, 0 to 255 125 | /// Initial green, 0 to 255 126 | /// Initial blue, 0 to 255 127 | public Pixel(int r, int g, int b) { 128 | this.Green = (byte)g; 129 | this.Red = (byte)r; 130 | this.Blue = (byte)b; 131 | } 132 | 133 | /// 134 | /// Creates a new pixel with given ARGB color, where A is ignored 135 | /// 136 | /// ARGB color value 137 | public Pixel(int argb) { 138 | this.Blue = (byte)argb; 139 | this.Green = (byte)(argb >> 8); 140 | this.Red = (byte)(argb >> 16); 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /Glovebox.Graphics/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Windows 10 for Iot LED Matrix Graphics Library")] 9 | [assembly: AssemblyDescription("Windows 10 for IoT LED Matrix Graphics Library to draw, scroll and control text or symbols on multiple 8x8 LED Matrices. Supports HT16K33 & MAX7219 LED Driver chips")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Dave Glover")] 12 | [assembly: AssemblyProduct("LED Matrix Graphics Library")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Version information for an assembly consists of the following four values: 18 | // 19 | // Major Version 20 | // Minor Version 21 | // Build Number 22 | // Revision 23 | // 24 | // You can specify all the values or you can default the Build and Revision Numbers 25 | // by using the '*' as shown below: 26 | // [assembly: AssemblyVersion("1.0.*")] 27 | [assembly: AssemblyVersion("1.0.0.4")] 28 | [assembly: AssemblyFileVersion("1.0.0.4")] 29 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /Glovebox.Graphics/Properties/LightLibrary.rd.xml: -------------------------------------------------------------------------------- 1 | 2 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /Glovebox.Graphics/SevenSegmentDisplay/SevenSegmentDisplayBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Glovebox.Graphics.SevenSegmentDisplay { 4 | public class SevenSegmentDisplayBase { 5 | int panelsPerFrame = 0; 6 | ulong[] frame; 7 | 8 | static object deviceLock = new object(); 9 | 10 | // https://www.bing.com/images/search?q=seven+segment+font&view=detailv2&id=E5B74669E8DEB7C3B01D5FEDB712861418895F3E&selectedindex=3&ccid=GPOmWJAJ&simid=608030661155621312&thid=OIP.M18f3a6589009a3a91c841f33b0078937o0&mode=overlay&first=1 11 | 12 | 13 | #region font 14 | 15 | /* 16 | Seven Segment Display Bitmap 17 | 18 | |-64--| 19 | 2 32 20 | |--1--| 21 | 4 16 22 | |--8--|.128 23 | */ 24 | 25 | public enum Symbols : byte { 26 | degrees = 99, 27 | } 28 | 29 | 30 | 31 | 32 | public byte[] Alphanumeric = new byte[] 33 | { 34 | 0, // space 35 | 0, // ! 36 | 0, // " 37 | 0, // # 38 | 0, // $ 39 | 0, // % 40 | 0, // & 41 | 0, // ' 42 | 0, // ( 43 | 0, // ) 44 | 0, // * 45 | 0, // + 46 | 0, // , 47 | 48 | 1, // - 49 | 128, // . 50 | 0, // blank 51 | 126, // 0 52 | 48, // 1 53 | 109, // 2 54 | 121, // 3 55 | 51, // 4 56 | 91, // 5 57 | 95, // 6 58 | 112, // 7 59 | 127, // 8 60 | 115, // 9 61 | 62 | 0, // : 63 | 0, // ; 64 | 0, // < 65 | 0, // = 66 | 0, // > 67 | 0, // ? 68 | 0, // @ 69 | 70 | 119, // a 71 | 31, // b 72 | 78, // c 73 | 61, // d 74 | 79, // e 75 | 71, // f 76 | 123, // g 77 | 23, // h 78 | 6, // i 79 | 60, // j 80 | 55, // k 81 | 14, // l 82 | 84, // m 83 | 21, // n 84 | 126, // o 85 | 103, // p 86 | 115, // q 87 | 5, // r 88 | 91, // s 89 | 15, // t 90 | 62, // u 91 | 28, // v 92 | 42, // w 93 | 55, // x 94 | 59, // y 95 | 109 // z 96 | }; 97 | 98 | #endregion font 99 | 100 | 101 | public SevenSegmentDisplayBase(string name, int panelsPerFrame) { 102 | if (panelsPerFrame < 1) { throw new Exception("Number of panels must be greater than zero"); } 103 | this.panelsPerFrame = panelsPerFrame; 104 | frame = new ulong[this.panelsPerFrame]; 105 | } 106 | 107 | public void DrawString(int number, int panel = 0) { 108 | DrawString(number.ToString(), panel); 109 | } 110 | 111 | public void DrawString(string data, int panel = 0) { 112 | lock (deviceLock) { 113 | string characters = data.ToUpper(); 114 | char c; 115 | 116 | if (panel < 0 || panel >= panelsPerFrame) { return; } 117 | 118 | frame[panel] = 0; 119 | 120 | for (int i = 0; i < characters.Length; i++) { 121 | c = characters.Substring(i, 1)[0]; 122 | if (c >= ' ' && c <= 'Z') { 123 | if (c == '.') { frame[panel] += 128; } 124 | else { 125 | if (i > 0) { frame[panel] <<= 8; } 126 | frame[panel] += Alphanumeric[c - 32]; 127 | } 128 | } 129 | } 130 | } 131 | } 132 | 133 | public void FrameClear() { 134 | lock (deviceLock) { 135 | for (int i = 0; i < frame.Length; i++) { 136 | frame[i] = 0; 137 | } 138 | } 139 | } 140 | 141 | public void FrameDraw() { 142 | lock (deviceLock) { 143 | FrameDraw(frame); 144 | } 145 | } 146 | 147 | protected virtual void FrameDraw(ulong[] frame) { } 148 | 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /Glovebox.Graphics/Util.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace Glovebox.Graphics { 4 | static class Util { 5 | static public void Delay(int milliseconds) { 6 | Task.Delay(milliseconds).Wait(); 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Glovebox.Graphics/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0" 4 | }, 5 | "frameworks": { 6 | "uap10.0": {} 7 | }, 8 | "runtimes": { 9 | "win10-arm": {}, 10 | "win10-arm-aot": {}, 11 | "win10-x86": {}, 12 | "win10-x86-aot": {}, 13 | "win10-x64": {}, 14 | "win10-x64-aot": {} 15 | } 16 | } -------------------------------------------------------------------------------- /HelloWorld/Assets/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloveboxes/Windows-IoT-Core-Graphics-Library/5ca0d0a85950fdb729678b82eb7518bde7ef7c54/HelloWorld/Assets/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /HelloWorld/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloveboxes/Windows-IoT-Core-Graphics-Library/5ca0d0a85950fdb729678b82eb7518bde7ef7c54/HelloWorld/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /HelloWorld/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloveboxes/Windows-IoT-Core-Graphics-Library/5ca0d0a85950fdb729678b82eb7518bde7ef7c54/HelloWorld/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /HelloWorld/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloveboxes/Windows-IoT-Core-Graphics-Library/5ca0d0a85950fdb729678b82eb7518bde7ef7c54/HelloWorld/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /HelloWorld/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloveboxes/Windows-IoT-Core-Graphics-Library/5ca0d0a85950fdb729678b82eb7518bde7ef7c54/HelloWorld/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /HelloWorld/Assets/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloveboxes/Windows-IoT-Core-Graphics-Library/5ca0d0a85950fdb729678b82eb7518bde7ef7c54/HelloWorld/Assets/StoreLogo.png -------------------------------------------------------------------------------- /HelloWorld/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloveboxes/Windows-IoT-Core-Graphics-Library/5ca0d0a85950fdb729678b82eb7518bde7ef7c54/HelloWorld/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /HelloWorld/LED Matrix HelloWorld Sample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x86 7 | {18B2C975-9740-47AC-9343-0C7F33CE5578} 8 | winmdobj 9 | Properties 10 | HelloWorld 11 | HelloWorld 12 | en-US 13 | UAP 14 | 10.0.10240.0 15 | 10.0.10240.0 16 | 14 17 | true 18 | 512 19 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 20 | false 21 | LED Matrix HelloWorld Sample_TemporaryKey.pfx 22 | true 23 | true 24 | 948DFE7CBA4AA662C2B05F9348E7EC88F8E09D44 25 | 26 | 27 | true 28 | bin\ARM\Debug\ 29 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 30 | ;2008 31 | full 32 | ARM 33 | false 34 | prompt 35 | true 36 | 37 | 38 | bin\ARM\Release\ 39 | TRACE;NETFX_CORE;WINDOWS_UWP 40 | true 41 | ;2008 42 | pdbonly 43 | ARM 44 | false 45 | prompt 46 | true 47 | true 48 | 49 | 50 | true 51 | bin\x64\Debug\ 52 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 53 | ;2008 54 | full 55 | x64 56 | false 57 | prompt 58 | true 59 | 60 | 61 | bin\x64\Release\ 62 | TRACE;NETFX_CORE;WINDOWS_UWP 63 | true 64 | ;2008 65 | pdbonly 66 | x64 67 | false 68 | prompt 69 | true 70 | true 71 | 72 | 73 | true 74 | bin\x86\Debug\ 75 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 76 | ;2008 77 | full 78 | x86 79 | false 80 | prompt 81 | true 82 | 83 | 84 | bin\x86\Release\ 85 | TRACE;NETFX_CORE;WINDOWS_UWP 86 | true 87 | ;2008 88 | pdbonly 89 | x86 90 | false 91 | prompt 92 | true 93 | true 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | Designer 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | {6b7bcbab-4c1a-4e90-9f9b-31b233f90370} 122 | Glovebox.Graphics 123 | 124 | 125 | 126 | 14.0 127 | 128 | 129 | 136 | -------------------------------------------------------------------------------- /HelloWorld/LED Matrix HelloWorld Sample_TemporaryKey.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloveboxes/Windows-IoT-Core-Graphics-Library/5ca0d0a85950fdb729678b82eb7518bde7ef7c54/HelloWorld/LED Matrix HelloWorld Sample_TemporaryKey.pfx -------------------------------------------------------------------------------- /HelloWorld/Package.appxmanifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | HelloWorld 7 | dglov 8 | Assets\StoreLogo.png 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /HelloWorld/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("HelloWorld")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("HelloWorld")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Version information for an assembly consists of the following four values: 18 | // 19 | // Major Version 20 | // Minor Version 21 | // Build Number 22 | // Revision 23 | // 24 | // You can specify all the values or you can default the Build and Revision Numbers 25 | // by using the '*' as shown below: 26 | // [assembly: AssemblyVersion("1.0.*")] 27 | [assembly: AssemblyVersion("1.0.0.0")] 28 | [assembly: AssemblyFileVersion("1.0.0.0")] 29 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /HelloWorld/Properties/Default.rd.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /HelloWorld/StartupTask.cs: -------------------------------------------------------------------------------- 1 | using Glovebox.Graphics.Components; 2 | using Glovebox.Graphics.Drivers; 3 | using System; 4 | using System.Diagnostics; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Windows.ApplicationModel.Background; 8 | 9 | // The Background Application template is documented at http://go.microsoft.com/fwlink/?LinkID=533884&clcid=0x409 10 | 11 | namespace HelloWorld 12 | { 13 | public sealed class StartupTask : IBackgroundTask 14 | { 15 | BackgroundTaskDeferral _deferral; // for a headless Windows 10 for IoT projects you need to hold a deferral to keep the app active in the background 16 | 17 | public void Run(IBackgroundTaskInstance taskInstance) 18 | { 19 | _deferral = taskInstance.GetDeferral(); // get the deferral handle 20 | 21 | MAX7219 driver = new MAX7219(4, MAX7219.Rotate.None, MAX7219.Transform.HorizontalFlip, MAX7219.ChipSelect.CE0); // 4 panels, rotate 90 degrees, SPI CE0 22 | LED8x8Matrix matrix = new LED8x8Matrix(driver); // pass the driver to the LED8x8Matrix Graphics Library 23 | 24 | while (true) { 25 | matrix.ScrollStringInFromRight("Hello World 2015 ", 100); 26 | } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /HelloWorld/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "Glovebox.IoT.Devices": "1.0.15", 4 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0" 5 | }, 6 | "frameworks": { 7 | "uap10.0": {} 8 | }, 9 | "runtimes": { 10 | "win10-arm": {}, 11 | "win10-arm-aot": {}, 12 | "win10-x86": {}, 13 | "win10-x86-aot": {}, 14 | "win10-x64": {}, 15 | "win10-x64-aot": {} 16 | } 17 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Windows 10 IoT Core 2 | # LED Matrix Graphics Library 3 | 4 | Graphics Lib to draw, scroll & control text or symbols on multiple 8x8 LED Matrices and Seven Segment Displays (7-Segment Displays). Supports HT16K33, Ht16K33BiColor and the MAX7219 LED Matrix Driver chips 5 | 6 | This project makes it really easy to add graphics to your Windows 10 for IoT project running on Raspberry Pi 2 or the Minnow Max Board. 7 | 8 | The main graphics library includes a font set, symbols and support for drawing lines, boxes, dots plus support for scrolling text across multiple display panels for form a larger frame. 9 | 10 | The library includes three LED Matrix drivers and the library is designed to be extensible making it easy to add new LED drivers. 11 | 12 | The MAX7219 LED driver supports chaining and rotation of multiple LED Matrix display and Seven Segment Displays (7-Segment) panels together over a single SPI line. These modules are cheap, readily available and a chain of four panels can be purchased on eBay for about $US6. 13 | 14 | The HT16K33 I2C driver supports two implementations. The Adafruit Mini 8x8 LED Matrix with I2C Backpack, and the Adafruit Bicolor LED Square Pixel Matrix with I2C Backpack. These can be chained and rotated together but each display panel must have a unique I2C address. 15 | 16 | The [Glovebox.Graphics Library](https://www.nuget.org/packages/Glovebox.Graphics/) is also available on [NuGet](https://www.nuget.org/packages/Glovebox.Graphics/). 17 | 18 | 19 | 20 | #LED Maxtrix Hello World Example 21 | 22 | ![LED Matrix](https://sbczha.bn1303.df.livefilestore.com/y3mpc3ISdWObpqEMpcN3BsFkFwcdEKJlRK0Qq9egVAjVKpTJC7KQheIFToyvMNXeVbNFupPpZ-w1086QHVNpu3EQpKyyeJlPtyY56tRBgZUlVH2aHmGoz3Wzonpnt3U5tgX9eTsgP61QfAhMsKvF4CNoqlb4xfu1EsPYr4v3Abe0_e7xrJYoeblurDR2EJ-MoF8/MAX7219.jpg?psid=1) 23 | 24 | 25 | using Glovebox.Graphics.Components; 26 | using Glovebox.Graphics.Drivers; 27 | using Windows.ApplicationModel.Background; 28 | 29 | // The Background Application template is documented at https://go.microsoft.com/fwlink/?LinkID=533884&clcid=0x409&WT.mc_id=iot-0000-dglover 30 | 31 | namespace HelloWorld { 32 | public sealed class StartupTask : IBackgroundTask 33 | { 34 | BackgroundTaskDeferral _deferral; // for a headless Windows 10 for IoT projects you need to hold a deferral to keep the app active in the background 35 | 36 | public void Run(IBackgroundTaskInstance taskInstance) { 37 | _deferral = taskInstance.GetDeferral(); // request the deferral 38 | 39 | MAX7219 driver = new MAX7219(4, MAX7219.Rotate.D90, MAX7219.ChipSelect.CE0); // 4 panels, rotate 90 degrees, SPI CE0 40 | LED8x8Matrix matrix = new LED8x8Matrix(driver); // pass the driver to the LED8x8Matrix Graphics Library 41 | 42 | while (true) { 43 | matrix.ScrollStringInFromRight("Hello World 2015", 100); 44 | } 45 | } 46 | } 47 | } 48 | 49 | 50 | #Seven Segment Display Example 51 | 52 | ![Seven Segment Display (7-Segment Display)](https://q9aboa.bn1303.df.livefilestore.com/y3mxuEFjT3gJp0o14LQ_W1LZ_SMcPdpGnUqAJ_Vy2oRCF2wWF2Ufl2Po6269RXSV7EfAy3AsX9ttxau3hn3vt31Z1E5KLF1CugW9ZiCBIlQce9BB-Buo1w9hWIsdJ9LVS6xM2JzcSw2z_3MWCjqOK-GynUgjVzcfJZE2LP9V5mM_fY/SevenSegmentDisplay.jpg?psid=1) 53 | 54 | 55 | using Glovebox.Graphics.Components; 56 | using Glovebox.Graphics.Drivers; 57 | using Glovebox.IoT.Devices.Sensors; 58 | using System; 59 | using System.Text; 60 | using System.Threading.Tasks; 61 | using Windows.ApplicationModel.Background; 62 | 63 | namespace SevenSegmentDisplaySample { 64 | public sealed class StartupTask : IBackgroundTask { 65 | 66 | BackgroundTaskDeferral _deferral; // for a headless Windows 10 for IoT projects you need to hold a deferral to keep the app active in the background 67 | double temperature; 68 | bool blink = false; 69 | StringBuilder data = new StringBuilder(40); 70 | 71 | public void Run(IBackgroundTaskInstance taskInstance) { 72 | _deferral = taskInstance.GetDeferral(); // get the deferral handle 73 | 74 | int count = 0; 75 | 76 | MAX7219 driver = new MAX7219(2); 77 | SevenSegmentDisplay ssd = new SevenSegmentDisplay(driver); 78 | BMP180 bmp = new BMP180(BMP180.Mode.HIGHRES); 79 | 80 | ssd.FrameClear(); 81 | ssd.FrameDraw(); 82 | ssd.SetBrightness(4); 83 | 84 | while (true) { 85 | temperature = bmp.Temperature.DegreesCelsius; 86 | 87 | data.Clear(); 88 | 89 | // is temperature less than 3 digits and there is a decimal part too then right pad to 5 places as decimal point does not take up a digit space on the display 90 | if (temperature < 100 && temperature != (int)temperature) { data.Append($"{Math.Round(temperature, 1)}C".PadRight(5)); } 91 | else { data.Append($"{Math.Round(temperature, 0)}C".PadRight(4)); } 92 | 93 | data.Append(Math.Round(bmp.Pressure.Hectopascals, 0)); 94 | 95 | if (blink = !blink) { data.Append("."); } // add a blinking dot on bottom right as an I'm alive indicator 96 | 97 | ssd.DrawString(data.ToString()); 98 | 99 | ssd.DrawString(count++, 1); 100 | 101 | ssd.FrameDraw(); 102 | 103 | Task.Delay(2000).Wait(); 104 | } 105 | } 106 | } 107 | } 108 | 109 | 110 | 111 | 112 | 113 | Be sure to review the examples in the [Example Project](https://github.com/gloveboxes/Windows-10-for-IoT-Graphics-Library-for-LED-Matrices/tree/master/Examples) for more extensice samples 114 | 115 | 116 | [Raspberry Pi 2 Pin Mappings](https://ms-iot.github.io/content/en-US/win10/samples/PinMappingsRPi2.htm) 117 | 118 | 119 | [MinnowBoard Max Pin Mapings](https://ms-iot.github.io/content/en-US/win10/samples/PinMappingsMBM.htm) 120 | 121 | 122 | # LED Matrix Drivers 123 | 124 | ##MAX7219 SPI LED Driver 125 | 126 | MAX7219 based LED matrices are great, they are simple to chain together and they connect to the Raspberry Pi via either SPI channel. Oh, and best of all they are cheap. You can buy 4 chained 8x8 LED matrices for about $US6 off eBay. Now that's a lot of LEDs for not a lot of money! 127 | 128 | This LED Matrix can only display one colour, so there is a Led palette in the Pixel class. Led.On() and led.Off() to turn a pixel on or off. But actually you can use any Pixel colour you like other than Black to turn a pixel on. 129 | 130 | 131 | ![max7219 matrix](https://sbczha.bn1303.df.livefilestore.com/y3mBPvZ3ePYiIjkMI3MOS40jAN1bpx_bvQPimDDn0Cd3TCpw6VTxXyD_egqaVPJlAlMqcijna5eqv1_cOnATc79jntj9vbB5iy0xBE-v2usufAVJEePnxDvfu_-PFqYSYgLjXfU-LFNWKdCjw7nFppCMKi2T-EP1_ds1AKy6SCb3GY/MAX7219.jpg) 132 | 133 | ###Wiring 134 | 135 | 136 | GPIO pin-outs 137 | ------------- 138 | The breakout board has two headers to allow daisy-chaining. 139 | 140 | | Name | Remarks | RPi Pin | RPi Function | 141 | |:-----|:------------|--------:|-------------------| 142 | | VCC | +5V Power | 2 | 5V0 | 143 | | GND | Ground | 6 | GND | 144 | | DIN | Data In | 19 | GPIO 10 (MOSI) | 145 | | CS | Chip Select | 24 | GPIO 8 (SPI CE0) | 146 | | CLK | Clock | 23 | GPIO 11 (SPI CLK) | 147 | 148 | 149 | ###Examples 150 | 151 | MAX7219 driver = new MAX7219() // create new MAX7219 LED Matrix driver and take all the defaults 152 | 153 | MAX7219 driver = new MAX7219(4, MAX7219.Rotate.D90, MAX7219.ChipSelect.CE0); // 4 panels, rotate 90 degrees, SPI CE0 154 | 155 | ###Constructors 156 | 157 | Name|Description 158 | -----------------|--------------- 159 | MAX7219()|Defaults to 1 Display Panel, No rotation, SPI CE0, SPI Controller Name SPI0 160 | MAX7219(numOfPanels)| Number of chained Display Panels 161 | MAX7219(numOfPanels, rotate)| Number of chained Display Panels. Rotate each display panel none, 90 degrees, 180 degrees 162 | MAX7219(numOfPanels, rotate, chipSelect)| Number of chained Display Panels. Rotate each display panel none, 90 degrees, 180 degrees. SPI Chip Select CE0, CE1 163 | MAX7219(numOfPanels, rotate, chipSelect, SPIControllerName)| Number of chained Display Panels. Rotate each display panel none, 90 degrees, 180 degrees. SPI Chip Select CE0, CE1. SPIControllerName = SPI0 on Raspberry Pi and MinnowBoard Max 164 | 165 | 166 | 167 | 168 | ##Class Ht16K33 I2C LED Driver 169 | 170 | This Adafruit 8x8 LED Matrix is a great way to add status to your project. They are available in multiple colours, from Red, to Green, yellow, white and more. You can create a wide display panel using multiple of these LED Matrices and treat them as one panel. 171 | 172 | This LED Matrix can only display one colour, so there is a Mono colour palette in the Pixel class. Mono.On and Mono.Off to turn a pixel on or off. But actually you can use any Pixel colour you like other than Black to turn a pixel on. 173 | 174 | ![max7219 matrix](https://7ubhjw.bn1303.df.livefilestore.com/y3mL_dA7IxZA5dt2T_pBUgnZX48asZQ0qf3iBQwt8oTodsphnRHw9WzDF4SB38kEoffUzGIcaAOWQEcyWjMs0Ak9cfPsGQsnPVjZgr-iMSor4VYvjNlLHfRpCmysy92tIooOMlfFJYrX-_J1j1aefoIAuZPb0qAGd8zhx3f1W9-cQQ/adafruit-mini-8x8-led-matrix-w_i2c-backpack--_EXP-R15-264_1.jpg) 175 | 176 | ###Wiring 177 | 178 | 179 | GPIO pin-outs 180 | ------------- 181 | The breakout board has two headers to allow daisy-chaining. 182 | 183 | | Name | Remarks | RPi Pin | RPi Function | 184 | |:-----|:------------|--------:|-------------------| 185 | | VCC | +5V Power | 2 | 5V0 | 186 | | GND | Ground | 6 | GND | 187 | | SDA | Serial Data Line | 3 | I2C1 SDA | 188 | | SCL | Serial Clock Line | 5 | I2C1 SCL | 189 | 190 | ###Examples 191 | 192 | Ht16K33 driver = new Ht16K33(new byte[] { 0x70, 0x72 }, Ht16K33.Rotate.None); // pass in two I2C Addresses for the panels to be treated as one display panel 193 | 194 | Ht16K33 driver = new Ht16K33() // create new driver and take defaults - I2C Address 0x70 195 | 196 | 197 | ###Constructors 198 | 199 | Name|Description 200 | -----------------|--------------- 201 | Ht16K33()| Defaults: I2C Address = 0x70, Rotate = none, Display on, Brightness 2 (0-15), I2C Controller Name I2C1 202 | Ht16K33(new byte[] { 0x70 })|Collection of I2C Addresses. Specify if not using the default 0x70 address or you are chaining multiple I2C LED Matrices together in to one long display panel 203 | Ht16K33(new byte[] { 0x70 }, Ht16K33.Rotate.None)| Rotate none, 90 degress, 180 degress) 204 | Ht16K33(new byte[] { 0x70 }, Ht16K33.Rotate.None, LedDriver.Display.On)| Display on or off 205 | Ht16K33(new byte[] { 0x70 }, Ht16K33.Rotate.None, LedDriver.Display.On, 2)| Brightness 0-15 206 | Ht16K33(new byte[] { 0x70 }, Ht16K33.Rotate.None, LedDriver.Display.On, 2, LedDriver.BlinkRate.Off)| Blink off, slow, medium, fast 207 | Ht16K33(new byte[] { 0x70 }, Ht16K33.Rotate.None, LedDriver.Display.On, 2, LedDriver.BlinkRate.Off, "I2C1")| I2C Controller name: I2C1 for Raspberry Pi, I2C5 for MinnowBoard Max 208 | 209 | 210 | ##Class Ht16K33BiColor 211 | 212 | The [Adafruit Bicolor LED Square Pixel Matrix with I2C Backpack](https://www.adafruit.com/product/902) are a great way to add a little more colour to your projects. With two LEDS, a Red and a Green you can actually combine and create three colours. Red, Green and Yellow, nice. 213 | 214 | You can create a wide display panel using multiple of these LED Matrices and treat them as one panel. 215 | 216 | The Pixel class includes a three colour palette, BiColour.Red, BiColour.Green and BiColor.Yellow to control this baby. 217 | 218 | ![max7219 matrix](https://u2yg7a.bn1303.df.livefilestore.com/y3mV3LodjhGwAHTY0FXLAPj4_gcR3fGclexYgUvzBSnMknj95Ew9-rOGfg5RVmGPLhr0LUrys38LEB7fFIV_B6SuwGbyS_9yNv3ROkVDB1byNjbyCFO4vSLox6mFl9DJ-3fT8YvC4L2jIahZexVoGOeoOBkzFdOb5a0AbcHsz84QlI/adafruit-bicolor-led-square-pixel-matrix-with-i2c-backpack.jpg) 219 | 220 | ###Wiring 221 | 222 | 223 | GPIO pin-outs 224 | ------------- 225 | The breakout board has two headers to allow daisy-chaining. 226 | 227 | | Name | Remarks | RPi Pin | RPi Function | 228 | |:-----|:------------|--------:|-------------------| 229 | | VCC | +5V Power | 2 | 5V0 | 230 | | GND | Ground | 6 | GND | 231 | | SDA | Serial Data Line | 3 | I2C1 SDA | 232 | | SCL | Serial Clock Line | 5 | I2C1 SCL | 233 | 234 | 235 | ###Examples 236 | 237 | Ht16K33 driver = new Ht16K33(new byte[] { 0x70, 0x72 }, Ht16K33.Rotate.None); // pass in two I2C Addresses for the panels to be treated as one display panel 238 | 239 | Ht16K33 driver = new Ht16K33() // create new driver and take defaults - I2C Address 0x70 240 | 241 | ###Constructors 242 | 243 | Name|Description 244 | -----------------|--------------- 245 | Ht16K33BiColor()| Defaults: I2C Address = 0x70, Rotate = none, Display on, Brightness 2 (0-15), I2C Controller Name I2C1 246 | Ht16K33BiColor(new byte[] { 0x70 })|Collection of I2C Addresses. Specify if not using the default 0x70 address or you are chaining multiple I2C LED Matrices together in to one long display panel 247 | Ht16K33BiColor(new byte[] { 0x70 }, Ht16K33.Rotate.None)| Rotate none, 90 degress, 180 degress) 248 | Ht16K33BiColor(new byte[] { 0x70 }, Ht16K33.Rotate.None, LedDriver.Display.On)| Display on or off 249 | Ht16K33BiColor(new byte[] { 0x70 }, Ht16K33.Rotate.None, LedDriver.Display.On, 2)| Brightness 0-15 250 | Ht16K33BiColor(new byte[] { 0x70 }, Ht16K33.Rotate.None, LedDriver.Display.On, 2, LedDriver.BlinkRate.Off)| Blink off, slow, medium, fast 251 | Ht16K33BiColor(new byte[] { 0x70 }, Ht16K33.Rotate.None, LedDriver.Display.On, 2, LedDriver.BlinkRate.Off, "I2C1")| I2C Controller name: I2C1 for Raspberry Pi, I2C5 for MinnowBoard Max 252 | 253 | 254 | 255 | #LED Matrix Manager 256 | 257 | ##Class LED8x8Matrix 258 | 259 | ###Constructors 260 | 261 | Name|Description 262 | -----------------|--------------- 263 | LED8x8Matrix(driver)| Pass in a MAX7219 or Ht16K33 or Ht16K33BiColor LED Matrix driver. 264 | 265 | ###Examples 266 | 267 | LED8x8Matrix matrix = new LED8x8Matrix(new MAX7219()); // take the defaults for the MAX7219 LED Matrix driver 268 | 269 | 270 | MAX7219 driver = new MAX7219(4, MAX7219.Rotate.D90, MAX7219.ChipSelect.CE0); // 4 panels, rotate 90 degrees, SPI CE0 271 | LED8x8Matrix matrix = new LED8x8Matrix(driver); // pass the driver to the LED8x8Matrix Graphics Library 272 | 273 | 274 | ###Methods 275 | 276 | 277 | ### Row and Column Roll Operators 278 | 279 | * ColumnRollUp 280 | * ColumnRollDown 281 | * ColumnRollLeft 282 | * ColumnRollRight 283 | * ColumnShiftLeft 284 | * ColumnShiftRight 285 | 286 | ### Row and Column Line Draw Operators 287 | 288 | * ColumnDrawLine 289 | * RowDrawLine 290 | 291 | ### Frame Operators 292 | 293 | A Frame is multiple display panels treated as one display frame 294 | 295 | * FrameRollUp 296 | * FrameRollDown 297 | * FrameRollLeft 298 | * FrameRollRight 299 | * FrameShiftLeft 300 | * FrameShiftRight 301 | 302 | ### Draw Operators 303 | 304 | * DrawBitmap 305 | * DrawBox 306 | * DrawLetter 307 | * DrawString 308 | * DrawSymbol 309 | 310 | ###Scroll Operators 311 | 312 | * ScrollBitmapInFromLeft 313 | * ScrollBitmapInFromRight 314 | * ScrollCharacterFromLeft 315 | * ScrollCharacterFromRight 316 | * ScrollStringInFromLeft 317 | * ScrollStringInFromRight 318 | * ScrollSymbolInFromLeft 319 | * ScrollSymbolInFromRight 320 | 321 | ###Frame Privatives 322 | 323 | * FrameClear 324 | * FrameDraw 325 | 326 | ### Frame Set Primatives 327 | 328 | * FrameSet 329 | * FrameSetBlocks 330 | 331 | ###Shift Primatives 332 | 333 | * FrameShift 334 | * FrameShiftBack 335 | * FrameShiftForward 336 | 337 | ## Pixel Point Primatives 338 | 339 | * FramePixelForward 340 | * FramePixelSwap 341 | * PointColour 342 | * PointPostion 343 | 344 | ### Spin Primatives - Circular LED Strings 345 | * SpinColour 346 | * SpinColourOnBackground 347 | 348 | ### LED Control 349 | 350 | * SetBlinkRate 351 | * SetBrightness 352 | * SetFrameState 353 | 354 | ## Properties 355 | 356 | Property| Description 357 | --------|------------ 358 | ColumnsPerPanel | Number of columns per panel 359 | RowsPerPanel | Number of rows per panel 360 | PixelsPerPanel | Number of pixels per panel. ColumnsPerPanel x RowsPerPanel 361 | PanelsPerFrame | Multiple panels make up a frame 362 | ColumnsPerFrame | Total columns across a frame 363 | RowsPerFrame | Total rows down a frame 364 | Length | Total number of Pixels in the Frame. PixelsPerPanel x PanelsPerFrame 365 | 366 | -------------------------------------------------------------------------------- /Seven Segment Display Sample/Assets/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloveboxes/Windows-IoT-Core-Graphics-Library/5ca0d0a85950fdb729678b82eb7518bde7ef7c54/Seven Segment Display Sample/Assets/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /Seven Segment Display Sample/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloveboxes/Windows-IoT-Core-Graphics-Library/5ca0d0a85950fdb729678b82eb7518bde7ef7c54/Seven Segment Display Sample/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /Seven Segment Display Sample/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloveboxes/Windows-IoT-Core-Graphics-Library/5ca0d0a85950fdb729678b82eb7518bde7ef7c54/Seven Segment Display Sample/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /Seven Segment Display Sample/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloveboxes/Windows-IoT-Core-Graphics-Library/5ca0d0a85950fdb729678b82eb7518bde7ef7c54/Seven Segment Display Sample/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /Seven Segment Display Sample/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloveboxes/Windows-IoT-Core-Graphics-Library/5ca0d0a85950fdb729678b82eb7518bde7ef7c54/Seven Segment Display Sample/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /Seven Segment Display Sample/Assets/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloveboxes/Windows-IoT-Core-Graphics-Library/5ca0d0a85950fdb729678b82eb7518bde7ef7c54/Seven Segment Display Sample/Assets/StoreLogo.png -------------------------------------------------------------------------------- /Seven Segment Display Sample/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloveboxes/Windows-IoT-Core-Graphics-Library/5ca0d0a85950fdb729678b82eb7518bde7ef7c54/Seven Segment Display Sample/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /Seven Segment Display Sample/Package.appxmanifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Seven Segment Display Sample 7 | dglov 8 | Assets\StoreLogo.png 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Seven Segment Display Sample/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Seven Segment Display Sample")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Seven Segment Display Sample")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Version information for an assembly consists of the following four values: 18 | // 19 | // Major Version 20 | // Minor Version 21 | // Build Number 22 | // Revision 23 | // 24 | // You can specify all the values or you can default the Build and Revision Numbers 25 | // by using the '*' as shown below: 26 | // [assembly: AssemblyVersion("1.0.*")] 27 | [assembly: AssemblyVersion("1.0.0.0")] 28 | [assembly: AssemblyFileVersion("1.0.0.0")] 29 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /Seven Segment Display Sample/Properties/Default.rd.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Seven Segment Display Sample/Seven Segment Display Sample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x86 7 | {80A04812-AC5A-4FAF-8546-4DB9F9C92C95} 8 | winmdobj 9 | Properties 10 | SevenSegmentDisplaySample 11 | Seven Segment Display Sample 12 | en-US 13 | UAP 14 | 10.0.10586.0 15 | 10.0.10240.0 16 | 14 17 | true 18 | 512 19 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 20 | false 21 | Seven Segment Display Sample_TemporaryKey.pfx 22 | true 23 | true 24 | 25 | 26 | true 27 | bin\ARM\Debug\ 28 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 29 | ;2008 30 | full 31 | ARM 32 | false 33 | prompt 34 | true 35 | 36 | 37 | bin\ARM\Release\ 38 | TRACE;NETFX_CORE;WINDOWS_UWP 39 | true 40 | ;2008 41 | pdbonly 42 | ARM 43 | false 44 | prompt 45 | true 46 | true 47 | 48 | 49 | true 50 | bin\x64\Debug\ 51 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 52 | ;2008 53 | full 54 | x64 55 | false 56 | prompt 57 | true 58 | 59 | 60 | bin\x64\Release\ 61 | TRACE;NETFX_CORE;WINDOWS_UWP 62 | true 63 | ;2008 64 | pdbonly 65 | x64 66 | false 67 | prompt 68 | true 69 | true 70 | 71 | 72 | true 73 | bin\x86\Debug\ 74 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 75 | ;2008 76 | full 77 | x86 78 | false 79 | prompt 80 | true 81 | 82 | 83 | bin\x86\Release\ 84 | TRACE;NETFX_CORE;WINDOWS_UWP 85 | true 86 | ;2008 87 | pdbonly 88 | x86 89 | false 90 | prompt 91 | true 92 | true 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | Designer 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | false 119 | 120 | 121 | false 122 | 123 | 124 | false 125 | 126 | 127 | false 128 | 129 | 130 | false 131 | 132 | 133 | false 134 | 135 | 136 | false 137 | 138 | 139 | 140 | 141 | {6b7bcbab-4c1a-4e90-9f9b-31b233f90370} 142 | Glovebox.Graphics 143 | 144 | 145 | 146 | 14.0 147 | 148 | 149 | 156 | -------------------------------------------------------------------------------- /Seven Segment Display Sample/Seven Segment Display Sample_TemporaryKey.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloveboxes/Windows-IoT-Core-Graphics-Library/5ca0d0a85950fdb729678b82eb7518bde7ef7c54/Seven Segment Display Sample/Seven Segment Display Sample_TemporaryKey.pfx -------------------------------------------------------------------------------- /Seven Segment Display Sample/StartupTask.cs: -------------------------------------------------------------------------------- 1 | using Glovebox.Graphics.Components; 2 | using Glovebox.Graphics.Drivers; 3 | using Glovebox.IoT.Devices.Sensors; 4 | using System; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Windows.ApplicationModel.Background; 8 | 9 | namespace SevenSegmentDisplaySample { 10 | public sealed class StartupTask : IBackgroundTask { 11 | 12 | BackgroundTaskDeferral _deferral; // for a headless Windows 10 for IoT projects you need to hold a deferral to keep the app active in the background 13 | double temperature; 14 | bool blink = false; 15 | StringBuilder data = new StringBuilder(40); 16 | 17 | public void Run(IBackgroundTaskInstance taskInstance) { 18 | _deferral = taskInstance.GetDeferral(); // get the deferral handle 19 | 20 | int count = 0; 21 | 22 | MAX7219 driver = new MAX7219(2); 23 | SevenSegmentDisplay ssd = new SevenSegmentDisplay(driver); 24 | BMP180 bmp = new BMP180(BMP180.Mode.HIGHRES); 25 | 26 | ssd.FrameClear(); 27 | ssd.FrameDraw(); 28 | ssd.SetBrightness(4); 29 | 30 | while (true) { 31 | temperature = bmp.Temperature.DegreesCelsius; 32 | 33 | data.Clear(); 34 | 35 | // is temperature less than 3 digits and there is a decimal part too then right pad to 5 places as decimal point does not take up a digit space on the display 36 | if (temperature < 100 && temperature != (int)temperature) { data.Append($"{Math.Round(temperature, 1)}C".PadRight(5)); } 37 | else { data.Append($"{Math.Round(temperature, 0)}C".PadRight(4)); } 38 | 39 | data.Append(Math.Round(bmp.Pressure.Hectopascals, 0)); 40 | 41 | if (blink = !blink) { data.Append("."); } // add a blinking dot on bottom right as an I'm alive indicator 42 | 43 | ssd.DrawString(data.ToString()); 44 | 45 | ssd.DrawString(count++, 1); 46 | 47 | ssd.FrameDraw(); 48 | 49 | Task.Delay(2000).Wait(); 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Seven Segment Display Sample/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "Glovebox.IoT.Devices": "1.0.15", 4 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0" 5 | }, 6 | "frameworks": { 7 | "uap10.0": {} 8 | }, 9 | "runtimes": { 10 | "win10-arm": {}, 11 | "win10-arm-aot": {}, 12 | "win10-x86": {}, 13 | "win10-x86-aot": {}, 14 | "win10-x64": {}, 15 | "win10-x64-aot": {} 16 | } 17 | } --------------------------------------------------------------------------------