Jump to content

Recommended Posts

So I've been playing around with some RGB LEDs the last few days.  I found some really nifty software called Glediator which I can use to control my LEDs.  I thought it would be fun to build some sort of tool to build LED animations that would be compatible with the Glediator protocol / microcontroller code.  The biggest challenge I was having was how to deal with mapping the pixel data to a specific LED.  The LED Pixel data is fed to the microcontroller is Serial; so I had to bust out some math skills to "map" the serial pixel stream to the LEDs as they are arranged.  Most RGB LED displays are either parallel strips, a "zig-zag" pattern (probably not the best term), a combo of the two or a custom design.  For my purposes I'm dealing strictly with 2D grid style layouts. 

I wanted to come up with a dynamic way to create a virtual Pixel Grid that I could programmatically assign the pixel ordering to without hard coding the ordering.  Here is what I've come up with.  The math probably isn't great, but I'm not a math wiz and it was hard enough figuring this much out. ;P

In this demo I am simply creating 2D arrays of various sizes and assigning each element a "Pixel Index" to another array with the binary stream of pixel data (not in this script). The arrays can be ordered/assigned using 1 of 4 modes (Horizontal Strips, Vertical Strips, Horizontal ZigZag and Vertical ZigZag) and the Starting point (dubbed Zero Pixel) can be located any of the four "corners" (Top Left, Top Right, Bottom Left and Bottom Right).
 

#include <Array.au3>

Global Enum Step *2 $PIXEL_GRID_MODE_HORIZONTAL_STRIPS, $PIXEL_GRID_MODE_VERTICAL_STRIPS, $PIXEL_GRID_MODE_HORIZONTAL_ZIGZAG, $PIXEL_GRID_MODE_VERTICAL_ZIGZAG
Global Enum Step *2 $PIXEL_GRID_TOP_LEFT, $PIXEL_GRID_TOP_RIGHT, $PIXEL_GRID_BOTTOM_LEFT, $PIXEL_GRID_BOTTOM_RIGHT

Global Const $PIXEL_GRID_ORDER_HSTL = "($iX + 1) + ($iY * ($iCols + 1))-1"
Global Const $PIXEL_GRID_ORDER_HSTR = "Abs((($iCols + 1)*($iRows + 1))-($iY * ($iCols + 1))-(($iCols)-$iX)-(($iCols + 1)*($iRows + 1)))"
Global Const $PIXEL_GRID_ORDER_HSBL = "(($iCols + 1)*($iRows + 1))-($iY * ($iCols + 1))-(($iCols)-$iX)-1"
Global Const $PIXEL_GRID_ORDER_HSBR = "Abs(($iX + 1) + ($iY * ($iCols + 1)) - (($iCols + 1)*($iRows + 1))-1)-1"

Global Const $PIXEL_GRID_ORDER_VSTL = "($iY + 1) + ($iX * ($iRows + 1))-1"
Global Const $PIXEL_GRID_ORDER_VSTR = "(($iCols + 1)*($iRows + 1))-($iX * ($iRows + 1))-(($iRows)-$iY)-1"
Global Const $PIXEL_GRID_ORDER_VSBL = "Abs((($iCols + 1)*($iRows + 1))-($iX * ($iRows + 1))-(($iRows)-$iY)-(($iCols + 1)*($iRows + 1)))"
Global Const $PIXEL_GRID_ORDER_VSBR = "Abs(($iY + 1) + ($iX * ($iRows + 1)) - (($iCols + 1)*($iRows + 1))-1)-1"

