<?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 Hardware</title>
    <atom:link rel="self" type="application/rss+xml" href="http://channel9.msdn.com/Tags/hardware/RSS"/>
    <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 Hardware</title>
      <link>http://channel9.msdn.com/Tags/hardware</link>
    </image>
    <itunes:image href=""/>
    <itunes:category text="Technology"/>
    <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/hardware</link>
    <language>en</language>
    <pubDate>Sun, 12 Feb 2012 15:51:10 GMT</pubDate>
    <lastBuildDate>Sun, 12 Feb 2012 15:51:10 GMT</lastBuildDate>
    <generator>Rev9</generator>
    <c9:totalResults>160</c9:totalResults>
    <c9:pageCount>7</c9:pageCount>
    <c9:pageSize>25</c9:pageSize>
  <item>
      <title>Building Hardware-accelerated Encrypted Storage Devices (eDrives) in Windows 8</title>
      <description><![CDATA[<p>This video presentation discusses how to build hardware-accelerated encrypted storage drives (eDrives) in Windows 8. It also&nbsp;dives into details on&nbsp;the differences between eDrives and self-encrypting drives.</p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/hardware/RSS&WT.dl=0&WT.entryid=Entry:RSSView:a04c8cacd3b344fc80f19fc0018a7c73">]]></description>
      <comments>http://channel9.msdn.com/posts/Building-Hardware-accelerated-Encrypted-Storage-Devices-eDrives-in-Windows-8</comments>
      <itunes:summary>This video presentation discusses how to build hardware-accelerated encrypted storage drives (eDrives) in Windows 8. It also&amp;nbsp;dives into details on&amp;nbsp;the differences between eDrives and self-encrypting drives.</itunes:summary>
      <itunes:duration>596</itunes:duration>
      <link>http://channel9.msdn.com/posts/Building-Hardware-accelerated-Encrypted-Storage-Devices-eDrives-in-Windows-8</link>
      <pubDate>Fri, 23 Dec 2011 06:45:03 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/posts/Building-Hardware-accelerated-Encrypted-Storage-Devices-eDrives-in-Windows-8</guid>
      <media:thumbnail url="http://video.ch9.ms/ch9/7c73/a04c8cac-d3b3-44fc-80f1-9fc0018a7c73/BuildingEDrivesInWindows8_100_ch9.jpg" height="75" width="100"/>
      <media:thumbnail url="http://video.ch9.ms/ch9/7c73/a04c8cac-d3b3-44fc-80f1-9fc0018a7c73/BuildingEDrivesInWindows8_220_ch9.jpg" height="165" width="220"/>
      <media:thumbnail url="http://video.ch9.ms/ch9/7c73/a04c8cac-d3b3-44fc-80f1-9fc0018a7c73/BuildingEDrivesInWindows8_512_ch9.jpg" height="384" width="512"/>
      <media:thumbnail url="http://video.ch9.ms/ch9/7c73/a04c8cac-d3b3-44fc-80f1-9fc0018a7c73/BuildingEDrivesInWindows8_custom_ch9.jpg" height="384" width="512"/>
      <media:group>
        <media:content url="http://smooth.ch9.ms/ch9/7c73/a04c8cac-d3b3-44fc-80f1-9fc0018a7c73/BuildingEDrivesInWindows8.ism/manifest" expression="full" duration="596" fileSize="8638" type="video/x-ms-wmv" medium="video"/>
        <media:content url="http://video.ch9.ms/ch9/7c73/a04c8cac-d3b3-44fc-80f1-9fc0018a7c73/BuildingEDrivesInWindows8_2MB_ch9.wmv" expression="full" duration="596" fileSize="213385130" type="video/x-ms-wmv" medium="video"/>
        <media:content url="http://video.ch9.ms/ch9/7c73/a04c8cac-d3b3-44fc-80f1-9fc0018a7c73/BuildingEDrivesInWindows8_ch9.mp3" expression="full" duration="596" fileSize="4769198" type="audio/mp3" medium="audio"/>
        <media:content url="http://video.ch9.ms/ch9/7c73/a04c8cac-d3b3-44fc-80f1-9fc0018a7c73/BuildingEDrivesInWindows8_ch9.webm" expression="full" duration="596" fileSize="42923801" type="video/webm" medium="video"/>
        <media:content url="http://video.ch9.ms/ch9/7c73/a04c8cac-d3b3-44fc-80f1-9fc0018a7c73/BuildingEDrivesInWindows8_ch9.wma" expression="full" duration="596" fileSize="4826399" type="audio/x-ms-wma" medium="audio"/>
        <media:content url="http://video.ch9.ms/ch9/7c73/a04c8cac-d3b3-44fc-80f1-9fc0018a7c73/BuildingEDrivesInWindows8_ch9.wmv" expression="full" duration="596" fileSize="56985003" type="video/x-ms-wmv" medium="video"/>
        <media:content url="http://video.ch9.ms/ch9/7c73/a04c8cac-d3b3-44fc-80f1-9fc0018a7c73/BuildingEDrivesInWindows8_high_ch9.mp4" expression="full" duration="596" fileSize="120546683" type="video/mp4" medium="video"/>
        <media:content url="http://video.ch9.ms/ch9/7c73/a04c8cac-d3b3-44fc-80f1-9fc0018a7c73/BuildingEDrivesInWindows8_low_ch9.mp4" expression="full" duration="596" fileSize="29175901" type="video/mp4" medium="video"/>
        <media:content url="http://video.ch9.ms/ch9/7c73/a04c8cac-d3b3-44fc-80f1-9fc0018a7c73/BuildingEDrivesInWindows8_med_ch9.mp4" expression="full" duration="596" fileSize="88198761" type="video/mp4" medium="video"/>
      </media:group>      
      <enclosure url="http://video.ch9.ms/ch9/7c73/a04c8cac-d3b3-44fc-80f1-9fc0018a7c73/BuildingEDrivesInWindows8_ch9.wmv" length="56985003" type="video/x-ms-wmv"/>
      <dc:creator>Roxanne Beaver</dc:creator>
      <itunes:author>Roxanne Beaver</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/posts/Building-Hardware-accelerated-Encrypted-Storage-Devices-eDrives-in-Windows-8/rss</wfw:commentRss>
      <category>encryption</category>
      <category>Hardware</category>
      <category>Windows 8</category>
    </item>
  <item>
      <title>Windows 8 Running on ARM </title>
      <description><![CDATA[ <p><span>Roger Gulrajani from the Windows Hardware Ecosystem group shows us a Qualcomm <a href="http://www.qualcomm.com/snapdragon">Snapdragon</a>&nbsp;reference device that uses an ARM processor. This is another example of the types of machines that will be running Windows 8.</span></p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/hardware/RSS&WT.dl=0&WT.entryid=Entry:RSSView:384315ae55154c0789249f5f011867e5">]]></description>
      <comments>http://channel9.msdn.com/posts/Windows-8-Running-on-ARM</comments>
      <itunes:summary> Roger Gulrajani from the Windows Hardware Ecosystem group shows us a Qualcomm Snapdragon&amp;nbsp;reference device that uses an ARM processor. This is another example of the types of machines that will be running Windows 8.</itunes:summary>
      <itunes:duration>215</itunes:duration>
      <link>http://channel9.msdn.com/posts/Windows-8-Running-on-ARM</link>
      <pubDate>Thu, 15 Sep 2011 21:49:23 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/posts/Windows-8-Running-on-ARM</guid>
      <media:thumbnail url="http://video.ch9.ms/ch9/67e5/384315ae-5515-4c07-8924-9f5f011867e5/W8SnapDragon_100_ch9.jpg" height="75" width="100"/>
      <media:thumbnail url="http://media.ch9.ms/ch9/67e5/384315ae-5515-4c07-8924-9f5f011867e5/W8SnapDragon_220_ch9.jpg" height="165" width="220"/>
      <media:thumbnail url="http://video.ch9.ms/ch9/67e5/384315ae-5515-4c07-8924-9f5f011867e5/W8SnapDragon_512_ch9.jpg" height="384" width="512"/>
      <media:group>
        <media:content url="http://smooth.ch9.ms/ch9/67e5/384315ae-5515-4c07-8924-9f5f011867e5/W8SnapDragon.ism/manifest" expression="full" duration="215" fileSize="8430" type="video/x-ms-wmv" medium="video"/>
        <media:content url="http://video.ch9.ms/ch9/67e5/384315ae-5515-4c07-8924-9f5f011867e5/W8SnapDragon_2MB_ch9.wmv" expression="full" duration="215" fileSize="143096667" type="video/x-ms-wmv" medium="video"/>
        <media:content url="http://video.ch9.ms/ch9/67e5/384315ae-5515-4c07-8924-9f5f011867e5/W8SnapDragon_ch9.mp3" expression="full" duration="215" fileSize="1727732" type="audio/mp3" medium="audio"/>
        <media:content url="http://video.ch9.ms/ch9/67e5/384315ae-5515-4c07-8924-9f5f011867e5/W8SnapDragon_ch9.wma" expression="full" duration="215" fileSize="1753307" type="audio/x-ms-wma" medium="audio"/>
        <media:content url="http://video.ch9.ms/ch9/67e5/384315ae-5515-4c07-8924-9f5f011867e5/W8SnapDragon_ch9.wmv" expression="full" duration="215" fileSize="46454724" type="video/x-ms-wmv" medium="video"/>
        <media:content url="http://video.ch9.ms/ch9/67e5/384315ae-5515-4c07-8924-9f5f011867e5/W8SnapDragon_high_ch9.mp4" expression="full" duration="215" fileSize="89908979" type="video/mp4" medium="video"/>
        <media:content url="http://video.ch9.ms/ch9/67e5/384315ae-5515-4c07-8924-9f5f011867e5/W8SnapDragon_low_ch9.mp4" expression="full" duration="215" fileSize="19533151" type="video/mp4" medium="video"/>
      </media:group>      
      <enclosure url="http://video.ch9.ms/ch9/67e5/384315ae-5515-4c07-8924-9f5f011867e5/W8SnapDragon_ch9.wmv" length="46454724" type="video/x-ms-wmv"/>
      <dc:creator>Larry Larsen</dc:creator>
      <itunes:author>Larry Larsen</itunes:author>
      <slash:comments>11</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/posts/Windows-8-Running-on-ARM/rss</wfw:commentRss>
      <category>Hardware</category>
      <category>Windows 8</category>
    </item>
  <item>
      <title>A Tweeting .NET Micro Framework breathalyzer</title>
      <description><![CDATA[ <p>This project shows how you can use the Netduino Plus to make a tweeting breathalyzer—a standalone breathalyzer that can post messages about the detected alcohol level to Twitter, using an inexpensive alcohol gas sensor.</p><p>The <a href="http://www.netduino.com/">Netduino</a> is an open source electronics platform based on a 32-bit microcontroller running the .NET Micro Framework. The <a href="http://www.netduino.com/netduinoplus/">Netduino Plus</a> is similar to the original Netduino, but adds a built-in Ethernet controller and MicroSD slot. Since the Netduino Plus can connect directly to a network, it can independently communicate with Twitter’s API without being connected to a computer.</p><h3>Hardware Overview</h3><p>&nbsp;</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/Img0058%5B4%5D.jpg"><img title="Img0058" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/Img0058_thumb%5B1%5D.jpg" alt="Img0058" width="640" height="438" border="0"></a></p><p>The <a href="http://www.makershed.com/ProductDetails.asp?ProductCode=MSMS01&amp;Click=37845">MakerShield</a> is a simple prototyping shield that is compatible with the standard Arduino and Netduino boards.</p><p>In this configuration, the MQ-3 alcohol gas sensor will output an analog voltage between 0 and 3.3V to indicate the amount of alcohol detected. This output will be connected to one of the Netduino’s analog input pins and read by its ADC.</p><p>While it would possible to convert the sensor’s output to a numeric BAC level, this would require careful calibration and would be prone to error. For this project, I will use approximate value ranges to determine which of several messages should be posted to Twitter. An approximate reading will be displayed on an RGB LED.</p><h4>RGB LED</h4><p>The RGB LED is the primary status indicator. During normal operation, it shows the level of alcohol, represented by colors ranging from green to red.</p><p>Three transistors are used to provide power to the RGB LED. The microcontroller used on the Netduino has a relatively low current limit per IO pin (around 8 mA for most pins) so it is generally not advised to drive LEDs (which can require 20-30 mA) directly from these pins. Using a transistor (or another LED driver) helps ensure that enough power will be made available to each LED without damaging the Netduino.</p><p><a href="http://www.kpsec.freeuk.com/trancirc.htm">This page</a> shows some common transistor circuits, including a few &quot;transistor as a switch&quot; circuits. Since the RGB LED I am using has a common cathode (low side) lead, I am using PNP transistors to switch the anode (high side) of each color.</p><h4>Alcohol Gas Sensor</h4><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/sensorschematic%5B2%5D.png"><img title="sensorschematic" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/sensorschematic_thumb.png" alt="sensorschematic" width="385" height="278" border="0"></a></p><p>The MQ-3 essentially has two components: a heater and an alcohol gas sensor. The heater literally applies heat to the sensor in order to provide more accurate measurements and requires a constant 5V power source. The alcohol sensor acts as a variable resistor, where the resistance decreases as the level of alcohol increases.</p><p>While the heating element requires 5V, the alcohol sensor can actually operate at a different voltage. Applying 3.3V to the sensor (V<sub>C</sub> in the above diagram) will ensure that the output voltage (V<sub>RL</sub>) doesn’t exceed the Netduino’s input limits.</p><p>The sensor and R<sub>L</sub> act as a voltage divider. The <a href="http://www.pololu.com/file/0J310/MQ3.pdf">datasheet</a> for this sensor shows that the resistance across the sensor is between 2K-20K ohms, so an R<sub>L</sub> value of 10K ohms will provide a wide voltage output range.</p><h4>Other Components</h4><p>The MakerShield has two LEDs that I am using to display some additional status information. The red LED indicates whether the device is ready to post to Twitter, and the Green LED indicates that a post is in progress.</p><p>I am also using the button on the MakerShield to trigger the Netduino to post a message on Twitter. You could also write code to automatically post based on level peak detection, but for simplicity I decided to just use the button as a trigger.</p><h3>Code</h3><p>Pin configuration, Twitter API keys, the NTP server address, and other settings are stored in a Config class (Config.cs in the project root). If you download the source code for this project from CodePlex, make sure you copy the Config.sample.cs to Config.cs and take a look through the file to confirm all the settings:</p><p><pre class="brush: csharp">public static class Config
{
    // NTP Server
    public const string NTPServer = &quot;time-a.nist.gov&quot;;
    public const int TimeOffset = -7;    // MakerShield LEDs
    public const Cpu.Pin RedLEDPin = Pins.GPIO_PIN_A5;
    public const Cpu.Pin GreenLEDPin = Pins.GPIO_PIN_A4;    // RGB LED
    public const Cpu.Pin RGBRedPin = Pins.GPIO_PIN_D10;
    public const Cpu.Pin RGBGreenPin = Pins.GPIO_PIN_D6;
    public const Cpu.Pin RGBBluePin = Pins.GPIO_PIN_D9;
    public const bool RGBInverted = true;    // Button
    public const Cpu.Pin ButtonPin = Pins.GPIO_PIN_A3;    // Alcohol Gas Sensor
    public const Cpu.Pin SensorPin = Pins.GPIO_PIN_A0;
    // The Netduino's 10-bit ADC has a maximum value of 1023, but the sensor may not reach the highest possible voltage.
    // Input values &gt;= the SensorMaxValue will be treated as 100%.
    public const int SensorMaxValue = 900;    // Twitter
    public const string ConsumerKey = &quot;YourConsumerKey&quot;;
    public const string ConsumerSecret = &quot;YourConsumerSecret&quot;;
    public const string UserToken = &quot;YourUserToken&quot;;
    public const string UserTokenSecret = &quot;YourUserTokenSecret&quot;;
}</pre></p><p>In order to post messages on Twitter, it is necessary to register an application through Twitter’s developer portal. Instructions for this can be found on the <a href="http://microtweet.codeplex.com">MicroTweet CodePlex Page</a>.</p><h4>Startup</h4><p>When the Netduino first powers on it will wait for a few moments to let the alcohol gas sensor heat up and establish a baseline reading. The sensor’s datasheet recommends a preheat time of 24-48 hours, but the readings typically stabilize after a few minutes. During this time the RGB LED will slowly fade from blue to red to indicate that the sensor is heating up.</p><h4>RGB LED</h4><p>A simple RGB LED helper class is included to help make controlling the color and output of the LED easier. The class must be instantiated with three Cpu.Pin addresses, one for each color:</p><p><pre class="brush: csharp">protected static RGBLED rgbLed = new RGBLED(Config.RGBRedPin, Config.RGBGreenPin, Config.RGBBluePin, Config.RGBInverted);</pre></p><p>In the sample code, these pins are pulled from the Config class. The last parameter for the RGBLED constructor, invertOutput, is used to determine whether a logical high output value turns the LED on or off.</p><h4>NTP</h4><p>Next, the Netduino will attempt to update the system time from an NTP server. This is necessary for communication with Twitter’s OAuth API because all requests must contain an accurate timestamp. If the NTP server is unreachable, the Twitter functionality will be disabled, but it will still be possible to see the alcohol level on the RGB LED.</p><p>The code to communicate with an NTP server is included with the MicroTweet library. The UpdateTimeFromNTPServer method will contact the specified NTP server and update the Netduino’s time:</p><p><pre class="brush: csharp">NTP.UpdateTimeFromNTPServer(Config.NTPServer);</pre></p><p>If the time is updated successfully, a new instance of the TwitterClient class is created:</p><p><pre class="brush: csharp">twitterClient = new TwitterClient(Config.ConsumerKey, Config.ConsumerSecret, Config.UserToken, Config.UserTokenSecret);</pre></p><h4>Measurements</h4><p>Measurements from the alcohol sensor are repeatedly taken within the main program loop. The 10-bit ADC will return a value between 0 and 1023, but these values don’t necessarily correspond to the minimum/maximum readings from the alcohol sensor so some calculations are performed to convert the ADC value to a number between 0 and 100:</p><p><pre class="brush: csharp">protected static AnalogInput SensorInput = new AnalogInput(Config.SensorPin);// ...public static int GetSensorValue()
{
    int rawValue;
    lock (SensorInput)
    {
        rawValue = SensorInput.Read();
    }
    int adjustedValue = (rawValue - SensorMinValue) * 100;
    int result = adjustedValue / (Config.SensorMaxValue - SensorMinValue);
    return result;
}</pre></p><p>SensorMinValue is the baseline measurement established when the program was starting up. Config.SensorMaxValue is the configured &quot;maximum&quot; value that indicates the highest detectable alcohol level. Depending on your sensor, this maximum value may need to be adjusted.</p><p>It’s also worth noting that it can take about 30 seconds for the sensor to return to its baseline value after a measurement. This screenshot shows the sensor’s output before and after taking a reading:</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/scope%5B2%5D.png"><img title="scope" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/scope_thumb.png" alt="scope" width="320" height="234" border="0"></a></p><p>In this test, the baseline measurement (with no alcohol applied to the sensor) was about 1V. When alcohol was applied to the sensor the output quickly peaked at just under 3V, and then slowly decreased once the alcohol was removed.</p><h4>Posting to Twitter</h4><p>Sending a tweet from a TwitterClient instance is simple:</p><p><pre class="brush: csharp">twitterClient.SendTweet(&quot;Hello, world!&quot;);</pre></p><p>In this project, the MakerShield’s button is used to trigger the Netduino to post a message on Twitter. This button is monitored by an instance of the InterruptPort class, which fires a C# event when the input changes on the selected pin:</p><p><pre class="brush: csharp">protected static InterruptPort button = new InterruptPort(Config.ButtonPin, true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLevelLow);// ...static void button_OnInterrupt(uint data1, uint data2, DateTime time)
{
    if (twitterClient == null)
        return;
    greenLED.Write(true);    int sensorValue = GetSensorValue();    string message;
    if (sensorValue &lt; 20)
        message = &quot;No alcohol detected&quot;;
    else if (sensorValue &lt; 40)
        message = &quot;Tipsy&quot;;
    else if (sensorValue &lt; 60)
        message = &quot;Drunk&quot;;
    else if (sensorValue &lt; 80)
        message = &quot;Whoa! #WINNING&quot;;
    else
        message = &quot;x_x&quot;;    DateTime adjustedTime = DateTime.Now &#43; new TimeSpan(Config.TimeOffset, 0, 0);    message &#43;= &quot; at &quot; &#43; adjustedTime.ToString(&quot;h:mm:ss tt&quot;);    try
    {
        twitterClient.SendTweet(message);
    }
    catch (Exception e)
    {
        Debug.Print(e.ToString());
    }    greenLED.Write(false);
    button.ClearInterrupt();
}</pre></p><p>The button event handler code in this project is relatively simple: the current level from the alcohol sensor is read, a message is generated, and it attempts to post the message to Twitter. The current time is appended to the end of the message to avoid issues with multiple identical tweets.</p><p>&nbsp;</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/twitter%5B2%5D%5B3%5D.png"><img title="twitter[2]" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/twitter%5B2%5D_thumb%5B4%5D.png" alt="twitter[2]" width="318" height="357" border="0"></a></p><h3>Conclusion</h3><p>The code for this project is included in the Samples folder of the MicroTweet library. Be sure to check out the <a href="http://microtweet.codeplex.com">MicroTweet project page</a> on CodePlex for the source code and more information.</p><p>MicroTweet is released under the Apache 2.0 license, so it can be freely used in your own projects with attribution.</p><p><a href="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/Img0044%5B4%5D.jpg"><img title="Img0044" src="http://files.channel9.msdn.com/wlwimages/1932b237046e4743a4e79e6800c0220f/Img0044_thumb%5B1%5D.jpg" alt="Img0044" width="640" height="445" border="0"></a></p><h3>About the Author</h3><p>Matt Isenhower is a desktop and mobile application developer who primarily works with the .NET Framework. His company, <a href="http://komodex.com">Komodex Systems</a>, is currently focused on building new and exciting apps for Windows Phone 7 and other platforms. He also has a <a href="http://blog.ike.to">blog</a> and can be followed on Twitter at <a href="http://twitter.com/mattisenhower">@mattisenhower</a>.</p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/hardware/RSS&WT.dl=0&WT.entryid=Entry:RSSView:aa3691d065274ffe84a59ee7012ffc85">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/A-Tweeting-NET-Micro-Framework-breathalyzer</comments>
      <itunes:summary> This project shows how you can use the Netduino Plus to make a tweeting breathalyzer—a standalone breathalyzer that can post messages about the detected alcohol level to Twitter, using an inexpensive alcohol gas sensor.The Netduino is an open source electronics platform based on a 32-bit microcontroller running the .NET Micro Framework. The Netduino Plus is similar to the original Netduino, but adds a built-in Ethernet controller and MicroSD slot. Since the Netduino Plus can connect directly to a network, it can independently communicate with Twitter’s API without being connected to a computer.Hardware Overview&amp;nbsp;The MakerShield is a simple prototyping shield that is compatible with the standard Arduino and Netduino boards.In this configuration, the MQ-3 alcohol gas sensor will output an analog voltage between 0 and 3.3V to indicate the amount of alcohol detected. This output will be connected to one of the Netduino’s analog input pins and read by its ADC.While it would possible to convert the sensor’s output to a numeric BAC level, this would require careful calibration and would be prone to error. For this project, I will use approximate value ranges to determine which of several messages should be posted to Twitter. An approximate reading will be displayed on an RGB LED.RGB LEDThe RGB LED is the primary status indicator. During normal operation, it shows the level of alcohol, represented by colors ranging from green to red.Three transistors are used to provide power to the RGB LED. The microcontroller used on the Netduino has a relatively low current limit per IO pin (around 8 mA for most pins) so it is generally not advised to drive LEDs (which can require 20-30 mA) directly from these pins. Using a transistor (or another LED driver) helps ensure that enough power will be made available to each LED without damaging the Netduino.This page shows some common transistor circuits, including a few &amp;quot;transistor as a switch&amp;quot; circuits. Since the RGB LED I am</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/A-Tweeting-NET-Micro-Framework-breathalyzer</link>
      <pubDate>Wed, 18 May 2011 20:17:55 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/A-Tweeting-NET-Micro-Framework-breathalyzer</guid>
      <media:thumbnail url="http://files.channel9.msdn.com/thumbnail/5a0fa24f-c2b7-4983-8cfc-f7a83e82ac44.jpg" height="75" width="100"/>
      <media:thumbnail url="http://files.channel9.msdn.com/thumbnail/87d49a7c-d4b9-4789-93c5-e19821d1aba1.jpg" height="165" width="220"/>      
      <dc:creator>Matt Isenhower</dc:creator>
      <itunes:author>Matt Isenhower</itunes:author>
      <slash:comments>12</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/A-Tweeting-NET-Micro-Framework-breathalyzer/RSS</wfw:commentRss>
      <category>.NET Micro Framework</category>
      <category>Hardware</category>
      <category>Electronics</category>
    </item>
  <item>
      <title>New Book Explores How to Determine Your Hardware Requirements for SQL Server</title>
      <description><![CDATA[ <p>A new book, <strong><a href="http://www.amazon.com/SQL-Server-Hardware-Glenn-Berry/dp/1906434638/">SQL Server Hardware</a></strong>,&nbsp;tells you what you need to know about your hardware before you create your database.&nbsp;The book&nbsp;by <a href="http://mvp.support.microsoft.com/">Most Valued Professional </a>Glenn Berry of Newsgator describes how you can determine your hardware requirements for SQL Server.</p><p>Glenn shares his expertise gained at <a href="http://www.newsgator.com/">Newsgator </a>with ISV Architect Evangelist Bruce Kyle. Glenn's book, <a href="http://www.simple-talk.com/content/article.aspx?article=1199">SQL Server Hardware </a>from <a href="http://simple-talk.com/">Simple Talk Press</a>&nbsp;provides the fundamental knowledge and resources you need to make intelligent decisions about choice, and optimal installation and configuration, of SQL Server hardware, operating system and SQL Server.</p><p>Glenn provides a few tips from his book in this video.</p><p>You find out more about the book on Amazon. See <a href="http://www.amazon.com/SQL-Server-Hardware-Glenn-Berry/dp/1906434638/">SQL Server Hardware</a>.</p><h3>Chapter Outline</h3><ol><li>Processors and Associated Hardware </li><li>The Storage Subsystem </li><li>Benchmarking Tools </li><li>Hardware Discovery </li><li>Operating System Selection and Configuration </li><li>SQL Server Version and Edition Selection </li><li>SQL Server Installation and Configuration </li></ol><h3>Glenn's Blog</h3><p><a href="http://sqlserverperformance.wordpress.com/">Glenn Berry's SQL Server Performance</a>&nbsp;is one of the best resources for SQL Server tips and tricks. He blogs daily exploring both the hardware and software sides of SQL.</p><p>Follow Glenn on Twitter at <a href="http://twitter.com/GlennAlanBerry">@GlennAlanBerry</a>.</p><p>See his interview with John O'Donnell at <a href="http://channel9.msdn.com/Blogs/jodonnell/Talking-with-NewsGator-at-PDC-2009">Talking with NewsGator at PDC 2009</a>.</p><h3>About Most Valued Professionals (MVP)</h3><p>Microsoft recognizes the best and brightest from technology communities around the world with the <br>Microsoft Most Valuable Professional (MVP) Award. These exceptional community leaders come from a wide range of backgrounds. They are teachers, artists, doctors, engineers, as well as technologists, who actively share their high-quality, real-world technical expertise with the community and with Microsoft.</p><h3>About NewsGator</h3><p>NewsGator was founded in 2004 to realize the potential of RSS (Really Simple Syndication) to transform the way people consume information. Today NewsGator's flagship product - Social Sites – is social computing software that’s built directly into Microsoft SharePoint.</p><h3>Other ISV Videos</h3><p>For other videos about independent software vendors (ISVs):</p><ul><li><a href="http://channel9.msdn.com/Blogs/bruceky/Quark-Extends-SharePoint-for-Dynamic-Publishing">Quark Extends SharePoint for Dynamic Publishing</a></li><li><a href="http://channel9.msdn.com/Blogs/bruceky/ProModel-Adds-Simulation-Visualization-to-Microsoft-Project">ProModel Adds Simulation, Visualization to Microsoft Project</a></li><li><a href="http://channel9.msdn.com/Blogs/bruceky/Thumb-Driven-Workflow-on-Windows-7-Slates-from-Blue-Dot-Solutions">Thumb-Driven Workflow on Windows 7 Slates from Blue Dot Solutions</a></li><li><a href="http://channel9.msdn.com/Blogs/bruceky/Accumulus-Makes-Subscription-Billing-Easy-for-Windows-Azure">Accumulus Makes Subscription Billing Easy for Windows Azure</a></li><li><a href="https://channel9.msdn.com/Blogs/bruceky/Azure-Email-Enables-Lists-Low-Cost-Storage-for-SharePoint">Azure Email-Enables Lists, Low-Cost Storage for SharePoint</a></li><li><a href="http://channel9.msdn.com/Blogs/bruceky/Crowd-Sourcing-Public-Sector-App-for-Windows-Phone-Azure">Crowd-Sourcing Public Sector App for Windows Phone, Azure</a></li><li><a href="http://channel9.msdn.com/Blogs/bruceky/Food-Buster-Game-Achieves-Scalability-with-Windows-Azure">Food Buster Game Achieves Scalability with Windows Azure</a></li></ul><h3>Up to Date News for ISVs and Software Developers</h3><p>See <a href="http://blogs.msdn.com/usivde">US ISV Community blog</a>.</p><p>&nbsp;</p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/hardware/RSS&WT.dl=0&WT.entryid=Entry:RSSView:de365c9f225b438ca2179ecc003adecc">]]></description>
      <comments>http://channel9.msdn.com/Blogs/bruceky/New-Book-Explores-How-to-Determine-Your-Hardware-Requirements-for-SQL-Server</comments>
      <itunes:summary> A new book, SQL Server Hardware,&amp;nbsp;tells you what you need to know about your hardware before you create your database.&amp;nbsp;The book&amp;nbsp;by Most Valued Professional Glenn Berry of Newsgator describes how you can determine your hardware requirements for SQL Server.Glenn shares his expertise gained at Newsgator with ISV Architect Evangelist Bruce Kyle. Glenn&#39;s book, SQL Server Hardware from Simple Talk Press&amp;nbsp;provides the fundamental knowledge and resources you need to make intelligent decisions about choice, and optimal installation and configuration, of SQL Server hardware, operating system and SQL Server.Glenn provides a few tips from his book in this video.You find out more about the book on Amazon. See SQL Server Hardware.Chapter OutlineProcessors and Associated Hardware The Storage Subsystem Benchmarking Tools Hardware Discovery Operating System Selection and Configuration SQL Server Version and Edition Selection SQL Server Installation and Configuration Glenn&#39;s BlogGlenn Berry&#39;s SQL Server Performance&amp;nbsp;is one of the best resources for SQL Server tips and tricks. He blogs daily exploring both the hardware and software sides of SQL.Follow Glenn on Twitter at @GlennAlanBerry.See his interview with John O&#39;Donnell at Talking with NewsGator at PDC 2009.About Most Valued Professionals (MVP)Microsoft recognizes the best and brightest from technology communities around the world with the Microsoft Most Valuable Professional (MVP) Award. These exceptional community leaders come from a wide range of backgrounds. They are teachers, artists, doctors, engineers, as well as technologists, who actively share their high-quality, real-world technical expertise with the community and with Microsoft.About NewsGatorNewsGator was founded in 2004 to realize the potential of RSS (Really Simple Syndication) to transform the way people consume information. Today NewsGator&#39;s flagship product - Social Sites – is social computing software that’s built directly into Microsoft </itunes:summary>
      <itunes:duration>276</itunes:duration>
      <link>http://channel9.msdn.com/Blogs/bruceky/New-Book-Explores-How-to-Determine-Your-Hardware-Requirements-for-SQL-Server</link>
      <pubDate>Mon, 16 May 2011 20:07:36 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Blogs/bruceky/New-Book-Explores-How-to-Determine-Your-Hardware-Requirements-for-SQL-Server</guid>
      <media:thumbnail url="http://media.ch9.ms/ch9/decc/de365c9f-225b-438c-a217-9ecc003adecc/sqlserverperformance_100_ch9.jpg" height="75" width="100"/>
      <media:thumbnail url="http://media.ch9.ms/ch9/decc/de365c9f-225b-438c-a217-9ecc003adecc/sqlserverperformance_220_ch9.jpg" height="165" width="220"/>
      <media:thumbnail url="http://media.ch9.ms/ch9/decc/de365c9f-225b-438c-a217-9ecc003adecc/sqlserverperformance_512_ch9.jpg" height="384" width="512"/>
      <media:group>
        <media:content url="http://media.ch9.ms/ch9/decc/de365c9f-225b-438c-a217-9ecc003adecc/sqlserverperformance_2MB_ch9.wmv" expression="full" duration="276" fileSize="572731925" type="video/x-ms-wmv" medium="video"/>
        <media:content url="http://media.ch9.ms/ch9/decc/de365c9f-225b-438c-a217-9ecc003adecc/sqlserverperformance_ch9.mp3" expression="full" duration="276" fileSize="2217264" type="audio/mp3" medium="audio"/>
        <media:content url="http://media.ch9.ms/ch9/decc/de365c9f-225b-438c-a217-9ecc003adecc/sqlserverperformance_ch9.wma" expression="full" duration="276" fileSize="2245963" type="audio/x-ms-wma" medium="audio"/>
        <media:content url="http://media.ch9.ms/ch9/decc/de365c9f-225b-438c-a217-9ecc003adecc/sqlserverperformance_ch9.wmv" expression="full" duration="276" fileSize="59431089" type="video/x-ms-wmv" medium="video"/>
        <media:content url="http://media.ch9.ms/ch9/decc/de365c9f-225b-438c-a217-9ecc003adecc/sqlserverperformance_high_ch9.mp4" expression="full" duration="276" fileSize="116793553" type="video/mp4" medium="video"/>
        <media:content url="http://media.ch9.ms/ch9/decc/de365c9f-225b-438c-a217-9ecc003adecc/sqlserverperformance_low_ch9.mp4" expression="full" duration="276" fileSize="25427038" type="video/mp4" medium="video"/>
        <media:content url="http://smooth.ch9.ms/ch9/decc/de365c9f-225b-438c-a217-9ecc003adecc/sqlserverperformance.ism/manifest" expression="full" duration="276" fileSize="10174" type="video/x-ms-wmv" medium="video"/>
      </media:group>      
      <enclosure url="http://media.ch9.ms/ch9/decc/de365c9f-225b-438c-a217-9ecc003adecc/sqlserverperformance_ch9.wmv" length="59431089" type="video/x-ms-wmv"/>
      <dc:creator>Bruce D Kyle</dc:creator>
      <itunes:author>Bruce D Kyle</itunes:author>
      <slash:comments>1</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Blogs/bruceky/New-Book-Explores-How-to-Determine-Your-Hardware-Requirements-for-SQL-Server/RSS</wfw:commentRss>
      <category>Computer Hardware</category>
      <category>Data</category>
      <category>Data Services</category>
      <category>Hardware</category>
      <category>ISV</category>
      <category>SQL</category>
      <category>SQL Server</category>
      <category>Storage</category>
      <category>USISV</category>
    </item>
  <item>
      <title>MJPEG Decoder</title>
      <description><![CDATA[ <p>Last year the Coding4Fun/Channel 9 guys asked me to work on a few things for <a href="http://live.visitmix.com/" target="_blank">MIX10</a>.&nbsp; One of these items was a way to output a webcam stream to Windows Phone 7 for use with Clint's <a href="http://blogs.msdn.com/b/coding4fun/archive/2010/03/16/9979874.aspx" target="_blank">t-shirt cannon project</a> you may have read about.&nbsp; I figured the easiest way to accomplish this was by using a network/IP camera capable of sending a Motion-JPEG stream, which can be easily decoded and displayed that can display a JPEG image.&nbsp; Thus, this library was born.</p><p>It has gone through quite a few changes and I have expanded it to easily display MJPEG streams on a variety of platforms.&nbsp; The developer just references the assembly appropriate to their platform, adds a few lines of code, and away it goes.</p><h2>Usage</h2><p>For those that are just interested in the usage, it's as simple as this:</p><ol><li>Reference one of the following assemblies appropriate for your project: <ul><li><strong>MjpegProcessorSL.dll</strong> - Silverlight (<strong>Out of Browser Only!</strong>) </li><li><strong>MjpegProcessorWP7.dll</strong> - Windows Phone 7 (XNA or Silverlight, performance maxes out around 320x240 @ 15fps, so set your camera settings accordingly) </li><li><strong>MjpegProcessorXna4.dll</strong> - XNA 4.0 (Windows) </li><li><strong>MjpegProcessor.dll</strong> - WinForms and WPF </li></ul></li><li>Create a new <strong>MjpegDecoder</strong> object. </li><li>Hook up the <strong>FrameReady</strong> event. </li><li>In the event handler, take the <strong>Bitmap</strong>/<strong>BitmapImage</strong> and assign it to your image display control: </li><li>In the case of XNA, use the <strong>GetMjpegFrame</strong> method in the Update method, which will return a Texture2D you can use in your Draw method. </li><li>Call the <strong>ParseStream</strong> method with the Uri of the MJPEG &quot;endpoint&quot;. </li></ol><p>That's it!&nbsp; The source code and binaries above both include projects demonstrating how to use the library on each of these platforms.&nbsp; As long as you set the appropriate reference, you can just copy and paste the code in the sample to get your project running (changing the Uri, of course).</p><pre class="brush: csharp;">public partial class MainWindow : Window
{
    MjpegDecoder _mjpeg;

    public MainWindow()
    {
        InitializeComponent();
        _mjpeg = new MjpegDecoder();
        _mjpeg.FrameReady &#43;= mjpeg_FrameReady;
    }

    private void Start_Click(object sender, RoutedEventArgs e)
    {
        _mjpeg.ParseStream(new Uri(&quot;http://192.168.2.200/img/video.mjpeg&quot;));
    }

    private void mjpeg_FrameReady(object sender, FrameReadyEventArgs e)
    {
        image.Source = e.BitmapImage;
    }
}</pre><p>If that doesn't fit your needs, you can also access the <strong>Bitmap/BitmapImage</strong> properties directly from the <strong>MjpegDecoder</strong> object, or the <strong>CurrentFrame</strong> property, which will contain the raw JPEG data prior to being decoded.</p><h2>A Word About Network/IP Cameras</h2><p>I have tested this against several different cameras.&nbsp; Each device has its own quirks, but all of them seem to work with this library with one exception:&nbsp; several cameras will respond differently when an Internet Explorer user agent header is sent with the HTTP request.&nbsp; Instead of sending down an MJPEG stream, it will send a single JPEG image as Internet Explorer does not properly support MJPEG streams.&nbsp; Unfortunately, this causes the Silverlight processor to not work properly as the header cannot be changed from the Internet Explorer default.&nbsp; When this happens, only a single frame will be sent, and the decoding will fail.&nbsp; The only fix I have found is to use a different camera that doesn't work in this way.</p><h2>What is MJPEG?</h2><p>Pretty simply, it's a video format where each frame of video is sent as a separate, compressed JPEG image.&nbsp; A standard HTTP request is made to a specific URL, and a multipart response is sent.&nbsp; Parsing this multipart stream into separate images as they are sent results in a series of JPEG images.&nbsp; The viewer displays those JPEG images as quickly as they are sent and that creates the video.&nbsp; It's not a well documented format, nor is it perfectly standardized, but it does work.&nbsp; For more information, see the <a href="http://en.wikipedia.org/wiki/Motion_JPEG" target="_blank">MJPEG article on Wikipedia</a>.</p><h2>How Do I Find the MJPEG URL of My Camera?</h2><p>Excellent question.&nbsp; Not an excellent answer.&nbsp; The user manual may mention the URL.&nbsp; A quick internet search with the model number should get you a result.&nbsp; Or, you can also try this company's <a href="http://skjm.com/icam/mjpeg.php" target="_blank">lookup tool</a>.</p><h2>How Does It Work?</h2><p>Glad you asked.&nbsp; If you take a look at the project, you'll notice there isn't much code.&nbsp; One single file is used with a variety of compiler directives to compile certain portions based on the platform assembly being generated.&nbsp; The <strong>MjpegDecoder.cs/.vb </strong>contains the entire implementation.</p><p>First, an asynchronous request is made to the provided MJPEG URL inside the <strong>ParseStream</strong> method.&nbsp; If we are in a Silverlight environment, the <strong>AllowReadStreamBuffering</strong> property must be set to <strong>false</strong> so the response returns immediately instead of being buffered.&nbsp; Additionally, we need to register the <strong>http://</strong> prefix to use the client http stack vs. the browser stack.&nbsp; Finally, the request is made using the <strong>BeginGetResponse</strong> method, specifying the <strong>OnGetResponse</strong> method as the callback.&nbsp; This will be called as soon as data is sent from the camera in response to our request.</p><pre class="brush: csharp;">public void ParseStream(Uri uri)
{
#if SILVERLIGHT
    HttpWebRequest.RegisterPrefix(&quot;http://&quot;, WebRequestCreator.ClientHttp);
#endif
    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);

#if SILVERLIGHT
    // start the stream immediately
    request.AllowReadStreamBuffering = false;
#endif
    // asynchronously get a response
    request.BeginGetResponse(OnGetResponse, request);
}</pre><p><strong>OnGetResponse</strong> grabs the response headers and uses the Content-Type header to determine the boundary marker that will be sent between JPEG frames.</p><pre class="brush: csharp;">private void OnGetResponse(IAsyncResult asyncResult)
{
    HttpWebResponse resp;
    byte[] buff;
    byte[] imageBuffer = new byte[1024 * 1024];
    Stream s;

    // get the response
    HttpWebRequest req = (HttpWebRequest)asyncResult.AsyncState;
    resp = (HttpWebResponse)req.EndGetResponse(asyncResult);

    // find our magic boundary value
    string contentType = resp.Headers[&quot;Content-Type&quot;];
    if(!string.IsNullOrEmpty(contentType) &amp;&amp; !contentType.Contains(&quot;=&quot;))
        throw new Exception(&quot;Invalid content-type header.  The camera is likely not returning a proper MJPEG stream.&quot;);
    string boundary = resp.Headers[&quot;Content-Type&quot;].Split('=')[1];
    byte[] boundaryBytes = Encoding.UTF8.GetBytes(boundary.StartsWith(&quot;--&quot;) ? boundary : &quot;--&quot; &#43; boundary);
...</pre><p>&nbsp;</p><p>It then streams the response data, looks for a JPEG header marker, then reads until it finds the boundary marker, copies the data into a buffer, decodes it, passes it on to whoever wants it via an event, and then starts over.</p><pre class="brush: csharp;">...
    s = resp.GetResponseStream();
    BinaryReader br = new BinaryReader(s);

    _streamActive = true;

    buff = br.ReadBytes(ChunkSize);

    while (_streamActive)
    {
        int size;

        // find the JPEG header
        int imageStart = buff.Find(JpegHeader);

        if(imageStart != -1)
        {
            // copy the start of the JPEG image to the imageBuffer
            size = buff.Length - imageStart;
            Array.Copy(buff, imageStart, imageBuffer, 0, size);

            while(true)
            {
                buff = br.ReadBytes(ChunkSize);

                // find the boundary text
                int imageEnd = buff.Find(boundaryBytes);
                if(imageEnd != -1)
                {
                    // copy the remainder of the JPEG to the imageBuffer
                    Array.Copy(buff, 0, imageBuffer, size, imageEnd);
                    size &#43;= imageEnd;

                    // create a single JPEG frame
                    CurrentFrame = new byte[size];
                    Array.Copy(imageBuffer, 0, CurrentFrame, 0, size);
#if !XNA
                    ProcessFrame(CurrentFrame);
#endif
                    // copy the leftover data to the start
                    Array.Copy(buff, imageEnd, buff, 0, buff.Length - imageEnd);

                    // fill the remainder of the buffer with new data and start over
                    byte[] temp = br.ReadBytes(imageEnd);

                    Array.Copy(temp, 0, buff, buff.Length - imageEnd, temp.Length);
                    break;
                }

                // copy all of the data to the imageBuffer
                Array.Copy(buff, 0, imageBuffer, size, buff.Length);
                size &#43;= buff.Length;
            }
        }
    }
    resp.Close();
}</pre><p>The <strong>ProcessFrame </strong>method seen above takes the raw byte buffer, which contains an undecoded JPEG image, and decodes it based on the environment.&nbsp; However this isn't called in the case of XNA which we'll see in a moment:</p><pre class="brush: csharp;">private void ProcessFrame(byte[] frameBuffer)
{
#if SILVERLIGHT
    // need to get this back on the UI thread
    Deployment.Current.Dispatcher.BeginInvoke((Action)(() =&gt;
    {
        // resets the BitmapImage to the new frame
        BitmapImage.SetSource(new MemoryStream(frameBuffer, 0, frameBuffer.Length));

        // tell whoever's listening that we have a frame to draw
        if(FrameReady != null)
            FrameReady(this, new FrameReadyEventArgs { FrameBuffer = CurrentFrame, BitmapImage = BitmapImage });
    }));
#endif

#if !SILVERLIGHT &amp;&amp; !XNA
    // I assume if there's an Application.Current then we're in WPF, not WinForms
    if(Application.Current != null)
    {
        // get it on the UI thread
        Application.Current.Dispatcher.BeginInvoke((Action)(() =&gt;
        {
            // create a new BitmapImage from the JPEG bytes
            BitmapImage = new BitmapImage();
            BitmapImage.BeginInit();
            BitmapImage.StreamSource = new MemoryStream(frameBuffer);
            BitmapImage.EndInit();

            // tell whoever's listening that we have a frame to draw
            if(FrameReady != null)
                FrameReady(this, new FrameReadyEventArgs { FrameBuffer = CurrentFrame, Bitmap = Bitmap, BitmapImage = BitmapImage });
        }));
    }
    else
    {
        // create a simple GDI&#43; happy Bitmap
        Bitmap = new Bitmap(new MemoryStream(frameBuffer));

        // tell whoever's listening that we have a frame to draw
        if(FrameReady != null)
            FrameReady(this, new FrameReadyEventArgs { FrameBuffer = CurrentFrame, Bitmap = Bitmap, BitmapImage = BitmapImage });
    }
#endif
}</pre><div>&nbsp;</div><p>In the case of Silverlight, the <strong>BitmapImage</strong> object has a <strong>SetSource</strong> method which takes a stream to be decoded and turned into the image.&nbsp; In WPF, <strong>BitmapImage</strong> works differently.&nbsp; In this case, <strong>BeginInit</strong> is called, then the <strong>StreamSource</strong> property is set to the stream of bytes, and finally <strong>EndInit</strong> is called.&nbsp; In WinForms, the library will return a <strong>Bitmap</strong> object which can be initialized with the stream right in the constructor.</p><p>In the code above, I look at the <strong>Application.Current</strong> property to determine if the library is being used by a WPF project.&nbsp; If that property is not null, it is assumed the library is being called from a WPF project.</p><p>When compiled as an XNA library, we have no use for a <strong>BitmapImage</strong> or a <strong>Bitmap</strong>â€¦we need a <strong>Texture2D</strong> object.&nbsp; The <strong>GetMjpegFrame</strong> method seen below is what is called by an XNA application during the Update method to pull the current frame:</p><pre class="brush: csharp;">public Texture2D GetMjpegFrame(GraphicsDevice graphicsDevice)
{
    // create a Texture2D from the current byte buffer
    if(CurrentFrame != null)
        return Texture2D.FromStream(graphicsDevice, new MemoryStream(CurrentFrame, 0, CurrentFrame.Length));
    return null;
}</pre><h2>Conclusion</h2><p>And that's about it for the library.&nbsp; Give it a try and please contact me with feedback or if you run into any issues.&nbsp; Enjoy!</p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/hardware/RSS&WT.dl=0&WT.entryid=Entry:RSSView:c0c99db087794de090759e86005409c8">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/MJPEG-Decoder</comments>
      <itunes:summary> Last year the Coding4Fun/Channel 9 guys asked me to work on a few things for MIX10.&amp;nbsp; One of these items was a way to output a webcam stream to Windows Phone 7 for use with Clint&#39;s t-shirt cannon project you may have read about.&amp;nbsp; I figured the easiest way to accomplish this was by using a network/IP camera capable of sending a Motion-JPEG stream, which can be easily decoded and displayed that can display a JPEG image.&amp;nbsp; Thus, this library was born.It has gone through quite a few changes and I have expanded it to easily display MJPEG streams on a variety of platforms.&amp;nbsp; The developer just references the assembly appropriate to their platform, adds a few lines of code, and away it goes.UsageFor those that are just interested in the usage, it&#39;s as simple as this:Reference one of the following assemblies appropriate for your project: MjpegProcessorSL.dll - Silverlight (Out of Browser Only!) MjpegProcessorWP7.dll - Windows Phone 7 (XNA or Silverlight, performance maxes out around 320x240 @ 15fps, so set your camera settings accordingly) MjpegProcessorXna4.dll - XNA 4.0 (Windows) MjpegProcessor.dll - WinForms and WPF Create a new MjpegDecoder object. Hook up the FrameReady event. In the event handler, take the Bitmap/BitmapImage and assign it to your image display control: In the case of XNA, use the GetMjpegFrame method in the Update method, which will return a Texture2D you can use in your Draw method. Call the ParseStream method with the Uri of the MJPEG &amp;quot;endpoint&amp;quot;. That&#39;s it!&amp;nbsp; The source code and binaries above both include projects demonstrating how to use the library on each of these platforms.&amp;nbsp; As long as you set the appropriate reference, you can just copy and paste the code in the sample to get your project running (changing the Uri, of course).public partial class MainWindow : Window
{
    MjpegDecoder _mjpeg;

    public MainWindow()
    {
        InitializeComponent();
        _mjpeg = new MjpegDecoder();
        _mjpeg.Fr</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/MJPEG-Decoder</link>
      <pubDate>Thu, 10 Feb 2011 05:15:49 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/MJPEG-Decoder</guid>
      <media:thumbnail url="http://files.channel9.msdn.com/thumbnail/2460fbee-0ebb-417a-b39e-bfd61639bde7.jpg" height="75" width="100"/>
      <media:thumbnail url="http://files.channel9.msdn.com/thumbnail/4dc598a2-fd65-4ce9-ad22-ef149e4ab524.jpg" height="165" width="220"/>      
      <dc:creator>Brian Peek</dc:creator>
      <itunes:author>Brian Peek</itunes:author>
      <slash:comments>28</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/MJPEG-Decoder/RSS</wfw:commentRss>
      <category>.NET</category>
      <category>.NET Framework</category>
      <category>Hardware</category>
      <category>Silverlight 4</category>
      <category>Windows Forms</category>
      <category>WPF</category>
      <category>XNA</category>
    </item>
  <item>
      <title>Windows 7 and SSDs</title>
      <description><![CDATA[ <p>Solid State Drives (SSD) are great, but going into that upgrade blind can leave you with less than impressive benchmarks. There are a few things you need to know before adding a SSD to your Windows 7 PC. Ed Bott has an article worth reading called <a href="http://www.zdnet.com/blog/bott/windows-7-and-ssds-setup-secrets-and-tune-up-tweaks/2910?utm_source=feedburner&amp;utm_medium=feed&amp;utm_campaign=Feed%3A&#43;zdnet%2FBott&#43;%28ZDNet&#43;Ed&#43;Bott%27s&#43;Microsoft&#43;Report%29&amp;utm_content=Google&#43;Reader">Windows 7 and SSDs: Setup secrets and tune-up tweaks</a>.&nbsp;One of the&nbsp;most important things to know abotu is what TRIM is and how to make sure you're using it. As Ed shows you, it can mean the difference between 10.77 MB/s random reads and 130.25 MB/s, a difference worth knowing about. </p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/hardware/RSS&WT.dl=0&WT.entryid=Entry:RSSView:ca2ab600cb2348a493ab9e790120271d">]]></description>
      <comments>http://channel9.msdn.com/Blogs/coolstuff/Windows-7-and-SSDs</comments>
      <itunes:summary> Solid State Drives (SSD) are great, but going into that upgrade blind can leave you with less than impressive benchmarks. There are a few things you need to know before adding a SSD to your Windows 7 PC. Ed Bott has an article worth reading called Windows 7 and SSDs: Setup secrets and tune-up tweaks.&amp;nbsp;One of the&amp;nbsp;most important things to know abotu is what TRIM is and how to make sure you&#39;re using it. As Ed shows you, it can mean the difference between 10.77 MB/s random reads and 130.25 MB/s, a difference worth knowing about. </itunes:summary>
      <link>http://channel9.msdn.com/Blogs/coolstuff/Windows-7-and-SSDs</link>
      <pubDate>Fri, 28 Jan 2011 17:35:21 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Blogs/coolstuff/Windows-7-and-SSDs</guid>
      <media:thumbnail url="http://files.channel9.msdn.com/thumbnail/0139b6d9-693c-4676-8688-8f2ec5e7e362.png" height="75" width="100"/>
      <media:thumbnail url="http://files.channel9.msdn.com/thumbnail/e24aad43-c820-4bf3-8a98-b35ba6475a0b.png" height="165" width="220"/>      
      <dc:creator>Larry Larsen</dc:creator>
      <itunes:author>Larry Larsen</itunes:author>
      <slash:comments>8</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Blogs/coolstuff/Windows-7-and-SSDs/RSS</wfw:commentRss>
      <category>Hardware</category>
      <category>Windows 7</category>
      <category>SSD</category>
    </item>
  <item>
      <title>PC Showcase with Ben the PC Guy </title>
      <description><![CDATA[ <p>Ben the PC Guy walked us through some of the coolest PC's in the Microsoft booth. There are so many to choose from with such different features, from high end laptops built for gaming or video editing to the incredible cut lines&nbsp;of the Samsung 9 Series to the futuristic dual-screened Acer ICONIA.&nbsp;There is something for everyone. </p><p>Follow Ben <a href="http://twitter.com/benthepcguy">on Twitter</a> or see more on the <a href="http://windowsteamblog.com/">Windows Team Blog</a>. </p><p><strong>00:25 - <a href="http://www.acer.com/iconia/">Acer ICONIA</a></strong> - Dual screen multitouch laptop. We looked at one in the back of the booth because there was a constant crowd around the one out front. Place 5 fingers on the bottom screen to bring up a wheel launcer or 10 fingers to bring up the keyboard. <br><strong>02:00 - <a href="http://www.bing.com/shopping/toshiba-satellite-a665-3dv-core-i7-740qm-1-73-ghz-15-6-tft/reviews/21601FBD1FD34E150001?q=Toshiba&#43;satillite&#43;A665-3Dv&amp;FORM=GR">Toshiba Satellite A665-3D</a></strong> - A fast i7-based gaming laptop with 3D glasses with a retail price of around $1300. <br><strong>02:33 - <a href="http://www.sonystyle.com/webapp/wcs/stores/servlet/CategoryDisplay?storeId=10151&amp;catalogId=10551&amp;langId=-1&amp;categoryId=8198552921644608896">Sony Vaio P</a></strong> - 8&quot; screen that fits in a back pocket. It has available turn-by-turn GPS navigation and Verizon Broadband built in. <br><strong>03:18 - <a href="http://www.hp.com/united-states/campaigns/holiday-beats/envy17.html">HP Envy 14</a></strong><a href="http://www.hp.com/united-states/campaigns/holiday-beats/envy17.html">&nbsp;</a>- The brains inside the much-feared and&nbsp;arguably dangerous <a href="http://blog.makezine.com/archive/2010/03/windows_phone-powered_t-shirt_canno.html">Coding4Fun T-Shirt cannon</a>, the 17&quot; version is my main PC, used to edit many of my Channel 9 videos. Why? Because it's a huge screened beauty with Beats Audio that gets a 7.1 <a href="http://www.weishare.net/">WEI score</a>. <br><strong>04:05 - <a href="http://www.samsung.com/us/news/newsRead.do?news_seq=19774&amp;page=1&amp;gltype=globalnews">Samsung Note PC 9 Series 900X</a></strong> - You've never seen a PC like this before. It's one of the lightest, thinnest 13&quot; laptops in the world. The body is Duralumin aircraft metal which feels both solid as a rock and light as a feather. Backlit keyboard, i5 processor. The screen is twice as bright as what you're probably used to, and for speed - world record holder at 12 seconds boot time.&nbsp;When you retire this machine you could use it to split wood.&nbsp;<br><strong>05:00 - <a href="http://ces2011.asus.com/photos/eee/asus-eee-slate-ep121/">ASUS Eee Slate EP121</a>&nbsp;</strong>- A&nbsp;slate PC that works as a multitouch device, as a&nbsp;Tablet PC, or with a&nbsp;BlueTooth keyboard. Forward facing camera for video chat and a home button that drives <a href="http://windows.microsoft.com/en-US/windows7/Using-Aero-Flip-3D">AeroFlip3d</a>. <br><strong>06:33 - <a href="http://www.dell.com/content/topics/topic.aspx/global/products/landing/en/inspiron?c=us&amp;l=en">Dell Inspiron duo&nbsp;</a></strong>- Very cool little&nbsp;convertible tablet that works as a laptop and&nbsp;with a push the screen flips around and it works as a touch tablet.&nbsp;It has an optional Audio Station, 2GB of RAM and will play HD movies. </p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/hardware/RSS&WT.dl=0&WT.entryid=Entry:RSSView:0effa94a922f4e7f954b9e650090de97">]]></description>
      <comments>http://channel9.msdn.com/posts/PC-Showcase-with-Ben-the-PC-Guy</comments>
      <itunes:summary> Ben the PC Guy walked us through some of the coolest PC&#39;s in the Microsoft booth. There are so many to choose from with such different features, from high end laptops built for gaming or video editing to the incredible cut lines&amp;nbsp;of the Samsung 9 Series to the futuristic dual-screened Acer ICONIA.&amp;nbsp;There is something for everyone. Follow Ben on Twitter or see more on the Windows Team Blog. 00:25 - Acer ICONIA - Dual screen multitouch laptop. We looked at one in the back of the booth because there was a constant crowd around the one out front. Place 5 fingers on the bottom screen to bring up a wheel launcer or 10 fingers to bring up the keyboard. 02:00 - Toshiba Satellite A665-3D - A fast i7-based gaming laptop with 3D glasses with a retail price of around $1300. 02:33 - Sony Vaio P - 8&amp;quot; screen that fits in a back pocket. It has available turn-by-turn GPS navigation and Verizon Broadband built in. 03:18 - HP Envy 14&amp;nbsp;- The brains inside the much-feared and&amp;nbsp;arguably dangerous Coding4Fun T-Shirt cannon, the 17&amp;quot; version is my main PC, used to edit many of my Channel 9 videos. Why? Because it&#39;s a huge screened beauty with Beats Audio that gets a 7.1 WEI score. 04:05 - Samsung Note PC 9 Series 900X - You&#39;ve never seen a PC like this before. It&#39;s one of the lightest, thinnest 13&amp;quot; laptops in the world. The body is Duralumin aircraft metal which feels both solid as a rock and light as a feather. Backlit keyboard, i5 processor. The screen is twice as bright as what you&#39;re probably used to, and for speed - world record holder at 12 seconds boot time.&amp;nbsp;When you retire this machine you could use it to split wood.&amp;nbsp;05:00 - ASUS Eee Slate EP121&amp;nbsp;- A&amp;nbsp;slate PC that works as a multitouch device, as a&amp;nbsp;Tablet PC, or with a&amp;nbsp;BlueTooth keyboard. Forward facing camera for video chat and a home button that drives AeroFlip3d. 06:33 - Dell Inspiron duo&amp;nbsp;- Very cool little&amp;nbsp;convertible tablet that works as a laptop and&amp;nbsp;wi</itunes:summary>
      <itunes:duration>480</itunes:duration>
      <link>http://channel9.msdn.com/posts/PC-Showcase-with-Ben-the-PC-Guy</link>
      <pubDate>Sat, 08 Jan 2011 10:35:23 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/posts/PC-Showcase-with-Ben-the-PC-Guy</guid>
      <media:thumbnail url="http://media.ch9.ms/ch9/DE97/0EFFA94A-922F-4E7F-954B-9E650090DE97/BenthePCGuy_100_ch9.jpg" height="75" width="100"/>
      <media:thumbnail url="http://media.ch9.ms/ch9/DE97/0EFFA94A-922F-4E7F-954B-9E650090DE97/BenthePCGuy_220_ch9.jpg" height="165" width="220"/>
      <media:thumbnail url="http://media.ch9.ms/ch9/DE97/0EFFA94A-922F-4E7F-954B-9E650090DE97/BenthePCGuy_512_ch9.jpg" height="384" width="512"/>
      <media:thumbnail url="http://media.ch9.ms/ch9/DE97/0EFFA94A-922F-4E7F-954B-9E650090DE97/BenthePCGuy_custom_ch9.jpg" height="384" width="512"/>
      <media:group>
        <media:content url="http://media.ch9.ms/ch9/DE97/0EFFA94A-922F-4E7F-954B-9E650090DE97/BenthePCGuy_2MB_ch9.wmv" expression="full" duration="480" fileSize="257376519" type="video/x-ms-wmv" medium="video"/>
        <media:content url="http://media.ch9.ms/ch9/DE97/0EFFA94A-922F-4E7F-954B-9E650090DE97/BenthePCGuy_ch9.mp3" expression="full" duration="480" fileSize="3846590" type="audio/mp3" medium="audio"/>
        <media:content url="http://media.ch9.ms/ch9/DE97/0EFFA94A-922F-4E7F-954B-9E650090DE97/BenthePCGuy_ch9.wma" expression="full" duration="480" fileSize="3892155" type="audio/x-ms-wma" medium="audio"/>
        <media:content url="http://media.ch9.ms/ch9/DE97/0EFFA94A-922F-4E7F-954B-9E650090DE97/BenthePCGuy_ch9.wmv" expression="full" duration="480" fileSize="104584313" type="video/x-ms-wmv" medium="video"/>
        <media:content url="http://media.ch9.ms/ch9/DE97/0EFFA94A-922F-4E7F-954B-9E650090DE97/BenthePCGuy_high_ch9.mp4" expression="full" duration="480" fileSize="215087043" type="video/mp4" medium="video"/>
        <media:content url="http://media.ch9.ms/ch9/DE97/0EFFA94A-922F-4E7F-954B-9E650090DE97/BenthePCGuy_low_ch9.mp4" expression="full" duration="480" fileSize="48582098" type="video/mp4" medium="video"/>
        <media:content url="http://media.ch9.ms/ch9/DE97/0EFFA94A-922F-4E7F-954B-9E650090DE97/BenthePCGuy_Zune_ch9.wmv" expression="full" duration="480" fileSize="55544368" type="video/x-ms-wmv" medium="video"/>
        <media:content url="http://smooth.ch9.ms/ch9/DE97/0EFFA94A-922F-4E7F-954B-9E650090DE97/BenthePCGuy.ism/manifest" expression="full" duration="480" fileSize="8410" type="video/x-ms-wmv" medium="video"/>
      </media:group>      
      <enclosure url="http://media.ch9.ms/ch9/DE97/0EFFA94A-922F-4E7F-954B-9E650090DE97/BenthePCGuy_ch9.wmv" length="104584313" type="video/x-ms-wmv"/>
      <dc:creator>Larry Larsen</dc:creator>
      <itunes:author>Larry Larsen</itunes:author>
      <slash:comments>7</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/posts/PC-Showcase-with-Ben-the-PC-Guy/rss</wfw:commentRss>
      <category>Hardware</category>
      <category>Video editing</category>
      <category>Tablet PC</category>
      <category>Gaming hardware</category>
    </item>
  <item>
      <title>Dancing Lights!</title>
      <description><![CDATA[ <p>A few years ago, Brian Peek, created a <a href="http://blogs.msdn.com/b/coding4fun/archive/2007/12/23/1230660.aspx">light sequencing application phidgets to animate your holiday cheer</a> and Don, a coding4fun reader, leveraged it to animate some lights of his own for this year!</p><div id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:0332c214-61c6-4d65-88c8-ef57e864e24e" class="wlWriterEditableSmartContent"><div id="1f8bd787-16c3-46e8-a0be-49adac0e4a87"><div><a href="http://www.youtube.com/watch?v=b3vsHCBDpEM" target="_new"><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10104847/video28d9e9295546.jpg" alt=""></a></div></div></div><p>Awesome job Don and thanks for telling us about it!&nbsp; </p><p>Update:&nbsp; Don has <a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10104847/lightSeq_cBrown.zip">shared his sequence file with us</a>!</p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/hardware/RSS&WT.dl=0&WT.entryid=Entry:RSSView:992ca31aafb64656afaa9e7600c6eabc">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/blog/Dancing-Lights</comments>
      <itunes:summary> A few years ago, Brian Peek, created a light sequencing application phidgets to animate your holiday cheer and Don, a coding4fun reader, leveraged it to animate some lights of his own for this year!Awesome job Don and thanks for telling us about it!&amp;nbsp; Update:&amp;nbsp; Don has shared his sequence file with us!</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/blog/Dancing-Lights</link>
      <pubDate>Tue, 14 Dec 2010 15:40:12 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/blog/Dancing-Lights</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/10104847_100.jpg" height="75" width="100"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/10104847_220.jpg" height="165" width="220"/>      
      <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/Dancing-Lights/RSS</wfw:commentRss>
      <category>Hardware</category>
      <category>c4fnews</category>
      <category>Phidgets</category>
      <category>old projects made new</category>
      <category>relays</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/hardware/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 ring, wh</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 url="http://ecn.channel9.msdn.com/o9/c4f/images/10104241_220.jpg" height="165" width="220"/>      
      <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>Meet the new Windows Phone 7 Devices</title>
      <description><![CDATA[ <p>Here's a quick look at the new hardware for Windows Phone 7</p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/hardware/RSS&WT.dl=0&WT.entryid=Entry:RSSView:7e918e27e50342cc814e9e0b0182eff5">]]></description>
      <comments>http://channel9.msdn.com/posts/Meet-the-new-Windows-Phone-7-Devices</comments>
      <itunes:summary> Here&#39;s a quick look at the new hardware for Windows Phone 7</itunes:summary>
      <itunes:duration>138</itunes:duration>
      <link>http://channel9.msdn.com/posts/Meet-the-new-Windows-Phone-7-Devices</link>
      <pubDate>Mon, 11 Oct 2010 13:49:50 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/posts/Meet-the-new-Windows-Phone-7-Devices</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/ch9/eff5/7e918e27-e503-42cc-814e-9e0b0182eff5/PhoneMeet_100_ch9.jpg" height="75" width="100"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/ch9/eff5/7e918e27-e503-42cc-814e-9e0b0182eff5/PhoneMeet_220_ch9.jpg" height="165" width="220"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/ch9/eff5/7e918e27-e503-42cc-814e-9e0b0182eff5/PhoneMeet_512_ch9.jpg" height="384" width="512"/>
      <media:group>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/eff5/7e918e27-e503-42cc-814e-9e0b0182eff5/PhoneMeet_2MB_ch9.wmv" expression="full" duration="138" fileSize="92656578" type="video/x-ms-wmv" medium="video"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/eff5/7e918e27-e503-42cc-814e-9e0b0182eff5/PhoneMeet_ch9.mp3" expression="full" duration="138" fileSize="1109129" type="audio/mp3" medium="audio"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/eff5/7e918e27-e503-42cc-814e-9e0b0182eff5/PhoneMeet_ch9.mp4" expression="full" duration="138" fileSize="14058840" type="video/mp4" medium="video"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/eff5/7e918e27-e503-42cc-814e-9e0b0182eff5/PhoneMeet_ch9.wma" expression="full" duration="138" fileSize="1128473" type="audio/x-ms-wma" medium="audio"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/eff5/7e918e27-e503-42cc-814e-9e0b0182eff5/PhoneMeet_ch9.wmv" expression="full" duration="138" fileSize="22454259" type="video/x-ms-wmv" medium="video"/>
      </media:group>      
      <enclosure url="http://ecn.channel9.msdn.com/o9/ch9/eff5/7e918e27-e503-42cc-814e-9e0b0182eff5/PhoneMeet_ch9.wmv" length="22454259" type="video/x-ms-wmv"/>
      <dc:creator>Laura Foy</dc:creator>
      <itunes:author>Laura Foy</itunes:author>
      <slash:comments>1</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/posts/Meet-the-new-Windows-Phone-7-Devices/rss</wfw:commentRss>
      <category>Hardware</category>
      <category>Windows Phone</category>
      <category>WP7</category>
    </item>
  <item>
      <title>First Look: Windows Phone 7 Hardware</title>
      <description><![CDATA[ <p>In this video, Microsoft CVP Steve Guggenheimer introduces the new hardware devices that will be offering Windows Phone 7. There's tactile keyboards, slide out speakers, surround sound, enhanced cameras, scratch resistance screens, and more. Check out the phones from Dell, LG, HTC &amp; Samsung.</p><p><a href="http://channel9.msdn.com/posts/Meet-the-new-Windows-Phone-7-Devices?preview">Here's another look at the phones</a></p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/hardware/RSS&WT.dl=0&WT.entryid=Entry:RSSView:5cb9da58c9f340019fee9e0c002d3394">]]></description>
      <comments>http://channel9.msdn.com/posts/First-Look-Windows-Phone-7-Hardware</comments>
      <itunes:summary> In this video, Microsoft CVP Steve Guggenheimer introduces the new hardware devices that will be offering Windows Phone 7. There&#39;s tactile keyboards, slide out speakers, surround sound, enhanced cameras, scratch resistance screens, and more. Check out the phones from Dell, LG, HTC &amp;amp; Samsung.Here&#39;s another look at the phones</itunes:summary>
      <itunes:duration>367</itunes:duration>
      <link>http://channel9.msdn.com/posts/First-Look-Windows-Phone-7-Hardware</link>
      <pubDate>Mon, 11 Oct 2010 13:48:19 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/posts/First-Look-Windows-Phone-7-Hardware</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/ch9/3394/5cb9da58-c9f3-4001-9fee-9e0c002d3394/WP7Gugg_100_ch9.jpg" height="75" width="100"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/ch9/3394/5cb9da58-c9f3-4001-9fee-9e0c002d3394/WP7Gugg_220_ch9.jpg" height="165" width="220"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/ch9/3394/5cb9da58-c9f3-4001-9fee-9e0c002d3394/WP7Gugg_512_ch9.jpg" height="384" width="512"/>
      <media:group>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/3394/5cb9da58-c9f3-4001-9fee-9e0c002d3394/WP7Gugg_2MB_ch9.wmv" expression="full" duration="367" fileSize="91649235" type="video/x-ms-wmv" medium="video"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/3394/5cb9da58-c9f3-4001-9fee-9e0c002d3394/WP7Gugg_ch9.mp3" expression="full" duration="367" fileSize="2944193" type="audio/mp3" medium="audio"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/3394/5cb9da58-c9f3-4001-9fee-9e0c002d3394/WP7Gugg_ch9.mp4" expression="full" duration="367" fileSize="40685884" type="video/mp4" medium="video"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/3394/5cb9da58-c9f3-4001-9fee-9e0c002d3394/WP7Gugg_ch9.wma" expression="full" duration="367" fileSize="2981941" type="audio/x-ms-wma" medium="audio"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/3394/5cb9da58-c9f3-4001-9fee-9e0c002d3394/WP7Gugg_ch9.wmv" expression="full" duration="367" fileSize="80807633" type="video/x-ms-wmv" medium="video"/>
      </media:group>      
      <enclosure url="http://ecn.channel9.msdn.com/o9/ch9/3394/5cb9da58-c9f3-4001-9fee-9e0c002d3394/WP7Gugg_ch9.wmv" length="80807633" type="video/x-ms-wmv"/>
      <dc:creator>Laura Foy</dc:creator>
      <itunes:author>Laura Foy</itunes:author>
      <slash:comments>20</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/posts/First-Look-Windows-Phone-7-Hardware/rss</wfw:commentRss>
      <category>Hardware</category>
      <category>Windows Phone 7</category>
      <category>WP7</category>
      <category>phones</category>
    </item>
  <item>
      <title>Hanselminutes on 9 - Gadget Basement with Ward Cunningham</title>
      <description><![CDATA[ <p>Scott stopped by Ward Cunningham (you know, the guy who <strong>invented the Wiki</strong>. Yes, that Ward Cunningham) to hang out, and discovered Ward's treasure trove of electronics, software, soldering guns and web accessible sensor arrays that run 24/7/365. Ever wish you had a real cool uncle that didn't take you fishing, but instead showed you how to create your own multi-processor computer with $2 chips off the shelf? Let's step into Uncle Ward's basement.</p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/hardware/RSS&WT.dl=0&WT.entryid=Entry:RSSView:ebc1276226864cb9b8489e060061be34">]]></description>
      <comments>http://channel9.msdn.com/Shows/HanselminutesOn9/Hanselminutes-on-9-Gadget-Basement-with-Ward-Cunningham</comments>
      <itunes:summary> Scott stopped by Ward Cunningham (you know, the guy who invented the Wiki. Yes, that Ward Cunningham) to hang out, and discovered Ward&#39;s treasure trove of electronics, software, soldering guns and web accessible sensor arrays that run 24/7/365. Ever wish you had a real cool uncle that didn&#39;t take you fishing, but instead showed you how to create your own multi-processor computer with $2 chips off the shelf? Let&#39;s step into Uncle Ward&#39;s basement.</itunes:summary>
      <itunes:duration>1669</itunes:duration>
      <link>http://channel9.msdn.com/Shows/HanselminutesOn9/Hanselminutes-on-9-Gadget-Basement-with-Ward-Cunningham</link>
      <pubDate>Tue, 05 Oct 2010 18:41:33 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Shows/HanselminutesOn9/Hanselminutes-on-9-Gadget-Basement-with-Ward-Cunningham</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/ch9/be34/ebc12762-2686-4cb9-b848-9e060061be34/HanselminutesOn9WardCunninghamGadgets_100_ch9.jpg" height="75" width="100"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/ch9/be34/ebc12762-2686-4cb9-b848-9e060061be34/HanselminutesOn9WardCunninghamGadgets_220_ch9.jpg" height="165" width="220"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/ch9/be34/ebc12762-2686-4cb9-b848-9e060061be34/HanselminutesOn9WardCunninghamGadgets_512_ch9.jpg" height="384" width="512"/>
      <media:group>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/be34/ebc12762-2686-4cb9-b848-9e060061be34/HanselminutesOn9WardCunninghamGadgets_2MB_ch9.wmv" expression="full" duration="1669" fileSize="982967227" type="video/x-ms-wmv" medium="video"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/be34/ebc12762-2686-4cb9-b848-9e060061be34/HanselminutesOn9WardCunninghamGadgets_ch9.mp3" expression="full" duration="1669" fileSize="13357513" type="audio/mp3" medium="audio"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/be34/ebc12762-2686-4cb9-b848-9e060061be34/HanselminutesOn9WardCunninghamGadgets_ch9.mp4" expression="full" duration="1669" fileSize="178109774" type="video/mp4" medium="video"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/be34/ebc12762-2686-4cb9-b848-9e060061be34/HanselminutesOn9WardCunninghamGadgets_ch9.wma" expression="full" duration="1669" fileSize="13513965" type="audio/x-ms-wma" medium="audio"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/be34/ebc12762-2686-4cb9-b848-9e060061be34/HanselminutesOn9WardCunninghamGadgets_ch9.wmv" expression="full" duration="1669" fileSize="352159446" type="video/x-ms-wmv" medium="video"/>
      </media:group>      
      <enclosure url="http://ecn.channel9.msdn.com/o9/ch9/be34/ebc12762-2686-4cb9-b848-9e060061be34/HanselminutesOn9WardCunninghamGadgets_ch9.wmv" length="352159446" type="video/x-ms-wmv"/>
      <dc:creator>Scott Hanselman</dc:creator>
      <itunes:author>Scott Hanselman</itunes:author>
      <slash:comments>7</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Shows/HanselminutesOn9/Hanselminutes-on-9-Gadget-Basement-with-Ward-Cunningham/RSS</wfw:commentRss>
      <category>Computer Hardware</category>
      <category>HanselminutesOn9</category>
      <category>Hardware</category>
      <category>sensors</category>
    </item>
  <item>
      <title>Home Energy Monitoring</title>
      <description><![CDATA[ <p>Recently, the noise from the multiple servers running in the garage, the enormous energy bills, and my general sense of “I should do more to save the planet” outweighed my procrastination and led me to take action and reduce my energy consumption.</p><p>My first step was buying an Energy Monitor. After looking at a few different models, I spotted <a href="http://www.currentcost.net/buynowmain.html">one</a> with a USB cable that would allow me to “send the readings to a home PC.” Ohh! I could do something with the data instead of just looking at it on a handheld monitor. Interesting… </p><h2>Getting Started</h2><p>The first thing to do is install the monitor and the next thing is to install the <a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10068304/win_drivers.zip">drivers for the USB cable</a>—these allow the USB connection to present itself as a COM port and make it easy to interact with. </p><p>Next, test the basic functionality. To do this (and to see the data transfer in action) you will need a Terminal client. Open your terminal software, set the COM port to whatever the USB Cable driver surfaced as (typically COM 3), set the baud rate to 57600bps, 8 data bits, “none” for parity, 1 stop bit, and no handshaking. When you “open” the COM port you should now see an Xml string being received every six seconds (for example):</p><p><strong>HTML</strong><br><pre class="brush: html">&lt;msg&gt;
   &lt;src&gt;CC128-v0.11&lt;/src&gt;
   &lt;dsb&gt;00089&lt;/dsb&gt;
   &lt;time&gt;13:02:39&lt;/time&gt;
   &lt;tmpr&gt;18.7&lt;/tmpr&gt;
   &lt;sensor&gt;1&lt;/sensor&gt;
   &lt;id&gt;01234&lt;/id&gt;
   &lt;type&gt;1&lt;/type&gt;
   &lt;ch1&gt;
      &lt;watts&gt;00345&lt;/watts&gt;
   &lt;/ch1&gt;
   &lt;ch2&gt;
      &lt;watts&gt;02151&lt;/watts&gt;
   &lt;/ch2&gt;
   &lt;ch3&gt;
      &lt;watts&gt;00000&lt;/watts&gt;
   &lt;/ch3&gt;
&lt;/msg&gt;
</pre></p><p>The format of the Xml data can be found in <a href="http://www.currentcost.com/cc128/xml.htm">this document</a>, available on the CurrentCost website.</p><h2>Project Outline / Design</h2><p>Thinking about the project outline and design, I knew that I wanted to be able to make the received data readings available to multiple applications and websites. I also wanted to be able to tweet my energy usage every couple of hours, upload the data to some data tracking/recording web app, and be able to store the data myself so I could chart it at a later date. I also wanted the ability to see the real-time data when I was away from home, and I wanted to be able to use my phone as a kind of remote monitor.</p><p>I sketched out some ideas and came up with a design for a core Windows service that simply grabbed the data from the device, decoded it, and then passed it on to a number of modules/plugins, each of which used the data to complete a specific action. This kind of module/plugin/extension framework is a good candidate for <a href="http://msdn.microsoft.com/en-us/library/dd460648.aspx">the Managed Extension Framework (MEF)</a> in .NET 4.0:</p><p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10068304/image.png"><img title="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10068304/image_thumb.png" border="0" alt="image" width="500" height="342"></a></p><p>In fact, we'll be targeting the .NET 4.0 framework because we need some of the newer System.Composition namespace elements for the Managed Extension Framework to work.</p><h2>Step 1 – The Windows Service</h2><p>The Windows Service is the core of the application and needs a serial port connection to receive the data from the monitor, making it able to alert each of the plugins of the new reading.</p><h5>Coding the Service</h5><p>To begin coding the service, you must first create a new “Windows Service” project type. Then, change the class name to EnergyService and the ServiceName to EnergyService, add the serial port, and wire it up. To do this, you'll need a System.IO.Ports.SerialPort member variable in the class:</p><p><strong>C#</strong><br><pre class="brush: csharp">SerialPort comm;</pre></p><p>Create the object in the class constructor, and wire up the ‘DataReceived' event:</p><p><strong>C#</strong><br><pre class="brush: csharp">comm = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
comm.DataReceived &#43;= new SerialDataReceivedEventHandler(SerialDataReceived);
</pre></p><p>Then, we pull the bytes from the serial port in the ‘SerialDataReceived' event handler and add them to a buffer, immediately checking the buffer to see if the bytes we have stored in there so far make up a full reading. If so, we process it. If we don't have a full reading, however, we simply wait for more bytes.</p><p><pre class="brush: csharp">void SerialDataReceived(object sender, SerialDataReceivedEventArgs e)
{
    rxBuffer &#43;= comm.ReadExisting();
    while (IsReading(rxBuffer))
    {
        // we have a reading (or partial reading), so let's process
        EnergyReading rdg = ExtractReading(ref rxBuffer);
        if (rdg.IsValid)
        {
            NotifyPlugins(rdg);
        }
    }
}

private EnergyReading ExtractReading(ref string rxBuffer)
{
    string rdgXml;
    int pos = rxBuffer.IndexOf(Environment.NewLine);
    rdgXml = rxBuffer.Substring(0, pos);
    rxBuffer = rxBuffer.Substring(pos &#43; 2);
    return new EnergyReading(rdgXml);
}</pre></p><h3>Debug</h3><p>I also added a debug feature allowing you to inject a reading every six seconds. To enable the debug mode, simply set “debug_enabled” to “true” in the appSettings section of the app.config file.</p><p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10068304/image_3.png"><img title="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10068304/image_thumb_3.png" border="0" alt="image" width="163" height="242"></a></p><h2>Parsing the Readings </h2><p>The xml text is passed to the constructor of the EnergyReading class and this parses the xml into the required properties, which gives us an object to pass around as needed. The EnergyReading class only extracts the timestamp, temperature and energy values, though there is scope for parsing much more, especially from the “history” readings (<a href="http://www.currentcost.com/cc128/xml.htm">see the Xml definition for more info</a>). <strong><em>Note:</em></strong><em> we also override the ToString() method so that we have a simple method of debugging the app/values.</em></p><p><strong>C#</strong><br><pre class="brush: csharp">class EnergyReading
{
    public DateTime TimeStamp { get; private set; }
    public float Energy { get; private set; }
    public float Temperature { get; private set; }
    public bool IsValid { get; private set; }

    public EnergyReading(string readingData)
    {
        TimeStamp = DateTime.MinValue;
        Energy = float.NaN;
        Temperature = float.NaN;
        IsValid = false;

        try
        {
            // parse the xml based reading
            XmlDocument xDoc = new XmlDocument();
            xDoc.LoadXml(readingData);

            XmlNode xNode = xDoc.SelectSingleNode(&quot;/msg/time&quot;);
            TimeStamp = DateTime.Parse(xNode.InnerText);
            xNode = xDoc.SelectSingleNode(&quot;/msg/tmpr&quot;);
            Temperature = float.Parse(xNode.InnerText);
            xNode = xDoc.SelectSingleNode(&quot;/msg/ch1/watts&quot;);
            Energy = int.Parse(xNode.InnerText);
            IsValid = true;
        }
        catch (Exception ex)
        {
            // invalid reading
            Debug.WriteLine(ex.Message);
        }
    }

    public override string ToString()
    {
        StringBuilder sb = new StringBuilder(TimeStamp.ToLongTimeString());
        sb.Append(&quot; - &quot;);
        sb.Append(Energy.ToString(&quot;N&quot;));
        sb.Append(&quot; Watts - &quot;);
        sb.Append(Temperature.ToString(&quot;N&quot;));
        sb.Append(&quot; Degrees&quot;);

        return sb.ToString();
    }
}
</pre></p><h2>Adding the Plugin Infrastructure</h2><p>Next up is adding the plumbing for the plugins. As previously mentioned, we will be using MEF, which makes it all incredibly simple.</p><p>Basically, we define an interface supported by all of the plugins, create a private variable of type IList&lt;PluginInterface&gt; and tag it with the [ImportMany] attribute (this holds our plugin objects), create a catalog of plugins (loaded from a specific directory), and then add that catalog to a CompositionContainer that automatically wires everything up for us. Sounds complex, but it only takes about 10 lines of code:</p><p><strong>C#</strong><br><pre class="brush: csharp">using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;

// snip....

CompositionContainer container;

// snip....

[ImportMany]
private IList&lt;IEnergyMonitorPlugin&gt; plugins { get; set; }

// snip....

private void LoadPlugins()
{
    string baseDir = AppDomain.CurrentDomain.BaseDirectory;
    DirectoryCatalog currDirCatalog = new DirectoryCatalog(baseDir);

    container = new CompositionContainer(currDirCatalog);
    container.ComposeParts(this);
}



</pre></p><p>Now that we have all of the plugins correctly wired up, we need to notify them. For the time being, we'll also leave a few lines of debugging messages in there:</p><p><strong>C#</strong><br><pre class="brush: csharp">private void NotifyPlugins(EnergyReading rdg)
{
    Debug.WriteLine(&quot;Notify : &quot; &#43; rdg.ToString());
    if (null != plugins)
    {
        foreach (IEnergyMonitorPlugin plugin in plugins)
        {
            try
            {
                Debug.WriteLine(&quot;Notify : &quot; &#43; plugin.Name);
                plugin.Notify(rdg);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(&quot;Plugin '&quot; &#43; plugin.Name &#43; &quot;' : &quot; &#43; ex.Message);
            }
        }
    }
}
</pre></p><h3>Adding an Installer to the Windows Service</h3><p>Now that we have completed the Windows Service, we need to test it out. To do so, we need to install it, and for that we need to add an Installer Class, as well as adding both a ServiceInstaller and a ServiceProcessInstaller to the designer (set the ServiceProcessInstaller Account property to “Local System” and run the service under this account).</p><p>Installing a service is different than installing a normal application. Luckily, we can use .NET framework's InstallUtil.exe to simplify things. I like to set InstallUtil.exe up as an External Tool in Visual Studio when I'm working on Windows Service projects, which makes the whole process as simple as highlighting the Windows Service project and clicking on the Install (or Uninstall) option under the Tools menu:</p><p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10068304/image_4.png"><img title="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10068304/image_thumb_4.png" border="0" alt="image" width="474" height="460"></a></p><p>The configuration to set this up as an “external tool” is as follows:</p><blockquote><table border="0" cellspacing="0" cellpadding="2" width="500"><tbody><tr><td width="107" valign="top">Title</td><td width="393" valign="top">Install Service (.NET 4) <br></td></tr><tr><td width="107" valign="top">Command</td><td width="393" valign="top">C:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe </td></tr><tr><td width="107" valign="top">Arguments</td><td width="393" valign="top">/i &quot;$(ProjectDir)\bin\debug\$(TargetName)$(TargetExt)&quot; </td></tr><tr><td width="107" valign="top">&nbsp;</td><td width="393" valign="top">&nbsp;</td></tr><tr><td width="107" valign="top">Title</td><td width="393" valign="top">Uninstall Service (.NET 4) <br></td></tr><tr><td width="107" valign="top">Command</td><td width="393" valign="top">C:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe </td></tr><tr><td width="107" valign="top">Arguments</td><td width="393" valign="top">/i &quot;$(ProjectDir)\bin\debug\$(TargetName)$(TargetExt)&quot;</td></tr></tbody></table></blockquote><p>For 32-bit operating systems, change the <strong>Framework64</strong> folder name to <strong>Framework</strong>.</p><h3>Testing the Windows Service</h3><p>Once you start the service, if you open the Output windows in Visual Studio and view the output from Debug, you should start seeing the readings come in:</p><p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10068304/image_5.png"><img title="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10068304/image_thumb_5.png" border="0" alt="image" width="376" height="134"></a></p><p><strong>&nbsp;</strong></p><h2>Step 2 – The Twitter Plugin</h2><p>The first plugin we'll write is a simple Twitter poster. Every 60 minutes, this plugin will send a tweet with your machine name and the average energy use over the last hour.</p><p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10068304/image_6.png"><img title="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10068304/image_thumb_6.png" border="0" alt="image" width="203" height="345"></a></p><p>Next, create a new Class Library project and name it “TwitterPlugin.” Then add a reference to the “EnergyService_CSharp” project and have the class implement the IEnergyMonitorPlugin interface. We will also need to add some class variables to hold the last tweet time, energy total, and reading count. <br>As Twitter no longer supports Basic Auth for API calls we will need to use oAuth. For this we will use the excellent oAuth class developed by <a href="http://eran.sandler.co.il/">Eran Sandler</a> and extended by <a href="http://www.voiceoftech.com/swhitley/index.php/category/software-development/page/2/">Shannon Witley</a>.</p><p><strong>C#</strong><br><pre class="brush: csharp">[Export(typeof(IEnergyMonitorPlugin))]
public class TwitterPlugin : IEnergyMonitorPlugin
{
    double twInterval;
    double twEnergy = 0;
    int twReadings = 0;
    DateTime twLastTweet = DateTime.MinValue;
    oAuthTwitter _oAuth = new oAuthTwitter();
</pre></p><p>Next, we give the plugin values for “Name” and “Description” and set the DeInit() function to return true (this is a simple plugin so no deinitialization is needed). For the Init() function, we want to read from the app.config the twitter oAuth parameters, and the interval between tweets—remember, this plugin is loaded into the AppDomain of the service, so we need to add the entries to the app.config file of the service, not the app.config of the twitterplugin project/class.</p><p>The code looks like this:</p><p><strong>C#</strong><br><pre class="brush: csharp">bool IEnergyMonitorPlugin.Init()
{
    _oAuth.Token = GetSetting(&quot;twitterplugin_token&quot;, &quot;&quot;);
    _oAuth.TokenSecret = GetSetting(&quot;twitterplugin_tokensecret&quot;, &quot;&quot;);
    _oAuth.Pin = GetSetting(&quot;twitterplugin_pin&quot;, &quot;&quot;);

    twInterval = double.Parse(GetSetting(&quot;twitterplugin_interval&quot;, &quot;60&quot;));
    return true;
}

private string GetSetting(string key, string defaultValue)
{
    NameValueCollection appSettings = ConfigurationManager.AppSettings;
    string val = appSettings.Get(key);
    if (null == val)
    {
        val = defaultValue;
    }

    return val;
}
</pre></p><p>The crux of a plugin is the “Notify” function, and for this one we simply add the energy value to the total energy count and increase the reading count. We then check if more than 60 minutes have passed since the last tweet, and if so we send the tweet:</p><p><strong>C#</strong><br><pre class="brush: csharp">bool IEnergyMonitorPlugin.Notify(EnergyReading rdg)
{
    bool retVal = false;

    twEnergy &#43;= rdg.Energy;
    twReadings&#43;&#43;;

    if (twLastTweet.AddMinutes(twInterval) &lt; DateTime.Now)
    {
    // it's time to tweet
        retVal= SendTweet(
            string.Format(
                &quot;In the last {0} mins {1} has used an average of {2} watts&quot;, 
                twInterval, 
                Environment.MachineName, 
                (twEnergy/twReadings)));
        twEnergy = 0;
        twReadings = 0;
        twLastTweet = DateTime.Now;
        retVal = true;
    }

    return retVal;
}
</pre></p><p>Sending the tweet requires that we UrlEncode the message and then call the oAuthWebRequest method of the oAuth class with the post data as a parameter. </p><p><pre class="brush: csharp">private bool SendTweet(string tweet)
{
    bool retVal = false;
    try
    {
        string encTweet = System.Web.HttpUtility.UrlEncode(tweet);
        string xml = _oAuth.oAuthWebRequest(
            oAuthTwitter.Method.POST,
            &quot;http://twitter.com/statuses/update.xml&quot;,
            &quot;status=&quot; &#43; tweet);
        retVal = true;
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine(&quot;Error : &quot; &#43; ex.ToString());
    }

    return retVal;
}</pre></p><p>Now we have the Notify functionality of the TwitterPlugin completed. To get it working, simply copy the plugin to the same folder as the running Windows Service, edit the setting for “twitterplugin_interval” in the service app.config files, and restart the service. The tweets will not yet be accepted by Twitter as we have not yet authorized the application – for this we need user interaction so it is not something we do in the Windows Service. Instead we build a ConfigTool that uses MEF to load in each of the plugins and calls the “Configure” method. <br>We add a Windows Form to the TwitterPlugin, add a button that takes the user to a Twitter application authorization page, add a textbox that the user enters the PIN displayed on the webpage into and save the resulting oAuth Token and TokenSecret we get back from calling the AccessTokenGet method of the oAuth class. When we have all the oAuth parameters back we simply save them into the app.config file:</p><p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10068304/image_7.png"><img title="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10068304/image_thumb_7.png" border="0" alt="image" width="200" height="149"></a><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10068304/image_8.png"><img title="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10068304/image_thumb_8.png" border="0" alt="image" width="161" height="149"></a></p><p>If all is well, you should see tweets appearing every X minutes (depending on the interval you have set) along with your energy averages.</p><p>Now that we have completed our first plugin, it should be easy to see how simple it is to write further plugins. You might consider writing the energy values to a local database, sending Facebook updates, or posting to a dedicated service that uses API to store sensor or energy values, such as <a href="http://www.pachube.com">http://www.pachube.com</a> or <a href="http://www.enio.co.uk">http://www.enio.co.uk</a>.</p><p><strong>&nbsp;</strong></p><h2>Step 3 – The WebService and Plugin</h2><h4>The next stage we'll develop will give us a little more flexibility. Essentially, this stage consists of a RESTful Windows Communication Framework (WCF) Service and a corresponding WebSvcPlugin that we'll use to update the WCF Service with the latest readings. We'll also build a couple of client applications that will retrieve the reading from the WCF Service (one is a simple webpage using jQuery AJAX to get the reading from the WCF Service, and the other is a Windows Phone 7 application using a HttpWebRequest to get the reading from the WCF Service).</h4><p>The plugin and clients will need the WCF Service to be in place before they can be written, so we'll tackle the WCF Service first by adding an “ASP.NET Empty Web Application” project to the solution and calling it “EnergyMonitorWs”:<a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10068304/image_9.png"><img title="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10068304/image_thumb_9.png" border="0" alt="image" width="500" height="230"></a></p><p>Then we add a new “AJAX-enabled WCF Service” and name it EnergyMonitor.svc:</p><p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10068304/image_10.png"><img title="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10068304/image_thumb_10.png" border="0" alt="image" width="500" height="224"></a></p><h4>The WCF Service will expose OperationContracts that allow clients to set the current values and receive each of the values in either JSON or XML format. The current values will be stored in an HttpRuntime.Cache object, so we don't need to worry about persisting the reading data to MSSQL or the FileSystem.</h4><p>The cache object is in the System.Web.Caching namespace, so we'll need a reference to that. We'll also need to make sure we are working in AspNetCompatibility mode. To do so, we'll add the following attribute to the class:</p><p><strong>C#</strong><br><pre class="brush: csharp">[AspNetCompatibilityRequirements(
    RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
</pre></p><p>Now let's code the “SetCurrentValues” function, which exposes a “/set” endpoint and takes date, time, energy, and temperature as parameters on the HTTP GET querystring and stores them in the cache for an hour (this function should be called every 6 seconds, so caching each reading for up to an hour gives us plenty of room for failed updates). </p><p><strong>C#</strong><br><pre class="brush: csharp">[OperationContract]
[WebInvoke(
    Method=&quot;GET&quot;,
    UriTemplate=&quot;set?energy={energy}&amp;temp={temp}&amp;date={date}&amp;time={time}&quot;)]
public void SetCurrentValues(string energy, string temp, string date, string time)
{
    Cache cache = HttpRuntime.Cache;

    try
    {
        cache.Remove(&quot;energy&quot;);
        cache.Remove(&quot;temp&quot;);
        cache.Remove(&quot;date&quot;);
        cache.Remove(&quot;time&quot;);
    }
    catch { }

    cache.Add(
        &quot;energy&quot;, 
        energy, 
        null, 
        DateTime.Now.AddHours(1), 
        Cache.NoSlidingExpiration, 
        CacheItemPriority.Default, 
        null);
    cache.Add(
        &quot;temp&quot;, 
        temp, 
        null, 
        DateTime.Now.AddHours(1), 
        Cache.NoSlidingExpiration, 
        CacheItemPriority.Default, 
        null);
    cache.Add(
        &quot;date&quot;, 
        date, 
        null, 
        DateTime.Now.AddHours(1), 
        Cache.NoSlidingExpiration, 
        CacheItemPriority.Default, 
        null);
    cache.Add(
        &quot;time&quot;, 
        time, 
        null, 
        DateTime.Now.AddHours(1), 
        Cache.NoSlidingExpiration, 
        CacheItemPriority.Default, 
        null);

    return;
}
</pre></p><p>We want to make request functions available via a simple HTTP GET and we want to provide the option of JSON or XML as the response. Therefore, we add a “/json/{x}” endpoint and a “/xml/{x}” endpoint where {x} is the reading data we want (energy, temp, date or time):</p><p><strong>C#</strong><br><pre class="brush: csharp">[OperationContract]
[WebInvoke(
    Method = &quot;GET&quot;, 
    UriTemplate = &quot;xml/{value}&quot;)]
public string GetValueXml(string value)
{
    WebOperationContext.Current.OutgoingResponse.ContentType = &quot;text/xml&quot;;
    return GetValue(value.ToLower());
}

[OperationContract]
[WebInvoke(
    Method = &quot;GET&quot;, 
    UriTemplate = &quot;json/{value}&quot;, 
    ResponseFormat = WebMessageFormat.Json)]
public string GetValueJson(string value)
{
    return GetValue(value.ToLower());
}

private string GetValue(string key)
{
    Cache cache = HttpRuntime.Cache;

    string retVal = (string)cache.Get(key);
    if (null == retVal)
    {
        retVal = &quot;N/A&quot;;
    }

    return retVal;
}
</pre></p><p>Now that we have the WCF Service in place, we can build the plugin that updates it. This is another Class Library project that we add to the solution (this time naming it WebServicePlugin), again making sure it implements the IEnergyMonitor interface (you'll need to add a reference to the EnergyMonitor_CSharp for this).</p><p>Give the plugin a Name and Description and set the Init() and DeInit() functions to return true. Then, simply have the code in the “Notify” function create an HTTP GET request with the values in the querystring to the “/set” endpoint (the SetCurrentValues function). This can be accomplished with a System.Net.WebClient object:</p><p><strong>C#</strong><br><pre class="brush: csharp">bool IEnergyMonitorPlugin.Notify(EnergyReading rdg)
{
    bool retVal = false;

    DateTime ts = rdg.TimeStamp;

    string getUrl = baseUrl &#43; &quot;/set?&quot;;
    getUrl &#43;= &quot;energy=&quot; &#43; rdg.Energy.ToString() &#43; &quot;&amp;&quot;;
    getUrl &#43;= &quot;temp=&quot; &#43; rdg.Temperature.ToString() &#43; &quot;&amp;&quot;;
    getUrl &#43;= &quot;date=&quot; &#43; ts.ToString(&quot;dd/MM/yy&quot;) &#43; &quot;&amp;&quot;;
    getUrl &#43;= &quot;time=&quot; &#43; ts.ToShortTimeString();

    WebClient wc = new WebClient();

    try
    {
        wc.DownloadString(getUrl);
        retVal = true;
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine(
            &quot;Error (Notify) : &quot; &#43; ex.Message);
    }


bool IEnergyMonitorPlugin.Init()
{
    // get the base url from the (Service) app.config
    baseUrl = GetSetting(
        &quot;websvcplugin_baseurl&quot;, 
        &quot;http://localhost/EnergyMonWs.svc&quot;);
    return true;
}

// snip....


private string GetSetting(string key, string defaultValue)
{
    NameValueCollection appSettings = ConfigurationManager.AppSettings;
    string val = appSettings.Get(key);
    if (null == val)
    {
        val = defaultValue;
    }

    return val;
}
</pre></p><p>Now that we're done with the WCF Service and WebSvcPlugin, we need to work on the two WCF Service client applications.</p><h2>Step 4 – The WebService Html Page Client</h2><h4>We'll first tackle the html webpage with jQuery—a simple webpage that uses the jQuery library to make AJAX calls to our WCF Service to get the current values—by adding a new ‘HTML Page' to the EnergyMonitorWs project. To begin, name the page EnergyMonitor.htm.</h4><h4>Next, we'll add some html to the page. This html is linked to some CSS, giving us a simple remote version of the energy monitor:</h4><p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10068304/image_11.png"><img title="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10068304/image_thumb_11.png" border="0" alt="image" width="305" height="181"></a></p><h4>Then we use jQuery to call the WCF Service and update the actual values with real reading data. We also add a JavaScript timer to make the WCF Service calls every 15 seconds. Obviously, we need to reference the jQuery code and the CSS in the head section:</h4><p><strong>HTML</strong><br><pre class="brush: html">&lt;head&gt;
    &lt;title&gt;Energy Monitor - Ken Hughes&lt;/title&gt;
    &lt;script 
        src=&quot;scripts/jquery-1.4.1.js&quot; 
        type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
    &lt;link 
        rel=&quot;Stylesheet&quot; href=&quot;css/style.css&quot; 
        type=&quot;text/css&quot; /&gt;
&lt;/head&gt;
</pre></p><p><strong>&nbsp;</strong></p><p>Then, after the main page display elements, we add the javascript code so the values are updated every 15 seconds:</p><p><strong>Javascript</strong><br><pre class="brush: js">function getReading(fname, elementid) {
    ajaxUrl = &quot;EnergyMonWs.svc/json/&quot; &#43; fname;
    $.ajax({
        type: &quot;GET&quot;,
        url: ajaxUrl,
        contentType: &quot;application/json; charset=utf-8&quot;,
        dataType: &quot;json&quot;,
        success: function (msg) {
            // Replace the div's content with the value returned.
            $(&quot;#&quot; &#43; elementid).text(msg);
        }
    });
}


function updateReadings() {
    getReading(&quot;temp&quot;, &quot;tempval&quot;);
    getReading(&quot;energy&quot;, &quot;energyval&quot;);
    getReading(&quot;time&quot;, &quot;timeval&quot;);
   
}

$(document).ready(function () {

    updateReadings();
    window.setInterval(function () {
        updateReadings();
    }, 15000);
});
</pre></p><h2>Step 5 – The WebService Windows Phone 7 Client</h2><p>The purpose of the Windows Phone 7 client is to act as a remote monitor. The client pulls its reading from the web service and updates a monitor-style display. To complete this part of the project, you will need to have the Windows Phone 7 Development tools installed.</p><p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10068304/image_12.png"><img title="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10068304/image_thumb_12.png" border="0" alt="image" width="292" height="539"></a></p><p>Begin by adding a new “Windows Phone Application” project and calling it “WinPhoneEnergyMonitor.” </p><p>First, in the constructor, add a Timer object, set the interval to 15 seconds, and have it call a function to update the screen values. This function calls the webservice for each value, receiving the latest reading data and updating the relevant TextBlock.</p><p>In Windows Phone 7, uses an asynchronous manner to call to things such as the WebClient and HttpWebRequest. Accordingly, we create a new WebClient object, assign a delegate to the “DownloadStringCompleted” event, and then call “DownloadStringAsync” with the relevant uri along with the TextBlock we want to update as the ‘userState' object. All of this allows us to update the correct item in the event handler.</p><p>The code looks like this:</p><p><strong>C#</strong><br><pre class="brush: csharp">private void UpdateScreen(object state)
{
    UpdateValueFromWebService(&quot;energy&quot;, this.energyValue);
    UpdateValueFromWebService(&quot;temp&quot;, this.tempValue);
    UpdateValueFromWebService(&quot;time&quot;, this.timeValue);
    UpdateValueFromWebService(&quot;date&quot;, this.dateValue);
}

private string UpdateValueFromWebService(string reading, TextBlock tb)
{
    string retVal = &quot;N/A&quot;;
    Uri uri = new Uri(baseUri &#43; &quot;/json/&quot; &#43; reading);

    try
    {
        WebClient wc = new WebClient();
        wc.DownloadStringCompleted &#43;= 
            new DownloadStringCompletedEventHandler(DownloadStringCompleted);
        wc.DownloadStringAsync(uri, tb);
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine(
            &quot;Error (UpdateValueFromWebService) : &quot; &#43; ex.Message);
    }

    return retVal;
}

void DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
    try
    {
        string val = e.Result.Replace(&quot;\&quot;&quot;, &quot;&quot;).Replace(&quot;\\&quot;, &quot;&quot;);
        System.Diagnostics.Debug.WriteLine(val);
        ((TextBlock)e.UserState).Text = val;
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine(
            &quot;Error (DownloadStringCompleted) : &quot; &#43; ex.Message);
    }
}
</pre></p><h2>Conclusion</h2><p>This was a really interesting project. Not only did it help me understand how much energy I was using (and help me reduce it), it also presented a software challenge covering a number of areas and technologies: Windows Service, WCF, Windows Phone 7, and javascript/jQuery.</p><p>I already have plans for a number of other plugins and new ways to visualize the usage data—keep an eye on the Codeplex site for updates.</p><p>If you want to try this out, the download link for the source code is at the top of the article!</p><h2>About The Author</h2><p>Ken Hughes is Chief Technical Officer at C2C Systems, a Microsoft Gold Partner ISV. He is passionate about technology, productivity, and automating <em>everything</em>. He stays up-to-date with and keeps his hand in new technologies by working on personal and open source projects such as <a href="http://www.dasblog.info/">dasBlog</a>. Contact information may be found on both his <a href="http://www.kapie.com">blog</a> and <a href="http://twitter.com/kjhughes">Twitter</a>.</p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/hardware/RSS&WT.dl=0&WT.entryid=Entry:RSSView:1d96a54fcf5c453abbe69e7600c88559">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Home-Energy-Monitoring</comments>
      <itunes:summary> Recently, the noise from the multiple servers running in the garage, the enormous energy bills, and my general sense of “I should do more to save the planet” outweighed my procrastination and led me to take action and reduce my energy consumption.My first step was buying an Energy Monitor. After looking at a few different models, I spotted one with a USB cable that would allow me to “send the readings to a home PC.” Ohh! I could do something with the data instead of just looking at it on a handheld monitor. Interesting… Getting StartedThe first thing to do is install the monitor and the next thing is to install the drivers for the USB cable—these allow the USB connection to present itself as a COM port and make it easy to interact with. Next, test the basic functionality. To do this (and to see the data transfer in action) you will need a Terminal client. Open your terminal software, set the COM port to whatever the USB Cable driver surfaced as (typically COM 3), set the baud rate to 57600bps, 8 data bits, “none” for parity, 1 stop bit, and no handshaking. When you “open” the COM port you should now see an Xml string being received every six seconds (for example):HTML&amp;lt;msg&amp;gt;
   &amp;lt;src&amp;gt;CC128-v0.11&amp;lt;/src&amp;gt;
   &amp;lt;dsb&amp;gt;00089&amp;lt;/dsb&amp;gt;
   &amp;lt;time&amp;gt;13:02:39&amp;lt;/time&amp;gt;
   &amp;lt;tmpr&amp;gt;18.7&amp;lt;/tmpr&amp;gt;
   &amp;lt;sensor&amp;gt;1&amp;lt;/sensor&amp;gt;
   &amp;lt;id&amp;gt;01234&amp;lt;/id&amp;gt;
   &amp;lt;type&amp;gt;1&amp;lt;/type&amp;gt;
   &amp;lt;ch1&amp;gt;
      &amp;lt;watts&amp;gt;00345&amp;lt;/watts&amp;gt;
   &amp;lt;/ch1&amp;gt;
   &amp;lt;ch2&amp;gt;
      &amp;lt;watts&amp;gt;02151&amp;lt;/watts&amp;gt;
   &amp;lt;/ch2&amp;gt;
   &amp;lt;ch3&amp;gt;
      &amp;lt;watts&amp;gt;00000&amp;lt;/watts&amp;gt;
   &amp;lt;/ch3&amp;gt;
&amp;lt;/msg&amp;gt;
The format of the Xml data can be found in this document, available on the CurrentCost website.Project Outline / DesignThinking about the project outline and design, I knew that I wanted to be able to make the received data readings available to multiple applications and websites. I also wanted to be able to tweet my energy </itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Home-Energy-Monitoring</link>
      <pubDate>Mon, 27 Sep 2010 14:43:11 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Home-Energy-Monitoring</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/10068304_100.jpg" height="75" width="100"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/10068304_220.jpg" height="165" width="220"/>      
      <dc:creator>Ken Hughes </dc:creator>
      <itunes:author>Ken Hughes </itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Home-Energy-Monitoring/RSS</wfw:commentRss>
      <category>Hardware</category>
      <category>jQuery</category>
      <category>WP7</category>
      <category>Home Automation</category>
    </item>
  <item>
      <title>First Look at Lifecam Studio</title>
      <description><![CDATA[This morning we announced the latest Microsoft webcam, the <a shape="rect" href="http://www.microsoft.com/hardware/digitalcommunication/ProductDetails.aspx?pid=021" shape="rect">
Microsoft Lifecam Studio</a>. This is our best webcam yet. First thing you will notice is a full 1080p HD sensor for an incredible picture. This updated Lifecam has a thread for tripod, ClearFrame and TrueColor provides a great picture in low light. &nbsp;Daniel
 from the hardware group walks us through some of the other new features. The LifeCam Studio will be available at Best Buy in October retailing for $99.95.
<br /><br />For more on the Lifecams and how they are made, check out <a shape="rect" href="http://channel9.msdn.com/posts/LarryLarsen/The-Labs-of-Microsoft-Hardware-4-of-6/" shape="rect">
this video from the Cam Lab</a>.  <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/hardware/RSS&WT.dl=0&WT.entryid=Entry:RSSView:d549e9b8eae44c3e917a9deb0100d8d0">]]></description>
      <comments>http://channel9.msdn.com/Blogs/LarryLarsen/First-Look-at-Lifecam-Studio</comments>
      <itunes:summary>This morning we announced the latest Microsoft webcam, the 
Microsoft Lifecam Studio. This is our best webcam yet. First thing you will notice is a full 1080p HD sensor for an incredible picture. This updated Lifecam has a thread for tripod, ClearFrame and TrueColor provides a great picture in low light. &amp;nbsp;Daniel
 from the hardware group walks us through some of the other new features. The LifeCam Studio will be available at Best Buy in October retailing for $99.95.
For more on the Lifecams and how they are made, check out 
this video from the Cam Lab. </itunes:summary>
      <itunes:duration>461</itunes:duration>
      <link>http://channel9.msdn.com/Blogs/LarryLarsen/First-Look-at-Lifecam-Studio</link>
      <pubDate>Mon, 13 Sep 2010 16:02:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Blogs/LarryLarsen/First-Look-at-Lifecam-Studio</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/previewImages/100/570582_100x75.jpg" height="75" width="100"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/previewImages/220/570582_220x165.jpg" height="165" width="220"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/ch9/0582/570582/LifecamStudio_320_ch9.jpg" height="240" width="320"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/ch9/0582/570582/LifecamStudio_512_ch9.jpg" height="384" width="512"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/ch9/0582/570582/LifecamStudio_85_ch9.jpg" height="64" width="85"/>
      <media:group>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/0582/570582/LifecamStudio_2MB_ch9.wmv" expression="full" duration="461" fileSize="130149208" type="video/x-ms-wmv" medium="video"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/0582/570582/LifecamStudio_ch9.mp3" expression="full" duration="461" fileSize="3695448" type="audio/mp3" medium="audio"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/0582/570582/LifecamStudio_ch9.mp4" expression="full" duration="461" fileSize="51290516" type="video/mp4" medium="video"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/0582/570582/LifecamStudio_ch9.wma" expression="full" duration="461" fileSize="3741953" type="audio/x-ms-wma" medium="audio"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/0582/570582/LifecamStudio_ch9.wmv" expression="full" duration="461" fileSize="98552197" type="video/x-ms-wmv" medium="video"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/0582/570582/LifecamStudio_Zune_ch9.wmv" expression="full" duration="461" fileSize="52984252" type="video/x-ms-wmv" medium="video"/>
      </media:group>      
      <enclosure url="http://ecn.channel9.msdn.com/o9/ch9/0582/570582/LifecamStudio_ch9.wmv" length="98552197" type="video/x-ms-wmv"/>
      <dc:creator>Larry Larsen</dc:creator>
      <itunes:author>Larry Larsen</itunes:author>
      <slash:comments>6</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Blogs/LarryLarsen/First-Look-at-Lifecam-Studio/RSS</wfw:commentRss>
      <category>Hardware</category>
    </item>
  <item>
      <title>First Look at Arc Touch Mouse </title>
      <description><![CDATA[I stopped by the hardware team to take a first look at the new <a shape="rect" href="http://www.arctouchmouse.com" shape="rect">
Arc Touch Mouse</a>, and shot this short video. The Touch folds flat, to about the same size as an HTC Touch phone. Where the old Arc Mouse fit well in a front pocket, the Arc Touch will do well in a back pocket. The folding portion of the mouse has 90 articulated
 pieces and snaps to a very solid feeling and natural arc. <br /><br />Between the bottons, a touch strip allows you to scroll or flick through your Windows, or touch the top or bottom of the strip to Page Up/Down. This refresh includes haptics, so you&nbsp;can actually feel (and hear) the page scrolling&nbsp;and BlueTrack so the Arc will
 track on almost any surface. The dongle for the Arc Touch is the very slim profile dongle as was used on the
<a shape="rect" href="http://channel9.msdn.com/posts/LarryLarsen/CES-2010-Microsofts-Arc-Keyboard/" shape="rect">
Arc Keyboard</a>.<br /><br />If you'd like to see some of what goes in to developing a mouse, see <a shape="rect" href="http://channel9.msdn.com/posts/PDCNews/Meet-the-Industrial-Design-Team/" shape="rect">
this video</a>&nbsp;on the design of the original Arc.  <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/hardware/RSS&WT.dl=0&WT.entryid=Entry:RSSView:bb4a897bb7cf4790962b9de901866f0b">]]></description>
      <comments>http://channel9.msdn.com/Blogs/LarryLarsen/First-Look-at-Arc-Touch-Mouse</comments>
      <itunes:summary>I stopped by the hardware team to take a first look at the new 
Arc Touch Mouse, and shot this short video. The Touch folds flat, to about the same size as an HTC Touch phone. Where the old Arc Mouse fit well in a front pocket, the Arc Touch will do well in a back pocket. The folding portion of the mouse has 90 articulated
 pieces and snaps to a very solid feeling and natural arc. Between the bottons, a touch strip allows you to scroll or flick through your Windows, or touch the top or bottom of the strip to Page Up/Down. This refresh includes haptics, so you&amp;nbsp;can actually feel (and hear) the page scrolling&amp;nbsp;and BlueTrack so the Arc will
 track on almost any surface. The dongle for the Arc Touch is the very slim profile dongle as was used on the

Arc Keyboard.If you&#39;d like to see some of what goes in to developing a mouse, see 
this video&amp;nbsp;on the design of the original Arc. </itunes:summary>
      <itunes:duration>375</itunes:duration>
      <link>http://channel9.msdn.com/Blogs/LarryLarsen/First-Look-at-Arc-Touch-Mouse</link>
      <pubDate>Wed, 01 Sep 2010 18:59:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Blogs/LarryLarsen/First-Look-at-Arc-Touch-Mouse</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/previewImages/100/570583_100x75.jpg" height="75" width="100"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/previewImages/220/570583_220x165.jpg" height="165" width="220"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/ch9/0583/570583/ArcMouseTouch_320_ch9.jpg" height="240" width="320"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/ch9/0583/570583/ArcMouseTouch_512_ch9.jpg" height="384" width="512"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/ch9/0583/570583/ArcMouseTouch_85_ch9.jpg" height="64" width="85"/>
      <media:group>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/0583/570583/ArcMouseTouch_2MB_ch9.wmv" expression="full" duration="375" fileSize="140917954" type="video/x-ms-wmv" medium="video"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/0583/570583/ArcMouseTouch_ch9.mp3" expression="full" duration="375" fileSize="3007284" type="audio/mp3" medium="audio"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/0583/570583/ArcMouseTouch_ch9.mp4" expression="full" duration="375" fileSize="41827337" type="video/mp4" medium="video"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/0583/570583/ArcMouseTouch_ch9.wma" expression="full" duration="375" fileSize="3045025" type="audio/x-ms-wma" medium="audio"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/0583/570583/ArcMouseTouch_ch9.wmv" expression="full" duration="375" fileSize="82951681" type="video/x-ms-wmv" medium="video"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/0583/570583/ArcMouseTouch_Zune_ch9.wmv" expression="full" duration="375" fileSize="43815736" type="video/x-ms-wmv" medium="video"/>
      </media:group>      
      <enclosure url="http://ecn.channel9.msdn.com/o9/ch9/0583/570583/ArcMouseTouch_ch9.wmv" length="82951681" type="video/x-ms-wmv"/>
      <dc:creator>Larry Larsen</dc:creator>
      <itunes:author>Larry Larsen</itunes:author>
      <slash:comments>14</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Blogs/LarryLarsen/First-Look-at-Arc-Touch-Mouse/RSS</wfw:commentRss>
      <category>Hardware</category>
    </item>
  <item>
      <title>A Pink Mouse for the Cure</title>
      <description><![CDATA[
<p>Call me a girl, but I like pink. I’ve never had a pink mouse though, although I’ve seen plenty for sale. But now there’s one available that’s tempting me to purchase, not just for its color but because I know it’s for a good cause.
</p>
<p>This upcoming special edition of the <a shape="rect" href="http://www.microsoft.com/hardware/mouseandkeyboard/ProductDetails.aspx?pid=013" shape="rect">
Wireless Mobile Mouse 4000</a> has been made in partnership with Susan G. Komen for the Cure, which you probably know is the world’s largest breast cancer charitable organization.
</p>
<p>Microsoft will be donating 10% of the selling price ($4.00 USD) with a minimum donation of $200,000 to Susan G. Komen for the Cure when the mouse goes on sale mid-September (retail price: $39.95 USD). The money will be used for research grants and community
 outreach projects, <a shape="rect" href="http://microsofthardwareblog.com/teaming-up-with-susan-g-komen-for-the-cure/" shape="rect">
reports</a> the Microsoft Hardware blog. </p>
<p>The mouse offers pretty great hardware specs, too, including BlueTrack technology, a tiny nano transceiver and customizable buttons. Windows 7 integration is supported as well. For more details, check out the full feature list
<a shape="rect" href="http://www.microsoft.com/hardware/mouseandkeyboard/ProductDetails.aspx?pid=013" shape="rect">
here</a> on Microsoft.com while you wait for the pink one to arrive in stores and online.
</p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/hardware/RSS&WT.dl=0&WT.entryid=Entry:RSSView:61fbd208cfae497796c59dec0026b4cf">]]></description>
      <comments>http://channel9.msdn.com/Blogs/coolstuff/A-Pink-Mouse-for-the-Cure</comments>
      <itunes:summary>
Call me a girl, but I like pink. I’ve never had a pink mouse though, although I’ve seen plenty for sale. But now there’s one available that’s tempting me to purchase, not just for its color but because I know it’s for a good cause.

This upcoming special edition of the 
Wireless Mobile Mouse 4000 has been made in partnership with Susan G. Komen for the Cure, which you probably know is the world’s largest breast cancer charitable organization.

Microsoft will be donating 10% of the selling price ($4.00 USD) with a minimum donation of $200,000 to Susan G. Komen for the Cure when the mouse goes on sale mid-September (retail price: $39.95 USD). The money will be used for research grants and community
 outreach projects, 
reports the Microsoft Hardware blog. 
The mouse offers pretty great hardware specs, too, including BlueTrack technology, a tiny nano transceiver and customizable buttons. Windows 7 integration is supported as well. For more details, check out the full feature list

here on Microsoft.com while you wait for the pink one to arrive in stores and online.

</itunes:summary>
      <link>http://channel9.msdn.com/Blogs/coolstuff/A-Pink-Mouse-for-the-Cure</link>
      <pubDate>Fri, 20 Aug 2010 13:49:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Blogs/coolstuff/A-Pink-Mouse-for-the-Cure</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/previewImages/320/on10_55f559a5-b6c2-4b82-a664-5374372f8376.jpg" height="0" width="0"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/previewImages/85/on10_cb76d7da-3c8e-4450-b54b-3a8695ab36a7.jpg" height="64" width="85"/>      
      <dc:creator>Sarah Perez</dc:creator>
      <itunes:author>Sarah Perez</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Blogs/coolstuff/A-Pink-Mouse-for-the-Cure/RSS</wfw:commentRss>
      <category>Hardware</category>
      <category>Pink</category>
      <category>charity</category>
      <category>mouse</category>
    </item>
  <item>
      <title>RFID kit with .Net Support!</title>
      <description><![CDATA[
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10050070/7026.image_5F00_2.png"><img class="wlDisabledImage" title="image" border="0" alt="image" align="right" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10050070/8203.image_5F00_thumb.png" width="240" height="146"></a>Trossen
 Robotics has a pretty awesome <a href="http://www.trossenrobotics.com/p/RFID-experimenters-kit.aspx">
RFID kit with a RedBee RFID reader by Robotic Connections</a>.&nbsp; Here are a few specs from the reader.</p>
<ul>
<li>Supports all EM41xx family 125 kHz RFID tags </li><li>USB, XBee, and TTL Serial communication </li><li>Serial Communication Protocol and Shared Serial Devices Protocol (SSDP) </li><li>.NET programming API </li><li>Operates as a slave device to PC or microcontroller </li><li>Onboard programmable microcontroller </li><li>Xbee point to point </li><li>Xbee Mesh networking </li><li>3 power input options (Barrel Connector, USB, or Vcc) </li><li>4 Configurable I/O pins </li><li>Valid/Invalid Tag LED </li><li>Xbee Comm LED </li></ul>
<p>There is even a <a href="http://www.trossenrobotics.com/store/p/6483-Redbee-RFID-Wall-Plate.aspx">
drywall with a gangbox cover</a> even!&nbsp; You can bet we'll be releasing a project with one of these shortly.
</p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/hardware/RSS&WT.dl=0&WT.entryid=Entry:RSSView:bec44d0d704f4b6981789e7600c8c0d5">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/blog/RFID-kit-with-Net-Support</comments>
      <itunes:summary>
Trossen
 Robotics has a pretty awesome 
RFID kit with a RedBee RFID reader by Robotic Connections.&amp;nbsp; Here are a few specs from the reader.

Supports all EM41xx family 125 kHz RFID tags USB, XBee, and TTL Serial communication Serial Communication Protocol and Shared Serial Devices Protocol (SSDP) .NET programming API Operates as a slave device to PC or microcontroller Onboard programmable microcontroller Xbee point to point Xbee Mesh networking 3 power input options (Barrel Connector, USB, or Vcc) 4 Configurable I/O pins Valid/Invalid Tag LED Xbee Comm LED 
There is even a 
drywall with a gangbox cover even!&amp;nbsp; You can bet we&#39;ll be releasing a project with one of these shortly.

</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/blog/RFID-kit-with-Net-Support</link>
      <pubDate>Fri, 13 Aug 2010 22:49:19 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/blog/RFID-kit-with-Net-Support</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/10050070_100.jpg" height="75" width="100"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/10050070_220.jpg" height="165" width="220"/>      
      <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/RFID-kit-with-Net-Support/RSS</wfw:commentRss>
      <category>Hardware</category>
      <category>RFID</category>
      <category>c4fnews</category>
    </item>
  <item>
      <title>Building the Laser Graffiti System</title>
      <description><![CDATA[
<p>Last year, Clint Rutkas contacted me about building a project involving lasers, graffiti and code. When you get a request like that, you never decline, especially when lasers are involved. The project requirements sounded quite simple: create an application
 that can, using a laser pointer as a virtual spray can, draw virtual graffiti on the side of a building. It sounded a little daunting to me at first, but after it was broken up into small digestible pieces, the project ended up not being very complicated.</p>
<p>Below is the basic hardware setup of the <i>Laser Graffiti System</i>.</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10042066/clip_image00110.png"><img title="clip_image001[10]" border="0" alt="clip_image001[10]" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10042066/clip_image00110_thumb.png" width="500" height="349"></a></p>
<h3>Building a Laser Tracker Engine</h3>
<h4>Giving Sight to the Blind</h4>
<p>The very first thing that needed to be proven was the ability to track a laser point. The most obvious solution was to give our application some vision with a webcam. Since this was going to be a WPF application, I decided to use my open-source project,
<a href="http://wpfmediakit.codeplex.com/">WPF MediaKit</a>, which comes with a webcam control called the VideoCaptureElement.</p>
<p>At the time, VideoCaptureElement was not very robust, and it occurred to me that my control wasn't very useful beyond looking at your webcam in a WPF app! I needed a way to get high-performance access to every pixel of every frame the webcam spat out. This
 was a good time to add that ability and increase value in my project. Without getting into the gory details of DirectShow and p/invoke, I was able to add a hook to pass me the pixel buffer, where I would wrap it in a Bitmap class and raise an event for each
 frame.</p>
<p>The XAML required to get each video sample from the web camera.</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">MediaKit:VideoCaptureElement</span> <span class="attr">LoadedBehavior</span><span class="kwrd">=&quot;Play&quot;</span>
    <span class="attr">RenderOptions</span>.<span class="attr">BitmapScalingMode</span><span class="kwrd">=&quot;LowQuality&quot;</span>
    <span class="attr">UnloadedBehavior</span><span class="kwrd">=&quot;Manual&quot;</span>
    <span class="attr">DesiredPixelWidth</span><span class="kwrd">=&quot;{Binding DesiredPixelWidth}&quot;</span>
    <span class="attr">DesiredPixelHeight</span><span class="kwrd">=&quot;{Binding DesiredPixelHeight}&quot;</span>
    <span class="attr">VideoCaptureDevice</span><span class="kwrd">=&quot;{Binding SelectedItem, ElementName=videoCapDevices}&quot;</span>
    <span class="attr">FPS</span><span class="kwrd">=&quot;30&quot;</span>
    <span class="attr">EnableSampleGrabbing</span><span class="kwrd">=&quot;True&quot;</span>
    <span class="attr">NewVideoSample</span><span class="kwrd">=&quot;VideoCaptureElement_NewVideoSample&quot;</span>
    <span class="attr">Margin</span><span class="kwrd">=&quot;0&quot;</span>
    <span class="attr">x:Name</span><span class="kwrd">=&quot;videoElement&quot;</span>
    <span class="attr">Stretch</span><span class="kwrd">=&quot;Fill&quot;</span>
    <span class="attr">MinHeight</span><span class="kwrd">=&quot;380&quot;</span>
    <span class="attr">MinWidth</span><span class="kwrd">=&quot;500&quot;</span> <span class="kwrd">/&gt;</span></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>
<h4>Did I Mention Lasers?</h4>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10042066/clip_image0045.png"><img title="clip_image004[5]" border="0" alt="clip_image004[5]" align="right" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10042066/clip_image0045_thumb.png" width="240" height="156"></a></p>
<p>Now that I had the ability to look at every pixel sent to me, I needed to make sense of it all. In order to complete the project, we have to be able to find a laser point shined on a wall. The difficulty lies in the fact that a laser can be of varying size
 and color. For example, if you take two consecutive video frames with the same green laser point, you will find the point may slightly differ between the two. This is because we are dealing with analog data and slightly changing lighting conditions. Whatever
 algorithm we choose to find the laser must take this into account.</p>
<p>There are many advanced ways to use video analytics to find the laser pointer, but this project did have a deadline, and I wanted to keep it fun, so I went with a simple method, which allows a user to filter the video based off ranges of hue, saturation,
 and luminance. To do this, we make use of the <a href="http://code.google.com/p/aforge/">
AForge image processing library</a>. AForge is an open-source library that comes with tons of useful utilities for just what we want to do.</p>
<h4>Filtering pixels and counting blobs…</h4>
<p>As previously mentioned, we need to first filter the image based on hue, saturation, and luminance. Luckily, the AForge library comes with such a filter, so there is not much work to be done here:
</p>
<pre class="csharpcode"><span class="rem">/* This AForge class helps us filter out the pixels we do not want */</span>
var hsl = <span class="kwrd">new</span> HSLFiltering
{
    Hue = <span class="kwrd">new</span> IntRange(HueMinimum, HueMaximum),
    Saturation = <span class="kwrd">new</span> DoubleRange(SaturationMinimum, SaturationMaximum),
    Luminance = <span class="kwrd">new</span> DoubleRange(LuminanceMinimum, LuminanceMaximum)
};

var bitmapData = bitmap.LockBits(
    <span class="kwrd">new</span> Rectangle((<span class="kwrd">int</span>)targetSearchArea.X, 
        (<span class="kwrd">int</span>)targetSearchArea.Y, 
        (<span class="kwrd">int</span>)targetSearchArea.Width, 
        (<span class="kwrd">int</span>)targetSearchArea.Height),
    System.Drawing.Imaging.ImageLockMode.ReadWrite, 
    m_lastBitmap.PixelFormat);


<span class="rem">/* Apply the AForge filter.  Doing it &quot;in place&quot; is more efficient as</span>
<span class="rem"> * new bitmap does not have to be allocated and copied */</span>
hsl.ApplyInPlace(bitmapData);</pre>
<p>So, what needs to be done now that we have a filtered image showing only a laser dot? The answer: Blob counting! A blob, in the context of video analytics, is a set of pixels that are all touching, and AForge comes with a class ready to tackle that too!</p>
<p>The AForge blob counter takes in a gray-scale image for processing, and then returns all blobs found in the image. The information included on a blob includes the rectangular pixel area where the laser was found in the video frame. The center of that area
 should be the center of our laser. It's important to note that if the HSL filter is improperly calibrated, we will get an overabundance of blobs and there will accordingly be no way we can tell if it is the laser point or not.</p>
<pre class="csharpcode"><span class="rem">/* Create an initialize our blob counter */</span>
var blobsCounter = <span class="kwrd">new</span> BlobCounter
    {
       FilterBlobs = <span class="kwrd">true</span>,
       ObjectsOrder = ObjectsOrder.Size,
       MinHeight = BlobMinimumHeight,
       MinWidth = BlobMinimumWidth,
       MaxWidth = 25,
       MaxHeight = 25
    };

<span class="rem">/* We first let the blob counter process our image */</span>
blobsCounter.ProcessImage(grayImage);

<span class="rem">/* Retrieve a list of blobs that were found */</span>
Blob[] blobs = blobsCounter.GetObjects(grayImage);</pre>
<p>The early laser tracking prototype. We can literally have it track anything, based off color.<a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10042066/clip_image0085.jpg"><img title="clip_image008[5]" border="0" alt="clip_image008[5]" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10042066/clip_image0085_thumb.jpg" width="275" height="397"></a></p>
<h3>Building the Laser Graffiti Application</h3>
<h4>Our Rocket Engine Needs a Rocket</h4>
<p>At this point, I had a working proof of concept and a laser tracker. What I needed now was an application to use it. You know, the laser-graffiti
<i>application</i>.</p>
<p>There are many ways to construct a WPF application and one pattern that's been getting a little bit of traction is MVVM. I chose to make a composite application using Prism and MVVM. Prism is a great guidance library pack for making composite WPF applications
 with tons of tools to help in common scenarios.</p>
<h4><i>Composite</i> What? Huh?</h4>
<p>When developing applications, usually of the larger variety, things can become complex. Complexity turns into a mess. A mess turns into time investment. Time investment turns into money. The more money spent, the fewer bonuses you will receive. To make sure
 we get that end-of-year pay raise, we want to control complexity from the get-go by making our code and our internal systems
<i>loosely coupled</i>. A composite application is just a collection of loosely coupled systems that is composited at runtime.</p>
<p>The advantages of a composite application are:</p>
<p>· Components can be developed independently</p>
<p>· Components can be swapped out more easily than if they were tightly coupled</p>
<p>· The application remains extendable, meaning you can more easily extend your application</p>
<p>· Maintenance is much clearer with less chance of breaking other components</p>
<p>· Unit testing is more feasible</p>
<h4>Composite Application Entrails</h4>
<p>There are many, many excellent resources about Prism available on the internet, so I'd rather not compete with them. I did, however, want to cover the basics, and at least how I've used it within the Laser Graffiti application.</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10042066/clip_image0095.png"><img title="clip_image009[5]" border="0" alt="clip_image009[5]" align="right" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10042066/clip_image0095_thumb.png" width="230" height="146"></a></p>
<p><b>The Shell Assembly</b> – This contains the main entry point of the application and the initial or main UI container for the application. Before anything else, this assembly will initialize something called a bootstrapper. The bootstrapper simply does
 any pre-initialization that needs to be done before initializing the rest of the application.</p>
<p><b>Module Assemblies</b> – Each module assembly can be considered a <i>component</i>. The bootstrapper initializes each component and then the module spins up any application
<i>services</i> and adds any user interface to the shell. For instance, the MediaKit module handles the capture of the video and the AForgeModule handles the vision routines.</p>
<p><b>The Infrastructure Assembly</b> – This contains any base classes, well known/shared interfaces or general infrastructure code. Simply put, most if not all modules will have reference to this.</p>
<h3>Rendering the Graffiti</h3>
<p>I needed a way to draw the graffiti to a projector. Overall, this will be accomplished by drawing the graffiti to a window. The window will be set to
<i>maximized</i> with no border. I also needed to write the code to draw the graffiti. Initially, I just used the WPF InkCanvas control, but I found it wasn't well tuned for what I wanted to do with it. So, I decided XNA would give the most performance and
 flexibility with the level of effects desired for drawing graffiti.</p>
<p>I had never really done any XNA development, so this project is certainly not built using best practices. The important part to notice is that the project is more or less a regular XNA application with the exception that the executable is added as a library
 reference. This is because we instantiate the XNA from our WPF application's process. The following snippet of code accomplishes this:</p>
<pre class="csharpcode"><span class="kwrd">private</span> <span class="kwrd">void</span> ShowGraffitiWall(<span class="kwrd">bool</span> show)
{
    <span class="kwrd">if</span> (m_game != <span class="kwrd">null</span>)
        m_game.Exit();

    <span class="kwrd">if</span> (!show) 
        <span class="kwrd">return</span>;

    var t = <span class="kwrd">new</span> Thread((ThreadStart)<span class="kwrd">delegate</span>
    {
        m_game = <span class="kwrd">new</span> XnaGraffitiGame();
        m_game.SetScreen(m_lastScreen);
        m_game.Effect = m_lastGraffitiEffect;
        m_game.Run();
        m_game.Dispose();
    });

    t.SetApartmentState(ApartmentState.STA);
    t.IsBackground = <span class="kwrd">true</span>;
    t.Start();
}</pre>
<p>We instantiate the XNA window this way because it allows our WPF code to send the XNA messages of where the laser pointer was detected.</p>
<h4>Drawing with the GPU</h4>
<p>A blanket statement about XNA is that it is a drawing API. XNA applications can get quite complex when you add in things like 3D or shaders, but for this article, I'm only covering the required simple stuff. That said, I do make the assumption that the reader
 has had at least a few hours of XNA experience.</p>
<p>Our primary goal is to render virtual graffiti using XNA. This means we need to be able to draw a line. I started by creating a PNG file that would act as a “brush.” In XNA, these 2D graphics are also known as sprites. The brush sprite looks like this:</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10042066/clip_image0115.png"><img title="clip_image011[5]" border="0" alt="clip_image011[5]" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10042066/clip_image0115_thumb.png" width="273" height="264"></a></p>
<p>Now we can use XNA's SpriteBatch class to draw our brush. The first problem I had, though, was that most XNA tutorials show drawing the sprite, continue, clear the screen, draw the sprite, continue, etc. I needed to retain previous brush strokes, which means
 drawing onto an intermediate drawing surface (RenderTarget2D), then drawing that to the screen.</p>
<p>The next issue I had was that the line I was trying to draw was very broken. See, the laser detection code runs at a maximum 30 FPS (the limit of my web camera). If I moved the laser fast enough, the screen would just look like a bunch of random points were
 being drawn. I had to move the laser very slowly to make it appear like a line. I remember reading an
<a href="http://www.cynergysystems.com/blogs/page/rickbarraza?entry=advanced_render_techniques_with_writeablebitmaps">
excellent article</a> detailing a project by Rick Barraza, which led me to <a href="http://www.cs.unc.edu/~mcmillan/comp136/Lecture6/Lines.html">
a link to some popular algorithms</a> for creating a line where your input is two, 2D points.</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10042066/clip_image0125.gif"><img title="clip_image012[5]" border="0" alt="clip_image012[5]" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10042066/clip_image0125_thumb.gif" width="298" height="146"></a></p>
<p>So, drawing a line required only a simple, two-step process of A) getting a new point from laser detection, and B) drawing a line from last_laser_coordinate to current_laser_coordinate. After putting that together, we can now produce some useful looking
 graffiti!</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10042066/clip_image0144.jpg"><img title="clip_image014[4]" border="0" alt="clip_image014[4]" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10042066/clip_image0144_thumb.jpg" width="401" height="302"></a></p>
<h4>Adding Crazy Graffiti Effects</h4>
<p>The excitement of drawing simple lines in XNA wore off pretty fast. After all, the GPU is capable of some pretty amazing things. What about drawing with fire? Fire isn't boring:</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10042066/clip_image0164.jpg"><img title="clip_image016[4]" border="0" alt="clip_image016[4]" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10042066/clip_image0164_thumb.jpg" width="455" height="281"></a></p>
<p>The fire effect is done using a method slightly similar to the solid color sprite method described earlier. However, since it uses a particle system, the fire effect is much more complex. Each particle has its own shader to control position and color. With
 the time constraints of this project, I had modified code from this <a href="http://creators.xna.com/en-US/sample/particle3d">
XNA tutorial</a>. There weren't many changes from the tutorial's code, but a big hurdle was that the particles took 3D coordinates instead of the 2D coordinates I needed to draw the graffiti. I found a small snippet to handle that, though I was informed by
 other XNA gurus that there is an easier way to accomplish this. If you are curious, this is what it looks like (and it's not for the faint of heart):</p>
<pre class="csharpcode"><span class="kwrd">protected</span> Vector3 ScreenPointToVector3(Point coords)
{
    Matrix viewMatrix = 
        Matrix.CreateTranslation(0, -25, 0) *
        Matrix.CreateRotationY(
            MathHelper.ToRadians(CameraRotation)) *
        Matrix.CreateRotationX(
            MathHelper.ToRadians(CameraArc)) *
        Matrix.CreateLookAt(
            <span class="kwrd">new</span> Vector3(0, 0, -CameraDistance),
            <span class="kwrd">new</span> Vector3(0, 0, 0), 
            Vector3.Up);

    <span class="kwrd">float</span> aspectRatio = 
        (<span class="kwrd">float</span>)m_game.GraphicsDevice.Viewport.Width /
            (<span class="kwrd">float</span>)m_game.GraphicsDevice.Viewport.Height;

    Matrix projectionMatrix = 
        Matrix.CreatePerspectiveFieldOfView(
            MathHelper.PiOver4,
            aspectRatio,
            1, 10000);

    Vector3 nearScreenPoint = <span class="kwrd">new</span> Vector3(coords.X, coords.Y, 0);
    Vector3 farScreenPoint = <span class="kwrd">new</span> Vector3(coords.X, coords.Y, 1);
    Vector3 nearWorldPoint = 
        m_game.GraphicsDevice.Viewport.Unproject(
            nearScreenPoint, 
            projectionMatrix, 
            viewMatrix, 
            Matrix.Identity);
    Vector3 farWorldPoint = 
        m_game.GraphicsDevice.Viewport.Unproject(
            farScreenPoint, 
            projectionMatrix, 
            viewMatrix, 
            Matrix.Identity);

    Vector3 direction = farWorldPoint - nearWorldPoint;

    <span class="kwrd">float</span> zFactor = -nearWorldPoint.Z / direction.Z;
    Vector3 zeroWorldPoint = nearWorldPoint &#43; direction * zFactor;

    <span class="kwrd">return</span> zeroWorldPoint;
}</pre>
<h3>The End Result</h3>
<p>Web-camera device selection:</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10042066/clip_image0204.jpg"><img title="clip_image020[4]" border="0" alt="clip_image020[4]" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10042066/clip_image0204_thumb.jpg" width="426" height="350"></a></p>
<p>Fine tuning the laser detection:</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10042066/clip_image0224.jpg"><img title="clip_image022[4]" border="0" alt="clip_image022[4]" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/10042066/clip_image0224_thumb.jpg" width="461" height="385"></a></p>
<h3>About Jeremiah</h3>
<p><a href="http://jmorrill.hjtcentral.com/">Jeremiah Morrill</a> is a software developer and 2010 MVP living in Las Vegas, Nevada. He owns a software company called HJT,
<a title="http://www.hjtcentral.com/" href="http://www.hjtcentral.com/">http://www.hjtcentral.com/</a>, with a couple partners. There he focuses on multimedia and rich user interfaces with WPF and Silverlight. Jeremiah spends a lot of his free time learning,
 listening and helping others in the online development communities.&nbsp; </p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/hardware/RSS&WT.dl=0&WT.entryid=Entry:RSSView:1516d45ea42c4399be2b9e7600c8f5c7">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Building-the-Laser-Graffiti-System</comments>
      <itunes:summary>
Last year, Clint Rutkas contacted me about building a project involving lasers, graffiti and code. When you get a request like that, you never decline, especially when lasers are involved. The project requirements sounded quite simple: create an application
 that can, using a laser pointer as a virtual spray can, draw virtual graffiti on the side of a building. It sounded a little daunting to me at first, but after it was broken up into small digestible pieces, the project ended up not being very complicated.
Below is the basic hardware setup of the Laser Graffiti System.

Building a Laser Tracker Engine
Giving Sight to the Blind
The very first thing that needed to be proven was the ability to track a laser point. The most obvious solution was to give our application some vision with a webcam. Since this was going to be a WPF application, I decided to use my open-source project,
WPF MediaKit, which comes with a webcam control called the VideoCaptureElement.
At the time, VideoCaptureElement was not very robust, and it occurred to me that my control wasn&#39;t very useful beyond looking at your webcam in a WPF app! I needed a way to get high-performance access to every pixel of every frame the webcam spat out. This
 was a good time to add that ability and increase value in my project. Without getting into the gory details of DirectShow and p/invoke, I was able to add a hook to pass me the pixel buffer, where I would wrap it in a Bitmap class and raise an event for each
 frame.
The XAML required to get each video sample from the web camera.
&amp;lt;MediaKit:VideoCaptureElement LoadedBehavior=&amp;quot;Play&amp;quot;
    RenderOptions.BitmapScalingMode=&amp;quot;LowQuality&amp;quot;
    UnloadedBehavior=&amp;quot;Manual&amp;quot;
    DesiredPixelWidth=&amp;quot;{Binding DesiredPixelWidth}&amp;quot;
    DesiredPixelHeight=&amp;quot;{Binding DesiredPixelHeight}&amp;quot;
    VideoCaptureDevice=&amp;quot;{Binding SelectedItem, ElementName=videoCapDevices}&amp;quot;
    FPS=&amp;quot;30&amp;quot;
    EnableSampleGrabbing=&amp;quot;True&amp;quo</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Building-the-Laser-Graffiti-System</link>
      <pubDate>Fri, 23 Jul 2010 19:54:04 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Building-the-Laser-Graffiti-System</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/10042066_100.jpg" height="75" width="100"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/10042066_220.jpg" height="165" width="220"/>      
      <dc:creator>Jeremiah Morrill</dc:creator>
      <itunes:author>Jeremiah Morrill</itunes:author>
      <slash:comments>2</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Building-the-Laser-Graffiti-System/RSS</wfw:commentRss>
      <category>Hardware</category>
      <category>PDC</category>
      <category>WPF</category>
      <category>XNA</category>
      <category>Lasers</category>
      <category>audiovideo</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/hardware/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 url="http://ecn.channel9.msdn.com/o9/c4f/images/10033092_220.jpg" height="165" width="220"/>      
      <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>Hardware</category>
      <category>c4fnews</category>
      <category>NETMF</category>
      <category>.NET Microframework</category>
      <category>embedded systems</category>
    </item>
  <item>
      <title>Wiimote Virtual Room Designer</title>
      <description><![CDATA[<p>Last year I had to earn my M.Sc. in engineering and decided to make up my own final graduation project, a part of which is this very cheap design tool. Check out the video below!</p>
<div class="wlWriterEditableSmartContent" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:b1eca4a2-e1cb-4db5-9ad3-7d44836b7766">
<div></div>
</div>
<p><a href="http://www.brianpeek.com/">Brian Peek</a>, author of <a href="http://wiimotelib.codeplex.com/">
WiimoteLib</a>, saw the video and asked me to write a practical article on how to create something like this yourself. Let’s get started!</p>
<h3>Hardware Setup</h3>
<p>To get this working, you only need a digital projector, a Wiimote, a few cheap components, and, of course, a computer. The latter won’t need a lot of horsepower; I’m even able to run it on my $300 netbook with an acceptable framerate! Let’s take a look at
 how to prepare these items before we get working on the software.</p>
<h4><a href="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-45-39-metablogapi/4035.clip_5F00_image002_5F00_2.jpg"><img height="330" width="454" src="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-45-39-metablogapi/7587.clip_5F00_image002_5F00_thumb.jpg" alt="clip_image002" border="0" title="clip_image002"></a></h4>
<h4>Creating the tabletop display</h4>
<p>First, let’s create the poor man’s version of the <a href="http://www.microsoft.com/surface/">
Microsoft Surface</a> table. If you are like me and aren’t burdened by a fat bank account,
<a>just take some ugly photo-in-a-frame off the wall and lay its protective sheet of glass down on a table-without-tabletop.
</a>Trust me: as long as you don’t sit on it, it works like a charm! Now go to a nearby grocery store and buy some white fat-free paper. Tape it on top of the glass to create your
<a href="http://en.wikipedia.org/wiki/Do_it_yourself">DIY</a> projection screen. You may also tape it to the bottom side, but in my experience it will start hanging down after some time has passed. As shown in the video, use an inclined mirror and a projector
 connected to your computer. Now you have your own backlit tabletop display!</p>
<h4>Making the display interactive</h4>
<p>Now comes the trick: making the display interactive. Enter the brilliant Nintendo Wiimote. Simply put it in a stable position facing the mirror on top of the projector, preferably right above the lens. The Wiimote contains a high-performance camera that
 can simultaneously track up to 4 infrared light sources. Now, if you <a href="http://www.instructables.com/id/Wiimote-Whiteboard-IR-Pen/">
fashion a simple infrared pen</a> (or do it the easy way and <a href="http://www.shop.irpensonline.com/">
buy one online</a>), the Wiimote can track its position all across the display!</p>
<h4>Fashioning the point-of-view device</h4>
<p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-45-39-metablogapi/8267.clip_5F00_image004_5F00_2.jpg"><img height="139" width="244" src="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-45-39-metablogapi/4061.clip_5F00_image004_5F00_thumb.jpg" alt="clip_image004" border="0" title="clip_image004"></a><a href="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-45-39-metablogapi/2311.clip_5F00_image006_5F00_2.jpg"><img height="139" width="244" src="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-45-39-metablogapi/5037.clip_5F00_image006_5F00_thumb.jpg" alt="clip_image006" border="0" title="clip_image006"></a></p>
<p>We’re not finished yet, because for this project we’re also going to need a point-of-view device. This device is nothing more than a small glass turned upside down, with two infrared LEDs in its bottom as shown in the photo. Building this is similar to building
 2 IR pens.&nbsp; Make sure the small glass is large enough to fit an AAA battery in there! It’s best to also incorporate a pushbutton switch right between the LEDs, so that they only emit light when the point-of-view is slightly pressed onto the tabletop display.
 It may be a bit tricky to get the button position exactly right, but I’m sure you’ll manage with some perseverance.</p>
<h4>Connecting to the Wiimote</h4>
<p>Now it’s time to connect to the Wiimote. For your convenience, I’ve copy-pasted
<a href="http://blogs.msdn.com/coding4fun/archive/2007/03/14/1879033.aspx">Brian’s short manual</a> here:</p>
<p>1. Start up your Bluetooth software and have it search for a device.</p>
<p>2. Hold down the 1 and 2 buttons on the Wiimote. You should see the LEDs at the bottom start flashing. Do not let go of these buttons until this procedure is complete.</p>
<p>3. Wiimotes should show up in the list of devices found as Nintendo RVL-CNT-01. If it's not there, start over and try again.</p>
<p>4. Click Next to move your way through the wizard. If at any point you are asked to enter a security code or PIN, leave the number blank or click Skip. Do not enter a number.</p>
<p>5. You may be asked which service to use from the Wiimote. Select the keyboard/mouse/HID service if prompted (you should only see one service available).</p>
<p>6. Finish the wizard.</p>
<p>If you can’t get it to connect, you might try using a <a href="http://wiibrew.org/wiki/List_of_Working_Bluetooth_Devices">
Wiimote compatible Bluetooth adapter and stack</a>.</p>
<h3>Inserting Some Third-Party Code</h3>
<p>With the hardware all set up, we’ll continue to the software. Make sure you have installed a (free) version of
<a href="http://www.microsoft.com/express/download/">Visual Studio with C#</a>, and
<a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=7D70D6ED-1EDD-4852-9883-9A33C0AD8FEE&amp;displaylang=en">
Microsoft XNA Game Studio</a> version 3.0 or higher. XNA integrates neatly into Visual Studio and we’ll use it as an easy way to harness your graphic card’s 3D power. Our home designer relies heavily on work done by the open-source community, so let’s start
 by inserting these components first.</p>
<h4>XNA Surface As A WinForms Control</h4>
<p>We’re going to use a hack that allows us to use XNA-controlled surfaces on as many forms as we like. There’s no need to know exactly how the hack works—we’ll just use it! Therefore, instead of starting a normal XNA project within Visual Studio, we’ll make
 use of a sample project that has been posted online at the XNA Creators club. <a href="http://creators.xna.com/en-US/sample/winforms_series1">
Download</a> and open it. If you run the solution you just downloaded, you’ll see two separate XNA-powered surfaces (the left one contains some text and the right one is a spinning triangle).</p>
<p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-45-39-metablogapi/3301.clip_5F00_image008_5F00_2.jpg"><img height="343" width="454" src="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-45-39-metablogapi/8171.clip_5F00_image008_5F00_thumb.jpg" alt="clip_image008" border="0" title="clip_image008"></a></p>
<p>Both are standard Controls, but why is that important? Because now we can easily create multiple WinForms, each containing its own XNA surface—one for the blueprint and the other for the 3D perspective view! Later on, it will look like this:</p>
<p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-45-39-metablogapi/5852.clip_5F00_image010_5F00_2.jpg"><img height="280" width="454" src="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-45-39-metablogapi/5875.clip_5F00_image010_5F00_thumb.jpg" alt="clip_image010" border="0" title="clip_image010"></a></p>
<h4>A Little Housekeeping</h4>
<p>Since we don’t want to do any more work than necessary, we’ll start our project from the this XNA control example project. Let’s do a little housekeeping to keep everything neat and tidy. First, make sure you delete
<b>all</b> controls present on the MainForm. In the solution explorer, rename “SpinningTriangleControl.cs” and “SpriteFontControl.cs” to “BluePrintControl.cs” and “_3Dcontrol.cs” respectively, and move all files except “MainForm.cs” to a new directory called
 “Controls”. By the way, this would also be an appropriate moment to rename both Control classes. We’ll change their functionality later on. Your solution explorer should now look like this:</p>
<p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-45-39-metablogapi/0576.clip_5F00_image012_5F00_2.jpg"><img height="255" width="238" src="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-45-39-metablogapi/6840.clip_5F00_image012_5F00_thumb.jpg" alt="clip_image012" border="0" title="clip_image012"></a></p>
<p>It may also be smart to change the name of our project from “WinFormsGraphicsDevice” to “HomeDesigner” or something (I actually call it “DualDesign”, but choose whatever you like).</p>
<h4>Enabling whiteboard functionality</h4>
<p>Time to honor the Wiimote community’s all-time great: Johnny Lee Chung! He’s the guy that used
<a href="http://johnnylee.net/projects/wii/">Brian’s managed Wiimote library</a> to build some amazing applications. We’ll tweak his Whiteboard application to make our blueprint interactive. Check out his video:</p>
<div class="wlWriterEditableSmartContent" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:cf9e7619-b5f3-4878-a5d5-31f9b07d1e01">
<div></div>
</div>
<p>I downloaded the source code for <a href="http://johnnylee.net/projects/wii/">
Johnny’s Whiteboard application</a> and then updated to support version 1.7 of WiimoteLib, which is more compatible than the version Johnny used.</p>
<p>Now, by adding the following code to the Click event handler, let’s add a button on our MainForm that starts Chung’s app inside our own:</p>
<p><b>C# </b></p>
<div id="codeSnippetWrapper">
<div id="codeSnippet">
<pre><span>try</span></pre>
<pre>{</pre>
<pre>    wiimoteForm = <span>new</span> WiimoteWhiteboard.WiimoteWhiteboardForm();</pre>
<pre>    wiimoteForm.Visible = <span>true</span>;</pre>
<pre>}</pre>
<pre><span>catch</span> (Exception x)</pre>
<pre>{</pre>
<pre>    System.Console.Out.WriteLine(<span>&quot;Exception: &quot;</span> &#43; x.Message);</pre>
<pre>}</pre>
</div>
</div>
<p>&nbsp;</p>
<p>Make sure you have established a Bluetooth connection to the Wiimote before running the code. What Lee’s app basically does is emulate a standard mouse. The operating system (and thus our blueprint control) won’t see the light pen but will receive standard
 MouseDown, MouseMove, and MouseUp events. This is very convenient, because we don’t need the Wiimote to be connected while debugging: we can simply draw on the form with our mouse since our blueprint won’t be able to tell the difference!</p>
<h4>Pretty Lines</h4>
<p>There’s one last component to insert before we can really start. In the demo, you saw the big, fat white lines I drew on the blueprint. These pretty RoundLines have been coded by Microsoft’s Mike Manders and released into the public domain. Download them
 and insert the code into our project. Make sure to manually copy all .xnb files to our project’s “bin\ … \debug\Content” directory using the Windows Explorer (<b>not</b> the Solution Explorer), otherwise your code might not run.</p>
<h3>Coding the BluePrintControl</h3>
<p>We’ve got all the third-party code we need, so now it’s time to get our hands dirty. However, the entire solution is pretty comprehensive and much of the code is trivial. Therefore, we won’t be getting into every nitty-gritty detail; instead, I will single
 out some of the interesting parts. A lot of the code is XNA-related. If you want to read more about it, “<a href="http://oreilly.com/catalog/9780596521967">Learning XNA 3.0</a>” (O’Reilly) is an excellent starting point, as are
<a href="http://www.riemers.net/">Riemer’s online tutorials</a>.</p>
<h4>XNA Basics</h4>
<p>In order to understand the code, you’ll need a grasp of some of the <b>very</b> basics of XNA Game Studio. XNA Game Studio is a comprehensive set of tools that allows the development of entire games, but we’ll only use it for basic visualization. XNA games
 run in a continuous loop, basically drawing frames to the viewport at as fast a rate as possible. A lot of things happen behind the scenes in each frame, but the most important part is the Draw() method in which all the drawing is done. Here, we draw all elements
 to the frame buffer, at the end of which the buffer <a>“empties” </a>to the viewport and becomes visible to the user.</p>
<h4>Drawing to the GraphicsDevice</h4>
<p>Because we were lazy and started with a pre-coded demonstration control, we’ll have to remove the unnecessary code in “BluePrintControl.cs” (the drawing of the spinning triangle). After cleaning up, make sure our Draw() method looks like this:</p>
<p><b>C# <br>
</b></p>
<div id="codeSnippetWrapper">
<div id="codeSnippet">
<pre><span>/// &lt;summary&gt;</span></pre>
<pre><span>/// Draws the control.</span></pre>
<pre><span>/// &lt;/summary&gt;</span></pre>
<pre><span>protected</span> <span>override</span> <span>void</span> Draw()</pre>
<pre>{</pre>
<pre>    <span>// clears the graphicsdevice</span></pre>
<pre>    GraphicsDevice.Clear(defaultBackgroundColor);</pre>
<pre>&nbsp;</pre>
<pre>    <span>// draws all elements to the viewport</span></pre>
<pre>    <span>this</span>.DrawWalls();</pre>
<pre>    <span>this</span>.DrawAllSprites();</pre>
<pre>    <span>this</span>.DrawObjectHandles();</pre>
<pre>    <span>this</span>.DrawButtons();</pre>
<pre>}</pre>
</div>
</div>
<p>&nbsp;</p>
<p>The GraphicsDevice is an abstraction of the graphics card and is what we draw to. The Clear() statement clears the entire frame buffer to our default background color on top of which we can draw. I used “Color.DarkBlue” but you can use anything you want
 here as long as it’s blue (otherwise you should have differently named the BluePrintControl class <img src='http://ecn.channel9.msdn.com/o9/content/images/emoticons/emotion-1.gif?v=c9' alt='Smiley' /> ). Next, we call four methods that draw all elements to the blueprint.</p>
<h5>Drawing the Walls</h5>
<p>Let’s take a look at the DrawWalls() method:</p>
<p><b>C# <br>
</b></p>
<div id="codeSnippetWrapper">
<div id="codeSnippet">
<pre><span>private</span> <span>void</span> DrawWalls()</pre>
<pre>        {</pre>
<pre>            <span>// Draw lines</span></pre>
<pre>            roundLineManager.Draw(</pre>
<pre>                ConvertWallListToRoundLineList(wallList), <span>// converts Walls to RoundLines</span></pre>
<pre>                defaultWallThickness,</pre>
<pre>                Color.White,</pre>
<pre>                camera.View * camera.Projection, <span>// 4x4 matrix to that allows XNA to map 3D coordinates to screen coordinates</span></pre>
<pre>                1f,</pre>
<pre>                roundLineManager.TechniqueNames[defaultTechnique]</pre>
<pre>                );</pre>
<pre>        }</pre>
</div>
</div>
<p>&nbsp;</p>
<p>This is where we make use of the RoundLine component. The RoundLineManager.Draw() method takes a list of RoundLine objects and
<a>draws them to </a>the graphicsdevice in one go. Internally, we store the walls in our own format, so the ConvertWallListToRoundLineList method does exactly what its name implies.</p>
<p>The fourth argument, camera.View * camera.Projection, tells XNA how to map 3D coordinates to the viewport. The View matrix contains information regarding the position and orientation of the camera, and the Projection matrix can be seen as a matrix describing
 the lens. Since we want the blueprint to be displayed without any distortion, we previously defined the projection matrix to be orthographic:</p>
<p><b>C# </b></p>
<div id="codeSnippetWrapper">
<div id="codeSnippet">
<pre>camera.Projection = Matrix.CreateOrthographic(<span>this</span>.Width, <span>this</span>.Height, 0, 100);</pre>
</div>
</div>
<p>To get an idea of what an orthographic camera is, imagine a real camera that is hanging 500 feet above our blueprint. In order to see the blueprint, it has to really zoom in. In this case, everything becomes very flat and undistorted—basically, it has become
 an orthogonal camera.</p>
<h5>Drawing the Objects Using Sprites</h5>
<p>The walls we just drew to the screen are flat lines floating in a true 3D space. However, with XNA it is also possible to just draw to the viewport coordinates; no 3D to 2D mapping has to be done in this case.</p>
<p>XNA handles this in a very convenient way using Sprites. A sprite is a bitmap drawn into a rectangle that you have specified in advance. It offers a very high performance since your graphics card does all the hard work! The following code draws the furniture
 to the blueprint using sprites:</p>
<p><b>C# <br>
</b></p>
<div id="codeSnippetWrapper">
<div id="codeSnippet">
<pre><span>private</span> <span>void</span> DrawAllSprites()</pre>
<pre>        {</pre>
<pre>            spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.BackToFront, SaveStateMode.SaveState);</pre>
<pre>&nbsp;</pre>
<pre>            <span>foreach</span> (ImageTextureObject tempObject <span>in</span> objectList)</pre>
<pre>            {</pre>
<pre>                Rectangle tempBoundingRectangle = <span>this</span>.GetBoundingScreenRectangleFromObject(tempObject);</pre>
<pre>&nbsp;</pre>
<pre>                spriteBatch.Draw(</pre>
<pre>                    tempObject.Texture, <span>// the bitmap</span></pre>
<pre>                    tempBoundingRectangle, <span>// the bounding rectangle (not yet rotated)</span></pre>
<pre>                    <span>null</span>,</pre>
<pre>                    Color.White,</pre>
<pre>                    -tempObject.Rotation.Y, <span>// determines the rotation of the sprite</span></pre>
<pre>                    <span>new</span> Vector2((<span>float</span>)tempObject.Texture.Width / 2, (<span>float</span>)tempObject.Texture.Height / 2),</pre>
<pre>                    SpriteEffects.None,</pre>
<pre>                    1</pre>
<pre>                );</pre>
<pre>            }</pre>
<pre>&nbsp;</pre>
<pre>            spriteBatch.End();</pre>
<pre>        }</pre>
</div>
</div>
<p>Note that we created an ImageTextureObject such that it contains all information about a piece of furniture: position, orientation, and size in addition to the image of that particular piece of furniture. Now, we loop through the entire list of furniture
 and use the SpriteBatch.Draw() method draw to the graphicsdevice. Note that any SpriteBatch.Draw() call has to occur within the SpriteBatch.Begin() and .End() statements. This prepares the graphics device to receive the data and allows some optimization to
 occur after a group of sprites has been received. We draw the handles that appear (see image
<a>below</a>) when clicking an object in exactly the same manner: </p>
<p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-45-39-metablogapi/2816.clip_5F00_image016_5F00_2.jpg"><img height="287" width="454" src="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-45-39-metablogapi/4073.clip_5F00_image016_5F00_thumb.jpg" alt="clip_image016" border="0" title="clip_image016"></a></p>
<h4>Receiving User Input</h4>
<p>Now, how do we let the user draw lines and drag furniture around? First, we’ll have to subscribe to the MouseDown, MouseMove, and MouseUp events:</p>
<p><b>C#</b></p>
<div id="codeSnippetWrapper">
<div id="codeSnippet">
<pre>&nbsp;</pre>
<pre><span>this</span>.MouseDown &#43;= <span>new</span> System.Windows.Forms.MouseEventHandler(<span>this</span>.bluePrintControl_MouseDown);</pre>
<pre><span>this</span>.MouseMove &#43;= <span>new</span> System.Windows.Forms.MouseEventHandler(<span>this</span>.bluePrintControl_MouseMove);</pre>
<pre><span>this</span>.MouseUp &#43;= <span>new</span> System.Windows.Forms.MouseEventHandler(<span>this</span>.bluePrintControl_MouseUp);</pre>
</div>
</div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h5>Recognizing Button Clicks</h5>
<p>When receiving a MouseDown event, we’ll first check if there is a button pressed. We do this using the ButtonPressed() method:</p>
<p><b>C# <br>
</b></p>
<div id="codeSnippetWrapper">
<div id="codeSnippet">
<pre><span>private</span> <span>int</span> ButtonPressed(System.Drawing.Point point)</pre>
<pre>{</pre>
<pre>    <span>foreach</span> (ButtonSprite button <span>in</span> buttonList)</pre>
<pre>    {</pre>
<pre>        <span>if</span> (button.Clicked(<span>new</span> Point(point.X, point.Y))) <span>return</span> buttonList.IndexOf(button);</pre>
<pre>    }</pre>
<pre>    <span>return</span> -1;</pre>
<pre>}</pre>
</div>
</div>
<p>&nbsp;</p>
<p>Each Rectangle object comes with a nice Intersects() method that allows us to check if two Rectangles well…intersect J. We exploit this by constructing a new 1x1 rectangle at the cursor location:</p>
<p><b>C# </b></p>
<div id="codeSnippetWrapper">
<div id="codeSnippet">
<pre><span>public</span> <span>bool</span> Clicked(Point location)</pre>
<pre>{</pre>
<pre>    <span>return</span> <span>this</span>.TargetRectangle.Intersects(<span>new</span> Rectangle(location.X, location.Y, 1, 1));</pre>
<pre>}</pre>
</div>
</div>
<p>&nbsp;</p>
<p>If true, the index of the button is returned by the ButtonPressed() method <a>
so</a> that we know what button was pressed. <a>In a similar way, we check if an object was clicked.</a></p>
<h5>Drawing Walls with the Light Pen</h5>
<p>If it turns out that there is no button, object, or handle at the MouseDown location, we assume that the user wants to draw a wall. The location sent along with the MouseDown event is in screen coordinates (in pixels); however, in order to draw a wall we
 need it in “world coordinates” (in meters). For that we employ the following method:</p>
<p><b>C# <br>
</b></p>
<div id="codeSnippetWrapper">
<div id="codeSnippet">
<pre><span>private</span> Vector3 ConvertLocalMouseToWorldCoors(System.Drawing.Point <span>value</span>)</pre>
<pre>{</pre>
<pre>    Vector3 worldCoors = <span>new</span> Vector3(</pre>
<pre>        <span>this</span>.camera.Target.X - <span>this</span>.camera.Width / 2 </pre>
<pre>            &#43; (<span>this</span>.camera.Width / (<span>float</span>)<span>this</span>.ClientSize.Width) * <span>value</span>.X,</pre>
<pre>        0,</pre>
<pre>        -<span>this</span>.camera.Target.Y - <span>this</span>.camera.Height / 2 </pre>
<pre>            &#43; (<span>this</span>.camera.Height / (<span>float</span>)<span>this</span>.ClientSize.Height) * <span>value</span>.Y</pre>
<pre>        );</pre>
<pre>    <span>return</span> worldCoors;</pre>
<pre>}</pre>
</div>
</div>
<p>&nbsp;</p>
<p>This method is called a lot throughout the code, and there is also a method that converts world coordinates to screen coordinates:
<a>ConvertWorldCoorsToLocalCoors</a>().</p>
<h5>Reading the Point-of-View Device</h5>
<p>Now comes some good old hackin’! The whiteboard component – the one that uses the light pen to emulate a mouse – only “sees” one infrared dot and ignores any others it may detect. We are going to tweak his code so that it does not discard these dots but
 instead passes these on to the BluePrintControl in the form of events, so that we can also track the point-of-view.</p>
<p>Whenever the Wiimote state changes (this may be up to 100 times per second), the mouse emulator will receive an event fired by Brian Peeks WiimoteLib. Instead of immediately passing the first IR dot to the emulator, we’ll tap into the process. No matter
 how many dots are visible, we’re gonna make sure that the emulator gets only the one dot it needs to “impersonate” a mouse.</p>
<p>Here’s how to tap into the emulator code. Open WiimoteWhiteboardForm.cs from the solution explorer and change the first part of the event listener as follows:</p>
<p><b>C# <br>
</b></p>
<div id="codeSnippetWrapper">
<div id="codeSnippet">
<pre><span>void</span> wm_OnWiimoteChanged(<span>object</span> sender, WiimoteChangedEventArgs args)</pre>
<pre>{</pre>
<pre>&nbsp;</pre>
<pre>    mut.WaitOne();</pre>
<pre>&nbsp;</pre>
<pre>    <span>// wiimote state with the real data</span></pre>
<pre>    WiimoteState wsReal = args.WiimoteState;</pre>
<pre>&nbsp;</pre>
<pre>    <span>// gets which IR point is mouse pointer and which are POV</span></pre>
<pre>    <span>int</span> mouseIR = <span>new</span> <span>int</span>();</pre>
<pre>    <span>int</span>[] POVIR = <span>new</span> <span>int</span>[2];</pre>
<pre>    <span>int</span>[,] rawIRCoors = <span>new</span> <span>int</span>[5, 2];</pre>
<pre>&nbsp;</pre>
<pre>    <span>// will contain the raw IR coors in array form for easy access</span></pre>
<pre>    <span>this</span>.IdentifyIRpoints(wsReal, <span>ref</span> rawIRCoors, <span>ref</span> mouseIR, <span>ref</span> POVIR);</pre>
<pre>&nbsp;</pre>
<pre> <span>// REST OF CODE OMITTED</span></pre>
<pre>}</pre>
</div>
</div>
<p>&nbsp;</p>
<p>This means that the “hard” work of recognizing point-of-view and light pen is done in the IdentifyIRpoints() method. Now imagine that there are three dots visible. We know that one belongs to the light pen and the others to the point of view. In the case
 of three visible points we’ll assume that:</p>
<p>1. the two points that are closest to each other belong to the point of view and</p>
<p>2. the remaining dot belongs to the light pen</p>
<p>We are able to make these assumptions since there is only one light pen and one point of view. Because the Wiimote can track up to four points simultaneously, it’s also possible to add another light pen. In this case, the algorithm becomes a little bit more
 complicated (and probably also less robust) but with some commonsense reasoning it should also be possible. I’ll leave that up to you!</p>
<p><b>C# <br>
</b></p>
<div id="codeSnippetWrapper">
<div id="codeSnippet">
<pre><span>/// &lt;summary&gt;</span></pre>
<pre><span>/// Recognizes which IR points are mouse point and POV points and returns</span></pre>
<pre><span>/// &lt;/summary&gt;</span></pre>
<pre><span>/// &lt;param name=&quot;ws&quot;&gt;WiimoteState object&lt;/param&gt;</span></pre>
<pre><span>/// &lt;param name=&quot;rawIRCoors&quot;&gt;Returns the IR-points in a raw form. Needs an initialized int[5,2]&lt;/param&gt;</span></pre>
<pre><span>/// &lt;param name=&quot;mouseIR&quot;&gt;Returns the index of the IR mouse dot or 0 if not found&lt;/param&gt;</span></pre>
<pre><span>/// &lt;param name=&quot;POVIR&quot;&gt;Returns the indices of the IR POV dots or null if not found&lt;/param&gt;</span></pre>
<pre><span>void</span> IdentifyIRpoints(WiimoteState ws, <span>ref</span> <span>int</span>[,] rawIRCoors, <span>ref</span> <span>int</span> mouseIR, <span>ref</span> <span>int</span>[] POVIR)</pre>
<pre>{</pre>
<pre>    <span>// Holds all IR points. Note: @index 0 the default values are stored if no point is found.</span></pre>
<pre>    <span>// This is needed for faking Chung's implementation.</span></pre>
<pre>    <span>int</span>[] IRState = <span>new</span> <span>int</span>[5];</pre>
<pre>    IRState[0] = 0;</pre>
<pre>    IRState[1]=Convert.ToInt16(ws.IRState.IRSensors[0].Found);</pre>
<pre>&nbsp;</pre>
<pre>    <span>// Contains the raw coors in a bidimensional array</span></pre>
<pre>    rawIRCoors[0, 0] = 1023; <span>// default value when not found</span></pre>
<pre>    rawIRCoors[0, 1] = 1023; <span>// default value when not found</span></pre>
<pre>    rawIRCoors[1, 0] = ws.IRState.IRSensors[0].RawPosition.X;</pre>
<pre>    rawIRCoors[1, 1] = ws.IRState.IRSensors[0].RawPosition.Y;</pre>
<pre>&nbsp;</pre>
<pre>    <span>// Calculates the total number of points seen</span></pre>
<pre>    <span>int</span> noOfPointsSeen = 0;</pre>
<pre>    <span>for</span> (<span>int</span> i = 1; i &lt;= 4; i&#43;&#43;) {</pre>
<pre>        noOfPointsSeen &#43;= IRState[i];</pre>
<pre>    }</pre>
<pre>&nbsp;</pre>
<pre>    <span>// Executes recognition of which dot is what based on</span></pre>
<pre>    <span>// the amount of dots seen</span></pre>
<pre>    <span>switch</span> (noOfPointsSeen)</pre>
<pre>    {</pre>
<pre>        <span>// No points seen</span></pre>
<pre>        <span>case</span> 0:</pre>
<pre>            mouseIR = 0;</pre>
<pre>            POVIR = <span>null</span>;</pre>
<pre>            <span>break</span>;</pre>
<pre>&nbsp;</pre>
<pre>        <span>// Only mouse seen</span></pre>
<pre>        <span>case</span> 1:</pre>
<pre>            <span>// passes the dotnumber containing the mouse</span></pre>
<pre>            <span>for</span>(<span>int</span> i=1; i&lt;=4; i&#43;&#43;) {</pre>
<pre>                <span>if</span>(IRState[i]==1)</pre>
<pre>                {</pre>
<pre>                    mouseIR=i;</pre>
<pre>                    <span>break</span>; <span>//exit for loop</span></pre>
<pre>                }</pre>
<pre>            }</pre>
<pre>            POVIR = <span>null</span>;</pre>
<pre>            <span>break</span>;</pre>
<pre>&nbsp;</pre>
<pre>        <span>// Only POV seen</span></pre>
<pre>        <span>case</span> 2:</pre>
<pre>            mouseIR = 0;</pre>
<pre>            POVIR = <span>new</span> <span>int</span>[2];</pre>
<pre>&nbsp;</pre>
<pre>            <span>// passes the dotnumbers containing the IR dots</span></pre>
<pre>            </pre>
<pre>            <span>int</span> tempIndex = 0;</pre>
<pre>            <span>for</span> (<span>int</span> i = 1; i &lt;= 4; i&#43;&#43;)</pre>
<pre>            {</pre>
<pre>&nbsp;</pre>
<pre>                <span>if</span> ((IRState[i] == 1) &amp;&amp; (tempIndex&lt;=1))</pre>
<pre>                {</pre>
<pre>                    POVIR[tempIndex] = i;</pre>
<pre>                    tempIndex&#43;&#43;;</pre>
<pre>                }</pre>
<pre>            }</pre>
<pre>            <span>break</span>;</pre>
<pre>&nbsp;</pre>
<pre>        <span>// determine which dots are closest. There are the POV dots</span></pre>
<pre>        <span>// (so I do not remember points but analyze each frame individually</span></pre>
<pre>&nbsp;</pre>
<pre>        <span>// Three dots seen</span></pre>
<pre>        <span>case</span> 3:</pre>
<pre>            <span>double</span> smallestDistanceSoFar = 10000000;</pre>
<pre>            <span>double</span> currentDistance;</pre>
<pre>            <span>int</span>[] closestTwoPoints = <span>new</span> <span>int</span>[2];</pre>
<pre>            POVIR = <span>new</span> <span>int</span>[2];</pre>
<pre>&nbsp;</pre>
<pre>            <span>// Algorithm to calculate the points the smallest distance apart.</span></pre>
<pre>            <span>// Only checks the first 3 points (which are all visible).</span></pre>
<pre>            <span>for</span> (<span>int</span> i = 1; i &lt;= 3; i&#43;&#43;)</pre>
<pre>            {</pre>
<pre>                <span>for</span> (<span>int</span> j = i &#43; 1; j &lt;= 3; j&#43;&#43;)</pre>
<pre>                {</pre>
<pre>                    <span>// Calculates the distance squared between points (using Pythagoras)</span></pre>
<pre>                    currentDistance =</pre>
<pre>                        (rawIRCoors[i, 0] - rawIRCoors[j, 0]) * (rawIRCoors[i, 0] - rawIRCoors[j, 0]) &#43;</pre>
<pre>                        (rawIRCoors[i, 1] - rawIRCoors[j, 1]) * (rawIRCoors[i, 1] - rawIRCoors[j, 1]);</pre>
<pre>&nbsp;</pre>
<pre>                    <span>// If this distance is smaller than the previously smallest distance,</span></pre>
<pre>                    <span>// the smallest distance so far is updated, as well as the array</span></pre>
<pre>                    <span>// containing the indices of this pair</span></pre>
<pre>                    <span>if</span> (currentDistance &lt; smallestDistanceSoFar)</pre>
<pre>                    {</pre>
<pre>                        smallestDistanceSoFar = currentDistance;</pre>
<pre>                        POVIR[0] = i; POVIR[1] = j;</pre>
<pre>                    }</pre>
<pre>&nbsp;</pre>
<pre>                    </pre>
<pre>                }</pre>
<pre>            }</pre>
<pre>            </pre>
<pre>            <span>// The mouse index is returned (can be calculated easily</span></pre>
<pre>            <span>// based on the fact that the the sum of all three indexes must be 0)</span></pre>
<pre>            mouseIR = 6 - (POVIR[0] &#43; POVIR[1]);</pre>
<pre>            <span>break</span>;</pre>
<pre>&nbsp;</pre>
<pre>        <span>// Four dots seen: not supported so no output</span></pre>
<pre>        <span>case</span> 4:</pre>
<pre>            mouseIR = 0;</pre>
<pre>            POVIR = <span>null</span>;</pre>
<pre>            <span>break</span>;</pre>
<pre>    }</pre>
<pre>}</pre>
</div>
</div>
<p><a>Consequently</a>, we create a new WiimoteState object only if a light pen is seen. This stripped-down state is then passed on to the emulator code, effectively filtering the information received by the emulator. An event with the point-of-view data is
 received by the BluePrintControl, which subsequently updates the camera position. I’ll leave checking for that in the source files to you.</p>
<h4>Inserting Images</h4>
<p>At the bottom of the BluePrintControl, there is a strip with images that can be inserted as objects. It is a so-called FlowLayoutPanel (found in the System.Windows.Forms namespace) and displays all .png images (“contained” in PictureBoxes) in a certain directory.
 Make sure you set the right directory by modifying the defaultImageDirectory private variable in the blueprint
<b>form</b> (not the control).</p>
<p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-45-39-metablogapi/1830.clip_5F00_image018_5F00_2.jpg"><img height="332" width="454" src="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-45-39-metablogapi/4314.clip_5F00_image018_5F00_thumb.jpg" alt="clip_image018" border="0" title="clip_image018"></a></p>
<p>I won’t run you through the code to add images to the FlowLayoutPanel because it is quite obvious. However, it’s worth noting that we’ll use a System.IO.FileSystemWatcher to update the list:</p>
<p><b>C# <br>
</b></p>
<div id="codeSnippetWrapper">
<div id="codeSnippet">
<pre><span>private</span> <span>bool</span> SetUpFileSystemWatcher()</pre>
<pre>{</pre>
<pre>    <span>try</span></pre>
<pre>    {</pre>
<pre>        fileSystemWatcher = <span>new</span> System.IO.FileSystemWatcher(defaultImageDirectory, defaultSupportedImageMasks);</pre>
<pre>    }</pre>
<pre>    <span>catch</span> (Exception ex)</pre>
<pre>    {</pre>
<pre>        System.Console.Out.WriteLine(<span>&quot;Error: {0}&quot;</span>, ex.Message);</pre>
<pre>        <span>return</span> <span>false</span>;</pre>
<pre>    }</pre>
<pre>&nbsp;</pre>
<pre>    <span>this</span>.fileSystemWatcher.Changed &#43;= <span>new</span> FileSystemEventHandler(fileSystemWatcher_Changed);</pre>
<pre>    <span>this</span>.fileSystemWatcher.EnableRaisingEvents = <span>true</span>;</pre>
<pre>&nbsp;</pre>
<pre>    <span>return</span> <span>true</span>;</pre>
<pre>}</pre>
</div>
</div>
<h5>Drag ‘n’ drop</h5>
<p>The drag procedure is initiated when the user clicks an image:</p>
<p><b>C# </b></p>
<div id="codeSnippetWrapper">
<div id="codeSnippet">
<pre><span>// initiates the drag procedure</span></pre>
<pre><span>private</span> <span>void</span> pictureBox_MouseDown(<span>object</span> sender, MouseEventArgs e)</pre>
<pre>{</pre>
<pre>    PictureBox pictureBox = (PictureBox)sender;</pre>
<pre>    pictureBox.DoDragDrop(pictureBox.Tag, DragDropEffects.Copy);</pre>
<pre>} </pre>
</div>
</div>
<p>&nbsp;</p>
<p>Now, we’ll have to subscribe to the DragEnter (when the cursor enters the control while dragging is in progress) in the BluePrintControl and DragDrop (when the user drops an object by releasing the button) events:</p>
<p><strong>C#</strong></p>
<div id="codeSnippetWrapper">
<div id="codeSnippet">
<pre><span>// Subscribes to (drag and) drop user actions</span></pre>
<pre><span>this</span>.DragEnter &#43;= <span>new</span> DragEventHandler(BluePrintControl_DragEnter);</pre>
<pre><span>this</span>.DragDrop &#43;= <span>new</span> DragEventHandler(BluePrintControl_DragDrop);</pre>
</div>
</div>
<p>In the method handling the DragDrop event, we can receive the object containing information regarding the image using the GetData method:</p>
<p><strong>C#</strong></p>
<div id="codeSnippetWrapper">
<div id="codeSnippet">
<pre><span>// called on a drop (as in drag &amp; drop)</span></pre>
<pre><span>void</span> BluePrintControl_DragDrop(<span>object</span> sender, DragEventArgs e)</pre>
<pre>{</pre>
<pre>    ImageObject tempImageObject = </pre>
<pre>        (ImageObject)e.Data.GetData(<span>&quot;DualDesign.Data_containers.ImageObject&quot;</span>);</pre>
<pre>    <span>// code below omitted</span></pre>
<pre>}</pre>
</div>
</div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h3>Coding the 3D Control</h3>
<h3><a href="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-45-39-metablogapi/8524.clip_5F00_image020_5F00_2.jpg"><img height="282" width="454" src="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-45-39-metablogapi/8524.clip_5F00_image020_5F00_thumb.jpg" alt="clip_image020" border="0" title="clip_image020"></a></h3>
<h4>Thread-safety</h4>
<p>We’ve come a long way by programming the blueprint. Since the 3D view doesn’t have to accept direct user input – all that is handled by the blueprint – all it has to do is display the home as-is. There are three types of data that the 3Dcontrol has to receive:</p>
<p>1. The walls</p>
<p>2. The objects</p>
<p>3. The location and orientation of the point of view</p>
<p>This introduces some problems related thread-safety: the 3D control and blueprint run asynchronously on separate threads. Imagine that the 3dview is reading an object that is just in the process of being deleted; in this case data corruption may occur and
 the application may crash with some seemingly unrelated error code.</p>
<p>We’ll use two different methods to avoid these issues in order to assess performance. The objects<b>
</b>are stored in a shared static class that uses <b>locking</b> to prevent data corruption. On the other hand, the walls and the point of view location object are sent in the form of events that have a
<b>copy</b> of the data attached. Now I hear you ask: why use two different methods? That’s because I wanted to assess the performance of both methods, which, by the way, turned out to be similar.</p>
<p>Here, I’ll focus on only the objects because the locking procedure they employ is cleaner and easier to implement. If I’d have to do the project again, I wouldn’t even bother using the data-exchange-through-events method.</p>
<h4>Locking the object list</h4>
<p>First, we’ll have to go back to the BluePrintControl for a moment. Internally, this control keeps track of the list containing all objects that have been placed on the blueprint. Also, we’ll have to make sure we can access this data from the 3D Control by
 implementing a static property in the BluePrintControl. In order to make it thread-safe, we’ll lock access to the list: simultaneous reads are possible, though simultaneous reads/writes are not.</p>
<p>ReaderWriterLockSlim, a class written by a programmer who was unhappy by the low-performing ReaderWriterLock class included in .NET, is what we are going to use for locking. This slimmed down version performed so well that Microsoft eventually bought it
 and included it in subsequent versions of .NET, and so we are now reaping the fruits J :</p>
<p><strong>C#</strong></p>
<div id="codeSnippetWrapper">
<div id="codeSnippet">
<pre><span>static</span> ReaderWriterLockSlim texturedObjectListLock = <span>new</span> ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);</pre>
<pre>&nbsp;</pre>
<pre><span>static</span> List&lt;ImageTextureObject&gt; objectList = <span>new</span> List&lt;ImageTextureObject&gt;();</pre>
<pre>&nbsp;</pre>
<pre><span>/// &lt;summary&gt;</span></pre>
<pre><span>/// Contains all ImageTextureObjects</span></pre>
<pre><span>/// &lt;/summary&gt;</span></pre>
<pre><span>public</span> <span>static</span> List&lt;ImageTextureObject&gt; ObjectList</pre>
<pre>{</pre>
<pre>    get </pre>
<pre>    {</pre>
<pre>        texturedObjectListLock.EnterReadLock();</pre>
<pre>        <span>try</span> { <span>return</span> BluePrintControl.objectList; }</pre>
<pre>        <span>finally</span> { texturedObjectListLock.ExitReadLock(); }</pre>
<pre>    }</pre>
<pre>    <span>private</span> set</pre>
<pre>    {</pre>
<pre>        texturedObjectListLock.EnterWriteLock();</pre>
<pre>        <span>try</span> { BluePrintControl.objectList = <span>value</span>; }</pre>
<pre>        <span>finally</span> { texturedObjectListLock.ExitWriteLock(); }</pre>
<pre>    }</pre>
<pre>}</pre>
</div>
</div>
<p>Unfortunately, however, we haven’t achieved complete thread-safety: <a>access to the list is locked, but not to the objects themselves!
</a>For this reason the access to properties of the ImageTextureObjects need locking too:</p>
<div id="codeSnippetWrapper">
<div id="codeSnippet">
<pre><span>public</span> Vector3 Position</pre>
<pre>{</pre>
<pre>    get </pre>
<pre>    {</pre>
<pre>        objectLock.EnterReadLock();</pre>
<pre>        <span>try</span> { <span>return</span> position; }</pre>
<pre>        <span>finally</span> { objectLock.ExitReadLock(); }</pre>
<pre>    }</pre>
<pre>    set </pre>
<pre>    {</pre>
<pre>        objectLock.EnterWriteLock();</pre>
<pre>        <span>try</span></pre>
<pre>        {</pre>
<pre>            dataChanged = <span>true</span>;</pre>
<pre>            position = <span>value</span>; </pre>
<pre>        }</pre>
<pre>        <span>finally</span> { objectLock.ExitWriteLock(); }</pre>
<pre>    }</pre>
<pre>}</pre>
</div>
</div>
<p>&nbsp;</p>
<p>Always use a try/finally combination to ensure that the writelock is released in all cases, no matter what.</p>
<h4>Drawing to the GraphicsDevice</h4>
<p>Now that we have reliable access to all the data we need, let’s actually draw our house in 3D! Of course, we rely heavily on XNA to get this done. This is what the Draw() method looks like:</p>
<p><strong>C#</strong></p>
<div id="codeSnippetWrapper">
<div id="codeSnippet">
<pre><span>protected</span> <span>override</span> <span>void</span> Draw()</pre>
<pre>{</pre>
<pre>    <span>// sets up device for new rendering round</span></pre>
<pre>    <span>this</span>.GraphicsDevice.Clear(Color.White);</pre>
<pre>    <span>this</span>.GraphicsDevice.RenderState.CullMode = CullMode.CullClockwiseFace; <span>// hides clockwise faces</span></pre>
<pre>    basicEffect.World = Matrix.Identity;</pre>
<pre>    basicEffect.View = camera.View;</pre>
<pre>    basicEffect.Projection = camera.Projection;</pre>
<pre>    <span>// draws elements to screen</span></pre>
<pre>    <span>this</span>.drawWalls();</pre>
<pre>    <span>this</span>.drawSkySphere();</pre>
<pre>    <span>this</span>.drawImageObjects(); <span>// these should be drawn last due to transparency</span></pre>
<pre>}</pre>
</div>
</div>
<p>A graphics cards works by rendering large amounts of triangle surfaces. Often, you only need to draw one side of the triangle, as is the case for us: since our walls have thickness, one side of each triangle is facing “into” the wall itself and will never
 be seen from that side. Therefore, we use the GraphicsDevice.RenderState.CullMode to tell the graphics card to not even bother drawing the triangle when the camera is on the “wrong” side of the triangle. This enhances performance, t<a>hough not so much in
 our case since our scenes are very simple, but it is still a small effort to tell the graphics card this.</a></p>
<p>Three essential matrices are also set: the Projection matrix determines the camera’s lens, the View matrix the camera’s position, and the World matrix the position of the drawn objects.</p>
<p>Looking at the drawWalls() method, the walls are drawn using the userfriendly DrawUserIndexedPrimitives method. We basically give two lists. The first contains a set of coordinates in 3D space (the corners of the walls) and the second contains a list of
 integers that refer to coordinates in the other list. In this way, we can easily construct a series of triangles while only specifying the coordinates of the corners once:</p>
<p><strong>C#</strong></p>
<div id="codeSnippetWrapper">
<div id="codeSnippet">
<pre>GraphicsDevice.DrawUserIndexedPrimitives&lt;VertexPositionNormalColor&gt;</pre>
<pre>(</pre>
<pre>    PrimitiveType.TriangleList,</pre>
<pre>    <span>this</span>.All3DWallVertices, 0,</pre>
<pre>    <span>this</span>.All3DWallVertices.Length,</pre>
<pre>    <span>this</span>.All3DWallIndices, 0,</pre>
<pre>    <span>this</span>.All3DWallIndices.Length / 3</pre>
<pre>);</pre>
</div>
</div>
<p>&nbsp;</p>
<p>The images are displayed by drawing textured triangles. In the DrawImageObjectTexturedFaces() method, we use the VertexPositionTexture custom vertex format to this end. This not only defines the texture itself, but also defines texture coordinates: these
 specify which part of the texture should be drawn onto a triangle:</p>
<p><strong>C#</strong></p>
<div id="codeSnippetWrapper">
<div id="codeSnippet">
<pre><span>this</span>.GraphicsDevice.DrawUserIndexedPrimitives&lt;VertexPositionTexture&gt;</pre>
<pre>(</pre>
<pre>    PrimitiveType.TriangleList,</pre>
<pre>    imageTextureObject.TexturedFaceVertices,</pre>
<pre>    0, 4,</pre>
<pre>    imageTextureObject.TexturedFaceIndices,</pre>
<pre>    0, 2</pre>
<pre>);</pre>
</div>
</div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h3>Conclusion</h3>
<p>The code is quite comprehensive, so I’ve only been able to explain a few parts and ideas. If you want to try this out, the download link for the source code is at the top of the article! And be creative! Why not create a smart Google Earth mash-up in which
 you can use point-of-view to navigate intuitively though a landscape? Surely there are also some innovative games you can think of. Be inspired by the Nintendo DS games that make use of a similar dual display layout!</p>
<h3>About The Author</h3>
<p>Thijs Brilleman has a Master in Mechanical Engineering but has always been interested in fun, tangible machines that are somewhere in-between computers and mechanical machines. Currently employed at the University of Twente, he designs new interaction methods
 that can be used in collaborative design. You can reach him at: <a href="mailto:thijsbrilleman@gmail.com">
thijsbrilleman@gmail.com</a></p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/hardware/RSS&WT.dl=0&WT.entryid=Entry:RSSView:9de71ce9bf41467a8c6c9e7600c91c81">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Wiimote-Virtual-Room-Designer</comments>
      <itunes:summary>Last year I had to earn my M.Sc. in engineering and decided to make up my own final graduation project, a part of which is this very cheap design tool. Check out the video below!



Brian Peek, author of 
WiimoteLib, saw the video and asked me to write a practical article on how to create something like this yourself. Let’s get started!
Hardware Setup
To get this working, you only need a digital projector, a Wiimote, a few cheap components, and, of course, a computer. The latter won’t need a lot of horsepower; I’m even able to run it on my $300 netbook with an acceptable framerate! Let’s take a look at
 how to prepare these items before we get working on the software.

Creating the tabletop display
First, let’s create the poor man’s version of the 
Microsoft Surface table. If you are like me and aren’t burdened by a fat bank account,
just take some ugly photo-in-a-frame off the wall and lay its protective sheet of glass down on a table-without-tabletop.
Trust me: as long as you don’t sit on it, it works like a charm! Now go to a nearby grocery store and buy some white fat-free paper. Tape it on top of the glass to create your
DIY projection screen. You may also tape it to the bottom side, but in my experience it will start hanging down after some time has passed. As shown in the video, use an inclined mirror and a projector
 connected to your computer. Now you have your own backlit tabletop display!
Making the display interactive
Now comes the trick: making the display interactive. Enter the brilliant Nintendo Wiimote. Simply put it in a stable position facing the mirror on top of the projector, preferably right above the lens. The Wiimote contains a high-performance camera that
 can simultaneously track up to 4 infrared light sources. Now, if you 
fashion a simple infrared pen (or do it the easy way and 
buy one online), the Wiimote can track its position all across the display!
Fashioning the point-of-view device

We’re not finished yet, because for this project w</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Wiimote-Virtual-Room-Designer</link>
      <pubDate>Mon, 21 Jun 2010 15:00:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Wiimote-Virtual-Room-Designer</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/10026326_100.jpg" height="75" width="100"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/10026326_220.jpg" height="165" width="220"/>      
      <dc:creator>Thijis Brilleman</dc:creator>
      <itunes:author>Thijis Brilleman</itunes:author>
      <slash:comments>2</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Wiimote-Virtual-Room-Designer/RSS</wfw:commentRss>
      <category>Hardware</category>
      <category>XNA</category>
      <category>wiimote</category>
    </item>
  <item>
      <title>Sharing Your Windows Experience Index with WEI Share</title>
      <description><![CDATA[<a shape="rect" href="http://windowsteamblog.com/members/Brandon-LeBlanc/" shape="rect">Brandon LeBlanc</a>&nbsp;from&nbsp;<a shape="rect" href="http://windowsteamblog.com/" shape="rect">The Windows Blog</a> and I talk about using the Azure service WEIShare.net
 to capture scores from your Windows Experience Index.  <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/hardware/RSS&WT.dl=0&WT.entryid=Entry:RSSView:dc5c4fb48c8e4c659f1e9dea00a208e8">]]></description>
      <comments>http://channel9.msdn.com/Blogs/LarryLarsen/Sharing-Your-Windows-Experience-Index-with-WEI-Share</comments>
      <itunes:summary>Brandon LeBlanc&amp;nbsp;from&amp;nbsp;The Windows Blog and I talk about using the Azure service WEIShare.net
 to capture scores from your Windows Experience Index. </itunes:summary>
      <itunes:duration>364</itunes:duration>
      <link>http://channel9.msdn.com/Blogs/LarryLarsen/Sharing-Your-Windows-Experience-Index-with-WEI-Share</link>
      <pubDate>Wed, 16 Jun 2010 20:23:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Blogs/LarryLarsen/Sharing-Your-Windows-Experience-Index-with-WEI-Share</guid>
      <media:thumbnail url="http://media.ch9.ms/ch9/08E8/DC5C4FB4-8C8E-4C65-9F1E-9DEA00A208E8/WEIShare3_100_ch9.jpg" height="75" width="100"/>
      <media:thumbnail url="http://media.ch9.ms/ch9/08E8/DC5C4FB4-8C8E-4C65-9F1E-9DEA00A208E8/WEIShare3_220_ch9.jpg" height="165" width="220"/>
      <media:thumbnail url="http://media.ch9.ms/ch9/08E8/DC5C4FB4-8C8E-4C65-9F1E-9DEA00A208E8/WEIShare3_512_ch9.jpg" height="384" width="512"/>
      <media:thumbnail url="http://media.ch9.ms/ch9/08E8/DC5C4FB4-8C8E-4C65-9F1E-9DEA00A208E8/WEIShare3_custom_ch9.jpg" height="384" width="512"/>
      <media:group>
        <media:content url="http://media.ch9.ms/ch9/08E8/DC5C4FB4-8C8E-4C65-9F1E-9DEA00A208E8/WEIShare3_2MB_ch9.wmv" expression="full" duration="364" fileSize="79769577" type="video/x-ms-wmv" medium="video"/>
        <media:content url="http://media.ch9.ms/ch9/08E8/DC5C4FB4-8C8E-4C65-9F1E-9DEA00A208E8/WEIShare3_ch9.mp3" expression="full" duration="364" fileSize="2917089" type="audio/mp3" medium="audio"/>
        <media:content url="http://media.ch9.ms/ch9/08E8/DC5C4FB4-8C8E-4C65-9F1E-9DEA00A208E8/WEIShare3_ch9.wma" expression="full" duration="364" fileSize="2954905" type="audio/x-ms-wma" medium="audio"/>
        <media:content url="http://media.ch9.ms/ch9/08E8/DC5C4FB4-8C8E-4C65-9F1E-9DEA00A208E8/WEIShare3_ch9.wmv" expression="full" duration="364" fileSize="45831615" type="video/x-ms-wmv" medium="video"/>
        <media:content url="http://media.ch9.ms/ch9/08E8/DC5C4FB4-8C8E-4C65-9F1E-9DEA00A208E8/WEIShare3_high_ch9.mp4" expression="full" duration="364" fileSize="119233021" type="video/mp4" medium="video"/>
        <media:content url="http://media.ch9.ms/ch9/08E8/DC5C4FB4-8C8E-4C65-9F1E-9DEA00A208E8/WEIShare3_low_ch9.mp4" expression="full" duration="364" fileSize="22231234" type="video/mp4" medium="video"/>
        <media:content url="http://media.ch9.ms/ch9/08E8/DC5C4FB4-8C8E-4C65-9F1E-9DEA00A208E8/WEIShare3_Zune_ch9.wmv" expression="full" duration="364" fileSize="41447670" type="video/x-ms-wmv" medium="video"/>
        <media:content url="http://smooth.ch9.ms/ch9/08E8/DC5C4FB4-8C8E-4C65-9F1E-9DEA00A208E8/WEIShare3.ism/manifest" expression="full" duration="364" fileSize="6006" type="video/x-ms-wmv" medium="video"/>
      </media:group>      
      <enclosure url="http://media.ch9.ms/ch9/08E8/DC5C4FB4-8C8E-4C65-9F1E-9DEA00A208E8/WEIShare3_ch9.wmv" length="45831615" type="video/x-ms-wmv"/>
      <dc:creator>Larry Larsen</dc:creator>
      <itunes:author>Larry Larsen</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Blogs/LarryLarsen/Sharing-Your-Windows-Experience-Index-with-WEI-Share/RSS</wfw:commentRss>
      <category>Azure</category>
      <category>Hardware</category>
      <category>Silverlight</category>
      <category>SQL Azure</category>
      <category>Windows 7</category>
      <category>WPF</category>
    </item>
  <item>
      <title>WEI Share: Share your Windows 7 Experience Index</title>
      <description><![CDATA[<a shape="rect" href="http://www.weishare.net/" shape="rect">WEI Share</a>&nbsp;(&quot;We Share&quot;) is a&nbsp;<a shape="rect" href="http://www.coding4fun.com/" shape="rect">Coding4Fun</a> code sample that takes your&nbsp;<a shape="rect" href="http://windows.microsoft.com/en-us/windows7/products/features/windows-experience-index" shape="rect">Windows Experience Index</a> score and shares it with the world (anonymously) to an Azure website with a Silverlight front end and lets you post your WEI score to Facebook for bragging rights. <br><br>Why would you want to share your WEI score with the world? First, this gives us a place to compare WEI scores across a wide range of hardware and even see how many touch points a multitouch computer may give you. Second, a computer's speed is&nbsp;dependent on the efficiency of the drivers. Sometimes WEI scores go up, sometimes they go down. This will allow you to judge the score that various versions of a driver may give you. <br><br>You can run WEI Share at <a shape="rect" href="http://www.weishare.net/" shape="rect">www.WEIShare.net</a> and download the source code at <a shape="rect" href="http://weishare.codeplex.com/" shape="rect">WEIShare.codeplex.com</a>&nbsp;(coming later this week).  <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/hardware/RSS&WT.dl=0&WT.entryid=Entry:RSSView:d99ed630e02a4ff1b35f9e1001029e35">]]></description>
      <comments>http://channel9.msdn.com/Blogs/LarryLarsen/WEI-Share-Share-your-Windows-7-Experience-Index</comments>
      <itunes:summary>WEI Share&amp;nbsp;(&amp;quot;We Share&amp;quot;) is a&amp;nbsp;Coding4Fun code sample that takes your&amp;nbsp;Windows Experience Index score and shares it with the world (anonymously) to an Azure website with a Silverlight front end and lets you post your WEI score to Facebook for bragging rights. Why would you want to share your WEI score with the world? First, this gives us a place to compare WEI scores across a wide range of hardware and even see how many touch points a multitouch computer may give you. Second, a computer&#39;s speed is&amp;nbsp;dependent on the efficiency of the drivers. Sometimes WEI scores go up, sometimes they go down. This will allow you to judge the score that various versions of a driver may give you. You can run WEI Share at www.WEIShare.net and download the source code at WEIShare.codeplex.com&amp;nbsp;(coming later this week). </itunes:summary>
      <itunes:duration>197</itunes:duration>
      <link>http://channel9.msdn.com/Blogs/LarryLarsen/WEI-Share-Share-your-Windows-7-Experience-Index</link>
      <pubDate>Thu, 10 Jun 2010 17:56:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Blogs/LarryLarsen/WEI-Share-Share-your-Windows-7-Experience-Index</guid>
      <media:group>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/4/9/5/4/5/5/weishare3_ch9.mp3" expression="full" duration="197" fileSize="1578156" type="audio/mp3" medium="audio"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/4/9/5/4/5/5/weishare3_ch9.mp4" expression="full" duration="197" fileSize="25997970" type="video/mp4" medium="video"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/4/9/5/4/5/5/weishare3_ch9.mp4" expression="full" duration="197" fileSize="25997970" type="video/x-ms-wmv" medium="video"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/4/9/5/4/5/5/weishare3_ch9.wma" expression="full" duration="197" fileSize="1600101" type="audio/x-ms-wma" medium="audio"/>
      </media:group>      
      <enclosure url="http://ecn.channel9.msdn.com/o9/ch9/4/9/5/4/5/5/weishare3_ch9.mp4" length="25997970" type="video/x-ms-wmv"/>
      <dc:creator>Larry Larsen</dc:creator>
      <itunes:author>Larry Larsen</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Blogs/LarryLarsen/WEI-Share-Share-your-Windows-7-Experience-Index/RSS</wfw:commentRss>
      <category>Azure</category>
      <category>DIY</category>
      <category>Hardware</category>
      <category>Silverlight 3</category>
      <category>SQL Azure</category>
      <category>Windows 7</category>
      <category>WPF</category>
    </item>
  <item>
      <title>WEI Share: Share your Windows 7 Experience Index</title>
      <description><![CDATA[<a shape="rect" href="http://www.weishare.net" shape="rect">WEI Share</a>&nbsp;(&quot;We Share&quot;) is a&nbsp;<a shape="rect" href="http://www.coding4fun.com" shape="rect">Coding4Fun</a> code sample that takes your&nbsp;<a shape="rect" href="http://windows.microsoft.com/en-us/windows7/products/features/windows-experience-index" shape="rect">Windows
 Experience Index</a> score and shares it with the world (anonymously) to an Azure website with a Silverlight front end and lets you post your WEI score to Facebook for bragging rights.
<br /><br />Why would you want to share your WEI score with the world? First, this gives us a place to compare WEI scores across a wide range of hardware and even see how many touch points a multitouch computer may give you. Second, a computer's speed is&nbsp;dependent on the
 efficiency of the drivers. Sometimes WEI scores go up, sometimes they go down. This will allow you to judge the score that various versions of a driver may give you.
<br /><br />You can run WEI Share at <a shape="rect" href="http://www.WEIShare.net" shape="rect">
www.WEIShare.net</a> and download the source code at <a shape="rect" href="http://WEIShare.codeplex.com" shape="rect">
WEIShare.codeplex.com</a>&nbsp;(coming later this week).  <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/hardware/RSS&WT.dl=0&WT.entryid=Entry:RSSView:81ebaed1318d47deb8419dea00a20ee2">]]></description>
      <comments>http://channel9.msdn.com/Blogs/LarryLarsen/WEI-Share-Share-you-Windows-7-Experience-Index</comments>
      <itunes:summary>WEI Share&amp;nbsp;(&amp;quot;We Share&amp;quot;) is a&amp;nbsp;Coding4Fun code sample that takes your&amp;nbsp;Windows
 Experience Index score and shares it with the world (anonymously) to an Azure website with a Silverlight front end and lets you post your WEI score to Facebook for bragging rights.
Why would you want to share your WEI score with the world? First, this gives us a place to compare WEI scores across a wide range of hardware and even see how many touch points a multitouch computer may give you. Second, a computer&#39;s speed is&amp;nbsp;dependent on the
 efficiency of the drivers. Sometimes WEI scores go up, sometimes they go down. This will allow you to judge the score that various versions of a driver may give you.
You can run WEI Share at 
www.WEIShare.net and download the source code at 
WEIShare.codeplex.com&amp;nbsp;(coming later this week). </itunes:summary>
      <itunes:duration>197</itunes:duration>
      <link>http://channel9.msdn.com/Blogs/LarryLarsen/WEI-Share-Share-you-Windows-7-Experience-Index</link>
      <pubDate>Tue, 08 Jun 2010 15:34:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Blogs/LarryLarsen/WEI-Share-Share-you-Windows-7-Experience-Index</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/previewImages/100/554594_100x75.jpg" height="75" width="100"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/previewImages/220/554594_220x165.jpg" height="165" width="220"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/ch9/4/9/5/4/5/5/weishare3_320_ch9.png" height="240" width="320"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/ch9/4/9/5/4/5/5/weishare3_512_ch9.png" height="384" width="512"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/ch9/4/9/5/4/5/5/weishare3_85_ch9.png" height="64" width="85"/>
      <media:group>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/4/9/5/4/5/5/weishare3_2MB_ch9.wmv" expression="full" duration="197" fileSize="129809747" type="video/x-ms-wmv" medium="video"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/4/9/5/4/5/5/weishare3_ch9.mp3" expression="full" duration="197" fileSize="1578156" type="audio/mp3" medium="audio"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/4/9/5/4/5/5/weishare3_ch9.mp4" expression="full" duration="197" fileSize="25997970" type="video/mp4" medium="video"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/4/9/5/4/5/5/weishare3_ch9.wma" expression="full" duration="197" fileSize="1600101" type="audio/x-ms-wma" medium="audio"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/4/9/5/4/5/5/weishare3_ch9.wmv" expression="full" duration="197" fileSize="40728277" type="video/x-ms-wmv" medium="video"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/4/9/5/4/5/5/weishare3_Zune_ch9.wmv" expression="full" duration="197" fileSize="27608329" type="video/x-ms-wmv" medium="video"/>
      </media:group>      
      <enclosure url="http://ecn.channel9.msdn.com/o9/ch9/4/9/5/4/5/5/weishare3_ch9.wmv" length="40728277" type="video/x-ms-wmv"/>
      <dc:creator>Larry Larsen</dc:creator>
      <itunes:author>Larry Larsen</itunes:author>
      <slash:comments>14</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Blogs/LarryLarsen/WEI-Share-Share-you-Windows-7-Experience-Index/RSS</wfw:commentRss>
      <category>Azure</category>
      <category>DIY</category>
      <category>Hardware</category>
      <category>Silverlight 3</category>
      <category>SQL Azure</category>
      <category>Windows 7</category>
      <category>WPF</category>
    </item>
  <item>
      <title>A Look Behind Mouse 2.0 ver. 2.0</title>
      <description><![CDATA[Back in December, <a shape="rect" href="http://channel9.msdn.com/posts/LarryLarsen/A-Look-Behind-Mouse-20/" shape="rect">
I talked to Dan Rosenfeld</a> about the capacitive version of the Mouse 2.0 project (we also&nbsp;<a shape="rect" href="http://channel9.msdn.com/posts/LarryLarsen/The-Labs-of-Microsoft-Hardware-2-of-6/" shape="rect">went by the Fab Lab</a> where mice are born).
 Hrvoje Benko is a researcher in the Adaptive Systems and Interaction group at <a shape="rect" href="http://research.microsoft.com/en-us/" shape="rect">
Microsoft Research</a>&nbsp;and is also working on the project. I recently stopped by <a shape="rect" href="http://research.microsoft.com/en-us/um/people/benko/" shape="rect">
Benko's</a> office to get more info and a detailed look at how some of the optical versions of Mouse 2.0&nbsp;may work.
<br /><br />In this video, Benko walks us through a deconstruction of the Orb mouse prototype and the FTIR (Frustrated Total Internal Reflection) mouse prototype.
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/hardware/RSS&WT.dl=0&WT.entryid=Entry:RSSView:4c8d4512e2a0471d99f09deb0009727c">]]></description>
      <comments>http://channel9.msdn.com/Blogs/LarryLarsen/A-Look-Behind-Mouse-20-ver-20</comments>
      <itunes:summary>Back in December, 
I talked to Dan Rosenfeld about the capacitive version of the Mouse 2.0 project (we also&amp;nbsp;went by the Fab Lab where mice are born).
 Hrvoje Benko is a researcher in the Adaptive Systems and Interaction group at 
Microsoft Research&amp;nbsp;and is also working on the project. I recently stopped by 
Benko&#39;s office to get more info and a detailed look at how some of the optical versions of Mouse 2.0&amp;nbsp;may work.
In this video, Benko walks us through a deconstruction of the Orb mouse prototype and the FTIR (Frustrated Total Internal Reflection) mouse prototype.
</itunes:summary>
      <itunes:duration>1188</itunes:duration>
      <link>http://channel9.msdn.com/Blogs/LarryLarsen/A-Look-Behind-Mouse-20-ver-20</link>
      <pubDate>Fri, 21 May 2010 22:46:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/Blogs/LarryLarsen/A-Look-Behind-Mouse-20-ver-20</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/previewImages/100/550881_100x75.jpg" height="75" width="100"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/previewImages/220/550881_220x165.jpg" height="165" width="220"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/ch9/1/8/8/0/5/5/Mouse2020_320_ch9.png" height="240" width="320"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/ch9/1/8/8/0/5/5/Mouse2020_512_ch9.png" height="384" width="512"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/ch9/1/8/8/0/5/5/Mouse2020_85_ch9.png" height="64" width="85"/>
      <media:group>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/1/8/8/0/5/5/Mouse2020_2MB_ch9.wmv" expression="full" duration="1188" fileSize="662945399" type="video/x-ms-wmv" medium="video"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/1/8/8/0/5/5/Mouse2020_ch9.mp3" expression="full" duration="1188" fileSize="9506774" type="audio/mp3" medium="audio"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/1/8/8/0/5/5/Mouse2020_ch9.mp4" expression="full" duration="1188" fileSize="216948776" type="video/mp4" medium="video"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/1/8/8/0/5/5/Mouse2020_ch9.wma" expression="full" duration="1188" fileSize="9614775" type="audio/x-ms-wma" medium="audio"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/1/8/8/0/5/5/Mouse2020_ch9.wmv" expression="full" duration="1188" fileSize="260950167" type="video/x-ms-wmv" medium="video"/>
        <media:content url="http://ecn.channel9.msdn.com/o9/ch9/1/8/8/0/5/5/Mouse2020_Zune_ch9.wmv" expression="full" duration="1188" fileSize="137750205" type="video/x-ms-wmv" medium="video"/>
      </media:group>      
      <enclosure url="http://ecn.channel9.msdn.com/o9/ch9/1/8/8/0/5/5/Mouse2020_ch9.wmv" length="260950167" type="video/x-ms-wmv"/>
      <dc:creator>Larry Larsen</dc:creator>
      <itunes:author>Larry Larsen</itunes:author>
      <slash:comments>5</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/Blogs/LarryLarsen/A-Look-Behind-Mouse-20-ver-20/RSS</wfw:commentRss>
      <category>Hardware</category>
      <category>Microsoft Research</category>
      <category>MS Research</category>
      <category>MSR</category>
    </item>
  <item>
      <title>MindBlaster</title>
      <description><![CDATA[ <p>In this article, Brian Peek describes his PDC 2009 project, an XNA game named MindBlaster which uses a Nintendo Wii Remote in conjunction with MindSet brain-wave sensing headset from Neurosky.</p><h3>Introduction</h3><p>Back in July of 2009 I learned of <a href="http://www.neurosky.com/" target="_blank">Neurosky</a>'s <a href="http://neurosky.com/mindset/mindset.html" target="_blank">MindSet</a> device via <a href="http://www.engadget.com/" target="_blank">Engadget.com</a>.&nbsp; The MindSet is a a brain-wave sensing headset costing only $200.&nbsp; I contacted the company and was placed on a short list to receive hardware when available to build a demo for <a href="http://www.microsoftpdc.com/" target="_blank">PDC 2009</a>.&nbsp; This is the result of that project.</p><div id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:a5633b39-d406-441d-8f4c-4f850d0f26b4" class="wlWriterSmartContent"><div id="2918f0c6-2afb-47a6-998c-0cce7d8fd121"><div><a href="http://www.youtube.com/watch?v=fRDDXzdyuRk&amp;feature=youtube_gdata" target="_new"><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9974237/video516c781982f3.jpg" alt=""></a></div></div></div><p>MindBlaster is a pretty simple game written using XNA which runs on a Windows PC in conjunction with the MindSet headset and a Nintendo Wiimote.&nbsp; The object of the game is to move your head, which moves a targeting reticule on the screen, to aim at enemy alien ships, then focus your concentration on the selected ship to heat it up and eventually make it explode.&nbsp; The more you focus, the faster the alien ship explodes.&nbsp; As more enemies are destroyed, they faster they fire back at you, causing a pretty frenetic gameplay experience until the onslaught becomes too much and you are destroyed.</p><p>So let's take a look at some of the components that went into creating MindBlaster and how the integrate into the final game.</p><h3>MindSet Headset</h3><p>As stated, the Mindset is a headset from Neurosky that is capable of reading alpha, beta, theta and gamma brain waves via 4 dry sensors, 3 located on the left earpiece, and one on an arm that touches the forehead.&nbsp; In addition, the device contains a microphone and ear speakers, making it a full-on audio headset as well.</p><p>This device connects to a PC via Bluetooth and shows up as a Bluetooth serial port.&nbsp; This means we can communicate with the device extremely easily.&nbsp; However, Neurosky also includes their own API with a simple C# wrapper that makes .NET development even easier.&nbsp; On top of that, I wrote a simple API which somewhat mimics my <a href="http://wiimotelib.codeplex.com/" target="_blank">Managed Wiimote Library</a>, which is available as a <a href="http://thinkgearnet.codeplex.com" target="_blank">separate download</a> from this application to make .NET development with the Mindset a bit easier.</p><p>One of the interesting things about the MindSet is that you don't actually need to know what brain-waves are or how they work.&nbsp; I don't know the difference between an alpha wave and a theta wave, but I was still able to produce a decent game using brain waves.&nbsp; Neurosky has developed a proprietary algorithm which takes your brain-wave values and turns them into a single score from 1 to 100 of “attention” and “meditation” allowing you can very easily determine how hard a person is concentrating or relaxing.</p><p>Using the provided API is pretty simple.&nbsp; Here is a chunk of code that connects to the headset and pulls brain-wave values in a loop.&nbsp; You wouldn't want to use this directly in your application, but it covers the important points:</p><p><pre class="brush: csharp">// get a connection ID
int connectionId = ThinkGear.TG_GetNewConnectionId();
if(connectionId &lt; 0)
    return false;

// connect to a COM port
int connect = ThinkGear.TG_Connect(_connectionId, @&quot;\\.\COM1&quot;, baud, ThinkGear.STREAM_PACKETS);
if(connect &lt; 0)
    return false;

while(true)
{
    // read data packets
    int packetsRead = ThinkGear.TG_ReadPackets(_connectionId, -1);
    if(packetsRead &gt; 0)
    {
        // get the attention value
        if(ThinkGear.TG_GetValueStatus(_connectionId, ThinkGear.DATA_ATTENTION) != 0)
            int attention = ThinkGear.TG_GetValue(connectionId, ThinkGear.DATA_ATTENTION);

        // get the meditation (relaxation) value
        if(ThinkGear.TG_GetValueStatus(_connectionId, ThinkGear.DATA_MEDITATION) != 0)
            int attention = ThinkGear.TG_GetValue(connectionId, ThinkGear.DATA_MEDITATION);
    }
}
</pre></p><p>This opens a connection ID with the API, opens a connection to the headset on a provided COM port, then, in a loop, reads all available packets from the headset and retrieves the current state of the values requested.</p><p>I have created a very simple library which interfaces with the headset and put it up as a separate download.&nbsp; If you're just interested in using this headset with .NET, please have a look at my <a href="http://thinkgearnet.codeplex.com/">ThinkGearNET library</a>.</p><h3>Wiimote</h3><p>A Nintendo Wiimote is strapped upside-down to the top of the headset and its IR camera is used for 2D head tracking.&nbsp; For PDC, I removed the Wiimote's guts from its case and mounted them directly to the headset, adding a battery holder box from Radio Shack.&nbsp; This isn't really necessary, and you can just mount your own cased Wiimote on top.</p><p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9974237/CIMG1285.jpg"><img title="CIMG1285" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9974237/CIMG1285_thumb.jpg" border="0" alt="CIMG1285" width="454" height="342"></a></p><p>The Wimote contains a 1024x768 camera which can detect the positions of up to 4 IR sources.&nbsp; For this application, I only needed a single IR source since rotation is unimportant.&nbsp; I used the <a href="http://www.amazon.com/dp/B000LFJNG6" target="_blank">Nyko Wireless Sensor Bar</a> for this source with one side covered in electrical tape.</p><p>Using my Managed Wiimote Library, I am able to poll the current state of the IR camera to pull the XY position of the IR source and translate that to the position of the targeting reticule on the screen.</p><div id="codeSnippetWrapper"><div id="codeSnippet"><pre><pre class="brush: csharp">
WiimoteState wmState = MindBlasterGame.Wiimote.WiimoteState;
if(wmState.IRState.IRSensors[0].Found)
{
    _reticule.Position.X = (wmState.IRState.IRSensors[0].Position.X) * MindBlasterGame.ScreenSize.X;
    _reticule.Position.Y = MindBlasterGame.ScreenSize.Y - (wmState.IRState.IRSensors[0].Position.Y) * MindBlasterGame.ScreenSize.Y;
}
</pre><br><br></pre></div></div><h3>Game Architecture</h3><p>The game uses parts of the XNA Creators Club <a href="http://creators.xna.com/en-US/samples/gamestatemanagement" target="_blank">Game State Management</a> sample for the overall game and screen architecture.&nbsp; Each screen is broken out into its own object with its own <strong>Update</strong>, <strong>Draw</strong>, <strong>LoadContent</strong>, etc. methods.&nbsp; This allows the title screen, settings screen, gameplay screen, and final scoring screen to remain separate “entities” for easier development.</p><p>Let's talk a little bit about each screen and important points for each.</p><h4>Settings Screen</h4><p>While developing at home and demonstrating this at PDC, I needed a very quick and dirty settings screen to easily enable and disable various features of the game.&nbsp; For example, I really didn't want to wear the headset the entire time I was developing, so I wrote some code which allowed me to use the mouse in place of the actual hardware.&nbsp; The settings screen allowed me to easily toggle those types of things.&nbsp; This was accomplished by creating an object that inherits from the <strong>MenuScreen</strong> class from the Game State Management sample.&nbsp; Menu entries can be then created as follows:</p><div id="codeSnippetWrapper"><div id="codeSnippet"><pre><span><pre class="brush: csharp">
</span>private readonly MenuEntry _menuEntry;
_menuEntry = new MenuEntry(&quot;My menu entry&quot;);
_menuEntry.Selected &#43;= _menuEntry_Selected;
MenuEntries.Add(_menuEntry);
</pre><br><br></pre></div></div><p>This creates the entry, sets its event handler, and adds it to the list.&nbsp; In the event handler, you can do whatever might be required; toggle an option on or off, increase or decrease a value, etc.</p><h4>Title Screen</h4><p>The title screen doesn't do much other than display the title graphic and the “Press Start” text, or any additional text noting if the headset is detached, the Wiimote is not connected, or other error conditions.&nbsp; </p><h4>Gameplay Screen</h4><p>This is where the magic happens.&nbsp; Perhaps surprisingly, there isn't a ton of code in the <strong>GamePlayScreen.cs</strong> file itself.&nbsp; The logic for the game is quite simple:&nbsp; move the targetting reticule based on the Wiimote IR position, detect if it's over an enemy, if it is, remove hitpoints from the enemy, and if the hitpoints drop below 0, blow up the enemy.&nbsp; In addition, the enemies fly around the screen and fire missiles at the player.&nbsp; Let's break down some of these elements.</p><h5>Enemies</h5><p>Every drawable object in the game derives from the <strong>Drawable2D</strong> or <strong>Drawable3D</strong> base classes.&nbsp; These classes define some simple properties like position, origin, scale, etc. and provide some methods which must be implemented by the derived classes, like <strong>LoadContent</strong>, <strong>Update</strong> and <strong>Draw</strong>, matching the architecture of a standard XNA application.&nbsp; Here is what the <strong>Drawable2D </strong>class looks like:</p><div id="codeSnippetWrapper"><div id="codeSnippet"><pre><span><pre class="brush: csharp">
</span>public abstract class Drawable2D
{
    public Vector2 Position;
    public Vector2 Origin;
    public float Rotation;
    public float Scale;

    public Drawable2D()
    {
        Scale = 1.0f;
        Visible = true;
    }

    public Drawable2D(Vector2 position)
    {
        Position = position;
    }

    // Update/Draw/Load which needs to be implemented by all Drawable types
    public virtual void LoadContent(ContentManager contentManager) {}
    public virtual void Update(GameTime gameTime) {}
    public virtual void Draw(GameTime gameTime) {}

    public bool Visible { get; set; }
}
</pre><br><span><br></span></pre></div></div><p>The <strong>Drawable3D</strong> class looks almost identical to this, but moves everything to 3D space using <strong>Vector3</strong> to denote positions.&nbsp; It also includes a <strong>Model</strong> property to hold the geometry of the object, and a property to hold the current <strong>World</strong> transformation matrix.&nbsp; </p><div id="codeSnippetWrapper"><div id="codeSnippet"><pre><pre class="brush: csharp">
public class Drawable3D
{
    public Vector3 Position;
    public Vector3 Rotation;
    public float Scale;

    protected Model Model;
    protected Matrix World;

    private Vector2 _position2D;

    protected Drawable3D()
    {
        Scale = 1.0f;
        Visible = true;
    }

    public Drawable3D(Vector3 position)
    {
        Position = position;
    }

    public Vector2 GetPosition2D(Camera camera)
    {
        Vector3 position = MindBlasterGame.ScreenManager.GraphicsDevice.Viewport.Project(this.Position, camera.Projection, camera.View, Matrix.Identity);
        _position2D.X = position.X;
        _position2D.Y = position.Y;
        return _position2D;
    }

    // Update/Draw/Load which needs to be implemented by all Drawable types
    public virtual void LoadContent(ContentManager contentManager) {}
    public virtual void Update(GameTime gameTime, Camera camera) {}
    public virtual void Draw(GameTime gameTime, Camera camera) {}
    public bool Visible { get; set; }
</pre><br><span><br></span></pre></div></div><p>The enemy ships and missiles were modeled in 3D Studio Max and exported to the .X file format to be used with the XNA Content Pipeline by <a href="http://www.kwxport.org/" target="_blank">kW X-port</a>, a free plugin for 3D Studio Max that can export models and animations to the .X format with a variety of user-controllable options.</p><h5>Rotate and fly</h5><p>If you've played the game or watched the video above, you've seen how the enemies rotate toward a position, fly to that position, and then rotate back toward the camera.&nbsp; To make the ships behave in this way, a random position in 3D space is calculated.&nbsp; Then the following code is run to rotate the ship to that position:</p><p><pre class="brush: csharp">protected Matrix RotateToTarget(Vector3 position, Vector3 target)
{
    // get direction from position to target
    Vector3 vecToTarget = Vector3.Normalize(target - position);
 
   // get angle to rotate
   double angle = Math.Acos(Vector3.Dot(vecToTarget, Vector3.Backward));

   // get axis to rotate on
   Vector3 axisToRotate = Vector3.Cross(Vector3.Backward, vecToTarget);

   axisToRotate.Normalize();

   // create a rotation matrix from the calculated axis and angle
   return Matrix.CreateFromAxisAngle(axisToRotate, (float)angle);
}</pre></p><div id="codeSnippetWrapper"><div id="codeSnippet"><pre class="brush: csharp">This code uses some vector math to get the direction the random point is in relation to the current ship orientation.&nbsp; The rotation angle is then calculated, the axis to actually rotate on depending on the location, and finally a rotation matrix is calculated and returned.</pre></div></div><p>This returned rotation matrix is used to rotate the ship over a short period of time using the <strong>Vector3.SmoothStep</strong> method, which interpolates between two values using a cubic equation.&nbsp; Once it has reached the target rotation, the ship then “smooth steps” to its destination position, then “smooth steps” back to being rotated toward the camera, using that same <strong>RotateToTarget</strong> method above, this time with the target position being the camera position.</p><h4>Using XNA Samples</h4><p>I used a few samples from the XNA Creators' Club in MindBlaster.&nbsp; I think there are some fabulous samples available on the site that make life easier for all XNA developers.&nbsp; I can't speak for everyone, but I'd rather pull out a known working, tested particle engine than spend the time to create one from scratch, especially on a deadline like I had for this project.&nbsp; Earlier in the article I explained how I used the Game State Management sample to provide the base screen architecture for my application.&nbsp; I also used its <strong>MenuScreen</strong> class to build my settings screen as described above.</p><h5>Particle Engine</h5><p>I also used the 2D particle engine from the <a href="http://creators.xna.com/en-US/starterkit/netrumble" target="_blank">NetRumble</a> sample.&nbsp; While my game is really in 3D, I was able to use some trickery to throw a particle effect up on the screen in 2D space on top of the ship's location in 3D space which provide a reasonable looking effect.</p><p>The particle engine provides sample effects for various explosions and trails.&nbsp; I used these effects for the enemy ship exploding, the enemy ship firing missiles, and the enemy ship spawning into view.</p><p>To get the 2D screen-space position of a 3D object in world-space, I used the following method, which is part of the <strong>Drawable3D</strong> class:</p><div id="codeSnippetWrapper"><div id="codeSnippet"><pre><span><pre class="brush: csharp"></span>
public Vector2 GetPosition2D(Camera camera)

{
    Vector3 position = MindBlasterGame.ScreenManager.GraphicsDevice.Viewport.Project(this.Position, camera.Projection, camera.View, Matrix.Identity);
    _position2D.X = position.X;
    _position2D.Y = position.Y;
    return _position2D;
}
</pre><br><br></pre></div></div><p>This uses XNA's <strong>Viewport.Project</strong> method to return the 2D position of this 3D object using the current 3D position, the current camera projection matrix, and the camera's view matrix and turns it into a 2D point with no additional effort.</p><p>So, when an enemy ship explodes or a missile is fired, the 3D object's 2D position is calculated, and the 2D particle effect is displayed at that position.</p><p>The background <strong>Starfield</strong> was also taken from NetRumble.&nbsp; This is a single class file that can be was easily pulled right out of the sample code and plopped into any XNA application to give a very nice moveable background.</p><h5>Bloom effect</h5><p>The <a href="http://creators.xna.com/en-US/sample/bloom" target="_blank">Bloom Postprocessor</a> sample on the XNA Creators Club site provides a very easy to use bloom <strong>DrawableGameComponent</strong>.&nbsp; A <strong>DrawableGameComponent</strong> is a class which implements a few methods such as <strong>Update</strong> and <strong>Draw</strong>, and then added to the <strong>Game</strong> object's <strong>Component</strong> collection.&nbsp; During each frame, the appropriate methods are called and the object updates and draws.</p><p>Blooming is a neat effect that produces some artifacts caused by bright lights.&nbsp; Think of how your vision reacts when you walk from a dark room out into a bright sunny day.&nbsp; I use this effect throughout the game to give the ships a neat glowing effect as they heat up.&nbsp; Also, when an enemy missile hits the player's screen, I flash the screen white for a few milliseconds, and the bloom effect in combination with this produces a nice effect similar to staring at a bright light and then looking quickly looking at something dark as your eyes adjust to the light difference.</p><p>Using the <strong>BloomComponent</strong> is amazingly simple.&nbsp; In the game's <strong>Initialize</strong> method:</p><div id="codeSnippetWrapper"><div id="codeSnippet"><pre><pre class="brush: csharp">
Bloom = new BloomComponent(this);
Components.Add(Bloom);
Bloom.Settings = BloomSettings.PresetSettings[3];
</pre><br><br></pre></div></div><p>With this in place, the object does the rest by hooking into the drawing surfaces and applying the effect every frame.&nbsp; The sample includes several different bloom effects with varying parameters, so its easy to experiment with these values and see what works best for your game. </p><h3>How to Install and Play</h3><p>Ensure you have either XNA Game Studio 3.1 installed, or the <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=53867a2a-e249-4560-8011-98eb3e799ef2&amp;displaylang=en" target="_blank">XNA 3.1 redistributable package</a>.</p><p>To play, start the executable and configure the settings that are appropriate to your setup.&nbsp; For example, you can turn off the Wiimote or the headset if you don't have the hardware to support it.</p><p>Up/Down/Left/Right - navigate setup menus <br>1 - Turn on debug info in game <br>F1 - Back <br>F2 - Start <br>Page Up - Reset the game </p><p>If you have turned off Wiimote support in the setup screen, the mouse can be <br>used to move the targetting reticule. </p><p>If you have turned off headset support in the setup screen, the attention <br>level can be increased/decreased with the left/right mouse buttons. </p><p>Move the reticule over an enemy and focus your attention on the enemy to make <br>your attention score increase.&nbsp; The higher your attention score, the faster <br>the enemy heats up and explodes.&nbsp; As you play, enemies will start to fire back <br>at you.&nbsp; Move the reticule over the missiles and focus your attention to blow <br>them up before they hit you.</p><h3>Conclusion</h3><p>There is obviously more to the game than what is seen here, however it would be impossible to cover every single bit of the code in an article here.&nbsp; I have tried to cover the important and more difficult parts here and show how it's very easy to leverage existing samples to get an XNA game up and running quickly.</p><p>If you have any questions or would like further explanation on how a certain portion of the game works, please contact us and I will be happy to answer the questions and perhaps expand the article further.</p><h3>Thanks</h3><ul><li><a href="http://www.joeybphotography.com/">Joey Buczek</a> for all of the 3d models and artwork in the game </li><li><a href="http://www.davidwallimann.com/">David Wallimann</a> for all of the sound effects and music in the game </li><li><a href="http://www.cynergysystems.com/blogs/page/rickbarraza">Rick Barraza</a> for the idea of moving the game into a space environment.&nbsp; Better than the road I was heading down… <img src="http://ecn.channel9.msdn.com/o9/content/images/emoticons/emotion-1.gif?v=c9" alt="Smiley"></li><li>Greg Hyver and Johnny Liu from <a href="http://www.neurosky.com/">Neurosky</a> for getting me set up with headsets and providing loaners for PDC </li><li>Michelle Leavitt for an infinite amount of playtesting </li><li>The <a href="http://creators.xna.com/">XNA</a> folks who created the various tutorials and starter kits whose code saved me a ton of time in creating the game.&nbsp; Without these, I'd probably still be writing particle engines, bloom shaders and various other pieces from scratch….these are a huge time saver! </li></ul><h3>Bio</h3><p>Brian is a <a href="https://mvp.support.microsoft.com/profile/Brian.Peek">Microsoft C# MVP</a> who has been actively developing in .NET since its early betas in 2000, and who has been developing solutions using Microsoft technologies and platforms for even longer. Along with .NET, Brian is particularly skilled in the languages of C, C&#43;&#43; and assembly language for a variety of CPUs. He is also well-versed in a wide variety of technologies including web development, document imaging, GIS, graphics, game development, and hardware interfacing. Brian has a strong background in developing applications for the health-care industry, as well as developing solutions for portable devices, such as tablet PCs and PDAs. Additionally, Brian has co-authored the book &quot;<a href="http://www.amazon.com/exec/obidos/ASIN/0596520743/brianpcom-20">Coding4Fun: 10 .NET Programming Projects for Wiimote, YouTube, World of Warcraft, and More</a>&quot; published <a href="http://www.oreilly.com/">O'Reilly</a>. He previously co-authored the book &quot;<a href="http://www.amazon.com/dp/0735711410/">Debugging ASP.NET</a>&quot; published by New Riders.&nbsp; Brian is also an author for MSDN's <a href="http://blogs.msdn.com/coding4fun/">Coding4Fun</a> website.</p> <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Tags/hardware/RSS&WT.dl=0&WT.entryid=Entry:RSSView:cedc9710c8e840e99c489e7600c9d6ca">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/MindBlaster</comments>
      <itunes:summary> In this article, Brian Peek describes his PDC 2009 project, an XNA game named MindBlaster which uses a Nintendo Wii Remote in conjunction with MindSet brain-wave sensing headset from Neurosky.IntroductionBack in July of 2009 I learned of Neurosky&#39;s MindSet device via Engadget.com.&amp;nbsp; The MindSet is a a brain-wave sensing headset costing only $200.&amp;nbsp; I contacted the company and was placed on a short list to receive hardware when available to build a demo for PDC 2009.&amp;nbsp; This is the result of that project.MindBlaster is a pretty simple game written using XNA which runs on a Windows PC in conjunction with the MindSet headset and a Nintendo Wiimote.&amp;nbsp; The object of the game is to move your head, which moves a targeting reticule on the screen, to aim at enemy alien ships, then focus your concentration on the selected ship to heat it up and eventually make it explode.&amp;nbsp; The more you focus, the faster the alien ship explodes.&amp;nbsp; As more enemies are destroyed, they faster they fire back at you, causing a pretty frenetic gameplay experience until the onslaught becomes too much and you are destroyed.So let&#39;s take a look at some of the components that went into creating MindBlaster and how the integrate into the final game.MindSet HeadsetAs stated, the Mindset is a headset from Neurosky that is capable of reading alpha, beta, theta and gamma brain waves via 4 dry sensors, 3 located on the left earpiece, and one on an arm that touches the forehead.&amp;nbsp; In addition, the device contains a microphone and ear speakers, making it a full-on audio headset as well.This device connects to a PC via Bluetooth and shows up as a Bluetooth serial port.&amp;nbsp; This means we can communicate with the device extremely easily.&amp;nbsp; However, Neurosky also includes their own API with a simple C# wrapper that makes .NET development even easier.&amp;nbsp; On top of that, I wrote a simple API which somewhat mimics my Managed Wiimote Library, which is available as a separate downlo</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/MindBlaster</link>
      <pubDate>Mon, 08 Mar 2010 17:00:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/MindBlaster</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/9974237_100.jpg" height="75" width="100"/>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/9974237_220.jpg" height="165" width="220"/>      
      <dc:creator>Brian Peek</dc:creator>
      <itunes:author>Brian Peek</itunes:author>
      <slash:comments>3</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/MindBlaster/RSS</wfw:commentRss>
      <category>Games</category>
      <category>Hardware</category>
      <category>PDC09</category>
      <category>XNA</category>
    </item>    
</channel>
</rss>
