<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" media="screen" href="/styles/xslt/rss.xslt"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:c9="http://channel9.msdn.com">
<channel>
	<title>Channel 9 - Entries tagged with NETMF</title>
    <atom:link rel="self" type="application/rss+xml" href="http://channel9.msdn.com/Tags/netmf/RSS"></atom:link>
    <itunes:summary></itunes:summary>
    <itunes:author>Microsoft</itunes:author>
    <itunes:subtitle></itunes:subtitle>
    <image>
      <url>http://mschnlnine.vo.llnwd.net/d1/Dev/App_Themes/C9/images/feedimage.png</url>
      <title>Channel 9 - Entries tagged with NETMF</title>
      <link>http://channel9.msdn.com/Tags/netmf</link>
    </image>
    <itunes:image href=""></itunes:image>
    <itunes:category text="Technology"></itunes:category>
    <description>Channel 9 keeps you up to date with the latest news and behind the scenes info from Microsoft that developers love to keep up with. From LINQ to SilverLight – Watch videos and hear about all the cool technologies coming and the people behind them.</description>
    <link>http://channel9.msdn.com/Tags/netmf</link>
    <language>en</language>
    <pubDate>Sun, 19 May 2013 21:00:50 GMT</pubDate>
    <lastBuildDate>Sun, 19 May 2013 21:00:50 GMT</lastBuildDate>
    <generator>Rev9</generator>
    <c9:totalResults>6</c9:totalResults>
    <c9:pageCount>1</c9:pageCount>
    <c9:pageSize>25</c9:pageSize>
  <item>
      <title>Maelstrom: An Overview</title>
      <description><![CDATA[<p>For <a href="http://buildwindows.com/">//build/ 2012</a>, we wanted to showcase what Windows 8 can offer developers.&nbsp; There are a lot of projects showing off great things like contracts and Live Tiles, but we wanted to show off some of the lesser known features.&nbsp; This project focuses on one of those: stereoscopic 3D with DirectX 11.1.</p><p>Prior to DirectX 11.1, stereoscopic 3D required specific hardware and a custom API written for that hardware.&nbsp; With DX11.1, stereoscopic 3D has been &quot;democratized.&quot;&nbsp; Any GPU that supports DirectX 11.1 can be connected to any device which supports stereoscopic 3D, be it a projector, an LCD TV, or anything else.&nbsp; Plug it in and DirectX does the rest.</p><p>From the software side of things, any DX11.1 application can determine if the connected display supports stereoscopic 3D, and choose to render itself separately for the player's left and right eye.</p><p>To showcase this feature, we decided to build a very simple game that would give the illusion of depth, but be easy to explain and play.&nbsp; What's easier than <a href="http://en.wikipedia.org/wiki/Pong">Pong</a>?&nbsp; So, we built the world's most over-engineered game of 3D Pong named Maelstrom.</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/WP_000414%5B6%5D.jpg"><img title="WP_000414" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/WP_000414_thumb%5B3%5D.jpg" alt="WP_000414" width="640" height="480" border="0"></a></p><h2>Software</h2><p>Each player setup consists of two applications: the DirectX 11.1 game written in C&#43;&#43;, and the touch-screen controller written in C#/XAML.&nbsp; Both are Windows Store applications.&nbsp; Since this is a two player game, there are two instances of each application running, one per player.&nbsp; All for applications are networked together using <strong>StreamSocket</strong>s from the Windows Runtime.&nbsp; The two controllers and player two's DirectX game connect to player one's DirectX game, which acts as the &quot;master&quot;.&nbsp; Controller input is sent here, and, once the ball and paddle positions are calculated, the data is drawn for player one and sent to player two which draws the world from the other player's perspective.</p><p><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B3%5D-2.png" alt="image" width="640" height="269" border="0"></p><h3>Direct3D Application</h3><h2>Getting Started with stereoscopic DirectX11, C&#43;&#43;, and XAML</h2><p>If you have never worked with DirectX before, it can be a little overwhelming at first. And even if you have worked with it some in the past, targeting the new Windows 8 ecosystem, along with C&#43;&#43; and XAML have added some additional changes in how you may have designed your solution previously.</p><p>Fortunately, the <a href="http://dev.windows.com/">Windows Dev Center</a> for Windows Store Apps has some great samples to get you started, and we took full advantage of them to get to speed. For a great, simple example of how to leverage the new stereoscopic feature in Direct3D 11.1, we started with <a href="http://code.msdn.microsoft.com/windowsapps/Direct3D-111-Simple-Stereo-9b2b61aa/view/SourceCode#content">Direct3D Stereoscopic Sample</a> which shows the basic adjustments to the Render loop for toggling your virtual cameras. However, to see a great example of a simple game structure that also leverages stereoscopic rendering where available, the tutorial found at <a href="http://msdn.microsoft.com/en-us/library/windows/apps/Hh780567.aspx">Walkthrough: a simple Windows Store game with DirectX</a> is invaluable. Further in this article, we will dive deeper into the specifics of stereoscopic rendering in our game.</p><p>One thing to note, if you follow the link in the above Walkthrough to the original project, it will take you to a C&#43;&#43; only implementation of the game. Now, of course, all the DirectX game objects such as the paddle, puck and walls are all rendered using D3D. However, for HUD (Heads up Display) elements, this C&#43;&#43; only sample also uses DirectX exclusively. If you are coming from a managed code background, this will definitely seem like unnecessary overhead. That is because this C&#43;&#43; only sample was created after last year's BUILD conference in 2011 and C&#43;&#43; and DirectX still did not play well with XAML.</p><p>However, a few months later, the ability to nest DirectX content in a XAML project became available for true hybrid style solutions (see the article <a href="http://msdn.microsoft.com/en-us/library/windows/apps/hh825871.aspx">DirectX and XAML interop - Windows Store apps using C&#43;&#43; and DirectX</a> for more information). After this feature was added, the simple Shooter Game referenced above had its HUD logic rewritten in XAML and posted up to Dev Center as <a href="http://code.msdn.microsoft.com/windowsapps/Metro-style-DirectX-18f98448#content">XAML DirectX 3D shooting game sample</a>, which shows both stereoscopic support, a simple Game Engine structure in C&#43;&#43; and XAML integration. At this point, we had all the starter code we needed to start writing our own game.</p><h2>Game Engine</h2><p>We modified the base sample to accommodate our needs.&nbsp; We created specific <strong>GameObject</strong>s, such as <strong>Paddle</strong>, <strong>Puck</strong>, etc. to add the behaviors we needed.&nbsp; We also added an <strong>Update</strong> and <strong>Render</strong> method to the base <strong>GameObject</strong> so that, for every frame, we could do any calculations required, and then draw the object to the screen.&nbsp; This is very similar to how XNA sets up its game engine.</p><h2>Game Constants</h2><p>Because we were tweaking a variety of values like colors, sizes, camera locations, etc., we created a <strong>GameConstants.h</strong> header file which contains nothing but these types of values in a single location.&nbsp; This made it very easy for us to quickly try out various tweaks and see the results on the next run.&nbsp; Using namespaces helped keep the code a bit more manageable here as well.&nbsp; Here’s a quick snippet of that file:</p><p><pre class="brush: csharp">
namespace GameConstants
{
    // bounds of the arena
    static const DirectX::XMFLOAT3 MinBound    = DirectX::XMFLOAT3( 0.0f,  0.0f,  0.0f);
    static const DirectX::XMFLOAT3 MaxBound    = DirectX::XMFLOAT3(19.0f, 10.0f, 90.0f);

    // game camera &quot;look at&quot; points
    static const DirectX::XMFLOAT3 LookAtP1    = DirectX::XMFLOAT3(9.5f, 5.0f, 90.0f);
    static const DirectX::XMFLOAT3 LookAtP2    = DirectX::XMFLOAT3(9.5f, 5.0f,  0.0f);

    // Waiting Room camera positions
    static const DirectX::XMFLOAT3 WaitingEyeP1                = DirectX::XMFLOAT3(GameConstants::MaxBound.x/2, GameConstants::MaxBound.y/2, GameConstants::MaxBound.z - 12.0f);
    static const DirectX::XMFLOAT3 WaitingEyeP2                = DirectX::XMFLOAT3(GameConstants::MaxBound.x/2, GameConstants::MaxBound.y/2, GameConstants::MinBound.z &#43; 12.0f);
    static const DirectX::XMFLOAT3 WaitingEyeMjpegStation    = DirectX::XMFLOAT3(GameConstants::MaxBound.x/2, GameConstants::MaxBound.y/2, GameConstants::MinBound.z &#43; 9.6f);

    // game camera eye position
    static const DirectX::XMFLOAT3 EyeP1        = DirectX::XMFLOAT3(GameConstants::MaxBound.x/2, GameConstants::MaxBound.y/2, GameConstants::MinBound.z - 6.0f);
    static const DirectX::XMFLOAT3 EyeP2        = DirectX::XMFLOAT3(GameConstants::MaxBound.x/2, GameConstants::MaxBound.y/2, GameConstants::MaxBound.z &#43; 6.0f);

    static const float Paddle2Position    = MaxBound.z - 5.0f;

    namespace PaddlePower
    {
        // power level to light paddle at maximum color
        static const float Max                    = 9.0f;

        // max paddle power color...each component will be multiplied by power factor
        static const DirectX::XMFLOAT4 Color    = DirectX::XMFLOAT4(0.2f, 0.4f, 0.7f, 0.5f);
    
        // factor to multiply mesh percentage based on power
        static const float MeshPercent            = 1.2f;
    };
    
    // time to cycle powerups
    namespace Powerup
    {
        namespace Split
        {
            static const float Time                        = 10.0f;
            static const float NumTiles                    = 4;
            static const DirectX::XMFLOAT4 TileColor    = DirectX::XMFLOAT4(0.1f, 0.4f, 1.0f, 1.0f);
            static const float TileFadeUp                = 0.20f;
            static const float TileDuration                = 2.10f;
            static const float TileFadeDown                = 0.20f;
            static const float TileMeshPercent            = 2.0f;
            static const float TileDiffusePercent        = 2.0f;
        };
    };
}
</pre></p><h2>Stereoscopic 3D</h2><p>Direct3D must be initialized properly to support stereoscopic displays.&nbsp; When the swap chains are created, an additional render target is required, such that one render target is for the left eye, and one render target is for the right eye.&nbsp; Direct3D will let you know if a stereoscopic display is available, so you can create the swap chain and render targets appropriately.</p><p>With those in place, it’s simply a matter of rendering your scene twice, once per eye…that is, once per render target.</p><p>For our game this was very simple.&nbsp; Our in-game camera contains two projection matrices, one representing the view from the left eye, and one from the right eye.&nbsp; These are calculated when the projection parameters are set.</p><p><pre class="brush: cpp">
void Camera::SetProjParams(
    _In_ float fieldOfView,
    _In_ float aspectRatio,
    _In_ float nearPlane,
    _In_ float farPlane
    )
{
    // Set attributes for the projection matrix.
    m_fieldOfView = fieldOfView;
    m_aspectRatio = aspectRatio;
    m_nearPlane = nearPlane;
    m_farPlane = farPlane;
    XMStoreFloat4x4(
        &amp;m_projectionMatrix,
        XMMatrixPerspectiveFovLH(
            m_fieldOfView,
            m_aspectRatio,
            m_nearPlane,
            m_farPlane
            )
        );

    STEREO_PARAMETERS* stereoParams = nullptr;
    // Update the projection matrix.
    XMStoreFloat4x4(
        &amp;m_projectionMatrixLeft,
        MatrixStereoProjectionFovLH(
            stereoParams,
            STEREO_CHANNEL::LEFT,
            m_fieldOfView,
            m_aspectRatio,
            m_nearPlane,
            m_farPlane,
            STEREO_MODE::NORMAL
            )
        );

    XMStoreFloat4x4(
        &amp;m_projectionMatrixRight,
        MatrixStereoProjectionFovLH(
            stereoParams,
            STEREO_CHANNEL::RIGHT,
            m_fieldOfView,
            m_aspectRatio,
            m_nearPlane,
            m_farPlane,
            STEREO_MODE::NORMAL
            )
        );
}
</pre></p><p>Depending on which eye we are rendering, we grab the appropriate projection matrix and pass it down to the vertex shader, so the final scene is rendered offset for the proper eye.</p><h2>Collision Detection</h2><p>If you are just starting to move into 3D modeling and programming, one of the trickier aspects of your game can be collision detection and response. Maelstrom uses primitives for all of the game elements, so our collision code was able to be a bit more straightforward compared to complex mesh collisions, but understanding a few core math concepts is still critical to grasp what the code is doing.</p><p>Fortunately, DirectX provides us with an <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ee415571%28v=vs.85%29.aspx">DirectX Math Library</a> that is able to do the serious heavy lifting, so the main complexity comes from framing the problem and learning how to apply the library.</p><p>For example, In our situation we had up to three very fast moving spheres and needed to check for wall collisions and then handle to appropriate bounce, since some of the walls would also be angled. In a 2D game, a collision detection between a sphere and an axis line is very easy. If the distance between a circle and the line is less than or equal to the radius of the sphere, they are touching. On every frame, you move your circle based on its velocity and do your collision test again. But even here, your solution may not be that easy for two reasons.</p><p>First, what if the line is angled and not lying flat on the X or Y axis? You have to find the point on the line based on the line's angle that is closest to the sphere to do your distance calculations. And if you then want it to bounce, you have to rotate the velocity of the circle by the line's angle, calculate your bounce, and then rotate back. And that's just rotated walls in 2D. When you move up to 3D, you have to take into account the surface normal&nbsp; (which way the 3D plane is facing) in your calculations.</p><p>The second complexity that we needed to account for and which pops up in either 2D or 3D collision detection is travel between frames. In other words, if your ball is travelling very fast, it may have completely travelled through your collision boundary in between frames and you wouldn't notice it if you are only doing a distance / overlap check as outlined above. In our case, the pucks had the ability of travelling very fast with a speed boost, so we needed a more robust solution. Therefore, instead of implementing a simple sphere plane intersection test, we needed to create a line of motion that represented where the ball ended on the previous frame and where it currently is after it's new velocity is added to it's position. That line then needs to first be tested to see if it crosses a WallTile. If it does cross, then we know an collision has occurred between frames. We then solve for the time (t) between frames the Sphere would have first made contact to know the exact point of impact and calculate the appropriate &quot;bounce off&quot; direction.</p><p>The final code for a puck (or moving sphere) and wallTile collision test looks like this:</p><p><pre class="brush: cpp">
bool GameEngine::CheckWallCollision(Puck^ puck)
{
    bool isIntersect = false;
    bool wallCollision = false;

    for(unsigned int i = 0; i &lt; m_environmentCollisionWalls.size(); i&#43;&#43;)
    {
        WallTile^ wall = m_environmentCollisionWalls[i];
        float radius = puck-&gt;Radius();
        float signedRadius = puck-&gt;Radius();
        float contactTime = 0.0f;
        XMVECTOR contactPlanePoint = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f);
        XMVECTOR contactPuckPosition = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f);

        bool intersectsPlane = false;

        // Determine the velocity of this tick by subtracting the previous position from the proposed current position.
        // in the previous update() cycle, puck-&gt;Position() = puck-&gt;OldPosition() &#43; ( puck-&gt;velocity * timerDelta ).
        // Therefore, this calculated velocity for the current frame movement differs from the stored velocity
        // since the stored velocity is independent of each game tick's timerDelta.
        XMVECTOR puckVectorVelocity = puck-&gt;VectorPosition() - puck-&gt;OldVectorPosition();
        float D = XMVectorGetX( XMVector3Dot( wall-&gt;VectorNormal(), wall-&gt;VectorPosition() ) );

        // Determine the distance of the puck to the plane of the wall.
        float dist = XMVectorGetX( XMVector3Dot(wall-&gt;VectorNormal(), puck-&gt;OldVectorPosition() )) - D;
        signedRadius = dist &gt; 0 ? radius : -radius;

        // if the distance of the puck to the plane is already less than the radius, the oldPosition() was intersecting already
        if ( fabs(dist) &lt; radius )
        {
            // The sphere is touching the plane.
            intersectsPlane = true;
            contactTime = 0.0f;
            contactPuckPosition = puck-&gt;OldVectorPosition();
            contactPlanePoint = puck-&gt;OldVectorPosition() &#43; wall-&gt;VectorNormal()*XMVectorSet(signedRadius,signedRadius,signedRadius,1.0f);
        }
        else
        {
            // See if the time it would take to cross the plane from the oldPosition() with the current velocity falls within this game tick.
            // puckVelocityNormal is the amount of force from the velocity exerted directly toward the plane.
            float puckVelocityNormal = XMVectorGetX(XMVector3Dot(wall-&gt;VectorNormal(), puckVectorVelocity ));
            // if the puckvVelocityNormal times the distance is less than zero, a plane intersection will occur
            if ( puckVelocityNormal * dist &lt; 0.0f )
            {
                // determine the contactTime, taking into account the shell of the sphere ( position() &#43; radius )
                // is what will make contact, not the position alone.
                contactTime =  (signedRadius - dist) / puckVelocityNormal;
                // if the contact time is bewteen zero and one, the intersection has occured bewteen oldPosition() and position()
                if ( contactTime &gt; 0.0f &amp;&amp; contactTime &lt; 1.0f )
                {
                    intersectsPlane = true;
                    // this is the position of the puck when its shell makes contact on the plane
                    contactPuckPosition = puck-&gt;OldVectorPosition() &#43; XMVectorScale(puckVectorVelocity, contactTime);
                    // this is the position on the plane where the shell touches.
                    contactPlanePoint = contactPuckPosition - XMVectorScale(wall-&gt;VectorNormal(), signedRadius);
                }
            }
        }

        // If the puck has contacted the wall plane, determine if the point of contact falls within the wall boundary for true contact.
        if (intersectsPlane)
        {
            float Kr = 1.0f; // Kr is the coefficient of restitution. At 1.0, we have a totally elastic bounce with no dampening. At Kr = 0.0, the ball would stop at the wall.

            // Make sure the puck velocity and wall normal are facing each other
            float impact = XMVectorGetX ( XMVector3Dot ( wall-&gt;VectorNormal(), puck-&gt;VectorVelocity()) );
            if (impact &lt; 0.0f)
            {
                wallCollision = true;

                //// bounce the vector off the plane
                XMVECTOR VectorNormal = XMVector3Dot(wall-&gt;VectorNormal(), puck-&gt;VectorVelocity())*wall-&gt;VectorNormal();
                XMVECTOR VectorTangent = puck-&gt;VectorVelocity() - VectorNormal;

                puck-&gt;Velocity(VectorTangent - (XMVectorScale(VectorNormal, Kr)));
                puck-&gt;Position(contactPuckPosition);

                int segment = (int)(puck-&gt;Position().z / GameConstants::WallSegmentDepth);
                segment = max(min(segment, GameConstants::NumWallSegments-1), 0);

                auto tiles = m_wallTiles[segment];
                WallTile^ tile = tiles[i];
                if(tile-&gt;GetPowerup() == Powerup::Split)
                    SplitPucks();

                break;
            }
        }
    }

    return wallCollision;
}
</pre></p><h2>Drawing Maelstrom</h2><p>To draw the game, we wanted to use some advanced techniques. We decided to go with a light pre-pass deferred rendering pipeline with normal mapping. That’s a lot of jargon but it isn’t all that complicated once you know what the jargon means, so let’s break it down.</p><p>When you draw something in 3D, there are three things that come together to determine the final color of each pixel on the screen: meshes, materials, and lights. A mesh is a collection of triangles that make up a game object (such as a wall tile in Maelstrom). On its own, a mesh is just a bunch of dots and lines. A material makes a mesh look like something. It could be as simple as a solid color but usually it’s a texture and sometimes it’s more (the wall tiles in Maelstrom use both a texture and a normal map to define their material properties). Lastly, lights transform materials by determining how bright they should appear and what sort of tint, if any, they should have. Without lights you would either have complete darkness or you would have flat lighting (where everything has a uniform brightness and adding a tint color would uniformly tint everything on the screen).</p><h2>Forward Rendering vs. Deferred Rendering vs. Light Pre-Pass Rendering</h2><p>The simplest approach to drawing 3D graphics is something called forward rendering. With forward rendering, drawing consists of rendering the mesh and calculating its material and all the lights that affect the material all at the same time. The more lights you add, the more complicated your shaders become since you have to determine whether each light affects the material and if so how much. (Ok, so there’s also multi-pass forward rendering, but that has its own problems – more passes mean longer render times and thus a lower frame rate – and we wanted to keep the descriptions simple).</p><p>In the last 5 years, many games started using a technique called deferred rendering. In classic deferred rendering, there are two rendering passes. The first pass renders the positions, normals, and material values of all the meshes in the scene to something called a G-Buffer (two or more render targets); nothing is actually drawn to the screen in this first pass. The second pass uses the data from the G-Buffer (which tells us everything we need to know about the geometry that appears at each screen pixel) and combines it with the lights to create the final image that you see. By doing this, we decouple geometry and lighting. This makes it possible to add more lights to the scene with a much smaller performance impact than in forward rendering since we don’t need to create a really complex pixel shader to handle all the lights (single-pass forward rendering) or draw the geometry over and over again for each light (multi-pass forward rendering).</p><p>There are drawbacks to classic deferred rendering though. Even a minimal G-Buffer takes up quite a bit of memory and the more different types of materials you want to support, the larger the G-Buffer will need to be. Wolfgang Engel, an XNA/DirectX MVP, came up with a variation on deferred rendering which he called <a href="http://diaryofagraphicsprogrammer.blogspot.com/2008/03/light-pre-pass-renderer.html">Light Pre-Pass Rendering</a>. This is a three pass technique. We once again use a G-Buffer, but in this case it is smaller than the classic deferred rendering G-Buffer and can even be squeezed down to a single render target which makes it viable for graphics hardware which does not support drawing to multiple render targets at the same time.</p><p>The G-Buffer is created in the first pass by rendering all the scene geometry. It only needs to store normals and the geometry’s world position. We stored the world position of the geometry at that screen position in one render target and its normal at that screen position in second render target for simplicity.</p><p>The next pass draws the lights to a light accumulation buffer. The buffer starts out entirely dark and each light that is rendered adds brightness (and tint, if any) to the light buffer. These lighting calculations take into account the normal and world position of the geometry that is at each screen position, drawing the values from the G-Buffer, such that each light only affects the pixels it is supposed to have an impact on. In Maelstrom we ended up only using point lights (spheres of light that fade out as you get further from the light’s position), but you can use any kind of light you can imagine (spot lights and directional lights are the two other common light types). Adding more lights has a very low impact on rendering time and this kind of lighting tends to be much easier for the designer to work with since there’s no need for him or her to understand HLSL or even any complicated C&#43;&#43; in order to add, remove, reposition, or otherwise change any lights.</p><p>The final pass draws the geometry a second time. This time, though, all the lighting calculations are done so all we do here is just render the meshes with their appropriate materials, adjust the color values and intensities from the material based on the light buffer value, and we’re done. Each rendering style (forward, deferred, and light pre-pass) has its own benefits and drawbacks, but in this case light pre-pass was a good solution and choosing it let us show how a state-of-the-art graphics technique works.</p><h2>Normal Mapping</h2><p>We also incorporated normal mapping. Normal mapping makes us of a special texture (a normal map) in addition to the regular texture that a material has. Normals are values used in lighting calculations to determine how much a particular light should affect a particular pixel. If you wanted to draw a brick wall, you would typically create two triangles that lined up to form a rectangle and you would apply a texture of a brick wall to them as their material. The end result of that doesn’t look very convincing though since unlike a real brick wall there are no grooves in the mortared area between each brick since our brick and mortar is just a flat texture applied to flat triangles. We could fix this by changing from two triangles to a fully modeled mesh with actual grooves, but that would add thousands of extra vertices which would lower the frame rate.</p><p>So instead we use a normal map, which fakes it. One of the reasons that the two triangles &#43; a brick wall texture approach doesn’t look right is because the lighting doesn’t behave correctly when compared to a real brick wall (or to a fully modeled mesh of a real brick wall). The normals point straight out perpendicular from the face of the rectangle whereas if we had the fully modeled mesh with actual grooves, the surface normals would only point straight out on the bricks themselves and they would curve along the mortared areas such that the lighting calculations would end up giving us the right levels of light and dark depending on the location and direction of the light. That’s where a normal map comes in. The normal map (which you can generate using a plugin for Adobe Photoshop or GIMP or by modeling a real brick wall in 3DSMax, Maya, or Blender which you then “bake” a normal map from) allows us to get the same lighting effect as we would with a fully modeled mesh while still keeping the simple two triangle &#43; a brick wall texture approach that gives us really good performance for our game. There are limits to the effectiveness of normal mapping (you can’t use it to fake anything too deep and it doesn’t hold up as well if the camera can get really close to the object) but in Maelstrom it allowed us to keep the walls as simple triangles (like the two triangles &#43; a brick wall texture example above) while making it seem like there were geometric grooves in the wall. Here’s a before and after screenshot using normal mapping:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/MaelstromNoBloomNoNormalMapping%5B9%5D.png"><img title="MaelstromNoBloomNoNormalMapping" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/MaelstromNoBloomNoNormalMapping_thumb%5B8%5D.png" alt="MaelstromNoBloomNoNormalMapping" width="640" height="360" border="0"></a></p><p>&nbsp;</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/MaelstromWithoutBloom%5B2%5D.png"><img title="MaelstromWithoutBloom" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/MaelstromWithoutBloom_thumb.png" alt="MaelstromWithoutBloom" width="640" height="360" border="0"></a></p><h2>Post-Processing Effects</h2><p>We also used several post-processing effects. The first was the bloom effect. Bloom is an effect that analyzes a rendered image, identifies parts that are above a certain brightness threshold, and makes those areas brighter and adds a peripheral glow to them as well, giving it a look and feel that is similar to a neon sign or to the light cycles in the movie <em>Tron</em>. Here’s the same shot as above with the addition of bloom:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/MaelstromWithNormalMapping%5B27%5D.png"><img title="MaelstromWithNormalMapping" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/MaelstromWithNormalMapping_thumb%5B18%5D.png" alt="MaelstromWithNormalMapping" width="640" height="360" border="0"></a></p><p>We also made use of two different damage effects. Whenever the player took damage, we had a reddish tinge around the edge of the screen. This was simply a full screen overlay texture that is actually white but is tinted red by the shader. It is alpha-blended over the final rendered scene and fades out over the course of a couple of seconds. Rather than fading out linearly, we use a power curve which helps to sell the effect as being more complicated than it really is.</p><p>Lastly we added in some damage particles. The particles themselves were created using a geometry shader. The vertex shader took in a series of points in world space and passed these points along to the geometry shader. The geometry shader expanded these points into two triangles by generating the missing vertices and applying the world-view-projection transformation matrix to transform the positions from world coordinates to homogeneous coordinates so that they can then be rasterized correctly by D3D and the resulting pixels passed along to the pixel shader. Once again we used a simple texture with alpha blending to simulate much more complicated geometry than we were actually drawing. In this case we also made use of a texture atlas (an image made up of smaller images) which, in conjunction with the randomizer we used to generate the initial vertices for the particles, allowed us to have several different particle textures. Like with the power curve for the damage texture, the texture atlas allowed us to make the particles seem more complex than they really were. It also let us show off the use of a geometry shader, a feature that was added in DirectX 10 and requires DirectX 10 or higher hardware.</p><h3>Audio</h3><p>All audio was done using the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ee415737%28v=vs.85%29.aspx">XAudio2 API</a>.&nbsp; Thankfully, we were able to get a huge head start by using some of the code from the sample project we started from.&nbsp; The audio engine sets up the very basics of XAudio2, and then wraps that with a simpler API for the rest of the application to call.</p><p>We don’t have many sound effects, so we on startup, we load all sounds effects and music cues into a <strong>std::map</strong>, keyed on a <strong>SoundCue</strong> enum.&nbsp; Sounds are loaded using the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms694197%28v=vs.85%29.aspx">Media Foundation</a> classes, and the resulting byte data of the sound (and some format information) are stored in our <strong>SoundEffect</strong> class.</p><p><pre class="brush: cpp">
void AudioEngine::Initialize()
{
    m_audio = ref new Audio();
    m_audio-&gt;CreateDeviceIndependentResources();

    m_mediaReader = ref new MediaReader();

    // Impacts
    m_soundMap[SoundCue::BallLaunch]    = LoadSound(&quot;Sounds\\Impacts\\BallLaunch.wav&quot;);
    m_soundMap[SoundCue::Buzz]          = LoadSound(&quot;Sounds\\Impacts\\Buzz.wav&quot;);
    m_soundMap[SoundCue::Impact1]       = LoadSound(&quot;Sounds\\Impacts\\Impact1.wav&quot;);
    m_soundMap[SoundCue::Impact2]       = LoadSound(&quot;Sounds\\Impacts\\Impact2.wav&quot;);

...

}

SoundEffect^ AudioEngine::LoadSound(String^ filename)
{
    Array&lt;byte&gt;^ soundData = m_mediaReader-&gt;LoadMedia(filename);
    auto soundEffect = ref new SoundEffect();
    soundEffect-&gt;Initialize(m_audio-&gt;SoundEffectEngine(), m_mediaReader-&gt;GetOutputWaveFormatEx(), soundData);
    return soundEffect;
}
</pre></p><p>When the game needs to play a sound, it simply calls the <strong>PlaySound</strong> method, passing in the cue to play, and the volume to play it at.&nbsp; <strong>PlaySound</strong> keys into the sound map, getting the associated <strong>SoundEffect</strong>, and plays it.</p><p><pre class="brush: cpp">
void AudioEngine::PlaySound(SoundCue cue, float volume, bool loop)
{
    m_soundMap[cue]-&gt;Play(volume, loop);
}
</pre></p><h3>MJPEG Cameras</h3><p>To achieve the effect of seeing the opponent in stereoscopic 3D, we strapped two <a href="http://www.axis.com/products/cam_m1014/">Axis M1014</a> network cameras side-by-side.&nbsp; Using Brian’s <a href="http://mjpeg.codeplex.com/">MJPEG Decoder</a> library, with a special port to Windows Runtime, individual JPEG frames were pulled off each camera, and then applied to a texture at the back of the arena.&nbsp; The image from the left camera is drawn when DirectX renders the player’s left eye, and the frame from the right camera is drawn when DirectX renders the right eye.&nbsp; This is a cheap and simple way to pull off live stereoscopic 3D.</p><p><pre class="brush: cpp">
void MjpegCamera::Update(GameEngine^ engine)
{
    if(m_decoderLeft != nullptr)
        UpdateTexture(m_decoderLeft-&gt;CurrentFrame, &amp;textureLeft);

    if(m_decoderRight != nullptr)
        UpdateTexture(m_decoderRight-&gt;CurrentFrame, &amp;textureRight);

    Face::Update(engine);
}

void MjpegCamera::Render(_In_ ID3D11DeviceContext *context, _In_ ID3D11Buffer *primitiveConstantBuffer, _In_ bool isFirstPass, int eye)
{
    if(eye == 1 &amp;&amp; textureRight != nullptr)
        m_material-&gt;SetTexture(textureRight.Get());
    else if(textureLeft != nullptr)
        m_material-&gt;SetTexture(textureLeft.Get());

    GameObject::Render(context, primitiveConstantBuffer, isFirstPass);
}
</pre></p><p>With the distance between the cameras being about the distance of human eyes (called the intra-axial distance), the effect works pretty well!</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/IMG_0284%5B5%5D.jpg"><img title="IMG_0284" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/IMG_0284_thumb%5B3%5D.jpg" alt="IMG_0284" width="640" height="480" border="0"></a></p><h3>Tablet/Controller</h3><p>The Tablet controller is the touch screen that lets the player control their 3D paddle in the Game Console app. For this part of the game system, there wasn't a reason to dive deep into DirectX and C&#43;&#43; since the controller is neither stereoscopic or visually intense, so we kept things simple with C#.</p><p>Since the controller would also serve as our attract screen in the podium to entice potential players, we wanted to have the wait screen do something eye-catching. However, if you are moving from C# in WPF to C# and XAML in WinRT and are used to taking advantage of some of the more common &quot;memory hoggish UX hacks&quot; from WPF, you'll quickly find them absent in WinRT! For example, we no longer have <strong>OpacityMask</strong>, non-rectangular clipping paths or the ability to render a <strong>UIElement</strong> to a Bitmap. Our bag of UX tricks may be in need of an overhaul. However, what we do get in C# / XAML for WinRT is Z rotation, which is something we've had in Silverlight but I personally have been begging for in WPF for a long time.</p><p>Therefore, the opening animation in the controller is a procedurally generated effect that rotates PNG &quot;blades&quot; in 3D space, creating a very compelling effect. Here is how it works. The <strong>Blade</strong> user control is a simple canvas that displays one of a few possible blade images. The <strong>Canvas</strong> has a <strong>RenderTransform</strong> to control the scale and rotation and a <strong>PlaneProjection</strong> which allows us to rotate the blade graphic in X, Y and Z space.</p><p><pre class="brush: xml">
&lt;Canvas&gt;
    &lt;Canvas.RenderTransform&gt;
        &lt;ScaleTransform x:Name=&quot;scale&quot; ScaleX=&quot;1.0&quot; ScaleY=&quot;1.0&quot; CenterX=&quot;0&quot; CenterY=&quot;0&quot;/&gt;
    &lt;/Canvas.RenderTransform&gt;
    &lt;Canvas.Projection&gt;
        &lt;PlaneProjection x:Name=&quot;projection&quot; CenterOfRotationX=&quot;0&quot; CenterOfRotationY=&quot;0&quot; CenterOfRotationZ=&quot;0&quot; RotationX=&quot;00&quot; RotationY=&quot;0&quot; RotationZ=&quot;0&quot;/&gt;
    &lt;/Canvas.Projection&gt;
    &lt;Image x:Name=&quot;img0&quot; Width=&quot;300&quot; Height=&quot;100&quot; Canvas.Left=&quot;-4&quot; Canvas.Top=&quot;-12&quot; Source=&quot;Images/s0.png&quot;/&gt;
&lt;/Canvas&gt;
</pre></p><p>Each Blade is added dynamically to the Controller when the Tablet application first loads, stored in a <strong>List</strong> to have it's <strong>Update</strong>() method called during the <strong>CompositionTarget</strong>.<strong>Rendering</strong>() loop.</p><p><pre class="brush: csharp">
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    canvas_blades.Children.Clear();
    _blades.Clear();
    
    for (int i = 0; i &lt; NumBlades; i&#43;&#43;)
    {
        Blade b = new Blade { X = 950.0, Y = 530.0 };
        int id = _rand.Next(0, 5);
        b.SetBlade(id);
        b.Speed = .1 &#43; id * .1;
        SeedBlade(b);
        _blades.Add(b);
        canvas_blades.Children.Add(b);
    }
}

void CompositionTarget_Rendering(object sender, object e)
{
    if(_inGame)
    {
        paddle.Update();
    }
    else if(_isClosing)
    {
        foreach (Blade b in _blades)
            b.UpdateExit();
    }
    else
    {
        foreach (Blade b in _blades)
            b.Update();
    }
}
</pre></p><p>Since each Blade has been assigned an individual speed and angle of rotation along all three axis, they have a very straightforward <strong>Update</strong> function. The reason we keep the rotation values between -180 and 180 during the spinning loop is to make it easier to spin them out zero when we need them to eventually leave the screen.</p><p><pre class="brush: csharp">
public void Update()
{
   _rotX &#43;= Speed;
   _rotZ &#43;= Speed;
   _rotY &#43;= Speed;

   if (_rotX &gt; 180) _rotX -= 360.0;
   if (_rotX &lt; -180) _rotX &#43;= 360.0;
   if (_rotY &gt; 180) _rotY -= 360.0;
   if (_rotY &lt; -180) _rotY &#43;= 360.0;
   if (_rotZ &gt; 180) _rotZ -= 360.0;
   if (_rotZ &lt; -180) _rotZ &#43;= 360.0;

   projection.RotationX = _rotX;
   projection.RotationY = _rotY;
   projection.RotationZ = _rotZ;
}

public void UpdateExit()
{
   _rotX *= .98;
   _rotZ *= .98;
   _rotY &#43;= (90.0 - _rotY) * .1;

   projection.RotationX = _rotX;
   projection.RotationY = _rotY;
   projection.RotationZ = _rotZ;
}
</pre></p><h3>&nbsp;</h3><h3>Network</h3><p>To continue the experiment of blending C# and C&#43;&#43; code, the network communication layer was written in C# as a Windows Runtime component.&nbsp; Two classes are key to the system: <strong>SocketClient</strong> and <strong>SocketListener</strong>.&nbsp; Player one’s game console starts a <strong>SocketListener</strong> to listen for incoming connections from each game controller, as well as player two’s game console.&nbsp; Each of those use a <strong>SocketClient</strong> object to make the connection.</p><p>In either case, once the connection is made, the client and the listener sit and wait for data to be transmitted.&nbsp; Data must be sent as an object which implements our <strong>IGamePacket</strong> interface.&nbsp; This contains two important methods: <strong>FromDataReaderAsync</strong> and <strong>WritePacket</strong>.&nbsp; These methods serialize and deserialze the byte data to/from an <strong>IGameState</strong> packet of whatever type is specified in the <strong>PacketType</strong> property.</p><p><pre class="brush: cpp">
namespace Coding4Fun.Maelstrom.Communication
{
    public enum PacketType
    {
        UserInputPacket = 0,
        GameStatePacket
    }
    
    public interface IGamePacket
    {
        PacketType Type { get; }
        
        IAsyncAction FromDataReaderAsync(DataReader reader);
        void WritePacket(DataWriter writer);
    }
}
</pre></p><p>The controllers write <strong>UserInputPacket</strong>s to the game console, consisting of X,Y positions of the paddle, as well as whether the player has tapped the screen to begin.</p><p><pre class="brush: csharp">
public sealed class UserInputPacket : IGamePacket
{
    public PacketType Type { get { return PacketType.UserInputPacket; } }
    
    public UserInputCommand Command { get; set; }
    public Point3 Position { get; set; }
}
</pre></p><p>Player one’s game console writes a <strong>GameStatePacket</strong> to player' two’s game console, which consists of the positions of each paddle, each ball, the score, and which tiles are lit for the ball splitter power up.&nbsp; Player two’s <strong>Update</strong> and <strong>Render</strong> methods use this data to draw the screen appropriately.</p><h3>Hardware</h3><p>The hardware layer of this project is responsible for two big parts.&nbsp; One is a rumble effect that fires every time the player is hit, and the other is a lighting effect that changes depending on the game state.</p><p>As all good programmers do, we reused code from another project.&nbsp; We leveraged the proven web server from <a href="http://channel9.msdn.com/coding4fun/articles/Project-Detroit-An-Overview">Project Detroit</a> for our Netduino, but with a few changes.&nbsp; Here, we had static class “modules” which knew how to talk to the physical hardware, and “controllers” which handled items like a player scoring, game state animations, and taking damage.&nbsp; Because the modules are static classes, we can have them referenced in multiple classes without issue.</p><h2>NETMF Web Server</h2><p>When a request comes in, we perform the requested operation, and then return a new line character to verify we got the request. If you don’t return any data, some clients will actually fire a second request which then can cause some odd behaviors.&nbsp; The flow is as follows:</p><ol><li>Parse the URL </li><li>Get the target controller </li><li>Execute the appropriate action </li></ol><p><pre class="brush: csharp">
private static void WebServerRequestReceived(Request request)
{
    var start = DateTime.Now;
    Logger.WriteLine(&quot;Start: &quot; &#43; request.Url &#43; &quot; at &quot; &#43; DateTime.Now);
    
    try
    {
        var data = UrlHelper.ParseUrl(request.Url);
        
        var targetController = GetController(data);
        
        if (targetController != null)
        {
            targetController.ExecuteAction(data);
        }
    }
    catch (Exception ex0)
    {
        Logger.WriteLine(ex0.ToString());
    }
    
    request.SendResponse(NewLine);
    
    Logger.WriteLine(&quot;End: &quot; &#43; request.Url &#43; &quot; at &quot; &#43; DateTime.Now &#43; &quot; took: &quot; &#43; (DateTime.Now - start).Milliseconds);
}

public static IController GetController(UrlData data)
{
    if (data.IsDamage)
        return Damage;
    
    if (data.IsScore)
        return Score;
    
    if (data.IsGameState)
        return GameState;
    
    // can assume invalid
    return null;
}
</pre></p><h2>Making It Shake</h2><p>We used a Sparkfun MP3 trigger board, a subwoofer amplifier, and bass rumble plates to create this effect.&nbsp; The MP3 board requires power, and two jumpers to cause the MP3 to play.&nbsp; It has an audio jack that then gets plugged into the amplifier which powers the rumble plates.</p><p>From here, we just needed to wire a ground to the MP3 player’s ground pin, and the target pin on the MP3 player to a digital IO pin on the Netduino.&nbsp; In the code, we declare it as an <strong>OutputPort</strong> and give it an initial state of true.&nbsp; When we get a request, we toggle the pin on a separate thread.</p><p><pre class="brush: csharp">
private static readonly OutputPort StopMusic = new OutputPort(Pins.GPIO_PIN_D0, true);
private static readonly OutputPort Track1 = new OutputPort(Pins.GPIO_PIN_D1, true);
// .. more pins

public static void PlayTrack(int track)
{
    switch (track)
    {
        case 1:
            TogglePin(Track1);
            break;
            // ... more cases
        default:
            // stop all, invalid choice
            TogglePin(StopMusic);
            break;
    }
}

public static void Stop()
{
    TogglePin(StopMusic);
}

private static void TogglePin(OutputPort port)
{
    var t = new Thread(() =&gt;
    {
            port.Write(false);
            Thread.Sleep(50);
            port.Write(true);
    });
    
    t.Start();
}
</pre></p><h2>Lighting Up the Room</h2><p>For lighting, we used some <a href="http://www.usledsupply.com/shop/12v-rgb-flex-strip.html">RGB Lighting strips</a>.&nbsp; The strips can change a single color and use a PWM signal to do this.&nbsp; This is different than the lighting we used in Project Detroit which allowed us to individually control each LED and used SPI to communicate.&nbsp; We purchased an RGB amplifier to allow a PWM signal to power a 12 volt strip.&nbsp; We purchased ours from US LED Supply and the exact product was <a href="http://www.usledsupply.com/shop/rgb-mini-amplifier-ttl.html">RGB Amplifier 4A/Ch for interfacing with a Micro-Controller (PWM/TTL Input)</a>.</p><p>We alter the Duty Cycle to shift the brightness of the LEDs and do this on a separate thread.&nbsp; Below is a stripped down version of the lighting hardware class.</p><p><pre class="brush: csharp">
public static class RgbStripLighting
{
    private static readonly PWM RedPwm = new PWM(Pins.GPIO_PIN_D5);
    private static readonly PWM GreenPwm = new PWM(Pins.GPIO_PIN_D6);
    private static readonly PWM BluePwm = new PWM(Pins.GPIO_PIN_D9);
    
    private const int ThreadSleep = 50;
    private const int MaxValue = 100;
    
    const int PulsePurpleIncrement = 2;
    const int PulsePurpleThreadSleep = 100;
    
    private static Thread _animationThread;
    private static bool _killThread;
    
    #region game state animations
    public static void PlayGameIdle()
    {
        AbortAnimationThread();
        
        _animationThread = new Thread(PulsePurple);
        _animationThread.Start();
    }
    #endregion
        
            
    private static void PulsePurple()
    {
        while (!_killThread)
        {
            for (var i = 0; i &lt;= 50; i &#43;= PulsePurpleIncrement)
            {
                SetPwmRgb(i, 0, i);
            }
            
            for (var i = 50; i &gt;= 0; i -= PulsePurpleIncrement)
            {
                SetPwmRgb(i, 0, i);
            }
            
            Thread.Sleep(PulsePurpleThreadSleep);
        }
    }
    
    private static void AbortAnimationThread()
    {
        _killThread = true;
        
        try
        {
            if(_animationThread != null)
                    _animationThread.Abort();
        }
        catch (Exception ex0)
        {
            Debug.Print(ex0.ToString());
            Debug.Print(&quot;Thread still alive: &quot;);
            Debug.Print(&quot;Killed Thread&quot;);
        }
        
        _killThread = false;
    }
    
    private static void SetPwmRgb(int red, int green, int blue)
    {
        // typically, 0 == off and 100 is on
        // things flipped however for the lighting so building this in.
        
        red = MaxValue - red;
        green = MaxValue - green;
        blue = MaxValue - blue;
        
        red = CheckBound(red, MaxValue);
        green = CheckBound(green, MaxValue);
        blue = CheckBound(blue, MaxValue);
        
        RedPwm.SetDutyCycle((uint) red);
        GreenPwm.SetDutyCycle((uint) green);
        BluePwm.SetDutyCycle((uint) blue);
        
        Thread.Sleep(ThreadSleep);
    }
    
    public static int CheckBound(int value, int max)
    {
        return CheckBound(value, 0, max);
    }
    
    public static int CheckBound(int value, int min, int max)
    {
        if (value &lt;= min)
            value = min;
        else if (value &gt;= max)
            value = max;
        
        return value;
    }
}
</pre></p><h3>Conclusion</h3><p>We built this experience over the course of around 4 to 5 weeks.&nbsp; It was our first DirectX application in a very long time, and our first C&#43;&#43; application in a very long time.&nbsp; However, we were able to pick up the new platform and language changes fairly easily and create a simple, yet fun game in that time period.</p><h3>Attributions</h3><ul><ul><li>Music track - <a href="http://soundcloud.com/neosvsatm/bullet">&quot;FatLoad- The Bullet(no master)&quot; by FreaK NeoS</a> </li><li>Sound effects &#43; music edition - <a href="http://davidwallimann.com/">David Wallimann</a> </li><li>DirectX shaders - <a href="http://geekswithblogs.net/mikebmcl/Default.aspx">Michael McLaughlin</a> </li></ul></ul> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/netmf/RSS&WT.dl=0&WT.entryid=Entry:RSSView:12ea0afdf04c46d0980ca101018434ed">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Maelstrom-An-Overview</comments>
      <itunes:summary>For //build/ 2012, we wanted to showcase what Windows 8 can offer developers.&amp;nbsp; There are a lot of projects showing off great things like contracts and Live Tiles, but we wanted to show off some of the lesser known features.&amp;nbsp; This project focuses on one of those: stereoscopic 3D with DirectX 11.1. Prior to DirectX 11.1, stereoscopic 3D required specific hardware and a custom API written for that hardware.&amp;nbsp; With DX11.1, stereoscopic 3D has been &amp;quot;democratized.&amp;quot;&amp;nbsp; Any GPU that supports DirectX 11.1 can be connected to any device which supports stereoscopic 3D, be it a projector, an LCD TV, or anything else.&amp;nbsp; Plug it in and DirectX does the rest. From the software side of things, any DX11.1 application can determine if the connected display supports stereoscopic 3D, and choose to render itself separately for the player&#39;s left and right eye. To showcase this feature, we decided to build a very simple game that would give the illusion of depth, but be easy to explain and play.&amp;nbsp; What&#39;s easier than Pong?&amp;nbsp; So, we built the world&#39;s most over-engineered game of 3D Pong named Maelstrom.  SoftwareEach player setup consists of two applications: the DirectX 11.1 game written in C&amp;#43;&amp;#43;, and the touch-screen controller written in C#/XAML.&amp;nbsp; Both are Windows Store applications.&amp;nbsp; Since this is a two player game, there are two instances of each application running, one per player.&amp;nbsp; All for applications are networked together using StreamSockets from the Windows Runtime.&amp;nbsp; The two controllers and player two&#39;s DirectX game connect to player one&#39;s DirectX game, which acts as the &amp;quot;master&amp;quot;.&amp;nbsp; Controller input is sent here, and, once the ball and paddle positions are calculated, the data is drawn for player one and sent to player two which draws the world from the other player&#39;s perspective.  Direct3D ApplicationGetting Started with stereoscopic DirectX11, C&amp;#43;&amp;#43;, and XAMLIf you have never worked with Direct</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Maelstrom-An-Overview</link>
      <pubDate>Tue, 20 Nov 2012 21:00:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Maelstrom-An-Overview</guid>
      <media:thumbnail url="http://files.channel9.msdn.com/thumbnail/af11e27a-5854-40e9-b005-01f97846f491.png" height="56" width="100"></media:thumbnail>
      <media:thumbnail url="http://files.channel9.msdn.com/thumbnail/c7f299fc-4bbf-45ee-84b3-d2460d947ceb.png" height="124" width="220"></media:thumbnail>
      <media:thumbnail url="http://files.channel9.msdn.com/thumbnail/8ced263b-4c1a-469a-a02b-471d27bb6705.png" height="288" width="512"></media:thumbnail>      
      <dc:creator>Brian Peek, Clint Rutkas, Dan Fernandez, Michael B. McLaughlin, Rick Barraza</dc:creator>
      <itunes:author>Brian Peek, Clint Rutkas, Dan Fernandez, Michael B. McLaughlin, Rick Barraza</itunes:author>
      <slash:comments>5</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Maelstrom-An-Overview/RSS</wfw:commentRss>
      <category>3D</category>
      <category>C++</category>
      <category>Coding4Fun</category>
      <category>Direct 3D</category>
      <category>DirectX 11</category>
      <category>NETMF</category>
      <category>Windows 8</category>
    </item>
  <item>
      <title>Project Detroit: Lighting System</title>
      <description><![CDATA[<p>In this article, we give a detailed look into the external lighting system of Project Detroit, the Microsoft-West Coast Custom Mustang creation. If you're not already familiar with this project, you can find more <a href="http://channel9.msdn.com/Blogs/Vector/The-400-horsepower-device">information here</a>.</p><h2>Overview</h2><p>The external lighting system for Project Detroit is run on a web server on a Netduino Plus, which uses the .NET Micro Framework (NETMF). To get an accelerated start, we leveraged code from the CodePlex project <a href="http://netduinohelpers.codeplex.com/">Netduino Helpers</a> to control the <a href="http://www.adafruit.com/products/306">AdaFruit LPD8806 LED</a> strip, and the <a href="http://forums.netduino.com/index.php?/topic/575-updated-web-server/">web server base code from the Netduino forums</a>. They have been tweaked slightly for our project.</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/netduino%5B8%5D.jpg"><img title="netduino" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/netduino_thumb%5B3%5D.jpg" alt="netduino" width="500" height="375" border="0"></a></p><h2>Controllers, Routes, RESTful oh my!</h2><p>We wanted the NETMF web server to have the exact same routes as the full-blown REST service layer in Detroit. With compiler conditionals, this allowed the same code to use the same routes on both the full .NET stack and NETMF. Since we couldn't use the ASP.NET MVC framework here, we had to make something close to it.</p><h2>Controllers</h2><p>Controllers implement an interface with a method named <strong>ExecuteAction</strong>. When <strong>GetController</strong> is called, we return the correct controller but cast as the interface <strong>IController</strong>. This lets us figure out what controller should be executing the request and continue to work generically in the context of the request connection thread. If new functionality is needed, we create a new controller that inherits from IController&nbsp;and update GetController:</p><p><pre class="brush: csharp">
private static void RequestReceived(Request request)
{
    // url comes in as /foo/bar/12345?style=255
    //
     // /CONTROLLER/ACTION/
    //
    // LIGHTING SAMPLE URL: /0/1/?r=255&amp;g=255&amp;b=255&amp;zone=EnumAsInt
    // /0/... 0 = NetduinoControllerType.Lighting
    var validResponse = false;
    try
    {
        Logger.WriteLine(&quot;Start: &quot; &#43; request.Url &#43; &quot; at &quot; &#43; DateTime.Now);
        var urlInParts = request.Url.TrimStart(UriPathSeparator).Split(new[] {'?'}, 2);
        string[] uriSubParts = null;
        string[] queryStringSubParts = null;
        if (urlInParts.Length &gt; 0)
            uriSubParts = urlInParts[0].Split(UriPathSeparator);
                
        if (urlInParts.Length &gt; 1)
            queryStringSubParts = urlInParts[1].Split(QueryStringSeparator);
        if (uriSubParts != null &amp;&amp; uriSubParts.Length &gt; 1)
        {
            var targetController = GetController(uriSubParts[0]);
            if (targetController != null)
            {
                var action = (uriSubParts.Length &gt;= 2) ? uriSubParts[1] : string.Empty;
                var result = targetController.ExecuteAction(action, queryStringSubParts);
                validResponse = true;
                request.SendResponse(result.ToString());
                Logger.WriteLine(&quot;Result: &quot; &#43; result &#43; &quot; from &quot; &#43; request.Url &#43; &quot; at &quot; &#43; DateTime.Now);
            }
        }
        if (!validResponse)
        {
            SendIndexHtml(request);
        }
    }
    catch(Exception ex0)
    {
        Logger.WriteLine(ex0.ToString());
    }
}
</pre></p><h2>Routes, strings and enums on NETMF</h2><p>NETMF can't parse an enum from a string, which is something that can be done in the full .NET Framework. But what does this actually mean? It means the routes for the NETMF web server are a bit unreadable. Here is the same route but with the parsing issue exposed:</p><p><strong>Detroit's REST service route with ASP.NET MVC:</strong><br>http://…/Lighting/Solid/?zone=all&amp;r=255&amp;g=0&amp;b=0<br><br><strong>Detroit's NETMF route:<br></strong>http://…/0/3/?zone=0&amp;r=255&amp;g=0&amp;b=0</p><p>This issue made direct device debugging a bit harder.</p><h2>Parsing the Action and query string</h2><p>Parsing the route is broken into two parts. The first is determines what controller to target. For Project Detroit, that meant the lighting system or the rear glass system. Once we know the controller, we still need to parse the query string and action into something more useful:</p><p><pre class="brush: csharp">
#if NETMF
private static readonly char[] QueryStringParamSeparator = new[] { '=' };
public static LightingData ParseQueryStringValues(string action, params string[] queryStringParameters)
#else
public static LightingData ParseQueryStringValues(string action, Dictionary&lt;string, object&gt; queryStringParameters)
#endif
{
    var data = new LightingData {LightingZone = LightingZoneType.All, LightingAction = ParseLightingActionType(action)};
#if NETMF
    if (queryStringParameters != null)
    {
        foreach (var queryString in queryStringParameters)
        {
            var valueKey = queryString.Split(QueryStringParamSeparator);
            if (valueKey.Length != 2)
                continue;
            var key = valueKey[0];
            var value = valueKey[1];
#else
        foreach(var key in queryStringParameters.Keys)
        {
            var value = queryStringParameters[key].ToString();
#endif
            switch (key.ToLower())
            {
                case ZoneHuman:
                case ZoneComputer:
                    data.LightingZone = ParseLightingZoneType(value);
                    break;
                // more stuff
            }
        }
#if NETMF
    }
#endif
    // more stuff
            
    return data;
}
</pre></p><h2>Turning on the lights</h2><p>Individually addressable LED strips allow us to tell each individual LED what color to be. To adjust the colors of the LED lights, we loop through all the LEDs, set their color value, and then call <strong>LedRefresh()</strong> on our LED strip. There's no need to set all of them, only the ones being updated:</p><p><pre class="brush: csharp">
private static void SolidAnimationWorker()
{
    var leds = GetLedsToIlluminate();
    var dataCopy = _data;
    for (var i = 0; i &lt; leds.Length; i&#43;&#43;)
        SetLed(leds[i], dataCopy.Red, dataCopy.Green, dataCopy.Blue);
    LedRefresh();
}
</pre></p><h2>Zones / Animation Threads</h2><p>A solid color is boring, but we can use procedural animations to add some flair. The current code&nbsp;supports the following animations:</p><ul><li>Solid - A single solid color. </li><li>Fill - Goes from black to the desired color. The color stays lit. Much like filling a glass of liquid. <img src='http://ecn.channel9.msdn.com/o9/content/images/emoticons/emotion-1.gif?v=c9' alt='Smiley' /> </li><li>Random - LEDs are set to a random value. </li><li>Pulse - A glowing effect from bright to black. </li><li>Snake - A one way lighting effect with a fading tail that moves left to right. </li><li>Sweep - This effect was inspired by KITT and a Cylon robot and is similar to a snake pattern. The effect can also handle being split in two while maintaining a continual line for items such as the grill or the wheels. </li><li>Police - Each side flashes a red and blue light. </li></ul><p>Since we know the LED strip is a single strand, we can be clever with offsets and create groupings. By having a dedicated animation thread in each zone, we can have the grill of the car in Police Mode while the bottom fades to red and the vents fill to blue at different refresh rates.</p><p>To run an animation, we need to first kill the old animation thread, spin up a new thread, mark LEDs in the &quot;All LED&quot; zone as do not touch, and execute the new pattern. Without a way to mark the LEDs as &quot;bad&quot; in the &quot;All&quot; zone, the two animation threads would compete for setting the color and result in a flickering effect. Other zones don't have to worry about this since there is zero overlap of LEDs:&nbsp;</p><p><pre class="brush: csharp">
public bool ExecuteAction(string action, params string[] queryStringParameters)
{
    var data = LightingDataHelper.ParseQueryStringValues(action, queryStringParameters);
            
    SignalToEndAnimationThread(data.LightingZone);
    int counter = 0;
    while (counter&#43;&#43; &lt; 5 &amp;&amp; IsThreadAlive(data.LightingZone))
        Thread.Sleep(10);
    if (IsThreadAlive(data.LightingZone))
        AbortAnimationThread(data.LightingZone);
    // moving data bucket into public so new threads can leverage it
    _data = data;
    if (_data.LightingAction == LightingActionType.Police || _data.LightingAction == LightingActionType.Sweep)
    {
        _data.LightingZone = LightingZoneType.Grill;
        if (IsThreadAlive(_data.LightingZone))
            AbortAnimationThread(_data.LightingZone);
    }
    // cleaning up just incase
    if (data.LightingZone != LightingZoneType.All)
    {
        for (var i = 0; i &lt; _zoneAllAnimation.Length; i&#43;&#43;)
        {
            var leds = GetLedsToIlluminate();
            for (var z = 0; z &lt; leds.Length; z&#43;&#43;)
            {
                // flagging item as bad in animation lib
                if (_zoneAllAnimation[i] == leds[z])
                    _zoneAllAnimation[i] = -1;
            }
        }
    }
    switch (_data.LightingAction)
    {
        case LightingActionType.Solid:
            Debug.Print(&quot;Solid&quot;);
            ExecuteThread(SolidAnimationWorker);
            break;
        // more patterns
    }
    return true;
}
</pre></p><p>We can now do something more interesting, like Police Mode:</p><p><pre class="brush: csharp">
private static void PoliceModeAnimationWorker()
{
    var leds = GetLedsToIlluminate();
    var dataCopy = _data;
    var length = leds.Length;
    var half = length / 2;
    var index = 0;
    while (IsThreadSignaledToBeAlive(dataCopy.LightingZone))
    {
        int redIntensity = (index == 0) ? 255 : 0;
        int blueIntensity = (index == 0) ? 0 : 255;
        for (var i = 0; i &lt; half; i&#43;&#43;)
            SetLed(leds[i], redIntensity, 0, 0);
        for (var i = half; i &lt; length; i&#43;&#43;)
            SetLed(leds[i], 0, 0, blueIntensity);
        LedRefresh();
        index&#43;&#43;;
        index %= 2;
        Thread.Sleep(100);
    }
}
</pre></p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/WP_000197%5B5%5D.jpg"><img title="WP_000197" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/WP_000197_thumb%5B2%5D.jpg" alt="WP_000197" width="500" height="375" border="0"></a></p><h2>Improvements</h2><p>Hindsight is 20/20. Nothing is ever perfect and there are of course items we'd love to change. At the start, the goal was to make this fairly generic and not Project Detroit &quot;aware.&quot; As you can see by looking at the source, that wasn't accomplished due to time constraints.</p><p>We would use a different LED system for two reasons: data transfer speed and power. The longer the LED strip is, the longer it takes to address an item further down the line. Project Detroit, having 15 meters of lighting in it, was impacted by this issue. It works well, just not as well as we hoped. The voltage requirements of the LEDs are another consideration. They are 5V, while a car uses 12V. Had we used 12V LEDs, our wiring would have been far simpler and wouldn't have required multiple transformers to get the required amperage needed at the correct voltage.</p><h2>Conclusion</h2><p>We think the lighting solution, coupled with the time and material constraints, worked out pretty well.&nbsp; Project Detroit was a ton of fun to build out and working with West Coast Customs was the chance of a lifetime.</p><p><img src="http://files.channel9.msdn.com/thumbnail/09615539-1a33-49f7-b438-ca1b9543d712.jpg" alt="" width="500" height="284"></p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/netmf/RSS&WT.dl=0&WT.entryid=Entry:RSSView:f6bef172711342dbbca9a046016a6843">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Project-Detroit-Lighting-System</comments>
      <itunes:summary>In this article, we give a detailed look into the external lighting system of Project Detroit, the Microsoft-West Coast Custom Mustang creation. If you&#39;re not already familiar with this project, you can find more information here. OverviewThe external lighting system for Project Detroit is run on a web server on a Netduino Plus, which uses the .NET Micro Framework (NETMF). To get an accelerated start, we leveraged code from the CodePlex project Netduino Helpers to control the AdaFruit LPD8806 LED strip, and the web server base code from the Netduino forums. They have been tweaked slightly for our project.  Controllers, Routes, RESTful oh my!We wanted the NETMF web server to have the exact same routes as the full-blown REST service layer in Detroit. With compiler conditionals, this allowed the same code to use the same routes on both the full .NET stack and NETMF. Since we couldn&#39;t use the ASP.NET MVC framework here, we had to make something close to it. ControllersControllers implement an interface with a method named ExecuteAction. When GetController is called, we return the correct controller but cast as the interface IController. This lets us figure out what controller should be executing the request and continue to work generically in the context of the request connection thread. If new functionality is needed, we create a new controller that inherits from IController&amp;nbsp;and update GetController: 
private static void RequestReceived(Request request)
{
    // url comes in as /foo/bar/12345?style=255
    //
     // /CONTROLLER/ACTION/
    //
    // LIGHTING SAMPLE URL: /0/1/?r=255&amp;amp;g=255&amp;amp;b=255&amp;amp;zone=EnumAsInt
    // /0/... 0 = NetduinoControllerType.Lighting
    var validResponse = false;
    try
    {
        Logger.WriteLine(&amp;quot;Start: &amp;quot; &amp;#43; request.Url &amp;#43; &amp;quot; at &amp;quot; &amp;#43; DateTime.Now);
        var urlInParts = request.Url.TrimStart(UriPathSeparator).Split(new[] {&#39;?&#39;}, 2);
        string[] uriSubParts = null;
       </itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Project-Detroit-Lighting-System</link>
      <pubDate>Mon, 21 May 2012 16:00:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Project-Detroit-Lighting-System</guid>
      <media:thumbnail url="http://files.channel9.msdn.com/thumbnail/09c00fc4-d404-424d-8120-278d433390bd.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://files.channel9.msdn.com/thumbnail/6bff8dd9-2c4a-4fc0-9e5a-c03e80a68796.jpg" height="165" width="220"></media:thumbnail>
      <media:thumbnail url="http://files.channel9.msdn.com/thumbnail/f7c84b3a-67a1-4580-aa9a-0554038a63bf.jpg" height="288" width="512"></media:thumbnail>      
      <dc:creator>Brian Peek, Clint Rutkas, Dan Fernandez</dc:creator>
      <itunes:author>Brian Peek, Clint Rutkas, Dan Fernandez</itunes:author>
      <slash:comments>4</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Project-Detroit-Lighting-System/RSS</wfw:commentRss>
      <category>NETMF</category>
      <category>Project Detroit</category>
    </item>
  <item>
      <title>Netduino Controlled LED Cube</title>
      <description><![CDATA[<p>Commercial LED cubes have been around for a while now and can be quite large and capable of some <a href="http://www.seekway.com.cn/e/3d/h32/detail.htm">interesting displays</a>. This project is on a smaller scale and goes through the steps required to build a Netduino Mini-controlled 512 LED cube (8 x 8 x 8).</p><p>Clearly, the Mini does not have 512 pins and so we use <a href="http://en.wikipedia.org/wiki/Persistence_of_vision">Persistence of Vision</a> to control the LEDs in the cube. The result is that seven pins on the Netduino Mini can control 512 LEDs.</p><p>At the end of this article you should be able to create a cube capable of the following:</p><p><object width="425" height="355"><param name="movie" value="http://www.youtube.com/v/FdpeC0GSRkM&hl=en"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/FdpeC0GSRkM&hl=en" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"></embed></object></p><h3>Bill of Materials</h3><table class="MsoTableLightShadingAccent1" border="1" cellspacing="0" cellpadding="0"><tbody><tr><td valign="top" width="308"><p class="MsoNormal"><span>Description</span></p></td><td valign="top" width="143"><p class="MsoNormal" align="center"><span>Quantity</span></p></td></tr><tr><td valign="top" width="308"><p class="MsoNormal"><strong><span>LEDs (I chose blue)</span></strong></p></td><td valign="top" width="143"><p class="MsoNormal" align="center"><span>512</span></p></td></tr><tr><td valign="top" width="308"><p class="MsoNormal"><strong><span>74HC595 Shift Registers</span></strong></p></td><td valign="top" width="143"><p class="MsoNormal" align="center"><span>8</span></p></td></tr><tr><td valign="top" width="308"><p class="MsoNormal"><strong><span>74HC238 3 to 8 line decoder</span></strong></p></td><td valign="top" width="143"><p class="MsoNormal" align="center"><span>1</span></p></td></tr><tr><td valign="top" width="308"><p class="MsoNormal"><strong><span>Netduino Mini</span></strong></p></td><td valign="top" width="143"><p class="MsoNormal" align="center"><span>1</span></p></td></tr><tr><td valign="top" width="308"><p class="MsoNormal"><strong><span>16 Pin DIL Socket (0.3&quot;)</span></strong></p></td><td valign="top" width="143"><p class="MsoNormal" align="center"><span>9</span></p></td></tr><tr><td valign="top" width="308"><p class="MsoNormal"><strong><span>24 Pin DIL Socket (0.6&quot;)</span></strong></p></td><td valign="top" width="143"><p class="MsoNormal" align="center"><span>1</span></p></td></tr><tr><td valign="top" width="308"><p class="MsoNormal"><strong><span>TIP122 NPN Transistor</span></strong></p></td><td valign="top" width="143"><p class="MsoNormal" align="center"><span>8</span></p></td></tr><tr><td valign="top" width="308"><p class="MsoNormal"><strong><span>100nF Ceramic Capacitor</span></strong></p></td><td valign="top" width="143"><p class="MsoNormal" align="center"><span>10</span></p></td></tr><tr><td valign="top" width="308"><p class="MsoNormal"><strong><span>2.2K Resistor</span></strong></p></td><td valign="top" width="143"><p class="MsoNormal" align="center"><span>8</span></p></td></tr><tr><td valign="top" width="308"><p class="MsoNormal"><strong><span>68 Ohm 0.25W Resistor (you may need to change these depending upon the LED you choose)</span></strong></p></td><td valign="top" width="143"><p class="MsoNormal" align="center"><span>64</span></p></td></tr><tr><td valign="top" width="308"><p class="MsoNormal"><strong><span>8 Way Single Row Socket</span></strong></p></td><td valign="top" width="143"><p class="MsoNormal" align="center"><span>9</span></p></td></tr><tr><td valign="top" width="308"><p class="MsoNormal"><strong><span>36 Way Header Strip (Straight)</span></strong></p></td><td valign="top" width="143"><p class="MsoNormal" align="center"><span>3</span></p></td></tr><tr><td valign="top" width="308"><p class="MsoNormal"><strong><span>2 Way Single Row Socket</span></strong></p></td><td valign="top" width="143"><p class="MsoNormal" align="center"><span>2</span></p></td></tr><tr><td valign="top" width="308"><p class="MsoNormal"><strong><span>2 Way PCB Mount Terminal Connector</span></strong></p></td><td valign="top" width="143"><p class="MsoNormal" align="center"><span>1</span></p></td></tr><tr><td valign="top" width="308"><p class="MsoNormal"><strong><span>8 Way Cable (ribbon or alarm)</span></strong></p></td><td valign="top" width="143"><p class="MsoNormal" align="center"><span>2.5m</span></p></td></tr><tr><td valign="top" width="308"><p class="MsoNormal"><strong><span>Wire</span></strong></p></td><td valign="top" width="143"><p class="MsoNormal" align="center"><span>Miscellaneous</span></p></td></tr><tr><td valign="top" width="308"><p class="MsoNormal"><strong><span>Pad board 160 x 115 Hole</span></strong></p></td><td valign="top" width="143"><p class="MsoNormal" align="center"><span>1</span></p></td></tr><tr><td valign="top" width="308"><p class="MsoNormal"><strong><span>Hex PCB spacer and screw (M3 threaded)</span></strong></p></td><td valign="top" width="143"><p class="MsoNormal" align="center"><span>4</span></p></td></tr></tbody></table><p><strong></strong>&nbsp;</p><p><strong>The following items are also required:</strong></p><ul><li>5V Power capable of delivering 2A </li><li>Solder (I used about 15 metres over the life of this project). </li><li>One 30cm x 30cm piece of wood </li><li>Drill and wood drill bits (4mm – 5mm) </li><li>Some cardboard and tape </li><li>A fair amount of patience </li><li>Good attention to detail </li></ul><p>You may need to shop around for the LEDs. I went to my preferred supplier and was quoted 18.5 pence each. By going on eBay I managed to negotiate the price down to 2.5 pence each including delivery. You are buying in bulk so don’t be afraid to ask for a good bulk price. Also, buy a few more than you need in case you have a faulty part or break a few.</p><h3>Building the Cube</h3><p>This is probably the most time consuming part of the project requiring a lot of patience and testing. The aim of the project is to convert these 512 blue LEDs:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B2%5D.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb.png" alt="image" width="602" height="449" border="0"></a></p><p>Into this:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B5%5D-3.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B1%5D-1.png" alt="image" width="602" height="615" border="0"></a></p><h4>Shaping the LEDs</h4><p>The exact dimensions of the cube depend upon the length of the legs on the LEDs. The legs are soldered together with the cathodes of the LEDs forming a horizontal plane and the anodes vertically connecting the layers. Each of the layers are configured into a common cathode display.</p><p>Take one of the LEDs and bend the cathode at a point as close to the body of the LED as possible. The cathode should be at 90 degrees to the anode and parallel to the flat base of the LED. This allows the horizontal legs to be soldered together to form the common cathode.</p><p>Shaping the anode is a little more difficult. The anodes connect the horizontal layers and so need to be shaped to ensure that each LED in the layer is directly above the corresponding LED in the layer below. Otherwise, each layer will be slightly offset from the one beneath it.</p><p>To achieve this, bend the anode in the opposite direction as described for the cathode. Then, still working with the anode, start about 2mm along the leg. Finally, bend the top 2-3mm through and fashion an angle at 90 degrees pointing back to the LED body. The end result should look like this:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B8%5D.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B2%5D-3.png" alt="image" width="624" height="526" border="0"></a></p><p>The horizontal leg is the cathode and the vertical leg is the anode. When these are connected it should look like this:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B11%5D-1.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B3%5D-4.png" alt="image" width="520" height="864" border="0"></a><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B14%5D-1.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B4%5D-1.png" alt="image" width="248" height="864" border="0"></a></p><p>Notice how the shaped anode allows the LEDs to be placed above each other.</p><p>Now repeat this process for the remaining 511 LEDs.</p><h4>Building a Layer</h4><p>Our next task is to connect the LEDs together. This is best achieved by using a template for the individual layers. Use a piece of wood with a grid of holes drilled into it as the template.</p><p>Measure the distance from the center of the now horizontal cathode to the end of the leg and subtract about 2mm. This will tell you how far apart the LEDs are in the horizontal plane. The 2mm will be used to overlap with the neighboring LED and will connect the cathodes. Now drill an 8 x 8grid of holes, each of which are distance of your choosing apart.&nbsp; Here they are 20mm apart.</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B17%5D.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B5%5D.png" alt="image" width="381" height="380" border="0"></a></p><p>The holes need to be large enough to hold the LEDs securely but should not be so small that the LEDs are wedged into the hole and difficult to remove.</p><p>Take eight of the LEDs and place them along the top row with the cathodes all pointing to either the right or the left. If all are pointing to the right, the cathodes of seven LEDs will overlap slightly with the next LED to the right. The rightmost cathode will go off into space. Solder the cathodes together.</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B20%5D-1.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B6%5D-2.png" alt="image" width="624" height="84" border="0"></a></p><p>Now let’s add the remaining LEDs in the layer. I started on the left because I hold the soldering iron in my right hand. Take another seven LEDs and place these under the top row and down the far left column. The cathode of each first LED should overlap the cathode of the LED in the top layer. Solder these together.</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B23%5D.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B7%5D-1.png" alt="image" width="624" height="394" border="0"></a></p><p>Repeat with the remaining columns. At this point, you should have a horizontal row of LEDs connected together with eight strings of seven LEDs hanging from it. Eventually you should have something looking like this:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B26%5D-1.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B8%5D-4.png" alt="image" width="624" height="468" border="0"></a></p><p>Now test the layer using a power supply and current limiting resistor. A 5V supply and a 68 Ohm resistor are adequate. Ground the cathode of the LED pointing off into space. Now touch each leg of the LEDs in turn with the positive output of the supply (through the current limiting resistor, of course). Each LED should light up and as you touch the anode.</p><p>One final bit of soldering is needed to add a stiffening wire to the layer. Cut and strip a piece of wire. The wire should be long enough to cross the entire layer. Place the stripped wire on the cathodes of the LEDs at the bottom of the string and solder it on to each.</p><p>At this point you will have one complete layer. Remove the layer from the template. This should be done carefully so that you do not put too much stress on the joints. Gently lifting it up with a screwdriver should help. Don’t hurry. Put this layer to one side and repeat another seven times.</p><h4>Connecting the Layers - The Cube Appears</h4><p>Now that all of the layers are built, test them again. This repeated test may save you future pain. Just imagine how difficult it will be to fix a bad joint in the middle of the cube. Check that the LEDs are still connected and none of the joints were broken when layers were removed from the template.</p><p>Now drop one of the layers back into the template. What we now need to do is to place a second layer on top of the first so that the anodes of the layer in the template touch the anodes of the LEDs in the upper layer. Once in place, we need to solder the anodes together, and so need a way of supporting the top layer whilst connecting the LEDs. A strip of cardboard can accomplish this. Cut the cardboard into strips (making sure the cardboard is the height needed to support the layer) and bind the strips together with tape. Two of these strips should be enough to support the layer. Here’s how it looked when several layers had already been connected:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B29%5D-1.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B9%5D.png" alt="image" width="624" height="631" border="0"></a></p><p>Now that you have the layer supported, solder the anode of each LED in the top layer to the anode of the corresponding LED in the layer directly beneath it. Once this has been done, test each LED. Connect the cathode of the bottom layer to ground and touch each of the legs on the top layer in turn with the positive supply (going through the current limiting resistor). The LED on the bottom layer should light up. Repeat for each LED in the layer. Move the cathode to the top layer and repeat the test—this time the LED on the top layer should light. Again, repeat for each LED in the layer.</p><p>Now add the remaining layers. Just for safety, test every layer in the cube as it is built up. This repeated testing sounds like a big pain, but trust me it's worth it. At this point you will have a cube of LEDs looking something like this:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B32%5D.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B10%5D-3.png" alt="image" width="624" height="650" border="0"></a></p><p>Now trim the cathodes that are still flying off into space.</p><h3>Building the Controller Board</h3><p>The controller board will allow any of the 512 LEDs in the cube to be turned on by a Netduino Mini using only seven pins.</p><h4>Persistence of Vision</h4><p>Connecting the anode to a positive supply while grounding the layer in which the LED is located can turn on any LED. You can also do this with more than one LED in a layer, and so within a layer can turn on 0 to 64 LEDs. To light the entire cube, we need to switch on each layer in turn while doing so fast enough to give the impression of static image. This is where the principle of <a href="http://en.wikipedia.org/wiki/Persistence_of_vision">Persistence of Vision</a> comes into play.</p><p>The basic algorithm is as follows:</p><ul><li><em>Layer</em> = 0 </li><li>Repeat <ul><li>Connect the anodes of the desired LEDs in <em>Layer</em> to positive supply </li><li>Connect <em>Layer</em> to ground (this turns the layer on) </li></ul></li><li>Move to next <em>Layer</em> </li></ul><p>If we do this fast enough, the human eye will see a single image as when watching TV or a movie.</p><p>Our basic building blocks for the controller are as follows:</p><ul><li>Microcontroller (a Netduino Mini) to run the whole show </li><li>Hardware to select the layer to be turned on (74HC238 and TIP122 transistors) </li><li>Hardware to turn on the LEDs (Shift registers) </li></ul><h4>Shift Registers</h4><p>The shift registers determine which LEDs are turned on. The board has a series of eight cascaded 74HC595 registers. This allows us to control 64 LEDs (8 chips x 8 outputs). The following schematic shows how two of these registers should be wired together:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B38%5D.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B12%5D-2.png" alt="image" width="624" height="498" border="0"></a></p><p>The above should be repeated until you have eight shift registers cascaded.</p><p>The output from the register is 5V and will give more than enough power to burn out an LED, so we need to put a <a href="http://en.wikipedia.org/wiki/LED_circuit">current limiting resistor</a> in the circuit. A 68 Ohm resistor is required for the LEDs in this project—make sure you verify the value you choose against the LEDs used.</p><p>Putting this together gives the following layout:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B41%5D.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B13%5D.png" alt="image" width="624" height="373" border="0"></a></p><p>Each socket holds a 74HC595 shift register. The connections are identical for each register with the data cascaded into the next register. So if we look at the bottom left socket you will see the following:</p><ul><li>Below the socket there is a connector that allows the output to be connected to the LEDs in the cube. </li><li>Above the connector are the resistors that limit the current flowing through the LEDs. </li><li>The socket above that will hold the 74HC595 shift register. </li><li>To the left of the socket is a 100nF capacitor. This smooths out the power supplied to the shift register and is connected between the power input and ground and placed as close to the IC as possible. </li></ul><p>The following colors have been used:</p><ul><li>Red = Power </li><li>Blue = SPI and cascaded data </li><li>Yellow = RCK </li><li>White = SPI clock </li></ul><p>Note that the connectors and current limiting resistor are slightly offset as output 0 is on pin 15 and this is routed on the underside of the board. The remaining connections are a direct one to one path from the pin to the resistor/connector.</p><p>The microcontroller uses the <a href="http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus">Serial Peripheral Interface</a> (SPI) bus to tell the shift registers which LED to turn on. The data from the registers is cascaded and so we can store 64 bits of information (1 bit for each LED in a layer). With logic 1 turning a particular LED on and 0 turns the LED off.</p><h4>Layer Switching</h4><p>The layer switching logic allows the controller to connect any one of the layers to ground (using a common cathode). Coupling this with the LED selection logic above allows us to turn on any one of the LEDs in the cube. This is achieved by using a transistor as a switch. The TIP122 was selected because it is capable of sinking 2A. This may seem like a lot considering the 25mA for each LED, but remember that we potentially have 64 LEDs being turned on at once. This means we may be drawing 1.6A of current. If you use a different LED, you will need to verify that the shift registers, power supply, and the transistor are capable of dealing with the amount of power you will be drawing.</p><p>The schematic for the layer switching looks like this:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B44%5D.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B14%5D-2.png" alt="image" width="624" height="468" border="0"></a></p><p>The 74HC238 has three input signals. These represent a binary number 0-7. The chip converts this number into eight output lines. 0 turns on line 0, 1 turns on line 1 etc. The output from each line (0 through 7) is then fed in the base of a TIP122 transistor. This turns on the appropriate layer by connecting the layer through to ground.</p><p>One line for the Netduino Mini controls enable line on the 72HC238 chip. This allows us to turn all of the outputs off whilst a new value is being loaded into the chip. This line is used to make sure that the transitions between the states are “invisible.” Without this there is the chance that the viewer may see a flickering effect when new values are loaded into both the 74HC595s and the 74HC238.</p><h4>The Completed Controller Board</h4><p>The completed controller board looks something like this:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B47%5D.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B15%5D.png" alt="image" width="624" height="491" border="0"></a></p><p>Note that there are a pair of connectors to the top right and bottom left of the Netduino Mini. The pair at the top right breakout the COM1 port. The two at the bottom left allow grounding of an FTDI lead (connected to the controller board) and also one socket that is not connected. This allows the 5V lead on the FTDI connector to have a place to live and not be in danger of touching something it shouldn’t.</p><p>And on the underside:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B50%5D.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B16%5D.png" alt="image" width="624" height="444" border="0"></a></p><h4>Connecting the Cube and Controller</h4><p>The final task (from a hardware point of view) is to connect the cube to the controller board. I tried both ribbon cable and alarm cable. The alarm cable was a little more difficult to connect but was flexible. The ribbon cable was easier to work with but was not as flexible. The principle is the same whichever you chose.</p><p>Place the cube on a flat surface (the anodes touching the surface) with one face of the cube facing you. The connections should be made so that the lower back left corner is co-ordinate (0, 0, 0). The co-ordinates increase moving to the right, towards you and up. So looking at the controller board above, shift register 0 connects to the LEDs farthest away from you with output 0 from the register connecting to the LED to the far left. Cut and make the 8 cables according to this pattern varying the lengths to suit the location of the controller board with respect to the cube. Each cable will need a single eight-way socket on one end with the other end connected to the appropriate LED.</p><p>The layer selection logic should be connected using a similar cable. Each layer should be connected to a TIP122 with layer 0 being the bottom layer.</p><p>The cube will then look like this:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B53%5D.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B17%5D-1.png" alt="image" width="624" height="587" border="0"></a></p><p>Connecting it up to the controller:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image%5B56%5D.png"><img title="image" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/image_thumb%5B18%5D.png" alt="image" width="624" height="346" border="0"></a></p><p>I found it easier to be consistent and wire each plug and LED identically, and so all of the connections above have a black wire to the right of the connector. It helps with connecting things up later.</p><p>If we have everything connected then we only need one more thing...</p><h3>Software</h3><p>The software running the cube needs to perform two main tasks:</p><ul><li>Work out which LEDs are turned on </li><li>Run the display (cube) </li></ul><p>These two tasks need to be performed at the same time (or so fast that they appear to run at the same time). Luckily the .NET Micro Framework has a built in mechanism to allow us to do this—threading. Threading allows us to do this by running two tasks interleaved. So task 1 will run for a while, the system will then switch and run task 2 for a while, then back to task 1 and so on.</p><p>To do this, the software is split into two parts, the main program that decides what to display and a separate class that runs the display.</p><h4>LEDCube Class</h4><p>This class has only one purpose in life, to output data to the controller board and so “run” the display. It is a relatively simple class containing the following methods:</p><ul><li>Constructor </li><li>Buffer update method </li><li>Display Buffer method </li></ul><p>The constructor sets everything up by instantiating an instance of the SPI class and setting the buffer (which contains the data to be displayed) to be empty, effectively clearing the cube:</p><p><pre class="brush: csharp">public LEDCube()
{
    config = new SPI.Configuration(SPI_mod: SPI.SPI_module.SPI1,
                                   ChipSelect_Port: Pins.GPIO_PIN_20,
                                   ChipSelect_ActiveState: false,
                                   ChipSelect_SetupTime: 0,
                                   ChipSelect_HoldTime: 0,
                                   Clock_IdleState: true,
                                   Clock_Edge: true,
                                   Clock_RateKHz: 100);    spi = new SPI(config);
    buffer = new byte[64];
    for (int index = 0; index &lt; buffer.Length; index&#43;&#43;)
    {
        buffer[index] = 0;
    }
}</pre></p><p>The buffer is 64 bytes of data, 8 rows of 8 bytes. Each byte corresponds to a vertical layer in the cube.</p><p>The UpdateBuffer method allows the calling program to change what is displayed in the cube. A little control is needed here to ensure that the pattern displayed in the cube is consistent, and so locking is used to ensure that the buffer cannot be updated part way through a display cycle:</p><p><pre class="brush: csharp">public void UpdateBuffer(byte[] newValues)
{
    lock (buffer)
    {
        for (int index = 0; index &lt; buffer.Length; index&#43;&#43;)
        {
            buffer[index] = newValues[index];
        }
    }
} </pre></p><p>The final method in this class is the method spawned off into it’s own thread:</p><p><pre class="brush: csharp">public void DisplayBuffer()
{
    while (true)
    {
        lock (buffer)
        {
            byte[] displayData = new byte[8];            for (int row = 0; row &lt; 8; row&#43;&#43;)
            {
                int offset = row * 8;                for (int index = 0; index &lt; 8; index&#43;&#43;)
                {
                    displayData[index] = buffer[offset &#43; index];
                }                enable.Write(true);
                bit0.Write((row &amp; 1) != 0);
                bit1.Write((row &amp; 2) != 0);
                bit2.Write((row &amp; 4) != 0);
                spi.Write(displayData);
                enable.Write(false);
            }
        }
    }
}</pre></p><p>This method again uses the lock statement to lock the buffer. This means we cannot update the buffer until a full cube of data has been displayed. The method takes a block of eight bytes representing a layer and then writes this to the shift registers using SPI. Note that the spi.Write is embedded in the write to the enable line. This ensures that all of the layers are turned off whilst we are updating the shift registers.</p><p>Wrapping all of this in the LEDCube class means that we now have a very simple class where we can spawn the DislpayBuffer method into its own thread.</p><h4>Main Program</h4><p>The main program sets the cube up and then controls what is actually shown in the cube. The first thing we need to do is to set up a buffer to store the cube display and then spawn off the DisplayBuffer into its own thread.</p><p><pre class="brush: csharp">private static LEDCube cube = new LEDCube();
private static byte[] newFrame = new byte[64];
ClearCube();
Cube.UpdateBuffer(newFrame);
Thread display = new Thread(new ThreadStart(cube.DisplayBuffer));
display.Start(); </pre></p><p>The ClearCube method is trivial and simply sets all of the bytes in newFrame to zero. At this point we have a cube with a whole lot of nothing going on. The next thing we need to do is to add some effects.</p><h4>Making it Rain</h4><p>Now that we have the mechanism to control the cube, we simply need to work out what we want to display. The rain effect in the opening video illustrates the majority of the techniques used to control the cube.</p><p>The rain algorithm is as follows:</p><ul><li>Set up the cube with a number of rain drops </li><li>Repeat <ul><li>Count the drops in the bottom layer </li><li>Move drops down one layer </li><li>Add the number of drops that have disappeared back into the top layer </li></ul></li></ul><p>To do this we will create two methods:</p><ul><li>AddDrops </li><li>Rain </li></ul><p><pre class="brush: csharp">private static void AddDrops(int count, int plane = -1)
{
    for (int drops = 0; drops &lt; count; drops&#43;&#43;)
    {
        bool findingSpace = true;
        while (findingSpace)
        {
            int x = rand.Next() % 8;
            int y = rand.Next() % 8;
            int z;            if (plane == -1)
            {
                z = rand.Next() % 8;
            }
            else
            {
                z = plane;
            }            int position = (z * 8) &#43; y;
            byte value = (byte) ((1 &lt;&lt; x) &amp; 0xff);
            if ((newFrame[position] &amp; value) == 0)
            {
                newFrame[position] |= value;
                findingSpace = false;
            }
        }
    }
}</pre></p><p>AddDrops simply adds a specified number of rain drops to the buffer. It also makes sure that if asked for 10 it will always add 10 by checking to see if one exists in the location it wanted to use (check out the findingSpace variable):</p><p><pre class="brush: csharp">private static void Rain(int noDrops, int cycles)
{
    ClearCube();
    AddDrops(noDrops);
    cube.UpdateBuffer(newFrame);
    for (int currentCycle = 0; currentCycle &lt; cycles; currentCycle&#43;&#43;)
    {
        int bitCount = 0;
        for (int plane = 0; plane &lt; 8; plane&#43;&#43;)
        {
            byte value = 1;
            for (int bit = 0; bit &lt; 8; bit&#43;&#43;)
            {
                if ((newFrame[56 &#43; plane] &amp; value) &gt; 0)
                {
                    bitCount&#43;&#43;;
                }
                value &lt;&lt;= 1;
            }
        }
        for (int plane = 7; plane &gt; 0; plane--)
        {
            for (int currentByte = 0; currentByte &lt; 8; currentByte&#43;&#43;)
            {
                newFrame[(plane * 8) &#43; currentByte] = newFrame[((plane - 1) * 8) &#43; currentByte];
            }
        }
        for (int b = 0; b &lt; 8; b&#43;&#43;)
        {
            newFrame[b] = 0;
        }
        AddDrops(bitCount, 0);
        cube.UpdateBuffer(newFrame);
        Thread.Sleep(75);
    }
}</pre></p><p>Rain adds the specified number of drops to the newFrame, shows the drops, and then moves them all down by one horizontal plane. Before doing this, it counts how many drops are going to fall out of the cube (the number in the bottom horizontal plane). After all the drops have moved down one plane it adds the drops which have disappeared out of the bottom of the cube back in at the top in random positions.</p><p>We can display this by adding the following to the main program:</p><p><pre class="brush: csharp">while (true)
{
    Rain(10, 60000);
} </pre></p><p>Full source code at <a href="http://netduinoledcontrol.codeplex.com/">http://netduinoledcontrol.codeplex.com/</a>.</p><p>If you add your own effects, remember to consider the rating of the equipment and parts used. Turning on a full horizontal layer consumes 1.6A for the LEDs alone. Things can get warm/hot if every LED in the cube is turned on at the same time so avoid such effects.</p><h3>Conclusion</h3><p>When I started out on this project I was not sure how fast the Netduino Mini could control the cube. It has proven that it is up to the task of keeping the display running whilst also being able to work on the upcoming “frame.” If you have gone this far and built a cube then how about expanding it:</p><ul><li>Add some filters and a microphone and make the display respond to its environment </li><li>Connect the cube to a PC using Bluetooth </li><li>Add an MP3 player module and write software to synchronise the display to the music </li></ul><p>Where will you take it?</p><h3>About The Author</h3><p>Mark Stevens is a software engineer and self-confessed technology addict. Mark started in the computer industry in the 1980s and at the age of 16 wrote a disk operating system for a then state of the art 8-bit microprocessor (despite the fact the machine already had one). He did it for fun and has been hooked on IT ever since then. Mark currently writes line of business applications for Win32, ASP.NET, and Silverlight platforms. He has recently taken up microelectronics as a hobby and has since discovered that his wife does not like the smell of solder. Marks’ current exploits, thoughts, and contact information can be found on his <a href="http://blog.mark-stevens.co.uk/">blog</a>.</p><p class="MsoNormal">&nbsp;</p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/netmf/RSS&WT.dl=0&WT.entryid=Entry:RSSView:a6740467db934541858d9f9101670ead">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Netduino-Controlled-LED-Cube</comments>
      <itunes:summary>Commercial LED cubes have been around for a while now and can be quite large and capable of some interesting displays. This project is on a smaller scale and goes through the steps required to build a Netduino Mini-controlled 512 LED cube (8 x 8 x 8). Clearly, the Mini does not have 512 pins and so we use Persistence of Vision to control the LEDs in the cube. The result is that seven pins on the Netduino Mini can control 512 LEDs. At the end of this article you should be able to create a cube capable of the following:  Bill of MaterialsDescription Quantity LEDs (I chose blue) 512 74HC595 Shift Registers 8 74HC238 3 to 8 line decoder 1 Netduino Mini 1 16 Pin DIL Socket (0.3&amp;quot;) 9 24 Pin DIL Socket (0.6&amp;quot;) 1 TIP122 NPN Transistor 8 100nF Ceramic Capacitor 10 2.2K Resistor 8 68 Ohm 0.25W Resistor (you may need to change these depending upon the LED you choose) 64 8 Way Single Row Socket 9 36 Way Header Strip (Straight) 3 2 Way Single Row Socket 2 2 Way PCB Mount Terminal Connector 1 8 Way Cable (ribbon or alarm) 2.5m Wire Miscellaneous Pad board 160 x 115 Hole 1 Hex PCB spacer and screw (M3 threaded) 4 &amp;nbsp; The following items are also required: 5V Power capable of delivering 2A Solder (I used about 15 metres over the life of this project). One 30cm x 30cm piece of wood Drill and wood drill bits (4mm – 5mm) Some cardboard and tape A fair amount of patience Good attention to detail You may need to shop around for the LEDs. I went to my preferred supplier and was quoted 18.5 pence each. By going on eBay I managed to negotiate the price down to 2.5 pence each including delivery. You are buying in bulk so don’t be afraid to ask for a good bulk price. Also, buy a few more than you need in case you have a faulty part or break a few. Building the CubeThis is probably the most time consuming part of the project requiring a lot of patience and testing. The aim of the project is to convert these 512 blue LEDs:  Into this:  Shaping the LEDsThe exact dimensions of the cub</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Netduino-Controlled-LED-Cube</link>
      <pubDate>Mon, 07 Nov 2011 22:50:33 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Netduino-Controlled-LED-Cube</guid>
      <media:thumbnail url="http://files.channel9.msdn.com/thumbnail/625598b3-50bc-4188-a5a8-4fe5cda94f85.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://files.channel9.msdn.com/thumbnail/e2ba5dbe-b6e5-4fa0-944f-76012370fb20.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Mark Stevens</dc:creator>
      <itunes:author>Mark Stevens</itunes:author>
      <slash:comments>25</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Netduino-Controlled-LED-Cube/RSS</wfw:commentRss>
      <category>Animation</category>
      <category>LED</category>
      <category>Electronics</category>
      <category>NETMF</category>
    </item>
  <item>
      <title>Tron Disc with .NET Microframework</title>
      <description><![CDATA[<p><a href="http://harfordhackerspace.org">Harford Hackerspace</a> wanted to make our own Tron Identity Disc using the Netduino, allowing us to quickly load different versions of code to change the disc's functionality. 
&nbsp; David Powell, Gary W. Cygiel, Jeremy Ashinghurst, Paul King, Jason 
McMahon present a simple lightshow in this tutorial, developers can easily extend the code and hardware
 to produce an interactive game. </p>
<div><a href="http://www.youtube.com/watch?v=I_KGca_g96U" target="_new"><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10104241/video7ca300f0af91.jpg" alt=""></a></div>
<p>To get started, we purchased and retrofitted a Spin Master Tron Identity Disc replica, which kept us from having to create a new physical disk, and so sidestepped the most difficult aspect of the project.
</p>

<h2>Operation Specifications</h2>
<p>We decided that we wanted our version of the Tron Idenity Disc to have the following specifications:</p>
<p><b>Power</b></p>
<ul>
<li>Rechargeable lithium-ion battery </li><li>LED to indicate the Tron Identity Disc is being charged </li><li>An On/Off switch enabling the battery to disconnect from the Netduino to conserve power while the disc is being stored
</li></ul>
<p><b>Operation</b></p>
<ul>
<li>Scenario 1 - Power On<b></b>
<ul>
<li>All LEDs turn on so we can make sure they are all working<b></b> </li></ul>
</li><li>Scenario 2 – Animations<b></b>
<ul>
<li>Pressing a momentary button will cycle through LED animations<b></b> </li></ul>
</li><li>Scenario 3 – Charge Detection<b></b>
<ul>
<li>Placing the Tron Idenity Disc on or removing the Tron Identity Disc from a charging station will raise an event handler. Placing the disc on the charger will start a pulsating animation. Removing the disc will resume the previous animation.<b></b>
</li></ul>
</li></ul>
<p><b>Hardware</b></p>
<ul>
<li><a href="http://www.google.com/url?q=http%3A%2F%2Fwww.toysrus.com%2Fproduct%2Findex.jsp%3FproductId%3D4068819&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNGJ-4fHEkYe0QbsDCi5xzVEoIgQfg">Deluxe</a><a href="http://www.google.com/url?q=http%3A%2F%2Fwww.toysrus.com%2Fproduct%2Findex.jsp%3FproductId%3D4068819&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNGJ-4fHEkYe0QbsDCi5xzVEoIgQfg">Tron</a><a href="http://www.google.com/url?q=http%3A%2F%2Fwww.toysrus.com%2Fproduct%2Findex.jsp%3FproductId%3D4068819&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNGJ-4fHEkYe0QbsDCi5xzVEoIgQfg">Identity</a><a href="http://www.google.com/url?q=http%3A%2F%2Fwww.toysrus.com%2Fproduct%2Findex.jsp%3FproductId%3D4068819&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNGJ-4fHEkYe0QbsDCi5xzVEoIgQfg">Disc</a><u></u>
</li><li><a href="http://www.google.com/url?q=http%3A%2F%2Fwww.netduino.com&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNFnCk2jHMrP3snNaRUoNADG8gXHBA">Netduino</a>
<u></u></li><li>Dremel with Cutoff Wheel<u></u> </li><li>Soldering Iron </li><li>Solder </li><li>Hot Glue Gun </li><li>Phillips Screw Driver </li><li>Wire Strippers </li><li>Heat Shrink </li><li><a href="http://www.sparkfun.com/products/341">Lithium-Ion Battery</a> (2x) </li><li><a href="http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;name=CKN9924-ND">SPST On/Off Switch</a>
</li><li><a href="http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;name=P12216SCT-ND">SPST Momentary Switch</a>
</li><li><a href="http://www.sparkfun.com/products/8812">Prototype Board</a> </li><li><a href="http://www.newark.com/vcc-visual-communications-company/vaol-5gsby4/led-5mm-blue-7000mcd-470nm/dp/57P7133?Ntt=VAOL-5GSBY4">Blue LEDs</a> (33x)
</li><li><a href="http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;name=MAX7219CNG%2B-ND">MAX7219</a>
</li><li><a href="http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;name=LM317TFS-ND">LM317T Adjustable Voltage Regulator</a>
</li><li><a href="http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;name=294-1108-ND">Heat sink for TO-220 devices</a>
</li><li><a href="http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;name=490-5401-ND">0.1uF capacitor</a> (2x)
</li><li><a href="http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;name=PN2222AD26ZCT-ND">2222 Transistor</a>
</li><li><a href="http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;name=201UR102B-ND">1k Ohm potentiometer</a>
</li><li><a href="http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;name=P470BACT-ND">470 Ohm resistor, ¼ watt</a> (2x)
</li><li><a href="http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;name=P10KBACT-ND">10k Ohm resistor, ¼ watt</a>
</li><li><a href="http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;name=P2.2KBATB-ND">2.2k Ohm resistor ¼ watt</a>
</li><li><a href="http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;name=PPC1.5W-1CT-ND">1.5 Ohm resistor, 1 watt</a>
</li><li><a href="http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;name=1N4001FSCT-ND">1N4001 Rectifier Diode</a>
</li></ul>
<h2>Tron Disc Light Ring</h2>
<p><b></b></p>
<p>The original <a href="http://www.google.com/url?q=http%3A%2F%2Fwww.toysrus.com%2Fproduct%2Findex.jsp%3FproductId%3D4068819&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNGJ-4fHEkYe0QbsDCi5xzVEoIgQfg">
Deluxe</a><a href="http://www.google.com/url?q=http%3A%2F%2Fwww.toysrus.com%2Fproduct%2Findex.jsp%3FproductId%3D4068819&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNGJ-4fHEkYe0QbsDCi5xzVEoIgQfg">Tron</a><a href="http://www.google.com/url?q=http%3A%2F%2Fwww.toysrus.com%2Fproduct%2Findex.jsp%3FproductId%3D4068819&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNGJ-4fHEkYe0QbsDCi5xzVEoIgQfg">Identity</a><a href="http://www.google.com/url?q=http%3A%2F%2Fwww.toysrus.com%2Fproduct%2Findex.jsp%3FproductId%3D4068819&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNGJ-4fHEkYe0QbsDCi5xzVEoIgQfg">Disc</a>
 contained six LED on the outer ring, which left much to be desired. Our modified disc includes 30 LEDs on the outer ring and two LEDs illuminating the inner arc.
</p>
<p>To get started, we opened the disc by removing its four Phillips head screws. Next, we removed all electronics including the wires, tilt sensor, LEDs, switch, speaker, and microcontroller board, taking care to not lose the plastic momentary button, since
 we later used it to switch between our animations. Then, we used a Dremel with a cutoff wheel to remove any unnecessary plastic in order to make room our own electronics. See Figure 1.</p>
<p align="center"><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10104241/Empty_Disc.jpg"><strong></strong></a><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10104241/Empty_Disc.jpg"><img title="Empty_Disc" border="0" alt="Empty_Disc" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10104241/Empty_Disc_thumb.jpg" width="500" height="333"></a></p>
<p align="center"><strong>Figure 1: Removed Plastic with Dremel</strong></p>
<p>As shown in Figure 2, we used superglue to attach the narrow end of the momentary button to the plastic Tron ring. Then, using the Dremel, we cut a small L bracket from a scrap piece of acrylic and attached it with cyanoacrylate. We reinforced the L bracket
 using hot glue and applied a small amount of cyanoacrylate to the momentary switch and attached it to the L bracket. Consequently, the original plastic momentary button now activates our momentary switch.
</p>
<p>While we had the hot glue gun out, we also attached the SPST On/Off switch and the two inner ring LEDs.</p>
<p align="center"><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10104241/mounting_switch.jpg"><strong><img title="mounting_switch" border="0" alt="mounting_switch" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10104241/mounting_switch_thumb.jpg" width="500" height="333"></strong></a></p>
<p align="center"><strong>Figure 2: Mounting Momentary Switch</strong></p>
<p>Next, we cut a circle from a piece of cardboard. Using a straight edge, we carefully marked the location of each LED to arrange an equally spaced circular pattern. Then, with a hobby razor knife, we cut notches in the cardboard at a slight angle to hold
 the LEDs. An additional benefit of the cardboard is it helps keep the anodes and cathodes from shorting out.</p>
<p align="center"><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10104241/clip_image006.jpg"><strong></strong></a><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10104241/clip_image006.jpg"><img title="clip_image006" border="0" alt="clip_image006" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10104241/clip_image006_thumb.jpg" width="500" height="333"></a></p>
<p align="center"><strong>Figure 3: LED Nestled in Notched Cardboard</strong></p>
<p>Next, we connected all of the components together per the following schematic diagrams. The MAX7219 IC is capable of controlling 64 LEDs. However, we chose to use only 30 in order to simplify of wiring. The circuit is divided into five segments, each containing
 six LEDs. In each segment, all the cathodes are tied together and then tied to a single segment pin on the MAX7219 and the anodes are routed back to its digit pins. There is one digit for each LED in the segment and the segments share digit pins. The Netduino
 controls the logic level of the digit and segment pins using “bit-banged” I2C. All that said, the schematic is the best reference as to how the LEDs were wired.</p>
<p align="center"><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10104241/3.png"><strong></strong></a><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10104241/3.png"><img title="3" border="0" alt="3" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10104241/3_thumb.png" width="500" height="212"></a></p>
<p align="center"><strong>Figure 4: Netduino and MAX7219 Schematic</strong></p>
<p><b></b></p>
<p><b></b></p>
<h2>Charging System</h2>
<p>The charging system is comprised of a charging circuit and a detection circuit. A lithium-ion battery inside the disc is charged from an external power source. The charging circuit, which was modified from a design by Scott Henion of<a href="http://www.google.com/url?q=http%3A%2F%2Fshdesigns.org%2F&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNGGePpOQjkuFZ45wutvAdxteBL_3w">SHDesigns</a><a href="http://www.google.com/url?q=http%3A%2F%2Fshdesigns.org%2F&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNGGePpOQjkuFZ45wutvAdxteBL_3w">.</a><a href="http://www.google.com/url?q=http%3A%2F%2Fshdesigns.org%2F&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNGGePpOQjkuFZ45wutvAdxteBL_3w">org</a>,
 provides a method of safe charging. The detection circuit allows the Netduino to know when it's being charged.</p>
<h3>Charging Circuit</h3>
<p align="center"><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10104241/1.png"><strong></strong></a><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10104241/1.png"><img title="1" border="0" alt="1" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10104241/1_thumb.png" width="497" height="347"></a></p>
<p align="center"><strong>Figure 5: Charging Station Schematic</strong></p>
<p>The LM317 is an adjustable voltage regulator that may also be used as an adjustable constant-current source. In this case, it's used as a voltage regulator. The 470 ohm resistor forms a voltage divider with the 1k ohm potentiometer and the 2.2k ohm resistor
 to set the output voltage at 8.4V. Since lithium-ion batteries should be charged using constant current-constant voltage, the transistor and resistor form the current limiting in the circuit. When the charge current reaches a certain threshold, the resistor's
 voltage drop exceeds the turn-on voltage of the transistor and the transistor starts to conduct. That takes current away from the voltage divider, dropping the voltage until the current is below the threshold. In this way, the current is limited until the
 voltage limit is reached; then, the current slowly drops off at a constant voltage.</p>
<h3>Detection circuit</h3>
<p><strong></strong></p>
<p align="center"><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10104241/Tron_Battery_Updated.jpg"><strong></strong></a><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10104241/Tron_Battery_Updated.jpg"><img title="Tron_Battery_Updated" border="0" alt="Tron_Battery_Updated" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10104241/Tron_Battery_Updated_thumb.jpg" width="500" height="251"></a></p>
<p align="center"><strong>Figure 6: Charge Detection Schematic</strong></p>
<p><b></b></p>
<p>The detection circuit works by applying a voltage to the disc whenever it is plugged in. When the disc is plugged in, 8.4V from the charger run through the 470 ohm resistor, then most of the current runs through the LED while a minimal amount runs through
 the 10k ohm resistor. The voltage to the Netduino is the voltage across the LED, equaling somewhere around 3V. When the charger is disconnected, however, the 10K ohm resistor pulls the voltage detection line to 0V. SW2 is a disconnect switch which feeds the
 main power to the Netduino. From there we use the Netduino's 5v power supply.</p>
<p>After all the connections were made we carefully placed all the wires and components inside the disc. We learned the hard way that you must pay extra attention since it's very easy to put a screw through one of your wires.
</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10104241/tucking_components.jpg"><img title="tucking_components" border="0" alt="tucking_components" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10104241/tucking_components_thumb.jpg" width="500" height="419"></a></p>
<p><b>Creating a driver for the MAX7219:</b></p>
<p>To create a driver for the MAX7219, we took a little information from the <a href="http://datasheets.maxim-ic.com/en/ds/MAX7219-MAX7221.pdf">
data sheet</a>. First, we created a basic class structure and initialized some static defines for the command reference as well as a few
<a href="http://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&amp;l=EN-US&amp;k=k%28MICROSOFT.SPOT.HARDWARE.OUTPUTPORT%29;k%28TargetFrameworkMoniker-%22.NETMICROFRAMEWORK%2cVERSION%3dV4.1%22%29;k%28DevLang-CSHARP%29&amp;rd=true">
OutputPort</a>'s to hold our pin's to <a href="http://en.wikipedia.org/wiki/Bit-banging">
bit-bang</a>. We bit-banged the protocol because the SPI implementation of the MAX7219 isn't 100% compliant with the Netduino's SPI Library:</p>
<pre class="csharpcode"><span class="kwrd">namespace</span> TronDisc
{
    <span class="kwrd">public</span> <span class="kwrd">class</span> max7219
    {
        <span class="rem">// Command reference</span>
        <span class="kwrd">public</span> <span class="kwrd">byte</span> max7219_reg_noop           = 0x00;
        <span class="kwrd">public</span> <span class="kwrd">byte</span> max7219_reg_digit0         = 0x01;
        <span class="kwrd">public</span> <span class="kwrd">byte</span> max7219_reg_digit1         = 0x02;
        <span class="kwrd">public</span> <span class="kwrd">byte</span> max7219_reg_digit2         = 0x03;
        <span class="kwrd">public</span> <span class="kwrd">byte</span> max7219_reg_digit3         = 0x04;
        <span class="kwrd">public</span> <span class="kwrd">byte</span> max7219_reg_digit4         = 0x05;
        <span class="kwrd">public</span> <span class="kwrd">byte</span> max7219_reg_digit5         = 0x06;
        <span class="kwrd">public</span> <span class="kwrd">byte</span> max7219_reg_digit6         = 0x07;
        <span class="kwrd">public</span> <span class="kwrd">byte</span> max7219_reg_digit7         = 0x08;
        <span class="kwrd">public</span> <span class="kwrd">byte</span> max7219_reg_decodeMode     = 0x09;
        <span class="kwrd">public</span> <span class="kwrd">byte</span> max7219_reg_intensity      = 0x0a;
        <span class="kwrd">public</span> <span class="kwrd">byte</span> max7219_reg_scanLimit      = 0x0b;
        <span class="kwrd">public</span> <span class="kwrd">byte</span> max7219_reg_shutdown       = 0x0c;
        <span class="kwrd">public</span> <span class="kwrd">byte</span> max7219_reg_displayTest    = 0x0f;

        <span class="rem">// Pin ports for spi</span>
        <span class="kwrd">private</span> OutputPort loadPin;
        <span class="kwrd">private</span> OutputPort dataPin;
        <span class="kwrd">private</span> OutputPort clkPin;

        <span class="rem">// Constructor, pass pin definitions</span>
        <span class="kwrd">public</span> max7219( OutputPort in_dataPin,
                        OutputPort in_clockPin,
   OutputPort in_loadPin )
        {
            <span class="rem">// Assign local port pins to ports passed from constructor</span>
            dataPin = in_dataPin;
            clkPin = in_clockPin;
            loadPin = in_loadPin;
     }
     }
}</pre>
<style type="text/css">
<!--
.csharpcode, .csharpcode 
 {font-size:small;
 color:black;
 font-family:consolas,"Courier New",courier,monospace;
 background-color:#ffffff}
.csharpcode 
 {margin:0em}
.csharpcode .rem
 {color:#008000}
.csharpcode .kwrd
 {color:#0000ff}
.csharpcode .str
 {color:#006080}
.csharpcode .op
 {color:#0000c0}
.csharpcode .preproc
 {color:#cc6633}
.csharpcode .asp
 {background-color:#ffff00}
.csharpcode .html
 {color:#800000}
.csharpcode .attr
 {color:#ff0000}
.csharpcode .alt
 {background-color:#f4f4f4;
 width:100%;
 margin:0em}
.csharpcode .lnum
 {color:#606060}
-->
</style>
<p>Next we added a method to our class to transmit a single byte to the MAX7219:</p>
<pre class="csharpcode"><span class="rem">// Transmits 1 byte over SPI, bitbang method</span>
<span class="kwrd">public</span> <span class="kwrd">void</span> putByte(<span class="kwrd">byte</span> data)
{
    <span class="kwrd">byte</span> i = 8;
    <span class="kwrd">int</span> mask;

    <span class="kwrd">while</span> (i &gt; 0)
    {
        mask = (1 &lt;&lt; i - 1);
        clkPin.Write(<span class="kwrd">false</span>);
        <span class="kwrd">if</span> (((<span class="kwrd">int</span>)data &amp; mask) == 0)
            dataPin.Write(<span class="kwrd">false</span>);
        <span class="kwrd">else</span>
            dataPin.Write(<span class="kwrd">true</span>);
        clkPin.Write(<span class="kwrd">true</span>);
        --i;
    }
}</pre>
<p>And finally, we added one more method that pulled our load pin low, transmitted the register and column bytes, and pulled load high again to latch the data:</p>
<pre class="csharpcode"><span class="rem">// Sends 1 Command / Data pair to a single driver chip</span>
<span class="kwrd">public</span> <span class="kwrd">void</span> maxSingle(<span class="kwrd">byte</span> reg, <span class="kwrd">byte</span> col)
{
    <span class="rem">// LOAD low</span>
    loadPin.Write(<span class="kwrd">false</span>);

    <span class="rem">// Transmit Register</span>
    putByte(reg);
    <span class="rem">// Transmit Column</span>
    putByte(col);

    <span class="rem">// LOAD high latches data sent</span>
    loadPin.Write(<span class="kwrd">true</span>);
}</pre>
<p>Complete with a function to send commands to the MAX via the maxSingle, we went back to our constructor and passed some initialization values after our pin assignments. maxSingle is so named because it only addresses one MAX7219, and since they are daisy-chainable,
 we can control multiple MAX7219s with little modification to our code:</p>
<pre class="csharpcode"><span class="rem">// Initialize MAX7219</span>
<span class="rem">// set scan limit</span>
maxSingle(max7219_reg_scanLimit, 0x07);
<span class="rem">// using an led matrix mode (not digits)</span>
maxSingle(max7219_reg_decodeMode, 0x00);
<span class="rem">// not in shutdown mode</span>
maxSingle(max7219_reg_shutdown, 0x01);
<span class="rem">// no display test</span>
maxSingle(max7219_reg_displayTest, 0x00);
<span class="rem">// set max intensity  (range 00-0f)</span>
maxSingle(max7219_reg_intensity, 0x0f);</pre>
<p><b>Using the driver:</b></p>
<p>To use the driver, we created a variable to hold the instance of our driver, created the actual OutputPort references to pins, and passed to our instanced MAX7219 driver. The pins we are using are D10, D11, D13:</p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">static</span> max7219 driver;

<span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> Main()
{
    <span class="rem">// Define spi pins</span>
    OutputPort loadPin = <span class="kwrd">new</span> OutputPort(Pins.GPIO_PIN_D10, <span class="kwrd">false</span>);
    OutputPort dataPin = <span class="kwrd">new</span> OutputPort(Pins.GPIO_PIN_D11, <span class="kwrd">false</span>);
    OutputPort clkPin = <span class="kwrd">new</span> OutputPort(Pins.GPIO_PIN_D13, <span class="kwrd">false</span>);

    <span class="rem">// Instance of driver, passing pin assignments</span>
    driver = <span class="kwrd">new</span> max7219(dataPin, clkPin, loadPin);
}</pre>
<p>At this point, we used our driver by calling driver.maxSingle(reg, col) to light either a single LED or a group of LEDs depending on specifications.</p>
<h2><b>Animations</b></h2>
<p>We completed two different types of animations, one based off of an algorithm and one using frame-by-frame animation for more complex patterns.</p>
<p>Our first animation is my personal favorite, the pulsating animation, which uses pulses to raise and lower the brightness:</p>
<pre class="csharpcode"><span class="rem">// Main loop</span>
<span class="kwrd">while</span> (<span class="kwrd">true</span>)
{
   <span class="rem">// if direction is 1, we are going to fade down</span>
   <span class="kwrd">if</span> (dir == 1)
      cnt--;
   <span class="kwrd">else</span> <span class="rem">// otherwise fade up</span>
      cnt&#43;&#43;;

   <span class="rem">// if direction is fading down and we are at 0 (the bottom)</span>
   <span class="rem">// switch directions to fading up</span>
   <span class="kwrd">if</span> (dir == 1 &amp;&amp; cnt == 0)
      dir = 0;
   <span class="rem">// and if we are fading up (dir == 0) and we are at the max intensity</span>
   <span class="rem">// lets start fading down</span>
   <span class="kwrd">else</span> <span class="kwrd">if</span> (dir == 0 &amp;&amp; cnt == 15)
      dir = 1;

    <span class="rem">// loop through driver.MAX7219_reg_digit0-7 and make sure all led's</span>
    <span class="rem">// are on by passing 0xFF which is all 8 bits on per digit</span>
   <span class="kwrd">for</span> (j = 1; j &lt; 8; j&#43;&#43;)
      driver.maxSingle(j, 0xFF);

   <span class="rem">// Pass the cnt value to the intensity register</span>
   driver.maxSingle(driver.max7219_reg_intensity, (<span class="kwrd">byte</span>)(cnt &amp; 0x0f));

   <span class="rem">// Add a small delay between levels of intensity</span>
   Thread.Sleep(15);
}</pre>
<p>Wow, that looks great! Now we can create all kinds of animations using simple algorithms. To create more complex animations, however, a simpler method was needed. The disc is wired up around the ring using five digits of six LED segments. To simplify the
 math, we made a graphical ring of 30 LEDs, recorded each frame, and stored five characters per frame using six bits per character.</p>
<p>The creator is posted on the web at <a href="http://harfordhackerspace.org/ledwiz/tron/">
http://harfordhackerspace.org/ledwiz/tron/</a> and was created using HTML/Javascript and CSS. We won't get into the details of that code in this article, but feel free to use it to create as many animations as your Netduino will hold!</p>
<p>After creating an animation, click the ‘generate' button to get an output similar to the following:</p>
<pre class="csharpcode"><span class="kwrd">byte</span>[] animation = <span class="kwrd">new</span> <span class="kwrd">byte</span>[] {
  0x2,0x11,0x4,0x21,0x8,
  0x4,0x22,0x8,0x2,0x11,
  0x8,0x4,0x11,0x4,0x22
};</pre>
<p>Here you can see three frames (one line per frame) with five characters using six bits per character. To display the animation, keep track of which digit (0-5) is active as the register and pass the character as the column:</p>
<pre class="csharpcode"><span class="kwrd">int</span> i;

<span class="kwrd">for</span> (i = 0; i &lt; animation.Length; i&#43;&#43;)
{
    driver.maxSingle((<span class="kwrd">byte</span>)((i % 5) &#43; 1), animation[i]);
}</pre>
<p>It's a simple animation. To slow it down, add a <a href="http://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&amp;l=EN-US&amp;k=k%28SYSTEM.THREADING.THREAD.SLEEP%29;k%28TargetFrameworkMoniker-%22.NETMICROFRAMEWORK%2cVERSION%3dV4.1%22%29;k%28DevLang-CSHARP%29&amp;rd=true">
Thread.sleep</a>(x) (x being the number of milliseconds between each command).</p>
<h2>Dealing with multiple frame by frame animations</h2>
<p>To create multi-frame animations, make a multi-dimensional array and modify the code to support multiple animations:</p>
<pre class="csharpcode"><span class="kwrd">byte</span> animation_num = 0;
<span class="kwrd">int</span> i;
<span class="kwrd">byte</span>[][] animations = <span class="kwrd">new</span> <span class="kwrd">byte</span>[][]
{
   <span class="kwrd">new</span> <span class="kwrd">byte</span>[]
   {
      0x2,0x11,0x4,0x21,0x8,
      0x4,0x22,0x8,0x2,0x11,
      0x8,0x4,0x11,0x4,0x22
   },
   <span class="kwrd">new</span> <span class="kwrd">byte</span>[]
   {
      0x1,0x10,0x2,0x8,0x2,
      0x3,0x18,0x6,0x2,0x8,
      0x7,0x3,0x18,0x1,0x8
   }
}
<span class="rem">// Main loop</span>
<span class="kwrd">while</span> (<span class="kwrd">true</span>)
{
   <span class="kwrd">for</span> (i = 0; i &lt; animations[animation_num].Length; i&#43;&#43;)
   {
      driver.maxSingle((<span class="kwrd">byte</span>)((i % 5) &#43; 1), animations[animation_num][i]);
   }
}</pre>
<p>Once it hits the main loop, it will keep playing the first animation (which is 0) until a change in the value of animation_num to 1 (then it will play the second animation).</p>
<p>A method is needed to read the button on the Disc and increment/loop the animation_num value. To do this, use the
<a href="http://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&amp;l=EN-US&amp;k=k%28MICROSOFT.SPOT.HARDWARE.INTERRUPTPORT%29;k%28TargetFrameworkMoniker-%22.NETMICROFRAMEWORK%2cVERSION%3dV4.1%22%29;k%28DevLang-CSHARP%29&amp;rd=true">
InterruptPort</a> class.</p>
<p>First, add the InterruptPort code to the Main() function before the Main loop:</p>
<pre class="csharpcode"><span class="rem">// Tron Button to Change Annimations, pulls high</span>
InterruptPort changeBtn = 
   <span class="kwrd">new</span> InterruptPort(
      Pins.GPIO_PIN_D0, 
      <span class="kwrd">false</span>, 
      Port.ResistorMode.Disabled,
      Port.InterruptMode.InterruptEdgeHigh);
changeBtn.OnInterrupt &#43;= <span class="kwrd">new</span> NativeEventHandler(changeBtn_OnInterrupt);</pre>
<p>Then, add a method called changeBtn_OnInterrupt to the program:</p>
<pre class="csharpcode"><span class="rem">//Interrupt Handler for changeBtn to change annimations</span>
<span class="kwrd">static</span> <span class="kwrd">void</span> changeBtn_OnInterrupt(<span class="kwrd">uint</span> data1, <span class="kwrd">uint</span> data2, DateTime time)
{
    <span class="kwrd">if</span> (&#43;&#43;new_animation_num &gt; animation_total)
    {
        new_animation_num = 0;
    }

     <span class="rem">// reset intensity to max incase previous animation exits with </span>
     <span class="rem">// intensity less than max</span>
    driver.maxSingle(driver.max7219_reg_intensity, 0x0f);

    <span class="rem">// Print debug string</span>
    Debug.Print(<span class="str">&quot;Animation Num: &quot;</span>);
    Debug.Print(new_animation_num.ToString());
}</pre>
<p>Finally, to get it all working, add a switcher at the top of the loop, change the animation_num values to be public throughout the class, as well as static since the program is static:</p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> Program
{
    <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">byte</span> new_animation_num = 0;
    <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">byte</span> animation_num = 0;
    <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">byte</span> animation_total = 2;

    <span class="rem">/* more goodness */</span>

    <span class="rem">// Main loop</span>
    <span class="kwrd">while</span> (<span class="kwrd">true</span>)
    {
        animation_num = new_animation_num;

        <span class="rem">// adding this to the top of our main loop</span>
    }
    <span class="rem">/* more goodness */</span>
}</pre>
<h2>Finishing touches</h2>
<p>To make it all work together, we mixed algorithmic animations by filling our animations array, hard-coded a few “if” statements to do algorithmic animations, as well as “else” statements for all the frame-based animations.&nbsp; We also added another InterruptHandler
 to both act like a button when the Disc is placed on the charging dock and change the animation to the pulse animation.&nbsp; Also, we tested the power by turning on all of the LEDs, waiting three seconds, and then proceeding.</p>
<h2>About</h2>
<p>Harford Hackerspace is a non-profit 501(C)(3) charitable organization set forth to create a place for people to collaborate on hardware and software projects. Members of the space have been meeting weekly since January 2009 to socialize, learn, and work
 on projects related to science and technology. In 2009 they built a <a href="http://harfordhackerspace.org/category/cnc/">
Computer Numerical Controller (CNC) Router</a> capable of precision cutting of wood, plastics, and aluminum. In August 2010 Harford Hackerspace hosted the first ever
<a href="http://harfordhackerspace.org/category/netduino/">Netduino class</a> with Secret Labs CTO Chris Walker. Most recently in November 2010 Harford Hackerspace won first place in the
<a href="http://www.baltimorehackathon.com">Baltimore Hackathon</a> with their <a href="http://harfordhackerspace.org/2010/11/haha-wins-first-place/">
RotoFoto Project.</a></p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/netmf/RSS&WT.dl=0&WT.entryid=Entry:RSSView:e40e14f6d92643b4be979e7600c6fbb8">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Tron-Disc-with-NET-Microframework</comments>
      <itunes:summary>Harford Hackerspace wanted to make our own Tron Identity Disc using the Netduino, allowing us to quickly load different versions of code to change the disc&#39;s functionality. 
&amp;nbsp; David Powell, Gary W. Cygiel, Jeremy Ashinghurst, Paul King, Jason 
McMahon present a simple lightshow in this tutorial, developers can easily extend the code and hardware
 to produce an interactive game.  

To get started, we purchased and retrofitted a Spin Master Tron Identity Disc replica, which kept us from having to create a new physical disk, and so sidestepped the most difficult aspect of the project.
 

Operation Specifications
We decided that we wanted our version of the Tron Idenity Disc to have the following specifications: 
Power 

Rechargeable lithium-ion battery LED to indicate the Tron Identity Disc is being charged An On/Off switch enabling the battery to disconnect from the Netduino to conserve power while the disc is being stored

Operation 

Scenario 1 - Power On

All LEDs turn on so we can make sure they are all working 
Scenario 2 – Animations

Pressing a momentary button will cycle through LED animations 
Scenario 3 – Charge Detection

Placing the Tron Idenity Disc on or removing the Tron Identity Disc from a charging station will raise an event handler. Placing the disc on the charger will start a pulsating animation. Removing the disc will resume the previous animation.


Hardware 

DeluxeTronIdentityDisc
Netduino
Dremel with Cutoff Wheel Soldering Iron Solder Hot Glue Gun Phillips Screw Driver Wire Strippers Heat Shrink Lithium-Ion Battery (2x) SPST On/Off Switch
SPST Momentary Switch
Prototype Board Blue LEDs (33x)
MAX7219
LM317T Adjustable Voltage Regulator
Heat sink for TO-220 devices
0.1uF capacitor (2x)
2222 Transistor
1k Ohm potentiometer
470 Ohm resistor, &#188; watt (2x)
10k Ohm resistor, &#188; watt
2.2k Ohm resistor &#188; watt
1.5 Ohm resistor, 1 watt
1N4001 Rectifier Diode

Tron Disc Light Ring
 
The original 
DeluxeTronIdentityDisc
 contained six LED on the outer r</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Tron-Disc-with-NET-Microframework</link>
      <pubDate>Mon, 13 Dec 2010 16:24:24 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Tron-Disc-with-NET-Microframework</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/10104241_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/10104241_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Harford Hackerspace</dc:creator>
      <itunes:author>Harford Hackerspace</itunes:author>
      <slash:comments>9</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Tron-Disc-with-NET-Microframework/RSS</wfw:commentRss>
      <category>Hardware</category>
      <category>Electronics</category>
      <category>NETMF</category>
      <category>mods</category>
    </item>
  <item>
      <title>Netduino – Open source hardware</title>
      <description><![CDATA[
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10045753/image.png"><img title="image" border="0" alt="image" align="right" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10045753/image_thumb.png" width="240" height="188"></a>
 There is a new .NET Micro Framework board that is 100% open source now.&nbsp; The <a href="http://www.netduino.com/">
netduino from Secret Labs</a> can leverage the arduino shields!&nbsp; Their projects page,
<a href="http://www.netduino.com/projects/">http://www.netduino.com/projects/</a>, has a few projects like how to get a blinking LED to work and read data from a color sensor to determine was color is in front of it.</p>
<p>Netduino combines 20 GPIOs with SPI, I2C, 2 UARTs (1 RTS/CTS), 4 PWM and 6 ADC channels.&nbsp; Best of all with NETMF 4.1, you can use Visual Studio 2010!</p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/netmf/RSS&WT.dl=0&WT.entryid=Entry:RSSView:f812db75ca054524b0d39e7600c8edff">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/blog/Netduino--Open-source-hardware</comments>
      <itunes:summary>

 There is a new .NET Micro Framework board that is 100% open source now.&amp;nbsp; The 
netduino from Secret Labs can leverage the arduino shields!&amp;nbsp; Their projects page,
http://www.netduino.com/projects/, has a few projects like how to get a blinking LED to work and read data from a color sensor to determine was color is in front of it. 
Netduino combines 20 GPIOs with SPI, I2C, 2 UARTs (1 RTS/CTS), 4 PWM and 6 ADC channels.&amp;nbsp; Best of all with NETMF 4.1, you can use Visual Studio 2010! 
</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/blog/Netduino--Open-source-hardware</link>
      <pubDate>Wed, 04 Aug 2010 02:36:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/blog/Netduino--Open-source-hardware</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/10045753_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/10045753_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Clint Rutkas</dc:creator>
      <itunes:author>Clint Rutkas</itunes:author>
      <slash:comments>10</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/blog/Netduino--Open-source-hardware/RSS</wfw:commentRss>
      <category>.NET Micro Framework</category>
      <category>C4FNews</category>
      <category>NETMF</category>
      <category>.NET Microframework</category>
    </item>
  <item>
      <title>.NET on a bicycle</title>
      <description><![CDATA[
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10033092/5367.image_5F00_23C3DD5D.png"><img title="image" border="0" alt="image" align="right" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10033092/7848.image_5F00_thumb_5F00_79F03C9C.png" width="240" height="183"></a>
 The .NET Micro Framework (NETMF) team has a great example of using low cost, embedded computing to improve their biking experience.</p>
<p>All the source code can be found at <a title="http://netmfbikecomputer.codeplex.com/" href="http://netmfbikecomputer.codeplex.com/">
http://netmfbikecomputer.codeplex.com/</a> and just a reminder, the NETMF is 100% open source as well!</p>
<ol>
<li><a href="http://blogs.msdn.com/b/netmfteam/archive/2010/05/25/bicycle-computer-1-introduction.aspx">Introduction</a>
</li><li><a href="http://blogs.msdn.com/b/netmfteam/archive/2010/05/25/bicycle-computer-2-getting-the-project-started.aspx">Getting the project set up</a>
</li><li><a href="http://blogs.msdn.com/b/netmfteam/archive/2010/05/28/bicycle-computer-3-sensors-and-sensor-integration.aspx">Sensors and Integration</a>
</li><li><a href="http://blogs.msdn.com/b/netmfteam/archive/2010/06/03/bicycle-computer-4-ui-continued-fonts-and-touch.aspx">UI – Font and touch</a>
</li><li><a href="http://blogs.msdn.com/b/netmfteam/archive/2010/06/08/bicycle-computer-5-ui-continued-custom-controls.aspx">UI custom controls</a>
</li><li><a href="http://blogs.msdn.com/b/netmfteam/archive/2010/06/14/bicycle-computer-6-more-complex-sensor-integration.aspx">Complex sensor integration</a>
</li><li><a href="http://blogs.msdn.com/b/netmfteam/archive/2010/06/21/bicycle-computer-7-working-with-the-emulator-when-you-have-new-peripherals.aspx">Working with emulator</a>
</li></ol>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/netmf/RSS&WT.dl=0&WT.entryid=Entry:RSSView:7d43a5a539af443e8ec19e7600c91776">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/blog/NET-on-a-bicycle</comments>
      <itunes:summary>

 The .NET Micro Framework (NETMF) team has a great example of using low cost, embedded computing to improve their biking experience. 
All the source code can be found at 
http://netmfbikecomputer.codeplex.com/ and just a reminder, the NETMF is 100% open source as well! 

Introduction
Getting the project set up
Sensors and Integration
UI – Font and touch
UI custom controls
Complex sensor integration
Working with emulator

</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/blog/NET-on-a-bicycle</link>
      <pubDate>Wed, 30 Jun 2010 16:35:38 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/blog/NET-on-a-bicycle</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/10033092_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/10033092_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Clint Rutkas</dc:creator>
      <itunes:author>Clint Rutkas</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/blog/NET-on-a-bicycle/RSS</wfw:commentRss>
      <category>.NET Micro Framework</category>
      <category>Hardware</category>
      <category>C4FNews</category>
      <category>NETMF</category>
      <category>.NET Microframework</category>
      <category>embedded systems</category>
    </item>    
</channel>
</rss>