Global Const $PIXEL_GRID_ORDER_HZTL = "(Mod($iY+1,2)=0) ? (" & $PIXEL_GRID_ORDER_HSTR & ") : (" & $PIXEL_GRID_ORDER_HSTL & ")"
Global Const $PIXEL_GRID_ORDER_HZTR = "(Mod($iY+1,2)=0) ? (" & $PIXEL_GRID_ORDER_HSTL & ") : (" & $PIXEL_GRID_ORDER_HSTR & ")"
Global Const $PIXEL_GRID_ORDER_HZBL = "(Mod($iY+1,2)=0) ? (" & $PIXEL_GRID_ORDER_HSBR & ") : (" & $PIXEL_GRID_ORDER_HSBL & ")"
Global Const $PIXEL_GRID_ORDER_HZBR = "(Mod($iY+1,2)=0) ? (" & $PIXEL_GRID_ORDER_HSBL & ") : (" & $PIXEL_GRID_ORDER_HSBR & ")"

Global Const $PIXEL_GRID_ORDER_VZTL = "(Mod($iX+1,2)=0) ? (" & $PIXEL_GRID_ORDER_VSBL & ") : (" & $PIXEL_GRID_ORDER_VSTL & ")"
Global Const $PIXEL_GRID_ORDER_VZTR = "(Mod($iCols+1,2)=0) ? ((Mod($iX+1,2)=0) ? (" & $PIXEL_GRID_ORDER_VSTR & ") : (" & $PIXEL_GRID_ORDER_VSBR & ")) : ((Mod($iX+1,2)=0) ? (" & $PIXEL_GRID_ORDER_VSBR & ") : (" & $PIXEL_GRID_ORDER_VSTR & "))"
Global Const $PIXEL_GRID_ORDER_VZBL = "(Mod($iX+1,2)=0) ? (" & $PIXEL_GRID_ORDER_VSTL & ") : (" & $PIXEL_GRID_ORDER_VSBL & ")"
Global Const $PIXEL_GRID_ORDER_VZBR = "(Mod($iCols+1,2)=0) ? ((Mod($iX+1,2)=0) ? (" & $PIXEL_GRID_ORDER_VSBR & ") : (" & $PIXEL_GRID_ORDER_VSTR & ")) : ((Mod($iX+1,2)=0) ? (" & $PIXEL_GRID_ORDER_VSTR & ") : (" & $PIXEL_GRID_ORDER_VSBR & "))"


Local $iWidth = 6
Local $iHeight = 9
$aPixelGrid = _PixelGrid_Create($iWidth, $iHeight, $PIXEL_GRID_MODE_HORIZONTAL_STRIPS, $PIXEL_GRID_TOP_LEFT)
_ArrayDisplay($aPixelGrid, "Horizontal Strips / Top Left")

$iWidth = 4
$iHeight = 5
$aPixelGrid = _PixelGrid_Create($iWidth, $iHeight, $PIXEL_GRID_MODE_VERTICAL_STRIPS, $PIXEL_GRID_BOTTOM_RIGHT)
_ArrayDisplay($aPixelGrid, "Vertical Strips / Bottom Right")

$iWidth = 6
$iHeight = 4
$aPixelGrid = _PixelGrid_Create($iWidth, $iHeight, $PIXEL_GRID_MODE_HORIZONTAL_ZIGZAG, $PIXEL_GRID_TOP_RIGHT)
_ArrayDisplay($aPixelGrid, "Horizontal ZigZag / Top Right")

$iWidth = 5
$iHeight = 5
$aPixelGrid = _PixelGrid_Create($iWidth, $iHeight, $PIXEL_GRID_MODE_VERTICAL_ZIGZAG, $PIXEL_GRID_BOTTOM_LEFT)
_ArrayDisplay($aPixelGrid, "Vertical ZigZag / Bottom Left")


Func _PixelGrid_Create($iCols = 0, $iRows = 0, $iMode = 0, $iZeroPixel = 0)
    If $iCols <= 0 Or $iRows <= 0 Then Return SetError(1, 0, 0) ;Verify Columns and Rows are >= 1
    If $iMode <= 0 Or $iZeroPixel <= 0 Then Return SetError(2, 0, 0) ;Verify Mode and ZeroPixel
    Local $aPixelGrid[$iRows][$iCols] ;Create Pixel Grid Array
    _PixelGrid_SetMode($aPixelGrid, $iMode, $iZeroPixel) ;Set Grid Numbering Based on Mode and Zero Pixel
    Return $aPixelGrid
