WPF-Blogger.com [Language: en] http://www.wpf-blogger.com All news and information about Windows Presentation Foundation and Silverlight at one place. Montag, 6. Februar 2012 Marketplace now open in 5 new markets <p>I’m happy to report that the Windows Phone Marketplace is now officially open for business in 5 new markets around the world—Argentina, Indonesia, Malaysia, Peru, and the Philippines. We can’t wait to see all the great new apps you’ll create and publish for customers there.</p> <p><a href="http://windowsteamblog.com/windows_phone/b/wpdev/archive/2012/01/05/new-markets-for-windows-phone-developers.aspx">As I mentioned</a> a few weeks ago, if you’d like your existing apps to reach Windows Phone owners in these new places, just log into App Hub and select them from the list—or choose “worldwide” if you want your app to appear in all 41 of the markets Marketplace is now available in. (You’ll need to do this even if you’ve previously opted to make your app available globally.) <a href="http://create.msdn.com/en-us/news/cross-submit-apps">Here’s</a> a quick walkthrough.</p> <p>Just a reminder that apps submitted to the Marketplaces for Indonesia, Malaysia and China (which is accepting apps but not yet open to consumers) will be subject to additional requirements due to local laws, regulations, or norms. For more details, see the <a href="http://msdn.microsoft.com/en-us/library/hh184842(v=VS.92).aspx">Application Certification Requirements</a>. If your app fails certification because of these additional requirements, you’ll need to update and resubmit it, or uncheck the submission boxes for those markets.</p> <p>That’s it for now. </p><div style="clear:both;"></div><img src="http://windowsteamblog.com/aggbug.aspx?PostID=575519" width="1" height="1"> http://windowsteamblog.com/windows_phone/b/wpdev/archive/2012/02/03/marketplace-now-open-in-5-new-markets.aspx Windows Phone Dev Blog 3579 2012-02-03T18:02:28 Complimentary Copies <p> When an author gets a book published, the publisher generally gives the author 10 complimentary copies of the book. Usually the author signs these books and gives them to all his friends, but then he has 7 or 8 copies still left over, and these tend to gather dust on the bookshelves of the author's home. </p><p>... more ...</p> http://www.charlespetzold.com/blog/2012/01/Complimentary-Copies.html Charles Petzold 3578 2012-02-02T18:00:00 Windows 8 Touch Events Interactions <p> During the week in September that I was attending the Microsoft Build conference and learning all about Windows 8, only one topic made me gloomy: This was the Windows 8 implemention of the <i>Manipulation</i> events. These events provide a high-level application programming interface to touch input, so obviously they are very important. </p><p>... more ...</p> http://www.charlespetzold.com/blog/2012/02/Windows-8-Touch-Events-Interactions.html Charles Petzold 3576 2012-02-01T13:00:00 Event Handler Memory Leaks, Unwiring Events, and the WeakEventManager in WPF 4.5 <p>Many developers don't realize that a common source of memory leaks in .NET applications is the event handler. WPF 4.5 includes built-in support for weak events to help us do the right thing and not eat up all the available memory.</p> <h3>The Problem</h3> <p>Events are ubiquitous in .NET. When you add an event handler using the <em>EventName += &lt;my event handler delegate&gt;</em> syntax, the event source acquires a reference to the listener. This situation is a circular reference, as the listener had a reference to the source to begin with.</p> <p>These references are "strong references". That is, they are actual pointers to resources.</p> <p><img src="http://10rem.net/media/83227/Windows-Live-Writer_WeakEventManager-in-WPF-4.5_EF5D_image_9.png" width="650" height="151" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></p> <p>In the .NET framework, circular references aren't usually a problem. If the set of objects can't be traced back to the root object in the application, they are garbage collected. That's great, but in this case, due to the references from the event source to the event listener, as long as the event source is reachable, the listener will also stay around, as the event source can be traced back to a valid object root.</p> <p>This can be a real problem if the event source is long-lived, as is the case with things like application configuration objects, or other static or singleton objects. Event handlers are often on the UI side of things, so the listener can be a resource and memory heavy Window object.</p> <p>Take this scenario: Over the course of an application's lifetime, the user opens and closes document windows. The document windows each have a reference to some other object: it could be the parent window, it could be a static configuration class, it could be a shared singleton data provider somewhere up the chain. The important thing is that the windows are listening to an event from that object: CollectionChanged, some custom DataLoaded or other event.</p> <p><img src="http://10rem.net/media/83232/Windows-Live-Writer_WeakEventManager-in-WPF-4.5_EF5D_image_17.png" width="650" height="228" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></p> <p>Now, when the parent window (and your code) releases all reference to the window instance, the event source still has a reference to them. And, because the event source also has a reference from the application (implicit if it's static - man that lifetime gets ugly), the windows stay around:</p> <p><img src="http://10rem.net/media/83237/Windows-Live-Writer_WeakEventManager-in-WPF-4.5_EF5D_image_20.png" width="650" height="228" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></p> <p>No GC or disposal for those window instances. Windows tend to have a lot of resources tied up just to paint (control templates, controles themselves, data even) so they're not cheap resources. It gets even nastier, though. If those instances have references to, say, individual ViewModel instances, and those ViewModels have references to a cache of data, you can end up with pretty enormous memory leaks. Open up enough windows and, eventually, your app will run out of resources.</p> <h3>Basis for Comparison</h3> <p>Before we look at the problem, here's a profile of the application opening 200 windows, closing the 200 windows, and then forcing a GC. I did this three and then closed the app. Each window allocates a bunch of memory in an array just to give it a payload. The window code looks like this:</p> <pre class="brush: csharp;"> public partial class TestChildWindow : Window<br /> {<br /> long[] _memoryHog;<br /> <br /> public TestChildWindow()<br /> {<br /> InitializeComponent();<br /> <br /> Random rnd = new Random();<br /> <br /> string imageName = "Assets/image" + rnd.Next(1, 9) + ".jpg";<br /> NeatoImage.Source = new BitmapImage(new Uri(imageName, UriKind.Relative));<br /> <br /> _memoryHog = new long[1024];<br /> <br /> Unloaded += new RoutedEventHandler(TestChildWindow_Unloaded);<br /> }<br /> <br /> void TestChildWindow_Unloaded(object sender, RoutedEventArgs e)<br /> {<br /> }<br /> } </pre> <p>&nbsp;</p> <p>In the upcoming examples, the TestChildWindow will have a reference to the SettingsManager. This is a stub class meant to represent pretty much any long-lived instance in your application.</p> <pre class="brush: csharp;"> namespace WpfWeakEventManager<br /> {<br /> class SettingsManager<br /> {<br /> public event EventHandler SettingsChanged;<br /> <br /> private static SettingsManager _current;<br /> public static SettingsManager Current<br /> {<br /> get<br /> {<br /> if (_current == null)<br /> _current = new SettingsManager();<br /> <br /> return _current;<br /> }<br /> }<br /> }<br /> }<br /> </pre> <p>Finally, the Main Window has three buttons that I used to test the application. The first opens 200 windows. The second closes all windows (except the main one) being tracked by the application. The third forces a GC collection. It also has a listbox to show diagnostic information when I'm not running with an attached debugger.</p> <pre class="brush: csharp;"> namespace WpfWeakEventManager<br /> {<br /> /// &lt;summary&gt;<br /> /// Interaction logic for MainWindow.xaml<br /> /// &lt;/summary&gt;<br /> public partial class MainWindow : Window<br /> {<br /> private SettingsManager _current;<br /> <br /> public MainWindow()<br /> {<br /> InitializeComponent();<br /> <br /> // make sure SettingsManager is referenced outside<br /> // just the child windows. Normally this would happen<br /> // just do to general use of the class. Forcing it here.<br /> <br /> _current = SettingsManager.Current;<br /> }<br /> <br /> private void OpenWindowsButton_Click(object sender, RoutedEventArgs e)<br /> {<br /> int openedCount = 0;<br /> DebugList.Items.Add("Total Memory Before Opening Windows: " + GC.GetTotalMemory(true));<br /> <br /> for (int i = 0; i &lt; 200; i++)<br /> {<br /> var window = new TestChildWindow();<br /> window.Show();<br /> openedCount++;<br /> }<br /> <br /> DebugList.Items.Add("Opened " + openedCount + " windows.");<br /> DebugList.Items.Add("Total Memory After Opening Windows: " + GC.GetTotalMemory(true));<br /> }<br /> <br /> private void CloseWindowsButton_Click(object sender, RoutedEventArgs e)<br /> {<br /> int closedCount = 0;<br /> foreach (Window window in Application.Current.Windows)<br /> {<br /> if (window != this)<br /> {<br /> window.Close();<br /> closedCount++;<br /> }<br /> }<br /> <br /> DebugList.Items.Add("Closed " + closedCount + " windows.");<br /> DebugList.Items.Add("App has " + Application.Current.Windows.Count + " window(s) it's holding on to.");<br /> }<br /> <br /> private void CollectButton_Click(object sender, RoutedEventArgs e)<br /> {<br /> GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);<br /> //GC.Collect();<br /> }<br /> }<br /> } </pre> <p>I experimented with a few variations on GC.Collect and some of the other notifications before the code that is here. A plain old GC.Collection will likely work just as well in any case.</p> <p>Here's what the window looks like after I opened 200 windows and then closed them and then opened another 200. <strong>200</strong> windows is actually a lot of windows, as it turns out, but if you consider an application where your user opens up 1 customer record every 5 minutes (for a phone support person, this is conservative), over the course of an 8 hour day, that could be as many as 160 forms, and that's assuming they close the application every day when they leave.</p> <p><a href="http://10rem.net/media/83242/Windows-Live-Writer_WeakEventManager-in-WPF-4.5_EF5D_image_32.png" target="_blank"><img src="http://10rem.net/media/83247/Windows-Live-Writer_WeakEventManager-in-WPF-4.5_EF5D_image_thumb_12.png" width="650" height="360" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <p>Now I needed to find a good way to track memory usage. The profiler in Visual Studio is really good for finding performance bottlenecks, but not really meant for the real-time memory usage graphing I wanted to do. So, I downloaded the 10 day trial of .NET Memory Profiler (an app I used a lot back when I was consulting) and had it capture data while I performed the above actions.</p> <p><a href="http://10rem.net/media/83252/Windows-Live-Writer_WeakEventManager-in-WPF-4.5_EF5D_image_22.png" target="_blank"><img src="http://10rem.net/media/83257/Windows-Live-Writer_WeakEventManager-in-WPF-4.5_EF5D_image_thumb_7.png" width="660" height="254" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <p>In this graph, the pink line is the active memory in use in bytes, the green line is the number of root references. (note: none of the memory graphs include memory from on-window images. I ran without the cute images, but I left the code in the form and the images in the screenshot just because)</p> <p>Remember, this is without any of the circular reference problems discussed so far. Now, let's take a look at the same actions when I have an event handler wired up in the constructor of the window.</p> <p><a href="http://10rem.net/media/83262/Windows-Live-Writer_WeakEventManager-in-WPF-4.5_EF5D_image_24.png" target="_blank"><img src="http://10rem.net/media/83267/Windows-Live-Writer_WeakEventManager-in-WPF-4.5_EF5D_image_thumb_8.png" width="660" height="253" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <p>Notice something about that graph? Yep. Memory just isn't being returned. It's leaking, and the root references keep on climbing. The only difference between this profiled version and the previous was that I added the SettingsManager event handler wireup in the constructor:</p> <pre class="brush: csharp;"> public partial class TestChildWindow : Window<br /> {<br /> long[] _memoryHog;<br /> <br /> public TestChildWindow()<br /> {<br /> InitializeComponent();<br /> <br /> Random rnd = new Random();<br /> <br /> string imageName = "Assets/image" + rnd.Next(1, 9) + ".jpg";<br /> NeatoImage.Source = new BitmapImage(new Uri(imageName, UriKind.Relative));<br /> <br /> _memoryHog = new long[1024];<br /> <br /> SettingsManager.Current.SettingsChanged += Current_SettingsChanged;<br /> <br /> Unloaded += new RoutedEventHandler(TestChildWindow_Unloaded);<br /> }<br /> <br /> void Current_SettingsChanged(object sender, EventArgs e)<br /> {<br /> // do something<br /> }<br /> <br /> void TestChildWindow_Unloaded(object sender, RoutedEventArgs e)<br /> {<br /> }<br /> } </pre> <p>The Unloaded handler is empty, but it is wired up. The key change here is the SettingsManager.Current.SettingsChanged wire-up.</p> <p>There are a multitude of considerations in this example, but let's deal with just the topic of this post: the event handlers.</p> <h3>Solution 1: Unwire Your Event Handlers</h3> <p>This generally doesn't work if you use anonymous delegates (one reason to be careful about using them with objects that live outside the scope of a single method), but in cases where you have a real event handler method, unhooking them when you're done with them is definitely a best practice.</p> <p>You can remove event handlers in Dispose methods, or in the case of a window, in the Unload event handler. That's what I did here.&nbsp; The code is a simple change:</p> <pre class="brush: csharp;"> void TestChildWindow_Unloaded(object sender, RoutedEventArgs e)<br /> {<br /> SettingsManager.Current.SettingsChanged -= Current_SettingsChanged;<br /> } </pre> <p>All I did was remove the event handler inside the Unloaded handler. Take a look at the impact it had on memory:</p> <p><a href="http://10rem.net/media/83272/Windows-Live-Writer_WeakEventManager-in-WPF-4.5_EF5D_image_26.png" target="_blank"><img src="http://10rem.net/media/83277/Windows-Live-Writer_WeakEventManager-in-WPF-4.5_EF5D_image_thumb_9.png" width="660" height="254" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <p>That's much better. The root references and memory both drop when I hit the "collect" button. Compare this to the previous example where the memory never went down. As to the differences between this graph and the first one, chalk it up to sample timing and my own non-deterministic button pushing.</p> <p>So, that's a great approach. In fact, if you can do this, you should do this. It's simple and highly effective.</p> <p>For other situations, perhaps where you don't control all the code, or when unwiring events is difficult or inconvenient, there's the Weak Event Pattern.</p> <h3>Solution 2: Weak Events</h3> <p>It's not always possible or practical to unwire event handlers. <strong>Actually, let me rephrase that</strong>: sometimes the level of effort and thought that needs to go into *where* you put event handler unwiring is more than developers have time to put into the app. :)</p> <p>Enter the Weak Event Pattern</p> <p>The concept of a Weak Event is nothing new. Many others have created their own various weak event solutions for use with WPF. Previous versions of .NET and WPF included the WeakEventManager, but required you to derive your own class and implement IWeakEventListener interfaces. That was a fair bit of work for developers who just need to get stuff done. The real news here is that WPF 4.5 includes the <strong>generic</strong> WeakEventManager type to make it easier for you to implement the weak event pattern in your own code, without all the other ceremony. You can still derive from WeakEventManager (if you can do the work, it's actually a good practice due to the performance benefits you'll get from it via having actual events and not reflection look-ups), but the new generic class makes it easy enough so that there's no excuse *not* to do it.</p> <p>Here's the memory usage of the application using Weak Events</p> <p><a href="http://10rem.net/media/83282/Windows-Live-Writer_WeakEventManager-in-WPF-4.5_EF5D_image_30.png" target="_blank"><img src="http://10rem.net/media/83287/Windows-Live-Writer_WeakEventManager-in-WPF-4.5_EF5D_image_thumb_11.png" width="660" height="254" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <p>And here's the code change. I removed the code to unwire the event, and did the event wireup using WeakEventManager rather than regular old events.</p> <pre class="brush: csharp;"> namespace WpfWeakEventManager<br /> {<br /> /// &lt;summary&gt;<br /> /// Interaction logic for TestChildWindow.xaml<br /> /// &lt;/summary&gt;<br /> public partial class TestChildWindow : Window<br /> {<br /> long[] _memoryHog;<br /> <br /> public TestChildWindow()<br /> {<br /> InitializeComponent();<br /> <br /> Random rnd = new Random();<br /> <br /> string imageName = "Assets/image" + rnd.Next(1, 9) + ".jpg";<br /> NeatoImage.Source = new BitmapImage(new Uri(imageName, UriKind.Relative));<br /> <br /> _memoryHog = new long[1024];<br /> <br /> // this version wires up an event handler which causes a hard reference<br /> // and, unless it is unwired, a memory leak<br /> // SettingsManager.Current.SettingsChanged += Current_SettingsChanged;<br /> <br /> // unwire the event handler. This is a good practice for avoiding leaks<br /> // Unloaded += new RoutedEventHandler(TestChildWindow_Unloaded);<br /> <br /> // this version avoids memory leaks without requiring you to<br /> // unwire the event.<br /> WeakEventManager&lt;SettingsManager, EventArgs&gt;<br /> .AddHandler(SettingsManager.Current,<br /> "SettingsChanged",<br /> Current_SettingsChanged);<br /> }<br /> <br /> void Current_SettingsChanged(object sender, EventArgs e)<br /> {<br /> // do something<br /> }<br /> <br /> void TestChildWindow_Unloaded(object sender, RoutedEventArgs e)<br /> {<br /> // SettingsManager.Current.SettingsChanged -= Current_SettingsChanged;<br /> }<br /> }<br /> }<br /> </pre> <p>This new WeakEventManager is much easier to use than anything we had before. You take a hit for relying on reflection to resolve the event name, but in all but the most performance-sensitive cases (where you probably wouldn't bother with events anyway), it's going to be worth it.</p> <h3>Summary</h3> <p>Event handlers and long-lived objects can be the source of memory leaks in any .NET application. Whenever you can, you should unwire your event handlers to help avoid these leaks. When that is impractical, the Weak Event Pattern using the WPF 4.5 WeakEventManager&lt;TObject, TArgs&gt; is a great way to help save you from the grief of memory leaks without requiring all the ceremony we had with the regular WeakEventManager and IWeakEventListener in the previous versions.</p> <p>Now there's no excuse to have leaky event handlers.</p> <p><a href="http://feedads.g.doubleclick.net/~a/vWEdpAaAZUJIGK0nCSdtRm-jICo/0/da"><img src="http://feedads.g.doubleclick.net/~a/vWEdpAaAZUJIGK0nCSdtRm-jICo/0/di" border="0" ismap="true"></img></a><br/> <a href="http://feedads.g.doubleclick.net/~a/vWEdpAaAZUJIGK0nCSdtRm-jICo/1/da"><img src="http://feedads.g.doubleclick.net/~a/vWEdpAaAZUJIGK0nCSdtRm-jICo/1/di" border="0" ismap="true"></img></a></p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=cNCfpxx_N5Y:OFmCXGG8D3g:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=cNCfpxx_N5Y:OFmCXGG8D3g:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=cNCfpxx_N5Y:OFmCXGG8D3g:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=cNCfpxx_N5Y:OFmCXGG8D3g:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=cNCfpxx_N5Y:OFmCXGG8D3g:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=cNCfpxx_N5Y:OFmCXGG8D3g:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=cNCfpxx_N5Y:OFmCXGG8D3g:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=cNCfpxx_N5Y:OFmCXGG8D3g:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=cNCfpxx_N5Y:OFmCXGG8D3g:gIN9vFwOqvQ" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/PeteBrown/~4/cNCfpxx_N5Y" height="1" width="1"/> http://feedproxy.google.com/~r/PeteBrown/~3/cNCfpxx_N5Y/event-handler-memory-leaks-unwiring-events-and-the-weakeventmanager-in-wpf-45 Pete Brown 3574 2012-02-01T05:27:14 Memory Profiling for Application Performance <p>Performance is a concern for all but the most trivial of applications, and in a constrained environment like the phone it is all the more so; performance issues directly manifest themselves in the user experience. Memory usage is one such source of performance issues that can degrade user experience, and the Windows Phone Marketplace enforces a <a href="http://msdn.microsoft.com/en-us/library/hh184840(v=VS.92).aspx">technical certification requirement</a> that an application must not exceed 90 MB of RAM usage, except on devices that have more than 256 MB of memory.</p> <p>What could cause 90 MB of usage in a garbage-collected runtime? There could be several causes:</p> <ul> <li>Allocating too much.</li> <li>Long living objects that bloat working set.</li> <li>Holding on to references unintentionally leading to memory leaks.</li> </ul> <p>Applications allocating too much could end up with working sets breaching this threshold; applications with a large working set might eventually exit with an “Out of Memory” exception; and holding on to references unintentionally can lead to memory leaks causing working set to increase steadily and stealthily, eventually leading to the application exiting with an “Out of Memory” exception.</p> <p>Up until the Windows Phone SDK 7.1 release, application developers had to guard against this by programmatically instrumenting their code with specific framework method calls and track memory usage. These methods included the following:</p> <ul> <li><a href="http://msdn.microsoft.com/en-us/library/system.gc.gettotalmemory(v=vs.95).aspx">System.GC.GetTotalMemory</a></li> <li><a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.info.devicestatus.devicetotalmemory(v=VS.92).aspx">Microsoft.Phone.Info.DeviceExtendedProperties.DeviceTotalMemory</a></li> <li><a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.info.devicestatus.applicationcurrentmemoryusage(v=VS.92).aspx">Microsoft.Phone.Info.DeviceExtendedProperties.ApplicationCurrentMemoryUsage</a></li> <li><a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.info.devicestatus.applicationpeakmemoryusage(v=VS.92).aspx">Microsoft.Phone.Info.DeviceExtendedProperties.ApplicationPeakMemoryUsage</a></li> </ul> <p>But beyond that there was little help from the tools.</p> <p>The <a href="http://www.microsoft.com/download/en/details.aspx?displaylang=en&amp;id=27570">Windows Phone SDK 7.1</a> addresses this through the introduction to <a href="http://msdn.microsoft.com/en-us/library/hh202934(v=VS.92).aspx">profiling tools</a> to analyze the execution, visual, and memory characteristics of an application.</p> <p>Install the SDK now, and let us walk through the Memory Profiler as we investigate a case of a memory leak caused by unintentionally holding on to references.</p> <h1>A Sample Application</h1> <p>Consider this <a href="http://windowsteamblog.com/windows/m/files/575359/download.aspx">application</a> that has two pages, and where the second page renders several images within a grid, and where one may navigate between pages.</p> <p>Page2 has 4 images controls within a grid control that is <i>bitmapcached</i>. During the initialization of Page2, it binds the 4 image controls to jpeg images and registers for an event handler.</p> <p>The two pages look as follows:</p> <p><a href="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/3808.image_5F00_2FCA31C4.png"><img style="border: 0px currentcolor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/2376.image_5F00_thumb_5F00_034101DE.png" width="154" height="254" /></a>&#160;&#160;&#160; <a href="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/6457.image_5F00_2CD4CD11.png"><img style="border: 0px currentcolor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/4375.image_5F00_thumb_5F00_062640C4.png" width="154" height="254" /></a></p> <p>As we try out the application going back and forth between the pages a few times, observe that memory usage keeps going up; there is a memory leak.</p> <h1>Visualizing the leak</h1> <p>To delve deeper into this leak further let us run this application through the Memory Profiler using the following steps:</p> <ol> <li>Invoke the Profiler, choose “Memory (managed object allocation and texture usage)”, and launch the application. Note the memory used by the application at the top of the screen.</li> <li>Click on Go To Page2. This will launch Page2, and display the 4 flower images.</li> <li>Click on the back button.</li> <li>Click on ‘Force GC’. Note the memory used by the application at the top of the screen. Observe that it does not go down.</li> <li>Repeat steps 2, 3, 4 four more times.</li> <li>Now click on ‘Stop Profiling’.</li> </ol> <p>We should see a graph like the following:</p> <p><a href="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/5722.image_5F00_6EAB8C92.png"><img style="border: 0px currentcolor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/4617.image_5F00_thumb_5F00_6C225AD4.png" width="508" height="365" /></a></p> <p>As expected memory usage is steadily growing.</p> <h1>Analysis</h1> <p>Select a range, from before the start of the first plateau to just after the after the start of the last plateau, for analysis. Once analysis is complete, using <b>Performance Warnings</b> as the starting point, navigate to the <b>Heap Summary </b>view. We should see a table similar to the following:</p> <p><a href="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/5187.image_5F00_0294F95C.png"><img style="border: 0px currentcolor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/8524.image_5F00_thumb_5F00_74760A5E.png" width="508" height="365" /></a></p> <p>Note that the memory held by <b>Retained Silverlight Visuals at End </b>is large as compared to that held by just managed objects. So, let’s drill down into these retained Silverlight visuals.</p> <p>Select <b>Retained Silverlight Visuals at End </b>and navigate to the <b>Types </b>view. In the <b>Types </b>view, sort the <b>Total Size (Bytes) </b>column in descending order. We should now see a table similar to the following:</p> <p><a href="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/6355.image_5F00_119BB269.png"><img style="border: 0px currentcolor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/1055.image_5F00_thumb_5F00_676C0480.png" width="508" height="365" /></a></p> <p>Note that Grid and Page2 are the heavy consumers. We also notice right away that 5 instances of Page2 are hanging around. In our scenario, we navigated 5 times to Page2, remember?</p> <p>Let’s look at what those 10 instances of the Grid are: click on the Grid and navigate to the <b>Instances </b>view. We should now see a table similar to the following:</p> <p><a href="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/2844.image_5F00_0B44B60E.png"><img style="border: 0px currentcolor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/2742.image_5F00_thumb_5F00_20DEEEAB.png" width="508" height="365" /></a></p> <p>Note that 5 of the instances are being allocated from Page2. Click on the hyperlink and you can go the line of code in XAML where the Grid is allocated.</p> <p>To see what is the memory being retained by the visual tree rooted at a Grid instance, click on, say, the grid with the ID 33 (this is a grid allocated from Page2), and navigate to the <b>Visual Tree </b>view. We should now a table similar to the following:</p> <p><a href="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/7180.image_5F00_249C937B.png"><img style="border: 0px currentcolor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/8880.image_5F00_thumb_5F00_48754508.png" width="508" height="365" /></a></p> <p>Note the visual tree rooted at that grid instance. We can see the 4 contained image controls, as well as the Texture memory associated with the grid.<b></b></p> <p>To cross check the association between the grid instance and Page2, we can go back to the Types view, select Page2, and navigate to the <b>Instances </b>view. We should then see a table similar to the following:</p> <p><a href="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/2818.image_5F00_2564D398.png"><img style="border: 0px currentcolor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/1715.image_5F00_thumb_5F00_226F6EE5.png" width="508" height="365" /></a></p> <p>Notice that there are 5 instances created and none of them has been destroyed (i.e. garbage collected).</p> <p>Now let’s look at the Visual Tree rooted at a Page2 instance. Select the first instance, and navigate to the <b>Visual Tree</b>. We should see a table similar to the following:</p> <p><a href="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/8535.image_5F00_718CB779.png"><img style="border: 0px currentcolor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/4718.image_5F00_thumb_5F00_0EB25F84.png" width="508" height="365" /></a></p> <p>Again, we see the grid, its associated texture memory, and its contained image controls. Earlier we saw that 5 instances of Page2 were hanging around. That leak was causing the associated grid, images, and texture memory to not get cleaned up.</p> <p>Now let us see why the Page2 instances were hanging around.</p> <p>Go back to the <b>Instances </b>view, select the first Page2 instance, and navigate to the <b>GC Roots </b>view. Collapse the tree structures. We should see a table similar to the following:</p> <p><a href="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/7824.image_5F00_44D3D7D3.png"><img style="border: 0px currentcolor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/7536.image_5F00_thumb_5F00_61F97FDD.png" width="508" height="365" /></a></p> <p>Ignore the weak references (these do not prevent the GC from acting on the references). But look at the TouchFrameEventHandler; expand it and we should see a table similar to the following:</p> <p><a href="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/4466.image_5F00_7F1F27E7.png"><img style="border: 0px currentcolor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/3276.image_5F00_thumb_5F00_4A3222AA.png" width="508" height="365" /></a></p> <p>There are 5 chained event handlers! The first one was allocated from our assembly. The rest were cloned within mscorlib, as each page appended its own TouchFrameEventHandler (the event handler is implemented as a .Net Delegate type). That event handler is holding a reference to the page that in turn is preventing the page from being garbage collected.</p> <p>So the eventhandlers references the Page2 instances, preventing it from being GC’d; and thus assets contained in Page2 are not cleaned up (the grid, associated texture memory, images).</p> <p>Solved!</p> <p>All that remains to be done is to find where that handler is being registered in our assembly.</p> <p>Go back to <b>Heap Summary</b>, select <b>Retained Allocations at End</b>, navigate to the <b>Types </b>view, sort by <b>Type Name</b> column, and scroll down to locate the TouchFrameEventHandler. We should see the following:</p> <p><a href="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/2117.image_5F00_550F03F2.png"><img style="border: 0px currentcolor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/1832.image_5F00_thumb_5F00_7CF20351.png" width="508" height="365" /></a></p> <p>To find out where that 1 instance was allocated in our application code, select the first entry, and navigate to the <b>Methods </b>view. You should see the following:</p> <p><a href="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/1738.image_5F00_193F4572.png"><img style="border: 0px currentcolor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/2781.image_5F00_thumb_5F00_2B3B6332.png" width="508" height="365" /></a></p> <p>Click on the <b>Allocating Method </b>hyperlink, and you will jump to the method that did the allocation. You should see the following:</p> <p><a href="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/3582.image_5F00_13547C0C.png"><img style="border: 0px currentcolor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/5102.image_5F00_thumb_5F00_57483A56.png" width="508" height="365" /></a></p> <p>There, right at the bottom is the place where we register to the eventhandler! The step of registering stashes away a strong reference to this instance of the page within the event handler delegate. Unless the user unregisters this handler, the Page2 instance will remain alive (and consequently so too will the grid and the images, and the texture memory will not get cleaned up).</p> <p>If you comment out the line that enregisters the handler, and rerun this scenario, here is the graph you would see:</p> <p><a href="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/6165.image_5F00_3B57055E.png"><img style="border: 0px currentcolor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/4426.image_5F00_thumb_5F00_664EF363.png" width="508" height="365" /></a></p> <p>Voilà!</p> <h1>Conclusion</h1> <p>Having a garbage collected runtime removes one of the biggest sources of program errors, memory allocation errors; you no longer have to worry about freeing memory which you no longer use. But leaks spring when you unintentionally hold on to object references that you no longer use. By providing a variety of Views on the applications memory usage the Memory Profiler can be a valuable tool to detect and fix such leaks.</p><div style="clear:both;"></div><img src="http://windowsteamblog.com/aggbug.aspx?PostID=575395" width="1" height="1"> http://windowsteamblog.com/windows_phone/b/wpdev/archive/2012/02/01/memory-profiling-for-application-performance.aspx Windows Phone Dev Blog 3571 2012-01-31T19:50:33 Yet Another Podcast #58–Julie Lerman and EF/CF http://feedproxy.google.com/~r/JesseLiberty-SilverlightGeek/~3/KlUXYu6MokM/ Jesse Liberty [MS] 3569 2012-01-31T17:34:48 Happy 75th Birthday, Philip Glass! <p> About 14 months ago I saw the New York premiere of Philip Glass's <i>Concerto for Violin and Orchestra No.2</i> at Carnegie Hall performed by violinist Robert McDuffie and the Venice Baroque Orchestra. McDuffie had commissioned the Glass work (subtitled "The American Four Seasons") for a program that also included the four violin concertos collected by Antonio Vivaldi as <i>The Four Seasons</i> almost three centuries earlier, and McDuffie took the program on a tour of 30 American cities. </p><p>... more ...</p> http://www.charlespetzold.com/blog/2012/01/Happy-75th-Birthday-Philip-Glass.html Charles Petzold 3568 2012-01-31T11:00:00 The .NET Gadgeteer Diaper Alarm Part 1 (Moisture Sensor) <p>During the .NET Microframework and <a href="http://www.youtube.com/playlist?list=PL7A0F12DEA2A538C2" target="_blank">.NET Gadgeteer code camp talk</a> that Andrew Duthie and I gave several weeks back, we tossed around the idea of using the Gadgeteer and a moisture sensor to alert parents of, ahhhh, soggy diaper issues.</p> <p>Shortly before the holidays, in the mail, I got a package of goodies from Microsoft Research. That package included one of these moisture sensors from Seeed Studio. These are meant for checking to see how wet soil is, but I figure one man's diaper is another man's soil, so, I can't resist. Must…prototype…solution.</p> <blockquote> <p>WARNING: Science in Progress. Also: diaper jokes.</p> </blockquote> <h3>First Iteration</h3> <p>I didn't have any of that handy inoffensive blue liquid available (the stuff they use to represent *any* bodily fluid on commercials; pretty sure that's how Smurfs are grown), so lacking any actual babies (my kids are all potty trained now. Yay!) I'm using plain old water. The real thing is a <a href="http://www.bing.com/search?q=conductivity+of+urine&amp;src=ie9tr" target="_blank">bit more conductive</a>, so you may need to vary some values I use. Also, I'm dealing with liquids only in this post. You're on your own with anything more…substantial, but I might recommend some sort of scale, or for the newborns, perhaps a blast detector <a href="http://www.amazon.com/3M-8979N-Performance-Nuclear-Slate/dp/B000NG3ZKI" target="_blank">held on with this</a>.</p> <h4>Hardware</h4> <p>I'm using the <a href="http://www.seeedstudio.com/depot/moisture-module-net-gadgeteer-compatible-p-973.html?cPath=203" target="_blank">Moisture Module from Seeed Studio</a>. (You can also <a href="http://www.ghielectronics.com/catalog/category/275/" target="_blank">purchase it through GHI</a> as they have a partnership.) This module returns back an analog voltage that is proportional to how wet the area is. As mentioned, it's is really meant to be used in soil, to tell you if you need to water your plants, so we'll have to finagle a few things to make it work here.</p> <p>&nbsp;</p> <p><a href="http://www.seeedstudio.com/depot/moisture-module-net-gadgeteer-compatible-p-973.html?cPath=203" target="_blank"><img src="http://10rem.net/media/83158/Windows-Live-Writer_The-.NET-Gadgeteer-Diaper-Alarm_13CA5_image_3.png" width="500" height="259" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <p>It's wired to socket 9 on my Gadgeteer board. That's one of the two analog sockets on the GHI Electronics Spider. I had one of the extra long ribbon cables which was perfect for this. You don't want the rest of your modules anywhere near what we're doing here. Also, this probably works best with babies who are relatively sedentary, preferably sleeping. Otherwise, you'll end up with a miniature Borg running around the house trailing some sort of dangling box of electronic goodies.</p> <blockquote> <p>Warning: I'm reasonably certain that none of this is actually baby-proof.</p> </blockquote> <h4>Yee Old Test Subject</h4> <p>Next, I need something to test in. No, don't go there as my wife would not appreciate getting that kind of laundry from me, not even in the name of science. I'm pretty sure I could get my almost-6 year old son to cooperate if I offered LEGO or something as a reward, but that'd also get me on the naughty list. Lacking other creative solutions, I'm just going to use a small plate and a paper towel to see how this all works.</p> <p><a href="http://10rem.net/media/83163/Windows-Live-Writer_The-.NET-Gadgeteer-Diaper-Alarm_13CA5_image_7.png" target="_blank"><img src="http://10rem.net/media/83168/Windows-Live-Writer_The-.NET-Gadgeteer-Diaper-Alarm_13CA5_image_thumb_2.png" width="481" height="448" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <p>I'll wet the towel, and wait until the moisture starts to hit the sensor. Then I can adjust for sensitivity. The idea is not to make the sensor swim, but to get an idea of how we the towel needs to be for this to work. Remember, the sensor is designed to be stuck in soil, not placed down on a towel.</p> <h4>Software</h4> <p>Be sure to <a href="http://www.tinyclr.com/support" target="_blank">download the latest Gadgeteer SDK and driver package</a>. The latest rev (as of this month) includes support for all the GHI and Seeed modules on the market, including this one. Once you'd done that, it's time to create a new project. Open up Visual Studio and create a new .NET Gadgeteer Project. I named mine DiaperMonitor.</p> <p><a href="http://10rem.net/media/83173/Windows-Live-Writer_The-.NET-Gadgeteer-Diaper-Alarm_13CA5_image_5.png" target="_blank"><img src="http://10rem.net/media/83178/Windows-Live-Writer_The-.NET-Gadgeteer-Diaper-Alarm_13CA5_image_thumb.png" width="550" height="387" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <p>Next, add the main board, if it's not already there. By default, mine came up with the FEZ Hydra, presumably because that's the last one I used. I simply removed that and dragged on a FEZ Spider from the list of main boards in the toolbox.</p> <p>Next, I added a Seeed.MoistureSensor module. You can either connect it automatically, or pick the port yourself and drag the connection to create the link. I have the moisture sensor on socket 9 as shown here. I also added one of the brand new GHI LED7R modules just to give us something interesting to light up.</p> <p><a href="http://10rem.net/media/83183/Windows-Live-Writer_The-.NET-Gadgeteer-Diaper-Alarm_13CA5_image_11.png" target="_blank"><img src="http://10rem.net/media/83188/Windows-Live-Writer_The-.NET-Gadgeteer-Diaper-Alarm_13CA5_image_thumb_3.png" width="650" height="361" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <p>If you don't have one of the new LED7R, you can use any LED module and simply change the code we'll use for the light up.</p> <h4>Le Code</h4> <p>The first iteration of code is simply going to check the moisture level, and light up the LED7R&nbsp; when the moisture level makes it over a certain threshold. On the Gadgeteer, you don't want to have a tight loop running from the ProgramStarted method - doing so would prevent other event handlers from running.</p> <p>The code for the sensor is really simple. If you look at the sensor itself, it appears to simply send a voltage down one side of the tongs and checks for conductivity with the other side. The driver uses a digital output for sending and an analog input for receiving. I was actually surprised to find a through-hole NPN transistor (it's a TO-932 package <a href="http://en.wikipedia.org/wiki/2N2222" target="_blank">2N2222 amplifier</a> marked 2N2222 H331) in there, as almost everything else gadgeteer-related uses surface mount components (including the two resistors on the board), but I know the 2N2222 itself is difficult (impossible?) to find in an SMT package.</p> <p>I'm far from an electronics expert, but my guess is that one side of the fork sends the regular (apx) 3.3v signal from pin 3 into the dirt/diaper. The other side will get a very faint amount of voltage transferred through the medium which it then amplifies with the transistor in order to make it meaningful to the microcontroller.</p> <p>So, instead of using a polling loop, I kick off a timer to handle polling the sensor. The timer is set to poll once per second and compare the returned value to the minimum moisture level. If the level is passed, then the LED7R animates once and then stays on. After changing the diaper, you reset the Gadgeteer to restart the program. Inelegant, but simple.</p> <pre class="brush: csharp;"> using System;<br /> using System.Threading;<br /> using Microsoft.SPOT;<br /> using Microsoft.SPOT.Presentation;<br /> using Microsoft.SPOT.Presentation.Controls;<br /> using Microsoft.SPOT.Presentation.Media;<br /> using Microsoft.SPOT.Touch;<br /> <br /> using Gadgeteer.Networking;<br /> using GT = Gadgeteer;<br /> using GTM = Gadgeteer.Modules;<br /> using Gadgeteer.Modules.Seeed;<br /> using Gadgeteer.Modules.GHIElectronics;<br /> <br /> namespace DiaperMonitor<br /> {<br /> public partial class Program<br /> {<br /> private GT.Timer _pollingTimer;<br /> private int minimumBadMoistureLevel = 200;<br /> <br /> void ProgramStarted()<br /> {<br /> Debug.Print("Program Started");<br /> <br /> _pollingTimer = new GT.Timer(1000);<br /> _pollingTimer.Tick += OnPollingTimerTick;<br /> <br /> _pollingTimer.Start();<br /> }<br /> <br /> void OnPollingTimerTick(GT.Timer timer)<br /> {<br /> int moisture = moistureSensor.GetMoistureReading();<br /> <br /> Debug.Print(moisture.ToString());<br /> <br /> if (moisture &gt; minimumBadMoistureLevel)<br /> {<br /> AlertParents();<br /> <br /> timer.Stop();<br /> }<br /> }<br /> <br /> private void AlertParents()<br /> {<br /> lED7R.Animate(10, true, true, true);<br /> }<br /> }<br /> } </pre> <p>This approach is nice, but doesn't do another loud or obvious. You'd have to keep looking in the room and checking for the lights. Chances are, the baby's own internal alarm would start sounding before you noticed the lights. In addition, this doesn't allow for any configuration of level, so on a hot summer night (thank's to Sammy Hagar, that song is now stuck in my head), there may be a general level of damp which doesn't quite meet the bar for a burst dam.</p> <p>So we have two problems: one is configuration, the second is for meaningful alerts. Let's look at configuration first.</p> <h3>Second Iteration - Configuration</h3> <p>The next step is to configure that alert level. You can leave it as a fixed value in code, or you can configure it via any number of other external inputs. One approach would be to use a potentiometer to set a threshold. Another would be to sample the current value and say that value is the "normal" value and anything well above it would be the "wet" value.</p> <p>Either approach would require some input device, like a button, to enable the timer and possibly to sample the data.</p> <p>First, I need to know what the possible values are. I couldn't find any documentation, so I simply went to the Gadgeteer codeplex site and <a href="http://gadgeteer.codeplex.com/SourceControl/changeset/view/14112" target="_blank">looked at the source code</a>. As I suspected, the sensor is an extremely simple wrapper around the analog input class. It returns a value in the range of 0 to 1600, as evidenced by this code:</p> <pre class="brush: csharp;"> /// &lt;summary&gt;<br /> /// Gets the current moisture reading.<br /> /// &lt;/summary&gt;<br /> /// &lt;returns&gt;An integer value, where 0 is fully dry and 1000 (or greater) is completely wet. &lt;/returns&gt;<br /> public int GetMoistureReading()<br /> {<br /> return (int) (analogInput.ReadProportion() * 1600.0);<br /> } </pre> <p>It also has a nice comment which isn't surfaced in the compiled version I have, so I assume that's a somewhat later rev. (Actually, I just looked in the Object Browser and there it is. I wonder why intellisense wasn't showing it? Odd.) In any case, it's useful to know you can always go and inspect the source if you have any question about how something is working at the Gadgeteer module driver level.</p> <p>So what can we do with that information? Well, let's look at the potentiometer approach.</p> <h4>Potentiometer approach</h4> <p>One thing most MCUs don't have is a large number of analog inputs. In order for a MCU to enable analog input, it has to have a digital to analog converter channel available. Most MCUs which have on-board ADC support either 10 bit or 12 bit analog conversion. The specs for the EMX module used by the Gadgeteer show that it has 7 10 bit analog inputs total. The FEZ Spider surfaces six of them, but only on two sockets. So, unless you have a multi-input devices that can use the 3 pins on a type A socket (or you create a breakout of some sort), you really end up being able to take input from only two analog modules. That leaves us with our diaper sensor and a potentiometer.</p> <p><a href="http://10rem.net/media/83193/Windows-Live-Writer_The-.NET-Gadgeteer-Diaper-Alarm_13CA5_image_13.png" target="_blank"><img src="http://10rem.net/media/83198/Windows-Live-Writer_The-.NET-Gadgeteer-Diaper-Alarm_13CA5_image_thumb_4.png" width="650" height="269" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>For this, I added a potentiometer module to the other analog socket: socket 10. The pot is going to be used to configure the minimum level at which we'll set off the diaper alarm. In addition, I added a button module that we'll use to arm the device.</p> <p>The new code refactors a few things. Explanation after the listing.</p> <pre class="brush: csharp;"> using System;<br /> using System.Threading;<br /> using Microsoft.SPOT;<br /> using Microsoft.SPOT.Presentation;<br /> using Microsoft.SPOT.Presentation.Controls;<br /> using Microsoft.SPOT.Presentation.Media;<br /> using Microsoft.SPOT.Touch;<br /> <br /> using Gadgeteer.Networking;<br /> using GT = Gadgeteer;<br /> using GTM = Gadgeteer.Modules;<br /> using Gadgeteer.Modules.Seeed;<br /> using Gadgeteer.Modules.GHIElectronics;<br /> <br /> namespace DiaperMonitor<br /> {<br /> public partial class Program<br /> {<br /> private GT.Timer _pollingTimer;<br /> <br /> private const int MoistureLevelRangeLow = 50;<br /> private const int MoistureLevelRangeHigh = 800;<br /> private int _minimumBadMoistureLevel = 200;<br /> <br /> void ProgramStarted()<br /> {<br /> Debug.Print("Program Started");<br /> <br /> button.ButtonPressed += button_ButtonPressed;<br /> }<br /> <br /> void button_ButtonPressed(Button sender, Button.ButtonState state)<br /> {<br /> Debug.Print("Button Pressed");<br /> <br /> if (_armed)<br /> {<br /> Disarm();<br /> <br /> // animate counter-clockwise and turn off<br /> lED7R.Animate(10, false, true, false);<br /> }<br /> else<br /> {<br /> Arm();<br /> lED7R.Animate(10, true, false, false);<br /> }<br /> }<br /> <br /> private void SetTriggerLevel()<br /> {<br /> // read from the pot<br /> double pot = potentiometer.ReadPotentiometerPercentage();<br /> <br /> // calculate the moisture level based on the bounds<br /> _minimumBadMoistureLevel = MoistureLevelRangeLow +<br /> (int)(pot * (MoistureLevelRangeHigh - MoistureLevelRangeLow));<br /> <br /> Debug.Print("Minimum trigger level: " + _minimumBadMoistureLevel);<br /> }<br /> <br /> bool _armed = false;<br /> private void Arm()<br /> {<br /> SetTriggerLevel();<br /> <br /> // start the timer<br /> _pollingTimer = new GT.Timer(1000);<br /> _pollingTimer.Tick += OnPollingTimerTick;<br /> <br /> _pollingTimer.Start();<br /> <br /> _armed = true;<br /> <br /> Debug.Print("Armed.");<br /> }<br /> <br /> private void Disarm()<br /> {<br /> // stop the timer<br /> _pollingTimer.Stop();<br /> _pollingTimer.Tick -= OnPollingTimerTick;<br /> <br /> _armed = false;<br /> <br /> Debug.Print("Disarmed.");<br /> }<br /> <br /> <br /> // event handler for the timer that polls the moisture sensor<br /> void OnPollingTimerTick(GT.Timer timer)<br /> {<br /> int moisture = moistureSensor.GetMoistureReading();<br /> <br /> Debug.Print(moisture.ToString());<br /> <br /> if (moisture &gt; _minimumBadMoistureLevel)<br /> {<br /> AlertParents();<br /> <br /> Disarm();<br /> }<br /> }<br /> <br /> // do all the obnoxious alert stuff in here<br /> private void AlertParents()<br /> {<br /> Debug.Print("Diaper Alert!");<br /> <br /> // animate clockwise and leave on<br /> lED7R.Animate(10, true, true, true);<br /> }<br /> }<br /> }<br /> </pre> <p>The new workflow is this:</p> <ul> <li>Set the potentiometer to some minimum trigger level. There's no readout or anything at the moment, so you'd just have to eyeball it.</li> <li>Once the pot is set, click the button to arm the diaper alert. The LEDs will cycle and you know it's armed.</li> <li>Wet the diaper (not you, personally, I hope)</li> <li>Diaper alert and then the system disarms.</li> </ul> <p>When disarming the alarm, to avoid leaks, I remove the event handler. When arming, I wire it back up. In our particular example, this doesn't buy you anything, but if you were to pull this code out into another class, it almost certainly would save you from eating up all the memory on the device over time.</p> <p>This new workflow is pretty good, but the diaper alert leaves something to be desired. You'd have to get in there to notice the LEDs (in a dark room they'd be ok), but there's nothing to really grab your attention. Clearly we can't have a piercing piezo siren or something, as that would wake up baby before the wet does.</p> <p>What other options do we have?</p> <p>Well, how about an alert that is sent to a remote device?</p> <p>That's the topic of the next post :)</p> <h3>Summary</h3> <p>Ok, that was fun :)</p> <p>For most of us, this is probably not how we'll use the Gadgeteer. Kids generally have <a href="http://www.youtube.com/results?search_query=crying+babies&amp;oq=crying+babies&amp;aq=f&amp;aqi=g10&amp;aql=&amp;gs_sm=e&amp;gs_upl=162l1874l0l1978l13l10l0l1l1l0l167l1011l3.6l9l0" target="_blank">pretty good built-in wet diaper alarms</a> as it is. However, you can use this sensor for just about anything from plant moisture detection to water leak detection to more. More importantly, this post shows how to use an analog sensor of any type, including how to configure the range and some other useful NETMF tips.</p> <p><a href="http://feedads.g.doubleclick.net/~a/Sx6v20tMCk4PVkFoe4pcprQO9rk/0/da"><img src="http://feedads.g.doubleclick.net/~a/Sx6v20tMCk4PVkFoe4pcprQO9rk/0/di" border="0" ismap="true"></img></a><br/> <a href="http://feedads.g.doubleclick.net/~a/Sx6v20tMCk4PVkFoe4pcprQO9rk/1/da"><img src="http://feedads.g.doubleclick.net/~a/Sx6v20tMCk4PVkFoe4pcprQO9rk/1/di" border="0" ismap="true"></img></a></p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=ly1EjFTELxs:ArD4Ii1KiHE:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=ly1EjFTELxs:ArD4Ii1KiHE:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=ly1EjFTELxs:ArD4Ii1KiHE:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=ly1EjFTELxs:ArD4Ii1KiHE:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=ly1EjFTELxs:ArD4Ii1KiHE:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=ly1EjFTELxs:ArD4Ii1KiHE:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=ly1EjFTELxs:ArD4Ii1KiHE:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=ly1EjFTELxs:ArD4Ii1KiHE:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=ly1EjFTELxs:ArD4Ii1KiHE:gIN9vFwOqvQ" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/PeteBrown/~4/ly1EjFTELxs" height="1" width="1"/> http://feedproxy.google.com/~r/PeteBrown/~3/ly1EjFTELxs/the-net-gadgeteer-diaper-alarm-part-1-moisture-sensor Pete Brown 3566 2012-01-30T23:22:37 The Last Catfish in the East Village? <p> People who live in New York City often inhabit tiny apartments, and the only reason we tolerate them is that we've exchanged private spaces for public spaces. We can frequently be found not in our apartments but walking around outside, or in a store, or a theater, or a concert hall, or a museum. </p><p>... more ...</p> http://www.charlespetzold.com/blog/2012/01/The-Last-Catfish-in-the-East-Village.html Charles Petzold 3565 2012-01-30T19:40:41 BAOC Countdown and WPAppItUp Wrap-Up <p><b>Big App on Campus: Two Weeks Left!</b></p> <p>Back in November, we <a href="http://windowsteamblog.com/windows_phone/b/wpdev/archive/2011/11/18/do-you-have-what-it-takes-to-be-the-big-app-on-campus.aspx">announced</a> a developer promotion for US students called “Big App on Campus.” There are exactly 18 days left to enter. Though we think it’s a no brainer, some of you have asked “Why should I enter?” Let’s recap:</p> <p>1. <b>For the experience of a lifetime</b> -&gt; 10 finalists, along with one of their friends, will win a trip to SxSW in March. If selected as a finalist, you and your friend will get to come hang out with <a href="http://www.thegraciousfew.com/">The Gracious Few</a> (featuring members of the bands <a href="http://youtu.be/FNrQOUtXYOo">LIVE</a> and <a href="http://youtu.be/JWhXyNL74yI">Candlebox</a>) and attend a rocking concert.</p> <p>2. <b>$30k in prize money</b> -&gt; the top paid app and the top free app will each win $15,000!</p> <p><em>3. </em><b>Serious bragging rights</b> -&gt; finalist apps will be featured on our Facebook page and the developers behind these creations will have some crazy stories to tell about their time in Austin at SxSW.<em></em></p> <blockquote> <p><em><font size="2">&lt;aside reason=”toAppeaseTheLawyers”&gt;No Purchase Necessary. Open only to US university students 18+ who are legal residents of the U.S. and D.C. Submissions due 02/14/2012 and game ends 03/13/2012. For Official Rules, click </font></em><a href="http://www.microsoft.com/student/bigapponcampus/"><em><font size="2">here</font></em></a><em><font size="2">&lt;/aside&gt;</font></em></p> </blockquote> <p>All Windows Phone applications published since August 1, 2011 are eligible for entry. However all apps must be published to the Marketplace by February 14<sup>th</sup>. Make your Valentine proud and <a href="http://www.zoomerang.com/Survey/WEB22DP5BYJKZH/">enter</a> your app today – I’m sure she/he won’t mind helping you spend the $15k in winnings up for grabs. Check out our Facebook <a href="http://www.facebook.com/MicrosoftTechStudent?sk=app_269100103148944">page</a> for all details and information on how to get started on building your first, or next, Windows Phone app.</p> <p><b>&#160;</b></p> <p><b>#WPAppItUp Wrap-Up</b></p> <p>Starting back in October, we challenged students to create Sketchflow prototypes of their app ideas for Windows Phone. I’m happy to announce the full list of winners:</p> <p><a href="http://www.twitter.com/cbarretopy">@cbarretopy</a></p> <p><a href="http://www.twitter.com/simzzdev">@simzzdev</a></p> <p><a href="http://www.twitter.com/m_naveed4u">@m_naveed4u</a></p> <p><a href="http://www.twitter.com/sp990">@sp990</a></p> <p><a href="http://www.twitter.com/gowtham1337">@gowtham1337</a></p> <p><a href="http://www.twitter.com/3xdev">@3xdev</a></p> <p><a href="http://www.twitter.com/utebolatas">@utebolatas</a></p> <p><a href="http://www.twitter.com/sakarshkumar">@sakarshkumar</a></p> <p><a href="http://www.twitter.com/sriharsha_63">@sriharsha_63</a></p> <p><a href="http://www.twitter.com/luciomsp">@luciomsp</a></p> <p>Congratulations to all the winners!</p> <p>Ben</p> <p><a href="http://twitter.com/benlower">@benlower</a> | <a href="mailto:phoneninja@microsoft.com?subject=Saw%20you%20on%20WPDev%20blog">phoneninja@microsoft.com</a> | +1 (206) 659-NINJA (6465)</p><div style="clear:both;"></div><img src="http://windowsteamblog.com/aggbug.aspx?PostID=575282" width="1" height="1"> http://windowsteamblog.com/windows_phone/b/wpdev/archive/2012/01/27/baoc-countdown-and-wpappitup-wrap-up.aspx Windows Phone Dev Blog 3562 2012-01-27T20:01:43 Playing A Sound, Simplified http://feedproxy.google.com/~r/JesseLiberty-SilverlightGeek/~3/-dIhlb0Gt-4/ Jesse Liberty [MS] 3561 2012-01-27T17:49:25 The n00b filter: Bad UX at its Finest in Eagle PCB <p>Speaking of UX…</p> <p>I finally decided to download and learn to use the industry-standard PCB and schematic layout software: Eagle. I've tried a bunch of others, and quite frankly, got tired of always using "also ran" software. The majority of the info on the web is for Eagle. It certainly doesn't have the best UI or the best workflow, but it has absolutely the most amount of information and the best support from PCB manufacturers. It's the industry standard, and like most industry-leading technical software (ever use industry-leading 3d modeling software? Gak!), it has some crazy issues.</p> <p>Here's the workflow. First, while working on the Schematic, you click this "Add" toolbar button</p> <p><a href="http://10rem.net/media/83112/Windows-Live-Writer_The-n00b-filter-Bad-UX-at-its-Finest_13D66_image_4.png" target="_blank"><img src="http://10rem.net/media/83117/Windows-Live-Writer_The-n00b-filter-Bad-UX-at-its-Finest_13D66_image_thumb_1.png" width="650" height="428" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>Next, you're shown a screen with the libraries on the left, and the selected part on the right. You can browse the libraries here, but it is not something I went into with the intent of using it to manage library entries.</p> <p><a href="http://10rem.net/media/83122/Windows-Live-Writer_The-n00b-filter-Bad-UX-at-its-Finest_13D66_image_2.png" target="_blank"><img src="http://10rem.net/media/83127/Windows-Live-Writer_The-n00b-filter-Bad-UX-at-its-Finest_13D66_image_thumb.png" width="649" height="439" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>I wanted to add the component, but I wasn't sure which button to press. Silly me, thought maybe "drop" meant to "drop it on the schematic" because, for whatever reason, "OK" didn't seem right.</p> <p><strong>Wrong.</strong></p> <p>"Drop", without so much as a confirmation MessageBox removes the library from the parts libraries on your computer. Yeah, so now I need to go find the library which contains every type of diode, because, umm, I deleted it.</p> <p><strong>At first, I thought I actually deleted it, but it turns out Eagle marks it to make it not show up in the Add dialog.</strong> I'm still going to finish this post anyway, because the brick was already passed painfully through the orifice when the library just went *poof* off the list.</p> <p>To restore it, you have to go into their separate Control Panel application (hint: if your app has a "control panel" app, there's an issue). That's better than having to reinstall the product, or download the library from RapidItsNotReallyATrojanWeSwearShare.com, but it's not entirely intuitive.</p> <p><a href="http://10rem.net/media/83132/Windows-Live-Writer_The-n00b-filter-Bad-UX-at-its-Finest_13D66_image_6.png" target="_blank"><img src="http://10rem.net/media/83137/Windows-Live-Writer_The-n00b-filter-Bad-UX-at-its-Finest_13D66_image_thumb_2.png" width="650" height="432" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p><strong>This type of feature can only be called a n00b filter</strong>, although I'm sure there's a more technical UX antipattern name for it, probably one which includes a four-letter word or two.</p> <p>I have a lot of experience in software. I rarely need to be hand-held, and the last time I took a class to learn how to use a piece of software was to be a Novell 4 CNA in the mid 90s, and I took that class *after* I had already set up the network. I almost never read manuals, and use "Help" in apps maybe 5 times a year total, and only because I'm trying new stuff all the time. All I'm trying to say here, is I'm not afraid of software, and I very rarely do something which destroys work or accidentally does a format c:\ or anything.</p> <p>Seriously. No confirmation. It's a button on the "Add Component" screen.</p> <p>No wonder users hate us.</p> <p><a href="http://feedads.g.doubleclick.net/~a/UM7vrnqiIN3UY0AP7h5tuKbjwVo/0/da"><img src="http://feedads.g.doubleclick.net/~a/UM7vrnqiIN3UY0AP7h5tuKbjwVo/0/di" border="0" ismap="true"></img></a><br/> <a href="http://feedads.g.doubleclick.net/~a/UM7vrnqiIN3UY0AP7h5tuKbjwVo/1/da"><img src="http://feedads.g.doubleclick.net/~a/UM7vrnqiIN3UY0AP7h5tuKbjwVo/1/di" border="0" ismap="true"></img></a></p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=a5Pb2Q2n6uQ:PyydrwzG00M:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=a5Pb2Q2n6uQ:PyydrwzG00M:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=a5Pb2Q2n6uQ:PyydrwzG00M:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=a5Pb2Q2n6uQ:PyydrwzG00M:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=a5Pb2Q2n6uQ:PyydrwzG00M:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=a5Pb2Q2n6uQ:PyydrwzG00M:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=a5Pb2Q2n6uQ:PyydrwzG00M:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=a5Pb2Q2n6uQ:PyydrwzG00M:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=a5Pb2Q2n6uQ:PyydrwzG00M:gIN9vFwOqvQ" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/PeteBrown/~4/a5Pb2Q2n6uQ" height="1" width="1"/> http://feedproxy.google.com/~r/PeteBrown/~3/a5Pb2Q2n6uQ/the-n00b-filter-bad-ux-at-its-finest-in-eagle-pcb Pete Brown 3559 2012-01-27T03:55:54 Maker Geek Roundup 006 for 1/25/2012 <p>The Maker Geek Roundup aggregates information of interest to makers everywhere. Topics include .NET Micro Framework, CNC, 3d Printing, Robotics, Microsoft Robotics Studio, Electronics, General Maker stuff, and more. If you have something interesting you've done or have run across, or you blog regularly on the topics included here, please send me the URL and brief description via the <a href="http://10rem.net/contact">contact link</a>.</p> <h3>3d Printing and CAD/CAM/CNC</h3> <ul> <li><a href="http://blog.ultimaker.com/2012/01/25/working-3d-printed-helicopter-blades/"> Working 3D printed helicopter blades</a> (Ultimaker)</li> <li><a href="http://richrap.blogspot.com/2012/01/slic3r-is-nicer-part-3-how-low-can-you.html"> Slic3r is Nicer - Part 3 - How low can you go?</a> (RichRap)</li> <li><a href="http://blog.rhino3d.com/2012/01/rhinocam-2012-is-latest-version-of.html"> RhinoCAM 2012 to Release February 6, 2012</a> (Rhino News)</li> <li><a href="http://blog.thingiverse.com/2012/01/25/the-3d-printing-troubadours-of-pocket-factory/"> The 3D Printing Troubadours of Pocket Factory!</a> (Thingiverse)</li> <li><a href="http://arduino.cc/blog/2012/01/10/circuit-milling-with-roland-imodela-now-available-on-arduino-store/"> Circuit Milling With Roland iModela, Now Available on Arduino Store</a> (Arduino Blog)</li> </ul> <h3>.NET Gadgeteer</h3> <ul> <li><a href="http://www.breakcontinue.com/2012/01/arduino-daisylink-module-for-gadgeteer.html"> Take a break: Arduino DaisyLink module for Gadgeteer</a> (Valentin Ivanov)</li> <li><a href="http://devhammer.net/hardware">Devhammer's Garage (Info on the IR LED module Andrew created)</a> (G. Andrew Duthie)</li> </ul> <h3>.NET Micro Framework General (Netduino, GHI FEZ, etc.)</h3> <ul> <li><a href="http://www.pix6t4.com/">PIX-6T4 - The PIX-6T4 Game Console</a> (Fabien Royer, Bertrand LeRoy)</li> <li><a href="http://blogs.msdn.com/b/netmfteam/archive/2012/01/09/new-netmf-book-out-for-v4-1-and-v4-2.aspx"> New NETMF Book out for v4.1 and v4.2</a> (Colin Miller)</li> <li><a href="http://mikedodaro.net/2012/01/21/text-to-speech-for-net-micro-framework/"> Text-To-Speech for .NET Micro Framework</a> (Marco Minerva)</li> <li><a href="http://mikedodaro.net/2011/12/14/xml-configuration-files-for-net-micro-framework-applications-english/"> XML Configuration Files for .NET Micro Framework Applications (English)</a> (Marco Minerva)</li> <li><a href="http://blogs.msdn.com/b/laurelle/archive/2012/01/21/using-a-light-transistor-sensor-and-a-led-to-create-a-detector.aspx"> Using a light transistor sensor and a led to create a detector</a> (Laurent Ellerbach)</li> </ul> <h3>Arduino</h3> <ul> <li><a href="http://arduino.cc/blog/2012/01/16/control-an-lcd-with-a-595-shift-register/"> Control An LCD with a 595 Shift Register</a> (Arduino Blog)</li> </ul> <h3>Other Micro Controllers (PIC, AVR, ARM and more)</h3> <ul> <li><a href="http://www.mikroe.com/eng/news/view/418/easypic-pro-v7-is-released/"> EasyPIC PRO v7 is released!</a> (MikroElektronika)</li> <li><a href="http://dangerousprototypes.com/2012/01/25/breakout-board-for-the-44pin-qfn-atxmega-microcontroller/"> Breakout board for the 44pin QFN ATxmega microcontroller</a> (Dangerous Prototypes)</li> </ul> <h3>General Electronics and Hardware Hacking</h3> <ul> <li><a href="http://blog.ianlee.info/2012/01/quick-tip-making-momentary-buttons.html"> Making Momentary Buttons Breadboard Friendly</a> (Software and Sawdust)</li> <li><a href="http://circuit-zone.com/index.php?electronic_project=659">555 LED Pulsing Breathing Circuit</a> (Circuit Zone)</li> <li><a href="http://citizenscientistsleague.com/2012/01/24/a-curiously-low-noise-amplifier/"> A Curiously Low Noise Amplifier</a> (Citizen Scientists League)</li> <li><a href="http://circuit-zone.com/index.php?electronic_project=658">1.5V FM Broadcast Transmitter</a> (Circuit Zone)</li> <li><a href="http://dangerousprototypes.com/2012/01/25/the-phone-box/">The phone box</a> (Dangerous Prototypes)</li> <li><a href="http://www.electronics-lab.com/blog/?p=16394">LED brightness controller with 64 taps</a> (Electronics Lab)</li> </ul> <h3>Robotics and Robotics Studio</h3> <ul> <li><a href="http://robotgrrl.com/blog/2012/01/23/brrd-brain-board-more-progress-less-zigzags/"> Brrd Brain Board: More progress &amp; less zigzags</a> (RobotGrrl)</li> </ul> <h3>Clocks</h3> <ul> <li><a href="http://hackaday.com/2012/01/25/tutorial-build-a-manifold-clock-for-10/"> Tutorial: Build a manifold clock for $10</a> (Hack a Day)</li> </ul> <h3>Synthesizers, MIDI and Electronic Instruments</h3> <ul> <li><a href="http://highlyliquid.com/blog/?p=852">Meng Qi's Wicki-Hayden MIDI Controller</a> (Highly Liquid)</li> <li><a href="http://highlyliquid.com/blog/?p=839">Trojan Chorus: Pinata as MIDI Controller</a> (Highly Liquid)</li> </ul> <h3>Photography</h3> <ul> <li><a href="http://www.diyphotography.net/diy-small-circular-softboxes">DIY: Small Circular Softboxes</a> (DIY Photography)</li> <li><a href="http://www.diyphotography.net/super-high-speed-footage-of-a-60d-exposure-cycle"> Super High Speed Footage Of A 60D Exposure Cycle</a> (DIY Photography)</li> <li><a href="http://www.diyphotography.net/using-a-double-flash-bracket-to-add-modeling-light-to-your-setup"> Using A Double Flash Bracket To Add Modeling light To Your Setup</a> (DIY Photography)</li> </ul> <h3>General Maker</h3> <ul> <li><a href="http://brando.ie/tweetsweets/">Tweet Sweet</a> (Brando)</li> <li><a href="http://vonkonow.com/wordpress/2012/01/software-for-home-automation/"> Software for web controlled home automation</a> (Johan von Konow)</li> </ul> <h3>Retro Computing and Commodore!</h3> <ul> <li><a href="http://www.mos6502.com/general-blogness/retro-game-fair-the-netherlands/"> Retro Game Fair, The Netherlands</a> (MOS6502)</li> <li><a href="http://www.rgcd.co.uk/2011/12/c64anabalt-c64-2011.html">C64anabalt (C64) (2011)</a> (RGCD)</li> <li><a href="http://www.mos6502.com/friday-commodore/commodore-inside/">Commodore Inside!</a> (MOS6502)</li> <li><a href="http://www.rgcd.co.uk/2012/01/hydra-castle-labyrinth-pc.html"> Hydra Castle Labyrinth (PC)</a> (RGCD)</li> </ul> <h3>Misc Geek</h3> <ul> <li><a href="http://vihart.com/blog/spongebob/">Open Letter to Nickelodeon, Re: SpongeBob's Pineapple under the Sea</a> (Vi Hart)</li> <li><a href="http://this8bitlife.com/this-8-bit-life/2012/1/13/cyberpunk-style-workstation-is-pretty-sexy.html"> Cyberpunk style Workstation is Pretty Sexy</a> (This 8 bit Life)</li> <li><a href="http://this8bitlife.com/this-8-bit-life/2012/1/24/amazing-legend-of-zelda-zora-armor-cosplay.html"> Amazing Legend of Zelda Zora Armor Cosplay</a> (This 8 bit Life)</li> </ul> <h3>Just Awesome</h3> <ul> <li><a href="http://www.youtube.com/watch?feature=player_embedded&amp;v=1wwilCs4Jqg"> You'll either thank me, or burn my house down for this one. Either way, those brain cells aren't coming back.</a> (YouTube)</li> </ul> <p><a href="http://feedads.g.doubleclick.net/~a/Clsbo6NvjY3r5PY3v6WfNJlE3fM/0/da"><img src="http://feedads.g.doubleclick.net/~a/Clsbo6NvjY3r5PY3v6WfNJlE3fM/0/di" border="0" ismap="true"></img></a><br/> <a href="http://feedads.g.doubleclick.net/~a/Clsbo6NvjY3r5PY3v6WfNJlE3fM/1/da"><img src="http://feedads.g.doubleclick.net/~a/Clsbo6NvjY3r5PY3v6WfNJlE3fM/1/di" border="0" ismap="true"></img></a></p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=PVD4L9hWMF4:odUC5g5Bsdw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=PVD4L9hWMF4:odUC5g5Bsdw:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=PVD4L9hWMF4:odUC5g5Bsdw:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=PVD4L9hWMF4:odUC5g5Bsdw:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=PVD4L9hWMF4:odUC5g5Bsdw:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=PVD4L9hWMF4:odUC5g5Bsdw:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=PVD4L9hWMF4:odUC5g5Bsdw:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=PVD4L9hWMF4:odUC5g5Bsdw:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=PVD4L9hWMF4:odUC5g5Bsdw:gIN9vFwOqvQ" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/PeteBrown/~4/PVD4L9hWMF4" height="1" width="1"/> http://feedproxy.google.com/~r/PeteBrown/~3/PVD4L9hWMF4/maker-geek-roundup-006-for-1-25-2012 Pete Brown 3557 2012-01-25T20:08:25 Now, more than ever, you need a designer <p>Before joining Microsoft, I was a consultant, primarily building desktop applications using a variety of MS technologies. During my last couple years there, Silverlight was a large part of that both for full apps and as parts of larger web sites. Prior to that, it was WPF, Windows Forms, VB, HTML and even SharePoint.</p> <blockquote> <p><strong>tl;dr:</strong> The point of this long post is not to show you examples of good design or pick apart existing designs. I'm not really qualified to do that. However, I can point out the need for design and give you some small amount of ammunition when presenting this to your own management. Visual and UX Design matters, even for internal apps, often far more than architecture or the other things we focus on. You'll be more efficient with a designer on-team, who you can iterate with. The world is evolving and we need to keep up. Go hire one now.</p> <p><strong>tl;dr the tl;dr:</strong> Hire a UX/Interaction designer.</p> </blockquote> <p><strong>The company I worked at wouldn't hire a UX/Visual designer.</strong> Why? Because they felt they could <strong>never sell the benefit of good UX and visual design to customers</strong>, and couldn't keep a designer busy 100% of the time. The problem was, without a portfolio of well-designed UI and sites, it became self-fulfilling. I had contended that if they hired one, they'd be amazed at just how busy that person would end up being. Quite frankly, they just didn't see the value.</p> <p>It got to the point that when I walked into my management's office, they'd be like "You're not going to tell us to hire a designer again, are you?"</p> <p><em>You may even be</em> <a href="http://10rem.net/blog/2010/11/19/windows-forms-to-xaml-do-i-really-need-a-designer-for-silverlight-or-wpf-applications" target="_blank"><em>thinking the same thing</em></a><em>, this post may see like Déjà vu if you've followed my blog for a few years :) I took a more conservative approach to the problem in that 2010 post. Basically saying the same types of things</em> <a href="http://www.hanselman.com/blog/SkipIntroCSS3IsTheNewFlash.aspx" target="_blank"><em>Scott Hanselman recently pointed out in his Skip Intro post</em></a><em>: don't over do it, and don't use things just because they're there. In that post, I argued that if you want to just keep making the same old battleship gray applications, you don't *need* a designer. However, I still think you can benefit from one in your projects regardless. So, I'm going to backtrack a little bit and deliver a more absolute form of the message: yes, you need a designer. Whether it is HTML/JS/CSS, or XAML/C#/VB, or something else, you should have design talent on staff.</em></p> <p>For a bit, we toyed around with the idea of partnering with an outside firm. The problem was, there was too much of a "hand off" approach to the design. Without having the design talent on-staff, you couldn't iterate during the project. The design was passed in at the beginning and then slowly destroyed by the developers (or people like me who had good UX but horrible Graphics design skills) over time.</p> <p><a href="http://bizarrocomic.blogspot.com/2010/06/tough-guy-ugly-baby-free-show.html" target="_blank"><img src="http://10rem.net/media/82999/Windows-Live-Writer_a2371b66e292_D4C8_image_22.png" width="270" height="317" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>I likened it to other disciplines, like partnering with a firm just to design the database. Sure, design it all up-front and then make the project live with that throughout the rest of the lifecycle. No one found that to be a sane idea, but still couldn't see the parallel with UX and Graphics design.</p> <p>Now, in their defense, the company primarily worked on large-scale transaction processing systems. However, the business had slowly evolved to include more commercial work, and more intranet and internet sites for these same customers. Also, in their defense, our customers felt the same way. They wanted really great UX and graphics, but somehow felt those things simply fell from the sky. They didn't want to pay for designers on projects either. <strong>They were still stuck in the team makeup and ideas that worked for mainframe applications and, as in most cases, haven't moved on.</strong></p> <blockquote> <p>One thing the enterprise development community in general has been slower to adopt is the idea that you really do need visual and UX design talent on staff. <strong>Application success or failure rarely comes from architecture, or reuse, or whether or not you use stored procedures or which ORM you use.</strong> Those are things we do to meet other, more internal, goals, most of which users don't care about in the least, many of which offer more perceived benefit than actual real project benefit. As Scott mentioned in another post, <a href="http://www.hanselman.com/blog/YourUsersDontCareIfYouUseWebSockets.aspx" target="_blank">users don't care if you use Web Sockets</a>. Sure, if you really botch the architecture, the app may be unusable, but beyond that, your investment is better spent elsewhere.</p> </blockquote> <p><a href="http://www.flickr.com/photos/binaryape/458758810/" target="_blank"><img src="http://10rem.net/media/83004/Windows-Live-Writer_a2371b66e292_D4C8_image_16.png" width="650" height="139" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <h3>Knowing Your Limits</h3> <p>Yesterday, <a href="http://www.hanselman.com/blog/SkipIntroCSS3IsTheNewFlash.aspx" target="_blank">Scott Hanselman blogged about the emerging trend to throw a dog's breakfast of features into HTML5/CSS3/JS sites</a>. He and I chatted about it for a little, and felt I should write something up here as well. Go read his post as well.</p> <p><strong>It's natural for developers to push the boundaries when a new technology comes out.</strong> That's how we learn. That's fine for demo sites in developer echo chambers and <a href="http://www.youtube.com/results?search_query=c64+compo" target="_blank">compos</a>, but <strong>don't do it in front of actual users</strong>. It's too easy to have your app look and perform like a Pirate's idea of wealth: all money and no style. Scott has links to a few examples of that in his post. There are a couple other good ones in the comments.</p> <p>How did we get to this point? Why do so many still not even realize we're here?</p> <h3>Modern Development</h3> <p>First, a little history:</p> <p><img src="http://10rem.net/media/83009/Windows-Live-Writer_a2371b66e292_D4C8_image_40.png" width="213" height="155" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/><a href="http://www.flickr.com/photos/vax-o-matic/5625208727/" target="_blank"><img src="http://10rem.net/media/83014/Windows-Live-Writer_a2371b66e292_D4C8_image_35.png" width="223" height="155" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a><img src="http://10rem.net/media/83019/Windows-Live-Writer_a2371b66e292_D4C8_image_38.png" width="209" height="155" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/>&nbsp;</p> <p><img src="http://10rem.net/media/83024/Windows-Live-Writer_a2371b66e292_D4C8_image_39.png" width="192" height="245" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/><a href="http://www.amazon.com/Wordperfect-5-1-Toolbox-Keyboard-Template/dp/078211007X/ref=cm_cmu_pg__header" target="_blank"><img src="http://10rem.net/media/83029/Windows-Live-Writer_a2371b66e292_D4C8_image_43.png" width="453" height="245" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>I don't wear a suit to work. In fact, I work from home, so what I wear barely counts as clothing some days. I also don't sit in front of a highly non-ergonomic greenscreen device, trying to remember arcane codes (ok, well I do when I'm messing around with microcontrollers or old computers). Why? Because the world has moved on from that. Gradually over the years, more and more UX thought has been given to applications.</p> <ul> <li>When applications were just command-line affairs, the only UX you really had to worry about was how hard the transaction codes were to remember. Most of the UX was the huge three-ring binder manual or the multiple volume boxed sets with textured cloth covers. Users often spent as much time in that as interacting with the screen, especially during their first X months. <strong>Graphics were Escher prints you hung on the wall.</strong> Computers were <strong>supposed to be hard</strong>, for some unknown reason. Engineering ruled the experience, and we didn't know any better.</li> <li>When they became full-screen character mode applications (Curses, anyone? No? How about the <a href="http://www.lanet.lv/simtel.net/msdos/turbo_c.html" target="_blank">windowing libraries for DOS TurboC</a>/C++ apps? IBM 3270? No? Pah. Youngsters.) there was more UX to worry about, but the layout and workflow choices were still so limited as to make it easier for a dev with a good eye to come up with something decent. <strong>Graphics were things scientists used for data visualization</strong>. Design was for <a href="http://www.thedieline.com/blog/2009/11/17/the-evolution-of-the-coca-cola-contour-bottle.html" target="_blank">companies making physical products customers had to hold in their hands</a>. An entire industry was built around plastic-coated cardboard keyboard templates to help you remember all the keyboard shortcuts required to navigate important applications, especially for DOS. I blame WordPerfect.</li> <li>When apps became battleship gray forms over data (white 2d forms first), <strong>UX consisted mainly of making sure you had a decent tab order and "fit as much as possible" on a single screen</strong>. Navigation often resembled those character mode applications we were upgrading/scraping/rewriting because our users didn't know any better, and we didn't know how to show them something else and prove it would be more efficient and/or easier. Things started to go south here. <strong>Graphics were for games and maybe 16x16 16 color icons</strong>. <a href="http://www.youtube.com/watch?v=lAD6Obi7Cag" target="_blank">Animation was for music videos</a>.</li> <li style="list-style: none"> <ul> <li>Early on, apps were even just black and white instead of gray. But when the gray "3d" chiseled look started coming into vogue late in Win 3.11's lifetime (there was a special common controls library just for it), developers went nuts and had apps that looked like Mayan pyramids. Borders within borders within borders. Uuuuugly. And I did it too. It was new. It was exciting, and it was abused.</li> </ul> </li> <li>When the web started making inroads into application development, UX became further complicated. First, the workflow options for early web apps really blew. <strong>Many apps had two buttons "Submit" and "Reset" and a big form above them</strong>. Validation and all other processing mostly took place server-side. Sometimes, we got clever, and sent all the data through an iframe to avoid a full page refresh. We made excuses because that's how all the other apps were working, and we didn't take much inspiration from branded experiences. However, at least they often looked nicer than those battleship gray apps. That made a real impression on people. Hmm. Graphics. Colors. Whitespace. Animation was for dancing hamsters or Pixar.</li> <li>And then the proliferation of consumer-oriented smart phones and tablets with great UX, driven in no small part by Apple, <strong>really brought UX and visual design to the front</strong>. It's not because the platform had a great API or something (I've never worked on it, but I hear the platform, from a programming and design standpoint is … interesting), but because it attracted a lot of designer types. It's no accident that companies like Apple and Microsoft chose design firms to create the first showcase prototypes of their new UI technologies. Now, even inside the enterprise, many customers expect this level of UX in their own applications. Graphics, colors, whitespace, touch, animation, easing and more all become important parts of the visual design, and it's <a href="http://kellabyte.com/2011/12/19/when-metro-design-falls-off-the-tracks/" target="_blank">very easy to get it wrong</a> unless you have a <a href="http://www.riagenic.com/archives/751" target="_blank">talent for design</a>.</li> <li style="list-style: none"> <ul> <li>Your users now and in the future are ones brought up on this crop of highly visual applications. What do you think they will have for expectations?</li> </ul> </li> </ul> <p>But now we're stuck, because we have the tools to do whatever we want, but haven't evolved the teams to effectively make use if them.</p> <p>We've had tools and platforms to build these types of apps for some time. Flash has been around forever, Silverlight since 2007, and finally, HTML5/CSS3 and its support in browsers is mostly catching up to where FutureSplash was in 1996. <strong>The capabilities are there, we just need to use them for good.</strong></p> <p>It's not just for consumer-oriented apps, either. As companies consolidate their development staff, expose more things outside the firewall, or work to support a large number of internal users, the line between consumer and enterprise development continues to thin.</p> <p>For grins, here are some apps I wrote in the 90s and early 2000-ish, where I happened to have saved some screen shots (I really wished I had saved more, especially the dBase/FoxPro apps I wrote for DOS and the VB3-6 and PowerBuilder ones for Windows 3.11). The first one was written for DOS entirely in Borland C++ (including the database) the others were, as I recall, .NET 1.0 beta versions of VB4 apps I wrote earlier. in the first one, I mainly just had to worry about tab order. In the second, the users were most comfortable with filling out an online version of the paper form (in fact, they'd have the paper form in front of them while doing this). The third was using the typical "Make it look like Outlook" model of the time.</p> <p><a href="http://10rem.net/media/83034/Windows-Live-Writer_a2371b66e292_D4C8_image_28.png" target="_blank"><img src="http://10rem.net/media/83039/Windows-Live-Writer_a2371b66e292_D4C8_image_thumb_10.png" width="400" height="188" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>That version actually looked quite a bit better on a giant 15" CRT, perched high enough up to count as neck-stretching exercise. :)</p> <p><a href="http://10rem.net/media/83044/Windows-Live-Writer_a2371b66e292_D4C8_image_24.png" target="_blank"><img src="http://10rem.net/media/83049/Windows-Live-Writer_a2371b66e292_D4C8_image_thumb_8.png" width="320" height="225" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a><a href="http://10rem.net/media/83054/Windows-Live-Writer_a2371b66e292_D4C8_image_26.png" target="_blank"><img src="http://10rem.net/media/83059/Windows-Live-Writer_a2371b66e292_D4C8_image_thumb_9.png" width="320" height="224" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>Like so many other developers, I simply copied prevalent design trends of the time (how many devs have you talked to back in the day who said they were trying to make their app look like Outlook or Visual Studio/Visual Basic?). I got away with it, but you can see that it doesn't 100% work. <strong>I force fit some things due to the limited palette of visual design patterns at my disposal</strong>. Bonus points: battleship gray.</p> <h3>Is it Customer-Facing?</h3> <p>I've heard many people say that they'll only invest in UX for customer-facing stuff. But who is the customer?</p> <p>It depends on how you define your customer. For many IT shops, the customer works for the same company. For sales apps, many times the field laptop/tablet application is seen by both a sales person and the customer. Many of the same things you'd do in a consumer application apply to these same customers, but <strong>because they're forced to use your app, they don't get the same attention to UX</strong> that external true consumer apps do.</p> <p>Here's a list of some common types of applications being built today, or in the near future. Tell me where UX doesn't matter? Which is customer-facing?</p> <ul> <li>Call center apps inside an organization</li> <li>The departmental day-to-day work application at your company</li> <li>Consumer touch-oriented apps on phones and tablets</li> <li>Consumer apps on the desktop</li> <li>Enterprise shrink-wrapped products for the desktop</li> <li>Your intranet site</li> <li>That forms-over-data application everyone in the company uses</li> <li>Time and expense reporting systems</li> <li>Your one-off shell script to update a bunch of database tables</li> </ul> <p>Ok, so I through the shell script in there just to have something where you could get away without UX. Of course, there's often some design put in there too. Did you take a moment to set up different command line arguments? UX, just no pretty graphics :)</p> <blockquote> <p>How many times have you heard "Sorry, the computer is really slow today" when you talk to someone at a call center? Typically this is because it takes forever to accomplish anything on their crappy apps. Sometimes, of course, they have a 9600bps serial connection from wherever they are to wherever the data is, but most of the time it's just a crap UI that takes forever to help you, or they've forgotten how to do a certain thing in the UI because it's so non-intuitive. I've seen these apps up close. I've seen the massive amount of training that people have to go through to learn them. Some of the most horrendous UX I've ever seen was in an in-house call center application to take outage reports at a power company - one of their most critical ways to help customers. Are they not worth better UX?</p> </blockquote> <p><strong>UX is important for all those applications</strong>. <strong>The more the application gets used, the more good or bad UX comes into play.</strong> It's not just about selling the application and getting 5 stars, it's also about making others more efficient and making their lives a little less hellish. Making them feel good while using it is a nice bonus.</p> <p>Most developers, let's not kid ourselves, are simply not well-equipped to make good UX decisions. They're too embedded in the software, <strong>and too aware of the underlying code and architecture changes that a change in UX would require</strong> so they push back, or don't even consider the things that really should be done. Or they build the system back-to-front and the UI, by necessity, resembles the data structures they used throughout the app. Oh, and changing the UX of an application is one of those things that becomes becomes far more expensive as you wait. UX is the entire workflow of the application. It touches just about everything.</p> <p><a href="http://www.flickr.com/photos/drewmaughan/6425581707/in/photostream/" target="_blank"><img src="http://10rem.net/media/83064/Windows-Live-Writer_a2371b66e292_D4C8_image_5.png" width="650" height="127" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>What about graphics? In companies, "Designer" often encompasses both UX and Visual/Graphics design. Often, good UX designers also have a decent visual design background as well, just as developers often have more than one related skill.</p> <h3>Just go Find Some Free Icons</h3> <p>That's something I heard over and over, and you probably hear it too. "Go find some clipart" or "go find a free icon set". Ugh. Invariably, the icon set would only have 1/3 of the required icons, and the remaining ones would have to magically appear. I was able to do that (Axialis Icon Designer saw a lot of me back then), not anywhere near as well as the original designer, but well enough. There were many other applications I saw which had different icons from various sets, with incompatible styles, all mashed together on the same toolbar.</p> <p>The same thing applies to site themes, css, and more. "Just go find a template" is almost as bad as "go find some free icons".</p> <p>There are more choices today, but you still end up with those toolbars (or pages, or whatever) where half the icons look good, and the other half show some bad image with a three letter acronym over it.</p> <p>They all have <a href="http://www.bing.com/images/search?q=splash+screen" target="_blank">splash screens</a> though, and with clip art. Maybe even from MS Word. :)</p> <p><a href="http://office.microsoft.com/en-us/images/results.aspx?qu=screenbeans" target="_blank"><img src="http://10rem.net/media/83069/Windows-Live-Writer_a2371b66e292_D4C8_image_19.png" width="650" height="68" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>In some cases, the UI starts to resemble that PTA fund raising newsletter sent home with your kid, or that office baby shower announcement :)</p> <p>When I did work on the graphics and visual design of applications a decade or more ago, I had to do it while hiding in the corner. I had a customer PM come over and tell me "don't let anyone see you drawing pictures". Clearly the visual design and icons and other elements "just appeared" from nowhere. The effort was not respected, but the outcome was expected.</p> <p>The problem here is not that developers don't know their limits (most do), but that <strong>management doesn't see the UX/Graphics Designer role as useful. It's not seen as a science, it's art. And just like in public schools, it's art that gets cut first</strong>.</p> <blockquote> <p>An introduction to Interaction Design should be a required subject for all Computer Science and MIS majors. Not because I would expect them to learn to be great at it, but because they need good solid exposure to it so they know something's possible, even if they don't have the required skills/talent. They'll see there's more science to it than they thought. In fact, Psychology backgrounds often help in UX design. It helps that most Psychology majors are otherwise unemployed :)</p> </blockquote> <p>Like I said to Scott "The more freedom and power you have, the more you need someone to tell you what <strong><span>not</span></strong> to do." You need this person on your team.</p> <h3>Who is On Your Team?</h3> <p>If you are on a team larger than two people, I bet you have a project manager, a dedicated DBA/database designer (or someone who doubles as DBA and database designer while also coding queries and services and whatnot), a front-end programmer, a back-end programmer, and maybe even a tester. Maybe you have an analyst or two, although those seem to be getting scarce. Larger teams tend to have more finely grained roles.</p> <p><a href="http://10rem.net/media/83074/Windows-Live-Writer_a2371b66e292_D4C8_image_10.png" target="_blank"><img src="http://10rem.net/media/83079/Windows-Live-Writer_a2371b66e292_D4C8_image_thumb_3.png" width="650" height="150" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>These are all seen as specialized skills. Not everyone is great at designing databases. Not everyone is equally skilled at creating good services and APIs. Not everyone can line up fields on a form. With web apps, the division tends to be even stronger due to the different languages and platforms in use in the different tiers or sections of the application. Inside the development community we, and our managers, understand these limitations and try to work within them.</p> <p>But most importantly, not everyone can take a problem and visualize an appropriate workflow and user experience, low-cost prototype it, test it with the users, and make the changes required to make the best UX the project budget will support. It's a specialized skill like any other.</p> <p><strong>And like any other part of a software project, you don't want to just do it at the end. No lipstick on a pig. Get a designer involved form the beginning, and include them in your iteration plan. You'll be amazed at what you can accomplish.</strong></p> <p><strong>How have your battles gone on this front? Have you been able to convince management about the importance of UX/Interaction/Visual design? If so, how did you go about it? What worked? What didn't?</strong></p> <p><a href="http://feedads.g.doubleclick.net/~a/KHHu-7N4oo6qJuTl19Z110ijeVg/0/da"><img src="http://feedads.g.doubleclick.net/~a/KHHu-7N4oo6qJuTl19Z110ijeVg/0/di" border="0" ismap="true"></img></a><br/> <a href="http://feedads.g.doubleclick.net/~a/KHHu-7N4oo6qJuTl19Z110ijeVg/1/da"><img src="http://feedads.g.doubleclick.net/~a/KHHu-7N4oo6qJuTl19Z110ijeVg/1/di" border="0" ismap="true"></img></a></p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=KjRU3dOJmeI:k0UEhhFKrnU:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=KjRU3dOJmeI:k0UEhhFKrnU:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=KjRU3dOJmeI:k0UEhhFKrnU:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=KjRU3dOJmeI:k0UEhhFKrnU:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=KjRU3dOJmeI:k0UEhhFKrnU:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=KjRU3dOJmeI:k0UEhhFKrnU:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=KjRU3dOJmeI:k0UEhhFKrnU:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=KjRU3dOJmeI:k0UEhhFKrnU:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=KjRU3dOJmeI:k0UEhhFKrnU:gIN9vFwOqvQ" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/PeteBrown/~4/KjRU3dOJmeI" height="1" width="1"/> http://feedproxy.google.com/~r/PeteBrown/~3/KjRU3dOJmeI/now-more-than-ever-you-need-a-designer Pete Brown 3555 2012-01-25T07:52:53 Arduino The Documentary <p>For anyone interested in open source microcontroller development, or why boards are named with *duino type names, this 1/2 hour documentary is a great watch.</p> <p><a href="http://vimeo.com/18539129" target="_blank"><img src="http://10rem.net/media/82982/Windows-Live-Writer_Arduino-the-Documentary_989_image_6.png" width="662" height="382" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p><a href="http://vimeo.com/18539129" title="http://vimeo.com/18539129">http://vimeo.com/18539129</a></p> <p>Arduino.TheDocumentary.2010.English explains the origin of the Arduino in a relatively non-technical interview-based documentary style, with interviews for people involved in the creation, as well as key partners and users.</p> <p>Spanish version is also available.</p> <p><a href="http://feedads.g.doubleclick.net/~a/MZ6XpYcOxlOmDwl-zBngC-b56Wg/0/da"><img src="http://feedads.g.doubleclick.net/~a/MZ6XpYcOxlOmDwl-zBngC-b56Wg/0/di" border="0" ismap="true"></img></a><br/> <a href="http://feedads.g.doubleclick.net/~a/MZ6XpYcOxlOmDwl-zBngC-b56Wg/1/da"><img src="http://feedads.g.doubleclick.net/~a/MZ6XpYcOxlOmDwl-zBngC-b56Wg/1/di" border="0" ismap="true"></img></a></p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=cjfhIcd9A28:TL--vRci44g:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=cjfhIcd9A28:TL--vRci44g:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=cjfhIcd9A28:TL--vRci44g:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=cjfhIcd9A28:TL--vRci44g:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=cjfhIcd9A28:TL--vRci44g:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=cjfhIcd9A28:TL--vRci44g:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=cjfhIcd9A28:TL--vRci44g:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=cjfhIcd9A28:TL--vRci44g:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=cjfhIcd9A28:TL--vRci44g:gIN9vFwOqvQ" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/PeteBrown/~4/cjfhIcd9A28" height="1" width="1"/> http://feedproxy.google.com/~r/PeteBrown/~3/cjfhIcd9A28/arduino-the-documentary Pete Brown 3552 2012-01-24T05:48:51 Yet Another Podcast #57–Kendo UI http://feedproxy.google.com/~r/JesseLiberty-SilverlightGeek/~3/_z42LvHCim0/ Jesse Liberty [MS] 3551 2012-01-23T19:49:57 My First Real PIX-6T4 Game: Sixty4Racer <p>After <a href="http://10rem.net/blog/2012/01/21/assembling-the-pix-6t4-netduino-powered-hand-held-game-system" target="_blank">assembling my Netduino-powered PIX-6T4</a>, I wanted to go and write a simple game. This post describes the construction of that game, including all source code.</p> <h3>Concept</h3> <p>When you have 64 monochrome red pixels, you need to keep the graphics simple. I decided on a game inspired by the classic <a href="http://www.bing.com/images/search?q=river+raid&amp;qs=n&amp;sk=&amp;sc=8-3&amp;form=QBIR" target="_blank">Atari River Raid game</a>. This is essentially a vertical scrolling game where you need to dodge obstacles with your boat. Variations included things like <a href="http://www.bing.com/images/search?q=commodore+spy+hunter&amp;qs=n&amp;sk=&amp;sc=8-13&amp;form=QBIR" target="_blank">Spy Hunter on the C64</a> and many many others. Most of those games also involved shooting and enemies, but that's a but more complex than you can reasonably do on this board. I won't enable moving walls like <a href="http://www.bing.com/images/search?q=laser+gates+atari&amp;qs=n&amp;sk=&amp;form=QBIR" target="_blank">Laser Gates</a>, but I'll leave things open enough not to make it impossible to do that in the future.</p> <p>The game had to be small enough that I could figure out the API, and then design, code, and blog about it in a single evening after my kids went to bed The PIX-6T4 is fun, but I have way too many projects on my backlog to be able to devote any <strong>significant</strong> time to it (<em>here's a taste: a ShapeOko CNC mill, an AVR MIDI-&gt;CV Converter, the final touches on the MIDI Thru Box, several MFOS Synth Modules, Several Gadgeteer Board Concepts, a Win8 XAML book, chapters to review in my Silverlight 5 book, and much much more</em>). In fact, that was one of the <strong>big selling points of this device: simple gameplay and quick to develop for</strong>. Combined with the great library Fabien designed, and my past experience with Netduino and, more specifically, C#, and this should be an evening project.</p> <h3>GamePlay</h3> <p>A simple dodge'em racing game. Levels get progressively longer and faster until you crash. And you will crash. And burn. And die.</p> <p>The joystick lets you control moving your single pixel vehicle either left or right. You can't move in any other direction.</p> <h4>Progression</h4> <p>Most good games increase in difficulty as you progress through the game. I decided that for this one, both the number of screens in the level and the overall speed would both increase as you progress through the game.</p> <h4>Goals</h4> <p>The goal is simple: not die. The longer you last, the more levels you'll make it through, and the more you'll be able to brag to your friends.</p> <h3>Screen Design</h3> <p>Back in the 80s, in 7th grade, I used to design single-color sprites for the commodore 64. The sprites themselves were 3 bytes wide, with each pixel represented as a single bit in the byte. I used to define them on graph paper, but alas, the notebooks I filled with sprites and BASIC listings have long since disappeared.</p> <p>I used to create my own fonts (programmable characters) as well. Those were done in a similar way, but on 8x8 graphs, eight bytes total for each character. Some pretty amazing games were created just with character graphics (the amazing <a href="http://www.mobygames.com/game/below-the-root" target="_blank">Below the Root on the C64</a>, as I recall, was one of them. You can <a href="http://www.youtube.com/watch?v=zWKpgpHa2Mo" target="_blank">see it played here</a>.). That model is what we have to work with on the PIX-6T4, but showing the equivalent of one character at a time.</p> <p>Here's an image from the Commodore 64 Programmer's Reference Manual</p> <p><a href="http://10rem.net/media/82883/Windows-Live-Writer_My-First-Real-PIX-6T4-Game_1194A_image_2.png" target="_blank"><img src="http://10rem.net/media/82888/Windows-Live-Writer_My-First-Real-PIX-6T4-Game_1194A_image_thumb.png" width="369" height="280" alt="image" border="0" style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <p>You can see there how the letter A is formed by the bit patterns for the eight bytes. I'm going to use a similar approach for the level design here. I'll create the "blocks" that make up the play area and then chain them together to create a playable game field.</p> <p>Here here are the initial screens I created, using notepad. The only criteria I had was to make sure the middle two spots were open at the start and end of each screen. Zeroes are safe areas, ones are walls/shore/hard-deadly-smashy-things.</p> <p><a href="http://10rem.net/media/82893/Windows-Live-Writer_My-First-Real-PIX-6T4-Game_1194A_image_4.png" target="_blank"><img src="http://10rem.net/media/82898/Windows-Live-Writer_My-First-Real-PIX-6T4-Game_1194A_image_thumb_1.png" width="660" height="205" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <p>The more variation in screens you add, the more challenging and interesting the game can be. So, I'll be sure to leave the design open enough to allow for other screens to be easily added.</p> <p>I don't need to limit myself to 8 bytes high, but I did anyway, as that will let you do things like use <a href="http://www.min.at/prinz/software/pixelfont/" target="_blank">8x8 pixel font editors</a> to design the screens. In fact, here are the same levels (with a couple slight modifications), plus a bunch more, done using the pixel font editor. I got a little carried away :)</p> <p><a href="http://10rem.net/media/82903/Windows-Live-Writer_My-First-Real-PIX-6T4-Game_1194A_image_6.png" target="_blank"><img src="http://10rem.net/media/82908/Windows-Live-Writer_My-First-Real-PIX-6T4-Game_1194A_image_thumb_2.png" width="660" height="152" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <p>The first entry is the start screen, the second is the end screen. All the ones after that are random ones which can be shown at any point during play. There are several "break" screens in there. That is, screens that aren't particularly difficult. And then there are a number of hair-pullers, and ones with dead-ends too :) Black is wall, white is passable space.</p> <p>Thanks to Fabien for pointing out this tool in the source code. It's so much easier to visualize the design when using the font editor, plus you get to export the bytes automatically. Speaking of export, here's what the tool generated for me:</p> <pre class="brush: csharp;"> <br /> // Font: ScreensSource.pf<br /> <br /> unsigned char font[2048] =<br /> {<br /> 0xC7, 0xC3, 0x83, 0x83, 0x81, 0x00, 0x00, 0x00, // Char 000 (.)<br /> 0x00, 0x00, 0x81, 0x81, 0xC3, 0xC3, 0xE7, 0xE7, // Char 001 (.)<br /> 0xE3, 0xCF, 0x87, 0xCF, 0x81, 0xF3, 0xC3, 0x87, // Char 002 (.)<br /> 0x87, 0xC1, 0xF1, 0xF9, 0xE1, 0x87, 0xC3, 0x81, // Char 003 (.)<br /> 0x81, 0xE7, 0x81, 0x99, 0x99, 0x81, 0xE7, 0xC3, // Char 004 (.)<br /> 0xE7, 0xE7, 0xF1, 0xC1, 0xCF, 0xE3, 0xF7, 0xE7, // Char 005 (.)<br /> 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, // Char 006 (.)<br /> 0xE3, 0xF9, 0xFC, 0xFE, 0xFC, 0xF9, 0xF3, 0xE7, // Char 007 (.)<br /> 0xE7, 0xE7, 0xEF, 0xE7, 0xF7, 0xE7, 0xEF, 0xE7, // Char 008 (.)<br /> 0xC3, 0xFB, 0xE1, 0xEF, 0xC1, 0xFB, 0x83, 0xE7, // Char 009 (.)<br /> 0xE7, 0xC1, 0x81, 0xF9, 0xC0, 0x81, 0x9F, 0x87, // Char 010 (.)<br /> 0xE7, 0xC3, 0x00, 0x7E, 0x00, 0xE7, 0xE7, 0x81, // Char 011 (.)<br /> 0xE7, 0x81, 0x18, 0x7E, 0x3C, 0x99, 0xC3, 0xE7, // Char 012 (.)<br /> 0x00, 0x18, 0x3C, 0x3C, 0x3C, 0x3C, 0x18, 0x00, // Char 013 (.)<br /> 0xC3, 0x89, 0x24, 0xB5, 0xA5, 0x2C, 0x81, 0xC3, // Char 014 (.)<br /> 0x86, 0x3C, 0x5A, 0x66, 0x3C, 0x28, 0x82, 0xC6, // Char 015 (.)<br /> 0x81, 0x00, 0x66, 0x66, 0x00, 0x99, 0x81, 0xA5, // Char 016 (.)<br /> 0xE7, 0xC3, 0xDF, 0x83, 0xF7, 0xA1, 0x8D, 0xE7, // Char 017 (.)<br /> 0xC3, 0x81, 0x00, 0x18, 0x18, 0x00, 0x81, 0xC3, // Char 018 (.)<br /> 0xE7, 0xC3, 0x99, 0x38, 0x1C, 0x99, 0xC3, 0xE7, // Char 019 (.)<br /> 0x04, 0x49, 0x02, 0x10, 0x4A, 0x00, 0x44, 0x20, // Char 020 (.)<br /> 0xA7, 0x2D, 0x6A, 0x2D, 0x26, 0x55, 0x56, 0x27, // Char 021 (.)<br /> 0xE7, 0xF7, 0xE7, 0xF7, 0xC3, 0xDB, 0xC3, 0xE7, // Char 022 (.)<br /> 0xE3, 0xCB, 0x9B, 0x3B, 0x89, 0x3D, 0x9D, 0xC5, // Char 023 (.)<br /> 0xE7, 0xC3, 0x99, 0xBD, 0x99, 0xC3, 0xE7, 0xE7, // Char 024 (.)<br /> 0xC3, 0xCF, 0xC3, 0xF3, 0xC7, 0xE3, 0xCF, 0xC7, // Char 025 (.)<br /> 0x65, 0xB6, 0x55, 0xB6, 0x65, 0xAA, 0x6D, 0xA7, // Char 026 (.)<br /> 0xE7, 0xC3, 0xE3, 0xF1, 0xF8, 0xF3, 0xC7, 0xE7, // Char 027 (.)<br /> 0xE4, 0xF4, 0xF4, 0xF4, 0xE4, 0x69, 0x0B, 0xA7, // Char 028 (.)<br /> 0x00, 0x18, 0x66, 0x5A, 0x5A, 0x66, 0x18, 0x00, // Char 029 (.)<br /> 0xA5, 0x91, 0x93, 0x97, 0x93, 0xCB, 0xE3, 0xE7, // Char 030 (.)<br /> 0x00, 0xDB, 0xC3, 0xE7, 0xE7, 0xC3, 0x99, 0x00, // Char 031 (.)<br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Char 032 ( )<br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Char 033 (!)<br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Char 034 (")<br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Char 035 (#)<br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Char 036 ($)<br /> ...<br /> 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Char 255 (.)<br /> }; </pre> <p>I then just needed to prune it to remove the stuff I wasn't using, and make it work in my app. The font designer certainly took a lot of the work out of it, though. The end-result can be seen in the code listing for the Screens class.</p> <p>With that in place, it was time to actually start creating the game.</p> <h3>First Iteration: Creating the scrolling playfield</h3> <p>I called my project PeteBrown.Sixty4Racer. Just as in the previous post, I copied over the Program.cs file from another project and used that as the start. Please <a href="http://10rem.net/blog/2012/01/21/assembling-the-pix-6t4-netduino-powered-hand-held-game-system" target="_blank">read my previous post</a> to see what references you need and whatnot.</p> <p>The first class I created was the one that manages the creation of the screens.</p> <h4>The Screens Class</h4> <p>The Screens class is responsible for storing all the known screens, and then assembling them into a level when requested. It knows how large the screens are, and how large a single level's full set of screens is.</p> <pre class="brush: csharp;"> using System;<br /> using Microsoft.SPOT;<br /> using netduino.helpers.Imaging;<br /> <br /> namespace PeteBrown.Sixty4Racer<br /> {<br /> class Screens<br /> {<br /> // Font: ScreensSource.pf<br /> private const int ScreenCount = 32;<br /> private const int ScreenHeight = 8;<br /> private readonly byte[] _screenBytes = new byte[ScreenCount * ScreenHeight]<br /> {<br /> 0xC7, 0xC3, 0x83, 0x83, 0x81, 0x00, 0x00, 0x00, // Start Screen<br /> 0x00, 0x00, 0x81, 0x81, 0xC3, 0xC3, 0xE7, 0xE7, // Stop Screen<br /> 0xE3, 0xCF, 0x87, 0xCF, 0x81, 0xF3, 0xC3, 0x87, // Char 002 (.)<br /> 0x87, 0xC1, 0xF1, 0xF9, 0xE1, 0x87, 0xC3, 0x81, // Char 003 (.)<br /> 0x81, 0xE7, 0x81, 0x99, 0x99, 0x81, 0xE7, 0xC3, // Char 004 (.)<br /> 0xE7, 0xE7, 0xF1, 0xC1, 0xCF, 0xE3, 0xF7, 0xE7, // Char 005 (.)<br /> 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, // Char 006 (.)<br /> 0xE3, 0xF9, 0xFC, 0xFE, 0xFC, 0xF9, 0xF3, 0xE7, // Char 007 (.)<br /> 0xE7, 0xE7, 0xEF, 0xE7, 0xF7, 0xE7, 0xEF, 0xE7, // Char 008 (.)<br /> 0xC3, 0xFB, 0xE1, 0xEF, 0xC1, 0xFB, 0x83, 0xE7, // Char 009 (.)<br /> 0xE7, 0xC1, 0x81, 0xF9, 0xC0, 0x81, 0x9F, 0x87, // Char 010 (.)<br /> 0xE7, 0xC3, 0x00, 0x7E, 0x00, 0xE7, 0xE7, 0x81, // Char 011 (.)<br /> 0xE7, 0x81, 0x18, 0x7E, 0x3C, 0x99, 0xC3, 0xE7, // Char 012 (.)<br /> 0x00, 0x18, 0x3C, 0x3C, 0x3C, 0x3C, 0x18, 0x00, // Char 013 (.)<br /> 0xC3, 0x89, 0x24, 0xB5, 0xA5, 0x2C, 0x81, 0xC3, // Char 014 (.)<br /> 0x86, 0x3C, 0x5A, 0x66, 0x3C, 0x28, 0x82, 0xC6, // Char 015 (.)<br /> 0x81, 0x00, 0x66, 0x66, 0x00, 0x99, 0x81, 0xA5, // Char 016 (.)<br /> 0xE7, 0xC3, 0xDF, 0x83, 0xF7, 0xA1, 0x8D, 0xE7, // Char 017 (.)<br /> 0xC3, 0x81, 0x00, 0x18, 0x18, 0x00, 0x81, 0xC3, // Char 018 (.)<br /> 0xE7, 0xC3, 0x99, 0x38, 0x1C, 0x99, 0xC3, 0xE7, // Char 019 (.)<br /> 0x04, 0x49, 0x02, 0x10, 0x4A, 0x00, 0x44, 0x20, // Char 020 (.)<br /> 0xA7, 0x2D, 0x6A, 0x2D, 0x26, 0x55, 0x56, 0x27, // Char 021 (.)<br /> 0xE7, 0xF7, 0xE7, 0xF7, 0xC3, 0xDB, 0xC3, 0xE7, // Char 022 (.)<br /> 0xE3, 0xCB, 0x9B, 0x3B, 0x89, 0x3D, 0x9D, 0xC5, // Char 023 (.)<br /> 0xE7, 0xC3, 0x99, 0xBD, 0x99, 0xC3, 0xE7, 0xE7, // Char 024 (.)<br /> 0xC3, 0xCF, 0xC3, 0xF3, 0xC7, 0xE3, 0xCF, 0xC7, // Char 025 (.)<br /> 0x65, 0xB6, 0x55, 0xB6, 0x65, 0xAA, 0x6D, 0xA7, // Char 026 (.)<br /> 0xE7, 0xC3, 0xE3, 0xF1, 0xF8, 0xF3, 0xC7, 0xE7, // Char 027 (.)<br /> 0xE4, 0xF4, 0xF4, 0xF4, 0xE4, 0x69, 0x0B, 0xA7, // Char 028 (.)<br /> 0x00, 0x18, 0x66, 0x5A, 0x5A, 0x66, 0x18, 0x00, // Char 029 (.)<br /> 0xA5, 0x91, 0x93, 0x97, 0x93, 0xCB, 0xE3, 0xE7, // Char 030 (.)<br /> 0x00, 0xDB, 0xC3, 0xE7, 0xE7, 0xC3, 0x99, 0x00 // Char 031 (.)<br /> };<br /> <br /> private RacerGame _parentGame;<br /> <br /> public Screens(RacerGame parentGame)<br /> {<br /> _parentGame = parentGame;<br /> }<br /> <br /> <br /> public int GetLevelScreenCount(int level)<br /> {<br /> return level * 6 + 2;<br /> }<br /> <br /> public int GetLevelPixelHeight(int level)<br /> {<br /> return GetLevelScreenCount(level) * ScreenHeight;<br /> }<br /> <br /> public Composition GetLevelComposition(int level)<br /> {<br /> int levelScreenCount = GetLevelScreenCount(level);<br /> <br /> byte[] bytes = new byte[ScreenHeight * levelScreenCount];<br /> <br /> int b = 0;<br /> int startIndex = 0;<br /> <br /> for (int i = 0; i &lt; levelScreenCount; i++)<br /> {<br /> if (i == 0)<br /> {<br /> // finish screen. This is the second screen in the array<br /> startIndex = ScreenHeight;<br /> }<br /> else if (i == levelScreenCount - 1)<br /> {<br /> // start screen. First screen in the array<br /> startIndex = 0;<br /> }<br /> else<br /> {<br /> // regular random screen<br /> int selectedScreen = _parentGame.Random.Next(ScreenCount - 2) + 2;<br /> <br /> startIndex = ScreenHeight * selectedScreen;<br /> }<br /> <br /> for (int a = startIndex; a &lt; startIndex + ScreenHeight; a++, b++)<br /> {<br /> bytes[b] = _screenBytes[a];<br /> }<br /> }<br /> <br /> return new Composition(bytes, 8, levelScreenCount * ScreenHeight);<br /> }<br /> <br /> }<br /> } </pre> <p>The class has the primary function GetLevelComposition which builds the background bitmap used to populate all the little red LEDs. The Composition class is one of the netduino helper classes in the PIX-6T4 library.</p> <p>The next class is the main game class.</p> <h4>The RacerGame class</h4> <p>The RacerGame class is responsible for all the game-specific logic. It handles scrolling the level, displaying messages, and (eventually), moving the player around the screen and handling collision detection. In this first iteration, all it does is display the level number and then scroll the level at the appropriate speed. The first level may seem to scroll painfully slow, but trust me, throw a player pixel in there and you'll change your mind.</p> <pre class="brush: csharp;"> using System;<br /> using Microsoft.SPOT;<br /> using netduino.helpers.Fun;<br /> using netduino.helpers.Imaging;<br /> using System.Threading;<br /> <br /> namespace PeteBrown.Sixty4Racer<br /> {<br /> class RacerGame : Game<br /> {<br /> private Screens _screens;<br /> <br /> public RacerGame(ConsoleHardwareConfig config)<br /> : base(config)<br /> {<br /> _screens = new Screens(this);<br /> <br /> DisplayDelay = 25;<br /> }<br /> <br /> protected override void OnGameEnd()<br /> {<br /> }<br /> <br /> <br /> protected override void OnGameStart()<br /> {<br /> base.OnGameStart();<br /> }<br /> <br /> <br /> private int _currentLevel = 0;<br /> private float _currentlevelSpeedIncrement = 0f;<br /> private float _exactScrollPosition = 0.0f;<br /> <br /> private int CurrentWorldLine<br /> {<br /> get { return (int)_exactScrollPosition; }<br /> }<br /> <br /> private void InitializeLevel()<br /> {<br /> World = _screens.GetLevelComposition(_currentLevel);<br /> _exactScrollPosition = _screens.GetLevelPixelHeight(_currentLevel) - 1;<br /> _currentlevelSpeedIncrement = 0.02f * (float)_currentLevel; // tweak this to change speed<br /> }<br /> <br /> private void CompleteLevel()<br /> {<br /> // TODO: Play some music<br /> <br /> Thread.Sleep(1500);<br /> ScrollMessage(" Level Up!");<br /> }<br /> <br /> private void IntroduceLevel()<br /> {<br /> // show the level number<br /> Hardware.Matrix.Display(SmallChars.ToBitmap(_currentLevel / 10, _currentLevel % 10));<br /> Thread.Sleep(1000);<br /> }<br /> <br /> private bool _firstTime = true;<br /> public override void Loop()<br /> {<br /> if (CurrentWorldLine == 0 || _firstTime)<br /> {<br /> if (!_firstTime)<br /> {<br /> CompleteLevel();<br /> }<br /> <br /> // Next Level<br /> _currentLevel++;<br /> InitializeLevel();<br /> IntroduceLevel();<br /> <br /> _firstTime = false;<br /> }<br /> else<br /> {<br /> _exactScrollPosition -= _currentlevelSpeedIncrement;<br /> }<br /> <br /> // draw the frame<br /> Hardware.Matrix.Display(World.GetFrame(0, CurrentWorldLine));<br /> }<br /> }<br /> } </pre> <p>The RacerGame class knows a level is complete when the top row of pixels is the first row of pixels in the level. Remember, since we're scrolling the screen down, we're moving from the bottom to the top of the rows of pixels. Get to the top, and the level is done.</p> <blockquote> <p><strong>Minor But Fatal Bitmap Class Bug</strong></p> <p>The GetFrame method in the version of the source code I used has an incorrect check. Where it says if (x &gt;= 0 &amp;&amp; x + FrameSize &lt; Width) it should say if (x &gt;= 0 &amp;&amp; x + FrameSize &lt;= Width). Notice the &lt;= instead of &lt;. The incorrect check means that any bitmaps that are exactly 8 pixels wide, like the one here, simply won't display. This bug may be fixed in the source you get, but you'll want to double-check. I'm just glad I had the source to refer to (and fix!). Isn't OSS great? :)</p> </blockquote> <p>When the level is complete, you get the scrolling "Level Up!" message. Click the joystick button and you're good to try the next level.</p> <p>Now is a good time to run the game and see what it looks like. You should see a vertically scrolling playfield, but no player just yet.</p> <h3>Second Iteration: Adding in the player</h3> <p>The PIX-6T4 libraries have built-in the concept of a PlayerMissile. This is a single pixel on the playfield. It may move, so it has X and Y speed. You can show or hide it, so it has Visibility. And most importantly, it has collision detection with other PlayerMissile instances. For our game, we're not going to use that, since we're looking for collision detection with the background. So, a little manual detection is in order.</p> <blockquote> <p><strong>Bitmap Class Bugs</strong></p> <p>While coding this game, I found a few more bugs in the Bitmap class. I've alerted Fabien, so you should see an updated set of source code soon. The first bug is that the GetPixel and SetPixel methods do some incorrect bounds checking up front. Y is checked against width rather than height, and the opposite happens with X. We're going to use GetPixel in a moment, so fixing this is important.</p> </blockquote> <p>Here's the updated RacerGame class</p> <pre class="brush: csharp;"> using System;<br /> using Microsoft.SPOT;<br /> using netduino.helpers.Fun;<br /> using netduino.helpers.Imaging;<br /> using System.Threading;<br /> <br /> namespace PeteBrown.Sixty4Racer<br /> {<br /> class RacerGame : Game<br /> {<br /> private Screens _screens;<br /> private PlayerMissile _ship;<br /> <br /> public RacerGame(ConsoleHardwareConfig config)<br /> : base(config)<br /> {<br /> _screens = new Screens(this);<br /> <br /> DisplayDelay = 25;<br /> }<br /> <br /> protected override void OnGameEnd()<br /> {<br /> ScrollMessage(" Game Over");<br /> }<br /> <br /> <br /> protected override void OnGameStart()<br /> {<br /> base.OnGameStart();<br /> <br /> _ship = new PlayerMissile()<br /> {<br /> Name = "ship",<br /> IsEnemy = false,<br /> X = 3,<br /> IsVisible = true,<br /> VerticalSpeed = 0,<br /> };<br /> <br /> ScrollMessage(" Sixty4Racer!");<br /> }<br /> <br /> <br /> private int _currentLevel = 0;<br /> private float _currentlevelSpeedIncrement = 0f;<br /> private const float BaseShipSpeed = 0.25f; // speed ship moves across the screen<br /> private float _exactScrollPosition = 0.0f;<br /> <br /> private int CurrentWorldLine<br /> {<br /> get { return (int)_exactScrollPosition; }<br /> }<br /> <br /> private void InitializeLevel()<br /> {<br /> World = _screens.GetLevelComposition(_currentLevel);<br /> World.AddMissile(_ship);<br /> <br /> _exactScrollPosition = _screens.GetLevelPixelHeight(_currentLevel) - 1;<br /> _currentlevelSpeedIncrement = 0.02f * (float)_currentLevel; // tweak this to change speed<br /> <br /> _ship.Y = CurrentWorldLine + 7; // always be on bottom line<br /> _ship.X = 3;<br /> }<br /> <br /> private void CompleteLevel()<br /> {<br /> // TODO: Play some music<br /> <br /> Thread.Sleep(1500);<br /> ScrollMessage(" Level Up!");<br /> }<br /> <br /> private void IntroduceLevel()<br /> {<br /> // show the level number<br /> Hardware.Matrix.Display(SmallChars.ToBitmap(_currentLevel / 10, _currentLevel % 10));<br /> Thread.Sleep(1000);<br /> }<br /> <br /> private bool CheckForCollision()<br /> {<br /> return World.Background.GetPixel(_ship.X, _ship.Y);<br /> }<br /> <br /> private bool _firstTime = true;<br /> public override void Loop()<br /> {<br /> _ship.HorizontalSpeed = (float)Hardware.JoystickLeft.XDirection * BaseShipSpeed;<br /> _ship.Move();<br /> <br /> if (_ship.X &lt; 0) _ship.X = 0;<br /> if (_ship.X &gt; 7) _ship.X = 7;<br /> <br /> if (CurrentWorldLine == 0 || _firstTime)<br /> {<br /> if (!_firstTime)<br /> {<br /> CompleteLevel();<br /> }<br /> <br /> // Next Level<br /> _currentLevel++;<br /> InitializeLevel();<br /> IntroduceLevel();<br /> <br /> _firstTime = false;<br /> }<br /> else<br /> {<br /> _exactScrollPosition -= _currentlevelSpeedIncrement;<br /> <br /> _ship.Y = CurrentWorldLine + 7; // always be on bottom line<br /> }<br /> <br /> // draw the frame<br /> Hardware.Matrix.Display(World.GetFrame(0, CurrentWorldLine));<br /> <br /> if (CheckForCollision())<br /> {<br /> // game over<br /> Stop();<br /> }<br /> }<br /> }<br /> } </pre> <p>This version of the source adds in the player pixel</p> <blockquote> <p><strong>I represent the "This Game is Too Damn Hard" Party</strong></p> <p>At this point, after adding the player and collision detection, I realized just how hard this game is! If you want to make it easier, I suggest editing the levels to make them a little more open, like a minimum of two pixels wide for any path, and no sudden moves left or right. You may even want to segment the level array into easy/medium/hard, and then change the mix of screens from level to level.</p> </blockquote> <p>With all that in place, now is another great time to try out the game. It has all the main functionality at this point; anything else is just polish.</p> <h3>Third Iteration: Polishing</h3> <p>The first thing I realized was that it was really hard to make out the player pixel in the sea of red. That's to be expected on a monochrome display at 8x8 resolution. The approach I came up with to make it a bit easier is to simply flicker the player pixel. Each time the game loop executes, I toggle the visibility of the ship PlayerMissile to give it a nice seizure-inducing flicker.</p> <pre class="brush: csharp; highlight: [7];"> public override void Loop()<br /> {<br /> _ship.HorizontalSpeed = (float)Hardware.JoystickLeft.XDirection * BaseShipSpeed;<br /> _ship.Move();<br /> <br /> // make the ship blink so we can see it<br /> _ship.IsVisible = !_ship.IsVisible;<br /> <br /> if (_ship.X &lt; 0) _ship.X = 0;<br /> if (_ship.X &gt; 7) _ship.X = 7;<br /> <br /> if (CurrentWorldLine == 0 || _firstTime)<br /> {<br /> if (!_firstTime)<br /> {<br /> CompleteLevel();<br /> }<br /> <br /> // Next Level<br /> _currentLevel++;<br /> InitializeLevel();<br /> IntroduceLevel();<br /> <br /> _firstTime = false;<br /> }<br /> else<br /> {<br /> _exactScrollPosition -= _currentlevelSpeedIncrement;<br /> <br /> _ship.Y = CurrentWorldLine + 7; // always be on bottom line<br /> }<br /> <br /> // draw the frame<br /> Hardware.Matrix.Display(World.GetFrame(0, CurrentWorldLine));<br /> <br /> if (CheckForCollision())<br /> {<br /> // game over<br /> Stop();<br /> }<br /> } </pre> <h4>Sound Effects</h4> <p>The next thing this needed was some sound effects. When you move left or right a full pixel, it would be helpful to play a little blip. Maybe that's annoying? Nah! Let's do it.</p> <p>This is really easy to do. I simply keep track of the last position the ship moved to. If the new position is different from the old one, I call the Beep function to make a noise. The actual implementation here results in an extra blip on startup, but I'm cool with that :)</p> <pre class="brush: csharp;"> private void Blip()<br /> {<br /> Beep(200, 30);<br /> }<br /> <br /> private bool _firstTime = true;<br /> private int _oldShipX = 0;<br /> public override void Loop()<br /> {<br /> _ship.HorizontalSpeed = (float)Hardware.JoystickLeft.XDirection * BaseShipSpeed;<br /> _ship.Move();<br /> <br /> if (_ship.X != _oldShipX)<br /> {<br /> Blip();<br /> _oldShipX = _ship.X;<br /> }<br /> <br /> <br /> // make the ship blink so we can see it<br /> _ship.IsVisible = !_ship.IsVisible;<br /> <br /> ...<br /> <br /> }<br /> </pre> <p>Next, we need to do a little bit of exploding when you hit the wall. And yes, you <strong>will</strong> hit the wall.</p> <h4>The Explosion Sprite</h4> <p>The final thing was to add a little bit of an explosion when the player hits the wall. I designed the sprite data using the same PixelFont editor.</p> <p><a href="http://10rem.net/media/82913/Windows-Live-Writer_My-First-Real-PIX-6T4-Game_1194A_image_8.png" target="_blank"><img src="http://10rem.net/media/82918/Windows-Live-Writer_My-First-Real-PIX-6T4-Game_1194A_image_thumb_3.png" width="660" height="90" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>I then copied just those 8 x 8 bytes of data into the initializer for the sprite class. Here's the Sprite class itself (without the initializer code).</p> <pre class="brush: csharp;"> using System;<br /> using Microsoft.SPOT;<br /> <br /> namespace PeteBrown.Sixty4Racer<br /> {<br /> class Sprite<br /> {<br /> private readonly byte[] _frames;<br /> private const int Width = 8;<br /> private const int Height = 8;<br /> private int _frameCount;<br /> <br /> public Sprite (byte[] frames)<br /> {<br /> _frames = frames;<br /> <br /> _frameCount = _frames.Length / Height;<br /> }<br /> <br /> public int FrameCount<br /> {<br /> get { return _frameCount; }<br /> }<br /> <br /> public int CurrentFrame<br /> {<br /> get { return _currentFrame; }<br /> }<br /> <br /> public void Reset()<br /> {<br /> _currentFrame = 0;<br /> }<br /> <br /> private int _currentFrame = 0;<br /> public byte[] GetNextFrame()<br /> {<br /> return GetFrame(_currentFrame++);<br /> }<br /> <br /> public byte[] GetFrame(int index)<br /> {<br /> if (index &gt;= FrameCount)<br /> throw new IndexOutOfRangeException("Index must be less than " + FrameCount);<br /> <br /> byte[] b = new byte[Height];<br /> <br /> for (int i = 0; i &lt; Height; i++)<br /> {<br /> b[i] = _frames[index * Height + i];<br /> }<br /> <br /> return b;<br /> }<br /> }<br /> } </pre> <p>(The initialization code will be in the next listing.)</p> <p>Next, I added in a little music. How about some Sad Trombone when you die? Sounds good to me. By looking at the Pac Man music example, and the source code for the RttlSong class, I was able to figure out how to build a string of notes to play the sad trombone sound asynchronously while the explosion happens. Rub it in!</p> <pre class="brush: csharp;"> Sprite _explosion = new Sprite(new byte[]<br /> {<br /> 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,<br /> 0x00, 0x00, 0x18, 0x24, 0x24, 0x18, 0x00, 0x00,<br /> 0x08, 0x3C, 0x72, 0x5B, 0xDE, 0x62, 0x3C, 0x08,<br /> 0x3C, 0xD2, 0xAD, 0xFE, 0x5F, 0xF5, 0x56, 0x28,<br /> 0x00, 0x3C, 0x56, 0x7A, 0x6E, 0x72, 0x3C, 0x00,<br /> 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00,<br /> 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,<br /> 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00<br /> });<br /> <br /> protected override void OnGameEnd()<br /> {<br /> var song = new RttlSong("SadTrombone:d=4,o=4,b=40:32d4,32c#4,32c4,4b3");<br /> var thread = song.Play(Hardware.Speaker, true);<br /> <br /> for (int i = 0; i &lt; _explosion.FrameCount; i++)<br /> {<br /> Hardware.Matrix.Display(_explosion.GetNextFrame());<br /> Thread.Sleep(200);<br /> }<br /> <br /> ScrollMessage(" Game Over");<br /> } </pre> <p>You can go further, of course, but I'm going to wrap it up at that.</p> <h3>Final Steps</h3> <p>The final things to do are to create the manifest file and bitmap which will be used on the SD card. I'll need to check with Fabien to see what the exact format of the .bin file is, but I suspect it's just the 8 bytes of data formatted like all the other bitmap data in this application. I'm also not sure if he has a nice little app to write that data out, or convert from a bitmap, or something else. I ended up just using a hex editor to recreate the pattern from one of the images I created in the font editor.</p> <p><a href="http://10rem.net/media/82923/Windows-Live-Writer_My-First-Real-PIX-6T4-Game_1194A_image_10.png" target="_blank"><img src="http://10rem.net/media/82928/Windows-Live-Writer_My-First-Real-PIX-6T4-Game_1194A_image_thumb_4.png" width="257" height="198" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>The assembly itself needs to be loaded from the SD card as a .pe file, as Fabien explains in <a href="http://fabienroyer.wordpress.com/2010/12/29/loading-assemblies-dynamically-from-an-sd-card-with-a-netduino/" target="_blank">his blog post on dynamically loading assemblies from an SD card</a>. Be sure to comment out the #define dev before your final compile. Make sure you take the .pet file from the LE (little endian) folder, not the BE (big endian) folder. The files look identical other than byte order, but the BE version will not work.</p> <p>I then created a cartridge.txt manifest file for my game. The contents of that consist of a single line:</p> <pre class="brush: csharp;"> <br /> assembly:file=PeteBrown.Sixty4Racer.pe;name=PeteBrown.Sixty4Racer;version=1.0.0.0;class=PeteBrown.Sixty4Racer.Program;method=Run<br /> <br /> </pre> <p>They must be in a folder with the same name as the root file name for the image. So, these go in a PeteBrown.Sixty4Racer folder.</p> <p>Finally, don't forget to reflash the PIX-6T4 with the main ConsoleBootLoader application from your solution.</p> <p>After that, pop the SD card into the PIX-6T4 and have a blast!</p> <h3>What You Can Do</h3> <p>This came is completely free and open source. While I'd love credit for the initial work, it's not a requirement. Go ahead and do whatever you'd like with the source and have a blast :)</p> <p>Here's a video of the game in action.</p> <div class="wlWriterEditableSmartContent" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:69c56f9e-f14a-4e1e-9f9f-43d6647494c3" style="margin: 0px; display: inline; float: none; padding: 0px;"> <div id="6da37833-fb66-423f-bda2-cefc06cf5131" style="margin: 0px; display: inline; padding: 0px;"><object width="611" height="343" data="http://www.youtube.com/v/10FzxWQTzzM?hl=en&amp;hd=1" type="application/x-shockwave-flash"><param name="src" value="http://www.youtube.com/v/10FzxWQTzzM?hl=en&amp;hd=1" /> </object></div> <div style="width: 611px; clear: both; font-size: 0.8em;">PIX-6T4 Netduino Mini Game</div> </div> <p><a href="http://feedads.g.doubleclick.net/~a/yocakmzHMcesqfhZTMHyJkfAQLk/0/da"><img src="http://feedads.g.doubleclick.net/~a/yocakmzHMcesqfhZTMHyJkfAQLk/0/di" border="0" ismap="true"></img></a><br/> <a href="http://feedads.g.doubleclick.net/~a/yocakmzHMcesqfhZTMHyJkfAQLk/1/da"><img src="http://feedads.g.doubleclick.net/~a/yocakmzHMcesqfhZTMHyJkfAQLk/1/di" border="0" ismap="true"></img></a></p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=ZnhAnsv1yk8:vlM6_TNId14:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=ZnhAnsv1yk8:vlM6_TNId14:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=ZnhAnsv1yk8:vlM6_TNId14:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=ZnhAnsv1yk8:vlM6_TNId14:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=ZnhAnsv1yk8:vlM6_TNId14:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=ZnhAnsv1yk8:vlM6_TNId14:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=ZnhAnsv1yk8:vlM6_TNId14:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=ZnhAnsv1yk8:vlM6_TNId14:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=ZnhAnsv1yk8:vlM6_TNId14:gIN9vFwOqvQ" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/PeteBrown/~4/ZnhAnsv1yk8" height="1" width="1"/> http://feedproxy.google.com/~r/PeteBrown/~3/ZnhAnsv1yk8/my-first-real-pix-6t4-game-sixty4racer Pete Brown 3549 2012-01-22T14:34:30 Assembling the PIX-6T4 Netduino-powered Hand-Held Game System <p>I recently picked up a PIX-6T4 build by Fabien Royer (with games by Fabien Royer and Bertrand Le Roy). This is a 64 pixel, two joystick/button, monophonic sound hand-held game device based around the Netduino Mini from Secret Labs. You create games in C# using Visual studio.</p> <blockquote> <p>Disclaimer: I work for Microsoft and I enjoy working in the .NET Micro Framework as well as C++ on other microcontrollers. I purchased this product on my own, at full price; this is not a sample or review unit. Presumably, I got the same package of goodies everyone else gets.</p> </blockquote> <h3>Unboxing</h3> <p>The kit came in a regular USPS shipping box inside which were four bags. Two bags had components, and two had joysticks.</p> <p><a href="http://10rem.net/media/82716/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_9.png" target="_blank"><img src="http://10rem.net/media/82721/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_thumb_3.png" width="660" height="316" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>Everything was well-packed in ESD safe bags. The two joysticks were in their original as-delivered bags.</p> <p>What's inside?</p> <h4>What the Kit Includes</h4> <p>The kit includes just about everything you need to assemble a working PIX-6T4 handheld game console. The PCB, of course, as well as a nice laser-cut acrylic bottom.</p> <p><a href="http://10rem.net/media/82726/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_11.png" target="_blank"><img src="http://10rem.net/media/82731/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_thumb_4.png" width="660" height="355" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p><a href="http://10rem.net/media/82736/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_13.png" target="_blank"><img src="http://10rem.net/media/82741/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_thumb_5.png" width="660" height="423" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>It can be powered by a 9v battery or a regular 9v power supply. When using a battery, you solder a barrel jack on the battery lead to make it easy to switch between the two.</p> <p>The entire thing is open source hardware and software from the Netduino all the way up to the full kit and the software to run it.</p> <h4>What it doesn't Include</h4> <p><strong>A USB to Serial converter</strong>. Many people with Netduino minis already have one of these cables. You can get them cheap online, or (worst case) get one at Best Buy or Fry's. I happened to have one just because my C64-TPC (a connection between my Commodore and my PC) needed one. Putting on-board USB would have been nice, but that typically requires a surface-mount FTDI chip which is very difficult for DIY soldering (or a breakout board from a place like SparkFun which adds bulk, cost, and complexity). The <a href="http://www.netduino.com/netduinomini/specs.htm" target="_blank">Netduino mini</a>, unlike the Netduino, doesn't offer an external USB interface. So, while I'm not a fan of the serial approach, I do think it was the best choice here.</p> <p><a href="http://www.netduino.com/netduinomini/specs.htm" target="_blank"><img src="http://10rem.net/media/82746/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_3.png" width="253" height="178" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>You can <a href="http://www.pix6t4.com/source" target="_blank">play the stock games by just loading them on the SD card</a>. However, if you want to do any programming or debugging of your own, you'll really need the USB converter, as debugging is impossible without it.</p> <p>Speaking of SD card, that's the other things that you'll need: <strong>A FAT32-formatted SD card</strong>. You'll need one of these to store the games you write and also to load the stock games.</p> <h3>Assembly</h3> <p>I love the blue board. I've always liked blue, black and red PCBs. The typical green solder mask just looks too much like some crap 486 motherboard. I'm glad they went with something attractive here.</p> <p>First step is the most unusual bit of soldering. There's one surface mount component, but it's stunningly easy to solder. That's the SD card slot. Make sure you following the video and do not solder the two pins on the right (although if they're not connected to anything, as long as you don't short them, I would think they'd be fine)</p> <p><a href="http://10rem.net/media/82751/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_15.png" target="_blank"><img src="http://10rem.net/media/82756/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_thumb_6.png" width="660" height="337" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>Next up, flip the board over and install the IC socket for the LED controller, and then a resistor.</p> <p><a href="http://10rem.net/media/82761/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_17.png" target="_blank"><img src="http://10rem.net/media/82766/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_thumb_7.png" width="660" height="327" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>In this particular case, it seems the stencil for the resistor was sized for a 1/8" watt resistor. The space is also cramped, but this resistor sticking up like that just breaks my heart. At least, it's on the bottom side of the board so we can all hide our shame :)</p> <p>Next, up, the LED array and then the Netduino mini socket.</p> <p><a href="http://10rem.net/media/82771/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_19.png" target="_blank"><img src="http://10rem.net/media/82776/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_thumb_8.png" width="660" height="400" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>A power switch and another resistor standing at attention</p> <p><a href="http://10rem.net/media/82781/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_21.png" target="_blank"><img src="http://10rem.net/media/82786/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_thumb_9.png" width="660" height="313" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>From there, it's the audio trim pot and the power LED. At this point, I have to mention that the power LED is REALLY bright and in your face when you're trying to play. I covered mine with a little bit of black paint, but even that isn't quite enough. I actually think it would be better to solder that LED upside down, so it is on the underside of the board. That might even be a cool effect with the acrylic down there. Fabien mentioned he might bump up the resistor value, but the more I think about putting it upside down, the more I like it. I might even desolder mine and put a new LED underneath :)</p> <p><a href="http://10rem.net/media/82791/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_23.png" target="_blank"><img src="http://10rem.net/media/82796/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_thumb_10.png" width="660" height="239" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>I did a few more steps before taking another photo. Resistors, the power connector (underside), and a transistor are all in place.</p> <p><a href="http://10rem.net/media/82801/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_25.png" target="_blank"><img src="http://10rem.net/media/82806/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_thumb_11.png" width="660" height="501" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>In case you haven't gathered, I'm not a big fan of having resistors stand up in general. In fact, I hate them in all but the most cramped design with huge multi-watt resistors. They're easy to knock over, bend, etc, and they're more difficult to solder in that configuration. There's tons of spare room on this board, so I'm not entirely sure why Fabien and folks did that. Just be careful when soldering the other components so you don't break these off.</p> <p>Ceramic capacitor, electrolytic capacitor, and the 3.3v power regulator in place. If I were designing this board, I think I would have found a way to position the regulator so it lay flat on the board with its leads bent at 90 degree angles. That's a pretty common approach in other builds, like the <a href="http://10rem.net/blog/2011/10/22/just-completed-my-sammich-sid-build" target="_blank">Sammich SID I built</a>.</p> <p><a href="http://10rem.net/media/82811/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_27.png" target="_blank"><img src="http://10rem.net/media/82816/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_thumb_12.png" width="660" height="305" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>Finally, the joysticks, pin headers, and the ICs themselves. Before I installed the ICs, I went and cleaned the bottom of the board with flux remover spray and a cleaning brush. It helps clean things up quite a bit. You'll see later, it also helped me see a bad solder joint. Organic Rosin flux isn't super harmful to leave on, but it's ugly to see on the board.</p> <p><a href="http://10rem.net/media/82821/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_29.png" target="_blank"><img src="http://10rem.net/media/82826/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_thumb_13.png" width="660" height="373" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>Don't forget the one IC that goes on the bottom.</p> <p><a href="http://10rem.net/media/82831/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_31.png" target="_blank"><img src="http://10rem.net/media/82836/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_thumb_14.png" width="660" height="225" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <h3>Smoke Test</h3> <p>Time for a power-on test! After I cleaned it up, dried if off, and installed the ICs, I powered it up without an SD card. This is what I saw:</p> <p><a href="http://10rem.net/media/82841/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_33.png" target="_blank"><img src="http://10rem.net/media/82846/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_thumb_15.png" width="660" height="275" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>Sweet! I got the skull and crossbones, which means it's working. As an aside, you can also see what I was talking about with the super bright LED. It easily overpowers the playing field. Looks cool in a photo, though, a bit like a Star Trek II photon torpedo.</p> <p>Next, I copied the three game folders (from the zip file referenced on the PIX-6T4 site) on to a 512MB SD card and started it up. I was greeted by the icons of the games I could choose. I picked a game and then…</p> <h3>And…I got nothing.</h3> <p>At first I thought it was this bad solder joint (which makes no sense, but hey, I figured the code was perfect!). It's really hard to see in this picture (and in fact, it looks ok in this picture), but when viewed through a lens you can see that I never heated the pin: the solder goes around the pin but never really joins with it.</p> <p><a href="http://10rem.net/media/82851/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_5.png" target="_blank"><img src="http://10rem.net/media/82856/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_thumb_1.png" width="520" height="330" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>I only found this after cleaning the board with flux remover. Flux can fill in holes like that and make it so you can't see them without doing a continuity test. I resoldered that pin (and the one next to it which didn't look much better), and then did a continuity test between the mini and each of the breakout pins, just to make sure there were no others.</p> <p>Still no go.</p> <p>After trying out a few SD cards and getting nothing, and following some other suggestions from Fabien, I still had nothing. Finally, Fabien recommended I dig out that usb-&gt;serial cable (I wasn't able to find it at first) and <a href="http://www.pix6t4.com/deploy-and-debug" target="_blank">compile and re-deploy</a> the current source from Codeplex. Guess what? It worked :)</p> <p>It turns out I had one of the Netduino Minis that had the old firmware on it, and the games were built with new firmware. The deploy got them synchronized.</p> <p>Excellent. I have a working PIX-6T4 :)</p> <h3>The Test Games</h3> <p>I tried the games that come with it. One plays the Pac Man song, one is a game of pong, and the other is an asteroid avoidance game. You have only 64 pixels to work with, and they're all the same color, so like the early days of video games, you need to use your imagination.</p> <p>The stock games are well done. However, since I had the debugger/programmer connected, I wanted to go and build something myself.</p> <h3>My First Game</h3> <p>My first game is going to be a test game. I added a new Netduino application project named "PeteTestGame". I did this in the same solution that contains the PIX6T4 source code and the other three stock games. Next, I added a reference to pix6t4.netduino.helpers project.</p> <p>In the project, I also removed the reference to SecretLabs.NETMF.Hardware.Netduino and add reference to SecretLabs.NETMF.Hardware.NetduinoMini</p> <p>Next, add a GameOfTest class. I named it this following the naming conventions Fabien and Bertrand set up, but you can call it anything. GameOfThrones is an obvious choice ;)</p> <h4>The GameOfTest class</h4> <pre class="brush: csharp;"> using System;<br /> using Microsoft.SPOT;<br /> using netduino.helpers.Fun;<br /> <br /> namespace PeteTestGame<br /> {<br /> class GameOfTest : Game<br /> {<br /> public GameOfTest(ConsoleHardwareConfig config)<br /> : base(config)<br /> {<br /> <br /> }<br /> <br /> protected override void OnGameEnd()<br /> {<br /> base.OnGameEnd();<br /> }<br /> <br /> protected override void OnGameStart()<br /> {<br /> base.OnGameStart();<br /> <br /> ScrollMessage(" Hello World!");<br /> }<br /> <br /> protected override void OnLeftButtonClick(uint port, uint state, DateTime time)<br /> {<br /> base.OnLeftButtonClick(port, state, time);<br /> }<br /> <br /> protected override void OnRightButtonClick(uint port, uint state, DateTime time)<br /> {<br /> base.OnRightButtonClick(port, state, time);<br /> }<br /> <br /> public override void Loop()<br /> {<br /> <br /> }<br /> }<br /> <br /> } <br /> </pre> <h4>Program</h4> <p>Next, I copied the Program.cs from one of the other projects. I made three changes to the source:</p> <ul> <li>Uncomment the #define dev at the top</li> <li>Changed the namespace to match the rest of the project</li> <li>Changed the class in the Run method to be GameOfTest instead of the one copied from the other project</li> </ul> <p>The program.cs enables you to deploy your test game as the only game on the device, without worrying about building up a manifest and icon and dealing with the SD card and whatnot. Obviously, this also makes debugging possible.</p> <p>Set the game project as startup. Next, right-click and select project properties and navigate to the .NET Micro Framework tab. Make sure the deployment is set to Serial and you have the COM port that your Netduino mini is attached to.</p> <p>Once done, you can run the project. In my case, I immediately saw the scrolling (and repeating) Hello World text. The ScrollMessage function is doing all the heavy lifting. It's great that Fabien put in the nifty retro font in there as well.</p> <p><a href="http://10rem.net/media/82861/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_7.png" target="_blank"><img src="http://10rem.net/media/82866/Windows-Live-Writer_Assembling-the-PIX-6T4-Netduino-powered-_102FF_image_thumb_2.png" width="520" height="408" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>Next step was to add some beeping. Because, well, it's not a game without beeping.</p> <pre class="brush: csharp;"> using System;<br /> using Microsoft.SPOT;<br /> using netduino.helpers.Fun;<br /> <br /> namespace PeteTestGame<br /> {<br /> class GameOfTest : Game<br /> {<br /> public GameOfTest(ConsoleHardwareConfig config)<br /> : base(config)<br /> {<br /> <br /> }<br /> <br /> protected override void OnGameEnd()<br /> {<br /> base.Beep(440, 500);<br /> base.Beep(220, 500);<br /> base.Beep(440, 500);<br /> }<br /> <br /> <br /> protected override void OnGameStart()<br /> {<br /> base.OnGameStart();<br /> <br /> base.Beep(440, 500);<br /> base.Beep(220, 500);<br /> base.Beep(440, 500);<br /> <br /> ScrollMessage(" Hello World!");<br /> }<br /> <br /> protected override void OnLeftButtonClick(uint port, uint state, DateTime time)<br /> {<br /> base.OnLeftButtonClick(port, state, time);<br /> <br /> base.Beep(440, 500);<br /> <br /> }<br /> <br /> protected override void OnRightButtonClick(uint port, uint state, DateTime time)<br /> {<br /> base.OnRightButtonClick(port, state, time);<br /> <br /> base.Beep(220, 500);<br /> <br /> }<br /> <br /> public override void Loop()<br /> {<br /> <br /> }<br /> }<br /> <br /> }<br /> </pre> <p>Now it plays a few beeps on startup and then beeps when you press down on either joystick. Note that that does stop the scrolling text, however.</p> <p>I'll leave the more complex games to a later date :)</p> <blockquote>Update 1/22: To see my first real full game, check out my blog <a href="http://10rem.net/blog/2012/01/22/my-first-real-pix-6t4-game-sixty4racer">post on building Sixty4Racer</a>.</blockquote> <h3>Conclusion</h3> <p>I'm impressed with what Fabien has come up with here, and the stock games he and Bertrand have done are just perfect. I think the board and enclosure could use a little more design to make it more compact and also more hand-friendly, but overall, I think this is an excellent way to get into Netduino programming using something fun and exciting. Also, because of the display technology, you are constrained to creating games with very simple graphics (just LEDs) so, by necessity, you avoid that common barrier to entry. Sometimes constraint is a good thing.</p> <p>Congratulations Fabien and Bertrand!</p> <p><a href="http://feedads.g.doubleclick.net/~a/whKP6-ORjtSSDYR-6izmoWJELE0/0/da"><img src="http://feedads.g.doubleclick.net/~a/whKP6-ORjtSSDYR-6izmoWJELE0/0/di" border="0" ismap="true"></img></a><br/> <a href="http://feedads.g.doubleclick.net/~a/whKP6-ORjtSSDYR-6izmoWJELE0/1/da"><img src="http://feedads.g.doubleclick.net/~a/whKP6-ORjtSSDYR-6izmoWJELE0/1/di" border="0" ismap="true"></img></a></p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=8a8bxEqkR_U:03Ulo_ojlQ8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=8a8bxEqkR_U:03Ulo_ojlQ8:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=8a8bxEqkR_U:03Ulo_ojlQ8:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=8a8bxEqkR_U:03Ulo_ojlQ8:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=8a8bxEqkR_U:03Ulo_ojlQ8:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=8a8bxEqkR_U:03Ulo_ojlQ8:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=8a8bxEqkR_U:03Ulo_ojlQ8:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=8a8bxEqkR_U:03Ulo_ojlQ8:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=8a8bxEqkR_U:03Ulo_ojlQ8:gIN9vFwOqvQ" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/PeteBrown/~4/8a8bxEqkR_U" height="1" width="1"/> http://feedproxy.google.com/~r/PeteBrown/~3/8a8bxEqkR_U/assembling-the-pix-6t4-netduino-powered-hand-held-game-system Pete Brown 3548 2012-01-21T08:12:51 WPF 4.5 Cross-Thread Collection Synchronization Redux <p>In my <a href="http://10rem.net/blog/2012/01/16/wpf-45-observable-collection-cross-thread-change-notification" target="_blank">post about WPF 4.5 Observable Collection Cross-thread Change Notification</a>, I showed the basics of how to synchronize collection updates in WPF, and how to avoid having to manually dispatch calls to the UI thread. In the comments, Jonathan Allen brought up some very good points that I simply didn't know the answers to (and a lock I was missing in the example). Thanks to Jonathan for keeping me honest :)</p> <blockquote> <p>For background, go back and <a href="http://10rem.net/blog/2012/01/16/wpf-45-observable-collection-cross-thread-change-notification" target="_blank">read that post</a>, but then come here for some of the updates.</p> </blockquote> <p>So, rather than guess at the answers, I went right to the guy responsible for most (all?) of the design of the binding structure in WPF: Sam Bent. I also went back to the spec document, and also dove deeper into what's actually happening.</p> <h3>Locking</h3> <p>Q: If I'm using collection synchronization, do I need to lock my own access to the collection?</p> <p>A: Yes, you do. The collection won't do any locking by itself (I had thought that ObservableCollection was doing some, but both Jonathan and Sam corrected me here. Sam also pointed out this works with just about any collection).&nbsp; Having the collection handle any locking internally is "full of pitfalls" (Sam's words, which I agree with having seen the examples) and was abandoned early in .NET's development cycle.</p> <p>What this does mean, is that my example from the previous post really needed to lock the collection add call. Here's the updated viewmodel source.</p> <pre class="brush: csharp;"> class MainViewModel<br /> {<br /> public ObservableCollection&lt;Stock&gt; Stocks { get; private set; }<br /> <br /> private object _stocksLock = new object();<br /> <br /> public MainViewModel()<br /> {<br /> Stocks = new ObservableCollection&lt;Stock&gt;();<br /> <br /> BindingOperations.EnableCollectionSynchronization(Stocks, _stocksLock);<br /> }<br /> <br /> <br /> private Random _random = new Random();<br /> public void AddNewItems()<br /> {<br /> lock (_stocksLock)<br /> {<br /> for (int i = 0; i &lt; 100; i++)<br /> {<br /> var item = new Stock();<br /> for (int j = 0; j &lt; _random.Next(2, 4); j++)<br /> {<br /> item.Symbol += char.ConvertFromUtf32(_random.Next(<br /> char.ConvertToUtf32("A", 0),<br /> char.ConvertToUtf32("Z", 0)));<br /> }<br /> <br /> item.Value = (decimal)(_random.Next(100, 6000) / 100.0);<br /> Stocks.Add(item);<br /> Debug.WriteLine(item.Symbol);<br /> }<br /> }<br /> }<br /> <br /> <br /> public void StartAddingItems()<br /> {<br /> Task.Factory.StartNew(() =&gt;<br /> {<br /> while (true)<br /> {<br /> AddNewItems();<br /> Thread.Sleep(500);<br /> }<br /> });<br /> <br /> }<br /> } </pre> <p>Notice how I lock the entire loop in AddNewItems. Depending on what's going on inside that loop, or how many iterations, that may simply be too large/long a lock. If you need a smaller/shorter lock, it would be safe to wrap the Add call instead, like this:</p> <pre class="brush: csharp;"> private Random _random = new Random();<br /> public void AddNewItems()<br /> {<br /> for (int i = 0; i &lt; 100; i++)<br /> {<br /> var item = new Stock();<br /> for (int j = 0; j &lt; _random.Next(2, 4); j++)<br /> {<br /> item.Symbol += char.ConvertFromUtf32(_random.Next(<br /> char.ConvertToUtf32("A", 0),<br /> char.ConvertToUtf32("Z", 0)));<br /> }<br /> <br /> item.Value = (decimal)(_random.Next(100, 6000) / 100.0);<br /> lock (_stocksLock)<br /> {<br /> Stocks.Add(item);<br /> }<br /> Debug.WriteLine(item.Symbol);<br /> }<br /> } </pre> <p><strong>I'll leave the choice of which one is appropriate up to the folks designing individual applications</strong>. It sounds like a punt, but it really is up to you guys. Each has merits (fewer lock acquisitions in first one, more atomic actions and less thread blocking in second one), but really are very application dependent. In my particular demo example here, with 100 iterations, I'm fine with handling the lock outside the loop.</p> <h3>About the EnableCollectionSynchronization Overload</h3> <p>Here's one question that Sam answered. I'll quote him directly.</p> <p>Q: Why are there two overloads to EnableCollectionSynchronization?</p> <p>A: <em>You pick which overload of EnableCollectionSynchronization to use based on how your app synchronizes access to its own collection. If you're using fancy synchronization primitives - semaphores, ReadWriteLock, ManualResetEvent, etc. - you'd use the overload with a callback argument. Whenever WPF needs to touch the collection, it calls the callback, which uses the fancy primitive to gain the right permissions. On the other hand, if you're just using&nbsp; "lock(x) { … }", you'd use the overload with just a lock object, passing in x. Whenever WPF needs to touch the collection, it also does "lock(x) { … }". This saves one level of callback in the common case.</em></p> <p>Also note that you can use <strong>BindingOperations.DisableCollectionSynchronization(collection)</strong> when you want to stop using synchronization.</p> <h3>Getting in Before the CollectionView is Created</h3> <p>The BindingOperations class provides an event CollectionRegistering, which lets you register the collection for cross-thread access before any CollectionView instances are generated for it. Inside this event handler, you can do the actual registering of the collection. Here's an example:</p> <pre class="brush: csharp;"> public ObservableCollection&lt;Stock&gt; Stocks { get; private set; }<br /> <br /> private object _stocksLock = new object();<br /> <br /> public MainViewModel()<br /> {<br /> Stocks = new ObservableCollection&lt;Stock&gt;();<br /> BindingOperations.CollectionRegistering += BindingOperations_CollectionRegistering;<br /> <br /> //BindingOperations.EnableCollectionSynchronization(Stocks, _stocksLock);<br /> }<br /> <br /> void BindingOperations_CollectionRegistering(object sender, CollectionRegisteringEventArgs e)<br /> {<br /> Debug.WriteLine("CollectionRegistering Event");<br /> if (e.Collection == Stocks)<br /> {<br /> BindingOperations.EnableCollectionSynchronization(Stocks, _stocksLock);<br /> }<br /> } </pre> <p>This is actually a good place to handle the registration, as you know you'll get to register for cross-thread access at the right time, before any dependent objects are created. In fact, I'd say this is the <strong>best place to do the EnableCollectionSynchronization call</strong>. You can do it in the constructor for simple apps, but once you start adding views (and sorting, and datagrids and the like), you'll want to do it here.</p> <h3>What's Happening with Change Notifications</h3> <p>Inside the framework, pending change notifications from the background thread are queued up and then acted on by the UI thread when it has time. This helps increase responsiveness for higher-priority events like input (mouse, keyboard, touch).</p> <p>This is new for .NET 4.5 as part of this cross-thread collection work.</p> <h3>Fin</h3> <p>I hope you've found that this post helps clarify some of the open questions from the previous post. The work the WPF team has done to enable cross-thread collections is a fair bit of work, even though it surfaces through a pretty small API. This is also one of those features which will simply make your own application code nicer, with less plumbing gunk in it.</p> <p>Updated example code attached.</p> <p><a href="http://feedads.g.doubleclick.net/~a/xpK0io5Brd9EB7uUB9hgei-WUrc/0/da"><img src="http://feedads.g.doubleclick.net/~a/xpK0io5Brd9EB7uUB9hgei-WUrc/0/di" border="0" ismap="true"></img></a><br/> <a href="http://feedads.g.doubleclick.net/~a/xpK0io5Brd9EB7uUB9hgei-WUrc/1/da"><img src="http://feedads.g.doubleclick.net/~a/xpK0io5Brd9EB7uUB9hgei-WUrc/1/di" border="0" ismap="true"></img></a></p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=c2zpPWogWkQ:xz9n4qu29zE:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=c2zpPWogWkQ:xz9n4qu29zE:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=c2zpPWogWkQ:xz9n4qu29zE:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=c2zpPWogWkQ:xz9n4qu29zE:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=c2zpPWogWkQ:xz9n4qu29zE:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=c2zpPWogWkQ:xz9n4qu29zE:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=c2zpPWogWkQ:xz9n4qu29zE:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=c2zpPWogWkQ:xz9n4qu29zE:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=c2zpPWogWkQ:xz9n4qu29zE:gIN9vFwOqvQ" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/PeteBrown/~4/c2zpPWogWkQ" height="1" width="1"/> http://feedproxy.google.com/~r/PeteBrown/~3/c2zpPWogWkQ/wpf-45-cross-thread-collection-synchronization-redux Pete Brown 3547 2012-01-20T22:59:04 Full Stack Resumes–MVVM Design http://feedproxy.google.com/~r/JesseLiberty-SilverlightGeek/~3/l-ZWlwjR-tw/ Jesse Liberty [MS] 3545 2012-01-19T15:15:29 New Videos Uploaded http://feedproxy.google.com/~r/JesseLiberty-SilverlightGeek/~3/Sm2SJooUVFw/ Jesse Liberty [MS] 3544 2012-01-18T18:50:10 Calling Navigate From The View Model http://feedproxy.google.com/~r/JesseLiberty-SilverlightGeek/~3/8EY0wAQIEDY/ Jesse Liberty [MS] 3541 2012-01-17T17:04:01 WPF 4.5: Observable Collection Cross-Thread Change Notification <p>WPF 4.5 is available as part of the <a href="http://msdn.microsoft.com/en-us/vstudio/hh127353" target="_blank">Visual Studio 11 Developer Preview</a> released at the Build 2011 conference, and is part of the .NET Framework version 4.5. WPF 4.5 addresses several important customer requests including the ability to have cross-thread change notification for collections - the topic of this post.</p> <blockquote><strong>Update 1/20/2012:</strong> I have <a href="http://10rem.net/blog/2012/01/20/wpf-45-cross-thread-collection-synchronization-redux"> posted a set of updates</a> to this post with additional information about the details, as well as a few code changes. Be sure to read that post as well as this one.</blockquote> <h3>The Problem</h3> <p>As I explained in my post on <a href="http://10rem.net/blog/2012/01/10/threading-considerations-for-binding-and-change-notification-in-silverlight-5" target="_blank">cross-thread change notification</a>, Silverlight and WPF have the concept of the UI thread and background (or secondary) threads. Code on a background thread is not allowed to interact with UI elements (controls, etc.) on the foreground thread. You can find more information about the general problem in that post.</p> <p>What happens when you need to add and remove items from a collection from that background thread? That's pretty common in applications which must keep a list updated (stock trading is an obvious example). When the collection raises the change notification events, the binding system and listeners, on the UI thread, have code executed. Remember, an event is just a delegate, or really, just a function pointer. So, essentially, the collection is calling a function on the UI thread. That's not allowed, and it throws an exception.</p> <p><img src="http://10rem.net/media/82267/Windows-Live-Writer_Threading-Considerations-for-Binding-in-_EF97_image_2.png"/></p> <p>The approach pre-4.5 was to dispatch all calls to add items to the collection. The diagram from the Silverlight post applies here.</p> <p><a href="http://10rem.net/media/82660/Windows-Live-Writer_WPF.5-Observable-Collection-Cross-Thread_CD9A_image_2.png" target="_blank"><img src="http://10rem.net/media/82665/Windows-Live-Writer_WPF.5-Observable-Collection-Cross-Thread_CD9A_image_thumb.png" width="650" height="265" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>If code on the background thread needs to access elements on the UI thread, set a property for example, it needs to dispatch the call to the UI thread using the dispatcher or synchronization context. Get enough of this happening, such as when constantly updating a collection, and you can run into some real performance problems.</p> <h3>The 4.5 Solution</h3> <p>We actually have a good solution for this in WPF 4.5. The BindingOperations class includes the EnableCollectionSynchronization function. This function helps the binding system and the collection intelligently handle change notification.</p> <p>Let's look at an example. The application, when run, will look like this:</p> <p><a href="http://10rem.net/media/82670/Windows-Live-Writer_WPF.5-Observable-Collection-Cross-Thread_CD9A_image_4.png" target="_blank"><img src="http://10rem.net/media/82675/Windows-Live-Writer_WPF.5-Observable-Collection-Cross-Thread_CD9A_image_thumb_1.png" width="500" height="318" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>The stocks in the ListBox are loaded by clicking the "Load" button. To test the change notification, click the Keep Loading button. For this example, the Keep Updating button doesn't do anything (more on that when I cover in-place sorting and updating in another post)</p> <h4>XAML</h4> <p>Just for grins, and to show its inclusion in 4.5, I've put the functionality into another new addition to WPF proper: the Ribbon. I didn't use commands although they are supported.</p> <pre class="brush: xml;"> &lt;RibbonWindow x:Class="WpfApplication2.MainWindow"<br /> xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"<br /> xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"<br /> xmlns:local="clr-namespace:WpfApplication2"<br /> Title="MainWindow" Height="350" Width="525"&gt;<br /> &lt;Grid&gt;<br /> &lt;Ribbon&gt;<br /> &lt;RibbonTab Header="First Tab"&gt;<br /> &lt;RibbonGroup Header="Group 1"&gt;<br /> &lt;RibbonButton x:Name="Foo" Label="Foo!" /&gt;<br /> &lt;RibbonButton x:Name="Bar"<br /> Label="Bar!" /&gt;<br /> &lt;/RibbonGroup&gt;<br /> &lt;RibbonGroup Header="Group 2"&gt;<br /> &lt;RibbonButton x:Name="Load"<br /> Click="Load_Click"<br /> Label="Load" /&gt;<br /> &lt;RibbonButton x:Name="KeepLoading"<br /> Click="KeepLoading_Click"<br /> Label="Keep loading" /&gt;<br /> &lt;RibbonButton x:Name="KeepUpdating"<br /> Label="Keep Updating" /&gt;<br /> <br /> &lt;/RibbonGroup&gt;<br /> &lt;RibbonGroup Header="Count"&gt;<br /> &lt;TextBlock Text="{Binding Stocks.Count}" /&gt;<br /> &lt;/RibbonGroup&gt;<br /> &lt;/RibbonTab&gt;<br /> &lt;RibbonTab Header="Second Tab"&gt;<br /> <br /> &lt;/RibbonTab&gt;<br /> &lt;RibbonTab Header="Stuff that doesn't go anywhere else"&gt;<br /> <br /> &lt;/RibbonTab&gt;<br /> &lt;/Ribbon&gt;<br /> <br /> &lt;Grid Margin="0,156,0,0"&gt;<br /> &lt;TextBlock VerticalAlignment="Top"<br /> FontSize="20"<br /> Text="WPF Rules" /&gt;<br /> <br /> &lt;Grid&gt;<br /> &lt;Grid.ColumnDefinitions&gt;<br /> &lt;ColumnDefinition Width="*" /&gt;<br /> &lt;ColumnDefinition Width="*" /&gt;<br /> &lt;/Grid.ColumnDefinitions&gt;<br /> <br /> &lt;ListBox ItemsSource="{Binding Stocks}"<br /> VirtualizingPanel.IsVirtualizing="True"<br /> VirtualizingPanel.CacheLengthUnit="Page"<br /> VirtualizingPanel.CacheLength="2,2"<br /> VirtualizingPanel.ScrollUnit="Item"&gt;<br /> &lt;ListBox.ItemTemplate&gt;<br /> &lt;DataTemplate&gt;<br /> &lt;Grid&gt;<br /> &lt;Grid.ColumnDefinitions&gt;<br /> &lt;ColumnDefinition Width="100" /&gt;<br /> &lt;ColumnDefinition Width="100" /&gt;<br /> &lt;/Grid.ColumnDefinitions&gt;<br /> <br /> &lt;TextBlock Text="{Binding Symbol}"<br /> Grid.Column="0" /&gt;<br /> &lt;TextBlock Text="{Binding Value}"<br /> Grid.Column="1" /&gt;<br /> &lt;/Grid&gt;<br /> &lt;/DataTemplate&gt;<br /> &lt;/ListBox.ItemTemplate&gt;<br /> &lt;/ListBox&gt;<br /> <br /> &lt;/Grid&gt;<br /> &lt;/Grid&gt;<br /> &lt;/Grid&gt;<br /> &lt;/RibbonWindow&gt;<br /> </pre> <p>For this example, the primary pieces to pay attention to are the ListBox which is bound to the stocks, and the ribbon buttons to Load and Update the stocks collection. Those use the Stock model item via the ViewModel.</p> <h4>The Model</h4> <p>The model consists of a single class, called Stock.</p> <pre class="brush: csharp;"> using System.ComponentModel;<br /> <br /> namespace WpfApplication2.Model<br /> {<br /> class Stock : INotifyPropertyChanged<br /> {<br /> public event PropertyChangedEventHandler PropertyChanged;<br /> <br /> private string _symbol;<br /> <br /> public string Symbol<br /> {<br /> get { return _symbol; }<br /> set { _symbol = value; NotifyPropertyChanged("Symbol"); }<br /> }<br /> private decimal _value;<br /> <br /> public decimal Value<br /> {<br /> get { return _value; }<br /> set { _value = value; NotifyPropertyChanged("Value"); }<br /> }<br /> <br /> protected void NotifyPropertyChanged(string propertyName)<br /> {<br /> if (PropertyChanged != null)<br /> PropertyChanged(this, new PropertyChangedEventArgs(propertyName));<br /> }<br /> }<br /> } </pre> <h4>The ViewModel</h4> <p>The ViewModel is where the action is. First the listing, and then the explanation.</p> <pre class="brush: csharp;"> using System.Threading;<br /> using System.Threading.Tasks;<br /> using System.Windows.Data;<br /> using WpfApplication2.Model;<br /> <br /> namespace WpfApplication2.ViewModel<br /> {<br /> class MainViewModel<br /> {<br /> public ObservableCollection&lt;Stock&gt; Stocks { get; set; }<br /> <br /> private object _stocksLock = new object();<br /> <br /> public MainViewModel()<br /> {<br /> Stocks = new ObservableCollection&lt;Stock&gt;();<br /> <br /> BindingOperations.EnableCollectionSynchronization(Stocks, _stocksLock);<br /> }<br /> <br /> <br /> private Random _random = new Random();<br /> public void AddNewItems()<br /> {<br /> for (int i = 0; i &lt; 100; i++)<br /> {<br /> var item = new Stock();<br /> for (int j = 0; j &lt; _random.Next(2, 4); j++)<br /> {<br /> item.Symbol += char.ConvertFromUtf32(_random.Next(<br /> char.ConvertToUtf32("A", 0),<br /> char.ConvertToUtf32("Z", 0)));<br /> }<br /> <br /> item.Value = (decimal)(_random.Next(100, 6000) / 100.0);<br /> Stocks.Add(item);<br /> Debug.WriteLine(item.Symbol);<br /> }<br /> }<br /> <br /> <br /> public void StartAddingItems()<br /> {<br /> Task.Factory.StartNew(() =&gt;<br /> {<br /> while (true)<br /> {<br /> AddNewItems();<br /> Thread.Sleep(500);<br /> }<br /> });<br /> <br /> }<br /> }<br /> }<br /> </pre> <p>When the MainViewModel is instantiated, the collection is created. Next, I call the EnableCollectionSynchronization method, providing it the collection and an object to use as a lock. The lock object is nothing special, just an instance of the CLR object type. This single method makes cross-thread collection change notification possible.</p> <p>The StartAddingItems method spins up another thread, using the Task parallel library, which then loads items into the collection. The data is randomly generated, but includes a large number of updates. When you run the application, you'll see that the ListBox is able to be quickly updated and that there are no cross-thread exceptions reported.</p> <p>If you want to cause the exceptions to happen as normal, comment out the BindingOperations.EnableCollectionSynchronization call.</p> <h3>Summary</h3> <p>WPF 4.5 includes a number of key targeted performance and capability features, one of which is cross-thread collection change notification. Enabling the change notification is as simple as the inclusion of a lock object and a single function call. Versus the manual dispatching approach, this can be a real performance win, not to mention save you some coding time.</p> <p><a href="http://feedads.g.doubleclick.net/~a/xxv0VpPdzRXDjKbdNUBQ_aF8JrU/0/da"><img src="http://feedads.g.doubleclick.net/~a/xxv0VpPdzRXDjKbdNUBQ_aF8JrU/0/di" border="0" ismap="true"></img></a><br/> <a href="http://feedads.g.doubleclick.net/~a/xxv0VpPdzRXDjKbdNUBQ_aF8JrU/1/da"><img src="http://feedads.g.doubleclick.net/~a/xxv0VpPdzRXDjKbdNUBQ_aF8JrU/1/di" border="0" ismap="true"></img></a></p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=scWqRnw-t04:K_OPDAcZ6m8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=scWqRnw-t04:K_OPDAcZ6m8:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=scWqRnw-t04:K_OPDAcZ6m8:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=scWqRnw-t04:K_OPDAcZ6m8:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=scWqRnw-t04:K_OPDAcZ6m8:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=scWqRnw-t04:K_OPDAcZ6m8:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=scWqRnw-t04:K_OPDAcZ6m8:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=scWqRnw-t04:K_OPDAcZ6m8:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=scWqRnw-t04:K_OPDAcZ6m8:gIN9vFwOqvQ" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/PeteBrown/~4/scWqRnw-t04" height="1" width="1"/> http://feedproxy.google.com/~r/PeteBrown/~3/scWqRnw-t04/wpf-45-observable-collection-cross-thread-change-notification Pete Brown 3540 2012-01-16T21:54:30 GNU C++ BlinkenLED Part 1 on the AVR (ATmega1284P with MikroElektronika EasyAVR6) and Atmel AVR Studio 5.1 <p>In this Part 1 post, I'll show how to interface with ATmega ports and pins to light up LEDs on a board. The follow-up post will show how to use the timer to actually blink the LED.</p> <p>Most of the Microcontroller code out in the public is C or Assembly. I have nothing personal against assembly or C (and may end up using a little assembly in the future), but I decided I wanted to write C++, as I like its encapsulation and structure when compared to straight C.</p> <blockquote> <p>I've written some other posts about getting started with these boards and environments. Be sure to check them out:</p> <ul> <li><a href="http://10rem.net/blog/2011/11/05/getting-started-with-avr-studio-5">Getting Started with AVR Studio 5</a></li> <li><a href="http://10rem.net/blog/2012/01/13/setting-up-for-developing-and-debugging-the-avr-atmega1284p-with-avrstudio-51"> Setting up for Developing and Debugging the AVR (ATmega1284P) with AVRStudio 5.1</a></li> </ul> </blockquote> <p><strong>Disclaimer:</strong> I don't have a lot of experience with the AVR. I'm writing as I'm learning. If you find a mistake below, please point it out in the comments.</p> <p><strong>C++ Disclaimer:</strong> If code size and execution speed are your primary concerns, you can certain do a bit better in C or even more so in assembly. C++ does add some overhead, especially if you go nuts on the class hierarchies. I've tried to strike a balance between size, speed, and encapsulation in my own libraries here, and also to show the differences. If you intend to write for some of the ATtiny chips with their miniscule 2k or 4k (sometimes a bit more) program memory, write some macro-oriented C or better yet, break out that assembler. For the larger chips with a little more headroom, C++ is a fun way to go, and is my preference.</p> <p><strong>Platform Disclaimer:</strong> Most of my readers will be far more productive on the .NET Micro Framework and the <a href="http://netduino.com/" target="_blank">Netduino</a>, <a href="http://www.ghielectronics.com/catalog/category/7/" target="_blank">FEZ Devices</a>, or <a href="http://www.netmf.com/gadgeteer/" target="_blank">Gadgeteer</a>. If you're not doing heavy speed-critical signal processing, you'll probably have more <strong>fun with NETMF and get from zero to application much more quickly</strong>. For people not using C# but who wish to continue with C/C++ on the AVR specifically, Arduino has most of these types of things figured out in its rich library. It's not really C++, but it's a good approach to developing on a subset of the AVR MCUs. If you're interested more in just getting something done specifically on the AVR, I recommend looking at that. Finally, if you want to write C on the metal, Atmel also makes their own AVR library which helps abstract away the differences between MCUs. I personally found that confusing to use, with many different ways to accomplish the same tasks, and a large number of poorly documented APIs to learn. They were C as well, and without great naming conventions on their part, it was next to impossible to get a ful picture of everything available in a particular problem domain. In my case, I specifically want to learn MCU programming without all that baggage, so I'm simply coding on the metal but using C++.</p> <h3>Ports and pins</h3> <p>This family of MCUs have 8*4 (32) General Purpose Input/Output (GPIO) pins. They can all be used for GPIO, but some ports can also be assigned different functions. Here's are the pin configurations for the PDIP and the TQFP/QFN/MLF surface mount versions from the data sheet. (There are other pages covering the tiny VFBGA and DRQFN versions, in case you wanted super tiny surface mount versions)</p> <p><a href="http://10rem.net/media/82484/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_9.png" target="_blank"><img src="http://10rem.net/media/82489/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_thumb_3.png" width="660" height="302" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <p>I'm using the PDIP version on the left. On that, you can see, for example, that pins 14 through 21 (port D) have the transmit (TXD) and receive (RXD) functions for the USARTs. When you use those pins for the USART, you can't use them for GPIO, so you need to be smart about which pins you use for which functions. (I've been doing a lot with port D and MIDI - more on that in a future post.) You can also see that the entire family of chips ATmega164A, ATmega164PA, ATmega324A, ATmega644A, ATmega644PA, ATmega1284, and ATmega1284P all share the same pin configuration and device layout. (and yeah, I'll admit that listing them all here was for search engines &lt;g&gt;). Where they differ is in memory. Here's the table from the same data sheet.</p> <p><a href="http://10rem.net/media/82494/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_10.png" target="_blank"><img src="http://10rem.net/media/82499/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_thumb_4.png" width="660" height="282" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <p>In this post, I'll concentrate on using Port A. As I previously mentioned, the MCU I'm using is the ATmega1284P, so I have a whopping (in MCU terms) available program size of 128K. That's as much total memory as the Commodore 128 computer sitting behind me on my desk, and that doesn't even count the 16K available RAM and 4k available EEPROM. In a nutshell, here's how that memory is used:</p> <ul> <li><strong>Flash</strong>: This is the memory used to store your program code. When you "program" the MCU, this memory is directly consumed by the instructions for your application.</li> <li><strong>EEPROM</strong>: This is where you can store persistent settings, like configuration set by the user of your end product.</li> <li><strong>RAM</strong>: Allocated variables, arrays etc. You can blow through 16K very quickly if you try and do things like you would on the desktop (like a lookup table of 16 bit values to make SIN calculations faster), so you need to be smart about that.</li> </ul> <p>Now, back to pins and ports. The ATmega and ATxmega MCUs by Atmel (and possibly the ATtiny and others - I haven't checked) group their IO pins into ports. The ATmega1284 has four ports A, B, C and D, each of which has 8 pins. By grouping this way, a single 8 bit register can contain the digital information for each in in the port.</p> <p><a href="http://10rem.net/media/82504/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_18.png" target="_blank"><img src="http://10rem.net/media/82509/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_thumb_8.png" width="650" height="116" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <p>So, if you know the base address of Port A's pins data register is 0x20 (or 0x00, for reasons explained in the data sheet), you can find out the value of pin 2 using code like this:</p> <pre class="brush: cpp;"> #define PINA_ADDRESS 0x20<br /> <br /> isHigh = (*PINA_ADDRESS) &amp; 0b00000100; </pre> <p>You can set pin 2 to high using this code, assuming that all the pins were low before (this actually *toggles* pin 2):</p> <pre class="brush: cpp;"> #define PINA_ADDRESS 0x20<br /> (*PINA_ADDRESS) |= 0b00000100; </pre> <p>After you set it, that bit of PINA will be 1 if the pin is high, and 0 if it is low, regardless of what your code actually sets it to when toggling.</p> <p>You can see how using preprocessor defines like that makes the code easier to read, but still results in a really tiny program. By default, the AVR libraries include even nicer preprocessor macros to get to individual pins, but we're not using them here. Of course, I did oversimplify a little, at least in the second example. There are other things you must consider before just setting pin values.</p> <h4>Direction and Data Registers</h4> <p>When you want to use pins on a port, you should configure its pins as input or output. For Port A, this involves the DDRA (Port A Data Direction Register). This is another 8 bit register which defines the direction for each pin: 1 is output, 0 is input.</p> <p>Also, when reading and writing values, you don't always use the same register.</p> <p><a href="http://10rem.net/media/82514/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_46.png" target="_blank"><img src="http://10rem.net/media/82519/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_thumb_22.png" width="650" height="261" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <p>You have to read the data sheet about 100 times to make sense of these groups. When compared to the xmega, I found the uses a bit opaque. So, here's my summary:</p> <ul> <li>To mark a pin as input, write a 0 to the appropriate bit in the DDRx register.</li> <li>To mark a pin as output, write a 1 to the appropriate bit in the DDRx register</li> <li>To read the value of a pin, check the appropriate bit in the PINx register</li> <li>To TOGGLE the value of a pin, write to the appropriate bit in the PINx register <ul> <li>This means you need to read the pin value before you toggle it.</li> </ul> </li> </ul> <p>Beyond that, there are some other registers that affect the entire port. This table is useful for figuring out what they do.</p> <p><a href="http://10rem.net/media/82524/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_12.png" target="_blank"><img src="http://10rem.net/media/82529/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_thumb_5.png" width="660" height="215" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <h3>Basic Implementation</h3> <p>Let's first look at an implementation that looks like C code in a CPP file. We'll use that as the benchmark for the rest of the application.</p> <h4>Creating the project</h4> <p>First, I assume you have Atmel AVR Studio 5.1 installed on your machine. If not, please refer to the two previous posts linked at the top of this post. I'm also going to be using a JTAGICE-compatible programmer and debugger here, also covered in that previous post.</p> <p>Create a new project in AVR Studio 5.1. If you're running only 5.0, you won't see the C++ options unless you have the C++ add-in. Also notice how these show up under "C/C++" and not under the board-specific folders. We won't be using the board templates here.</p> <p><a href="http://10rem.net/media/82534/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_20.png" target="_blank"><img src="http://10rem.net/media/82539/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_thumb_9.png" width="650" height="402" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <p>I named the project AvrBlinkenLed.</p> <p>The next step is to pick the processor. Make sure you pick the one you're using. I'm using the ATmega1284P. The easiest way to find your processor is to enter its model number in the search box at the upper right.</p> <p><a href="http://10rem.net/media/82544/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_22.png" target="_blank"><img src="http://10rem.net/media/82549/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_thumb_10.png" width="650" height="464" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <p>Once you select the processor, Visual Studio will load up the project template and put you right in the main .cpp file. You'll want to adjust a couple things before you do any real coding, however.</p> <h4>Setting clock speed and Debugger</h4> <p>Next, we'll need to set the clock speed. You could leave it at the default 1Mhz, as we're not doing anything special here. However, why not bump it up to 8Mhz? To do that, we'll need to make changes in a few places. First, we'll need to actually set the value on the chip. In this case, we only need to clear the multiplier fuse which forces the ship at 1MHz by default.</p> <p>Go into Tools | AVR Programming. After a moment, the AVR Programming tool will come up. It'll look for your JTAG programmer and, if found, will display it in the tool list at the left and the found MCU in the Device drop down to its right. If it was not found, your JTAG programmer/ debugger is not set up correctly, or your board isn't connected. Refer to the manufacturer instructions to fix that before going any further.</p> <p><a href="http://10rem.net/media/82554/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_24.png" target="_blank"><img src="http://10rem.net/media/82559/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_thumb_11.png" width="650" height="354" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <p>If you only have the one JTAG programmer/debugger installed, and aren't doing any chaining of devices (if you're reading this post, you almost certainly are not) simply click the "Apply" button to pull back the MCU information. Click on the "Fuses" tab.</p> <p><a href="http://10rem.net/media/82564/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_26.png" target="_blank"><img src="http://10rem.net/media/82569/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_thumb_12.png" width="650" height="398" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <blockquote> <p><strong>WARNING</strong>: Setting some fuses or lock bits can <strong>brick your MCU and require special high-power parallel programming to reset it</strong>. Be sure you completely understand the purpose of a given fuse or lock before you do anything with it.</p> </blockquote> <p>I had already cleared the CKDIV8 fuse in my MCU. If you just got yours, it will be set. What this does is divide the 8MHz clock down so you get a CPU clock of 1MHz. Clear that fuse, and only that fuse, and then click the "Program" button on the right. Make sure if works.</p> <p>While there, make sure the JTAGEN fuse is set so you can use the JTAG debugger. If not set, set it and program that one fuse setting.</p> <p>Next, go into the project properties (right-click the AvrBlinkenLed project and select "Properties") and click the "Tool" tab. This is where you set up the programmer/debugger to use.</p> <p><a href="http://10rem.net/media/82574/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_28.png" target="_blank"><img src="http://10rem.net/media/82579/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_thumb_13.png" width="650" height="385" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <p>Pick the JTAG programmer from the list. Once you do that, change the interface on the right to JTAG so you can debug. By default, it is ISP (In System Programmer) which only allows programming. Then change the JTAG clock so it's some value lower than 8Mhz / 4.</p> <p><a href="http://10rem.net/media/82584/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_30.png" target="_blank"><img src="http://10rem.net/media/82589/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_thumb_14.png" width="568" height="178" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <p>Finally, we'll define a compiler constant in the main file. The F_CPU constant is a standard approach you'll see often. In fact, if you use some of the AVR libraries, they require that specific constant to be set.</p> <pre class="brush: cpp;"> /*<br /> * AvrBlinkenLed.cpp<br /> *<br /> * Created: 1/15/2012 4:21:24 PM<br /> * Author: Peter.Brown<br /> */<br /> #define F_CPU 8000000<br /> //#include &lt;avr/io.h&gt;<br /> <br /> int main(void)<br /> {<br /> while(1)<br /> {<br /> //TODO:: Please write your application code<br /> }<br /> } </pre> That's the default template with the addition of the F_CPU constant. <strong>Also note that I commented out the io.h include. We're going to do things from scratch here.</strong> The code doesn't do anything yet, though, although it does compile. <h4>A few more helpful constants and macros</h4> <p>One reason straight C code tends to be so efficient, is that there are almost no constants, enums, or variables in use for chip-specific stuff. Instead, most everything is done in the preprocessor, which ends up resolving down to pointer manipulation.</p> <p>We're not taking that approach here, but we'll still use some constants to help us out.</p> <p>Add a new include file to the project, named ATmega1284P.h</p> <p><a href="http://10rem.net/media/82594/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_34.png" target="_blank"><img src="http://10rem.net/media/82599/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_thumb_16.png" width="650" height="315" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <p>The file will contain the processor-specific constants and types we want to use. In this case, the addresses for the registers.</p> <pre class="brush: cpp;"> /*<br /> * ATmega1284P.h<br /> *<br /> * Created: 1/15/2012 4:41:26 PM<br /> * Author: Peter.Brown<br /> */<br /> <br /> <br /> #ifndef ATMEGA1284P_H_<br /> #define ATMEGA1284P_H_<br /> <br /> typedef volatile unsigned char register8_t;<br /> <br /> #define PINA (*(register8_t*) 0x20)<br /> #define DDRA (*(register8_t*) 0x21)<br /> #define PORTA (*(register8_t*) 0x22)<br /> <br /> #endif /* ATMEGA1284P_H_ */ </pre> <p>Once you do that, we have enough to be able to turn the LEDs on or off. We're going to light the LEDs in a pattern as shown in this photo. You can see from the little diagram on the board (under the RoHS symbol) that the LEDs are configured in current source configuration, so setting them to 1 will light them up.</p> <p><a href="http://10rem.net/media/82604/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_36.png" target="_blank"><img src="http://10rem.net/media/82609/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_thumb_17.png" width="660" height="340" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <p>Here's the code for the main file. Doing this will set the above pattern for the LEDS.</p> <pre class="brush: cpp;"> /*<br /> * AvrBlinkenLed.cpp<br /> *<br /> * Created: 1/15/2012 4:21:24 PM<br /> * Author: Peter.Brown<br /> */<br /> #define F_CPU 8000000<br /> <br /> #include "ATmega1284P.h"<br /> <br /> int main(void)<br /> {<br /> DDRA = 0b11111111;<br /> PINA = 0b10101010;<br /> <br /> while(1)<br /> {<br /> //TODO:: Please write your application code<br /> <br /> }<br /> } </pre> <p>In this code, I set all 8 pins to output, and then set alternated pins to 1 to set them to high (<strong>it actually toggles the pin value, but because they were all low (0) to begin with, this works</strong>). In a current source configuration, where the LEDs get their voltage from the MCU and the MCU is the source of the current, setting the pin to high will cause the LED to light. If they were in a current sink configuration, where the MCU provides ground reference, setting them to low (0) would light the LEDs. The LED class we create will support either configuration.</p> <h4>Deploying and Running</h4> <p>To deploy the code, first compile. You'll see output which states how small the code is (178 bytes total, wow!)</p> <pre class="brush: plain;"> ------ Build started: Project: AvrBlinkenLed, Configuration: Debug AVR ------<br /> Build started.<br /> Project "AvrBlinkenLed.cppproj" (default targets):<br /> Target "PreBuildEvent" skipped, due to false condition; ('$(PreBuildEvent)'!='') was evaluated as (''!='').<br /> Target "CoreBuild" in file "C:\Program Files (x86)\Atmel\AVR Studio 5.1\Vs\Compiler.targets" from project "D:\Documents\Docs\Projects\AvrBlinkenLed\AvrBlinkenLed\AvrBlinkenLed.cppproj" (target "Build" depends on it):<br /> Task "RunCompilerTask"<br /> C:\Program Files (x86)\Atmel\AVR Studio 5.1\make\make.exe all<br /> AvrBlinkenLed.cpp<br /> Invoking: AVR8/GNU C++ Compiler<br /> "C:\Program Files (x86)\Atmel\AVR Studio 5.1\extensions\Atmel\AVRGCC\3.3.1\AVRToolchain\bin\avr-g++.exe" -funsigned-char -funsigned-bitfields -O1 -fpack-struct -fshort-enums -g2 -Wall -c -mmcu=atmega1284p -o"AvrBlinkenLed.o" ".././AvrBlinkenLed.cpp"<br /> Finished building: .././AvrBlinkenLed.cpp<br /> Building target: AvrBlinkenLed.elf<br /> Invoking: AVR8/GNU C++ Linker<br /> "C:\Program Files (x86)\Atmel\AVR Studio 5.1\extensions\Atmel\AVRGCC\3.3.1\AVRToolchain\bin\avr-g++.exe" -o AvrBlinkenLed.elf AvrBlinkenLed.o -Wl,-Map="AvrBlinkenLed.map" -Wl,-lm -mmcu=atmega1284p<br /> Finished building target: AvrBlinkenLed.elf<br /> "C:\Program Files (x86)\Atmel\AVR Studio 5.1\extensions\Atmel\AVRGCC\3.3.1\AVRToolchain\bin\avr-objcopy.exe" -O ihex -R .eeprom -R .fuse -R .lock -R .signature "AvrBlinkenLed.elf" "AvrBlinkenLed.hex"<br /> "C:\Program Files (x86)\Atmel\AVR Studio 5.1\extensions\Atmel\AVRGCC\3.3.1\AVRToolchain\bin\avr-objcopy.exe" -j .eeprom --set-section-flags=.eeprom=alloc,load --change-section-lma .eeprom=0 --no-change-warnings -O ihex "AvrBlinkenLed.elf" "AvrBlinkenLed.eep" || exit -j .eeprom --set-section-flags=.eeprom=alloc,load --change-section-lma .eeprom=0 --no-change-warnings -O ihex "AvrBlinkenLed.elf" "AvrBlinkenLed.eep" || exit 0<br /> "C:\Program Files (x86)\Atmel\AVR Studio 5.1\extensions\Atmel\AVRGCC\3.3.1\AVRToolchain\bin\avr-objdump.exe" -h -S "AvrBlinkenLed.elf" &gt; "AvrBlinkenLed.lss"<br /> "C:\Program Files (x86)\Atmel\AVR Studio 5.1\extensions\Atmel\AVRGCC\3.3.1\AVRToolchain\bin\avr-size.exe" -C --mcu=atmega1284p "AvrBlinkenLed.elf"<br /> AVR Memory Usage<br /> ----------------<br /> Device: atmega1284p<br /> Program: 178 bytes (0.1% Full)<br /> (.text + .data + .bootloader)<br /> Data: 0 bytes (0.0% Full)<br /> (.data + .bss + .noinit)<br /> Done executing task "RunCompilerTask".<br /> Done building target "CoreBuild" in project "AvrBlinkenLed.cppproj".<br /> Target "PostBuildEvent" skipped, due to false condition; ('$(PostBuildEvent)' != '') was evaluated as ('' != '').<br /> Target "Build" in file "C:\Program Files (x86)\Atmel\AVR Studio 5.1\Vs\Avr.common.targets" from project "D:\Documents\Docs\Projects\AvrBlinkenLed\AvrBlinkenLed\AvrBlinkenLed.cppproj" (entry point):<br /> Done building target "Build" in project "AvrBlinkenLed.cppproj".<br /> Done building project "AvrBlinkenLed.cppproj".<br /> <br /> Build succeeded.<br /> ========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========<br /> </pre> <p>The next step is to take the hex file that was created and load that to the board via the JTAG programmer. Go under Tools | AVR Programming again, and select the "Memories" tab after hitting "apply" to pull up the ATmega we're using.</p> <p><a href="http://10rem.net/media/82614/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_38.png" target="_blank"><img src="http://10rem.net/media/82619/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_thumb_18.png" width="650" height="439" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <p>Select the hex file from your project. You can see where it's located on my file system. The programmer will remember this from project to project, so always double-check to make sure you're programming the right code. Once sure, click the "Program" button. You'll see the following status:</p> <p><a href="http://10rem.net/media/82624/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_40.png" target="_blank"><img src="http://10rem.net/media/82629/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_thumb_19.png" width="164" height="74" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <p>You should immediately see the output on your test board. If not, close the AVR Programming tool and hit the Reset button on your board.</p> <p>Now, all of that is wonderfully efficient, but not particularly friendly or reusable. So, let's look at how to do this another way.</p> <h3>First Implementation in real C++</h3> <p>The C code is simple and very tight. However, once you get into a complex application, the code can get confusing and jumbled. The nature of a language like C requires extreme discipline to keep the code compartmentalized and reduce dependencies between the different modules. Often times, the developer will trade away some of that for the sake of performance or code size. The AVR libraries that come with AVR Studio include a fair bit of that.</p> <p><strong>To be clear, you can write very good code in C as long as you have discipline.</strong> You can also write crap code in C++, but the compiler and language give you a few more things to help you do the right thing.</p> <h4>The IOPort class</h4> <p>In my first version of this code, I created an IOPin class rather than IOPort. I did this because I wanted to make my library smell a bit like the NETMF libraries where you code against DigitalInput and DigitalOutput classes. However, that meant creating an instance of the class for each pin you wanted to manipulate - an entire class for 3 bits (literally, bits) worth of data. It also didn't allow me to group operations at the port level. So, in the version I'm presenting here, I went at it at the port level with the IOPort class.</p> <p>First, create a header file named IOPort.h</p> <pre class="brush: cpp;"> /*<br /> * IOPort.h<br /> *<br /> * Created: 1/15/2012 5:43:58 PM<br /> * Author: Peter.Brown<br /> */<br /> <br /> <br /> #ifndef IOPORT_H_<br /> #define IOPORT_H_<br /> <br /> #include "ATmega1284P.h"<br /> <br /> enum PinDirection<br /> {<br /> DirectionInput = 0,<br /> DirectionOutput = 1<br /> };<br /> <br /> class IOPort<br /> {<br /> protected:<br /> volatile register8_t* _port;<br /> volatile register8_t* _pins;<br /> volatile register8_t* _ddr;<br /> public:<br /> IOPort(register8_t* portRegister, register8_t* pinsRegister, register8_t* ddrRegister) :<br /> _port(portRegister),<br /> _pins(pinsRegister),<br /> _ddr(ddrRegister) {}<br /> <br /> void SetPortDirection(register8_t directionBits); <br /> void SetPortValues(register8_t valueBits);<br /> void GetPortValues(register8_t &amp;valueBits);<br /> <br /> void SetPinDirection(int pin, PinDirection direction);<br /> void SetPinValue(int pin, bool value);<br /> void GetPinValue(int pin, bool &amp;value);<br /> };<br /> <br /> <br /> <br /> #endif /* IOPORT_H_ */ </pre> <p>You can see the class has separate methods for working with individual pins versus the entire port. In that way, we can do bulk port operations and individual pin operations from the same class. We can get away with that here, unlike in the .NET Micro Framework, because we know that all the AVR pinsNow for the implementation. Create a code file IOPort.cpp</p> <pre class="brush: cpp;"> /*<br /> * IOPort.cpp<br /> *<br /> * Created: 1/15/2012 6:03:06 PM<br /> * Author: Peter.Brown<br /> */<br /> <br /> #include "IOPort.h"<br /> <br /> void IOPort::SetPortDirection(register8_t directionBits)<br /> {<br /> *_ddr = directionBits;<br /> }<br /> void IOPort::SetPortValues(register8_t valueBits)<br /> {<br /> *_pins = valueBits;<br /> }<br /> void IOPort::GetPortValues(register8_t &amp;valueBits)<br /> {<br /> valueBits = *_pins;<br /> }<br /> <br /> void IOPort::SetPinDirection(int pin, PinDirection direction)<br /> {<br /> // assumes pin is correctly in the range of 0..7<br /> if (direction == DirectionOutput)<br /> *_ddr |= (1 &lt;&lt; pin);<br /> else<br /> *_ddr ^= (1 &lt;&lt; pin);<br /> }<br /> <br /> <br /> void IOPort::SetPinValue(int pin, bool value)<br /> {<br /> // assumes pin is correctly in the range of 0..7<br /> <br /> // if the pin was already high and we want it high, do nothing.<br /> // if the pin was already low and we want it low, do nothing.<br /> // if the pin was high, and we're requesting low, toggle it<br /> // if the pin was low, and we're requesting high, toggle it<br /> <br /> <br /> if (*_pins &amp; (1 &lt;&lt; pin))<br /> {<br /> // pin is currently high<br /> <br /> if (!value)<br /> *_pins = (1 &lt;&lt; pin); // toggle pin because we want it low<br /> }<br /> else<br /> {<br /> // pin is currently low<br /> <br /> if (value)<br /> *_pins = (1 &lt;&lt; pin); // toggle pin because we want it high<br /> } <br /> <br /> }<br /> <br /> void IOPort::GetPinValue(int pin, bool &amp;value)<br /> {<br /> value = (bool)(* _pins &amp; (1 &lt;&lt; pin));<br /> } </pre> <p>Note how writing a 1 to the pin doesn't set it high, it toggles it. That means we need to read the current value of the pin, and then decide whether it needs to be toggled or not.</p> <p>This IOPort class doesn't support everything. For example, I haven't included here the code to set the pull-up resistors. I also didn't add anything optional to the constructor to set initial direction or values from that call. However, it works for our purposes in this example.</p> <blockquote> <p><strong>Supporting multiple types of processors</strong></p> <p>In the code I'm using for my own projects, I don't include the processor-specific include file in every class. Instead, I include a common include file which has a preprocessor constant for the processor I'm using and then makes a decision as to which processor-specific include file to pull in. I blatantly stole this idea from the AVR libraries, as it's a good one.</p> </blockquote> <h4>Lighting up some LEDs</h4> <p>Now to light up some LEDs. I very slightly changed the pattern so you can be sure you're seeing the newly flash firmware, and not the original version. Here's the new code for the main function.</p> <pre class="brush: cpp;"> /*<br /> * AvrBlinkenLed.cpp<br /> *<br /> * Created: 1/15/2012 4:21:24 PM<br /> * Author: Peter.Brown<br /> */<br /> #define F_CPU 8000000<br /> <br /> #include "ATmega1284P.h"<br /> #include "IOPort.h"<br /> <br /> int main(void)<br /> {<br /> //DDRA = 0b11111111;<br /> //PINA = 0b10101010;<br /> <br /> IOPort portA(&amp;PORTA, &amp;PINA, &amp;DDRA);<br /> <br /> portA.SetPortDirection(0xFF);<br /> portA.SetPortValues(0b10101111);<br /> <br /> while(1)<br /> {<br /> //TODO:: Please write your application code<br /> <br /> }<br /> } </pre> <p>Program it on the MCU and look at the LEDs. You should now see pins 0-3 lit up, as well as pins 5 and 7. This works because the pins were, by default, all low. <strong>Calling SetPortValues toggles all the values for that port</strong>. If you called it again with the same pattern, they'd all turn off.</p> <blockquote> <p><strong>I prefer the ATxmega approach</strong></p> <p>The ATxmega (the follow-on to the ATmega) has a couple different registers to accomplish the task of setting the pin value. One is OUTSET where any set bits cause the pins to go high. The other is OUTCLR where any set bits cause the pins to go low. In that way, you don't have to do a read-compare-modify cycle. If that chip were available in PDIP so creating DIY kits for other people who don't want to surface mount solder, I'd be in heaven.</p> </blockquote> <p>As to size: if I comment out the Pin-specific functionality, in order to get a fair comparison with our original program, the program compiles to 320 bytes. Compare that to the 178 bytes of the macro-version. It's a bit under twice the size for this tiny program. Whether that's a concern to you is, well, your concern :) If you leave in the pin-specific functionality, you get around 510 bytes. On a processor with 128K, that's not a big deal, but if you're looking at a processor with only 2K total memory, that can certainly be an important distinction. At the different levels of optimization, I get the following program sizes:</p> <table border="1" cellspacing="0" cellpadding="2" width="298"> <tbody> <tr> <td valign="top" width="208">Optimization level</td> <td valign="top" width="88">Program Size in Bytes</td> </tr> <tr> <td valign="top" width="208">None (-O0)</td> <td valign="top" width="88">856</td> </tr> <tr> <td valign="top" width="208">Optimize (-O1) default</td> <td valign="top" width="88">512</td> </tr> <tr> <td valign="top" width="208">Optimize more (-O2)</td> <td valign="top" width="88">496</td> </tr> <tr> <td valign="top" width="208">Optimize most (-O3)</td> <td valign="top" width="88">496</td> </tr> <tr> <td valign="top" width="208">Optimize for size (-Os)</td> <td valign="top" width="88">484</td> </tr> </tbody> </table> <p>The different optimization levels certainly make an impact on size. Beware, though, as sometimes optimization can make the code larger, or slower. It can also make it more difficult to debug or trace. I tend to leave the optimization on the default -O1.</p> <p>In addition, you can definitely trim this down a bit by removing some of the conversions, the enum, and doing a little more optimization. You can even do a little inline assembly, but I'm not a big fan of the AVR G++ approach to that, using strings. I used to write a fair bit of inline assembly in Borland C++ for DOS, and to do that, you simply had an asm block with statements in it like asm { mov AX, AY }.</p> <p>Without actually trying it, I suspect that the code to construct the string would take up more space than the inline assembly would give us back, so I'm going to leave it out of this example.</p> <h3>Abstracting Away LED Behavior</h3> <p>LEDs can be connected a two main ways: in current source or current sink configuration. I would like to create an LED class which properly works regardless of how you hook up the LEDs.&nbsp;</p> <p>Create a header file named Led.h</p> <pre class="brush: cpp;"> /*<br /> * Led.h<br /> *<br /> * Created: 1/15/2012 7:12:19 PM<br /> * Author: Peter.Brown<br /> */<br /> <br /> #ifndef LED_H_<br /> #define LED_H_<br /> <br /> #include "ATmega1284P.h"<br /> #include "IOPort.h"<br /> <br /> enum LedConfiguration<br /> {<br /> LedCurrentSource,<br /> LedCurrentSink <br /> };<br /> <br /> class Led<br /> {<br /> protected:<br /> IOPort* _port;<br /> LedConfiguration _configuration;<br /> uint8_t _pin;<br /> <br /> public:<br /> Led(IOPort* port, uint8_t pin, LedConfiguration configuration) :<br /> _port((IOPort *)port),<br /> _configuration(configuration),<br /> _pin(pin) {};<br /> <br /> <br /> void TurnOn();<br /> void TurnOff();<br /> };<br /> <br /> #endif /* LED_H_ */ </pre> <p>Next, create the implementation file Led.cpp. The code in this file will set the pin values based on whether or not we're in Source (1 to light) or Sink (0 to light) mode.</p> <pre class="brush: cpp;"> /*<br /> * Led.cpp<br /> *<br /> * Created: 1/15/2012 7:18:36 PM<br /> * Author: Peter.Brown<br /> */<br /> <br /> #include "Led.h"<br /> <br /> <br /> void Led::TurnOn()<br /> {<br /> _port-&gt;SetPinValue(_pin, (_configuration == LedCurrentSource));<br /> }<br /> <br /> void Led::TurnOff()<br /> { <br /> _port-&gt;SetPinValue(_pin, !(_configuration == LedCurrentSource));<br /> } </pre> <p>To make that work, we're going to need another type, so let's <strong>add the following to the processor-specific header file ATmega1284P.h</strong>. At the same time, we'll change the definition of register8_t to use this type.</p> <pre class="brush: cpp;"> typedef unsigned char uint8_t;<br /> typedef volatile uint8_t register8_t; </pre> <p>I need uint8_t because I'm keeping the pin number in the class, and don't want to allocate a whole 16 bit int to hold a number between 0 and 7. Memory on these devices is even more scarce than program memory so you want to use small types to keep the stack small and the data (if you allocate any) small.</p> <blockquote> <p><strong>Why no New Operator?</strong></p> <p>You'll notice that I'm not using the new operator anywhere, instead I'm allocating everything as local variables. At some point, I may change that, but at least for now, the price isn't worth it. Adding in the new operator, and all the malloc stuff it requires, adds a huge amount of code to your application. By default, AVR G++ doesn't include it in so you can save that 4-10k.</p> </blockquote> <p>The new main function looks like this:</p> <pre class="brush: cpp;"> /*<br /> * AvrBlinkenLed.cpp<br /> *<br /> * Created: 1/15/2012 4:21:24 PM<br /> * Author: Peter.Brown<br /> */<br /> #define F_CPU 8000000<br /> <br /> #include "ATmega1284P.h"<br /> #include "IOPort.h"<br /> #include "Led.h"<br /> <br /> int main(void)<br /> {<br /> IOPort portA(&amp;PORTA, &amp;PINA, &amp;DDRA);<br /> <br /> portA.SetPortDirection(0xFF);<br /> //portA.SetPortValues(0b10101111);<br /> <br /> Led ledA0(&amp;portA, (uint8_t)0, LedCurrentSource);<br /> Led ledA1(&amp;portA, (uint8_t)1, LedCurrentSource);<br /> Led ledA2(&amp;portA, (uint8_t)2, LedCurrentSource);<br /> Led ledA3(&amp;portA, (uint8_t)3, LedCurrentSource);<br /> Led ledA4(&amp;portA, (uint8_t)4, LedCurrentSource);<br /> Led ledA5(&amp;portA, (uint8_t)5, LedCurrentSource);<br /> Led ledA6(&amp;portA, (uint8_t)6, LedCurrentSource);<br /> Led ledA7(&amp;portA, (uint8_t)7, LedCurrentSource);<br /> <br /> ledA0.TurnOn();<br /> ledA1.TurnOn();<br /> ledA2.TurnOn();<br /> ledA3.TurnOn();<br /> ledA4.TurnOn();<br /> ledA5.TurnOn();<br /> ledA6.TurnOn();<br /> ledA7.TurnOn();<br /> <br /> while(1)<br /> {<br /> //TODO:: Please write your application code<br /> <br /> }<br /> } </pre> <p>Rather than inherit LED from the port, as I did in the pin-based version in some other code I've written, I decided to have the LED simply take in an instance of the port. The LED class assumes you've already configured the LED pin as output, as that is an operation that is often done an entire port at a time. Again, another small concession to efficiency without sacrificing the main benefits of C++.</p> <p>If you want to test that the led is properly toggling the values, uncomment the SetPortValues call there to give the port some initial values. Or, you can just make the LEDs toggle like we will in the next post.</p> <p>At this point, if you run the application, you should see all eight LEDs lit</p> <p><a href="http://10rem.net/media/82634/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_42.png" target="_blank"><img src="http://10rem.net/media/82639/Windows-Live-Writer_C-BlinkenLED-on-the-AVR-and-MikroElektro_B9E5_image_thumb_20.png" width="660" height="263" alt="image" border="0" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px"/></a></p> <p>In the next post, we'll learn what it's going to take to blink these LEDs with a specified time interval.</p> <p><a href="http://feedads.g.doubleclick.net/~a/0eJzNZAu9T8l2z_61oaWPoxzHEo/0/da"><img src="http://feedads.g.doubleclick.net/~a/0eJzNZAu9T8l2z_61oaWPoxzHEo/0/di" border="0" ismap="true"></img></a><br/> <a href="http://feedads.g.doubleclick.net/~a/0eJzNZAu9T8l2z_61oaWPoxzHEo/1/da"><img src="http://feedads.g.doubleclick.net/~a/0eJzNZAu9T8l2z_61oaWPoxzHEo/1/di" border="0" ismap="true"></img></a></p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=UTsWJ5EZz2o:s6fohLwSUss:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=UTsWJ5EZz2o:s6fohLwSUss:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=UTsWJ5EZz2o:s6fohLwSUss:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=UTsWJ5EZz2o:s6fohLwSUss:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=UTsWJ5EZz2o:s6fohLwSUss:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=UTsWJ5EZz2o:s6fohLwSUss:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=UTsWJ5EZz2o:s6fohLwSUss:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=UTsWJ5EZz2o:s6fohLwSUss:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=UTsWJ5EZz2o:s6fohLwSUss:gIN9vFwOqvQ" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/PeteBrown/~4/UTsWJ5EZz2o" height="1" width="1"/> http://feedproxy.google.com/~r/PeteBrown/~3/UTsWJ5EZz2o/gnu-cplusplus-blinkenled-part-1-on-the-avr-atmega1284p-with-mikroelektronika-easyavr6-and-atmel-avr-studio-51 Pete Brown 3538 2012-01-16T00:49:40 Setting up for Developing and Debugging the AVR (ATmega1284P) with AVRStudio 5.1 <p>In the wee hours of the night, I've been continuing to learn how to develop for the various AVR family chips from Atmel. I also do a lot with NETMF, Netduino, and the .NET Gadgeteer, but sometimes (despite the pain!) it feels good to code right on the metal.</p> <p>Introductory/getting started information for the AVR family is not always the easiest to find, so this post covers a few other important details I think you'll find helpful.</p> <h3>Select the MCU</h3> <p>MCUs vary wildly in capabilities. Which MCU you choose for tinkering isn't hugely important, but if you have any sort of project in mind, you'll want to try and narrow it down to a family. The programming model is not identical across different families, and capabilities can vary in significant ways. Here are a few things to consider:</p> <ul> <li>Do I need to limit myself to those offered in a <a href="http://en.wikipedia.org/wiki/PDIP">PDIP package</a> in order to make it easy for DIY use? Most people in the DIY community are not able to solder the zillion pins on the smaller surface mount packages. The more powerful the chip (and I define "powerful" very loosely here) the harder it will be to find a PDIP package. In those cases, you may need to rely on a <a href="http://www.mikroe.com/eng/products/view/83/bigavr-mcu-cards/"> vendor's own carrier boards</a>.</li> <li>How many USARTS (sync/async serial communication) do I need? Serial is important for microcontroller to device communication</li> <li>How many I/O pins to I need?</li> <li>How speed-intensive is my code?</li> <li>How much program memory do I expect to require</li> </ul> <p>For this project, I chose the ATmega1284P. I chose this because</p> <ul> <li>It is offered in a 40 PDIP, so it is DIY friendly</li> <li>It is inexpensive at <a href="http://www.mouser.com/Search/ProductDetail.aspx?R=ATMEGA1284P-PUvirtualkey55650000virtualkey556-ATMEGA1284P-PU"> under $6 per unit</a> in very small quantities.</li> <li>It has the most memory of any AVR PDIP package MCU</li> <li>It has two USARTs for serial communication</li> <li>It supports SPI so I'll be able to use the SPI DACs I'm playing with</li> <li>It supports JTAG programming and debugging</li> </ul> <p>Note that speed wasn't really a concern. You'll be amazed at how much you can accomplish in native code on an MCU running at just a couple MHz. Amazing!</p> <p><a href="http://10rem.net/media/82343/Windows-Live-Writer_b3541542a059_B73E_image_21.png" target="_blank"><img src="http://10rem.net/media/82348/Windows-Live-Writer_b3541542a059_B73E_image_thumb_9.png" width="660" height="261" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>Whatever microcontroller you choose, make sure you know what clock speed it's running at. It's not as simple as buying a 20Mhz MCU and saying it's running at 20Mhz. By default, some of the MCUs run at 1MHz to make sure you can program them with anything. Beyond that, you can change the speed using "fuses" (flags set on the chip outside of your program memory), external clock sources, and code in your application.</p> <p>For example, the development board I use (more on that in a moment) has an 8MHz crystal oscillator on the board. I had incorrectly assumed that the chip was running at 8MHz. However, I stumbled across the following in the datasheet for the chip:</p> <p><a href="http://10rem.net/media/82353/Windows-Live-Writer_b3541542a059_B73E_image_2.png" target="_blank"><img src="http://10rem.net/media/82358/Windows-Live-Writer_b3541542a059_B73E_image_thumb.png" width="660" height="110" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>Aha! So many things rely on you knowing the correct clock speed, that if you get it wrong, you'll find half your code simply fails.</p> <h3>Get the Data Sheets</h3> <p>In the case of Atmel, finding the data sheets is pretty easy. What's confusing is that there will often be more than one version floating around, and they're not always updated correctly. In addition, newer chips like the XMega I played with previously, have a fair number of errors in the data sheet.</p> <p>The way to find the sheet is to go to the Atmel site and browse for your chip. First pick the architecture</p> <p><a href="http://10rem.net/media/82363/Windows-Live-Writer_b3541542a059_B73E_image_4.png" target="_blank"><img src="http://10rem.net/media/82368/Windows-Live-Writer_b3541542a059_B73E_image_thumb_1.png" width="492" height="448" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>Then, and the bottom left, pick the family</p> <p><a href="http://10rem.net/media/82373/Windows-Live-Writer_b3541542a059_B73E_image_6.png" target="_blank"><img src="http://10rem.net/media/82378/Windows-Live-Writer_b3541542a059_B73E_image_thumb_2.png" width="490" height="448" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>In this case, I chose "megaAVR" as that's the family the MPU I chose belongs to. It's next to my awesome MSPaint arrow there on the left.</p> <p>Next, scroll down and pick the model that's written on your chip.</p> <p><a href="http://10rem.net/media/82383/Windows-Live-Writer_b3541542a059_B73E_image_8.png" target="_blank"><img src="http://10rem.net/media/82388/Windows-Live-Writer_b3541542a059_B73E_image_thumb_3.png" width="500" height="289" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>You can, of course, simply type your chip's name into Bing/Google and see what comes up. Just ignore all those third-party datasheet sites. They're the usual link bait crap you find on the internet.</p> <p>You'll eventually make your way to the MCU's product page on the Atmel site.</p> <p><a href="http://10rem.net/media/82393/Windows-Live-Writer_b3541542a059_B73E_image_10.png" target="_blank"><img src="http://10rem.net/media/82398/Windows-Live-Writer_b3541542a059_B73E_image_thumb_4.png" width="500" height="627" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>These product pages are really nice, especially when you're doing the initial research to figure out which MCU to choose.</p> <p>Finally, clock on the "documents" tab at the top. The first two documents for any given MCU will typically be a short summary, useful when investigating capabilities, and then a a full data sheet.</p> <p><a href="http://10rem.net/media/82403/Windows-Live-Writer_b3541542a059_B73E_image_12.png" target="_blank"><img src="http://10rem.net/media/82408/Windows-Live-Writer_b3541542a059_B73E_image_thumb_5.png" width="500" height="434" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>Now, here comes the fun part with Atmel. Make note of the various MCUs listed in the data sheet. That means they all follow the same design, but differ in something relatively trivial like the amount of program or flash memory on board. Now, look up the data sheets for a couple of those and see if they're any later than this one. Atmel doesn't always do a good job of making sure the data sheets make it out to all the right places on their site. It'll only take a moment.</p> <p>With the MCU chosen, the next step is to buy or build something to host it.</p> <h3>Optionally, Pick up a Development Board</h3> <p>When getting started, using a development board is almost always the easiest approach. Atmel makes a number of nice development boards for their MCUs. One great thing about them is that the development environment has templates and examples build around those.</p> <p>You can also find relatively inexpensive development boards on ebay. My experience with those has been pretty spotty: if it works, awesome. If it doesn't work, support is pretty non-existent and the language barrier makes self-help on the sites almost impossible.</p> <p>Despite the lack of direct support for them in AVR Studio, I'm really partial to the Mikroelektronika boards. They are extremely well made, and feature-rich without getting in your way. This <a href="http://www.mikroe.com/eng/products/view/321/easyavr6-development-system/"> EasyAVR6</a> is one that I put on my Christmas list and found under the tree on December 25 :) The board is not tiny, it's about the size of a mini ATX motherboard. Also note that it does not come with the two LCD screens, those must be purchased separately from Mikroelektronika. They're inexpensive enough, though.</p> <p><a href="http://www.mikroe.com/eng/products/view/321/easyavr6-development-system/" target="_blank"><img src="http://10rem.net/media/82413/Windows-Live-Writer_b3541542a059_B73E_image_15.png" width="550" height="410" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>Considerations when picking a board:</p> <ul> <li>Does it support the MCU(s) I plan to use?</li> <li>Is there native support for it in my dev environment? It's not necessary, but it removes some barriers to getting started</li> <li>Does it break out all the pins in a way that is easy to use? In the AVR6, the pins are all broken out in the headers on the right</li> <li>Does it break out key features in ways I plan to use them (RS-232 connector, display, buttons, LEDs)</li> <li>Does it include debug LEDs so I can easily see the status of any pin? (not necessary, but VERY helpful)</li> <li>Is it built well, well-supported, and easy to use?</li> </ul> <p>You can go with less expensive boards, of course. MikroElektronika makes a much smaller <a href="http://www.mikroe.com/eng/products/view/795/ready-for-avr-board/" target="_blank">Ready for AVR</a> board which supports the 40 pin AVR chips like this one. It doesn't have any debug LEDs or buttons, but it has all the required oscillator circuitry and pin headers. It also supports USB deployment, but does not include a JTAG header for debugging. This is not a show-stopper, but I personally consider it critical for non-trivial work.</p> <p>Here's an example of the debug LEDs in use on my board</p> <p><a href="http://10rem.net/media/82418/Windows-Live-Writer_b3541542a059_B73E_image_23.png" target="_blank"><img src="http://10rem.net/media/82423/Windows-Live-Writer_b3541542a059_B73E_image_thumb_10.png" width="660" height="290" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>Each LED on the left corresponds to one pin. They're labeled so I can easily see that Port A, Pin 0 and Pin 4, and Port D pins 2 and 3 are all high. This is incredibly helpful when writing your applications.</p> <p>Whatever development board you choose, you'll ideally want to make sure it breaks out the interface for debugging the MCU, so you can attach a debugger to it.</p> <h3>Get a Debugger and Programmer</h3> <p>Most development boards include nice on-board USB <strong>programming</strong>. One thing none of them provide is any sort of USB <strong>debugging</strong>. For those of us used to single-stepping through code and adding breakpoints, inspecting values, etc., this can be a real step backwards in usability.</p> <p>Without a debugger, all you can do is debug using tricks like blinky lights and (eventually) outputting messages to an LCD (but that comes MUCH later). It's time-consuming and can be frustrating.</p> <p>For AVR programming in AVR Studio 5.1, one of the best consumer debuggers is the JTAGICE Mk3 from Atmel. The problem is, this thing costs $300!</p> <p>There is one good chinese clone of this device. It's a reverse engineering of the protocol, not a blatant copy like some others. I recommend this one above all else. It's called the JTAGICE mkII-CN by Mcuzone. Make sure you get the red-case one <strong>branded by Mcuzone</strong>, and none of the other copies. It runs around $80. <strong>Get it shipped DHL, don't use China Post</strong>.</p> <p><a href="http://10rem.net/media/82428/Windows-Live-Writer_b3541542a059_B73E_image_17.png" target="_blank"><img src="http://10rem.net/media/82433/Windows-Live-Writer_b3541542a059_B73E_image_thumb_7.png" width="399" height="468" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>I did a quick ebay search on JTAGICE and crossed off the ones I do not recommend getting. Notice how one of those is the red box. It doesn't say "mcuZone" on it, so it may very well be a clone. <strong>You want one which says mcuZone and has the serial number tag on the bottom</strong>. That version comes build for use with AVR Studio 4, but includes a firmware update to work with AVR Studio 5.</p> <p>Some of the other units are blatant copies of other people's IP, so I'd rather not support those.</p> <p><a href="http://10rem.net/media/82438/Windows-Live-Writer_b3541542a059_B73E_image_27.png" target="_blank"><img src="http://10rem.net/media/82443/Windows-Live-Writer_b3541542a059_B73E_image_thumb_12.png" width="660" height="396" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>Again, get it shipped DHL even though that costs a bit more. It's much faster and far more reliable.</p> <p>You'll also need to make sure the test board you use has a debug port of some sort. For the larger AVR chips, that will almost always be JTAG, although there are other options.</p> <h3>Set up the IDE</h3> <p>AVR Studio 5.1 is build on Microsoft Visual Studio 2010 Isolated Shell. That means current Visual Studio developers will feel pretty comfortable with the IDE.</p> <p>I previously <a href="http://10rem.net/blog/2011/11/05/getting-started-with-avr-studio-5" target="_blank">covered using AVR Studio 5 in this blog post</a>. In that one, I used the Ready for XMEGA board. That's a great board, but the XMEGA is a surface mount device. If surface mount isn't a concern, I highly recommend it as that chip has a lot of great capabilities and that board is nice and inexpensive…and includes a JTAG deployment/debugging report.</p> <p>Atmel has released a beta of version 5.1. I found the link to that on the <a href="http://www.avrfreaks.net/index.php?name=PNphpBB2&amp;file=viewforum&amp;f=23" target="_blank">avrfreaks AVR Studio 5 forum</a>. Be sure to visit there to get it, as the links change, and there may be a later version out by the time you read this.</p> <p>Version 5.1 supports C++ right in the box, which was key to what I want to do. Note, however, that if you go C++, you're pretty much on your own. All the templates are for C and/or assembly. I was ok with that, though, as I actually found it easier to learn everything by discarding the AVR software framework that the templates use.</p> <p><a href="http://10rem.net/media/82448/Windows-Live-Writer_b3541542a059_B73E_image_31.png" target="_blank"><img src="http://10rem.net/media/82453/Windows-Live-Writer_b3541542a059_B73E_image_thumb_14.png" width="640" height="527" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>Looks familiar, doesn't it? That's a MIDI to CV project I've been working on. The AVR library I'm building is from scratch, primarily because I want to learn the chip without someone else's framework obscuring the details. Oh, and because I want to write C++ :) Still, the optimized byte size of this app so far is about 2k. In this screen shot, I had turned optimization off as I was trying to figure out why JTAG wasn't working. Speaking of that…</p> <h3>Important IDE Settings for JTAG Debugging</h3> <p>The external hardware debuggers are pretty much the only choice when it comes to actually debugging the chip. It's things like this that make you realize just how much the .NET Micro Framework is doing for you behind the scenes.</p> <p>JTAG debugging has some important considerations with regard to the speed it runs at. This one tripped me up for quite a while. Remember earlier I said you need to know what clock speed you're running the MCU at? Here's one place where it makes a huge difference.</p> <p><a href="http://10rem.net/media/82458/Windows-Live-Writer_b3541542a059_B73E_image_29.png" target="_blank"><img src="http://10rem.net/media/82463/Windows-Live-Writer_b3541542a059_B73E_image_thumb_13.png" width="520" height="369" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>Notice the JTAG clock slider, and the note under it. If JTAG debugging isn't working, here's one place to check. By default, the slider was set at 1MHz. By default, the MCU was also running at 1MHz. So, once I slid the slider down to around 200Mhz (which was automatically corrected to the multiplied value you see above), JTAG debugging started working! Yay!</p> <p>One you have that, you can set breakpoints and single-step through your code just like you thought you should. If you bump up the CPU speed on the processor, be sure to come back here and bump this up as well, so you get the most speed out it.</p> <p><a href="http://feedads.g.doubleclick.net/~a/f3o5C2sgTUWm_GxcuiHZ6krlYuM/0/da"><img src="http://feedads.g.doubleclick.net/~a/f3o5C2sgTUWm_GxcuiHZ6krlYuM/0/di" border="0" ismap="true"></img></a><br/> <a href="http://feedads.g.doubleclick.net/~a/f3o5C2sgTUWm_GxcuiHZ6krlYuM/1/da"><img src="http://feedads.g.doubleclick.net/~a/f3o5C2sgTUWm_GxcuiHZ6krlYuM/1/di" border="0" ismap="true"></img></a></p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=HE-yRR4B7Ss:YNychl2Kvjw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=HE-yRR4B7Ss:YNychl2Kvjw:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=HE-yRR4B7Ss:YNychl2Kvjw:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=HE-yRR4B7Ss:YNychl2Kvjw:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=HE-yRR4B7Ss:YNychl2Kvjw:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=HE-yRR4B7Ss:YNychl2Kvjw:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=HE-yRR4B7Ss:YNychl2Kvjw:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=HE-yRR4B7Ss:YNychl2Kvjw:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=HE-yRR4B7Ss:YNychl2Kvjw:gIN9vFwOqvQ" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/PeteBrown/~4/HE-yRR4B7Ss" height="1" width="1"/> http://feedproxy.google.com/~r/PeteBrown/~3/HE-yRR4B7Ss/setting-up-for-developing-and-debugging-the-avr-atmega1284p-with-avrstudio-51 Pete Brown 3536 2012-01-14T00:31:25 Windows Client Developer Roundup 086 for 1/11/2012 <p>The Windows Client Developer Roundup aggregates information of interest to Windows Client Developers, including <a href="http://dev.windows.com/">WinRT XAML</a>, <a href="http://windowsclient.net/">WPF</a>, <a href="http://silverlight.net/">Silverlight</a>, <a href="http://msdn.microsoft.com/en-us/visualc/default.aspx">Visual C++</a>, <a href="http://creators.xna.com/">XNA</a>, <a href="http://expression.microsoft.com/">Expression Blend</a>, <a href="http://www.microsoft.com/surface/">Surface</a>, <a href="http://msdn.microsoft.com/en-us/windows/default.aspx">Windows 7</a>, <a href="http://msdn.microsoft.com/en-us/ff380145.aspx">Windows Phone</a>, Visual Studio, <a href="http://silverlight.net/riaservices/">WCF RIA Services</a> and more. Sometimes I even include a little jQuery and HTML5. If you have something interesting you've done or have run across, or you blog regularly on the topics included here, please send me the URL and brief description via the <a href="http://10rem.net/contact">contact link</a>.</p> <p>Note that I've started breaking the Netduino, Electronics, Robotics, Synthesizer and similar content into a new roundup series called the <a href="http://10rem.net/blog?filterby=MakerRoundup">Maker Geek Roundup</a>.</p> <h3>Shout-Outs</h3> <ul> <li><a href="http://blogs.msdn.com/b/visualstudio/archive/2012/01/04/give-us-your-feedback-on-visual-studio-11-and-receive-a-gift.aspx"> Give us your feedback on Visual Studio 11 etc. and receive a gift!</a> (Visual Studio Blog)</li> </ul> <h3>Windows 8 and WinRT/Metro General</h3> <ul> <li><a href="http://blogs.msdn.com/b/davedev/archive/2012/01/05/windows-8-first-apps-contest.aspx"> Windows 8 - First Apps Contest</a> (Dave Isbitski)</li> <li><a href="http://kellabyte.com/2011/12/19/when-metro-design-falls-off-the-tracks/"> When Metro design falls off the tracks</a> (Kelly Sommers)</li> <li><a href="http://www.sharpgis.net/post/2011/12/11/Make-your-Windows-8-Video-App-use-the-PlayTo-feature.aspx"> SharpGIS | Make your Windows 8 Video App use the PlayTo feature</a> (Morten Nielsen)</li> </ul> <h3>XAML Technologies (Silverlight, WPF, WinRT Metro XAML)</h3> <ul> <li><a href="http://www.andybeaulieu.com/Home/tabid/67/EntryID/223/Default.aspx"> "Physamajig" for Windows 8</a> (Andy Beaulieu)</li> <li><a href="http://www.sharpgis.net/post/2011/12/07/Building-an-Augmented-Reality-XAML-control.aspx"> Building an Augmented Reality XAML control</a> (Morten Nielsen)</li> </ul> <h3>WinJS / JavaScript and HTML Applications for Windows Metro</h3> <ul> <li><a href="http://adamkinney.com/blog/2011/12/07/setting-up-your-first-use-of-the-animation-library-in-winjs/"> Setting up your first use of the Animation library in WinJS</a> (Adam Kinney)</li> <li><a href="http://adamkinney.com/blog/2011/12/05/no-alert-in-winjs-use-console-or-messagedialog-instead/"> No Alert in WinJS! Use console or MessageDialog instead</a> (Adam Kinney)</li> </ul> <h3>Direct X Technologies (DirectX, XNA, WinRT DirectX, General GPU and Game Programming)</h3> <ul> <li><a href="http://geekswithblogs.net/mikebmcl/archive/2011/12/31/getting-started-with-metro-style-directx.aspx"> Getting started with Metro style DirectX</a> (Bob Taco Industries)</li> <li><a href="http://digitalerr0r.wordpress.com/2011/12/12/xna-4-0-shader-programming-1intro-to-hlsl-ambient-light/"> XNA 4.0 Shader Programming #1-Intro to HLSL, Ambient light</a> (digitalerr0r)</li> <li><a href="http://digitalerr0r.wordpress.com/2011/12/13/xna-4-0-shader-programming-2diffuse-light/"> XNA 4.0 Shader Programming #2-Diffuse light</a> (digitalerr0r)</li> <li><a href="http://digitalerr0r.wordpress.com/2011/12/20/xna-4-0-shader-programming-3specular-light/"> XNA 4.0 Shader Programming #3-Specular light</a> (digitalerr0r)</li> </ul> <h3>C++ and Native Development</h3> <ul> <li><a href="http://blogs.msdn.com/b/sdl/archive/2011/12/02/security.aspx"> Compiler Security Enhancements in Visual Studio 11</a> (SDL Team)</li> </ul> <h3>Visual Studio and .NET General</h3> <ul> <li><a href="http://blogs.msdn.com/b/somasegar/archive/2011/12/15/visual-studio-11-platform-tooling-advances.aspx"> Visual Studio 11 Platform Tooling Advances</a> (Soma)</li> <li style="list-style: none"> <ul> <li>Good DirectX content in this one as well</li> </ul> </li> <li><a href="http://blogs.msdn.com/b/delay/archive/2012/01/09/make-things-as-simple-as-possible-but-not-simpler-managedmsiexec-sample-app-shows-how-to-use-the-windows-installer-api-from-managed-code.aspx"> ManagedMsiExec sample app shows how to use the Windows Installer API from managed code</a> (David Anson)</li> </ul> <h3>NUI (Kinect, Surface, More)</h3> <ul> <li><a href="http://kinecthacks.net/microsoft-kinect-coming-to-windows-on-february-1st-up-for-pre-order-now/"> Microsoft Kinect coming to Windows on February 1st, up for pre-order now!</a> (KinectHacks)</li> <li><a href="http://robrelyea.wordpress.com/2012/01/11/kinect-apps-ensuring-kinect-runtime-is-installed/"> Kinect Apps - ensuring Kinect Runtime is installed</a> (Rob Relyea)</li> <li><a href="http://robrelyea.wordpress.com/2011/12/17/depth-api-improvements-in-v1/"> Examples of depth API improvements coming in v1</a> (Rob Relyea)</li> <li><a href="http://channel9.msdn.com/coding4fun/kinect/Kinect--3D--Fusion4D"> Kinect + 3D = Fusion4D</a> (Greg Duncan)</li> <li><a href="http://channel9.msdn.com/coding4fun/blog/Connecting-your-Netduino-to-your-Kinect"> Connecting your Netduino to your Kinect</a> (Greg Duncan)</li> <li><a href="http://digitalerr0r.wordpress.com/2011/12/13/kinect-fundamentals-4-implementing-skeletal-tracking/"> Kinect Fundamentals #4: Implementing Skeletal Tracking | digitalerr0r</a> (digitalerr0r)</li> <li><a href="http://studentguru.gr/b/vangos/archive/2012/01/01/kinect-amp-html5-using-websockets-and-canvas.aspx"> Kinect &amp; HTML5 using WebSockets and Canvas</a> (Vangos Pterneas)</li> </ul> <h3>Off-Topic Fun</h3> <ul> <li><a href="http://poorlydrawnlines.com/comic/when-its-cold/">Poorly Drawn Lines - When It's Cold</a> (for all the ADD types)</li> <li><a href="http://xkcd.com/1002/">xkcd: Game AIs</a> (xkcd)</li> <li><a href="http://www.smbc-comics.com/index.php?db=comics&amp;id=2470&amp;"> Benoit Mandelbrot: Master of seduction</a> (SMBC)</li> <li style="list-style: none"> <ul> <li>and <a href="http://www.smbc-comics.com/index.php?db=comics&amp;id=2471&amp;"> Saturday Morning Breakfast Cereal</a>&nbsp;</li> <li>and <a href="http://www.smbc-comics.com/index.php?db=comics&amp;id=2475&amp;"> Saturday Morning Breakfast Cereal</a>&nbsp;</li> </ul> </li> <li><a href="http://www.smbc-comics.com/index.php?db=comics&amp;id=2478">Grammar!</a> (SMBC)</li> <li><a href="http://moistproduction.blogspot.com/2011/12/lego-skeleton-cross-section-for-purists.html"> Lego Skeleton inside Mini Figure (for the purists)</a> (MoistProduction)</li> </ul> <p><a href="http://feedads.g.doubleclick.net/~a/p_8ykcYhniBNnwhBOEzdPxlcqWQ/0/da"><img src="http://feedads.g.doubleclick.net/~a/p_8ykcYhniBNnwhBOEzdPxlcqWQ/0/di" border="0" ismap="true"></img></a><br/> <a href="http://feedads.g.doubleclick.net/~a/p_8ykcYhniBNnwhBOEzdPxlcqWQ/1/da"><img src="http://feedads.g.doubleclick.net/~a/p_8ykcYhniBNnwhBOEzdPxlcqWQ/1/di" border="0" ismap="true"></img></a></p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=PvD8YY82TMA:ZbVh6LC2cvg:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=PvD8YY82TMA:ZbVh6LC2cvg:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=PvD8YY82TMA:ZbVh6LC2cvg:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=PvD8YY82TMA:ZbVh6LC2cvg:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=PvD8YY82TMA:ZbVh6LC2cvg:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=PvD8YY82TMA:ZbVh6LC2cvg:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=PvD8YY82TMA:ZbVh6LC2cvg:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=PvD8YY82TMA:ZbVh6LC2cvg:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=PvD8YY82TMA:ZbVh6LC2cvg:gIN9vFwOqvQ" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/PeteBrown/~4/PvD8YY82TMA" height="1" width="1"/> http://feedproxy.google.com/~r/PeteBrown/~3/PvD8YY82TMA/windows-client-developer-roundup-086-for-1-11-2012 Pete Brown 3533 2012-01-12T02:02:35 Windows Phone 2011 Retrospective <p><a href="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/5481.WP_2D00_Marketplace_2D00_Opportunity_2D00_infographic_2D00_r09b_2D00_011112_5F00_588D8EFF.jpg"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="WP-Marketplace-Opportunity-infographic-r09b 011112" border="0" alt="WP-Marketplace-Opportunity-infographic-r09b 011112" src="http://windowsteamblog.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-53-84-metablogapi/5383.WP_2D00_Marketplace_2D00_Opportunity_2D00_infographic_2D00_r09b_2D00_011112_5F00_thumb_5F00_57B52915.jpg" width="604" height="1224" /></a></p> <p>We created this infographic to provide a retrospective look back on Windows Phone in 2011, with a specific view to information developers would want to see.</p><div style="clear:both;"></div><img src="http://windowsteamblog.com/aggbug.aspx?PostID=574758" width="1" height="1"> http://windowsteamblog.com/windows_phone/b/wpdev/archive/2012/01/11/windows-phone-2011-retrospective.aspx Windows Phone Dev Blog 3532 2012-01-11T19:30:12 Your Welcome <p> Dear Spammer, </p><p>... more ...</p> http://www.charlespetzold.com/blog/2012/01/Your-Welcome.html Charles Petzold 3531 2012-01-11T15:01:52 Expression Blend 4, MRU location I&#8217;m working on my book for O&#8217;Reilly this month (HLSL and Pixel Shaders for XAML Developers).&#160; If you&#8217;ve written books or articles yourself you know there is a lot of prep involved in getting your machine into a clean state for screenshots.&#160; You don&#8217;t want to show a list of client project names to the [...]<!-- Easy AdSense V2.51 --> <!-- Post[count: 2] --> <div class="ezAdsense adsense adsense-leadout" style="float:left;margin:12px; border:#00FFFF solid 1px" onmouseover="this.style.border='#FF0000 solid 1px'" onmouseout="this.style.border='#00FFFF solid 1px'"><script type="text/javascript"><!-- google_ad_client = "pub-7194001785119580"; /* blog.wpfwonderland 300x250, created 6/16/09 */ google_ad_slot = "2567713628"; google_ad_width = 300; google_ad_height = 250; //--> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script></div> http://blog.wpfwonderland.com/2012/01/10/expression-blend-4-mru-location/ Walt Ritscher 3530 2012-01-11T07:20:34 Threading Considerations for Binding and Change Notification in Silverlight 5 <p>A reader of <a href="http://manning.com/pbrown2" target="_blank">my Silverlight 5 book</a> recently reached out to me about threading and why I create some objects on the UI thread in the examples. We discussed some of the reasons, but I felt this would be a good topic to share with everyone. In fact, this is one area where it would have been fun to go into great detail in my book, but there simply wasn't the space. Threading and cross-thread exceptions can be a bit of a mystery to new Silverlight and WPF developers.</p> <h3>Background</h3> <p>The user interface in Silverlight runs on a thread commonly known as the UI Thread. Any code you create in the code-behind, and any code it calls all the way down the chain, unless it explicitly creates another thread, runs on this same UI thread. It's not at all uncommon to see Silverlight and WPF applications which never explicitly create a second thread, but do make calls to other services which create background threads for processing.</p> <p>There are many other examples, but networking is one place where the Silverlight .NET Framework explicitly creates (or uses) different threads. Not all calls return on the UI thread.</p> <p><strong>Threads other than the UI thread are not allowed to access or manipulate UI objects</strong>. If they attempt to do so, the runtime throws an Invalid Cross-Thread Access exception. It looks like this:</p> <p><a href="http://10rem.net/media/82267/Windows-Live-Writer_Threading-Considerations-for-Binding-in-_EF97_image_2.png" target="_blank"><img src="http://10rem.net/media/82272/Windows-Live-Writer_Threading-Considerations-for-Binding-in-_EF97_image_thumb.png" width="477" height="277" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>But wait! I wasn't accessing any UI objects from my code. What gives?</p> <p>It's not always obvious that you're interacting with UI objects on the UI thread, though. Here's the stack trace from this particular exception:</p> <pre class="brush: csharp; highlight: [2];"> {System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---&gt;<br /> System.UnauthorizedAccessException: Invalid cross-thread access.<br /> at MS.Internal.XcpImports.CheckThread()<br /> at MS.Internal.XcpImports.GetValue(IManagedPeerBase managedPeer, DependencyProperty property)<br /> at System.Windows.DependencyObject.GetOldValue(DependencyProperty property, EffectiveValueEntry&amp; oldEntry)<br /> at System.Windows.DependencyObject.UpdateEffectiveValue(DependencyProperty property, EffectiveValueEntry oldEntry, EffectiveValueEntry&amp; newEntry, ValueOperation operation)<br /> at System.Windows.DependencyObject.RefreshExpression(DependencyProperty dp)<br /> at System.Windows.Data.BindingExpression.SendDataToTarget()<br /> at System.Windows.Data.BindingExpression.SourcePropertyChanged(PropertyPathListener sender, PropertyPathChangedEventArgs args)<br /> at System.Windows.PropertyPathListener.ReconnectPath()<br /> at System.Windows.Data.Debugging.BindingBreakPoint.&lt;&gt;c__DisplayClass4.&lt;BreakOnSharedType&gt;b__3()<br /> --- End of inner exception stack trace ---<br /> at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)<br /> at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)<br /> at System.Delegate.DynamicInvokeImpl(Object[] args)<br /> at System.Delegate.DynamicInvoke(Object[] args)<br /> at MainPagexaml.BindingOperation(Object BindingState, Int32 , Action )} </pre> <p>This stack trace was generated by <strong>trying to raise a PropertyChangedNotification when I manipulated a model object from a background thread</strong>. So, it was obvious that I was working with an object on the background thread, but it wasn't obvious that I'd get a cross-thread exception (well it was in this case, as I contrived the example). If you consider a larger application where you have division of ownership for different pieces, a client-side developer may simply work with your viewmodel, but not realize you're farming some work out to another thread.</p> <p>I wrote a blog post back in 2010 ( <a href="http://10rem.net/blog/2010/04/23/essential-silverlight-and-wpf-skills-the-ui-thread-dispatchers-background-workers-and-async-network-programming"> Essential Silverlight and WPF Skills: The UI Thread, Dispatchers, Background Workers and Async Network Programming</a>) explaining some of the ways to work with threads and dispatching. I didn't have SynchronizationContext in there at the time, but it's something I tend to use a lot these days.</p> <p>Let's take a look at a few of the common scenarios and how it works with threading.</p> <h3>Common Scenarios</h3> <p>All of these scenarios make use of a simple Customer class with a single property:</p> <pre class="brush: csharp;"> namespace SilverlightThreadingExample.Model<br /> {<br /> public class Customer : Observable<br /> {<br /> private string _firstName;<br /> public string FirstName<br /> {<br /> get { return _firstName; }<br /> set { _firstName = value; NotifyPropertyChanged("FirstName"); }<br /> }<br /> }<br /> } </pre> <p>The customer is <em>observable</em> that is, it notifies any listeners when properties change. While not necessary, I encapsulated the observable code in this base class. You could, instead, put the implementation in a partial class if you wanted to make sure your model object's signature from your ORM or whatever remains the same as it was on the server.</p> <pre class="brush: csharp;"> using System.ComponentModel;<br /> <br /> namespace SilverlightThreadingExample<br /> {<br /> public class Observable : INotifyPropertyChanged<br /> {<br /> public event PropertyChangedEventHandler PropertyChanged;<br /> <br /> protected void NotifyPropertyChanged(string propertyName)<br /> {<br /> if (PropertyChanged != null)<br /> PropertyChanged(this, new PropertyChangedEventArgs(propertyName));<br /> }<br /> }<br /> } </pre> <p>This is actually a pretty typical approach to handling INotifyPropertyChanged. There are even more robust versions out there which use lambdas and reflection to help avoid passing in strings, but they ultimately come down to raising the PropertyChanged event. Many of them also fail to work properly in cross-thread situations.</p> <p>I expose the Customer class and a collection of customers from a ViewModel class.</p> <pre class="brush: csharp;"> namespace SilverlightThreadingExample.ViewModel<br /> {<br /> public class CustomerEntryViewModel : Observable<br /> {<br /> private Customer _currentCustomer;<br /> public Customer CurrentCustomer<br /> {<br /> get { return _currentCustomer; }<br /> set { _currentCustomer = value; NotifyPropertyChanged("CurrentCustomer"); }<br /> }<br /> <br /> private ObservableCollection&lt;Customer&gt; _customers = new ObservableCollection&lt;Customer&gt;();<br /> public ObservableCollection&lt;Customer&gt; Customers<br /> {<br /> get { return _customers; }<br /> }<br /> <br /> public void LoadCustomersOnSameThread()<br /> {<br /> LoadDummyData();<br /> }<br /> <br /> private void LoadDummyData()<br /> {<br /> _customers.Add(new Customer() { FirstName = "Pete" });<br /> _customers.Add(new Customer() { FirstName = "Jon" });<br /> _customers.Add(new Customer() { FirstName = "Tim" });<br /> _customers.Add(new Customer() { FirstName = "Scott" });<br /> _customers.Add(new Customer() { FirstName = "Andy" });<br /> _customers.Add(new Customer() { FirstName = "Blaine" });<br /> _customers.Add(new Customer() { FirstName = "Jesse" });<br /> _customers.Add(new Customer() { FirstName = "Rey" });<br /> <br /> _currentCustomer = _customers[0];<br /> }<br /> <br /> }<br /> } </pre> <p>Finally, the UI is bound to those classes. The DataContext for the UI (which will be set in code-behind) is the ViewModel.</p> <pre class="brush: xml;"> &lt;UserControl x:Class="SilverlightThreadingExample.MainPage"<br /> xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"<br /> xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"<br /> xmlns:d="http://schemas.microsoft.com/expression/blend/2008"<br /> xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"<br /> mc:Ignorable="d"<br /> d:DesignHeight="400" d:DesignWidth="600"&gt;<br /> <br /> &lt;Grid x:Name="LayoutRoot" Background="White"&gt;<br /> &lt;Grid Width="500"&gt;<br /> &lt;Grid.ColumnDefinitions&gt;<br /> &lt;ColumnDefinition Width="*" /&gt;<br /> &lt;ColumnDefinition Width="250" /&gt;<br /> &lt;/Grid.ColumnDefinitions&gt;<br /> <br /> &lt;ListBox x:Name="CustomerList"<br /> Grid.Column="0" Margin="10"<br /> ItemsSource="{Binding Customers}"<br /> SelectedItem="{Binding CurrentCustomer, Mode=TwoWay}"&gt;<br /> &lt;ListBox.ItemTemplate&gt;<br /> &lt;DataTemplate&gt;<br /> &lt;TextBlock Text="{Binding FirstName}" /&gt;<br /> &lt;/DataTemplate&gt;<br /> &lt;/ListBox.ItemTemplate&gt;<br /> &lt;/ListBox&gt;<br /> <br /> &lt;StackPanel Grid.Column="1"&gt;<br /> &lt;TextBox x:Name="FirstNameField" Margin="10"<br /> DataContext="{Binding CurrentCustomer}"<br /> Text="{Binding FirstName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /&gt;<br /> <br /> &lt;Button x:Name="AddCustomer"<br /> Content="Add Customer from UI Thread"<br /> Height="30" Margin="5"<br /> Click="AddCustomer_Click" /&gt;<br /> &lt;Button x:Name="AddCustomerSecond"<br /> Content="Add Customer from Second Thread"<br /> Height="30" Margin="5"<br /> Click="AddCustomerSecond_Click" /&gt;<br /> &lt;Button x:Name="ChangeNameFromSecondThread"<br /> Content="Change Name from Second Thread"<br /> Height="30" Margin="5"<br /> Click="ChangeNameFromSecondThread_Click" /&gt;<br /> &lt;/StackPanel&gt;<br /> <br /> &lt;/Grid&gt;<br /> <br /> &lt;/Grid&gt;<br /> &lt;/UserControl&gt; </pre> <p>The code-behind looks like this</p> <pre class="brush: csharp;"> using System.Windows;<br /> using System.Windows.Controls;<br /> using SilverlightThreadingExample.ViewModel;<br /> using System.Threading;<br /> using SilverlightThreadingExample.Model;<br /> <br /> namespace SilverlightThreadingExample<br /> {<br /> public partial class MainPage : UserControl<br /> {<br /> CustomerEntryViewModel _vm;<br /> <br /> public MainPage()<br /> {<br /> InitializeComponent();<br /> <br /> CreateViewModelOnUIThread();<br /> }<br /> <br /> <br /> private void CreateViewModelOnUIThread()<br /> {<br /> _vm = new CustomerEntryViewModel();<br /> <br /> _vm.LoadCustomersOnSameThread();<br /> <br /> DataContext = _vm;<br /> }<br /> <br /> <br /> private void AddCustomer_Click(object sender, RoutedEventArgs e)<br /> {<br /> }<br /> <br /> <br /> private void AddCustomerSecond_Click(object sender, RoutedEventArgs e)<br /> {<br /> }<br /> <br /> <br /> private void ChangeNameFromSecondThread_Click(object sender, RoutedEventArgs e)<br /> {<br /> }<br /> <br /> <br /> }<br /> }<br /> </pre> <p>The methods are named to keep the context clear in this example. I wouldn't expect you to name your VM instantiation/locator method "CreateViewModelOnUIThread", for example.</p> <p>Now let's look at those scenarios.</p> <h4>Changing a property value from a background thread</h4> <p>Often in an application, you have a class which is used in UI binding (an entity/model object) but still need to modify a property from code. Sometimes, you need to do that from a background thread. For example, you make a network call to get an updated price for an item. You will get a cross-thread access error when the class raises change notification events from that property setter. If the class is truly POCO (Plan Old CLR Object) and doesn't do any change notification or other event raising, you'll be fine. If, however, change notification is involved, you'll get the cross-thread exception.</p> <p><img src="http://10rem.net/media/82277/Windows-Live-Writer_Threading-Considerations-for-Binding-in-_EF97_image_13.png" width="640" height="261" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></p> <p>Assuming the same Customer and Observable classes defined above, and the same XAML UI, the following code in the code-behind will throw that exception.</p> <pre class="brush: csharp;"> private void ChangeNameFromSecondThread_Click(object sender, RoutedEventArgs e)<br /> {<br /> Thread t = new Thread((o) =&gt;<br /> {<br /> _vm.CurrentCustomer.FirstName = "UpdatedFromSecondThread";<br /> });<br /> <br /> t.Start();<br /> } </pre> <p>The exception doesn't happen when you set the property value; that's perfectly acceptable. It happens here, at the highlighted line:</p> <pre class="brush: csharp; highlight: [4];"> protected void NotifyPropertyChanged(string propertyName)<br /> {<br /> if (PropertyChanged != null)<br /> PropertyChanged(this, new PropertyChangedEventArgs(propertyName));<br /> } </pre> <p>So, what are the options for working around this? Let's consider two common approaches.</p> <h5>Approach 1</h5> <p>The first approach is to do the whole property change from the UI thread. To do this, simply wrap the property set code with a call to the dispatcher. You can use either the Dispatcher object, or if you keep a copy of the SynchronizationContext around, use that.</p> <p><img src="http://10rem.net/media/82282/Windows-Live-Writer_Threading-Considerations-for-Binding-in-_EF97_image_22.png" width="640" height="261" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></p> <p>Here's some example code which implements this. The code looks a bit silly because I'm forcing a background thread. However, pretend that the background thread is a given and you need to work from it (again, the callback from a network call or something.)</p> <pre class="brush: csharp;"> private void ChangeNameFromSecondThread_Click(object sender, RoutedEventArgs e)<br /> {<br /> Thread t = new Thread((o) =&gt;<br /> {<br /> Deployment.Current.Dispatcher.BeginInvoke(() =&gt;<br /> {<br /> _vm.CurrentCustomer.FirstName = "UpdatedFromSecondThread";<br /> });<br /> });<br /> <br /> t.Start();<br /> } </pre> <p>This approach works well, but requires the calling code to handle all the dispatching. If you have a number of properties to change in different bits of code, it gets a bit cumbersome. Let's look at another approach.</p> <h5>Approach 2</h5> <p>The real problem is the property change notification, so the the second approach is to dispatch just the change notification to the UI thread.</p> <p><a href="http://10rem.net/media/82287/Windows-Live-Writer_Threading-Considerations-for-Binding-in-_EF97_image_24.png" target="_blank"><img src="http://10rem.net/media/82292/Windows-Live-Writer_Threading-Considerations-for-Binding-in-_EF97_image_thumb_8.png" width="640" height="261" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>You can put this code into the Observable base class in order to avoid repeating it throughout all your classes.</p> <pre class="brush: csharp;"> // Code-behind<br /> // ----------------------------------------------<br /> <br /> <br /> // this version throws an exception if the Observable base class isn't doing thread checking<br /> private void ChangeNameFromSecondThread_Click(object sender, RoutedEventArgs e)<br /> {<br /> Thread t = new Thread((o) =&gt;<br /> {<br /> _vm.CurrentCustomer.FirstName = "UpdatedFromSecondThread";<br /> });<br /> <br /> t.Start();<br /> }<br /> <br /> <br /> // Observable<br /> // ----------------------------------------------<br /> <br /> <br /> using System.ComponentModel;<br /> using System.Windows;<br /> <br /> namespace SilverlightThreadingExample<br /> {<br /> public class Observable : INotifyPropertyChanged<br /> {<br /> public event PropertyChangedEventHandler PropertyChanged;<br /> <br /> protected void NotifyPropertyChanged(string propertyName)<br /> {<br /> if (PropertyChanged != null)<br /> {<br /> if (Deployment.Current.Dispatcher.CheckAccess())<br /> {<br /> PropertyChanged(this, new PropertyChangedEventArgs(propertyName));<br /> }<br /> else<br /> {<br /> Deployment.Current.Dispatcher.BeginInvoke(() =&gt;<br /> {<br /> PropertyChanged(this, new PropertyChangedEventArgs(propertyName));<br /> });<br /> }<br /> }<br /> }<br /> }<br /> } </pre> <p>Note how I first check to see if we have access to the UI thread using the CheckAccess call. If we do, there's no reason to incur the overhead and delay of a dispatcher call. However, if we are running on the background thread, then the call is dispatched to the UI thread. In either case, we avoid the errors cause by cross-thread property change notification.</p> <p>Next up: Collections</p> <h4>Populating an ObservableCollection from a networking return call</h4> <p>A more robust Observable base class like this won't help with collection change notification (WPF 4.5 has a great solution for that using BindingOperations.EnableCollectionSynchronization, but unfortunately Silverlight does not).</p> <p>Most applications make networking calls to get information from some resource on an intranet or out on the web. In Silverlight (and WPF), it's common practice to populate an ObservableCollection with the results from those calls. The ObservableCollection class is nice because it implements INotifyCollectionChanged and raises an event whenever items are added to or deleted from the collection, or when the collection is cleared. It's this notification that enables the various items controls and grids in the UI to stay in sync with the items in the collection.</p> <p><img src="http://10rem.net/media/82297/Windows-Live-Writer_Threading-Considerations-for-Binding-in-_EF97_image_16.png" width="640" height="261" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></p> <p>This version is very similar to what we saw with individual properties earlier. That's because, it's really the same problem: we're trying to notify the binding system across threads.</p> <pre class="brush: csharp;"> private void AddCustomerSecond_Click(object sender, RoutedEventArgs e)<br /> {<br /> Thread t = new Thread((o) =&gt;<br /> {<br /> var cust = new Customer() { FirstName = "AddedFromSecondThread" };<br /> _vm.Customers.Add(cust);<br /> });<br /> <br /> t.Start();<br /> } </pre> <p>Note that the problem exists regardless of where you actually create the customer. For example, this code will also fail:</p> <pre class="brush: csharp;"> private void AddCustomerSecond_Click(object sender, RoutedEventArgs e)<br /> {<br /> var cust = new Customer() { FirstName = "AddedFromSecondThread" };<br /> <br /> Thread t = new Thread((o) =&gt;<br /> {<br /> _vm.Customers.Add(cust);<br /> });<br /> <br /> t.Start();<br /> } </pre> <p>The reason is, again, it's not the object access that is causing the cross-thread exception, it's the collection changed notification that's full of hate here.</p> <p>So, how do you get around this? Unless you want to create your own ObservableCollection type class for Silverlight, you'll need to dispatch all collection add calls. Luckily, you'll typically have fewer of these scattered throughout the application, so it's not quite so onerous.</p> <p><img src="http://10rem.net/media/82302/Windows-Live-Writer_Threading-Considerations-for-Binding-in-_EF97_image_27.png" width="640" height="261" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></p> <p>The code to implement this is just another easy call to the dispatcher (or SynchronizationContext, if you prefer).</p> <pre class="brush: csharp;"> private void AddCustomerSecond_Click(object sender, RoutedEventArgs e)<br /> {<br /> // you can create customer on any thread<br /> var cust = new Customer() { FirstName = "AddedFromSecondThread" };<br /> <br /> Thread t = new Thread((o) =&gt;<br /> {<br /> <br /> // dispatch to UI thread to add it to the collection. You can't<br /> // access the observable collection x-thread<br /> Deployment.Current.Dispatcher.BeginInvoke(() =&gt;<br /> {<br /> _vm.Customers.Add(cust);<br /> });<br /> });<br /> <br /> t.Start();<br /> } </pre> <p>If you're going to run from an unknown state, be sure to call CheckAccess to see if you really need to do the dispatching. In this case, I know I'm always going to be on a background thread, so I don't bother.</p> <h3>Summary</h3> <p>The intent here was to show a few of the common threading pitfalls in Silverlight (and WPF) applications, specifically in the context of change notification. In most code, it's easy to tell when you're accessing objects cross-thread, but change notification is a somewhat behind the scenes operation, so it's not always obvious.</p> <p>For property change notification, the solutions were:</p> <ul> <li>Dispatch the entire property change operation to the UI thread</li> <li>Update the NotifyPropertyChanged code to check to see which thread it's running on, and then dispatch the event as appropriate</li> </ul> <p>Either way works, but I prefer the update to the NotifyPropertyChanged method.</p> <p>For collection change notifications in Silverlight, the solutions are:</p> <ul> <li>Create (or find) an implementation of ObservableCollection which does the cross-thread checking. The reason this isn't built-in is change notification happens often, and dispatching each and every change notification can be a real performance drain. That's also why WPF has a separate and optimized solution. You'd need to enable batching to avoid the overhead of hundreds of dispatch calls.</li> <li>Dispatch the entire collection update when you're running on a background thread.</li> </ul> <p>In contrast to the property change notifications, for collection change, I prefer to dispatch the entire call. If you're adding 1 object or 100, you'll still get only one dispatch call, so performance is better.</p> <p>The Task Parallel Library in WPF, and the subset of it in Silverlight also offer some alternative approaches to handling cross-thread work. Similarly, the async and await keywords in .NET 4.5 and Windows 8 XAML can also come into play. More on those in the future.</p> <p><a href="http://feedads.g.doubleclick.net/~a/uwQIQJePQRlDzsX961fUfvyocuc/0/da"><img src="http://feedads.g.doubleclick.net/~a/uwQIQJePQRlDzsX961fUfvyocuc/0/di" border="0" ismap="true"></img></a><br/> <a href="http://feedads.g.doubleclick.net/~a/uwQIQJePQRlDzsX961fUfvyocuc/1/da"><img src="http://feedads.g.doubleclick.net/~a/uwQIQJePQRlDzsX961fUfvyocuc/1/di" border="0" ismap="true"></img></a></p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=mPgdkOol8xE:Rd1oCIMrnYU:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=mPgdkOol8xE:Rd1oCIMrnYU:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=mPgdkOol8xE:Rd1oCIMrnYU:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=mPgdkOol8xE:Rd1oCIMrnYU:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=mPgdkOol8xE:Rd1oCIMrnYU:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=mPgdkOol8xE:Rd1oCIMrnYU:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=mPgdkOol8xE:Rd1oCIMrnYU:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=mPgdkOol8xE:Rd1oCIMrnYU:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=mPgdkOol8xE:Rd1oCIMrnYU:gIN9vFwOqvQ" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/PeteBrown/~4/mPgdkOol8xE" height="1" width="1"/> http://feedproxy.google.com/~r/PeteBrown/~3/mPgdkOol8xE/threading-considerations-for-binding-and-change-notification-in-silverlight-5 Pete Brown 3527 2012-01-10T17:48:00 Tracking Expression Blend 4 version numbers It&#8217;s a bit hard to know the version numbers for Expression Blend releases as the information is scattered about the Internet. Version Name Number Release Date Expression Blend 4, original release 4.0 June 7, 2010 Expression Blend 4 Service Pack 1 (SP1) 4.0.20901.0 Sept 7, 2010 Windows Phone SDK 7.1 version 4.0.30816.0 Sept 28,2011 Microsoft [...] http://blog.wpfwonderland.com/2012/01/09/tracking-expression-blend-4-version-numbers/ Walt Ritscher 3525 2012-01-10T01:13:22 Silverlight Reporting Open Source Printing/Reports Example Updated for Silverlight 5 <p>I recently posted an updated version of Silverlight reporting on <a href="http://silverlightreporting.codeplex.com/" target="_blank">codeplex</a>. Here's the overview.</p> <p><a href="http://silverlightreporting.codeplex.com/" target="_blank"><img src="http://10rem.net/media/82245/Windows-Live-Writer_Silverlight-Reporting-Open-Source-Printi_EA02_image_5.png" width="490" height="100" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>This project, a unofficial project by Pete Brown of Microsoft, provides a a very basic framework for building simple, short, multi-page reports using Silverlight 5.</p> <p>The intent is not to be an all-encompassing reporting solution, or a solution for large reports. Instead, this is a set of code you can build upon to create short (2-5 page) reports from your Silverlight applications.</p> <p>Currently the sample consists of the full source code of a simple report writer. It includes:</p> <ul> <li>automatic pagination</li> <li>support for line items of varying height</li> <li>total page count</li> <li>templating</li> <li>page headers and footers</li> <li>report footer with support for calculated fields</li> <li>events to allow hooking into printing at various stages</li> </ul> <h3>Latest Release</h3> <p>Version information changed to use semantic versioning. This vesion is numbered: <a href="http://silverlightreporting.codeplex.com/releases/view/80092" target="_blank">1.0.0-alpha.3</a></p> <ul> <li>Now targets Silverlight 5</li> <li>Added ability to specify postscript (vector) printing. The selected driver must support PostScript or this setting will have no effect.</li> <li>Fixed issue with not being able to re-print the report. (and fixed leaky event handlers)</li> <li>Added null check on templates</li> </ul> <p><a href="http://silverlightreporting.codeplex.com/" target="_blank"><img src="http://10rem.net/media/82250/Windows-Live-Writer_Silverlight-Reporting-Open-Source-Printi_EA02_image_6.png" width="366" height="468" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>This is still alpha, and is a minor project. Expect bugs. Report them when you do. Offer fixes if you can :)</p> <p><a href="http://silverlightreporting.codeplex.com/releases/view/80092" target="_blank">Get the latest release here</a>.</p> <p><a href="http://feedads.g.doubleclick.net/~a/sqK4kgMZ8xBG6YpQ-5KAvyU1Ya8/0/da"><img src="http://feedads.g.doubleclick.net/~a/sqK4kgMZ8xBG6YpQ-5KAvyU1Ya8/0/di" border="0" ismap="true"></img></a><br/> <a href="http://feedads.g.doubleclick.net/~a/sqK4kgMZ8xBG6YpQ-5KAvyU1Ya8/1/da"><img src="http://feedads.g.doubleclick.net/~a/sqK4kgMZ8xBG6YpQ-5KAvyU1Ya8/1/di" border="0" ismap="true"></img></a></p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=9lvuBR5MsTc:VL2o9HdVqXw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=9lvuBR5MsTc:VL2o9HdVqXw:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=9lvuBR5MsTc:VL2o9HdVqXw:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=9lvuBR5MsTc:VL2o9HdVqXw:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=9lvuBR5MsTc:VL2o9HdVqXw:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=9lvuBR5MsTc:VL2o9HdVqXw:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=9lvuBR5MsTc:VL2o9HdVqXw:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=9lvuBR5MsTc:VL2o9HdVqXw:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=9lvuBR5MsTc:VL2o9HdVqXw:gIN9vFwOqvQ" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/PeteBrown/~4/9lvuBR5MsTc" height="1" width="1"/> http://feedproxy.google.com/~r/PeteBrown/~3/9lvuBR5MsTc/silverlight-reporting-open-source-printing-reports-example-updated-for-silverlight-5 Pete Brown 3523 2012-01-09T21:44:30 MFOS Synth 7: Front Panel Update (Knobs and started wiring) <p>Today, I started wiring the front panel.</p> <blockquote> <p>Over the next several months I'll be building what is definitely my most complex electronics project to date: the MFOS (Music From Outer Space) <a href="http://www.musicfromouterspace.com/index.php?MAINTAB=SYNTHDIY&amp;PROJARG=SOUNDLAB_ULTIMATE/page1.html&amp;VPW=1326&amp;VPH=1153"> Sound Lab Ultimate</a>, <a href="http://www.musicfromouterspace.com/index.php?MAINTAB=SYNTHDIY&amp;PROJARG=ULTIMATE_EXPANDER/ultexpanderpg1.html&amp;VPW=1326&amp;VPH=1153"> Ultimate Expander</a> and (if Santa brings one) <a href="http://www.musicfromouterspace.com/index.php?MAINTAB=SYNTHDIY&amp;PROJARG=SOUNDLABMINIMARKII/page1.php&amp;VPW=1326&amp;VPH=1153"> Sound Lab Mini-Synth Mark II</a>, likely all in the same home-made wooden case, side by side. The Ultimate and Expander are together a 3 oscillator monophonic true analog synthesizer with filters, envelopment generator, ring modulator, sample and hold and more. You patch between the different logical modules using banana cables, so it's a bit of a self-contained modular synthesizer. The Mark II is smaller, newer, and has a few fewer features, but a sound of its own. You also patch that with banana cables, and can integrate the two. This blog post is another in the series. Previous posts include:</p> <ul> <li><a href="http://10rem.net/blog/2011/12/02/mfos-synth-1-built-the-power-supply">MFOS Synth 1: Built the Power Supply</a></li> <li><a href="http://10rem.net/blog/2011/12/02/mfos-synth-2-some-main-synthesizer-board-work"> MFOS Synth 2: Some main synthesizer board work</a></li> <li><a href="http://10rem.net/blog/2011/12/04/mfos-synth-3-starting-the-front-panel">MFOS Synth 3: Starting the Front Panel</a></li> <li><a href="http://10rem.net/blog/2011/12/16/mfos-synth-4-resistors-all-soldered">MFOS Synth 4: Resistors all soldered</a></li> <li><a href="http://10rem.net/blog/2011/12/18/mfos-synth-5-trimmers-and-some-capacitors-in-place"> MFOS Synth 5: Trimmers and some capacitors in place</a></li> <li><a href="http://10rem.net/blog/2012/01/04/mfos-synth-6-pcb-complete">MFOS Synth 6: PCB Complete</a></li> </ul> </blockquote> <p>I received a shipment from Small Bear Electronics. They had the <a href="http://www.smallbearelec.com/Detail.bok?no=9">24mm Alpha 1M and 100K audio taper pots</a> back in stock, so I ordered a few. I liked the smaller pots, but not how they wiggled in the holes no matter how much I tightened the nuts. I didn't feel like making spacers for them.</p> <p>I also decided which control knobs I wanted to use. I was really torn as I liked the <a href="http://www.smallbearelec.com/Detail.bok?no=727">violet knobs</a> both in size and style, but I really disliked how they showed the pot washer and nut. It just looked too DIY with those showing for each pot. Instead, I went with the other one I liked: the same style that's on my Moog slim phatty.</p> <p><a href="http://10rem.net/media/81801/Windows-Live-Writer_aaeffbe643b4_1967_image_2.png" target="_blank"><img src="http://10rem.net/media/81806/Windows-Live-Writer_aaeffbe643b4_1967_image_thumb.png" width="520" height="344" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>At Small Bear, these are <a href="http://www.smallbearelec.com/Detail.bok?no=1112">Synth Pointer #4</a>. I cleaned them out, and actually have a few on backorder.</p> <p>With all the potentiometers in place, I decided to start some of the front panel wiring. Ray has a good diagram on his site showing the wiring. I printed that out, and as he recommended in the build notes, I took a marker and colored each wire as I completed it.</p> <p><a href="http://10rem.net/media/81811/Windows-Live-Writer_aaeffbe643b4_1967_image_4.png" target="_blank"><img src="http://10rem.net/media/81816/Windows-Live-Writer_aaeffbe643b4_1967_image_thumb_1.png" width="520" height="396" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>From the diagram, you can see, I've completed almost 1/2 the rear panel wiring. Here's the panel.</p> <p><a href="http://10rem.net/media/81821/Windows-Live-Writer_aaeffbe643b4_1967_image_6.png" target="_blank"><img src="http://10rem.net/media/81826/Windows-Live-Writer_aaeffbe643b4_1967_image_thumb_2.png" width="520" height="396" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>You can also see that I have a number of SPDT and DPDT where the plans call for SPST and DPST switches. I simply couldn't find a decent price on the latter, and just substituted the double throw switches. I'll wire them as though they were ST.</p> <p>I decided to have all the intra-panel wiring gray. I'll use other color wires for connecting to the board, but the wires on the panel are easy to trace by eye (I know, famous last words).</p> <p>Before I can do too much more with the front panel, I need to do the following:</p> <ul> <li>Fabricate and install a few brackets to hold the grounded aluminum shield in place. Ray did this with the <a href="http://www.musicfromouterspace.com/index.php?MAINTAB=SYNTHDIY&amp;PROJARG=SOUNDLABMINIMARKII/page6.php&amp;VPW=1521&amp;VPH=1094"> Mark II build</a>, and I really like the idea.</li> <li>Create a few LED holders (also like Ray did on the Mark II)</li> </ul> <p>The Mark II is Ray's latest creation. Being able to incorporate some of the ideas from that into the Sound Lab Ultimate is fortunate. I'll do the same with the expander and the Mark II, both of which are waiting on my desk to be part of this one large synthesizer.</p> <p>Oh, and tried out some new solder today: the recommended one from Kester. It smokes a lot more, but seems to let out less flux. Folks seem to swear by it, but I don't see a lot of difference right now. We'll see once I use it for component soldering.</p> <p><a href="http://feedads.g.doubleclick.net/~a/18InE_7OpsSoqNZ5uZNdJyJ-Lu4/0/da"><img src="http://feedads.g.doubleclick.net/~a/18InE_7OpsSoqNZ5uZNdJyJ-Lu4/0/di" border="0" ismap="true"></img></a><br/> <a href="http://feedads.g.doubleclick.net/~a/18InE_7OpsSoqNZ5uZNdJyJ-Lu4/1/da"><img src="http://feedads.g.doubleclick.net/~a/18InE_7OpsSoqNZ5uZNdJyJ-Lu4/1/di" border="0" ismap="true"></img></a></p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=65hSh0IzLII:VYpYEzZ8Ue4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=65hSh0IzLII:VYpYEzZ8Ue4:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=65hSh0IzLII:VYpYEzZ8Ue4:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=65hSh0IzLII:VYpYEzZ8Ue4:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=65hSh0IzLII:VYpYEzZ8Ue4:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=65hSh0IzLII:VYpYEzZ8Ue4:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=65hSh0IzLII:VYpYEzZ8Ue4:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=65hSh0IzLII:VYpYEzZ8Ue4:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=65hSh0IzLII:VYpYEzZ8Ue4:gIN9vFwOqvQ" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/PeteBrown/~4/65hSh0IzLII" height="1" width="1"/> http://feedproxy.google.com/~r/PeteBrown/~3/65hSh0IzLII/mfos-synth-7-front-panel-update-knobs-and-started-wiring Pete Brown 3520 2012-01-08T07:19:46 Maker Geek Roundup 005 for 1/7/2012 <p>The Maker Geek Roundup aggregates information of interest to makers everywhere. Topics include .NET Micro Framework, CNC, 3d Printing, Robotics, Microsoft Robotics Studio, Electronics, General Maker stuff, and more. If you have something interesting you've done or have run across, or you blog regularly on the topics included here, please send me the URL and brief description via the <a href="http://10rem.net/contact">contact link</a>.</p> <h3>Shout Outs</h3> <ul> <li><a href="http://www.makerbot.com/blog/2012/01/06/want-to-know-what-were-announcing-at-ces/"> MakerBot launches a text adventure to give a hint of what we're going to announce at CES!</a> (Makerbot Industries)</li> </ul> <h3>3d Printing and CAD/CAM/CNC</h3> <ul> <li><a href="http://cncsnap.com/wiki/motors/dc-motor-wiring">Wiring Diagram for DC Motor + Domo*pes or Arduino + Circuit + Code</a> (CNC Snap)</li> <li><a href="http://hydraraptor.blogspot.com/2011/12/mendel90.html">Mendel90</a> (HydraRaptor)</li> <li style="list-style: none"> <ul> <li>also <a href="http://hydraraptor.blogspot.com/2011/12/mendel90-extruder.html"> Mendel90 extruder</a> and <a href="http://hydraraptor.blogspot.com/2011/12/mendel90-axes.html">Mendel90 axes</a></li> </ul> </li> <li><a href="http://www.grassrootsengineering.com/blog/2011/12/23/3d-printed-snowman-army/"> 3d Printed Snowman Army</a> (Grass Roots Engineering)</li> <li><a href="http://vonkonow.com/wordpress/2011/12/lego-compatible-android-minifigure/"> Lego compatible Android minifigure</a> (Johan von Konow)</li> <li><a href="http://www.3dfuture.com.au/2012/01/3d-printing-bridges-across-gaps/"> 3D Printing Bridges across Gaps</a> (3d Printing is the Future)</li> </ul> <h3>.NET Gadgeteer</h3> <ul> <li><a href="http://devhammer.net/blog/ghi-non-beta-.net-gadgeteer-sdk-released"> GHI (non-beta) .NET Gadgeteer SDK released! - Devhammer's Den</a> (G. Andrew Duthie)</li> <li><a href="http://blogs.msdn.com/b/net_gadgeteer/archive/2011/12/19/why-not-while-true.aspx"> Why not while(true)? - .NET Gadgeteer</a> (Kerry Hammil)</li> <li><a href="http://blogs.msdn.com/b/net_gadgeteer/archive/2011/12/20/looking-for-api-reference-docs-for-the-core-gadgeteer-libraries.aspx"> Looking for API reference docs for the core Gadgeteer libraries?</a> (Kerry Hammil)</li> <li><a href="http://blogs.msdn.com/b/net_gadgeteer/archive/2011/12/18/how-to-build-a-flipbook-maker-part-1.aspx"> How to Build a Flipbook Maker: Part 1</a> (Kerry Hammil)</li> <li style="list-style: none"> <ul> <li><a href="http://blogs.msdn.com/b/net_gadgeteer/archive/2011/12/21/how-to-build-a-flipbook-maker-part-2.aspx" target="_blank">Part 2</a>, and <a href="http://blogs.msdn.com/b/net_gadgeteer/archive/2012/01/03/how-to-build-a-flipbook-maker-part-3.aspx" target="_blank">Part 3</a></li> </ul> </li> <li><a href="http://blogs.msdn.com/b/net_gadgeteer/archive/2011/12/08/thursday-featured-module-buttons.aspx"> Thursday Featured Module: Buttons - .NET Gadgeteer</a> (Kerry Hammil)</li> <li><a href="http://devhammer.net/blog/great-sites-and-blogs-for-learning-about-.net-gadgeteer"> Great Sites and Blogs for Learning about .NET Gadgeteer - Devhammer's Den</a> (G. Andrew Duthie)</li> <li><a href="http://mikedodaro.net/2012/01/02/seeed-temperature-humidity-sensor-with-oled-display/"> Seeed Temperature Humidity Sensor with OLED Display</a> (Integral Design)</li> <li><a href="http://mikedodaro.net/2011/12/22/using-a-servo-with-a-net-gadgeteer-camera-device/"> Using a Servo in a .NET Gadgeteer Camera Device « Integral Design</a> (Integral Design)</li> <li style="list-style: none"> <ul> <li>also <a href="http://mikedodaro.net/2012/01/06/controlling-the-servo-using-a-windows-phone-application/"> Controlling the Servo using a Windows Phone application</a></li> </ul> </li> <li><!--EndFragment--> <a href="http://blog.ianlee.info/2012/01/making-gadgeteer-daisylink-extender.html"> Software &amp; Sawdust: Making a Gadgeteer DaisyLink Extender Module</a> (Software &amp; Sawdust)</li> </ul> <h3>.NET Micro Framework General (Netduino, GHI FEZ, etc.)</h3> <ul> <li><a href="http://highfieldtales.wordpress.com/2011/12/04/very-fast-spi-to-parallel-interface-for-netduino/"> Very fast SPI-to-parallel interface for Netduino</a> (Highfield Tales)</li> <li><a href="http://blogs.msdn.com/b/laurelle/archive/2011/12/12/asp-net-and-net-microframework-http-web-server-together-part-1-2.aspx"> ASP.NET and .NET Microframework HTTP web server together (part 1/2)</a> (Laurent Ellerbach)</li> <li style="list-style: none"> <ul> <li><a href="http://blogs.msdn.com/b/laurelle/archive/2011/12/19/asp-net-and-net-microframework-http-web-server-together-part-2-2.aspx"> Part 2</a></li> </ul> </li> <li><a href="http://blogs.msdn.com/b/laurelle/archive/2011/12/07/creating-dynamically-a-web-page-using-net-micro-framework.aspx"> Creating dynamically a web page using .NET Micro framework</a> (Laurent Ellerbach)</li> <li><a href="http://mcinnes01.blogspot.com/2011/12/netduino-long-awaited-update.html"> Netduino - Long awaited update</a> (My projects)</li> </ul> <h3>Other Micro Controllers (PIC, AVR, ARM and more)</h3> <ul> <li><a href="http://www.mikroe.com/eng/news/view/410/new-easymx-pro-v7-board-coming-january-2012/"> News - New EasyMx PRO v7 board coming January 2012</a> (MikroElektronika)</li> <li><a href="http://jumptuck.com/2011/12/12/avr-analog-comparator/">AVR Analog Comparator</a> (Jumptuck)</li> </ul> <h3>General Electronics</h3> <ul> <li><a href="http://hackaday.com/2012/01/07/remove-function-lock-key-with-a-4016-and-a-555/"> Remove Function Lock Key with a 4016 and a 555</a> (Hack a Day)</li> <li><a href="http://circuit-zone.com/index.php?electronic_project=656">TV Transmitter Circuit</a> (Circuit-Zone)</li> <li><a href="http://circuit-zone.com/index.php?electronic_project=655">Capacitance Meter</a> (Circuit-Zone)</li> <li><a href="http://circuit-zone.com/index.php?electronic_project=654">Function Generator XR2206</a> (Circuit-Zone)</li> <li><a href="http://dangerousprototypes.com/2012/01/06/high-resolution-capacitor-meter/"> High resolution capacitor meter</a> (Dangerous Prototypes)</li> <li><a href="http://hackaday.com/2012/01/07/using-555-timers-to-add-free-play-functionality-to-classic-arcade-machines/"> Using 555 timers to add "free play" functionality to classic arcade machines</a> (Hack a Day)</li> </ul> <h3>Robotics and Robotics Studio</h3> <ul> <li><a href="http://blogs.msdn.com/b/msroboticsstudio/archive/2011/12/01/household-robot.aspx"> What is a Household Robot?</a> (Greg Shirakyan)</li> <li><a href="http://blogs.msdn.com/b/msroboticsstudio/archive/2011/12/07/announcing-robotics-developer-studio-4-beta-2.aspx"> Announcing Robotics Developer Studio 4 Beta 2</a> (Trevor Taylor)</li> <li><a href="http://blogs.msdn.com/b/msroboticsstudio/archive/2011/12/08/behind-the-scenes-motion-tracking-robot-controller-at-maker-fair-2011.aspx"> Behind the Scenes: Motion Tracking Robot Controller at Maker Faire 2011</a> (Gershon Parent)</li> <li><a href="http://hackaday.com/2012/01/06/treaded-robot-modified-for-stair-climbing/"> Treaded robot modified for stair climbing</a> (Hack a Day)</li> </ul> <h3>Clocks</h3> <ul> <li><a href="http://www.electronics-lab.com/blog/?p=16099">Soviet Nixie Clock IN-18 (HD)</a> (Electronics-Lab.com)</li> <li><a href="http://jumptuck.com/2012/01/01/binary-burst-clock-concept/">Binary Burst clock concept</a> (Jumptuck)</li> </ul> <h3>Synthesizers, MIDI and Electronic Instruments</h3> <ul> <li><a href="http://meeblip.noisepages.com/2011/12/13/meet-the-meeblip-micro-small-hackable-project-synth/"> Meet the MeeBlip micro: Small, Hackable Project Synth, Shipping Now, $39.95</a> (Meeblip)</li> <li><a href="http://meeblip.noisepages.com/2011/12/09/how-we-changed-the-meeblip-to-make-it-more-playable-new-firmware-overlay-tour/"> How We Changed the MeeBlip To Make it More Playable: New Firmware-Overlay Tour</a> (Meeblip)</li> <li><a href="https://amazingdiy.wordpress.com/2011/12/28/casio-dg-20-fretboard/"> Casio DG-20, fretboard</a> (My DIY Blog)</li> </ul> <h3>General Maker</h3> <ul> <li><a href="http://volpinprops.blogspot.com/2012/01/half-life-2-gravity-gun.html"> Half Life 2: Gravity Gun</a> (Volpin Props)</li> <li><a href="http://hackaday.com/2012/01/06/737-cockpit-will-satisfy-even-the-most-discriminating-simulator-afficiandos/"> 737 cockpit will satisfy even the most discriminating simulator afficiandos</a> (Hack a Day)</li> <li><a href="https://amazingdiy.wordpress.com/2012/01/01/mame-cabinet-system-upgrade-part-2/"> MAME cabinet, system upgrade part 2</a> (My DIY Blog)</li> </ul> <h3>Retro Computing and Commodore!</h3> <ul> <li><a href="http://dangerousprototypes.com/2012/01/05/preview-xt-ide-cpld-adapter-v2/"> PREVIEW: CPLD-based XT-IDE adapter V2</a> (Dangerous Prototypes)</li> <li><a href="http://www.mos6502.com/friday-commodore/30-years-of-commodore-64/"> 30 Years of Commodore 64</a> (MOS6502)</li> <li><a href="http://www.mos6502.com/friday-commodore/being-precise-on-the-c64/"> Being precise on the C64</a> (MOS6502)</li> </ul> <h3>Misc Geek</h3> <ul> <li><a href="http://www.breakcontinue.com/2011/12/show-your-skills.html">Take a break: Show your skills</a> (Valentin Ivanov)</li> <li><a href="http://www.electronics-lab.com/blog/?p=16076">Trillion-frame-per-second video</a> (Electronics-Lab.com)</li> </ul> <h3>Just Awesome</h3> <ul> <li><a href="http://www.makermasters.com/jetpack-man-races-with-fighter-jets-yves-rossi"> Jetpack Man Races With Fighter Jets</a> (Maker Masters)</li> </ul> <p><a href="http://feedads.g.doubleclick.net/~a/P8gJcvEnbEewAWoLXPb9PfPebVo/0/da"><img src="http://feedads.g.doubleclick.net/~a/P8gJcvEnbEewAWoLXPb9PfPebVo/0/di" border="0" ismap="true"></img></a><br/> <a href="http://feedads.g.doubleclick.net/~a/P8gJcvEnbEewAWoLXPb9PfPebVo/1/da"><img src="http://feedads.g.doubleclick.net/~a/P8gJcvEnbEewAWoLXPb9PfPebVo/1/di" border="0" ismap="true"></img></a></p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=3pYIs3lR6Ck:Oa2LZJbuipc:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=3pYIs3lR6Ck:Oa2LZJbuipc:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=3pYIs3lR6Ck:Oa2LZJbuipc:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=3pYIs3lR6Ck:Oa2LZJbuipc:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=3pYIs3lR6Ck:Oa2LZJbuipc:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=3pYIs3lR6Ck:Oa2LZJbuipc:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=3pYIs3lR6Ck:Oa2LZJbuipc:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=3pYIs3lR6Ck:Oa2LZJbuipc:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=3pYIs3lR6Ck:Oa2LZJbuipc:gIN9vFwOqvQ" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/PeteBrown/~4/3pYIs3lR6Ck" height="1" width="1"/> http://feedproxy.google.com/~r/PeteBrown/~3/3pYIs3lR6Ck/maker-geek-roundup-005-for-1-7-2012 Pete Brown 3519 2012-01-08T00:27:11 Rick Santorum and Group Marriage <p> One of the most common arguments against same-sex marriage is that it would open the floodgates to all sorts of other types of marriage. For example, James Dobson in his book <i>Gay Marriage: Why We Must Win This Battle</i> (Multnomah, 2004) writes: </p><p>... more ...</p> http://www.charlespetzold.com/blog/2012/01/Rick-Santorum-and-Group-Marriage.html Charles Petzold 3518 2012-01-07T16:31:20 New Markets for Windows Phone Developers <p>We’re pleased to start off the New Year with an update to App Hub that will enable you to distribute apps and games to even more customers in more markets. App Hub now allows you to submit apps for distribution in 6 new markets; Argentina, China, Indonesia, Malaysia, Peru and the Philippines.&#160; Although you will be able to now select these markets for distribution in App Hub, the Windows Phone Marketplace is not yet available to customers in these markets. We will provide more information about availability of the Marketplace for customers in these markets in a future post. </p> <p>You should be aware that applications submitted to three of these six new markets – China, Indonesia and Malaysia – will be subject to additional requirements due to local laws, regulations or norms. You can find information on these additional requirements in the <a href="http://msdn.microsoft.com/en-us/library/hh184842(v=VS.92).aspx">Application Certification Requirements</a>.</p> <p>Given the Marketplace is not yet available for customers in these markets and the addition of new requirements, we’re opening the submission process early to give those of you interested in distribution to these markets a head start on certification. We’re viewing this as an early access period and you can expect the certification process to take a little longer during this time period.</p> <p>As usual, when submitting either an update or a new application in App Hub, you can choose to publish the app “worldwide” to the full set of 41 markets to you can select specific markets.&#160; When you select worldwide, the additional requirements of the new markets apply.&#160; As a result, if your application fails certification, you will need to either update and resubmit your app to meet all worldwide requirements, or de-select the markets where your application will not meet requirements. </p> <p>Also included in this release are a number of minor enhancements and bug fixes, including improvements that will streamline the payout process and enhance reporting to provide data like crash counts and exceptions to assist in improving your apps.&#160; These are a result of your feedback and we’ll continue to provide other improvements in each release.</p> <p>We’re pleased to start the New Year off by expanding markets to which you can submit apps for distribution, and will provide more information on the consumer experiences for those markets when we are ready to go live.</p><div style="clear:both;"></div><img src="http://windowsteamblog.com/aggbug.aspx?PostID=574230" width="1" height="1"> http://windowsteamblog.com/windows_phone/b/wpdev/archive/2012/01/05/new-markets-for-windows-phone-developers.aspx Windows Phone Dev Blog 3517 2012-01-05T23:57:33 My new recording mic: Shure SM7B <p>Over the Christmas break, I decided to replace my great Samson C01U mic with something a little more high end. Today was the first day I really got to try it out at work.</p> <h3>Criteria</h3> <p>I knew I wanted a new mic, but there were some specific things I was looking for. For the new one, I had the following criteria:</p> <ul> <li>Not a USB mic. Straight XLR</li> <li>Must sound good for close-talking voice overs</li> <li>Must be well under $500</li> <li>Visually needs to let me see more of my screen (more on that in a second)</li> <li>Similar to the last one, it needs to mount on my boom arm, and not require desk space when not in use</li> </ul> <h4>Why not USB?</h4> <p>My C01U USB mic worked well, but it was very picky about the juice in the USB line. Depending on what else was running (even with a powered hub) it would sometimes produce really low volume output. In addition, it took up a lot of USB bandwidth while in use. Recognizing that, I made sure to hook up my MOTU using Firewire instead of USB. Still, I have a TON of USB devices hanging off my machine, and I just needed to eliminate this one. The MOTU has balanced mic inputs and plenty of DSP to spare.</p> <p>The use and price should be easy to understand. I use my mic for Skype and Lync calls almost every weekday, sometimes on podcasts with other folks, and when recording narration for the videos I create (which I plan to do even more in 2012). My office is not silent. There's a fridge behind me, and my PC itself produces more noise than I'd want in video (I'm picky). Also, some mics (especially headset mics) pick up keyboard taps as loud thumps. I can't have any of that.</p> <h4>Seeing my Screen!</h4> <p>When recording a video showing how to use an app or write some code, it helps if I could actually see my screen at the same time. The Samson had a largish shock mount and then a big pop screen. If I ran it without the pop screen (as I did later), the <a href="http://en.wikipedia.org/wiki/Plosive" target="_blank">plosives</a> would come through on the recordings as very loud spikes. I spent a bit of time editing them out for the latest Silverlight videos, but I didn't get them all. Small pop screens weren't worth the effort as they were hard to position and also just didn't work well. You should have seen the neck contortion to see my screen with a mic in my face.</p> <h3>The C01U</h3> <p>My C01U is still a good microphone. If you don't have an external audio interface with balanced mic inputs and good preamps, I wouldn't hesitate to to recommend it to someone looking for a USB microphone. In fact, I've recommended it to many others, with the <a href="http://10rem.net/blog/2009/10/25/samson-c01u-microphone-and-windows-7-and-vista" target="_blank">caveat about USB power</a>. Several of the Blue mics are also good to check out.</p> <h3>The SM7B</h3> <p><img src="http://10rem.net/media/81762/Windows-Live-Writer_My-new-recording-mic-Shure-SM7B_13DC2_image_16.png" width="400" height="373" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></p> <p>The mic I finally decided on is the <a href="http://www.shure.com/americas/products/microphones/sm/sm7b-vocal-microphone" target="_blank">Shure SM7B</a>. This is a broadcast quality mic, but still within the price range of most mortals. The cardiod pickup pattern helps reduce the amount of keyboard and background noise that makes it into the recording.</p> <p>I decided on this mic after a lot of research. Initially I looked at condensor mics, but came to the conclusion that at my price range, they're all a bit meh. Granted, I didn't get a chance to actually use any in-person, so I was only able to go by recordings, reviews, and feedback on the web.</p> <p>Why did I pick this mic?</p> <ul> <li>Industry standard sound, often used in talk radio and video voice overs. Optimized for those scenarios, but useful in many others.</li> <li>Does not need a separate shock mount</li> <li>Does not need an external pop filter even when used in close-mic applications.</li> <li>Has good shielding for use around computers and other equipment (have you <strong>seen</strong> my desk?)</li> <li>Price was within budget</li> </ul> <p>I use this mic with the large close-mic foam windscreen over the end. I even like the way that looks a bit better. It's also still smaller than most pop filters.</p> <p>Here's a good <a href="http://tweakheadz.com/reviews/review_of_the_shure_sm7b.htm" target="_blank">review of the SM7B at TweakHeadz</a>.</p> <h3>Preamp</h3> <p>The SM7B needs a powerful preamp. That was a bit of a surprise when I picked it up, as I thought my MOTU would be sufficient. The 52db of gain available on the MOTU 828mkIII may be appropriate for a condensor mic, but I got almost nothing out of the SM7B with the gain cranked all the way up. After a bunch of research I made two decisions:</p> <ol> <li>I really want to build my own preamp based on plans/kits on the web. They're just cool electronics projects with significant opportunity for high-voltage electrocution. I can't resist!</li> <li>I need something fairly inexpensive but decent to work with until I get around to building my own.</li> </ol> <p>So, I went to the local Guitar Center and picked up a PreSonus TUBEPre. This is a tube-based 1/3 width 1U high microphone pre-amp. It sounds decent enough, although you can replace the inexpensive Chinese 12AX7 tube for further customization of the sound. There's a VU meter on the front, but it isn't particularly useful and is more just for eye candy unless you're screaming into the mic.</p> <p><img src="http://10rem.net/media/81767/Windows-Live-Writer_My-new-recording-mic-Shure-SM7B_13DC2_image_17.png" width="240" height="150" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/><img src="http://10rem.net/media/81772/Windows-Live-Writer_My-new-recording-mic-Shure-SM7B_13DC2_image_18.png" width="251" height="125" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></p> <p>Surprisingly, the TubePre gain only goes up to about 40db. However, it sounds louder and cleaner than the MOTU at the full 52db gain setting. I haven't investigated why.</p> <p>I found a number of <a href="http://www.bing.com/search?q=diy+mic+preamp&amp;qs=n&amp;sk=&amp;sc=7-13&amp;form=QBRE" target="_blank">cool plans and kits for building your own preamp</a>. They all tended to run several hundred dollars in parts, but that's still a lot cheaper than most "good" preamps. More on those when I decide to build one.</p> <h3>In the end…</h3> <p>The mic sounds great, although I am still tweaking it (and the preamp and eq) to see what things I like and don't. In the end, typical video compression renders a lot of the nuance from the preamp and mic pretty much undetectable. That's ok, though, as I'll create the best possible source recordings, and enjoy myself while doing it. It just feels better to work with good equipment.</p> <p><a href="http://feedads.g.doubleclick.net/~a/0yQTlhE0Bv_8cnwUI2ky3HaKAaE/0/da"><img src="http://feedads.g.doubleclick.net/~a/0yQTlhE0Bv_8cnwUI2ky3HaKAaE/0/di" border="0" ismap="true"></img></a><br/> <a href="http://feedads.g.doubleclick.net/~a/0yQTlhE0Bv_8cnwUI2ky3HaKAaE/1/da"><img src="http://feedads.g.doubleclick.net/~a/0yQTlhE0Bv_8cnwUI2ky3HaKAaE/1/di" border="0" ismap="true"></img></a></p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=c47SU1Y_69Q:gIexxopQIRg:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=c47SU1Y_69Q:gIexxopQIRg:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=c47SU1Y_69Q:gIexxopQIRg:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=c47SU1Y_69Q:gIexxopQIRg:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=c47SU1Y_69Q:gIexxopQIRg:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=c47SU1Y_69Q:gIexxopQIRg:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=c47SU1Y_69Q:gIexxopQIRg:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=c47SU1Y_69Q:gIexxopQIRg:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=c47SU1Y_69Q:gIexxopQIRg:gIN9vFwOqvQ" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/PeteBrown/~4/c47SU1Y_69Q" height="1" width="1"/> http://feedproxy.google.com/~r/PeteBrown/~3/c47SU1Y_69Q/my-new-recording-mic-shure-sm7b Pete Brown 3515 2012-01-05T06:01:08 Yet Another Podcast #56–Jeff Blankenburg: Evangelist http://feedproxy.google.com/~r/JesseLiberty-SilverlightGeek/~3/PNz7x8tb7dQ/ Jesse Liberty [MS] 3514 2012-01-04T16:45:04 MFOS Synth 6: PCB Complete <p>Over Christmas vacation, I completed all the component mounting on my MFOS Ultimate board.</p> <blockquote> <p>Over the next several months I'll be building what is definitely my most complex electronics project to date: the MFOS (Music From Outer Space) <a href="http://www.musicfromouterspace.com/index.php?MAINTAB=SYNTHDIY&amp;PROJARG=SOUNDLAB_ULTIMATE/page1.html&amp;VPW=1326&amp;VPH=1153"> Sound Lab Ultimate</a>, <a href="http://www.musicfromouterspace.com/index.php?MAINTAB=SYNTHDIY&amp;PROJARG=ULTIMATE_EXPANDER/ultexpanderpg1.html&amp;VPW=1326&amp;VPH=1153"> Ultimate Expander</a> and (if Santa brings one) <a href="http://www.musicfromouterspace.com/index.php?MAINTAB=SYNTHDIY&amp;PROJARG=SOUNDLABMINIMARKII/page1.php&amp;VPW=1326&amp;VPH=1153"> Sound Lab Mini-Synth Mark II</a>, likely all in the same home-made wooden case, side by side. The Ultimate and Expander are together a 3 oscillator monophonic true analog synthesizer with filters, envelopment generator, ring modulator, sample and hold and more. You patch between the different logical modules using banana cables, so it's a bit of a self-contained modular synthesizer. The Mark II is smaller, newer, and has a few fewer features, but a sound of its own. You also patch that with banana cables, and can integrate the two. This blog post is another in the series. Previous posts include:</p> <ul> <li><a href="http://10rem.net/blog/2011/12/02/mfos-synth-1-built-the-power-supply">MFOS Synth 1: Built the Power Supply</a></li> <li><a href="http://10rem.net/blog/2011/12/02/mfos-synth-2-some-main-synthesizer-board-work"> MFOS Synth 2: Some main synthesizer board work</a></li> <li><a href="http://10rem.net/blog/2011/12/04/mfos-synth-3-starting-the-front-panel">MFOS Synth 3: Starting the Front Panel</a></li> <li><a href="http://10rem.net/blog/2011/12/16/mfos-synth-4-resistors-all-soldered">MFOS Synth 4: Resistors all soldered</a></li> <li><a href="http://10rem.net/blog/2011/12/18/mfos-synth-5-trimmers-and-some-capacitors-in-place"> MFOS Synth 5: Trimmers and some capacitors in place</a></li> </ul> </blockquote> <p>The board now has installed all the capacitors, resistors, diodes, ICs, trimpots, and transistors specified in the parts list.</p> <p>Here's the overall shot of the board. For the most part, I tried to use the best components I could reasonably get. One place where I decided to spring for a little bit better was with capacitors 49 and 50 in the filter. I don't have a DMM sensitive enough to measure pF capacitance, so I couldn't measure and match those. There are circuits you can build which will let you measure capacitance, but I'm not particularly interested in building one. Instead, I sprung for 1% tolerance capacitors figuring that will get them pretty darn close.</p> <p><a href="http://10rem.net/media/81670/Windows-Live-Writer_MFOS-Synth-6-todo_13715_image_2.png" target="_blank"><img src="http://10rem.net/media/81675/Windows-Live-Writer_MFOS-Synth-6-todo_13715_image_thumb.png" width="520" height="368" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>A thing of beauty!</p> <p>Here's a shot of one of the three oscillators. You can see the 2k ohm tempco (temperature compensating) resistor mounted over the SSM2210. I don't have any appropriate thermal or potting epoxy around, so it's just touching it right now. I'll bed it once I test everything and I pick up the epoxy.</p> <p><a href="http://10rem.net/media/81680/Windows-Live-Writer_MFOS-Synth-6-todo_13715_image_4.png" target="_blank"><img src="http://10rem.net/media/81685/Windows-Live-Writer_MFOS-Synth-6-todo_13715_image_thumb_1.png" width="520" height="296" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p><a href="http://10rem.net/media/81690/Windows-Live-Writer_MFOS-Synth-6-todo_13715_image_12.png" target="_blank"><img src="http://10rem.net/media/81695/Windows-Live-Writer_MFOS-Synth-6-todo_13715_image_thumb_5.png" width="520" height="395" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>After I took these photos, I cleaned the bottom of the board using <a href="http://www.amazon.com/Chemtronics-Flux-Off%C2%AE-Rosin-Flux-Remover/dp/B000ARQ5H0" target="_blank">Flux Off Rosin Flux remover by Chemtronics</a>. What a mess! It took the whole 10oz can to clean the board (at $17 a can!), and then it still (due to the "X" holes) redistributed some of the sticky flux to the component side. Once I finished up the can, I managed to get almost all of the flux off the top, and all of it off the bottom. Still, what a mess. You have to spray enough of the remover on to liquefy the flux and run it off the board. Any dissolved flux which stays on the board simply spreads out. That stickiness, if not removed, will attract dust and dirt, making more of a mess of the board.</p> <p>I'll give it this: the bottom *did* get clean. The burnt flux from removing a couple mistakes (one transistor soldered backwards, for example) was all washed off, as were the sticky hard globs of resin.</p> <p><a href="http://10rem.net/media/81700/Windows-Live-Writer_MFOS-Synth-6-todo_13715_image_14.png" target="_blank"><img src="http://10rem.net/media/81705/Windows-Live-Writer_MFOS-Synth-6-todo_13715_image_thumb_6.png" width="520" height="369" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>Of course, this is before I solder on all the front panel wires, so there will be flux from that too.</p> <p>Flux can be corrosive over time, not to mention ugly, so it's a good idea to clean it off. Other approaches to consider include using 99% alcohol if you can get it. I just ordered <a href="http://www.zackelectronics.com/servlet/the-18045/MCC-dsh-PRO/Detail" target="_blank">order some of this</a>, because it is likely the same type of stuff for less than half the price of the Flux Off.</p> <p>Rosin flux is more benign than most, and actually cures hard to entrap the contaminants. Don't get water washable flux unless you intend to do a really thorough job cleaning the board. Typical water washable flux is highly corrosive if only partially cleaned.</p> <p>I've also heard that the particular solder I used for this project (60/40 from Radio Shack) tends to have quite a mess of flux. Folks have recommended <a href="http://www.bing.com/shopping/kester-44-rosin-core-solder-63-37-031-1-lb-spool/p/A2DD57AC51D513865006?q=Kester+44+Rosin+Core+Solder+63%2f37&amp;lpq=Kester%2044%20Rosin%20Core%20Solder%2063%2f37&amp;FORM=HURE" target="_blank">Kester 44 Rosin Core 63/37</a> as a better replacement with both more stable soldering (less time in the intermediate state) and cleaner flux. I have some on order for the next few boards :)</p> <p>Here are a few more glam shots of the board</p> <p><a href="http://10rem.net/media/81710/Windows-Live-Writer_MFOS-Synth-6-todo_13715_image_6.png" target="_blank"><img src="http://10rem.net/media/81715/Windows-Live-Writer_MFOS-Synth-6-todo_13715_image_thumb_2.png" width="261" height="201" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a><a href="http://10rem.net/media/81720/Windows-Live-Writer_MFOS-Synth-6-todo_13715_image_8.png" target="_blank"><img src="http://10rem.net/media/81725/Windows-Live-Writer_MFOS-Synth-6-todo_13715_image_thumb_3.png" width="261" height="201" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p><a href="http://10rem.net/media/81730/Windows-Live-Writer_MFOS-Synth-6-todo_13715_image_10.png" target="_blank"><img src="http://10rem.net/media/81735/Windows-Live-Writer_MFOS-Synth-6-todo_13715_image_thumb_4.png" width="261" height="201" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a><a href="http://10rem.net/media/81740/Windows-Live-Writer_MFOS-Synth-6-todo_13715_image_16.png" target="_blank"><img src="http://10rem.net/media/81745/Windows-Live-Writer_MFOS-Synth-6-todo_13715_image_thumb_7.png" width="261" height="201" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>For the next step, I'll either work on testing and calibrating the oscillators here (which will require building the 1V/Octave test board), or I'll start wiring some of the panel. Whatever I end up doing, I'll be sure to write about it here :)</p> <p><a href="http://feedads.g.doubleclick.net/~a/PeCv5Hwh6f4In1NgCkWAUhD7YuI/0/da"><img src="http://feedads.g.doubleclick.net/~a/PeCv5Hwh6f4In1NgCkWAUhD7YuI/0/di" border="0" ismap="true"></img></a><br/> <a href="http://feedads.g.doubleclick.net/~a/PeCv5Hwh6f4In1NgCkWAUhD7YuI/1/da"><img src="http://feedads.g.doubleclick.net/~a/PeCv5Hwh6f4In1NgCkWAUhD7YuI/1/di" border="0" ismap="true"></img></a></p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=Q65SMTLEJzo:rUeJfb-qggc:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=Q65SMTLEJzo:rUeJfb-qggc:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=Q65SMTLEJzo:rUeJfb-qggc:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=Q65SMTLEJzo:rUeJfb-qggc:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=Q65SMTLEJzo:rUeJfb-qggc:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=Q65SMTLEJzo:rUeJfb-qggc:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=Q65SMTLEJzo:rUeJfb-qggc:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=Q65SMTLEJzo:rUeJfb-qggc:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=Q65SMTLEJzo:rUeJfb-qggc:gIN9vFwOqvQ" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/PeteBrown/~4/Q65SMTLEJzo" height="1" width="1"/> http://feedproxy.google.com/~r/PeteBrown/~3/Q65SMTLEJzo/mfos-synth-6-pcb-complete Pete Brown 3513 2012-01-04T08:08:42 Vibrating the phone http://feedproxy.google.com/~r/JesseLiberty-SilverlightGeek/~3/i_5oxPrr7BY/ Jesse Liberty [MS] 3511 2012-01-03T18:31:15 Binding Formatting http://feedproxy.google.com/~r/JesseLiberty-SilverlightGeek/~3/darvONxKku4/ Jesse Liberty [MS] 3501 2011-12-29T18:48:15 Perspective : easy 3D programming with Silverlight 5 RTM <p>While Silverlight 5 has hit&nbsp;its&nbsp;final (? wait and see :-) version, I&#39;ve updated my work about <a href="http://perspective4sl.codeplex.com/releases/view/79549">3D programming&nbsp;with the Perspective library</a>.</p> <p>&nbsp;<img style="WIDTH:298px;HEIGHT:305px;" title="Perspective 3D for Silverlight" alt="Perspective 3D for Silverlight" src="http://www.odewit.net//Articles/Sl3DIntro/BitmapTexture.png" width="298" height="305" /></p> <p>Read more :</p> <ul> <li><a href="http://www.odewit.net/ArticleContent.aspx?id=Sl3DIntro&amp;format=html">Perspective : Easy 3D programming with Silverlight 5</a></li> <li><a href="http://www.odewit.net/ArticleContent.aspx?id=Sl3DModels&amp;format=html">Perspective : basic 3D models for Silverlight 5</a></li></ul> <p>Enjoy !</p><img src="http://blogs.windowsclient.net/aggbug.aspx?PostID=481756" width="1" height="1"> http://blogs.windowsclient.net/odewit/archive/2011/12/28/Perspective3d4sl5rtm.aspx Olivier Dewit 3500 2011-12-28T22:09:00 Parsing CSS for EPUB <p> I've been trying to build an EPUB viewer for Windows 8, mostly because I want to read books on the Windows 8 tablet I got at the Build conference, and it's more fun writing one's own application rather than using someone else's. This will obviously <i>not</i> be a commercial product or I would have thought of a snappier and less wonky name for the program than The New Epublic! [I've decided I don't want to distribute the code at this time. &#x2014; Jan. 5, 2012] <!-- Here's the latest <a href="http://www.charlespetzold.com/blog/2011/12/TheNewEpublic3.zip">Visual Studio solution</a> for the program. --> </p><p>... more ...</p> http://www.charlespetzold.com/blog/2011/12/Parsing-CSS-for-EPUB.html Charles Petzold 3493 2011-12-26T19:33:30 DecryptR Part 2 http://feedproxy.google.com/~r/JesseLiberty-SilverlightGeek/~3/8EuD3TxkFPE/ Jesse Liberty [MS] 3480 2011-12-21T16:37:03 Living room window bench and bookcase update: cabinet doors! <p>In every project, there comes a part you just dread doing. It's always the part you put off until the very end. When programming, maybe it's that exception logging, or security interface. With most house projects, it's painting.</p> <p>With carpentry/cabinetry, well, I hate building cabinet doors.</p> <p>There. I said it. I love woodworking, but BOY do I hate doors. I know the appropriate tricks for squaring them up and for adjusting the squareness once they are assembled, but it seems they always bite me in the end. Bah!</p> <p>Well, I couldn't have yet another set of cabinets without doors (ask my wife about the kitchen), so I decided to build the four doors for the living room window bench seat cabinets. These doors go on the lower cabinets underneath the bookcases on either side of the bench seat.</p> <blockquote> <p>Want to see more of this project including the full view of the bench seat and cabinets? <a href="http://10rem.net/blog/2011/10/23/window-bench-seat-update-crown-and-valence" target="_blank">Here's the recap</a> I wrote in October.</p> </blockquote> <p>I may hate making doors, but I hate looking at ugly doors even more. So, I went and made these flush inset doors, but compromised on the hinge. It's a nice hinge, but unlike the maple cabinets in the kitchen, these painted poplar cabinets use simple 1/16" spacing no-mortise surface mounted hinges. No mortising means these doors won't be quite so fiddly to hang.</p> <p><a href="http://10rem.net/media/81548/Windows-Live-Writer_70e08746c186_13A1A_image_18.png" target="_blank"><img src="http://10rem.net/media/81553/Windows-Live-Writer_70e08746c186_13A1A_image_thumb_8.png" width="520" height="400" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>I took some basic measurements, dug up all the wood, and headed out to the shed with my scribbled notes in hand.</p> <p><a href="http://10rem.net/media/81558/Windows-Live-Writer_70e08746c186_13A1A_image_24.png" target="_blank"><img src="http://10rem.net/media/81563/Windows-Live-Writer_70e08746c186_13A1A_image_thumb_11.png" width="512" height="468" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>The stiles are 1x3 (3/4" x 2 1/2") poplar while the top rail is 1x4 (3/4" x 3 1/2") and the bottom rail is cut to 1x5" (3/4" x 5" exactly) from larger stock.</p> <p><a href="http://10rem.net/media/81568/Windows-Live-Writer_70e08746c186_13A1A_image_2.png" target="_blank"><img src="http://10rem.net/media/81573/Windows-Live-Writer_70e08746c186_13A1A_image_thumb.png" width="173" height="135" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a><a href="http://10rem.net/media/81578/Windows-Live-Writer_70e08746c186_13A1A_image_4.png" target="_blank"><img src="http://10rem.net/media/81583/Windows-Live-Writer_70e08746c186_13A1A_image_thumb_1.png" width="173" height="135" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a><a href="http://10rem.net/media/81588/Windows-Live-Writer_70e08746c186_13A1A_image_6.png" target="_blank"><img src="http://10rem.net/media/81593/Windows-Live-Writer_70e08746c186_13A1A_image_thumb_2.png" width="173" height="135" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>The core of each door is 1/4" thick plywood, glued into 1/4" routed grooves 1/2" deep in the rails and stiles, offset 3/8" from the front of the door. As is always the case, the plywood was warped, so I had to fight that during assembly.</p> <p><a href="http://10rem.net/media/81598/Windows-Live-Writer_70e08746c186_13A1A_image_14.png" target="_blank"><img src="http://10rem.net/media/81603/Windows-Live-Writer_70e08746c186_13A1A_image_thumb_6.png" width="520" height="396" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p><a href="http://10rem.net/media/81608/Windows-Live-Writer_70e08746c186_13A1A_image_12.png" target="_blank"><img src="http://10rem.net/media/81613/Windows-Live-Writer_70e08746c186_13A1A_image_thumb_5.png" width="520" height="396" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>The rail and stile joints are reinforced with 8x50 dowels using my <a href="http://www.mcfeelys.com/product/574332/Festool-DOMINO-DF-500-Plus-Joining-System" target="_blank">Festool Domino</a>. I've had that tool since it first came out in 2007ish, and have used it over and over again. It's really a huge help when it comes to this type of assembly. FWIW, I cut the mortises in the rails to the exact width, and used the wider setting when cutting the mortises in the stiles. This gives me a little wiggle room during assembly.</p> <p><a href="http://10rem.net/media/81618/Windows-Live-Writer_70e08746c186_13A1A_image_8.png" target="_blank"><img src="http://10rem.net/media/81623/Windows-Live-Writer_70e08746c186_13A1A_image_thumb_3.png" width="520" height="396" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>It's humid year-round here in the mid-atlantic, so I had to microwave the domino tenons to get them to fit reasonably well. Microwaving helps remove some of the moisture that swells the wood. I had them stored in a plastic bag inside a Festool systainer, but it was outside in my work shed.</p> <p><a href="http://10rem.net/media/81628/Windows-Live-Writer_70e08746c186_13A1A_image_16.png" target="_blank"><img src="http://10rem.net/media/81633/Windows-Live-Writer_70e08746c186_13A1A_image_thumb_7.png" width="520" height="396" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>The detail in the center of the door is 1/4" x 2 1/2" poplar simply glued in place on the plywood.</p> <p><a href="http://10rem.net/media/81638/Windows-Live-Writer_70e08746c186_13A1A_image_10.png" target="_blank"><img src="http://10rem.net/media/81643/Windows-Live-Writer_70e08746c186_13A1A_image_thumb_4.png" width="357" height="468" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>The joints came out horribly. But honestly I didn't fuss over them that much as the doors will simply be painted. I'm just happy to have the doors done :) Between the glued-in plywood (it's plywood, so you can glue it in. Don't do that with solid wood) and the eight big 8x50 dominos used on each door, they should hold up to quite a bit of use…maybe even to what my kids dish out. I'm not so sure about the overlays in the middle, though. Only time will tell there, but as they rely on the stability and quality of the plywood (ha!), I can see them popping off with the top skin of the plywood going with them. I hope not, but it seems plausible.</p> <p>The next step was into the house to have wood filler put on the defects and bad joinery. After that, because they're ever so slightly oversize (something I did on purpose), I'll trim them on the table saw and do a final squaring up at the same time. Here are all four doors in front of one of the cabinets. As you can see, the cabinet is already being put to good use.</p> <p><a href="http://10rem.net/media/81648/Windows-Live-Writer_70e08746c186_13A1A_image_20.png" target="_blank"><img src="http://10rem.net/media/81653/Windows-Live-Writer_70e08746c186_13A1A_image_thumb_9.png" width="520" height="396" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>From there, it will be final sanding and then painting. They look horrible right now, but once sanded and painted, no one will ever know of my sins. Well, except all of you :)</p> <p>What do you know? I might actually have doors on these cabinets in time so Santa doesn't have to see all our messy craft and homeschool supplies.</p> <p><a href="http://feedads.g.doubleclick.net/~a/O3mTVFVKMmZ847IdAgxSrzsQmdU/0/da"><img src="http://feedads.g.doubleclick.net/~a/O3mTVFVKMmZ847IdAgxSrzsQmdU/0/di" border="0" ismap="true"></img></a><br/> <a href="http://feedads.g.doubleclick.net/~a/O3mTVFVKMmZ847IdAgxSrzsQmdU/1/da"><img src="http://feedads.g.doubleclick.net/~a/O3mTVFVKMmZ847IdAgxSrzsQmdU/1/di" border="0" ismap="true"></img></a></p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=O7gpw1wvyKs:oJXTfVEhsEU:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=O7gpw1wvyKs:oJXTfVEhsEU:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=O7gpw1wvyKs:oJXTfVEhsEU:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=O7gpw1wvyKs:oJXTfVEhsEU:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=O7gpw1wvyKs:oJXTfVEhsEU:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=O7gpw1wvyKs:oJXTfVEhsEU:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=O7gpw1wvyKs:oJXTfVEhsEU:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=O7gpw1wvyKs:oJXTfVEhsEU:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=O7gpw1wvyKs:oJXTfVEhsEU:gIN9vFwOqvQ" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/PeteBrown/~4/O7gpw1wvyKs" height="1" width="1"/> http://feedproxy.google.com/~r/PeteBrown/~3/O7gpw1wvyKs/living-room-window-bench-and-bookcase-update-cabinet-doors Pete Brown 3476 2011-12-19T04:25:50 MFOS Synth 5: Trimmers and some capacitors in place <p>The next step was to solder yet more components to the board. I soldered the trimmer potentiometers as well as a number of the capacitors.</p> <blockquote> <p>Over the next several months I'll be building what is definitely my most complex electronics project to date: the MFOS (Music From Outer Space) <a href="http://www.musicfromouterspace.com/index.php?MAINTAB=SYNTHDIY&amp;PROJARG=SOUNDLAB_ULTIMATE/page1.html&amp;VPW=1326&amp;VPH=1153"> Sound Lab Ultimate</a>, <a href="http://www.musicfromouterspace.com/index.php?MAINTAB=SYNTHDIY&amp;PROJARG=ULTIMATE_EXPANDER/ultexpanderpg1.html&amp;VPW=1326&amp;VPH=1153"> Ultimate Expander</a> and (if Santa brings one) <a href="http://www.musicfromouterspace.com/index.php?MAINTAB=SYNTHDIY&amp;PROJARG=SOUNDLABMINIMARKII/page1.php&amp;VPW=1326&amp;VPH=1153"> Sound Lab Mini-Synth Mark II</a>, likely all in the same home-made wooden case, side by side. The Ultimate and Expander are together a 3 oscillator monophonic true analog synthesizer with filters, envelopment generator, ring modulator, sample and hold and more. You patch between the different logical modules using banana cables, so it's a bit of a self-contained modular synthesizer. The Mark II is smaller, newer, and has a few fewer features, but a sound of its own. You also patch that with banana cables, and can integrate the two. This blog post is another in the series. Previous posts include:</p> <ul> <li><a href="http://10rem.net/blog/2011/12/02/mfos-synth-1-built-the-power-supply"> MFOS Synth 1: Built the Power Supply</a></li> <li><a href="http://10rem.net/blog/2011/12/02/mfos-synth-2-some-main-synthesizer-board-work"> MFOS Synth 2: Some main synthesizer board work</a></li> <li><a href="http://10rem.net/blog/2011/12/04/mfos-synth-3-starting-the-front-panel"> MFOS Synth 3: Starting the Front Panel</a></li> <li><a href="http://10rem.net/blog/2011/12/16/mfos-synth-4-resistors-all-soldered"> MFOS Synth 4: Resistors all soldered</a></li> </ul> </blockquote> <h3>Trim pots</h3> <p>The MFOS synthesizer uses multi-turn cermet trim pots to make tuning the various parameters possible. I picked them up from <a href="http://www.taydaelectronics.com/servlet/the-Potentiometer--fdsh--Variable-Resistors-cln-Cermet-Potentiometers-cln-3296W/Categories" target="_blank">Tayda Electronics</a>. These are used throughout the synthesizer to enable calibration.</p> <p><img src="http://10rem.net/media/81497/Windows-Live-Writer_a3c8f3d1c9f0_EA25_image_3.png" width="200" height="141" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></p> <p>These are +/- 10% Cermet pots with a top-mounted multi-turn (25 I think) adjustment screw. Not for this board, but for the others, I recall running into a case where I could only find the side-mounted adjustment screw versions for at least one of the values. Those will work too, but the adjustment screw may be more difficult to access.</p> <p><a href="http://10rem.net/media/81502/Windows-Live-Writer_a3c8f3d1c9f0_EA25_image_7.png" target="_blank"><img src="http://10rem.net/media/81507/Windows-Live-Writer_a3c8f3d1c9f0_EA25_image_thumb_2.png" width="520" height="396" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <h3>Capacitors</h3> <p>Pay attention to the build notes at the MFOS site. Ray has a few substitutions you may wish to make, specifically swapping out some of the Tantalum capacitors for aluminum electrolytic ones of the same value.</p> <p><a href="http://10rem.net/media/81512/Windows-Live-Writer_a3c8f3d1c9f0_EA25_image_9.png" target="_blank"><img src="http://10rem.net/media/81517/Windows-Live-Writer_a3c8f3d1c9f0_EA25_image_thumb_3.png" width="520" height="361" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>One thing I didn't like about the board layout was that several of the spots for the aluminum electrolytics were sized for a much larger capacitor with 5mm leads. The smaller sized ones (of the correct voltage and capacitance) work fine, but they stick up from the board a bit rather than sitting flat. For grins, I tried finding 5mm lead versions on Mouser, but those are almost impossible to find. My guess is that Ray had much larger values originally spec'd or something.</p> <p><a href="http://10rem.net/media/81522/Windows-Live-Writer_a3c8f3d1c9f0_EA25_image_5.png" target="_blank"><img src="http://10rem.net/media/81527/Windows-Live-Writer_a3c8f3d1c9f0_EA25_image_thumb_1.png" width="520" height="396" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>I ordered some additional capacitors from Mouser. It turns out I was missing a few values. Those should hopefully arrive either just before or just after Christmas. Once those are in, I'll be able to calibrate the three oscillators. That's <a href="http://www.youtube.com/watch?v=5gs-xL4JdT4" target="_blank">where the real fun begins</a> :)</p> <h3>Other work</h3> <p>Based on feedback from the last post, I also replaced the doubled-up 1/8W 3M resistors with single ones. Doubling up the resistors in parallel actually decreased the resistance, and it turns out the board won't need the full 1/4" watt ones anyway (although those might be more heat stable). I'll keep an eye on them in case heat becomes an issue.</p> <p>Also, after pricing out the headers I'd need to make this board easily disconnected from the panel, I decided to just pass and instead wire the front panel directly to the board like everyone else. I will, however, end up using coax for the mixer section as Ray recommended in his MFOS Sound Lab Mini Synth Mark II build.</p> <p><a href="http://feedads.g.doubleclick.net/~a/2tEbALiqQTxrFWkqvX5S75Zozw0/0/da"><img src="http://feedads.g.doubleclick.net/~a/2tEbALiqQTxrFWkqvX5S75Zozw0/0/di" border="0" ismap="true"></img></a><br/> <a href="http://feedads.g.doubleclick.net/~a/2tEbALiqQTxrFWkqvX5S75Zozw0/1/da"><img src="http://feedads.g.doubleclick.net/~a/2tEbALiqQTxrFWkqvX5S75Zozw0/1/di" border="0" ismap="true"></img></a></p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=PnBVziu8BJM:P6ciS3KDdjI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=PnBVziu8BJM:P6ciS3KDdjI:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=PnBVziu8BJM:P6ciS3KDdjI:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=PnBVziu8BJM:P6ciS3KDdjI:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=PnBVziu8BJM:P6ciS3KDdjI:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=PnBVziu8BJM:P6ciS3KDdjI:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=PnBVziu8BJM:P6ciS3KDdjI:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=PnBVziu8BJM:P6ciS3KDdjI:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=PnBVziu8BJM:P6ciS3KDdjI:gIN9vFwOqvQ" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/PeteBrown/~4/PnBVziu8BJM" height="1" width="1"/> http://feedproxy.google.com/~r/PeteBrown/~3/PnBVziu8BJM/mfos-synth-5-trimmers-and-some-capacitors-in-place Pete Brown 3474 2011-12-19T03:04:55 Yet Another Podcast #55–David Plat on Why Software Sucks http://feedproxy.google.com/~r/JesseLiberty-SilverlightGeek/~3/G-DECH5bOW0/ Jesse Liberty [MS] 3470 2011-12-16T18:44:57 MFOS Synth 4: Resistors all soldered <p>Phew! The resistors are all soldered. The board has a few hundred of them, so there was quite a bit of soldering.</p> <blockquote> <p>Over the next several months I'll be building what is definitely my most complex electronics project to date: the MFOS (Music From Outer Space) <a href="http://www.musicfromouterspace.com/index.php?MAINTAB=SYNTHDIY&amp;PROJARG=SOUNDLAB_ULTIMATE/page1.html&amp;VPW=1326&amp;VPH=1153"> Sound Lab Ultimate</a>, <a href="http://www.musicfromouterspace.com/index.php?MAINTAB=SYNTHDIY&amp;PROJARG=ULTIMATE_EXPANDER/ultexpanderpg1.html&amp;VPW=1326&amp;VPH=1153"> Ultimate Expander</a> and (if Santa brings one) <a href="http://www.musicfromouterspace.com/index.php?MAINTAB=SYNTHDIY&amp;PROJARG=SOUNDLABMINIMARKII/page1.php&amp;VPW=1326&amp;VPH=1153"> Sound Lab Mini-Synth Mark II</a>, likely all in the same home-made wooden case, side by side. The Ultimate and Expander are together a 3 oscillator monophonic true analog synthesizer with filters, envelopment generator, ring modulator, sample and hold and more. You patch between the different logical modules using banana cables, so it's a bit of a self-contained modular synthesizer. The Mark II is smaller, newer, and has a few fewer features, but a sound of its own. You also patch that with banana cables, and can integrate the two. This blog post is another in the series. Previous posts include:</p> <ul> <li><a href="http://10rem.net/blog/2011/12/02/mfos-synth-1-built-the-power-supply">MFOS Synth 1: Built the Power Supply</a></li> <li><a href="http://10rem.net/blog/2011/12/02/mfos-synth-2-some-main-synthesizer-board-work"> MFOS Synth 2: Some main synthesizer board work</a></li> <li><a href="http://10rem.net/blog/2011/12/04/mfos-synth-3-starting-the-front-panel">MFOS Synth 3: Starting the Front Panel</a></li> </ul> </blockquote> <p>Here's an image of the board with all the resistors in place. In the oscillator section to the left, one resistor in each of the three is not used. I marked it with a silver sharpie. In addition, a second resistor is left empty in each oscillator if you use the temperature compensating resistors. Since I'm going that route, that slot is empty and marked with a brown sharpie.</p> <p><a href="http://10rem.net/media/81441/Windows-Live-Writer_MFOS-Synth_14E25_image_2.png" target="_blank"><img src="http://10rem.net/media/81446/Windows-Live-Writer_MFOS-Synth_14E25_image_thumb.png" width="520" height="371" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>Overall the resistor soldering was enjoyable but monotonous. The only problem I ran into was a mistake I made when ordering. When I ordered the 3M resistors, I accidentally ordered 1/8W instead of 1/4W. Looking at inventory at Mouser, I realize why: they have no small quantities available for 1/4w 3M resistors. It's possible the board only needs 1/8W (I haven't calculated it), but rather than take any chances, I put two 1/8W 3M resistors in parallel in the two spots that required 1/4W 3M resistors.</p> <blockquote>NOTE: Don't do this. I was only thinking about wattage, but didn't realize that resistance drops when you do this. The two 3M resistors end up producing only 1.5M actual resistance. Thanks to Michael in the comments for saving me some annoying debugging later :)</blockquote> <p>Other than that, I forgot to swap out two replacement values for R184 and R189 as recommended in the MFOS page. I did that after I took the photo.</p> <p><a href="http://10rem.net/media/81451/Windows-Live-Writer_MFOS-Synth_14E25_image_4.png" target="_blank"><img src="http://10rem.net/media/81456/Windows-Live-Writer_MFOS-Synth_14E25_image_thumb_1.png" width="520" height="402" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>I could have just ordered some replacements, but I really didn't feel like waiting, or wasting the money. Here's another shot of the board with resistors in place.</p> <p><a href="http://10rem.net/media/81461/Windows-Live-Writer_MFOS-Synth_14E25_image_6.png" target="_blank"><img src="http://10rem.net/media/81466/Windows-Live-Writer_MFOS-Synth_14E25_image_thumb_2.png" width="520" height="396" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>Once everything is assembled, I'll set up some better lighting and take a few wallpaper-quality shots of the board. Here are some opinions on soldering all these resistors:</p> <p><a href="http://10rem.net/media/81471/Windows-Live-Writer_MFOS-Synth_14E25_image_8.png" target="_blank"><img src="http://10rem.net/media/81476/Windows-Live-Writer_MFOS-Synth_14E25_image_thumb_3.png" width="520" height="175" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></a></p> <p>I actually found it relaxing to solder all those (well, once I got a decent fume removing fan). Resistors are pretty immune to all types of crappy techniques: other than making sure you have the right values, you don't have to worry a whole lot about them. Soldering transistors, on the other hand…</p> <p>Next up will likely be capacitors or the trimmer pots.</p> <p><a href="http://feedads.g.doubleclick.net/~a/jFKBAxpUlbosk1ce18gY6ALG6bo/0/da"><img src="http://feedads.g.doubleclick.net/~a/jFKBAxpUlbosk1ce18gY6ALG6bo/0/di" border="0" ismap="true"></img></a><br/> <a href="http://feedads.g.doubleclick.net/~a/jFKBAxpUlbosk1ce18gY6ALG6bo/1/da"><img src="http://feedads.g.doubleclick.net/~a/jFKBAxpUlbosk1ce18gY6ALG6bo/1/di" border="0" ismap="true"></img></a></p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=sLsPXxfxjrE:qyXnOQUU7xY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=sLsPXxfxjrE:qyXnOQUU7xY:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=sLsPXxfxjrE:qyXnOQUU7xY:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=sLsPXxfxjrE:qyXnOQUU7xY:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=sLsPXxfxjrE:qyXnOQUU7xY:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=sLsPXxfxjrE:qyXnOQUU7xY:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=sLsPXxfxjrE:qyXnOQUU7xY:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=sLsPXxfxjrE:qyXnOQUU7xY:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=sLsPXxfxjrE:qyXnOQUU7xY:gIN9vFwOqvQ" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/PeteBrown/~4/sLsPXxfxjrE" height="1" width="1"/> http://feedproxy.google.com/~r/PeteBrown/~3/sLsPXxfxjrE/mfos-synth-4-resistors-all-soldered Pete Brown 3468 2011-12-16T05:14:26 Slides and Code from my VSLive Silverlight 5, REST, WCF Web API, MVC talk <p>This talk was an adaptation of two chapters from Silverlight 5 in Action. I started with a brief explanation of REST, and then explained the solution we were going to build during the session. The idea was to show how you can use REST in place of the heavier Soap approach in many cases, and make your services accessible to far more clients.</p> <p>I also showed how to share model objects between various implementations of .NET, using linked files and conditional compilation.</p> <p>Without watching the session or reading the chapters, the source and slides are only somewhat useful as you miss the interim steps. So, if you happen to be at an event where I deliver this again (I've submitted it to several upcoming 2012 events), great. If not…<a href="http://www.manning.com/pbrown2/" target="_blank">buy my Silverlight 5 book</a> ;)</p> <p><img src="http://10rem.net/media/81420/Windows-Live-Writer_cb379422aa67_EC67_image_3.png" width="520" height="394" alt="image" border="0" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px"/></p> <ul> <li>In addition to what's covered in my book, I also <a href="http://10rem.net/blog/2011/08/01/creating-a-silverlight-5-helper-for-aspnet-mvc3-razor" target="_blank">showed how to create a basic Razor Helper to load Silverlight in the page</a>. You can learn more at the linked blog post.</li> <li>The WCF Web API may be found at the <a href="http://wcf.codeplex.com/" target="_blank">WCF CodePlex Site</a>.</li> <li>You can learn (a lot) more about ASP.NET MVC at our <a href="http://asp.net/" target="_blank">ASP.NET Community Site</a>.</li> <li>Of course, you can get all the Silverlight 5 bits at our <a href="http://silverlight.net/" target="_blank">Silverlight Community Site</a>.</li> </ul> <p>Everything else is attached to this blog post. The zip file is around 7mb.</p> <p>Feel free to present this at your own internal or public events. I only ask that you not submit this as a session at VSLive, TechEd, DevConnections or other large events where I may be planning to present. When in doubt, ask.</p> <p><a href="http://feedads.g.doubleclick.net/~a/obk0hnTlqqvnfldr6SjD4MydasI/0/da"><img src="http://feedads.g.doubleclick.net/~a/obk0hnTlqqvnfldr6SjD4MydasI/0/di" border="0" ismap="true"></img></a><br/> <a href="http://feedads.g.doubleclick.net/~a/obk0hnTlqqvnfldr6SjD4MydasI/1/da"><img src="http://feedads.g.doubleclick.net/~a/obk0hnTlqqvnfldr6SjD4MydasI/1/di" border="0" ismap="true"></img></a></p><div class="feedflare"> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=pkCoMdUor7M:PTldNfnHokM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=pkCoMdUor7M:PTldNfnHokM:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=pkCoMdUor7M:PTldNfnHokM:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/PeteBrown?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=pkCoMdUor7M:PTldNfnHokM:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=pkCoMdUor7M:PTldNfnHokM:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=pkCoMdUor7M:PTldNfnHokM:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=pkCoMdUor7M:PTldNfnHokM:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PeteBrown?a=pkCoMdUor7M:PTldNfnHokM:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/PeteBrown?i=pkCoMdUor7M:PTldNfnHokM:gIN9vFwOqvQ" border="0"></img></a> </div><img src="http://feeds.feedburner.com/~r/PeteBrown/~4/pkCoMdUor7M" height="1" width="1"/> http://feedproxy.google.com/~r/PeteBrown/~3/pkCoMdUor7M/slides-and-code-from-my-vslive-silverlight-5-rest-wcf-web-api-mvc-talk Pete Brown 3466 2011-12-15T22:13:05 DecryptR–A Glass House Application http://feedproxy.google.com/~r/JesseLiberty-SilverlightGeek/~3/jFwWfLowsQQ/ Jesse Liberty [MS] 3459 2011-12-12T21:40:16