<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Photons, Electrons, and Dirt &#187; FPGA</title>
	<atom:link href="https://bikerglen.com/blog/category/fpga/feed/" rel="self" type="application/rss+xml" />
	<link>https://bikerglen.com/blog</link>
	<description>A blog by Glen Akins</description>
	<lastBuildDate>Sat, 22 Aug 2026 16:30:53 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.2.38</generator>
	<item>
		<title>Reverse Engineering the iColor Flex Protocol</title>
		<link>https://bikerglen.com/blog/reverse-engineering-the-icolor-flex-protocol/</link>
		<comments>https://bikerglen.com/blog/reverse-engineering-the-icolor-flex-protocol/#comments</comments>
		<pubDate>Sun, 17 Nov 2019 02:10:08 +0000</pubDate>
		<dc:creator><![CDATA[Glen]]></dc:creator>
				<category><![CDATA[FPGA]]></category>
		<category><![CDATA[Lighting]]></category>
		<category><![CDATA[RGB LED]]></category>

		<guid isPermaLink="false">https://bikerglen.com/blog/?p=1705</guid>
		<description><![CDATA[Back in the early 2000&#8217;s&#8211;at least a decade before there were Neopixels or WS2812b LEDs&#8211;Color Kinetics introduced flexible color changing LED string lights. Each string contained fifty RGB color changing nodes. Each node contained an RGB LED and a custom &#8230; <a href="https://bikerglen.com/blog/reverse-engineering-the-icolor-flex-protocol/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<div id="attachment_1803" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/11/house.jpg"><img class="size-large wp-image-1803" src="https://bikerglen.com/wp/wp-content/uploads/2019/11/house-1024x576.jpg" alt="Hanging a bunch of iColor Flex LMX string lights on the house for Halloween." width="640" height="360" /></a><p class="wp-caption-text">Hanging a bunch of iColor Flex LMX string lights on the house for Halloween. These are quite visible even though it&#8217;s still daylight out!</p></div>
<p>Back in the early 2000&#8217;s&#8211;at least a decade before there were Neopixels or WS2812b LEDs&#8211;Color Kinetics introduced flexible color changing LED string lights. Each string contained fifty RGB color changing nodes. Each node contained an RGB LED and a custom ASIC. The nodes were strung along at either 4&#8243; or 12&#8243; spacing along a three conductor cable. The cable connected back to a power data supply that powered the nodes and translated the light level data from either DMX-512 or Ethernet UDP packets into the proprietary protocol used by the nodes. Today we&#8217;re going to reverse engineer that proprietary protocol.</p>
<p><span id="more-1705"></span></p>
<h2>Branding</h2>
<p>Color Kinetics is big into branding and trademarks. They call their RGB LED string lights iColor Flex, the ASIC inside each node is a Chromasic, and the protocol they use to communicate is called the Chromasic protocol. The biggest differentiators between all the different products are the color of light emitted, RGB or white, and the diameter of the node, 15 mm or 35 mm.</p>
<h3>iColor Flex SL</h3>
<div id="attachment_1792" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/11/icolor-flex-sl.jpg"><img class="size-large wp-image-1792" src="https://bikerglen.com/wp/wp-content/uploads/2019/11/icolor-flex-sl-1024x684.jpg" alt="Three iColor Flex SL nodes." width="640" height="428" /></a><p class="wp-caption-text">Three iColor Flex SL nodes.</p></div>
<p>The original iColor Flex product was iColor Flex SL. Each node was a dot about 15 mm in diameter and contained a single RGB LED. These were available in eight different configurations by selecting from among the following options:</p>
<ul>
<li>Black wire and nodes or white wire and nodes.</li>
<li>Nodes spaced at 4&#8243; or 12&#8243;.</li>
<li>Dome or cone diffuser.</li>
<li>Clear or translucent diffuser.</li>
</ul>
<p>The iColor Flex SL product ran from 7.5 V and was advertised as capable of producing 68 billion color combinations. Each node used three channels for control: one for red, one for green, and one for blue. A twenty foot leader cable extended from the first node in the string and plugged directly into a power data supply. The power supply connector was permanently attached to the leader cable.</p>
<h3>iColor Flex SLX</h3>
<p>The second product was iColor Flex SLX. Each node was a dot about 35 mm in diameter and contained three RGB LEDs. These were available in eight different configuration too except the choices for the shape of the diffuser were now dome or flat. These ran from 12 V, used three control channels, and came with an attached twenty feet leader cable that plugged directly into a power data supply.</p>
<h3>iColor Flex MX, LMX, MX gen2, and LMX gen2</h3>
<div id="attachment_1799" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/11/icolor-flex-lmx-nodes.jpg"><img class="size-large wp-image-1799" src="https://bikerglen.com/wp/wp-content/uploads/2019/11/icolor-flex-lmx-nodes-1024x684.jpg" alt="iColor Flex LMX nodes." width="640" height="428" /></a><p class="wp-caption-text">iColor Flex LMX nodes.</p></div>
<p>As RGB LEDs continued to get brighter, Color Kinetics refreshed their product line. The small nodes became iColor Flex MX and MX gen2. The large nodes became iColor Flex LMX and LMX gen2. In addition the large nodes now contained six RGB LEDs instead of three and ran from 24 V instead of 12 V.</p>
<p>Another big change introduced with these products was a detachable leader cable that could be shortened to fit the user&#8217;s application. The string of nodes now shipped with a short three foot pigtail that plugged into a leader cable that connected back to the power supply through a dongle. We&#8217;ll cover the dongle and leader cable in detail in a following section.</p>
<h3>Fixed and Variable Color Temperature White Strings</h3>
<div id="attachment_1800" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/11/ew-flex-nodes.jpg"><img class="size-large wp-image-1800" src="https://bikerglen.com/wp/wp-content/uploads/2019/11/ew-flex-nodes-1024x684.jpg" alt="eW Flex SLX nodes." width="640" height="428" /></a><p class="wp-caption-text">eW Flex SLX nodes.</p></div>
<p>Color Kinetics also makes their string lights in fixed and variable color temperature white light versions. The fixed color temperature versions are branded as eW Flex or Essential White Flex. These contain one or five white LEDs and are available in a variety of fixed color temperatures. Each node requires three control channels. The first channel controls the brightness of the node. The second and third channels are unused.</p>
<p>The variable color temperature versions are branded as iW Flex or intelliWhite Flex. These contain both 2700 K and 6500 K LEDs and require three control channels per node. The first channel controls the 2700 K LEDs and the second channel controls the 6500 K LEDs. The third channel is unused. These products are capable of producing any color temperature between 2700 K and 6500 K by varying the levels of the different color temperature LEDs.</p>
<p>Like their RGB counterparts, these products went through several product generations too. Some examples:</p>
<ul>
<li>eW Flex SLX, 24V, fixed color temperature, direct connection to power supply</li>
<li>eW Flex Micro, 7.5V, fixed color temperature, direct connection to power supply</li>
<li>eW Flex Compact, 24V, fixed color temperature, leader cable required to connect to power supply</li>
<li>iW Flex Compact, 24V, variable color temperature, leader cable required to connect to power supply</li>
</ul>
<p>As a side note, the eW Flex Compact lights are used on the Bay Bridge in San Francisco.</p>
<h3>Even Newer Products</h3>
<p>They also have some newer products branded FlexElite. It&#8217;s likely they use a different ASIC and protocol since many of these products have four channels instead of three channels of LEDs. I don&#8217;t have any of these products so we&#8217;ll have to skip reverse engineering them for now.</p>
<h2>The Typical iColor Flex Setup</h2>
<div id="attachment_1746" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/11/ckca-setups.png"><img class="size-large wp-image-1746" src="https://bikerglen.com/wp/wp-content/uploads/2019/11/ckca-setups-1024x589.png" alt="The two different of iColor Flex setups. These are distinguished by having an integrated leader cable or a separate dongle and leader cable." width="640" height="368" /></a><p class="wp-caption-text">The two different iColor Flex setups. These are distinguished by having an integrated leader cable or a separate dongle and leader cable.</p></div>
<p>In a typical iColor Flex setup, a controller connects to a power data supply over a DMX-512 or wired Ethernet network and the power data supply connects to the lights via a leader cable. The power data supply injects DC power into the string of lights and translates the DMX-512 or Ethernet packets from the controller into the proprietary packet format used by the nodes.</p>
<p>In early versions of the lights, the leader cable was directly connected to the first node in the string and was typically twenty feet long. In the later versions, the power supply connects to the lights using a dongle and a leader cable that connects to a short pigtail from the first node in the string. The change was made to support non-outdoor power supplies, to allow for a longer leader cable, and to allow the leader cable to be cut to shorter lengths in the field.</p>
<h3>The Older Setup: Controller, Power Supply, and Lights</h3>
<div id="attachment_1790" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/11/icolor-flex-sl-setup.jpg"><img class="size-large wp-image-1790" src="https://bikerglen.com/wp/wp-content/uploads/2019/11/icolor-flex-sl-setup-1024x682.jpg" alt="An iColor Flex SL setup. DMX data feeds into power data supply then power data supply connects to nodes using an integrated twenty foot leader cable." width="640" height="426" /></a><p class="wp-caption-text">An iColor Flex SL setup. DMX data from a controller (not pictured) feeds into the power data supply then the power data supply connects to nodes using an integrated twenty foot leader cable.</p></div>
<p>On the older iColor Flex light strings, the lights connected directly to the power data supply via an integrated leader cable. The stock leader cable was twenty feet long but could be ordered shorter for custom products. The leader cable has a four-pin AMP connector that plugs directly into the power data supply. The AMP connector is very similar to the Molex connectors used on PC power supplies but is not the same and the two are not interchangeable.</p>
<div id="attachment_1787" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/11/outdoor-pds60ca-early.jpg"><img class="size-large wp-image-1787" src="https://bikerglen.com/wp/wp-content/uploads/2019/11/outdoor-pds60ca-early-1024x684.jpg" alt="A first generation outdoor rated power data supply with a string of lights with " width="640" height="428" /></a><p class="wp-caption-text">A string of lights with a permanently attached twenty foot leader cable connected directly to a first generation outdoor rated power data supply. The four-pin power data connector is not removable so the waterproof cable bushing comes preinstalled on the leader cable.</p></div>
<p>The only power supplies available at the time were versions designed for outdoor use. Since the four-pin AMP connector on the leader cable could not be removed and re-installed in the field, the leader cable came with a waterproof strain relief preinstalled. The end user would mount the power data supply and lights, feed the end of the leader cable into the power data supply, mount the strain relief on the power-data supply, then plug in the 4-pin amp connector. Any excess cable would have to be bundled up, hidden, and stored near the supply or lights.</p>
<h3>The Newer Setup: Controller, Power Supply, Dongle, Cable, and Lights</h3>
<div id="attachment_1795" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/11/icolor-flex-lmx-setup.jpg"><img class="size-large wp-image-1795" src="https://bikerglen.com/wp/wp-content/uploads/2019/11/icolor-flex-lmx-setup-1024x682.jpg" alt="A complete iColor Flex LMX setup minus the controller. Ethernet data feeds into the power data supply. The power data supply is then connected to the nodes using a dongle and leader cable." width="640" height="426" /></a><p class="wp-caption-text">A complete iColor Flex LMX setup minus the controller. Ethernet data feeds into the power data supply. The power data supply is then connected to the nodes using a dongle and leader cable.</p></div>
<p>On the newer iColor Flex light strings, the lights connect to the power data supply via a dongle and detachable leader cable. The dongle plugs into the power supply, one end of the leader cable screws into a terminal block inside the dongle, and the other end of the dongle connects to a short pigtail from the first node in the string using three-pin Amphenol LTW circular connectors.</p>
<div id="attachment_1797" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/11/indoor-supply-with-leader-cable.jpg"><img class="size-large wp-image-1797" src="https://bikerglen.com/wp/wp-content/uploads/2019/11/indoor-supply-with-leader-cable-1024x684.jpg" alt="A newer indoor supply with a dongle, leader cable, and a few iColor Flex LMX nodes." width="640" height="428" /></a><p class="wp-caption-text">A newer indoor supply with a dongle, leader cable, and a few iColor Flex LMX nodes.</p></div>
<p>This change has several advantages. First, the user can order a stock leader cable, remove the dongle, shorten the leader cable, and then reconnect the dongle. This allows custom leader cable lengths to be cut in the field. Second, leader cables could be made longer while maintaining their signal integrity. Third, the installation of a waterproof strain relief could be performed in the field: detach the dongle, thread the strain relief on to the leader cable, then re-attach the dongle. If the installation is indoors, the use of the waterproof strain relief can be skipped. If the installation is outdoors, the dongle is small enough to fit two of them inside the outdoor power data supplies.</p>
<h2>Goals for Our Reverse Engineering</h2>
<p>Our goal is to figure out the pin out of each connector and the protocol used at each point between the power supply and first node on the string. This includes at the four-pin AMP connector on the power data supply, the screw terminal block inside the dongle, and at the three-pin Amphenol LTW circular connector at the lights. Let&#8217;s start by looking for any publicly available information about the power supplies, protocol, and lights.</p>
<h2>What Public Information Is Available?</h2>
<p>A good reverse engineering effort starts with surveying what information is publicly available. In the case of the iColor Flex LED strings, there&#8217;s a data sheet and a patent.</p>
<h3>Data Sheet</h3>
<div id="attachment_1809" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/11/datasheet.png"><img class="size-large wp-image-1809" src="https://bikerglen.com/wp/wp-content/uploads/2019/11/datasheet-1024x885.png" alt="The block diagram from the Chromasic data sheet." width="640" height="553" /></a><p class="wp-caption-text">The block diagram from the Chromasic data sheet.</p></div>
<p>Color Kinetics has a <a href="https://www.docs.colorkinetics.com/support/datasheets/Chromasic1.pdf">mostly useless data sheet</a> on their Chromasic chip posted on their website. The block diagram excerpted above is interesting just to see what is inside the chip. The most important information here is that the resolution of the chip and most likely the protocol is &#8220;12 bit PWM&#8221; with &#8220;64 billion additive RGB colors.&#8221; This implies we&#8217;re looking for 3 words of 12 bits in the protocol.</p>
<h3>Patents</h3>
<div id="attachment_1805" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/11/patents.jpg"><img class="size-large wp-image-1805" src="https://bikerglen.com/wp/wp-content/uploads/2019/11/patents-1024x684.jpg" alt="A tag listing two of Color Kinetics patents. These patents are both expired and the link is now dead too." width="640" height="428" /></a><p class="wp-caption-text">A tag listing two of Color Kinetics patents. These patents are both expired and the link is now dead too.</p></div>
<p>Color Kinetics likes patents and were quite litigious in their early days. The lawsuits slowed down after their acquisition by Philips and many of their early patents have expired or are expiring soon. But patents aren&#8217;t just for litigation&#8211;patents are supposed to describe inventions such that a person having ordinary skill in the art can reproduce those inventions, right?</p>
<p>Two patent numbers are listed on the tags on each string. These are not the patents we&#8217;re interested in though. These are patents on using PWM to dim LEDs and mix colors and have both expired. The patent we&#8217;re interested in is <a href="https://patents.google.com/patent/US7598684B2"><em>US Patent 7,598,684, Methods and apparatus for controlling devices in a networked lighting system</em></a>. This patent covers &#8220;a plurality of LED-based lighting systems are arranged as computer controllable &#8216;light strings.'&#8221; This patent doesn&#8217;t expire until August 8, 2021.</p>
<h4>Encoding</h4>
<div id="attachment_1806" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/11/figure-10b.png"><img class="size-large wp-image-1806" src="https://bikerglen.com/wp/wp-content/uploads/2019/11/figure-10b-795x1024.png" alt="Figure 10B in the patent is used to describe encoding zeros and ones on the wire and recovering those values in the LED node." width="640" height="824" /></a><p class="wp-caption-text">Figure 10B in the patent is used to describe encoding zeros and ones on the wire and recovering those values in the LED node.</p></div>
<p>The first of two big pieces of information in the patent is how bits are encoded. The patent includes a Figure 10B which shows a block diagram of the circuitry used to decode bits at the input of the node and re-encode new bits at the output of the node. The text that accompanies the figure describes a bit encoding scheme where the location of the falling edge between two rising edges determines the value of the bit. If the falling edge occurs before 1/2 the period, the bit is a zero. If the falling edge occurs after 1/2 the period, the bit is a one. The patent then goes on to describe a method using a counter to decode this encoding back to zeros and ones.</p>
<h4>Self-Addressing</h4>
<div id="attachment_1807" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/11/figure-11.png"><img class="size-large wp-image-1807" src="https://bikerglen.com/wp/wp-content/uploads/2019/11/figure-11-795x1024.png" alt="Figure 11 from the patent" width="640" height="824" /></a><p class="wp-caption-text">Figure 11 in the patent described the self-addressing scheme including detecting start codes and replacing &#8220;used&#8221; levels with start codes to forward to the next node.</p></div>
<p>The second of two big pieces of information in the patent is how the nodes are addressed. The text describing the addressing scheme is accompanied by a Figure 11. Basically the node looks for a start code then grabs the next three channels of data and uses those to set its levels. Rather than forward those three channels of data to the next node, it replaces those three channels of data with three start codes. The next node in the string will now see four start codes then grab three levels of data replacing the grabbed data with additional start codes. This continues until the last node on the string.</p>
<h2>Power Supply and Power Supply Connector Pin Out</h2>
<div id="attachment_1759" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/11/ckca-pds-pinout.png"><img class="wp-image-1759 size-large" src="https://bikerglen.com/wp/wp-content/uploads/2019/11/ckca-pds-pinout-1024x627.png" alt="ckca pds pinout" width="640" height="392" /></a><p class="wp-caption-text">7.5 V and 24 V power data supply 4-pin power/data connector pin out.</p></div>
<p>The next step in reverse engineering the protocol was to figure out the pin out of the four-pin connectors on the power supplies. The string lights only use three of the four pins on the four-pin plug. I used a DMM and measured across the various permutations of these three pins on a 24 V power supply until I found a pair of pins that matched the supply voltage. The third pin should then be the data pin. I measured the voltage and it was about 2.35 V which is well within the electrical limits of my scope and its probes.</p>
<div id="attachment_1815" style="width: 810px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/11/scope_0.png"><img class="size-full wp-image-1815" src="https://bikerglen.com/wp/wp-content/uploads/2019/11/scope_0.png" alt="The data output at the output of the power data supply." width="800" height="632" /></a><p class="wp-caption-text">The data output at the output of the power data supply.</p></div>
<p>The next step was to use an oscilloscope to observe the signal on the third pin. The signal had a low voltage of 0 V, a high voltage of 5 V, and a frequency of 454.5 kHz measured rising edge to rising edge. The observed square wave signal alternated between two distinct duty cycles. The first duty cycle was high for 0.6 us then low for 1.6 us. The second duty cycle was high for 1.6 us then low for 0.6 us. These findings were good news because both the frequency and the waveforms are similar to those described in the patent.</p>
<div id="attachment_1785" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/11/connectors.jpg"><img class="size-large wp-image-1785" src="https://bikerglen.com/wp/wp-content/uploads/2019/11/connectors-1024x684.jpg" alt="On the left is a string of lights requiring 24 V. On the right is a string of lights requiring 7.5 V. Notice the pin out differences between the two." width="640" height="428" /></a><p class="wp-caption-text">On the left is a string of lights requiring 24 V. On the right is a string of lights requiring 7.5 V. Notice the pin out differences between the two.</p></div>
<p>The next catch was that the 7.5 V string lights and the 24 V string lights use a different set of three of the four pins. A bit more probing with the DMM discovered that both strings of lights used the same data and ground pin but the 7.5 V lights used a different third pin than the 24 V lights. I probed the 7.5 V power supply and quickly discovered that the two power supplies place their output voltages on different pins presumably to stop end users from accidentally applying 24 V to a 7.5 V light string.</p>
<p>The last step was to discover the manufacturer and part number for the connectors used on the power supply and the string of lights. They looked like Molex connectors but observing the connectors under a microscope revealed an AMP logo and pin numbers embossed in the plastic. I used a set of calipers to take some measurements of the connectors and browsed the Digi-Key and TE Connectivity websites until I found the matching connectors. The connectors and their part numbers for making your own power supplies, cables, and adapters are:</p>
<table>
<tbody>
<tr>
<th>Description</th>
<th>Manufacturer</th>
<th>Part #</th>
</tr>
<tr>
<td>Board-mount connector</td>
<td>TE Connectivity</td>
<td>1-770174-0</td>
</tr>
<tr>
<td>Right-angle board-mount connector</td>
<td>TE Connectivity</td>
<td>1-770968-0</td>
</tr>
<tr>
<td>Free-hanging plug</td>
<td>TE Connectivity</td>
<td>172167-1</td>
</tr>
<tr>
<td>Crimp contacts for 18-22 AWG wire</td>
<td>TE Connectivity</td>
<td>794831-1</td>
</tr>
</tbody>
</table>
<p>I couldn&#8217;t justify a ratcheting crimping tool to crimp wires on to the contacts so I&#8217;m using a Molex #63811-1000 non-ratcheting hand crimp tool to crimp the contacts onto wires when making my own cables.</p>
<h2>The Dongle</h2>
<div id="attachment_1783" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/11/dongle-front.jpg"><img class="size-large wp-image-1783" src="https://bikerglen.com/wp/wp-content/uploads/2019/11/dongle-front-1024x682.jpg" alt="The dongle doesn't look very complicated." width="640" height="426" /></a><p class="wp-caption-text">The dongle doesn&#8217;t look very complicated.</p></div>
<p>The next step was to figure out what the dongle and the huge lump at the end of the leader cable do. The dongle has a three-inch pigtail terminated in an AMP four-pin connector that plugs into a power data supply. The other end of the dongle has four-position screw terminal block that connects to the leader cable. The user can remove the cable from the dongle, cut it to length, install a waterproof bushing for outdoor use, then reconnect the cable to the dongle.</p>
<p>Taking a dongle apart, it looks simple enough. V+, V+, GND, and DATA solder pads on the input side, a bunch of coils, and RED, BLUE, BLUE/WHITE, BLK labels on the screw terminals on the output side. The V+ and V+ solder pads on the input side have a trace connecting them together so that the dongle gets power regardless of whether it is attached to a 7.5 V or 24 V power data supply. Looking at the leader cable though, the four conductors are two different gauges. The red and black wires are heavier gauge then the blue and blue/white wires. Furthermore, the blue and blue/white wires are twisted together into a pair. Something more must be going on.</p>
<div id="attachment_1782" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/11/dongle-rear.jpg"><img class="size-large wp-image-1782" src="https://bikerglen.com/wp/wp-content/uploads/2019/11/dongle-rear-1024x684.jpg" alt="OMG. There's a ton of stuff going on inside the dongle." width="640" height="428" /></a><p class="wp-caption-text">OMG. There&#8217;s a ton of stuff going on inside the dongle.</p></div>
<p>Indeed, removing the board completely from the plastic enclosure and looking at the back reveals quite a few chips and passives. There&#8217;s a what&#8217;s most likely a comparator, a small power supply, and most importantly for us, a MAX485 RS-485/RS-422 transceiver. While examining the circuit board traces around the MAX485, I made a few observations. First the MAX485&#8217;s receiver is hard-wired to be disabled. Second, the MAX485&#8217;s transmitter is hard-wired to be enabled. Lastly, the MAX485&#8217;s output is directly connected to the blue and blue/white screw terminals.</p>
<div id="attachment_1817" style="width: 810px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/11/scope_4.png"><img class="size-full wp-image-1817" src="https://bikerglen.com/wp/wp-content/uploads/2019/11/scope_4.png" alt="Differential data output at the output of the dongle." width="800" height="632" /></a><p class="wp-caption-text">Differential data output at the output of the dongle.</p></div>
<p>My conclusion is that the dongle converts the single-ended signal from the power data supply into a differential signal to transmit through the leader cable and to the lights. Differential signalling allows the use of leader cables up to about 100 feet versus the old single-ended lights that had a maximum leader cable length of up to about 20 feet. Viewing the dongle&#8217;s data input and outputs on a scope confirms this is the case.</p>
<p>The screw terminal labeled RED is the DC voltage from the power supply. The BLUE terminal is the inverted data output. The BLUE/WHT terminal is the non-inverting data output. Finally, the BLACK terminal is ground.</p>
<h2>The Other End of the Leader Cable</h2>
<div id="attachment_1780" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/11/leader-cable-lump.jpg"><img class="size-large wp-image-1780" src="https://bikerglen.com/wp/wp-content/uploads/2019/11/leader-cable-lump-1024x684.jpg" alt="The lump in the far end of the leader cable that connects to the light strings." width="640" height="428" /></a><p class="wp-caption-text">The lump in the far end of the leader cable that connects to the light strings.</p></div>
<p>The other end of the leader cable has a huge lump with an Amphenol LTW three-pin circular connector that connects to the light string. This end of the cable is pretty well sealed so I didn&#8217;t take it apart. This end of the cable converts the differential signal back into a single-ended signal to drive the lights.</p>
<div id="attachment_1770" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/11/ckca-leader-pinout.png"><img class="size-large wp-image-1770" src="https://bikerglen.com/wp/wp-content/uploads/2019/11/ckca-leader-pinout-1024x643.png" alt="Leader cable pin out." width="640" height="402" /></a><p class="wp-caption-text">Leader cable pin out.</p></div>
<p>I used a DMM and scope to determine the pin out of the connector. The connectors on the light strings are stamped LTW. I used this fact along with a set of measurements to find the connector manufacturer and part numbers for making my own cables.</p>
<table>
<tbody>
<tr>
<th>Description</th>
<th>Manufacturer</th>
<th>Part #</th>
</tr>
<tr>
<td>Board-mount receptacle, sockets</td>
<td>Amphenol LTW</td>
<td>BD-03PMFS-LC7001</td>
</tr>
<tr>
<td>Inline receptacle, sockets</td>
<td>Amphenol LTW</td>
<td>BD-03BMFA-LL7001</td>
</tr>
<tr>
<td>Inline plug, pins</td>
<td>Amphenol LTW</td>
<td>BD-03BFMA-LL7001</td>
</tr>
</tbody>
</table>
<h2>Digging into the Protocol</h2>
<p>Time to dig into the protocol and see how to control the lights. We already used a scope to derive the voltage levels and timing of the protocol. Now it was time to capture lots of data with varying light levels to derive how the levels are communicated to the lights. From the patent, we&#8217;re looking for a start code followed by light levels. From their marketing communications, we&#8217;re looking for RGB levels with 68 billion possible different colors. This translate to 36 bits or three words of 12 bits.</p>
<div id="attachment_1778" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/11/probing_nodes.jpg"><img class="size-large wp-image-1778" src="https://bikerglen.com/wp/wp-content/uploads/2019/11/probing_nodes-1024x682.jpg" alt="Using a small USB logic analyzer to capture data into and out of the the first node in the light string." width="640" height="426" /></a><p class="wp-caption-text">Using a small USB logic analyzer to capture data into and out of the the first node in the light string.</p></div>
<p>This step involved a lot of tedious work sending different color patterns to different numbers of nodes and observing the output of the power data supply with a small logic analyzer. I used two channels of the logic analyzer. The first channel was connected between the power data supply and the first node on the string of lights. The second channel was connected between the first and second node on the string of lights.</p>
<p>After performing a capture with the logic analyzer, I saved the captured data to a file then wrote some C code to parse the timing of the rising and falling edges into zeros and ones based on whether or not the falling edge occurred before (zero) or after (one) half the time between two successive rising edges. There were two possibilities here. I guessed correctly.</p>
<p>After many, many captures the protocol became apparent. Here&#8217;s a snip of a data capture between an older outdoor-rated power data supply and the first node with the first node set to red with a bit of blue and the second node set to yellow:</p>
<pre>111111111111100000000
101111111111100000001000000000000000000010011000000000000000
101111111111100000001010100001111000000010000000000000000000
100000000000000000001000000000000000000010000000000000000000
100000000000000000001000000000000000000010000000000000000000
100000000000000000001000000000000000000010000000000000000000
100000000000000000001000000000000000000010000000000000000000
100000000000000000001000000000000000000010000000000000000000
100000000000000000001000000000000000000010000000000000000000</pre>
<p>I noticed a start code of 13 ones followed by 8 zeros followed by data that varied based on the light levels. This pattern occurred at 25 ms interval which matched the update rate set in my controller software.</p>
<p>Immediately following this start code were 20 bit words. Each word began with a one, had 12 varying bits, then ended with 7 zero bits. From varying the levels and performing many captures I observed the light levels varied between 0 and 4094, were ordered red -&gt; green -&gt; blue, and were sent least-significant bit first. A light level of 4095 would be identical to a start code so the maximum light level is 4094 instead of 4095.</p>
<p>The data between the first node and second node was identical to the data between the power supply and the first node except the start code was now a 20 bit word and the RGB levels of the first node&#8217;s data had been replaced with start codes:</p>
<pre>11111111111110000000
111111111111100000001111111111111000000011111111111110000000
101111111111100000001010100001111000000010000000000000000000
100000000000000000001000000000000000000010000000000000000000
100000000000000000001000000000000000000010000000000000000000
100000000000000000001000000000000000000010000000000000000000
100000000000000000001000000000000000000010000000000000000000
100000000000000000001000000000000000000010000000000000000000
100000000000000000001000000000000000000000000000000000000000

</pre>
<p>There were some additional wrinkles in the protocol. About six nodes of zero data are sent after the number of nodes configured in the software. These seem to be required to pump the last few nodes of data out to the end of the strings for some reason. With the newer power data supplies, the blue channel is sent as a 21 bit word instead of a 20 bit word. The newer power data supplies also send a start code followed by a few zero bits when the line is idle versus the older power data supplies that just send zero bits all the time.</p>
<h2>The Protocol</h2>
<p>Here&#8217;s my final observation of the protocol:</p>
<ol>
<li>Send zero bits when the line is idle. Optionally: send start codes followed by a small number of zero bits. When ready to send data, revert to sending zero bits for a few hundred bits.</li>
<li>When node data is ready to send:
<ol>
<li>Send the 21 bit start code &#8216;b1_111111111111_00000000</li>
<li>Send the first node&#8217;s 20 bit red value &#8216;b1_rrrrrrrrrrrr_0000000</li>
<li>Send the first node&#8217;s 20 bit green value &#8216;b1_gggggggggggg_0000000</li>
<li>Send the first node&#8217;s 21 bit blue value &#8216;b1_bbbbbbbbbbbb_00000000</li>
<li>Repeat steps B through D for the remaining nodes</li>
</ol>
</li>
<li>When node data is done being sent, send six nodes of zero level data:
<ol>
<li>Send 20 bit red zero value &#8216;b1_000000000000_0000000</li>
<li>Send 20 bit green zero value &#8216;b1_000000000000_0000000</li>
<li>Send 21 bit blue zero value &#8216;b1_000000000000_00000000</li>
<li>Repeat steps A through C six times</li>
</ol>
</li>
</ol>
<p>The above protocol seems to work with the string lights that I have.</p>
<h2>Compared to WS2812b / Neopixels</h2>
<p>The WS2812b / Neopixel LEDs, tapes, and strings were developed about a decade after the iColor Flex string lights. It might be worth comparing and contrasting the Chromasic protocol to the WS2812b protocol.</p>
<p>First, the similarities. Sending a zero and a one is similar between the two protocols. A zero is a pulse with a short high time and a long low time. A one is a pulse with a long high time and short low time.</p>
<p>Now the differences:</p>
<table>
<tbody>
<tr>
<th>Item</th>
<th>WS2812b</th>
<th>Chromasic</th>
</tr>
<tr>
<td>Baud Rate</td>
<td>800 kHz</td>
<td>454.4 kHz</td>
</tr>
<tr>
<td>Bits Per Pixel</td>
<td>24</td>
<td>36</td>
</tr>
<tr>
<td>Idle Pattern</td>
<td>Hold data line low</td>
<td>Send zeros</td>
</tr>
<tr>
<td>Addressing Mode</td>
<td>Reset to address first node; used data is &#8220;swallowed&#8221; by the node and not sent to downstream nodes.</td>
<td>Send start code to address first node; consumed data is replaced by start codes sent to downstream nodes.</td>
<td></td>
</tr>
</tbody>
</table>
<p>Overall, the WS2812b protocol seems easier to implement on both microcontrollers and FPGAs mostly because you do not have to continuously send an idle pattern with the WS2812b LEDs.</p>
<h2>Gamma Correction</h2>
<p>Eight-bit DMX values from 0 to 255 map non-linearly to 12-bit values from 0 to 4094. This mapping is performed by the power data supply. I have not determined the exact mapping due to the time consuming nature of sending levels, capturing data with a logic analyzer, decoding it with my C code, then parsing through text files of zeros and ones. This would need to be done 254 more times to map all 256 DMX levels to their 12-bit values. I may build another FPGA in the future to help decode and determine the mapping used by the power data supplies.</p>
<h2>Using an FPGA to Implement the Protocol</h2>
<h3>Hardware Interface</h3>
<div id="attachment_1819" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/11/fpga-with-ckca-pmod.jpg"><img class="size-large wp-image-1819" src="https://bikerglen.com/wp/wp-content/uploads/2019/11/fpga-with-ckca-pmod-1024x684.jpg" alt="Digilent Cora Z7 FPGA board with a custom PMOD board to interface the FPGA to the iColor Flex strings." width="640" height="428" /></a><p class="wp-caption-text">Digilent Cora Z7 FPGA board with a custom PMOD board to interface the FPGA to the iColor Flex strings.</p></div>
<p>The final step was to try my own implementation of the protocol against some of the iColor Flex light strings I own. I decided to use a Digilent Cora Z7 FPGA board and to build my own PMOD interface board to connect to the light strings. The interface board passes a DC power supply voltage to the light strings and contains a 3.3 V to 5 V level translator IC to convert the FPGA&#8217;s 3.3 V output to a 5 V data output for the light strings. It has a pair of AMP four-pin connectors so that up to two light strings may be connected at once.</p>
<h3>Verilog</h3>
<p>The protocol is implemented in two Verilog RTL modules. Both modules run at 10 MHz. The first module generates an enable at the baud rate of 1/2.2e-6 bits per second and encodes zeros and ones into the data encoding used by the light strings.</p>
<pre>module ckca_encode
(
    input    wire            clk,
    input    wire            rst,
    output    reg                baudEn,
    input    wire            txd,
    output    reg             dout
);

    reg [4:0] encodeCount;

    always @ (posedge clk)
    begin
        if (rst)
        begin
            baudEn &lt;= 0;
            dout &lt;= 1;
            encodeCount &lt;= 0;
        end
        else
        begin
            baudEn &lt;= (encodeCount == 20);

            if (encodeCount == 21)
            begin
                encodeCount &lt;= 0;
                dout &lt;= 1;
            end
            else
            begin
                encodeCount &lt;= encodeCount + 1;
                if ((encodeCount == 5) &amp;&amp; (txd == 0))
                begin
                    dout &lt;= 0;
                end
                else if ((encodeCount == 15) &amp;&amp; (txd == 1))
                begin
                    dout &lt;= 0;
                end
            end
        end
    end

endmodule</pre>
<p>The second module is a funky UART that can send either 20 or 21 bits based on a flag in the input data word. Input data words come from a FIFO connected to the FPGA&#8217;s AXI4-Lite bus and internal ARM CPU. Bit[12] of the data word is the 20/21 bit flag. Bits[11:0] of the data word are the data to transmit and are positioned within the 20/21 bits sent to the ckca_encode module. The bits are sent to the ckca_module at the baud rate using the enable generated by that module.</p>
<pre>module ckca_uart
(
    input    wire            clk,                // system clock
    input    wire            rst,                // synchronous, active-high system reset
    input    wire            baudEn,                // enable at baud rate
    input    wire            avail,                // new data byte to transmit available
    input    wire    [12:0]    data,                // 20/21b flag + 12 data bits
    output    reg                ack,                // data byte moved to transmit hold register
    output    reg                txd                    // transmit data out
);

localparam TXIDLE = 0, TXBRK = 1, TXMAB = 2, TXDAT = 3;

reg  [1:0] txbusy;                                // transmit state
reg  [4:0] bitnum;                                // current tx bit number
reg  [4:0] txbits;                                // number of bits to transmit minus one
reg    [19:0] txdata;                                // tranmsit data hold register

always @ (posedge clk)
begin
    if (rst)
    begin
        ack &lt;= 0;
        txd &lt;= 0;
        txbusy &lt;= 0;
        bitnum &lt;= 0;
        txbits &lt;= 0;
        txdata &lt;= 0;
    end
    else
    begin
        ack &lt;= 0;

        if (baudEn)
        begin
            case (txbusy)

                TXIDLE: begin
                    if (avail)
                    begin
                        ack &lt;= 1;
                        txd &lt;= 1;
                        txbusy &lt;= TXDAT;
                        bitnum &lt;= 0;
                        txbits &lt;= data[12] ? 20 : 19;
                        txdata &lt;= { 8'h00, data[11:0] };
                    end
                    else
                    begin
                        txd &lt;= 0;
                        bitnum &lt;= 0;
                        txbusy &lt;= TXIDLE;
                    end
                end

                TXDAT: begin
                    if (bitnum &gt;= txbits)
                    begin
                        if (avail)
                        begin
                            ack &lt;= 1;
                            txd &lt;= 1;
                            txbusy &lt;= TXDAT;
                            bitnum &lt;= 0;
                            txbits &lt;= data[12] ? 20 : 19;
                            txdata &lt;= { 8'h00, data[11:0] };
                        end
                        else
                        begin
                            txd &lt;= 0;
                            bitnum &lt;= 0;
                            txbusy &lt;= TXIDLE;
                        end
                    end
                    else
                    begin
                        txd &lt;= txdata[0];
                        txdata &lt;= { 1'b0, txdata[19:1] };
                        bitnum &lt;= bitnum + 1;
                    end
                end
        
            endcase
        end
    end
end

endmodule</pre>
<p>These two modules are instantiated inside a wrapper along with a FIFO and AXI4-Lite interface and connected to the Zynq FPGA&#8217;s ARM core using Vivado&#8217;s IP integrator.</p>
<div id="attachment_1822" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/11/vivado-block-diagram1.png"><img class="size-large wp-image-1822" src="https://bikerglen.com/wp/wp-content/uploads/2019/11/vivado-block-diagram1-1024x668.png" alt="Two instances of my implementation of the protocol in the Vivado IP Integrator." width="640" height="418" /></a><p class="wp-caption-text">Two instances of my implementation of the protocol in the Vivado IP Integrator.</p></div>
<h3>Software</h3>
<p>Some quick software was written using the Xilinx SDK IDE to have 6 colors chase down a string of 10 nodes.</p>
<pre>// includes
#include "platform.h"
#include "xgpio.h"
#include "xil_printf.h"
#include "xparameters.h"

// short cuts 
#define CKCA0_TIMEBASE_VALUE_REG    (XPAR_CKCA_WRAPPER_0_BASEADDR + 0x10)
#define CKCA0_TIMEBASE_FLAG_REG     (XPAR_CKCA_WRAPPER_0_BASEADDR + 0x14)
#define CKCA0_FIFO_DATA_REG         (XPAR_CKCA_WRAPPER_0_BASEADDR + 0x18)

// color table
static const uint16_t colors[6][3] = {
    { 0x0FFE, 0x0000, 0x1000 }, // RED
    { 0x0FFE, 0x0FFE, 0x1000 }, // YELLOW
    { 0x0000, 0x0FFE, 0x1000 }, // GREEN
    { 0x0000, 0x0FFE, 0x1FFE }, // CYAN
    { 0x0000, 0x0000, 0x1FFE }, // BLUE
    { 0x0FFE, 0x0000, 0x1FFE }  // PURPLE
};

// main
int main()
{
    XGpio gpio;

    init_platform ();
    XGpio_Initialize(&amp;gpio, 0);
    XGpio_SetDataDirection(&amp;gpio, 2, 0x00000000); // set LED GPIO channel tristates to All Output
    XGpio_SetDataDirection(&amp;gpio, 1, 0xFFFFFFFF); // set BTN GPIO channel tristates to All Input

    int timer = 0;
    int color = 0;
    int j, k;

    while (1) {
        if (Xil_In32 (CKCA0_TIMEBASE_FLAG_REG) &amp; 0x1) {
            Xil_Out32 (CKCA0_TIMEBASE_FLAG_REG, 0x1);
            xil_printf (".");

            timer++;
            if (timer &gt;= 20) {
                timer = 0;

                // send start code
                Xil_Out32 (CKCA0_FIFO_DATA_REG, 0x1FFF);

                // cycle through colors
                k = color;
                for (j = 0; j &lt; 10; j++) {
                    Xil_Out32 (CKCA0_FIFO_DATA_REG, colors[k][0]);
                    Xil_Out32 (CKCA0_FIFO_DATA_REG, colors[k][1]);
                    Xil_Out32 (CKCA0_FIFO_DATA_REG, colors[k][2]);
                    if (++k &gt; 5) {
                        k = 0;
                    }
                }

                // send six empty nodes of data to push data through last nodes
                for (j = 0; j &lt; 6; j++) {
                    Xil_Out32 (CKCA0_FIFO_DATA_REG, 0x0000);
                    Xil_Out32 (CKCA0_FIFO_DATA_REG, 0x0000);
                    Xil_Out32 (CKCA0_FIFO_DATA_REG, 0x1000);
                }

                if (--color &lt; 0) {
                    color = 5;
                }
            }
        }
    }

    return 0;
}</pre>
<h3> Trying It All Out</h3>
<p>Here&#8217;s the result with a string of 10 iColor Flex MX nodes:</p>
<p><a href="https://bikerglen.com/wp/wp-content/uploads/2019/11/success-mx.jpg"><img class="alignnone size-large wp-image-1825" src="https://bikerglen.com/wp/wp-content/uploads/2019/11/success-mx-1024x638.jpg" alt="success-mx" width="640" height="399" /></a></p>
<p>Here&#8217;s the result with a string of 6 iColor Flex MX gen 2 nodes:</p>
<p><a href="https://bikerglen.com/wp/wp-content/uploads/2019/11/success-mx-gen2.jpg"><img class="alignnone size-large wp-image-1826" src="https://bikerglen.com/wp/wp-content/uploads/2019/11/success-mx-gen2-1024x584.jpg" alt="success-mx-gen2" width="640" height="365" /></a></p>
<p>Here&#8217;s the result with a string of 10 iColor Flex LMX nodes:</p>
<p><a href="https://bikerglen.com/wp/wp-content/uploads/2019/11/success-lmx.jpg"><img class="alignnone size-large wp-image-1827" src="https://bikerglen.com/wp/wp-content/uploads/2019/11/success-lmx-1024x576.jpg" alt="success-lmx" width="640" height="360" /></a></p>
<h2>Conclusion</h2>
<p>I successfully reverse engineered the protocol used to control iColor Flex string lights based on their Chromasic chip and Chromasic protocol. After reverse engineering the protocol, I built a small circuit board and FPGA to implement the protocol and control a few different types of light strings.</p>
]]></content:encoded>
			<wfw:commentRss>https://bikerglen.com/blog/reverse-engineering-the-icolor-flex-protocol/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Folding the Six Panel Wall into a Cube</title>
		<link>https://bikerglen.com/blog/folding-the-six-panel-wall-into-a-cube/</link>
		<comments>https://bikerglen.com/blog/folding-the-six-panel-wall-into-a-cube/#comments</comments>
		<pubDate>Sun, 25 May 2014 23:18:17 +0000</pubDate>
		<dc:creator><![CDATA[Glen]]></dc:creator>
				<category><![CDATA[BeagleBone Black]]></category>
		<category><![CDATA[FPGA]]></category>
		<category><![CDATA[LED Matrix]]></category>
		<category><![CDATA[Lighting]]></category>
		<category><![CDATA[RGB LED]]></category>

		<guid isPermaLink="false">http://bikerglen.com/blog/?p=127</guid>
		<description><![CDATA[After seeing this cube and this cube, I decided it was time to build an LED cube of my own leveraging the BeagleBone Black and FPGA work I had already done for my six-panel mini video wall. The cube project &#8230; <a href="https://bikerglen.com/blog/folding-the-six-panel-wall-into-a-cube/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>After seeing <a href="https://www.flickr.com/photos/osr/12689589335/">this cube</a> and <a href="https://learn.adafruit.com/diy-led-video-cube/overview">this cube</a>, I decided it was time to build an LED cube of my own leveraging the BeagleBone Black and FPGA work I had already done for <a href="http://bikerglen.com/blog/expanding-the-beaglebone-black-and-fpga-to-drive-6-or-more-panels/">my six-panel mini video wall</a>. The cube project is essentially purely mechanical since the existing BBB software and FPGA code will work unmodified to drive the cube.</p>
<div id="attachment_154" style="width: 650px" class="wp-caption alignleft"><a href="http://bikerglen.com/wp/wp-content/uploads/2014/05/hangingcube.jpg"><img class="size-large wp-image-154" title="Hanging Cube" src="http://bikerglen.com/wp/wp-content/uploads/2014/05/hangingcube-1024x682.jpg" alt="" width="640" height="426" /></a><p class="wp-caption-text">The finished cube hanging from the rafters in my basement.</p></div>
<p><span id="more-127"></span></p>
<h2>3D Printed Brackets</h2>
<p>The first step in this project was to decide how to hold the six RGB LED panels together in a cube shape. I experimented with cutting and drilling aluminum angle iron into brackets to hold each panel to its neighbors. That experiment worked but was not easy to replicate. I finally decided to draw a set of brackets using Sketchup and have the brackets 3D printed. The brackets would attach at the corners and midpoints of each panel. Since I do not own a 3D printer, I used <a href="http://sculpteo.com">sculpteo.com</a> to print the brackets out of white nylon.</p>
<div id="attachment_130" style="width: 650px" class="wp-caption alignleft"><a href="http://bikerglen.com/wp/wp-content/uploads/2014/05/brackets.jpg"><img class="size-large wp-image-130" title="3D Printed Brackets" src="http://bikerglen.com/wp/wp-content/uploads/2014/05/brackets-1024x683.jpg" alt="" width="640" height="426" /></a><p class="wp-caption-text">3D printed brackets. The larger brackets hold the corners together. The small brackets hold the midpoints together.</p></div>
<p>I wanted to be able to hang the cube from the ceiling. Rather than hang the cube by its power cord or networking cable, I decided to hang the bracket using a piece of wire rope. I swaged two stops on to one end of the wire rope. The wire rope and stops are a bit rough and would eventually wear through the plastic nylon corner so I used <a href="shapeways.com">shapeways.com</a> to 3D print a pre-drilled hanging bracket for the top corner out of stainless steel.</p>
<div id="attachment_131" style="width: 650px" class="wp-caption alignleft"><a href="http://bikerglen.com/wp/wp-content/uploads/2014/05/cube-hanging-bracket.jpg"><img class="size-large wp-image-131" title="cube-hanging-bracket" src="http://bikerglen.com/wp/wp-content/uploads/2014/05/cube-hanging-bracket-1024x682.jpg" alt="" width="640" height="426" /></a><p class="wp-caption-text">Cube Hanging Bracket</p></div>
<p>Both the Sketchup and STL files for each of these different brackets are in my <a href="https://github.com/bikerglen/beagle/tree/master/projects/led-panel-6up/mechanical/3d_cube">github repository</a>.</p>
<h2>Panel Order</h2>
<p>The next step was to decide the order of the panels. I wanted to minimize the seams between images so I decided panels 1, 2, and 3 should connect at their sides then panels 4, 5, and 6 should connect at their sides. I also wanted the panel with the minimum number of wired connections to be the lid. Panel 1 only has one power connection and one data connection so it had to be the lid. Finally panels 1, 2, and 3 would slide sideways into panels 4, 5, and 6. This would make the corner where panels 1, 4, and 5 come together the top.</p>
<div id="attachment_129" style="width: 647px" class="wp-caption alignleft"><a href="http://bikerglen.com/wp/wp-content/uploads/2014/05/123456.png"><img class="size-full wp-image-129" title="Panel Ordering" src="http://bikerglen.com/wp/wp-content/uploads/2014/05/123456.png" alt="" width="637" height="425" /></a><p class="wp-caption-text">Panel ordering. Panels 1, 2, 3 and 4, 5, 6 form two seamless units that are connected together.</p></div>
<h2>Construction</h2>
<p>The next step was to assemble the cube using the brackets and M3 x 6mm screws.</p>
<div id="attachment_191" style="width: 650px" class="wp-caption alignleft"><a href="http://bikerglen.com/wp/wp-content/uploads/2014/05/brackets2.jpg"><img class="size-large wp-image-191" title="Brackets Connecting Panels" src="http://bikerglen.com/wp/wp-content/uploads/2014/05/brackets2-1024x681.jpg" alt="" width="640" height="425" /></a><p class="wp-caption-text">Some of the brackets holding the RGB LED panels together.</p></div>
<p>The lid panel is secured using friction. I cut the heads off four longer M3 screws and threaded those into the four corners of the lid panel. Friction and gravity are enough to hold the lid panel on top of the cube.</p>
<div id="attachment_133" style="width: 650px" class="wp-caption alignleft"><a href="http://bikerglen.com/wp/wp-content/uploads/2014/05/lid.jpg"><img class="size-large wp-image-133" title="M3 Post on Lid Panel" src="http://bikerglen.com/wp/wp-content/uploads/2014/05/lid-1024x682.jpg" alt="" width="640" height="426" /></a><p class="wp-caption-text">One of four corners of panel 1, the lid panel, showing the M3 post used to hold the lid on to the cube.</p></div>
<p>Temporarily assemble the cube and mark the corners of the panel where the wire rope will exit the cube.</p>
<div id="attachment_135" style="width: 650px" class="wp-caption alignleft"><a href="http://bikerglen.com/wp/wp-content/uploads/2014/05/corners1.jpg"><img class="size-large wp-image-135" title="corners1" src="http://bikerglen.com/wp/wp-content/uploads/2014/05/corners1-1024x681.jpg" alt="" width="640" height="425" /></a><p class="wp-caption-text">Mark the corners with a white paint marker then file them down with a rotary tool.</p></div>
<p>Disassemble the marked panels and use a rotary tool or file to knock the corners of the panels down just enough for the wire rope to exit the cube. Labeling the panels with tape makes it easier to keep track of which panel is which as the cube is being assembled.</p>
<div id="attachment_147" style="width: 650px" class="wp-caption alignleft"><a href="http://bikerglen.com/wp/wp-content/uploads/2014/05/corners2.jpg"><img class="size-large wp-image-147" title="Corners After Grinding" src="http://bikerglen.com/wp/wp-content/uploads/2014/05/corners2-1024x681.jpg" alt="" width="640" height="425" /></a><p class="wp-caption-text">The corners of panels 1, 4, and 5 were they meet at the top of the cube. The corners were knocked down just enough with a rotary tool for the wire rope to exit the cube.</p></div>
<p>Complete the mechanical assembly of the cube using seven of the nylon corner brackets and eight of the nylon side brackets. The corner brackets will need to be rotated to accommodate the holes in the panels.</p>
<div id="attachment_148" style="width: 650px" class="wp-caption alignleft"><a href="http://bikerglen.com/wp/wp-content/uploads/2014/05/inside.jpg"><img class=" wp-image-148 " title="Inside the Cube Before Wiring" src="http://bikerglen.com/wp/wp-content/uploads/2014/05/inside-1024x768.jpg" alt="" width="640" height="480" /></a><p class="wp-caption-text">Inside the cube before wiring. Looks like I forgot a screw too.</p></div>
<h2> Electrical Connections</h2>
<p>Now wire the cube. Connect the output of panel 6 to the input of panel 5, the output of panel 5 to the input of panel 4, etc., until finally connecting the output of panel 2 to in the input of panel 1. You’ll need to make a slightly longer ribbon cable assembly to connect the output of panel 4 to the input of panel 3. Connect the output of the LogiBone FPGA board to the input of panel 6.</p>
<p>After making the data connections, use three of the wire harnesses that came with the LED panels to supply power to the cube. I used a wire nut to join all the ground connections together and another wire nut to join all the +5V connections together. These were connected using some hookup wire to a 2.1mm DC barrel jack that mates with the plug on my +5V DC power supply.</p>
<div id="attachment_150" style="width: 650px" class="wp-caption alignleft"><a href="http://bikerglen.com/wp/wp-content/uploads/2014/05/connections.jpg"><img class="size-large wp-image-150" title="Wired Cube Interior" src="http://bikerglen.com/wp/wp-content/uploads/2014/05/connections-1024x768.jpg" alt="" width="640" height="480" /></a><p class="wp-caption-text">Wired cube interior. The BBB and LB FPGA boards are inside a plastic bag until a proper mounting bracket can be fabricated.</p></div>
<p>Be sure to use electrical tape to insulate any exposed power conductors and secure any cables that could come loose inside the enclosure. I have the BeagleBone Black and LogiBone FPGA board inside a plastic bag to keep them from shorting to any exposed conductors on the LED panels. This is a temporary measure (beware of heat!) until I have time to design a bracket to mount the BBB and LB boards to the inside surface of one of the LED panels.</p>
<h2>The Finished Product</h2>
<p>Here’s a photo of the finished cube hanging in my basement.</p>
<div id="attachment_154" style="width: 650px" class="wp-caption alignleft"><a href="http://bikerglen.com/wp/wp-content/uploads/2014/05/hangingcube.jpg"><img class="size-large wp-image-154" title="Hanging Cube" src="http://bikerglen.com/wp/wp-content/uploads/2014/05/hangingcube-1024x682.jpg" alt="" width="640" height="426" /></a><p class="wp-caption-text">The finished cube hanging from the rafters in my basement.</p></div>
<h2>Using a Stand to Display the Cube</h2>
<p>I also built a small stand out of dowel rods and MDF plywood. I’ve yet to paint the stand. If you would rather use a stand than hang the cube, the magic angle for cutting the dowel rods is 55 degrees. The stand still needs to be painted flat black.</p>
<div id="attachment_160" style="width: 650px" class="wp-caption alignleft"><a href="http://bikerglen.com/wp/wp-content/uploads/2014/05/deskstand.jpg"><img class="size-large wp-image-160" title="Cube Stand" src="http://bikerglen.com/wp/wp-content/uploads/2014/05/deskstand-1024x682.jpg" alt="" width="640" height="426" /></a><p class="wp-caption-text">The cube sitting in its stand on my desk. The dowel rods are cut at 55 degrees and hold the cube with the top corner pointing straight up. The stand still needs to be painted black.</p></div>
<h2>Some Ideas for Improvements</h2>
<p>The interior of the cube gets quite warm. Ideally the BBB and LB would be located in a plastic housing attached to the wire rope above and outside the cube. A short ribbon cable would then run from the plastic housing to the interior of the cube. Lastly, I need to install the wireless drivers and connect to the BBB over WiFi instead of using a wired Ethernet cable. This would greatly reduce the bulky wiring exiting the top of the cube.</p>
]]></content:encoded>
			<wfw:commentRss>https://bikerglen.com/blog/folding-the-six-panel-wall-into-a-cube/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Expanding the BeagleBone Black and FPGA to Drive 6 (or more) Panels</title>
		<link>https://bikerglen.com/blog/expanding-the-beaglebone-black-and-fpga-to-drive-6-or-more-panels/</link>
		<comments>https://bikerglen.com/blog/expanding-the-beaglebone-black-and-fpga-to-drive-6-or-more-panels/#comments</comments>
		<pubDate>Sat, 05 Apr 2014 06:07:09 +0000</pubDate>
		<dc:creator><![CDATA[Glen]]></dc:creator>
				<category><![CDATA[BeagleBone Black]]></category>
		<category><![CDATA[FPGA]]></category>
		<category><![CDATA[LED Matrix]]></category>
		<category><![CDATA[Lighting]]></category>
		<category><![CDATA[RGB LED]]></category>

		<guid isPermaLink="false">http://bikerglen.com/blog/?p=73</guid>
		<description><![CDATA[After completing my first BeagleBone Black + FPGA project and tutorial where I drove a single 32&#215;32 RGB LED matrix, I decided it was time to go bigger. The result is the project shown below—a 3 x 2 matrix of &#8230; <a href="https://bikerglen.com/blog/expanding-the-beaglebone-black-and-fpga-to-drive-6-or-more-panels/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>After completing my first BeagleBone Black + FPGA <a href="http://bikerglen.com/blog/?p=42">project</a> and <a href="http://bikerglen.com/projects/lighting/led-panel-1up/">tutorial</a> where I drove a single 32&#215;32 RGB LED matrix, I decided it was time to go bigger. The result is the project shown below—a 3 x 2 matrix of 32&#215;32 RGB LED panels. That’s 6,144 RGB LEDs or 18,432 LED chips—each of which can be controlled with 12-bit color at a refresh rate of 200Hz. Let’s take a closer look at the steps required to move from driving one panel to driving six panels.</p>
<p>Here is a video on YouTube of the <a href="http://www.youtube.com/watch?v=LBeVMGOgWvY">six panel project in action</a>.</p>
<div id="attachment_84" style="width: 650px" class="wp-caption alignleft"><a href="http://bikerglen.com/wp/wp-content/uploads/2014/04/DSC_1838_2128.jpg"><img class="size-large wp-image-84" title="Perlin Noise" src="http://bikerglen.com/wp/wp-content/uploads/2014/04/DSC_1838_2128-1024x681.jpg" alt="" width="640" height="425" /></a><p class="wp-caption-text">576mm x 384mm RGB LED “wall” displaying a frame of Perlin noise. The BeagleBone Black can perform the roughly 600,000 3D Perlin noise calculations required to produce a smooth animation sequence at about 50% CPU utilization.</p></div>
<div id="attachment_88" style="width: 650px" class="wp-caption alignleft"><a href="http://bikerglen.com/wp/wp-content/uploads/2014/04/video-wall-rear.jpg"><img class="size-large wp-image-88" title="rear of rgb led wall" src="http://bikerglen.com/wp/wp-content/uploads/2014/04/video-wall-rear-1024x682.jpg" alt="" width="640" height="426" /></a><p class="wp-caption-text">576mm x 384mm RGB LED “wall” construction showing six 192mm x 192mm 32&#215;32 RGB LED panels, the 3mm thick aluminum frame, two pieces of 20x40mm aluminum extrusion, wall mounting brackets, electronics, and power supply.</p></div>
<p><span id="more-73"></span></p>
<h2>The Frame</h2>
<p>The first step was to build a frame to mount the panels. I used a set of calipers to locate each mounting hole and determine the clearance required for each of the connectors on the LED panels. I drew the frame using the free front panel design software from frontpanelexpress.com. I added holes to mount the BeagleBone Black and a 60W +3.3V power supply. Once I had the basic layout completed, I decided to use 20mm x 40mm aluminum extrusions to give the panel some depth to hold the electronics behind the frame and panels. I finally had the frame and two wall mounting brackets fabricated at frontpanelexpress.com.</p>
<h2>The Verilog</h2>
<p>The Verilog needed some changes to drive the increased number of panels:</p>
<ul>
<li>The number of clock cycles used to shift each set of RGB data bits into the panels was reduced from 3 to 2.</li>
<li>The frame buffer memories were increased from 2 x 1024 x 12 bits to 2 x 8192 x 12 bits.</li>
<li>To maintain my 12-bit color depth and 200Hz refresh rate, the clock used to drive the panel refresh logic was bumped to 25MHz from 10MHz.</li>
<li>I added support for global dimming so that the overall brightness of the panel could be controlled without affecting the color depth of the panel.</li>
</ul>
<p>These changes were relatively quick and easy to make. A few simulations and a run through the Xilinx ISE tools yielded a new bit file ready to drive up to six panels.</p>
<p>The Xilinx Spartan 6 LX9 has enough block RAM to drive up to 16 panels. By bumping the clock to 30MHz from 25MHz, 8 panels could be driven. If the refresh rate were dropped to 100Hz, 16 panels could be driven. If more I/Os were available on the LogiBone FPGA board, 16 panels could be driven at 200Hz. All with 12-bit color.</p>
<h2>The Software</h2>
<p>Most of the software used to display patterns only required changing the display width and height defines and the write levels function to port to the larger display. The exception was the Perlin noise routine. In a floating point implementation with all compiler optimization disabled, the Perlin noise routine could only drive about 1.5 panels. I converted the Perlin noise routine to use fixed point arithmetic and turned on -O3 compiler optimizations. With these changes, the BeagleBone Black can perform the approximately 600,000 3D Perlin noise operations required to update the 6144 pixels fifty times a second at about 50% CPU utilization.</p>
<h2>The Results</h2>
<p>Below are some photos and <a href="http://youtu.be/LBeVMGOgWvY">here is a video of the six panel project in action</a>.</p>

<a href='https://bikerglen.com/blog/expanding-the-beaglebone-black-and-fpga-to-drive-6-or-more-panels/dsc_1838_2128/'><img width="150" height="150" src="https://bikerglen.com/wp/wp-content/uploads/2014/04/DSC_1838_2128-150x150.jpg" class="attachment-thumbnail" alt="576mm x 384mm RGB LED “wall” displaying a frame of Perlin noise." /></a>
<a href='https://bikerglen.com/blog/expanding-the-beaglebone-black-and-fpga-to-drive-6-or-more-panels/video-wall-rear/'><img width="150" height="150" src="https://bikerglen.com/wp/wp-content/uploads/2014/04/video-wall-rear-150x150.jpg" class="attachment-thumbnail" alt="576mm x 384mm RGB LED “wall” construction." /></a>
<a href='https://bikerglen.com/blog/expanding-the-beaglebone-black-and-fpga-to-drive-6-or-more-panels/bbb_mounting/'><img width="150" height="150" src="https://bikerglen.com/wp/wp-content/uploads/2014/04/bbb_mounting-150x150.jpg" class="attachment-thumbnail" alt="BeagleBone Black CPU board, LogiBone FPGA board, and PMOD-to-panel adapter board." /></a>
<a href='https://bikerglen.com/blog/expanding-the-beaglebone-black-and-fpga-to-drive-6-or-more-panels/wall_mounting_detail/'><img width="150" height="150" src="https://bikerglen.com/wp/wp-content/uploads/2014/04/wall_mounting_detail-150x150.jpg" class="attachment-thumbnail" alt="Wall Mounting Detail" /></a>
<a href='https://bikerglen.com/blog/expanding-the-beaglebone-black-and-fpga-to-drive-6-or-more-panels/extrusion_detail/'><img width="150" height="150" src="https://bikerglen.com/wp/wp-content/uploads/2014/04/extrusion_detail-150x150.jpg" class="attachment-thumbnail" alt="Extrusion Detail" /></a>
<a href='https://bikerglen.com/blog/expanding-the-beaglebone-black-and-fpga-to-drive-6-or-more-panels/dsc_1820/'><img width="150" height="150" src="https://bikerglen.com/wp/wp-content/uploads/2014/04/DSC_1820-150x150.jpg" class="attachment-thumbnail" alt="Sneak Preview" /></a>
<a href='https://bikerglen.com/blog/expanding-the-beaglebone-black-and-fpga-to-drive-6-or-more-panels/img_20140404_213943_802/'><img width="150" height="150" src="https://bikerglen.com/wp/wp-content/uploads/2014/04/IMG_20140404_213943_802-150x150.jpg" class="attachment-thumbnail" alt="Obligatory Generic Falling Blocks Video Game" /></a>
<a href='https://bikerglen.com/blog/expanding-the-beaglebone-black-and-fpga-to-drive-6-or-more-panels/dsc_1848/'><img width="150" height="150" src="https://bikerglen.com/wp/wp-content/uploads/2014/04/DSC_1848-150x150.jpg" class="attachment-thumbnail" alt="Bloodshot Eyeball Animated GIF" /></a>
<a href='https://bikerglen.com/blog/expanding-the-beaglebone-black-and-fpga-to-drive-6-or-more-panels/dsc_1875/'><img width="150" height="150" src="https://bikerglen.com/wp/wp-content/uploads/2014/04/DSC_1875-150x150.jpg" class="attachment-thumbnail" alt="Audio Spectrum Analyzer" /></a>
<a href='https://bikerglen.com/blog/expanding-the-beaglebone-black-and-fpga-to-drive-6-or-more-panels/dsc_1883/'><img width="150" height="150" src="https://bikerglen.com/wp/wp-content/uploads/2014/04/DSC_1883-150x150.jpg" class="attachment-thumbnail" alt="Test Pattern" /></a>
<a href='https://bikerglen.com/blog/expanding-the-beaglebone-black-and-fpga-to-drive-6-or-more-panels/dsc_1845/'><img width="150" height="150" src="https://bikerglen.com/wp/wp-content/uploads/2014/04/DSC_1845-150x150.jpg" class="attachment-thumbnail" alt="Nyan Cat" /></a>

<h2>Resources</h2>
<p>Source code for the FPGA, the software, and the frame design are available in my <a href="https://github.com/bikerglen/beagle/tree/master/projects/led-panel-6up">github repository</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://bikerglen.com/blog/expanding-the-beaglebone-black-and-fpga-to-drive-6-or-more-panels/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Driving a 32&#215;32 RGB LED Matrix with a BeagleBone Black and an FPGA</title>
		<link>https://bikerglen.com/blog/driving-a-32x32-rgb-led-matrix-with-a-beaglebone-black-and-an-fpga/</link>
		<comments>https://bikerglen.com/blog/driving-a-32x32-rgb-led-matrix-with-a-beaglebone-black-and-an-fpga/#comments</comments>
		<pubDate>Fri, 04 Apr 2014 20:33:19 +0000</pubDate>
		<dc:creator><![CDATA[Glen]]></dc:creator>
				<category><![CDATA[BeagleBone Black]]></category>
		<category><![CDATA[FPGA]]></category>
		<category><![CDATA[LED Matrix]]></category>
		<category><![CDATA[Lighting]]></category>
		<category><![CDATA[RGB LED]]></category>

		<guid isPermaLink="false">http://bikerglen.com/blog/?p=42</guid>
		<description><![CDATA[My latest project uses a BeagleBone Black and a Xilinx Spartan 6 LX9 FPGA to drive a 32&#215;32 RGB LED matrix. This project lets me display cool and interesting patterns on a matrix of 32&#215;32 RGB LEDs. That’s 1024 RGB &#8230; <a href="https://bikerglen.com/blog/driving-a-32x32-rgb-led-matrix-with-a-beaglebone-black-and-an-fpga/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>My latest project uses a BeagleBone Black and a Xilinx Spartan 6 LX9 FPGA to drive a 32&#215;32 RGB LED matrix.</p>
<div id="attachment_49" style="width: 650px" class="wp-caption alignnone"><a href="http://bikerglen.com/wp/wp-content/uploads/2014/04/IMG_1478_blog.jpg"><img class="size-large wp-image-49" title="BeagleBone Black + LogiBone FPGA board driving a SparkFun 32x32 RGB LED panel." src="http://bikerglen.com/wp/wp-content/uploads/2014/04/IMG_1478_blog-1024x683.jpg" alt="" width="640" height="426" /></a><p class="wp-caption-text">BeagleBone Black + LogiBone FPGA board driving a SparkFun 32x32 RGB LED panel.The displayed pattern is a frame from a Perlin noise pseudorandom sequence.</p></div>
<p>This project lets me display cool and interesting patterns on a matrix of 32&#215;32 RGB LEDs. That’s 1024 RGB LEDs or 3072 individual LED chips that need to be controlled! Rather than attempt to control all the LEDs in software only or using one of the BBB’s programmable real-time units (PRU), I decided to use the CPU to generate the patterns and use the FPGA to handle the heavy duty task of refreshing the LEDs.</p>
<p><span id="more-42"></span>Using the FPGA to refresh the LEDs leaves me with nearly 100% of the BBB CPU available to generate patterns and lets me implement 12-bit color at a refresh rate of 200Hz. A 200Hz refresh rate has no perceptible flicker and prevents scan lines from showing when photographing or filming the panel. A typical 12-bit color software implementation using the PRU to refresh the panels only refreshes at 50 to 60Hz.</p>
<p>Having the CPU free to compute patterns rather than refresh the display lets me generate some rather complicated patterns that otherwise might not be possible. Right now the most complicated and interesting pattern is seamlessly looping Perlin noise but other various abstract patterns, animated GIFs, text, etc., can be displayed.</p>
<p>Seamlessly looping Perlin noise running at 50Hz on 1024 pixels requires 102,400 3D Perlin noise calculations per second. Using floating point math with no compiler optimization, this quickly burns through the BBB CPU cycles. Had I attempted to refresh the panel using a small embedded processor such as an Arduino, I wouldn’t have had the CPU bandwidth available to both calculate this complicated pattern and refresh the display.</p>
<div id="attachment_68" style="width: 650px" class="wp-caption alignnone"><a href="http://bikerglen.com/wp/wp-content/uploads/2014/04/rgb-led-panel-with-power.png"><img class="size-large wp-image-68" title="rgb led panel wiring" src="http://bikerglen.com/wp/wp-content/uploads/2014/04/rgb-led-panel-with-power-1024x576.png" alt="" width="640" height="360" /></a><p class="wp-caption-text">The wiring that is required to interface the BBB and LogiBone FPGA board to the 32x32 RGB LED panel.</p></div>
<p>To build this project, I used a stock BeagleBone Black SOC board, a ValentFX LogiBone FPGA board with a Xilinx Spartan 6 LX9 FPGA, a 32&#215;32 RGB LED panel from SparkFun, and some jumper wires from Pololu Robotics. The LogiBone FPGA board was a beta unit acquired through their Kickstarter campaign. To build and simulate the FPGA, I used the free Xilinx WebPack tools. Being free, the Xilinx WebPack tools permit hobbyists (or anyone building small designs) to simulate, synthesize, map, and place and route code for a select set of Xilinx’s devices.</p>
<p>Speaking of simulation, do it! The very first bit file I loaded into the FPGA board worked the very first time I loaded it except that I had a mirror image on the display from feeding the RGB data into the display right-to-left instead of left-to-right. I reversed the order, ran another sim, and built another part. Bingo. Second try. Perfection.</p>
<p>After building everything and getting everything to work, I made a short video demonstration of the project, wrote a complete tutorial on how anyone with a BeagleBone Black, a LogiBone FPGA board, and an LED panel can replicate results, then uploaded all the required code and files to github. Below are links to the code, tutorial, and video.</p>
<p>Links to Project Files:</p>
<p><a title="Source Code" href="https://github.com/bikerglen/beagle/tree/master/projects/led-panel-v01">Source Code</a></p>
<p><a title="Step-by-Step Tutorial" href="http://bikerglen.com/projects/lighting/led-panel-1up/">Step-by-Step Tutorial</a></p>
<p><a title="Demonstration Video" href="http://youtu.be/OIyI8KaPdwk">Demonstration Video</a></p>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>https://bikerglen.com/blog/driving-a-32x32-rgb-led-matrix-with-a-beaglebone-black-and-an-fpga/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