EndFunc   ;==>_PixelGrid_Create

Func _PixelGrid_SetOrder(ByRef $aPixelGrid, $sFormula = "")
    If Not UBound($aPixelGrid, 2) Or Not $sFormula Then Return SetError(1, 0, 0) ;Simple Error Checking
    Local $iRows = UBound($aPixelGrid, 1) - 1 ;Collect Rows and Columns
    Local $iCols = UBound($aPixelGrid, 2) - 1
    For $iY = 0 To $iRows ;Loop Through Grid from Top Left to Bottom Right
        For $iX = 0 To $iCols
            $aPixelGrid[$iY][$iX] = Execute($sFormula) ;Use Order Formula to Assign Pixel Address
        Next
    Next
EndFunc   ;==>_PixelGrid_SetOrder

Func _PixelGrid_SetMode(ByRef $aPixelGrid, ByRef $iMode, ByRef $iZeroPixel)
    Switch $iMode
        Case $PIXEL_GRID_MODE_HORIZONTAL_STRIPS
            Switch $iZeroPixel
                Case $PIXEL_GRID_TOP_LEFT
                    _PixelGrid_SetOrder($aPixelGrid, $PIXEL_GRID_ORDER_HSTL)
                Case $PIXEL_GRID_BOTTOM_LEFT
                    _PixelGrid_SetOrder($aPixelGrid, $PIXEL_GRID_ORDER_HSBL)
                Case $PIXEL_GRID_TOP_RIGHT
                    _PixelGrid_SetOrder($aPixelGrid, $PIXEL_GRID_ORDER_HSTR)
                Case $PIXEL_GRID_BOTTOM_RIGHT
                    _PixelGrid_SetOrder($aPixelGrid, $PIXEL_GRID_ORDER_HSBR)
            EndSwitch
        Case $PIXEL_GRID_MODE_VERTICAL_STRIPS
            Switch $iZeroPixel
                Case $PIXEL_GRID_TOP_LEFT
                    _PixelGrid_SetOrder($aPixelGrid, $PIXEL_GRID_ORDER_VSTL)
                Case $PIXEL_GRID_BOTTOM_LEFT
                    _PixelGrid_SetOrder($aPixelGrid, $PIXEL_GRID_ORDER_VSBL)
                Case $PIXEL_GRID_TOP_RIGHT
                    _PixelGrid_SetOrder($aPixelGrid, $PIXEL_GRID_ORDER_VSTR)
                Case $PIXEL_GRID_BOTTOM_RIGHT
                    _PixelGrid_SetOrder($aPixelGrid, $PIXEL_GRID_ORDER_VSBR)
            EndSwitch
        Case $PIXEL_GRID_MODE_HORIZONTAL_ZIGZAG
            Switch $iZeroPixel
                Case $PIXEL_GRID_TOP_LEFT
                    _PixelGrid_SetOrder($aPixelGrid, $PIXEL_GRID_ORDER_HZTL)
                Case $PIXEL_GRID_BOTTOM_LEFT
                    _PixelGrid_SetOrder($aPixelGrid, $PIXEL_GRID_ORDER_HZBL)
                Case $PIXEL_GRID_TOP_RIGHT
                    _PixelGrid_SetOrder($aPixelGrid, $PIXEL_GRID_ORDER_HZTR)
                Case $PIXEL_GRID_BOTTOM_RIGHT
                    _PixelGrid_SetOrder($aPixelGrid, $PIXEL_GRID_ORDER_HZBR)
            EndSwitch
        Case $PIXEL_GRID_MODE_VERTICAL_ZIGZAG
            Switch $iZeroPixel
                Case $PIXEL_GRID_TOP_LEFT
                    _PixelGrid_SetOrder($aPixelGrid, $PIXEL_GRID_ORDER_VZTL)
                Case $PIXEL_GRID_BOTTOM_LEFT
                    _PixelGrid_SetOrder($aPixelGrid, $PIXEL_GRID_ORDER_VZBL)
                Case $PIXEL_GRID_TOP_RIGHT
                    _PixelGrid_SetOrder($aPixelGrid, $PIXEL_GRID_ORDER_VZTR)
                Case $PIXEL_GRID_BOTTOM_RIGHT
                    _PixelGrid_SetOrder($aPixelGrid, $PIXEL_GRID_ORDER_VZBR)
            EndSwitch
    EndSwitch
EndFunc   ;==>_PixelGrid_SetMode

Not only was this a fun, personal challenge, but it should integrate into the rest of my LED code nicely!  I hope others find this example interesting and perhaps useful and/or inspiring.

P.S.  I know there are endless way to "formulate" the ordering of the grid, by this is all I need for now.  As cool as diagonal zigzags, fills, spirals, etc. are,  I haven't seen any LED panels designed with those physical layouts...they would be very specialized...and probably pretty awesome too;  just not in the works for my needs.  I'll save those cool "orderings" for when I get actual pixel animations designed. ;)

Edited by spudw2k
Link to comment
Share on other sites

Pretty cool project, seems like an awesome thing to get to write some code for  :)

 

Ian

My projects:

  • IP Scanner - Multi-threaded ping tool to scan your available networks for used and available IP addresses, shows ping times, resolves IPs in to host names, and allows individual IPs to be pinged.
  • INFSniff - Great technicians tool - a tool which scans DriverPacks archives for INF files and parses out the HWIDs to a database file, and rapidly scans the local machine's HWIDs, searches the database for matches, and installs them.
  • PPK3 (Persistent Process Killer V3) - Another for the techs - suppress running processes that you need to keep away, helpful when fighting spyware/viruses.
  • Sync Tool - Folder sync tool with lots of real time information and several checking methods.
  • USMT Front End - Front End for Microsoft's User State Migration Tool, including all files needed for USMT 3.01 and 4.01, 32 bit and 64 bit versions.
  • Audit Tool - Computer audit tool to gather vital hardware, Windows, and Office information for IT managers and field techs. Capabilities include creating a customized site agent.
  • CSV Viewer - Displays CSV files with automatic column sizing and font selection. Lines can also be copied to the clipboard for data extraction.
  • MyDirStat - Lists number and size of files on a drive or specified path, allows for deletion within the app.
  • 2048 Game - My version of 2048, fun tile game.
  • Juice Lab - Ecigarette liquid making calculator.
  • Data Protector - Secure notes to save sensitive information.
  • VHD Footer - Add a footer to a forensic hard drive image to allow it to be mounted or used as a virtual machine hard drive.
  • Find in File - Searches files containing a specified phrase.
Link to comment
Share on other sites

Thanks.  What can I say...I like things that light up and change color. ;)

LEDkIT can be found here!

I'm working on a GUI tool to read and write frame sequences.  I'm not much of a graphic programming guy so I'll be struggling for a bit.  I used the _Grid UDF to get things rolling (proof of concept) but will have break down and draft me a GDI+ solution to improve performance.  Here's a screenshot of the GUi concept at this point.  If anyone can point me in the right direction or give me some tips on how I can dynamically create a grid with GDI+ real-time.

edit: updated GUi code.  Still WIP/POC, but working limited functionality to show the intent.  The _Grid UDF is an embarrassing workaround (no offense to that UDF, but pixel art is not what Input boxes are intended for *wink).  I'll get something GDI+ going eventually.  Hopefully sooner than later.

BTW.  In the demo, notice the colors look out of order.  That is because the pixel stream was generated on a "zigzag" screen (hint hint).  Thus demonstrates the main motivator I had that drove me to solve this problem. 

Edited by spudw2k
added GUi code for reference
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...