<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-1951153510791888567</atom:id><lastBuildDate>Thu, 16 Feb 2012 13:55:13 +0000</lastBuildDate><category>Microsoft</category><category>FAQ</category><category>installation</category><category>Windows 8</category><category>HowTo</category><category>VirtualBox</category><category>blogspot</category><category>.Net</category><category>DataGrid</category><category>UI</category><category>LCD</category><category>benchmark</category><category>conference</category><category>Apple</category><category>recap</category><category>Programming</category><category>array</category><category>FileFormat</category><category>Ribbon</category><category>C++</category><category>Text</category><category>HSV</category><category>set</category><category>PDC2008</category><category>cursor</category><category>UtahCodeCamp</category><category>comparison</category><category>Delphi</category><category>sports</category><category>class</category><category>resource</category><category>Win32</category><category>Debugging</category><category>firmware</category><category>WTF</category><category>Jolicloud</category><category>usability</category><category>rant</category><category>humor</category><category>arduino</category><category>ethernet</category><category>LINQ</category><category>router</category><category>nunchuck</category><category>Office</category><category>VisualStudio</category><category>AboutMe</category><category>object</category><category>wii</category><category>rave</category><category>stepper motor</category><category>CompilerBug</category><category>networking</category><category>hpebley3</category><category>trip</category><category>Binary</category><category>SplashScreen</category><category>C#</category><category>pascal</category><category>Interfaces</category><category>Reflection</category><category>ValueConverter</category><category>RGB</category><category>blogger</category><category>report</category><category>Linux</category><category>dictionary</category><category>Colors</category><category>design</category><category>UserExperience</category><category>references</category><category>kit</category><category>WWSGD</category><category>WPF</category><category>problem</category><category>binding</category><title>Skylark Software</title><description>Giving wings to the imagination</description><link>http://www.skylark-software.com/</link><managingEditor>noreply@blogger.com (Harley Pebley)</managingEditor><generator>Blogger</generator><openSearch:totalResults>54</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/SkylarkSoftware" /><feedburner:info uri="skylarksoftware" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>SkylarkSoftware</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1951153510791888567.post-2595429997719637609</guid><pubDate>Tue, 27 Sep 2011 12:00:00 +0000</pubDate><atom:updated>2011-09-27T06:00:09.503-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">HowTo</category><category domain="http://www.blogger.com/atom/ns#">problem</category><category domain="http://www.blogger.com/atom/ns#">C++</category><category domain="http://www.blogger.com/atom/ns#">Microsoft</category><title>How to fix Visual Studio C++ Warning: LINK4075</title><description>At the beginning of last week's sprint, I picked up a task to reduce our warning count. One of the issues that I scratched my head over a couple minutes was a bunch of warnings with the text &lt;em&gt;warning LNK4075: ignoring '/EDITANDCONTINUE' due to '/SomeOtherSetting' specification.&lt;/em&gt; As indicated by the LNK identifier, I knew the linker emitted this warning. However, in my perusal of the linker options, I couldn't find where the EDITANDCONTINUE setting existed. I even glanced through the other property pages looking for it.&lt;br /&gt;
&lt;br /&gt;
Per my wont, I searched the web and eventually found it based on some oblique references on a &lt;a href="http://stackoverflow.com/questions/1574367/lnk4075-ignoring-editandcontinue-due-to-opticf-specification"&gt;StackOverflow question&lt;/a&gt;. The reason I had trouble finding it? It's a compiler option. And it's not called EDITANDCONTINUE.&lt;br /&gt;
&lt;br /&gt;
This is controlled by the &lt;em&gt;Debug Information Format&lt;/em&gt; setting on the C/C++ General page. If the option is &lt;em&gt;Program Database and Edit and Continue,&lt;/em&gt; a.k.a. &lt;strong&gt;/ZI&lt;/strong&gt;, then the output obj files apparently have a flag embedded in them that is incompatible with certain settings in the linker. Hence, the linker emits the warnings when it hits these conditions. It would have been nice for the message to have contained the &lt;strong&gt;/ZI&lt;/strong&gt; option (which is what's used in the compiler) rather then than the EDITANDCONTINUE pseudo-option which isn't used anywhere, as near as I can tell.&lt;br /&gt;
&lt;br /&gt;
To fix this warning, either change the linker options that are incompatible with the &lt;strong&gt;/ZI&lt;/strong&gt; option or change the compiler option to something other than &lt;strong&gt;/ZI&lt;/strong&gt;, such as &lt;strong&gt;/Zi&lt;/strong&gt;. As of the time of this writing, the linker options incompatible with EDITANDCONTINUE include setting optimization to &lt;strong&gt;/OPT:REF&lt;/strong&gt; or &lt;strong&gt;/OPT:ICF&lt;/strong&gt;, turning off incremental compilation or setting one of &lt;/strong&gt;/ORDER&lt;/strong&gt;, &lt;strong&gt;/RELEASE&lt;/strong&gt; or &lt;strong&gt;/FORCE&lt;/strong&gt;. (These are from &lt;a href="http://msdn.microsoft.com/en-us/library/962ct2hz.aspx"&gt;this MSDN page.&lt;/a&gt;)&lt;br /&gt;
&lt;br /&gt;
Hope this helps someone.&lt;div class="blogger-post-footer"&gt;&lt;hr /&gt;  &lt;a href="http://skylark-software.com"&gt;Skylark Software&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1951153510791888567-2595429997719637609?l=www.skylark-software.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/VGlNVYZfE2Iml9yt90i-P3xyYs8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/VGlNVYZfE2Iml9yt90i-P3xyYs8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/VGlNVYZfE2Iml9yt90i-P3xyYs8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/VGlNVYZfE2Iml9yt90i-P3xyYs8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/SkylarkSoftware/~4/vPHjGUapsWo" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SkylarkSoftware/~3/vPHjGUapsWo/how-to-fix-visual-studio-c-warning.html</link><author>noreply@blogger.com (Harley Pebley)</author><thr:total>1</thr:total><feedburner:origLink>http://www.skylark-software.com/2011/09/how-to-fix-visual-studio-c-warning.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1951153510791888567.post-7367999940623349827</guid><pubDate>Fri, 23 Sep 2011 12:00:00 +0000</pubDate><atom:updated>2011-09-23T06:00:02.699-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">HowTo</category><category domain="http://www.blogger.com/atom/ns#">problem</category><category domain="http://www.blogger.com/atom/ns#">installation</category><category domain="http://www.blogger.com/atom/ns#">VirtualBox</category><category domain="http://www.blogger.com/atom/ns#">Windows 8</category><category domain="http://www.blogger.com/atom/ns#">Microsoft</category><title>Sharing folders with Windows 8 between VirtualBox machines</title><description>Currently Windows 8 runs just fine inside a VirtualBox machine. However, guest additions, the tools to enable certain useful features of VirutalBox, do not yet work with Windows 8. Today I wanted to use some Visual Studio projects from an existing Windows XP virtual machine in my new Windows 8 machine. The obvious first choice was to simply use a shared folder on the host in both virtual machines. However, this requires the guest additions, so I went looking for a work around.&lt;br /&gt;
&lt;br /&gt;
What I found to work was a second virtual hard drive. In VirtualBox, on my primary development machine, I created a new hard drive on the existing IDE controller. I then started the machine and went into Windows' device manager. The disk manager started the new disk wizard. After initialization, I created and formatted an NTFS partition. I then copied the files I wanted to work with to this new disk. Finally I shutdown this machine.&lt;br /&gt;
&lt;br /&gt;
Next, in VirturalBox, I added the same, new hard drive image as a second drive on the Window 8 box's SATA controller. (If you add the drive to the IDE controller, Windows 8 will try to boot to it first and fail with a bad image error.) When I booted Windows 8 and went into Explorer, the second drive showed up with all the data I'd copied to it.&lt;br /&gt;
&lt;br /&gt;
That's it, pretty simple and straight forward, but not the obvious (to me) first solution.&lt;br /&gt;
&lt;br /&gt;
Warning: I don't know what would happen if both virtual machines are run at the same time. I suspect (and hope) the second one started would get some sort of sharing violation and not allow the disk to be mounted. I can't imagine VirtualBox is smart enough to allow two machines to attach to the same vdi file at the same time without corrupting the data. However, it seems to work just fine as long as there is only one machine using the file at any given point of time.&lt;br /&gt;
&lt;br /&gt;
Hope this helps someone.&lt;br /&gt;
&lt;div class="blogger-post-footer"&gt;&lt;hr /&gt;  &lt;a href="http://skylark-software.com"&gt;Skylark Software&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1951153510791888567-7367999940623349827?l=www.skylark-software.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/vGm4fXQI76z9PmV7xVd2BNMpqPY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vGm4fXQI76z9PmV7xVd2BNMpqPY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/vGm4fXQI76z9PmV7xVd2BNMpqPY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vGm4fXQI76z9PmV7xVd2BNMpqPY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/SkylarkSoftware/~4/TYkn3qFotsc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SkylarkSoftware/~3/TYkn3qFotsc/sharing-folders-with-windows-8-between.html</link><author>noreply@blogger.com (Harley Pebley)</author><thr:total>0</thr:total><feedburner:origLink>http://www.skylark-software.com/2011/09/sharing-folders-with-windows-8-between.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1951153510791888567.post-3635120277838196386</guid><pubDate>Mon, 19 Sep 2011 12:00:00 +0000</pubDate><atom:updated>2011-09-19T21:32:37.228-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">UserExperience</category><category domain="http://www.blogger.com/atom/ns#">recap</category><category domain="http://www.blogger.com/atom/ns#">Windows 8</category><category domain="http://www.blogger.com/atom/ns#">Microsoft</category><title>First Thoughts Regarding Windows 8</title><description>&lt;p&gt;With all the hubbub around Microsoft's BUILD conference and the developer preview of Windows 8, I thought I'd grab a copy to check it out. This is what I found; it's going to be pretty short...&lt;/p&gt;

&lt;h3&gt;Installation&lt;/h3&gt;
&lt;p&gt;I downloaded a copy of Windows 8,&lt;sup&gt;&lt;small&gt;&lt;a href="#Win8firstImpression1"&gt;[1]&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt; created a new machine in VirtualBox, attached the downloaded ISO to the CD and booted the machine.&lt;sup&gt;&lt;small&gt;&lt;a href="#Win8firstImpression2"&gt;[2]&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt; It started the install OK and then hung part way through. After waiting awhile, I powered off the VM. On restart, it tried to do an install restart but this time give me a failure message. So I powered it down again and then back up. This time during the restart it showed me the partitions on the drive. I deleted all the previously created partitions and it finally ran through the install to the end. When it finished, it did the typical Windows reboot but hung during the reload. I turned the machine off, detached the ISO image from the CD and turned it back on. This time it booted just fine. It asked me a couple of standard questions, like user name and password and took me to a phone/tablet looking screen.&lt;/p&gt;

&lt;h3&gt;Cursor problems&lt;/h3&gt;
&lt;p&gt;At this point the cursor pretty much went wonky. Yes, that's a technical term. When moving the cursor from the host OS to the Windows 8 machine, the cursor would jump to an odd place and then jump back off the guest screen back to the host. It was pretty much unusable. I tried installing VirtualBox's guest additions. The installer asked all the startup questions but then stopped when I told it to begin the actual install saying it didn't support that version of Windows. I suppose that's not too surprising. As a last ditch effort, I moved the virtual screen off my large secondary screen to the laptop's smaller main screen and all of a sudden the cursor started working correctly. At this point I'm not sure if it's a problem with VirtualBox on the secondary screen or if it's a Windows 8 incompatibility or perhaps some of each. In any case, the cursor problem doesn't show up on the main screen and the mouse/keyboard capturing works as I'd expect; i.e. once the guest OS has control, you have to hit the Host button to get back out.&lt;/p&gt;

&lt;h3&gt;Operation&lt;/h3&gt;
&lt;p&gt;Once the cursor started working correctly, I played around with a bit. IE10 works pretty much like you'd expect a browser to although the UI is somewhat different in keeping with the Metro design. The biggest thing is the address bar is at the bottom of the screen. Other than that, it worked OK. Google returned search results. GMail showed me my mail. However, when I went to YouTube, it needed the Flash plug-in. I knew the Metro version of IE didn't support plug-ins, so I wasn't sure what would happen. But everything worked, sort of: clicking the link took me to Adobe's web site, downloading and installing worked just fine. Yet when I went back to YouTube, it still complained about no plug-in. I went to the desktop (one of the many tiles on the "start page"), clicked on the IE icon there and then navigated to YouTube. It worked. This is one of those differences between the Metro version and the desktop version. However, I had to know that going in, otherwise it would have simply looked like it didn't work. There was no indication saying the Metro version didn't support plug-ins or that the desktop version did.&lt;/p&gt;

&lt;p&gt;I tried clicking on some of the other tiles on the start page and didn't get too far. Most of them seem to need features unique to mobile devices. &lt;em&gt;Word Hunt&lt;/em&gt; wanted me to "bump" with a friend's device to initiate the connection. I assume that's some sort of bluetooth thing. &lt;em&gt;Labyrinth&lt;/em&gt; simply sat there staring at me. No instructions. Clicking, click-dragging and other random character presses yielded no results. I'm guessing it wanted some sort of tilt sensor input. The last thing I tried was &lt;em&gt;BitBox.&lt;/em&gt; I had high hopes of getting somewhere since it actually started with a mini-tutorial. My hopes were dashed on about the third step when told to do a pinch operation to continue. Um, how do you do multi-touch with a mouse?&lt;/p&gt;

&lt;p&gt;At that point I pretty much gave up and turned the thing off. That was a bit of an adventure itself. First I tried sending the power off signal from VirualBox. This is equivalent to pressing the power button on a typical PC/Laptop. Nothing happened. I looked around a bit for a shutdown option. All I could find was logout. I ended up going to the desktop and pressing Alt-F4. That has worked since at least Windows 3.1, and it still does. I got a familiar "what do you want to do? shutdown, restart" type dialog. (I have subsequently learned there is a power button that's available after you logout.)&lt;/p&gt;

&lt;h3&gt;Opinions&lt;/h3&gt;
&lt;p&gt;My first impression after about an hour of playing with it is that it seems fairly comparable to the iPad and Android regarding user experience. (I've played around with both these about as much as I have Windows 8.) Basically there are big squares that slide around and you can click on them. The applications open in full screen mode. Shrug. I guess some people might get excited about it. To me, it seems about the same as everything else on the market.&lt;/p&gt;

&lt;p&gt;What I find interesting about these devices is the infrastructure, development environment and community support that grows up around them. The iPad and Android ecosystems both have their strengths and weaknesses. I think it's too early to tell much about what will happen with the ecosystem around Windows 8. Will Microsoft learn from both their previous successes and mistakes, as well as those of Apple and Google, to become a market leader? Will they become another fairly equal player? Or will they become an also ran in this race?&lt;/p&gt;

&lt;p&gt;From an internal design perspective, I like the direction Microsoft is going better than Apple or Google. Apple has a split between the desktop/laptop OS X and the mobile device iOS. Google is trying to scale the mobile/browser experience to the desktop in ChromeOS. I think both these are weak strategies.&lt;/p&gt;

&lt;p&gt;Apple has two, separate code bases to maintain, much of which could probably be combined. I think long term this is going to cause compatibility problems much like Microsoft has had between the mobile/embedded Windows and the desktop version and more lately between WPF and Silverlight. Very similar systems with differing code bases have made the developer community pretty aggravated at times.&lt;/p&gt;

&lt;p&gt;Google has a similar problem with the bifurcation between Android and ChromeOS. Android probably has the potential for making a pretty nice desktop OS. Give some development effort, it'd be pretty comparable, from a design perspective, as Windows 8. The high-level design documents for both would look very similar. However, Google has decided to try to expand the browser into an operating system. I've experimented with ChromeOS and it works acceptably if all you want to do is available on the web. But frequently I want to use my computer off-line and the whole ecosystem is not up to this task. Perhaps in 5 years everything will be a web app. I doubt it though.&lt;/p&gt;

&lt;p&gt;Microsoft is pairing down the core of Windows and then placing different layers on top of it. From a design perspective this seems like the best long term solution. It has always appeared that desktop Windows was the first-class citizen and the embedded/phone OS by the same name (which only had passing resemblance to its big brother) was second-class. By putting a desktop UI on the same core as the mobile device UI, they can both become equal products, just for different markets. As a desktop developer, the biggest fear I have is, instead of raising the mobile UI to be equal to the desktop's, they are going to push the desktop down to second-class status. As it stands with this preview, the first and primary experience is the Metro look and feel. It works great on a tablet. I have yet to see it work well on a desktop. Without major changes to the current experience, I predict Windows 8 will work well on mobile devices but will not be adopted in the desktop world. Hmm, will Windows 8 make &lt;a href="http://www.google.com/search?q=the+year+of+the+linux+desktop"&gt;the year of the Linux desktop&lt;/a&gt; finally a reality?&lt;/p&gt;
&lt;h3&gt;Updates&lt;/h3&gt;
&lt;p&gt;The above all happened on Friday. Monday morning, I started the Windows 8 virtual machine. It hung during boot. I turned it off and tried again. Again it hung (at a different place) during boot. I deleted the image. Too much hassle at this point.&lt;/p&gt;
&lt;p&gt;Monday evening: I created a VirtualBox machine hosted on my MacBook Pro. Pretty much the same configuration as I had on the other one hosted in Windows 7: 50GB hard drive with about 2.5GB of memory. It installed perfectly the first time and so far has worked flawlessly. (Well, other than the weirdnesses of a touch based interface driven by a keyboard/mouse.)&lt;/p&gt;
&lt;hr/&gt;
&lt;div id="Win8firstImpression1" style="margin-left:2em;text-indent:-2em"&gt;1. Download &lt;a href="http://msdn.microsoft.com/en-us/windows/apps/br229516"&gt;Windows 8 preview here&lt;/a&gt;&lt;/div&gt;&lt;div id="Win8firstImpression2" style="margin-left:2em;text-indent:-2em"&gt;2. This is not intended to be a tutorial. There are already good tutorials to &lt;a href="http://www.pcworld.com/article/240119/how_to_download_and_install_windows_8_on_a_new_partition.html"&gt;install onto a hard drive&lt;/a&gt; and &lt;a href="http://www.pcworld.com/article/240117/how_to_download_and_install_windows_8_into_a_virtual_machine.html"&gt;into a virtual machine&lt;/a&gt; available.&lt;/div&gt;
&lt;div class="blogger-post-footer"&gt;&lt;hr /&gt;  &lt;a href="http://skylark-software.com"&gt;Skylark Software&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1951153510791888567-3635120277838196386?l=www.skylark-software.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/RNPr5BM3M9_eOQHa9tjP9LC38Qo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/RNPr5BM3M9_eOQHa9tjP9LC38Qo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/RNPr5BM3M9_eOQHa9tjP9LC38Qo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/RNPr5BM3M9_eOQHa9tjP9LC38Qo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/SkylarkSoftware/~4/PZ_PSqh4iKg" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SkylarkSoftware/~3/PZ_PSqh4iKg/first-thoughts-regarding-windows-8.html</link><author>noreply@blogger.com (Harley Pebley)</author><thr:total>0</thr:total><feedburner:origLink>http://www.skylark-software.com/2011/09/first-thoughts-regarding-windows-8.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1951153510791888567.post-311163776041816454</guid><pubDate>Thu, 14 Jul 2011 12:00:00 +0000</pubDate><atom:updated>2011-07-14T06:00:01.537-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">comparison</category><category domain="http://www.blogger.com/atom/ns#">Programming</category><category domain="http://www.blogger.com/atom/ns#">set</category><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">LINQ</category><category domain="http://www.blogger.com/atom/ns#">benchmark</category><title>LINQ and set notation</title><description>So I learned something today.&lt;br /&gt;
&lt;br /&gt;
It's been a long time since I had any classes dealing with sets. I vaguely remember discussions including Venn diagrams and odd notation that didn't have any relevance to any other context that I was familiar with, but they were also pretty cool to study and get to know. However, they're the types of things that have a highly technical, mathematically rigorous side to them and also the day-to-day intuitive side that I use. Not needing it on a regular basis, the finer points of set algebra quickly sink into the background and aren't easily recalled.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="float: right; margin-bottom: 0.5em; margin-left: 0.5em;"&gt;&lt;a href="http://www.flickr.com/photos/the_episodic_author/5936167552/" title="Intersection by The Episodic Author, on Flickr"&gt;&lt;img alt="Intersection" height="75" src="http://farm7.static.flickr.com/6026/5936167552_8a6fe2d0f2_t.jpg" width="100" /&gt;&lt;/a&gt;&lt;/div&gt;Today I needed to do some set manipulation. I knew LINQ had some set related methods in it, such as Intersect which gives only the items that are in both lists.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="float: right; margin-bottom: 1em; margin-left: 0.5em;"&gt;&lt;a href="http://www.flickr.com/photos/the_episodic_author/5936167562/" title="Union by The Episodic Author, on Flickr"&gt;&lt;img alt="Union" height="75" src="http://farm7.static.flickr.com/6125/5936167562_4bdb6a7da5_t.jpg" width="100" /&gt;&lt;/a&gt;&lt;/div&gt;And I knew it had the Union that gives all the items in both lists, without duplicates.&lt;br /&gt;
&lt;br /&gt;
Needing to find the differences between two lists, I suspected there was something to do that easily.&amp;nbsp;I had two string lists and needed the items from both lists that were only in one of the two lists. In other words, I needed the inverse of Intersect. First I looked at the options in the code completion list. Nothing jumped out at me. I couldn't recall the technical name so I did a web search for "LINQ intersect inverse" and found the Except method. The description sounded promising but, when I tried it, I didn't get what I expected. It only gave the things that were in the first list but not in the second list. In other words, it did not include the things in the second list that weren't in the first. Figuring the people who wrote these methods probably knew something about what they were doing, I went digging a little deeper.&lt;br /&gt;
&lt;br /&gt;
The next web search was for "set intersect inverse" that led me to a Wikipedia page on&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Intersection_%28set_theory%29)"&gt;set intersection&lt;/a&gt;. Scrolling to the bottom "see also" section, I saw &lt;a href="http://en.wikipedia.org/wiki/Complement_%28set_theory%29)"&gt;Complement&lt;/a&gt;. Ah-ha! That rang a bell from the distant past. Clicking on that link confirmed that Complement was in fact the difference between two sets.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="float: right; margin-bottom: 0.5em; margin-left: 0.5em;"&gt;&lt;a href="http://www.flickr.com/photos/the_episodic_author/5936167574/" title="RelativeComplement by The Episodic Author, on Flickr"&gt;&lt;img alt="RelativeComplement" height="75" src="http://farm7.static.flickr.com/6014/5936167574_1c4eba52a4_t.jpg" width="100" /&gt;&lt;/a&gt;&lt;/div&gt;And this is where I started to learn something new: there are multiple types of differences in set theory. In general, the Complement refers to things not in a given set. First, there's the relative complement as implemented by LINQ's Except method. This gives the things from one list that are not in the other list. For example, if &lt;em&gt;list1 = new List&amp;lt;string&gt; {"a", "b", "c"}&lt;/em&gt; and &lt;em&gt;list2 = new List&amp;lt;string&gt;{"b", "c", "d"}&lt;/em&gt; then &lt;em&gt;list1.Except(list2)&lt;/em&gt; will return "a".&lt;br /&gt;
&lt;br /&gt;
&lt;div style="float: right; margin-bottom: 0.5em; margin-left: 0.5em;"&gt;&lt;a href="http://www.flickr.com/photos/the_episodic_author/5935608821/" title="AbsoluteComplement by The Episodic Author, on Flickr"&gt;&lt;img alt="AbsoluteComplement" height="75" src="http://farm7.static.flickr.com/6126/5935608821_f641345480_t.jpg" width="100" /&gt;&lt;/a&gt;&lt;/div&gt;Second, there's the absolute complement. This is the universe of all things not in a given set. Hopefully it's obvious that this can't be implemented in software.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="float: right; margin-bottom: 0.5em; margin-left: 0.5em;"&gt;&lt;a href="http://www.flickr.com/photos/the_episodic_author/5936167594/" title="SymmetricDifference by The Episodic Author, on Flickr"&gt;&lt;img alt="SymmetricDifference" height="75" src="http://farm7.static.flickr.com/6127/5936167594_d922029d20_t.jpg" width="100" /&gt;&lt;/a&gt;&lt;/div&gt;Finally, there is the &lt;a href="http://en.wikipedia.org/wiki/Symmetric_difference"&gt;symmetric difference&lt;/a&gt;. This is the name of what I needed. It's the list of things that are in only one of two given sets. Thinking in terms of set operations, it's the relative complement between the union of the sets and the intersection of the sets. In LINQ terms it's &lt;em&gt;list1.Union(list2).Except(list1.Intersect(list2))&lt;/em&gt;. This got me what I want.&lt;br /&gt;
&lt;br /&gt;
Now that I had a technical term to search on, out of curiosity I tried "symmetric difference LINQ". (It's always easier to find what you're looking for when you know the proper keywords.) This returned a link to a &lt;a href="http://stackoverflow.com/questions/2404301/linq-find-differences-in-two-lists"&gt;StackOverflow question&lt;/a&gt; that not only gave the answer I came up with but also pointed out there's a SymmetricExceptWith method on the HashSet class.&lt;br /&gt;
&lt;br /&gt;
Curiosity now drove me to do a quick benchmark. Knowing LINQ has never been a speed demon, I assumed it probably wouldn't beat out the HashSet implementation. I threw together a quick console app that simply ran both the above LINQ query and HashSet.SymmetricExceptWith call on two short lists a million times and reported the elapsed times. I used three different types of input containers to see if that made much difference. Here's what I found...&lt;br /&gt;
&lt;table&gt;&lt;tr&gt;&lt;th&gt;Input type&lt;/th&gt;&lt;th&gt;Using LINQ&lt;/th&gt;&lt;th&gt;Using HashSet.SymmetricExceptWith&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;List&amp;lt;string&gt;&lt;/td&gt;&lt;td&gt;2.8 s&lt;/td&gt;&lt;td&gt;1.0 s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LinkedList&amp;lt;string&gt;&lt;/td&gt;&lt;td&gt;2.9 s&lt;/td&gt;&lt;td&gt;1.1 s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;HashSet&amp;lt;string&gt;&lt;/td&gt;&lt;td&gt;2.7 s&lt;/td&gt;&lt;td&gt;0.8 s&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;div class="blogger-post-footer"&gt;&lt;hr /&gt;  &lt;a href="http://skylark-software.com"&gt;Skylark Software&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1951153510791888567-311163776041816454?l=www.skylark-software.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/dQVfNQJjNO2mPnUb9M5MjdRkAb0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/dQVfNQJjNO2mPnUb9M5MjdRkAb0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/dQVfNQJjNO2mPnUb9M5MjdRkAb0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/dQVfNQJjNO2mPnUb9M5MjdRkAb0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/SkylarkSoftware/~4/gjfvamM1bqo" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SkylarkSoftware/~3/gjfvamM1bqo/linq-and-set-notation.html</link><author>noreply@blogger.com (Harley Pebley)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://farm7.static.flickr.com/6026/5936167552_8a6fe2d0f2_t.jpg" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://www.skylark-software.com/2011/07/linq-and-set-notation.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1951153510791888567.post-651835007111680365</guid><pubDate>Fri, 08 Jul 2011 12:00:00 +0000</pubDate><atom:updated>2011-07-08T06:00:05.588-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Delphi</category><category domain="http://www.blogger.com/atom/ns#">comparison</category><category domain="http://www.blogger.com/atom/ns#">pascal</category><category domain="http://www.blogger.com/atom/ns#">C#</category><title>Local procedures from Delphi in C#</title><description>Pascal has this nifty feature where you can declare procedures inside of procedures. Something like:&lt;br /&gt;
&lt;pre class="code"&gt;&lt;code&gt;procedure procA

    procedure procB
    begin
        // procedure B code here
    end;

begin
    // procedure A code here calling procB
end;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
It's not the type of thing I used a lot, but there were times where it came in handy. It was a nice thing to have in the tool belt even if it wasn't pulled out too often. A couple times I have wanted to do this in C# and have resorted to other means.&lt;br /&gt;
&lt;br /&gt;
Today while reading &lt;a href="http://www.johndcook.com/blog/2011/07/06/maybe-c-hasnt-jumped-the-shark-after-all/"&gt;an article by John Cook about C++&lt;/a&gt;, I realized this is trivially easy to do in C#: simply use named lambdas. It's one of those things that's so obviously simple and easy, I don't know why it didn't occur to me before.&lt;br /&gt;
&lt;br /&gt;
So, the above Pascal code could be written in C# like so:&lt;br /&gt;
&lt;pre class="code"&gt;&lt;code&gt;public void procA()
{
    Action procB = () =&gt; 
        {
            // procedure B code here
        }

    // procedure A code here calling procB()
}&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;hr /&gt;  &lt;a href="http://skylark-software.com"&gt;Skylark Software&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1951153510791888567-651835007111680365?l=www.skylark-software.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/r1OoCkvTM3f1dhM71Z4SvvOp9VE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/r1OoCkvTM3f1dhM71Z4SvvOp9VE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/r1OoCkvTM3f1dhM71Z4SvvOp9VE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/r1OoCkvTM3f1dhM71Z4SvvOp9VE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/SkylarkSoftware/~4/iF8EeExW00s" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SkylarkSoftware/~3/iF8EeExW00s/local-procedures-from-delphi-in-c.html</link><author>noreply@blogger.com (Harley Pebley)</author><thr:total>0</thr:total><feedburner:origLink>http://www.skylark-software.com/2011/07/local-procedures-from-delphi-in-c.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1951153510791888567.post-4421121613057774140</guid><pubDate>Thu, 09 Jun 2011 05:44:00 +0000</pubDate><atom:updated>2011-06-08T23:44:03.302-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">arduino</category><category domain="http://www.blogger.com/atom/ns#">stepper motor</category><category domain="http://www.blogger.com/atom/ns#">references</category><title>Stepper motor references</title><description>Recently I have been playing around with stepper motors on my Arduino. (An overview of one project is on &lt;a href="http://www.hookedonlight.com/2011/05/time-lapse-turntable-project.html"&gt;my photography blog&lt;/a&gt;.) Here's a list of online resources I've found helpful in my education:&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://www.ehow.com/how_4738199_wire-stepper-motor.html"&gt;How to wire a stepper motor&lt;/a&gt; has a good overview of the different types of steppers and how to identify the wires on an unknown motor.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://arduino.cc/en/Reference/StepperUnipolarCircuit"&gt;Circuits for Unipolar motors&lt;/a&gt; on the Arduino site uses a ULN2003 or ULN2004 chip. One circuit has a couple resistors and a diode to allow two pin control of the motor. The other uses only the chip but requires four pins. I built the two pin configuration and it worked flawlessly. Note: the ULN2003 will only source up to 500mA. Higher current motors will cause its magic smoke to escape.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://www.circuitstoday.com/stepper-motor-controller"&gt;Stepper motor controller&lt;/a&gt; circuit uses two logic chips, four each of resistors, transistors and diodes and is controlled by two pins. Since it uses discrete components, it's easily modified for higher current motors than the ULN2003/ULN2004 can support. I haven't built this one, but have the components to do so in the future.&lt;br /&gt;
&lt;br /&gt;
The &lt;a href="http://www.google.com/?q=28BYJ-48+stepper+motor"&gt;28BYJ-48 stepper motor&lt;/a&gt; is a really cheap, high resolution stepper motor that comes in both 5V and 12V ratings. Not sure how reliable it is, but so far in my experiments it has worked well. It has a 64:1 reduction gear head built into it, so it is pretty high torque for the current draw (I think it's spec'd to be around 250ma) and a whole lot of steps per revolution.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://www.stepperworld.com/Tutorials/pgBipolarTutorial.htm"&gt;Stepper Motors and Control&lt;/a&gt; is a good overview tutorial. It includes logic charts for different ways of driving stepper motors for different purposes: lower power, higher torque and higher number of steps. It also talks about identifying different types of steppers and how to select a current limiting resistor.&lt;br /&gt;
&lt;br /&gt;
I'll update this list if I find anything else that seems like it'd be good to have here.&lt;div class="blogger-post-footer"&gt;&lt;hr /&gt;  &lt;a href="http://skylark-software.com"&gt;Skylark Software&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1951153510791888567-4421121613057774140?l=www.skylark-software.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/sq0f85rLT08YkseNRI8mY-7zues/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/sq0f85rLT08YkseNRI8mY-7zues/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/sq0f85rLT08YkseNRI8mY-7zues/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/sq0f85rLT08YkseNRI8mY-7zues/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/SkylarkSoftware/~4/L2OH8v8WpAc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SkylarkSoftware/~3/L2OH8v8WpAc/stepper-motor-references.html</link><author>noreply@blogger.com (Harley Pebley)</author><thr:total>2</thr:total><feedburner:origLink>http://www.skylark-software.com/2011/06/stepper-motor-references.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1951153510791888567.post-7628792060756439193</guid><pubDate>Thu, 26 May 2011 12:00:00 +0000</pubDate><atom:updated>2011-05-26T06:00:03.162-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">WPF</category><category domain="http://www.blogger.com/atom/ns#">design</category><category domain="http://www.blogger.com/atom/ns#">cursor</category><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">resource</category><title>There and back again: A Cursor's tale</title><description>I've been working on UI code recently and have run into this quite a bit:&lt;br /&gt;
&lt;pre class="code"&gt;&lt;code&gt;Cursor = Cursors.Wait;
SomeLongRunningTask();
Cursor = Cursors.Default;&lt;/code&gt;&lt;/pre&gt;Pretty straight forward code. I see this type of thing a lot, not just in the C# code I'm working on now, but I've seen this in the past. In other languages. On other platforms. It's a common practice. The problem is it only works in some cases.&lt;br /&gt;
&lt;br /&gt;
This will have problems if any method in the "long running task" does the same thing. The cursor will be set back to default prematurely. Of course, this is easily solved by saving the old value prior to setting the new one.&lt;br /&gt;
&lt;pre class="code"&gt;&lt;code&gt;var oldCursor = Cursor;
Cursor = Cursors.Wait;
SomeLongRunningTask();
Cursor = oldCursor;&lt;/code&gt;&lt;/pre&gt;This is an improvement but will still fail if an exception is raised. This can be fixed with a try/finally.&lt;br /&gt;
&lt;pre class="code"&gt;&lt;code&gt;var oldCursor = Cursor;
Cursor = Cursors.Wait;
try
{
    SomeLongRunningTask();
}
finally            
{
    Cursor = oldCursor;
}&lt;/code&gt;&lt;/pre&gt;Ok. So now we have some code that works reasonably well. The issue now is one of code maintainability and clarity. Every method that needs to change the cursor needs to add nine lines before it can do any work of its own. It's nine lines where bugs could hide. It's nine lines obscuring the real purpose of the method. There's got to be a better way.&lt;br /&gt;
&lt;br /&gt;
Way back in my Delphi days, I had a small class which handled this chore for me. The constructor took a parameter containing the new cursor. The current cursor was saved in a class field, the cursor was changed and the constructor finished. The destructor simply set the cursor back to the saved value. In that environment, interfaces were reference counted and destroyed when the reference went to zero. The compiler took care of all the bookkeeping automatically. So I could create an instance of this class, store it in a local variable and, when the variable went out of scope, the object was destroyed, resetting the cursor. It worked really well. One line to change the cursor to whatever I wanted and it automatically reset to the original value when done. Pretty sweet.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, C# does not have any deterministic way of handling object lifetimes. This is one of my biggest frustrations with the language. The closest thing we have is the hack that is the using statement. Since this is the best we have, I have put together a class, shown below, similar to the one I had before. The constructor takes the new cursor value and control whose cursor should be changed, saves the current one and, in the Dispose method, resets it back. Now we can have three simple lines with one code block rather than the nine lines with two blocks. It's a big improvement although still not the single line like I'd prefer.&lt;br /&gt;
&lt;br /&gt;
In use, it looks like this:&lt;br /&gt;
&lt;pre class="code"&gt;&lt;code&gt;using ChangeCursor(this, Cursors.Wait)
{
    SomeLongRunningTask();
}&lt;/code&gt;&lt;/pre&gt;Arguably, this is a bit cleaner than even the first code snippet we started with.&lt;br /&gt;
&lt;br /&gt;
Since this takes a FrameworkElement, it's WPF specific. It'd be easy enough to change the type to work with WinForms, if needed. The same technique could be used to handle other things where a state needs to be set to one value and then reset when some unit of work is done. For example, if using TreeViews with BeginUpdate/EndUpdate pairs.&lt;br /&gt;
&lt;br /&gt;
Hope this helps someone.&lt;br /&gt;
&lt;pre class="code"&gt;&lt;code&gt;using System;
using System.Windows;
using System.Windows.Input;

namespace CursorResourceProtection
{
    public class ChangeCursor : IDisposable
    {
        private FrameworkElement Context { get; set; }
        private bool Disposed { get; set; }
        private Cursor OriginalCursor { get; set; }

        public ChangeCursor(FrameworkElement context, Cursor newCursor)
        {
            Disposed = false;
            Context = context;
            OriginalCursor = context.Cursor;
            context.Cursor = newCursor;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if(Disposed)
                return;

            Context.Cursor = OriginalCursor;
            Disposed = true;
        }

        ~ChangeCursor()
        {
            Dispose(false);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;hr /&gt;  &lt;a href="http://skylark-software.com"&gt;Skylark Software&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1951153510791888567-7628792060756439193?l=www.skylark-software.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/gnkIAYcqVuVWnIgmVWvfn-S95UA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/gnkIAYcqVuVWnIgmVWvfn-S95UA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/gnkIAYcqVuVWnIgmVWvfn-S95UA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/gnkIAYcqVuVWnIgmVWvfn-S95UA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/SkylarkSoftware/~4/rPVEIgNyDzQ" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SkylarkSoftware/~3/rPVEIgNyDzQ/there-and-back-again-cursors-tale.html</link><author>noreply@blogger.com (Harley Pebley)</author><thr:total>0</thr:total><feedburner:origLink>http://www.skylark-software.com/2011/05/there-and-back-again-cursors-tale.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1951153510791888567.post-3831508274048501953</guid><pubDate>Wed, 11 May 2011 12:00:00 +0000</pubDate><atom:updated>2011-07-07T12:01:01.586-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Delphi</category><category domain="http://www.blogger.com/atom/ns#">comparison</category><category domain="http://www.blogger.com/atom/ns#">array</category><category domain="http://www.blogger.com/atom/ns#">pascal</category><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">dictionary</category><title>Non-int array indexes from Delphi in C#</title><description>In Delphi, array indexes can be any type that resolves to an integer, not just integers. So for example, enum and bool types can be array indexes. This can be handy in many situations to reduce a if-then or switch construct to a simple assignment. A simple, contrived example:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="code"&gt;&lt;code&gt;
MyEnum = (item1, item2, item3);
...
function enumToString(value: MyEnum): string
begin
switch(value)
case item1: result = "Item one";
case item2: result = "Item two";
case item3: result = "Item three";
end;
end;
...
SomeLabel.Caption = enumToString(value);
...
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
becomes something like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="code"&gt;&lt;code&gt;
MyEnum = (item1, item2, item3);
enumToString[MyEnum]: string = ("Item one", "Item two", "Item three");
...
SomeLabel.Caption = enumToString[value];
...
&lt;/code&gt;&lt;/pre&gt;Not only does it reduce code, it also reduces possible bugs. Consider what happens when a value is added to MyEnum. The first example will simply return an empty string creating a possible silent failure that hopefully will be caught when tests are run. The second will generate a compiler error, forcing the programmer to intentionally decide what to do.&lt;br /&gt;
&lt;br /&gt;
In C#, array indexes must be one of the four integer types: int, uint, long or ulong. I really miss the ability to use bools and enums. While lamenting this lack as I looked at some code today similar to the original switch statement, I realized I could use a generic dictionary. The new code looks like this:&lt;br /&gt;
&lt;pre class="code"&gt;&lt;code&gt;
MyEnum = (item1, item2, item3);
enumToString = new Dictionary&lt;MyEnum, string&gt; = {{item1, "Item one"}, {item2, "Item two"}, {item3, "Item three")};
...
SomeLabel.Contents = enumToString[value];
...
&lt;/code&gt;&lt;/pre&gt;On one hand, it is a bit more wordy than the Delphi array; on the other, it's clearer how things are associated in the initializer. The biggest drawback is it doesn't have the compiler error when things are added to the enum. This is mitigated a bit by the runtime exception generated by a missing key; it's not quite as silent as just returning nothing in the original code. However, it still depends on good test coverage to find it.&lt;div class="blogger-post-footer"&gt;&lt;hr /&gt;  &lt;a href="http://skylark-software.com"&gt;Skylark Software&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1951153510791888567-3831508274048501953?l=www.skylark-software.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/rkHLWarBGwpSkjI9TUvKt-WEH7M/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rkHLWarBGwpSkjI9TUvKt-WEH7M/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/rkHLWarBGwpSkjI9TUvKt-WEH7M/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rkHLWarBGwpSkjI9TUvKt-WEH7M/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/SkylarkSoftware/~4/UCiuUDU3SfM" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SkylarkSoftware/~3/UCiuUDU3SfM/non-int-array-indexes-from-delphi-in-c.html</link><author>noreply@blogger.com (Harley Pebley)</author><thr:total>0</thr:total><feedburner:origLink>http://www.skylark-software.com/2011/05/non-int-array-indexes-from-delphi-in-c.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1951153510791888567.post-844740537704773291</guid><pubDate>Fri, 06 May 2011 13:00:00 +0000</pubDate><atom:updated>2011-05-06T07:00:07.866-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">HowTo</category><category domain="http://www.blogger.com/atom/ns#">arduino</category><category domain="http://www.blogger.com/atom/ns#">LCD</category><category domain="http://www.blogger.com/atom/ns#">kit</category><title>Arduino notebook: 16x2 LCD display (Part 2)</title><description>&lt;h3&gt;How to change the default behavior&lt;/h3&gt;&lt;h4&gt;Prologue&lt;/h4&gt;My &lt;a href="http://www.skylark-software.com/2011/02/arduino-notebook-16x2-lcd-display-part.html"&gt;last article&lt;/a&gt; in this series talked about why I chose Sparkfun's Serial Enabled LCD display kit and how to build it. One of the reasons it caught my eye was because it uses an Arduino as the controller for the display. I figured it was pretty busy doing nothing most of the time and thought it could be used for other purposes in addition to driving the display. Upon further investigation, it turns out I was right.&lt;br /&gt;
&lt;br /&gt;
Nicole, a friend of mine, recently e-mailed me about a photography project she was interested in doing but didn't want to spend the money for a professional rig to do some of the things involved. She asked if I had any ideas. I'd already given some thought to the problem, the investigation of which led me to the Arduino platform in the first place. This project was one I had stewing on the back burner for quite a while and it was now time to turn up the heat on it.&lt;br /&gt;
&lt;br /&gt;
One of the requirements was to be stand-alone. It had to allow for some user configuration at the time of use in battery mode, without any other devices attached. This ruled out the obvious easy solution of setting the parameters via USB through a computer. Also, it involved controlling a stepper motor. I immediately thought of the LCD kit. I knew I would at least use it for the display, and hopefully some toggle switches. I had a distant hope I could also use it for the motor control. Since this was going to be a pretty permanent build, I immediately ordered another LCD to use specifically for this project.&lt;br /&gt;
&lt;br /&gt;
After getting a new display on the way, I pulled out my first kit to take a look at it. Sure enough, it had a handful of empty holes on the PCB labeled with both digital and analog pin assignments. Cool. It had enough extra pins to accomodate everything I needed to do. So, I started work on the rest of the project while I waited for the LCD to arrive. (The other details of this project I'll write about in future articles here and on my photography blog &lt;a href="HookedOnLight.com"&gt;Hooked On Light&lt;/a&gt;.)&lt;br /&gt;
&lt;br /&gt;
First thing after getting the new kit, I assembled it. It went much faster this time with no of the frustrations I experienced on the first one. It actually worked the first time I applied power.&lt;br /&gt;
&lt;br /&gt;
One of the biggest things I did differently was to use ribbon cable between the display and controller boards. In some ways this made things easier and in other ways it was harder. I think on the next project I'll probably put the header pins that come with the kit in one board and get a socket to solder onto the other board. That will give me a cleaner build like the first one, but with the ability to separate the boards for easier access like I have with the ribbon cable on the second one.&lt;br /&gt;
&lt;br /&gt;
The &lt;a href="http://www.sparkfun.com/products/10097"&gt;web site to order the kit&lt;/a&gt; indicates the firmware can be reprogrammed with an FTDI Basic Breakout board. I had ordered one with the first kit, but hadn't had a chance to use it prior to this project. Knowing I needed to use this, I also purchased some 90 degree header pins from my local electronics parts supplier and soldered them into the holes on one end of the board designed for the purpose. This allowed the FTDI board to plug onto the controller board, providing a plug for a USB cable to be plugged in.&lt;br /&gt;
&lt;br /&gt;
Now I started looking for instructions on how to actually reprogram the thing. The order page indicated you needed to change a setting in the Arduino IDE and referenced the &lt;a href="https://github.com/jimbloom/Serial-LCD-Kit/wiki/Serial-Enabled-LCD-Kit-Datasheet"&gt;github page&lt;/a&gt; for further instructions. Well, the github page had no other instructions on programming the thing. All it talked about was how to use the board through the serial interface. The software for the firmware was also hosted there. Besides the one sentence on the order page, I couldn't find any other instructions either on those two sites or anywhere else via web searches on how to reprogram this kit.&lt;br /&gt;
&lt;h4&gt;Reprograming the kit&lt;/h4&gt;I figured, no guts, no glory and decided to experiment some. I downloaded the source code from github, loaded it in the Arduino IDE and made a simple change to the splash screen text. Since the splash screen is the first thing you see, I thought this would be an easy way to verify if my changes worked or not. In the IDE, as instructed on the order page, I changed the target machine to &lt;em&gt;Arduino Duemilanove or Nano w/ ATmega328&lt;/em&gt; and hit the upload button.&lt;br /&gt;
&lt;br /&gt;
It compiled.&lt;br /&gt;
&lt;br /&gt;
It uploaded.&lt;br /&gt;
&lt;br /&gt;
And when it reset after the upload, there was my new splash screen text.&lt;br /&gt;
&lt;br /&gt;
Amazing. That was all there was to reprogram the kit's default software. The reason I couldn't find any other instructions was, there weren't any other instructions needed.&lt;br /&gt;
&lt;h4&gt;Epilogue&lt;/h4&gt;After this success, it was simply a matter of changing things to do what I needed it to do for this project. Essentially, I ripped out everything the existing software does and replaced it with what I needed. There are a few lines to initialize the LCD and one function to write characters to the screen that are the same, but everything else is completely new.&lt;br /&gt;
&lt;br /&gt;
Now that I've found how easy this is to repurpose, I think I'll probably use it for other projects in the future too. It's an easy way to get an entire Arduino system up and running in a clean package with a simple user interface and minimal external support circuitry needed.&lt;div class="blogger-post-footer"&gt;&lt;hr /&gt;  &lt;a href="http://skylark-software.com"&gt;Skylark Software&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1951153510791888567-844740537704773291?l=www.skylark-software.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/PbNy070Zlm4RRVFayoXsYNnvHzE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/PbNy070Zlm4RRVFayoXsYNnvHzE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/PbNy070Zlm4RRVFayoXsYNnvHzE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/PbNy070Zlm4RRVFayoXsYNnvHzE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/SkylarkSoftware/~4/B3t-5vAAIvg" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SkylarkSoftware/~3/B3t-5vAAIvg/arduino-notebook-16x2-lcd-display-part.html</link><author>noreply@blogger.com (Harley Pebley)</author><thr:total>0</thr:total><feedburner:origLink>http://www.skylark-software.com/2011/05/arduino-notebook-16x2-lcd-display-part.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1951153510791888567.post-2792149913446370010</guid><pubDate>Mon, 21 Feb 2011 13:00:00 +0000</pubDate><atom:updated>2011-05-05T23:13:17.205-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">HowTo</category><category domain="http://www.blogger.com/atom/ns#">arduino</category><category domain="http://www.blogger.com/atom/ns#">problem</category><category domain="http://www.blogger.com/atom/ns#">LCD</category><category domain="http://www.blogger.com/atom/ns#">UI</category><category domain="http://www.blogger.com/atom/ns#">kit</category><title>Arduino notebook: 16x2 LCD display (Part 1)</title><description>As I experiment with my Arduino kit, I find I want an easy, self-contained way to display information. The system provides one easy method in the Serial object with its print functions to send things to the computer through the USB port. This works well in development phase when the computer is attached to the board. However, I want to be able to run the kit detached from the computer and still get feedback. When there's limited data, I can use LEDs. They can be on or off to provide one bit of information. Additionally, they can be blinked in various patterns to communicate more than one bit of data. However, this is more abstract than I want. It doesn't strike me as easy, either to program or to use. I just want to read something directly without resorting to Morse Code to get the information.&lt;br /&gt;
&lt;br /&gt;
I also don't want to spend much money.&lt;br /&gt;
&lt;br /&gt;
So, with these three requirements in mind, I searched around. It seemed an LCD display was the way to go, as I found a couple different options. The first is to connect the LCD directly to the Arduino kit. At about $10, it is an inexpensive choice. It requires a number of wires and a moderate amount of programming to drive the display. Yes, this meets the cost and self-contained requirements, but isn't as easy as I would like. The second option is a kit with one of these LCDs and support circuitry to allow me to simply hook power, ground and a single data line to my Arduino. It uses the same Serial object to display information as the computer uses to receive data via USB. So, it satisfies the easy requirement much better, is more self-contained than the bare LCD, and at $25, still doesn't break the bank.&lt;br /&gt;
&lt;br /&gt;
Upon further investigation, the support circuitry turns out to be an Arduino. I'm pretty sure this controller is sitting idle, spinning around doing nothing, most of the time. In addition to getting an LCD display, I believe this option in essence gives me a second Arduino that I might be able to reprogram to have additional features.&lt;br /&gt;
&lt;br /&gt;
With all this going for it, I purchased &lt;a href="http://www.sparkfun.com/products/10097"&gt;this kit&lt;/a&gt; from &lt;a href="http://www.sparkfun.com/index"&gt;SparkFun.com&lt;/a&gt;.&lt;br /&gt;
&lt;h3&gt;How to build a Sparkfun Serial Enabled LCD kit (LCD-10097)&lt;/h3&gt;&lt;h3&gt;Some assembly required&lt;/h3&gt;&lt;a href="http://www.flickr.com/photos/the_episodic_author/5409321475/" title="SparkFun Serial LCD kit - Step 1 by The Episodic Author, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5136/5409321475_615b49e42d_m.jpg" width="240" height="116" alt="SparkFun Serial LCD kit - Step 1" /&gt;&lt;/a&gt;&lt;br /&gt;
(Click any of the pictures for a larger view.)&lt;br /&gt;
&lt;br /&gt;
This is definitely a kit. It comes as seen above: a printed circuit board (PCB), some capacitors, a resistor, a crystal, a transistor, a potentiometer, a 28-pin chip, the LCD screen assembled on its own board and miscellaneous hardware. All this comes in a plastic bag in a box.&lt;br /&gt;
&lt;br /&gt;
There were no instructions with the kit, nor could I find any online. To make up for this, the circuit board was well marked with silk screened values for the components and orientation marks for items that have to go in one way. Since I have put together many electronics kits over the years, I wasn't intimidated by this at all. If you are new to building kits, not having instructions might put you off a bit. However, don't let it. It's really pretty simple if you know how to solder. I'll outline what I did below to help you along.&lt;br /&gt;
&lt;br /&gt;
As an overview, I basically installed the smallest components first and worked my way up to the larger ones.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;a href="http://www.flickr.com/photos/the_episodic_author/5409936270/" title="SparkFun Serial LCD kit - Step 2 by The Episodic Author, on Flickr"&gt;&lt;img src="http://farm5.static.flickr.com/4128/5409936270_6fd4007b86_t.jpg" width="100" height="48" alt="SparkFun Serial LCD kit - Step 2" /&gt;&lt;/a&gt;&lt;/div&gt;First, I installed the small, ceramic capacitors and the one resistor. There are two values for the capacitors. The capacitors labeled "220" go in the locations marked "22pF" on the PCB and "104" capacitors go in the locations marked "0.1uF". The resistor goes in the place marked for it. How these components are oriented on the board does not matter. Either lead can go in either hole.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;a href="http://www.flickr.com/photos/the_episodic_author/5409322577/" title="SparkFun Serial LCD kit - Step 3 by The Episodic Author, on Flickr"&gt;&lt;img src="http://farm5.static.flickr.com/4106/5409322577_239d85b3e3_t.jpg" width="100" height="48" alt="SparkFun Serial LCD kit - Step 3" /&gt;&lt;/a&gt;&lt;/div&gt;Next I added the transistor, crystal and electrolytic capacitor. The crystal can go in either way. The transistor and capacitor however need to be oriented correctly. For the transistor, make sure the flat side of the component matches the outline on the PCB. The capacitor has a light band with a minus sign in it running down one side. Make sure the lead next to this marking goes in the hole with the minus sign silk screened next to it on the PCB.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;a href="http://www.flickr.com/photos/the_episodic_author/5409937320/" title="SparkFun Serial LCD kit - Step 4 by The Episodic Author, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5173/5409937320_a305a832d1_t.jpg" width="100" height="48" alt="SparkFun Serial LCD kit - Step 4" /&gt;&lt;/a&gt;&lt;/div&gt;Following this, I added the power/data connector and the potentiometer. These pretty much can only go in one way. Just match the components to the silk screen outlines on the PCB.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;a href="http://www.flickr.com/photos/the_episodic_author/5409323637/" title="SparkFun Serial LCD kit - Step 5 by The Episodic Author, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5215/5409323637_0e5ddf1708_t.jpg" width="100" height="48" alt="SparkFun Serial LCD kit - Step 5" /&gt;&lt;/a&gt;&lt;/div&gt;After installing all the discrete components, I went to my local electronics store and picked up some DIP sockets. Generally, I don't like soldering IC chips onto boards directly. If I damage them with too much heat while soldering, or do something else stupid to cause them not to work, I don't want to go through the hassle of unsoldering all those connections to replace it. I've had to do that before and it's no fun.&lt;br /&gt;
&lt;br /&gt;
The store didn't have any 28-pin DIP sockets in the narrow variety, but two 14-pin ones will sit nicely next to each other without any problems. On the PCB, note the silk screened outline. One end has a flat edge and the other end has a divot taken out. By convention, the edge with the divot marks the end where pin one goes. The sockets should also have one end that's flat with the other end notched. It's best to put them in with the same orientation as the silk screen. This makes things much less confusing. After the sockets are soldered in place, the chip can be inserted into it. The chip also has a notch in one end. Just line up all the notches and everything should be good.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="float: right; margin-bottom: 1em; margin-left: 0.5em;"&gt;&lt;a href="http://www.flickr.com/photos/the_episodic_author/5409324239/" title="SparkFun Serial LCD kit - Step 6 by The Episodic Author, on Flickr"&gt;&lt;img src="http://farm5.static.flickr.com/4147/5409324239_c00942edba_m.jpg" width="240" height="116" alt="SparkFun Serial LCD kit - Step 6" /&gt;&lt;/a&gt;&lt;/div&gt;Finally, I did a good visual inspection of all my solder joints with a magnifying glass. The next step involves soldering the two boards together. Once this is done, it will be very hard to take them apart, so I wanted to be sure everything looked good.&lt;br /&gt;
&lt;br /&gt;
There are three primary things to look for:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Solder bridges. This is when solder spans two pads when it shouldn't. This is particularly easy to do on the pins for the IC sockets, but they can happen anywhere.&lt;/li&gt;
&lt;li&gt;Cold or missing solder joints. When working down a row of IC pins, it's easy to accidentally miss one. A cold joint is when one part of the joint, either the PCB pad or the component leg isn't hot enough to melt the solder but the other one is. Solder will flow onto one but not the other. Both cold joints and missing joints can cause intermittent or unreliable operation.&lt;/li&gt;
&lt;li&gt;Solder splatters. Sometimes solder will splatter or drop onto the board where it shouldn't be. Make sure there isn't any messy blobs anywhere. If you do find one, typically they'll just scratch off pretty easily.&lt;/li&gt;
&lt;/ol&gt;&lt;br /&gt;
After the visual inspection, I soldered the header to the LCD's PCB. Then I placed a small piece of cardboard between the two PCBs to function as a spacer. I placed the controller's PCB on the other side of the header's pins and made sure the two boards were parallel. I wrapped a bit of scrap wire around the assembly to hold them together while I soldered the two end pins. Once they were soldered, I took the wire off and finished soldering the rest of the pins to the controller board. When all the pins were done, I removed the cardboard and declared myself finished with the construction phase.&lt;br /&gt;
&lt;h3&gt;Batteries not included&lt;/h3&gt;Now that I had the physical assembly done, the next step was to hook it up to the Arduino. I went to the oracle of all things technical, Google. Unfortunately, with a moderate amount of searching, I didn't find any definitive instructions regarding what to do next. I found some forum postings that alluded to using the Serial object and some others that said to just hook it up, but didn't give any details.&lt;br /&gt;
&lt;br /&gt;
I figured I probably couldn't hurt anything too badly with a bit of guess work. The connector for the LCD was clearly marked with 5V, Gnd and Rx, so I connected the red wire to the 5V pin, black wire to the Gnd pin and the Rx wire to the Tx pin on the Arduino. Typically in serial communication, transmit on one device goes to receive on the other. With the normal trepidation that I always have turning on a kit for the first time, I plugged in the USB cable.&lt;br /&gt;
&lt;br /&gt;
The backlight came on and no smoke escaped. Well, that's a good first step. The SparkFun site points to some documentation on github, but it only talks about command sequences to control the LCD, it doesn't talk about how to talk to the LCD. It presupposes you know how to do that. I found a library that seemed to imply it worked with this kit, but didn't outright say it did. When I tried using some of the code from it, I got nothing. At this point I didn't know if it was a software problem or a hardware problem. I turned everything off, unconnected the LCD and took a magnifying glass to the kit. I looked at all the solder joints I could. Unfortunately, most were in the middle where I couldn't see. I examined all the legs on the chip going into the socket to make sure none of them got folded up underneath the package instead of going into the socket. They all looked good. I hooked everything back up and tried again. Nothing. I tried more searching online to see if I could find more information. Nothing. Arg. Frustrated, I set it aside for a week.&lt;br /&gt;
&lt;br /&gt;
When I came back to it, I rechecked all the hardware I could with the magnifying glass. I plugged it in and tried writing to it. Same result as before. The backlight came on but I couldn't get it to display anything. Looking at the library code, it seemed a bit suspect, but even if it was wrong, I thought I should still see something. I searched more online but found no new information. One last time I decided to take a look at the kit before contacting customer support. And then it hit me. Pin one was in the wrong position. I couldn't believe it, I'd stupidly put the chip in backwards. I pulled the chip out and put it in the correct way. This time when I applied power, it showed a splash screen. Oh, much, much better.&lt;br /&gt;
&lt;br /&gt;
I uploaded a program that I expected to put some data on the screen and it worked. Well, sort of. That code that looked suspect in the library I used didn't work properly. I suspect it was for some other serial controller with a different command set. I threw together some code based on the manufacturer's documentation on github and suddenly it worked properly. Woo, hoo!&lt;br /&gt;
&lt;h3&gt;Lessons learned&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;If you build this kit, expect to see a splash screen on power up. This will tell you if the board works or not, independent of serial communication.&lt;/li&gt;
&lt;li&gt;Make sure to get some sockets for the chip. I'm sure glad I did. It would have been a nightmare if I'd accidentally soldered the chip in backwards and then had to desolder first the header and then the chip itself to correct the mistake.&lt;/li&gt;
&lt;li&gt;If I ever build another one, I will get a plug for the header. This would allow the two boards to plug together rather than be soldered together. A ribbon cable could also be placed between them for more flexibility with mounting.&lt;/li&gt;
&lt;/ol&gt;&lt;br /&gt;
That's about it for this write up. Next for this project is to figure out the best way to communicate with it. I need to look at the library to see if I was using it wrong or if it really is designed for a different unit. After that, I plan to investigate reprogramming the LCD's controller to investigate using it for additional processing tasks.&lt;div class="blogger-post-footer"&gt;&lt;hr /&gt;  &lt;a href="http://skylark-software.com"&gt;Skylark Software&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1951153510791888567-2792149913446370010?l=www.skylark-software.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/zAzzJ_aMiNouLjViaOa1QG2leFg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/zAzzJ_aMiNouLjViaOa1QG2leFg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/zAzzJ_aMiNouLjViaOa1QG2leFg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/zAzzJ_aMiNouLjViaOa1QG2leFg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/SkylarkSoftware/~4/eO9qOzbGJHI" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SkylarkSoftware/~3/eO9qOzbGJHI/arduino-notebook-16x2-lcd-display-part.html</link><author>noreply@blogger.com (Harley Pebley)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://farm6.static.flickr.com/5136/5409321475_615b49e42d_t.jpg" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://www.skylark-software.com/2011/02/arduino-notebook-16x2-lcd-display-part.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1951153510791888567.post-6698417754031095145</guid><pubDate>Thu, 03 Feb 2011 13:00:00 +0000</pubDate><atom:updated>2011-02-03T06:00:29.280-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">sports</category><category domain="http://www.blogger.com/atom/ns#">humor</category><title>A Geek's Guide to Sports</title><description>I understand there is a big sports competition coming up this weekend. I don't know much about sports, but thought I'd share what I do know with my fellow geeks so they can be more informed around the office for water cooler conversations.&lt;br /&gt;
&lt;h3&gt;American Football&lt;/h3&gt;This is where two smart guys are mad at each other. They each have recruited two groups of really big supports. By "really big," I mean physically huge. Each group is trying to kill the other group's smart guy while at the same time trying to keep their smart guy from getting murdered by the opposing side's hit squad. They do this in a strange, alternating dance, where one team tries to kill the other's smart guy for a while and then they trade off and the second team tries to do in the first team's smart guy. To make their homicidal intents socially acceptable, they hide their true, life-ending goal behind a facade of moving an oblong ball from one end of a grassy expanse to the other.&lt;br /&gt;
&lt;h3&gt;Rugby&lt;/h3&gt;This is a variation of American Football, just without the smart guys.&lt;br /&gt;
&lt;h3&gt;Australian Football&lt;/h3&gt;This was developed in the southern hemisphere where everyone is upside down. I think the blood rushes to their heads since they've confused the rules. Like American Football and Rugby, there are two teams. However, half of each team plays American Football while the other half of each team plays Rugby.&lt;br /&gt;
&lt;h3&gt;Basketball&lt;/h3&gt;This is a track and field sport for tall people during the winter months when it's too cold to go outside. It involves a lot of running back and forth and back and forth (the track part) and jumping and heaving heavy objects (the field part) over their heads attempting to get it into a basket about the same size as the ball. All the while the other side is trying to stop the person with the ball. There are a couple guys running around dressed like zebras who randomly stop the action. Everyone gets angry at them. I think this has something to do with some hunting ritual that has slipped into the game. It's probably to remind us that sustenance is more important than games and we need to stop once in a while, come together and remember to focus on the hunt. Does zebra taste good? Seems like an odd animal to incorporate into the game.&lt;br /&gt;
&lt;h3&gt;Soccer&lt;/h3&gt;(This is known as Football in the rest of the world which actually makes more sense than what Americans call Football since it actually uses the feet whereas American Football uses the hands. Perhaps we should rename American Football to Handball. It'd certainly be more logical.) Anyway, soccer is just the same as Basketball except it's for short people who can't use their hands.&lt;br /&gt;
&lt;h3&gt;Hockey&lt;/h3&gt;This is soccer for people living in Canada where it's too cold for grass to grow. Since it's icy all the time, they play on frozen ponds while wearing skates. Other than that it's just like soccer. I think they must be really mad they have to play on ice since score is kept based on how much blood is shed.&lt;br /&gt;
&lt;h3&gt;Baseball&lt;/h3&gt;The strategy of this game is to play it so slow that you bore the other team into forfeiting. It's played with a small ball that, one by one, each team member tries to hit with a thin, long stick. Since these two items are both so small, they only come into contact randomly, thus prolonging the game. This is a great strategy to make the other team think they really are trying to move the game along when in fact it's simply a delaying tactic.&lt;br /&gt;
&lt;h3&gt;Cricket&lt;/h3&gt;The English have taken Baseball and really perfected the underlying goal of boring everyone. They obviously have much more patience that Americans though and have adapted the game to prolong it even further than the short-attention spans we have here in the colonies.&lt;br /&gt;
&lt;br /&gt;
Well, now that you're better informed, I hope that helps you the next time the topic of sports comes up in the lunch room or during hallway conversations.&lt;div class="blogger-post-footer"&gt;&lt;hr /&gt;  &lt;a href="http://skylark-software.com"&gt;Skylark Software&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1951153510791888567-6698417754031095145?l=www.skylark-software.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Rj2TXw9eeOkhURbM9HRv_PW1Y_M/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Rj2TXw9eeOkhURbM9HRv_PW1Y_M/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Rj2TXw9eeOkhURbM9HRv_PW1Y_M/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Rj2TXw9eeOkhURbM9HRv_PW1Y_M/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/SkylarkSoftware/~4/UX56sRcp1ho" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SkylarkSoftware/~3/UX56sRcp1ho/geeks-guide-to-sports.html</link><author>noreply@blogger.com (Harley Pebley)</author><thr:total>0</thr:total><feedburner:origLink>http://www.skylark-software.com/2011/02/geeks-guide-to-sports.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1951153510791888567.post-7190483486370797105</guid><pubDate>Mon, 31 Jan 2011 13:00:00 +0000</pubDate><atom:updated>2011-01-31T06:00:05.361-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">HSV</category><category domain="http://www.blogger.com/atom/ns#">arduino</category><category domain="http://www.blogger.com/atom/ns#">UserExperience</category><category domain="http://www.blogger.com/atom/ns#">usability</category><category domain="http://www.blogger.com/atom/ns#">class</category><category domain="http://www.blogger.com/atom/ns#">object</category><category domain="http://www.blogger.com/atom/ns#">Colors</category><category domain="http://www.blogger.com/atom/ns#">UI</category><category domain="http://www.blogger.com/atom/ns#">RGB</category><title>Arduino notebook: an RGB LED and the color wheel (Part 3)</title><description>In my &lt;a href="http://www.skylark-software.com/2011/01/arduino-notebook-rgb-led-and-color_21.html"&gt;last article,&lt;/a&gt; I demonstrated use of a potentiometer to control the hue of an RGB LED. In the HSV color space, the hue is one of three parameters controling the color. The other two are saturation and value. With a single control, there isn't a way to vary the other two parameters to give us a greater color range. In this article, I show one technique to control any of the three color variables.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Designing the input&lt;/h3&gt;But first, a short design discussion. In order to change what the potentiometer does, we need some method to change its mode of operation. I toyed with several ideas. My preferred method was three buttons: one button puts it in hue change mode, the second button puts it in saturation change mode and finally, the third button puts it in value change mode. The user would press a button and twist the potentiometer, setting that button's associated value. I like this because there is a one-to-one mapping between the buttons and the mode. It makes it easy for the user to understand and use. The problem: I only have two buttons.&lt;br /&gt;
&lt;br /&gt;
My next idea was no button pressed changes hue, one button pressed changes saturation and the other button pressed changes the value. However, as I thought this through, I realized this would not give the user a nice flow between modes since every time one of the buttons was released, the hue mode would be entered, setting it to whatever value the potentiometer was in for the end of the last mode. This would cause the colors to jump around as modes changed and the un-pressed mode, hue, would have to be changed last. This clearly would not work very well.&lt;br /&gt;
&lt;br /&gt;
After further thought, I hit upon the idea of using one button to cycle through the three modes with each button press and using the other button to enter that mode (or in other words, activate the potentiometer). Sort of like one button controls a menu and the other selects and deselects that menu option. To implement this, two additional LEDs are needed to indicate the mode and a third LED to indicate whether the potentiometer is enabled or not. This allows switching between modes without changing the output of the LED until the mode is selected. When the mode is exited, the LED would not change color as it would have in the previous scenario.&lt;br /&gt;
&lt;br /&gt;
I implemented this design. However, after building it, I didn't like it since a binary readout is used to indicate the mode. I considered this sub-optimal from a usability standpoint. How many people can read binary numbers? In addition to the usability issue, it required three LEDs in addition to the switches, increasing the parts count and clutter on the breadboard. It worked but just seemed pretty clunky.&lt;br /&gt;
&lt;br /&gt;
As I thought about it some more, I realized I could use the buttons directly in a binary pattern to select the mode and simply use a short delay before entering the mode. In other words, press and hold one button to change hue. Press and hold the other button to change saturation. Press and hold both buttons to change the value. I like this. It will reduce the parts count and eliminate a level of abstraction in the user interface; the buttons will directly control the mode. This is what I'll present below.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Hardware changes&lt;/h3&gt;Starting with the last circuit with in the previous article, I added two switches, two resistors and some jumpers. If you look at the schematic, pins 12 and 13 are connected to ground through a resistor when the switch is open. This means these two pins are normally in the LOW state when &lt;em&gt;digitalRead&lt;/em&gt; is called with their pin numbers. When the button is closed, they are connected to the 5V side and become HIGH. The resistor puts a load on the circuit when the button is closed. If the resistor is removed, a direct short between ground and power exists when the button closes; not a good thing to do.&lt;br /&gt;
&lt;br /&gt;
That's it. Pretty simple circuit changes.&lt;a href="http://www.flickr.com/photos/the_episodic_author/5403198173/" title="RGB LED color wheel with HSV controls by The Episodic Author, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5052/5403198173_28ae6c244f.jpg" width="379" height="500" alt="RGB LED color wheel with HSV controls" /&gt;&lt;/a&gt;&lt;br /&gt;
Click the image for a larger view or &lt;a href="http://www.flickr.com/photos/the_episodic_author/5403796314/" title="RGB LED color wheel with HSV controls by The Episodic Author, on Flickr"&gt;here for a schematic.&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Software changes&lt;/h3&gt;The software changes are a bit more involved. First, the simple part, I added two declarations for the pins. The next change is a semi-advanced technique, but first a bit of analysis.&lt;br /&gt;
&lt;br /&gt;
There are two buttons. For each button, the software needs to time how long the user has pressed it and, when they have held it down long enough, switch into active mode. To do this, each button requires a timer and a memory of the last button state. The code is the same for both, but the memory to track their status needs to be separate.&lt;br /&gt;
&lt;br /&gt;
To facilitate this type of design, where there are two sections of memory with the same functions working on it, I used something called a class. Put simply, a class associates data with code. To create a class, start with the &lt;em&gt;class&lt;/em&gt; keyword followed by the name of the class. This is the name you as a programmer decide to call it. Since this class contains the state information for a mode switch, I called the class &lt;em&gt;ModeSwitchState&lt;/em&gt;.&lt;br /&gt;
&lt;br /&gt;
Next, I defined the state information tracked for each switch. This includes the pin the switch is connected to, a timer to track when the last change was made to the switch's state and the switch's last value (i.e. was it pressed or not). These three things are what are called private variables, as indicated by the &lt;em&gt;private&lt;/em&gt; keyword. This means nothing outside of functions defined in the class can access their values. The big, technical term for this is &lt;em&gt;data encapsulation&lt;/em&gt;. All that means is it's harder to accidentally change the wrong thing because the only things that can get to the memory is this one class.&lt;br /&gt;
&lt;br /&gt;
After I defined the private memory, I created two functions that any code can use. The first is what's called the constructor. This simply means it's the function that is called when a new variable of this type is created. In this case, the constructor takes a parameter to indicate the Arduino pin the rest of the functions will use. Since the pin variable is private, this is the only way to set its value. The idea is you create a variable of this class type for each button to be controlled. The constructor also sets initial values for the other variables and calls pinMode for the pin it reads.&lt;br /&gt;
&lt;br /&gt;
Finally, I wrote a function to read the current value of the pin and, if it's different from the last value, reset the timer and the last value read variables. It then returns true if the button is pressed and the difference between the timer and the current time is greater than 500 ms. Otherwise it will return false.&lt;br /&gt;
&lt;br /&gt;
That's it for the definition of this class. Next, I created two variables of this class type, called &lt;em&gt;modeSwitch1&lt;/em&gt; and &lt;em&gt;modeSwitch2&lt;/em&gt;. The constructor is called with the values of the pin assignment previously defined.&lt;br /&gt;
&lt;br /&gt;
And that's it for the advanced stuff. All the other changes are in the loop function.&lt;br /&gt;
&lt;br /&gt;
First the loop gets the current mode state of each switch. Remember, since this is calling the function on the class, all the timer code is neatly tucked away out of sight from the main processing loop. All we have to do now is worry about getting the current value as defined by the &lt;em&gt;readModeSwitch&lt;/em&gt; function. That's done by the first two lines.&lt;br /&gt;
&lt;br /&gt;
Next I check to see if either of the switches are currently active. If so, then the potentiometer is read. Following this, either hue, saturation or value is changed to the pot's value based on which combination of switches are pressed. The case where both switches are pressed needs to be checked first, followed by the test for a single switch. If neither of these conditions are met, then the other switch must be pressed and its associated value changed.&lt;br /&gt;
&lt;br /&gt;
Finally, after all this, the RGB color is computed and the LED is set to that color.&lt;br /&gt;
&lt;br /&gt;
If neither switch is pressed, then nothing happens, the loop exits and immediately begins again.&lt;br /&gt;
&lt;br /&gt;
Here's the final code.&lt;br /&gt;
&lt;pre class="code"&gt;&lt;code&gt;int ledPins[] = { 11, 9, 10 };
int analogPin = 0;
int modeBit0pin = 12;
int modeBit1pin = 13;

int hueValue = 0;
double satValue = 1.0;
double lumValue = 1.0;

class ModeSwitchState
{
  private:
    int pin;
    long timer;
    boolean lastValue;

  public:
    ModeSwitchState(int switchPin)
      : pin(switchPin), timer(0), lastValue(false)
    {
      pinMode(pin, OUTPUT);
    }
    
    boolean readModeSwitch()
    {
      boolean curValue = digitalRead(pin) == HIGH;
      if (curValue != lastValue)
      {
        lastValue = curValue;
        timer = millis();
      }
      return curValue &amp;&amp; ((millis() - timer) &gt; 500);
    }
};

ModeSwitchState modeSwitch1(modeBit0pin), modeSwitch2(modeBit1pin);

void setup()
{
  pinMode(analogPin, INPUT);
  
  for(int i = 0; i &lt; 3; i++)
    pinMode(ledPins[i], OUTPUT);
}

void loop()
{
  boolean mode1enabled = modeSwitch1.readModeSwitch();
  boolean mode2enabled = modeSwitch2.readModeSwitch();
  
  if (mode1enabled || mode2enabled)
  {
    int analogValue = analogRead(analogPin);

    if (mode1enabled &amp;&amp; mode2enabled)
        hueValue = map(analogValue, 0, 1024, 0, 360);
    else if (mode1enabled)
        satValue = analogValue / 1024.0;
    else
        lumValue = analogValue / 1024.0;
  
    byte* colors = hsvToRgb(hueValue, satValue, lumValue);
    setColor(ledPins, colors);
  }
}

void setColor(int* led, const byte* color)
{
  for(int i = 0; i &lt; 3; i++)
    analogWrite(led[i], 255-color[i]);
}

byte rgb[3];
byte* hsvToRgb(int h, double s, double v)
{
        // Make sure our arguments stay in-range
        h = max(0, min(360, h));
        s = max(0, min(1.0, s));
        v = max(0, min(1.0, v));
        if(s == 0)
        {
                // Achromatic (grey)
                rgb[0] = rgb[1] = rgb[2] = round(v * 255);
                return rgb;
        }
        double hs = h / 60.0; // sector 0 to 5
        int i = floor(hs);
        double f = hs - i; // factorial part of h
        double p = v * (1 - s);
        double q = v * (1 - s * f);
        double t = v * (1 - s * (1 - f));
        double r, g, b;
        switch(i)
        {
                case 0:
                        r = v;
                        g = t;
                        b = p;
                        break;
                case 1:
                        r = q;
                        g = v;
                        b = p;
                        break;
                case 2:
                        r = p;
                        g = v;
                        b = t;
                        break;
                case 3:
                        r = p;
                        g = q;
                        b = v;
                        break;
                case 4:
                        r = t;
                        g = p;
                        b = v;
                        break;
                default: // case 5:
                        r = v;
                        g = p;
                        b = q;
        }
        rgb[0] = round(r * 255.0);
        rgb[1] = round(g * 255.0);
        rgb[2] = round(b * 255.0);
        
        return rgb;
}&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;Conclusion and downloads&lt;/h3&gt;That's about all I'm going to do with the RGB LED for now. The source code for this and the past two articles can be downloaded here:&lt;ul&gt;&lt;li&gt;&lt;a href="http://dl.dropbox.com/u/15523784/SkylarkSoftware/ArduinoNotebook/RGB_LED_colorWheel_part1.pde"&gt;Arduino notebook: an RGB LED and the color wheel (Part 1)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://dl.dropbox.com/u/15523784/SkylarkSoftware/ArduinoNotebook/RGB_LED_colorWheel_part2.pde"&gt;Arduino notebook: an RGB LED and the color wheel (Part 2)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://dl.dropbox.com/u/15523784/SkylarkSoftware/ArduinoNotebook/RBG_LED_colorWheel_part3.pde"&gt;Arduino notebook: an RGB LED and the color wheel (Part 3)&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;
In the next article I will talk about the joys and sorrows of building a simple LCD kit to use with the Arduino.&lt;div class="blogger-post-footer"&gt;&lt;hr /&gt;  &lt;a href="http://skylark-software.com"&gt;Skylark Software&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1951153510791888567-7190483486370797105?l=www.skylark-software.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/rJG9ZvGF1CDW5qdaogZ2SlY3fwo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rJG9ZvGF1CDW5qdaogZ2SlY3fwo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/rJG9ZvGF1CDW5qdaogZ2SlY3fwo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rJG9ZvGF1CDW5qdaogZ2SlY3fwo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/SkylarkSoftware/~4/cUsKi8CzBus" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SkylarkSoftware/~3/cUsKi8CzBus/arduino-notebook-rgb-led-and-color_31.html</link><author>noreply@blogger.com (Harley Pebley)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://farm6.static.flickr.com/5052/5403198173_28ae6c244f_t.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://www.skylark-software.com/2011/01/arduino-notebook-rgb-led-and-color_31.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1951153510791888567.post-9041757747783625338</guid><pubDate>Fri, 21 Jan 2011 13:00:00 +0000</pubDate><atom:updated>2011-01-21T06:00:08.746-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">HSV</category><category domain="http://www.blogger.com/atom/ns#">arduino</category><category domain="http://www.blogger.com/atom/ns#">Colors</category><category domain="http://www.blogger.com/atom/ns#">RGB</category><title>Arduino notebook: an RGB LED and the color wheel (Part 2)</title><description>In the last &lt;a href="http://www.skylark-software.com/2011/01/arduino-notebook-rgb-led-and-color.html"&gt;Arduino Notebook article,&lt;/a&gt; I showed how to take one of the standard tutorials and modify the sketch to do something a bit different than given. I've updated that article with breadboard and schematic diagrams.&lt;br /&gt;
&lt;br /&gt;
In this article I'll add a potentiometer that came with my kit to allow additional control over the LED. With this new input, I'll show how to use it to control two different aspects of the LED. First, I will change the sketch so the potentiometer controls the speed the LED cycles through the color wheel. At one end it will be so fast it will look more like a rapid switch between a reddish color and a blueish color. At the other extreme end, it will take about 30 seconds to cycle all the way through.&lt;br /&gt;
&lt;br /&gt;
Second, I will make the position of the potentiometer control the color. So, as you turn the control, it will change to the hue represented by that position of the control. In other words at the starting position it will be red. Turn it one third of the way and it'll be green. Another one third and it will be blue. Turn it all the way to the end and it'll go back to red.&lt;br /&gt;
&lt;br /&gt;
So, let's get started.&lt;br /&gt;
&lt;br /&gt;
First, I place a potentiometer on the breadboard so each of the three pins is in a separate row of the breadboard. Then I connect one side to ground and the other side to 5V. The middle pin I connect to the Arduino's analog 0 pin. That's it for the hardware. It should look something like this.&lt;br /&gt;
&lt;a href="http://www.flickr.com/photos/the_episodic_author/5374797794/" title="RGB LED color wheel with pot_bb by The Episodic Author, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5208/5374797794_f04c476532.jpg" width="369" height="500" alt="RGB LED color wheel with pot_bb" /&gt;&lt;/a&gt;&lt;br/&gt;Click the image for a larger view or &lt;a href="http://www.flickr.com/photos/the_episodic_author/5374797738/in/photostream/"&gt;here for a schematic.&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Ok, now for the software.&lt;br /&gt;
&lt;br /&gt;
The first set of changes will let the potentiometer change the speed the LED cycles through the color wheel. Starting with the sketch I ended with in the previous article, in the setup function, I add a call to initialize pin 0 for input. Next I change the loop to get the current value of the analog pin. This value will be from 0 to 1024 depending on the position of the potentiometer. Since I want the total time to cycle through the colors to be 30 seconds and there are 360 steps, then each step should take 83 milliseconds. To convert the number read from pin 0 from one range to another the Arduino has a function called map. This is much easier to use than doing the math to handle the conversion. So, I call this function with the value read from the potentiometer and the beginning and ending values of the two ranges. The result is fed into the delay in the loop. Compile and upload to the Arduino and now the potentiometer controls the speed.&lt;pre class="code"&gt;&lt;code&gt;int ledPins[] = { 11, 9, 10 };
int inputPin = 0;

void setup()
{
  pinMode(inputPin, INPUT);
  for(int i = 0; i &lt; 3; i++)
    pinMode(ledPins[i], OUTPUT);
}

void loop()
{
  int inputValue = analogRead(inputPin);
  int delayValue = map(inputValue, 0, 1024, 0, 83);

  setHueValue(computeNextValue());
  
  delay(delayValue);
}

int colorValue = 0;

int computeNextValue()
{
  colorValue = (colorValue+1) % 360;
  return colorValue;
}

void setHueValue(int hueValue)
{
  setColor(ledPins, hsvToRgb(hueValue, 1, 1));
}

void setColor(int* led, const byte* color)
{
  for(int i = 0; i &lt; 3; i++)
    analogWrite(led[i], 255-color[i]);
}

byte rgb[3];

byte* hsvToRgb(int h, double s, double v)
{
        // Make sure our arguments stay in-range
        h = max(0, min(360, h));
        s = max(0, min(1.0, s));
        v = max(0, min(1.0, v));
        if(s == 0)
        {
                // Achromatic (grey)
                rgb[0] = rgb[1] = rgb[2] = round(v * 255);
                return rgb;
        }
        double hs = h / 60.0; // sector 0 to 5
        int i = floor(hs);
        double f = hs - i; // factorial part of h
        double p = v * (1 - s);
        double q = v * (1 - s * f);
        double t = v * (1 - s * (1 - f));
        double r, g, b;
        switch(i)
        {
                case 0:
                        r = v;
                        g = t;
                        b = p;
                        break;
                case 1:
                        r = q;
                        g = v;
                        b = p;
                        break;
                case 2:
                        r = p;
                        g = v;
                        b = t;
                        break;
                case 3:
                        r = p;
                        g = q;
                        b = v;
                        break;
                case 4:
                        r = t;
                        g = p;
                        b = v;
                        break;
                default: // case 5:
                        r = v;
                        g = p;
                        b = q;
        }
        rgb[0] = round(r * 255.0);
        rgb[1] = round(g * 255.0);
        rgb[2] = round(b * 255.0);
        return rgb;
}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
The second set of changes let the potentiometer set the color. This is a really simple change. Everything is done in the loop function. Remember, setColorWheel takes a value in the range 0 to 360 representing the angle of the hue on the color wheel. All that needs to be done is to change the second range in the map function to end at 360 instead of 83. The result is now fed into the setColorWheel function instead of computeNextValue. And finally, the time delay is removed and the computeNextValue can be deleted.&lt;br /&gt;
&lt;br /&gt;
And that's it. Pretty simple changes and now the potentiometer can be used to set the color.&lt;pre class="code"&gt;&lt;code&gt;int ledPins[] = { 11, 9, 10 };
int inputPin = 0;

void setup()
{
  pinMode(inputPin, INPUT);
  for(int i = 0; i &lt; 3; i++)
    pinMode(ledPins[i], OUTPUT);
}

void loop()
{
  int inputValue = analogRead(inputPin);
  int hueValue = map(inputValue, 0, 1024, 0, 360);

  setHueValue(hueValue);
}

void setHueValue(int hueValue)
{
  setColor(ledPins, hsvToRgb(hueValue, 1, 1));
}

void setColor(int* led, const byte* color)
{
  for(int i = 0; i &lt; 3; i++)
    analogWrite(led[i], 255-color[i]);
}

byte rgb[3];

byte* hsvToRgb(int h, double s, double v)
{
        // Make sure our arguments stay in-range
        h = max(0, min(360, h));
        s = max(0, min(1.0, s));
        v = max(0, min(1.0, v));
        if(s == 0)
        {
                // Achromatic (grey)
                rgb[0] = rgb[1] = rgb[2] = round(v * 255);
                return rgb;
        }
        double hs = h / 60.0; // sector 0 to 5
        int i = floor(hs);
        double f = hs - i; // factorial part of h
        double p = v * (1 - s);
        double q = v * (1 - s * f);
        double t = v * (1 - s * (1 - f));
        double r, g, b;
        switch(i)
        {
                case 0:
                        r = v;
                        g = t;
                        b = p;
                        break;
                case 1:
                        r = q;
                        g = v;
                        b = p;
                        break;
                case 2:
                        r = p;
                        g = v;
                        b = t;
                        break;
                case 3:
                        r = p;
                        g = q;
                        b = v;
                        break;
                case 4:
                        r = t;
                        g = p;
                        b = v;
                        break;
                default: // case 5:
                        r = v;
                        g = p;
                        b = q;
        }
        rgb[0] = round(r * 255.0);
        rgb[1] = round(g * 255.0);
        rgb[2] = round(b * 255.0);
        return rgb;
}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
All in all, I think this demonstrates pretty well how a small amount of hardware and some trivial software changes can provide very different end user results. The combination of hardware and software that Arduino makes available to the experimenter I find really cool.&lt;br /&gt;
&lt;br /&gt;
Next time, I have some other ideas to add another input method to this circuit and some minor tweaks in software to increase the range of colors that can be generated by the RGB LED.&lt;div class="blogger-post-footer"&gt;&lt;hr /&gt;  &lt;a href="http://skylark-software.com"&gt;Skylark Software&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1951153510791888567-9041757747783625338?l=www.skylark-software.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/aDytmWZC9L_kq22vzX0BQW09zXc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/aDytmWZC9L_kq22vzX0BQW09zXc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/aDytmWZC9L_kq22vzX0BQW09zXc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/aDytmWZC9L_kq22vzX0BQW09zXc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/SkylarkSoftware/~4/DFcHx9Tjpeo" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SkylarkSoftware/~3/DFcHx9Tjpeo/arduino-notebook-rgb-led-and-color_21.html</link><author>noreply@blogger.com (Harley Pebley)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://farm6.static.flickr.com/5208/5374797794_f04c476532_t.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://www.skylark-software.com/2011/01/arduino-notebook-rgb-led-and-color_21.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1951153510791888567.post-9157228462768723738</guid><pubDate>Tue, 18 Jan 2011 13:00:00 +0000</pubDate><atom:updated>2011-01-20T23:38:49.465-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">HSV</category><category domain="http://www.blogger.com/atom/ns#">arduino</category><category domain="http://www.blogger.com/atom/ns#">Colors</category><category domain="http://www.blogger.com/atom/ns#">RGB</category><title>Arduino notebook: an RGB LED and the color wheel (Part 1)</title><description>As I recently &lt;a href="http://www.skylark-software.com/2011/01/let-games-begin-my-own-microcontroller.html"&gt;wrote about&lt;/a&gt;, I received a new Arduino experimental kit a couple weeks ago for Christmas. In a simple learning phase, last weekend I built one of the projects in the getting started book and then expanded on it to make it do a bit more.&lt;br /&gt;&lt;br /&gt;The project was to control a RGB LED that came with the kit. A RGB LED basically has three LEDs in a single physical package. The LEDs have a common anode so the package has four leads coming out of it. One you connect to +5V and each of the others you connect to its own pin on the Arduino through a resistor. This configuration allows you to turn on each color individually by setting that color's pin off (to ground). If the pin is set on, the voltage is +5V and the LED will turn off since there is no current going through the LED. This is a bit backwards from normal intuition, but it makes sense if you understand what's happening with the voltage/current.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.flickr.com/photos/the_episodic_author/5374166595/" title="RGB LED color wheel_bb by The Episodic Author, on Flickr"&gt;&lt;img src="http://farm6.static.flickr.com/5207/5374166595_a43d52159b.jpg" width="436" height="500" alt="RGB LED color wheel_bb" /&gt;&lt;/a&gt;Click image to see larger. Here's &lt;a href="http://www.flickr.com/photos/the_episodic_author/5374766892/in/photostream/"&gt;a schematic view.&lt;/a&gt;&lt;br/&gt;&lt;br /&gt;I started with a simple circuit as shown in CIRC-12 &lt;a href="http://www.ardx.org/src/circ/CIRC00-sheet-ADAF.pdf"&gt;here&lt;/a&gt;. &lt;em&gt;[Update: also shown above.]&lt;/em&gt; It simply consists of the LED connected to +5V on its anode and three resistors on the other legs. The other side of the resistors are connected to three pins on the controller. Pretty simple stuff. I then entered the following program from the manual and ran it.&lt;pre class="code"&gt;&lt;code&gt;int ledPins[] = { 9, 10, 11 };&lt;br /&gt;int inputPin = 0;&lt;br /&gt;&lt;br /&gt;const boolean ON = LOW;&lt;br /&gt;const boolean OFF = HIGH;&lt;br /&gt;&lt;br /&gt;const boolean RED[] = {ON, OFF, OFF};&lt;br /&gt;const boolean GREEN[] = {OFF, ON, OFF};&lt;br /&gt;const boolean BLUE[] = {OFF, OFF, ON};&lt;br /&gt;const boolean YELLOW[] = {ON, ON, OFF};&lt;br /&gt;const boolean CYAN[] = {OFF, ON, ON};&lt;br /&gt;const boolean MAGENTA[] = {ON, OFF, ON};&lt;br /&gt;const boolean WHITE[] = {ON, ON, ON};&lt;br /&gt;const boolean BLACK[] = {OFF, OFF, OFF};&lt;br /&gt;const boolean* COLORS[] = {RED, YELLOW, GREEN, CYAN, BLUE, MAGENTA, WHITE, BLACK};&lt;br /&gt;&lt;br /&gt;void setup()&lt;br /&gt;{&lt;br /&gt;for(int i = 0; i &lt; 3; i++)&lt;br /&gt;    pinMode(ledPins[i], OUTPUT);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void loop()&lt;br /&gt;{&lt;br /&gt;  //setColor(ledPins, YELLOW);&lt;br /&gt;  randomColor();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void randomColor()&lt;br /&gt;{&lt;br /&gt;  int rand = random(0, sizeof(COLORS) / sizeof(boolean*));&lt;br /&gt;  setColor(ledPins, COLORS[rand]);&lt;br /&gt;  delay(1000);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void setColor(int* led, const boolean* color)&lt;br /&gt;{&lt;br /&gt;  for(int i = 0; i &lt; 3; i++)&lt;br /&gt;    digitalWrite(led[i], color[i]);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;This simple program (sketch in Arduino terminology), will either set the color to one of the predefined values if the first line in loop() is uncommented or will randomly select one of the colors each second if the second line is uncommented. One thing to note, because the LED has a common anode, to turn a color off, we have to give that pin a voltage. This is why the ON constant to indicate the color should be lit is defined as a LOW voltage and the OFF is defined as a HIGH voltage. This definition makes it easier to read the color definitions.&lt;br /&gt;&lt;br /&gt;So far, so good, but a bit on the boring side. I decided in order to juice things up a bit I wanted it to cycle through the colors of the color wheel rather than randomly pick things out of an array. In addition to this, I wanted to fade from one color to the next rather than have abrupt jumps. At this point, one of the beauties of microcontrollers comes to the forefront: all this can be done through simply software changes.&lt;br /&gt;&lt;br /&gt;The example above turns each LED either full on or full off. To make a smooth transition, I needed to display the LEDs in partially lit states. This is done with what's called &lt;a href="http://en.wikipedia.org/wiki/Pulse_width_modulation"&gt;pulse-width modulation&lt;/a&gt;, or PWM. The beauty of the Arduino is that it has this facility built-in. Instead of calling digitalWrite as in the code above, you call analogWrite with a value between 0 and 255 where 0 is full off, 255 is full on and values in-between represent a proportional state between full off and full on. So, the first step was to change the boolean types to bytes. This was a simple change of type and the definitions for ON and OFF. Finally, I changed setColor to use analogWrite instead of digitalWrite. This gave a functionally equivalent version that was now setup to use intermediate values.&lt;pre class="code"&gt;&lt;code&gt;int ledPins[] = { 9, 10, 11 };&lt;br /&gt;int inputPin = 0;&lt;br /&gt;&lt;br /&gt;const byte ON = 0;&lt;br /&gt;const byte OFF = 255;&lt;br /&gt;&lt;br /&gt;const byte RED[] = {ON, OFF, OFF};&lt;br /&gt;const byte GREEN[] = {OFF, ON, OFF};&lt;br /&gt;const byte BLUE[] = {OFF, OFF, ON};&lt;br /&gt;const byte YELLOW[] = {ON, ON, OFF};&lt;br /&gt;const byte CYAN[] = {OFF, ON, ON};&lt;br /&gt;const byte MAGENTA[] = {ON, OFF, ON};&lt;br /&gt;const byte WHITE[] = {ON, ON, ON};&lt;br /&gt;const byte BLACK[] = {OFF, OFF, OFF};&lt;br /&gt;const byte* COLORS[] = {RED, YELLOW, GREEN, CYAN, BLUE, MAGENTA, WHITE, BLACK};&lt;br /&gt;&lt;br /&gt;void setup()&lt;br /&gt;{&lt;br /&gt;  for(int i = 0; i &lt; 3; i++)&lt;br /&gt;    pinMode(ledPins[i], OUTPUT);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void loop()&lt;br /&gt;{&lt;br /&gt;  //setColor(ledPins, YELLOW);&lt;br /&gt;  randomColor();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void randomColor()&lt;br /&gt;{&lt;br /&gt;  int rand = random(0, sizeof(COLORS) / sizeof(byte*));&lt;br /&gt;  setColor(ledPins, COLORS[rand]);&lt;br /&gt;  delay(1000);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void setColor(int* led, const byte* color)&lt;br /&gt;{&lt;br /&gt;  for(int i = 0; i &lt; 3; i++)&lt;br /&gt;    analogWrite(led[i], color[i]);&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The next step is to change the code to display colors in the order of the color wheel rather than randomly. To start, I used the existing COLORS array. I changed the loop method to call a new method setHueValue with a parameter that computed the new hue value and added a delay. I also removed the randomColor function since I wasn't using it anymore.&lt;pre class="code"&gt;&lt;code&gt;int ledPins[] = { 9, 10, 11 };&lt;br /&gt;int inputPin = 0;&lt;br /&gt;&lt;br /&gt;const byte ON = 0;&lt;br /&gt;const byte OFF = 255;&lt;br /&gt;&lt;br /&gt;const byte RED[] = {ON, OFF, OFF};&lt;br /&gt;const byte GREEN[] = {OFF, ON, OFF};&lt;br /&gt;const byte BLUE[] = {OFF, OFF, ON};&lt;br /&gt;const byte YELLOW[] = {ON, ON, OFF};&lt;br /&gt;const byte CYAN[] = {OFF, ON, ON};&lt;br /&gt;const byte MAGENTA[] = {ON, OFF, ON};&lt;br /&gt;const byte WHITE[] = {ON, ON, ON};&lt;br /&gt;const byte BLACK[] = {OFF, OFF, OFF};&lt;br /&gt;const byte* COLORS[] = {RED, YELLOW, GREEN, CYAN, BLUE, MAGENTA, WHITE, BLACK};&lt;br /&gt;&lt;br /&gt;void setup()&lt;br /&gt;{&lt;br /&gt;  for(int i = 0; i &lt; 3; i++)&lt;br /&gt;    pinMode(ledPins[i], OUTPUT);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void loop()&lt;br /&gt;{&lt;br /&gt;  setHueValue(computeNextValue());&lt;br /&gt;  delay(1000);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int colorValue = -1;&lt;br /&gt;&lt;br /&gt;int computeNextValue()&lt;br /&gt;{&lt;br /&gt;  colorValue = (colorValue+1) % 6;&lt;br /&gt;  return colorValue;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void setHueValue(int hueValue)&lt;br /&gt;{&lt;br /&gt;  setColor(ledPins, COLORS[hueValue]);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void setColor(int* led, const byte* color)&lt;br /&gt;{&lt;br /&gt;  for(int i = 0; i &lt; 3; i++)&lt;br /&gt;    analogWrite(led[i], color[i]);&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;This was great for five values, but I wanted it to cycle smoothly from one color to the next. To do this with a table lookup method was going to require a huge table. A different approach to the problem was needed.&lt;br /&gt;&lt;br /&gt;RGB is a common way to model color with anything that projects light, such as computer monitors and LEDs. However, there are other ways of thinking about color. For example, things that reflect light such as painting and printing, use CMYK or Cyan-Magenta-Yellow-Black. If you ever mixed paint in art class, this is the color wheel you learned. There are another models that can be handy when doing various types of computations, one of which is Hue-Saturation-Value, or HSV. For what I wanted to do, this works well.&lt;br /&gt;&lt;br /&gt;The first step in this stage was to find an easy to use function for converting HSV values to RGB values. A simple search of Google for "hsv to rgb converter" gave me an open source PHP (or perhaps it was Python) function. A quick conversion to C used by the Arduino and I had the hsvToRgb function below. This function takes a hue value in the range 0 to 360. This is because the HSV model maps the hue to a circle and so it uses a degree measurement to specify the hue value. The Saturation and Value portions of the model are a percentage from 0 to 100%, represented by fractional values from 0 to 1. For the purposes of this experiment, I just set them both to 1.&lt;br /&gt;&lt;br /&gt;Once I had the color converter, I next changed computeNextValue to return a max value of 359 instead of 5. This will give me the proper input for the hue value. Then I removed all the color definitions at the top of the sketch since the color values are now computed and the constants won't be needed. I reduced the time delay to 10 milliseconds. With 360 steps, this will give about a 3.5 second cycle time. Next I changed the COLORS array reference in setColor to call the new function. Since the HSV code returns values in 0 to 255 range and the pins need things inverted for voltage reasons, in setColor, I subtract the color in the byte array from 255 rather than passing it in directly. The only real difference this makes from a user perspective is the starting color is at red instead of 180 degrees out of phase at cyan.&lt;br /&gt;&lt;br /&gt;With all this, I accomplished my goals for this experiment. Here is the final sketch.&lt;pre class="code"&gt;&lt;code&gt;int ledPins[] = { 9, 10, 11 };&lt;br /&gt;int inputPin = 0;&lt;br /&gt;void setup()&lt;br /&gt;{&lt;br /&gt;  for(int i = 0; i &lt; 3; i++)&lt;br /&gt;    pinMode(ledPins[i], OUTPUT);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void loop()&lt;br /&gt;{&lt;br /&gt;  setHueValue(computeNextValue());&lt;br /&gt;  delay(10);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int colorValue = 0;&lt;br /&gt;&lt;br /&gt;int computeNextValue()&lt;br /&gt;{&lt;br /&gt;  colorValue = (colorValue+1) % 360;&lt;br /&gt;  return colorValue;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void setHueValue(int hueValue)&lt;br /&gt;{&lt;br /&gt;  setColor(ledPins, hsvToRgb(hueValue, 1, 1));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void setColor(int* led, const byte* color)&lt;br /&gt;{&lt;br /&gt;  for(int i = 0; i &lt; 3; i++)&lt;br /&gt;    analogWrite(led[i], 255-color[i]);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;byte rgb[3];&lt;br /&gt;&lt;br /&gt;byte* hsvToRgb(int h, double s, double v)&lt;br /&gt;{&lt;br /&gt;        // Make sure our arguments stay in-range&lt;br /&gt;        h = max(0, min(360, h));&lt;br /&gt;        s = max(0, min(1.0, s));&lt;br /&gt;        v = max(0, min(1.0, v));&lt;br /&gt;        if(s == 0)&lt;br /&gt;        {&lt;br /&gt;                // Achromatic (grey)&lt;br /&gt;                rgb[0] = rgb[1] = rgb[2] = round(v * 255);&lt;br /&gt;                return rgb;&lt;br /&gt;        }&lt;br /&gt;        double hs = h / 60.0; // sector 0 to 5&lt;br /&gt;        int i = floor(hs);&lt;br /&gt;        double f = hs - i; // factorial part of h&lt;br /&gt;        double p = v * (1 - s);&lt;br /&gt;        double q = v * (1 - s * f);&lt;br /&gt;        double t = v * (1 - s * (1 - f));&lt;br /&gt;        double r, g, b;&lt;br /&gt;        switch(i)&lt;br /&gt;        {&lt;br /&gt;                case 0:&lt;br /&gt;                        r = v;&lt;br /&gt;                        g = t;&lt;br /&gt;                        b = p;&lt;br /&gt;                        break;&lt;br /&gt;                case 1:&lt;br /&gt;                        r = q;&lt;br /&gt;                        g = v;&lt;br /&gt;                        b = p;&lt;br /&gt;                        break;&lt;br /&gt;                case 2:&lt;br /&gt;                        r = p;&lt;br /&gt;                        g = v;&lt;br /&gt;                        b = t;&lt;br /&gt;                        break;&lt;br /&gt;                case 3:&lt;br /&gt;                        r = p;&lt;br /&gt;                        g = q;&lt;br /&gt;                        b = v;&lt;br /&gt;                        break;&lt;br /&gt;                case 4:&lt;br /&gt;                        r = t;&lt;br /&gt;                        g = p;&lt;br /&gt;                        b = v;&lt;br /&gt;                        break;&lt;br /&gt;                default: // case 5:&lt;br /&gt;                        r = v;&lt;br /&gt;                        g = p;&lt;br /&gt;                        b = q;&lt;br /&gt;        }&lt;br /&gt;        rgb[0] = round(r * 255.0);&lt;br /&gt;        rgb[1] = round(g * 255.0);&lt;br /&gt;        rgb[2] = round(b * 255.0);&lt;br /&gt;        return rgb;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;In the next installment, I'll walk through adding some simple control mechanisms to this circuit along with various software changes to make it respond differently with the same hardware.&lt;div class="blogger-post-footer"&gt;&lt;hr /&gt;  &lt;a href="http://skylark-software.com"&gt;Skylark Software&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1951153510791888567-9157228462768723738?l=www.skylark-software.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/OiRCGKs4WLUg1s0d6r4-AcAhCT8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/OiRCGKs4WLUg1s0d6r4-AcAhCT8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/OiRCGKs4WLUg1s0d6r4-AcAhCT8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/OiRCGKs4WLUg1s0d6r4-AcAhCT8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/SkylarkSoftware/~4/2kzccwi3ELI" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SkylarkSoftware/~3/2kzccwi3ELI/arduino-notebook-rgb-led-and-color.html</link><author>noreply@blogger.com (Harley Pebley)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://farm6.static.flickr.com/5207/5374166595_a43d52159b_t.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://www.skylark-software.com/2011/01/arduino-notebook-rgb-led-and-color.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1951153510791888567.post-6904907308300848032</guid><pubDate>Wed, 12 Jan 2011 13:00:00 +0000</pubDate><atom:updated>2011-01-12T06:00:07.601-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">arduino</category><category domain="http://www.blogger.com/atom/ns#">wii</category><category domain="http://www.blogger.com/atom/ns#">nunchuck</category><title>Arduino Notebook: a multi-input device</title><description>As I &lt;a href="http://www.skylark-software.com/2011/01/let-games-begin-my-own-microcontroller.html"&gt;previously mentioned&lt;/a&gt;, I recently got an Arduino development kit for Christmas and have been experimenting with it. One of the things on my to do list involves using a joystick. Since the kit only came with a momentary contact switch and a potentiometer, I went online to try to find something that would fit my needs. The &lt;a href="http://www.makershed.com/ProductDetails.asp?ProductCode=MKPX10"&gt;cheap one&lt;/a&gt; I initially wanted to get was out of stock, so I searched around a bit.&lt;br /&gt;
&lt;br /&gt;
I ran across a &lt;a href="http://www.windmeadow.com/node/42"&gt;site talking about a Wii Nunchuck&lt;/a&gt; as an input device. Hmm. That sounded interesting. Not being a gamer, I didn't quite know what a nunchuck was. Although many times I would have liked to take a traditional one to the computer, I didn't quite think that was what was associated with the Wii gaming system. A bit of research told me it's an extension controller that plugs into the standard Wii controller giving you an extra two buttons, a joystick and 3-axis accelerometer. The idea is you can use the regular controller in one hand and use the extension controller in your other hand. The examples say this lets you run and jump with one hand while the other swings a sword. Yeah. Right. Like that's going to happen. I have enough problem trying to use one controller on the rare occasion that I try a game out. There's no way I'm coordinated enough to use two.&lt;br /&gt;
&lt;br /&gt;
Be that as it may, I'm not interested in gaming applications; I'm interested in Arduino control. I found some controllers for &lt;a href="http://www.amazon.com/gp/product/B000IMYKQ0?ie=UTF8&amp;tag=theepiaut-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B000IMYKQ0"&gt;sale on Amazon&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=theepiaut-20&amp;l=as2&amp;o=1&amp;a=B000IMYKQ0" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt;for less than $20. A whole lot more than the $5 for the joystick I first looked at, but this one has extra sensors and was packaged in a neat little hand-held device. And even though it's an order of magnitude more expensive, at less than the cost of a fast food dinner with my wife, it's not going to break the bank. (But being as frugal as I am, I still opted for the black one at $1.70 less than the white one.)&lt;br /&gt;
&lt;br /&gt;
The biggest drawback to this hack was the original site instructed you to cut off the connector to use it with the Arduino. That didn't sound too appealing. A bit more surfing and I found &lt;a href="http://todbot.com/blog/2008/02/18/wiichuck-wii-nunchuck-adapter-available/"&gt;someone&lt;/a&gt; who made an adapter. Yeah. That'll work. The adapter is sold through several places online, I got it from &lt;a href="http://www.sparkfun.com/products/9281"&gt;SparkFun&lt;/a&gt; since they had several other things I was interested in (and I'll probably blog about in the future). So, I placed the two orders.&lt;br /&gt;
&lt;br /&gt;
Well, they arrived yesterday and I opened them tonight. The adapter was just a PC board with no instructions. I went to the adaptor creator's web site and found some pictures and software. First, it was obvious that it needed some header pins to plug it into the Uno board. Fortunately, the development kit came with a strip of break-off headers. I broke four pins off and soldered them onto the board based on the pictures on the web. Next I downloaded the software in a zip file.&lt;br /&gt;
&lt;br /&gt;
As instructed on the site, I plugged the adapter into the Arduino's analog pins 2, 3, 4 and 5. The zip file has a demo sketch that I uploaded onto the board. It ran, but when I opened the Serial Monitor all I got was garbage. Hmm. I looked at the code for the sketch and it initialized the Serial port to 19200 but the Serial Monitor window defaults to 9600. After a simple change of the baud rate, everything worked.&lt;br /&gt;
&lt;br /&gt;
The demo sketch displayed the data from the switches and the x- and y-axis accelerometers. Since the joystick info was what really interested me, I started reading the library code to figure out how to get it. I quickly found a routine in the library to display all the sensor information. I removed the display code in the demo and replaced it with the single line call to the library and uploaded the new code. Viola: all the information.&lt;br /&gt;
&lt;br /&gt;
In a quick five minute review of the library code, there are some things that on the surface don't look like the most effective way of handling the data. When I dive into this to really start looking at it, I'll do a code review and write up some notes if my initial impressions prove correct. I'll probably also write up some notes if I'm wrong about it since that would probably be interesting too.&lt;br /&gt;
&lt;br /&gt;
While looking up the web site addresses for this article, I ran across a &lt;a href="http://www.solarbotics.com/products/31040"&gt;competitor's adapter&lt;/a&gt;. This looks like a better design and if I were to do it again, I'd probably get this one rather than the one I got, even though it's a buck more expensive. Huh. There goes my savings from getting the black nunchuck instead of the white one.&lt;div class="blogger-post-footer"&gt;&lt;hr /&gt;  &lt;a href="http://skylark-software.com"&gt;Skylark Software&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1951153510791888567-6904907308300848032?l=www.skylark-software.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/UETRV9Yh5q0wIQOWC5A-JfPnp6E/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UETRV9Yh5q0wIQOWC5A-JfPnp6E/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/UETRV9Yh5q0wIQOWC5A-JfPnp6E/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UETRV9Yh5q0wIQOWC5A-JfPnp6E/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/SkylarkSoftware/~4/oF-6AnnLCgE" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SkylarkSoftware/~3/oF-6AnnLCgE/arduino-notebook-multi-input-device.html</link><author>noreply@blogger.com (Harley Pebley)</author><thr:total>0</thr:total><feedburner:origLink>http://www.skylark-software.com/2011/01/arduino-notebook-multi-input-device.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1951153510791888567.post-2888593736621809992</guid><pubDate>Mon, 10 Jan 2011 13:00:00 +0000</pubDate><atom:updated>2011-01-10T06:00:04.719-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">arduino</category><title>Let the games begin: My own microcontroller kit</title><description>Woo, hoo! I'm excited.&lt;br /&gt;
&lt;br /&gt;
I've had two opportunities in my career to work with embedded software directly. The first was in mid-80's when the company I was working for developed a Z80-based product. And then a couple years ago, I was able to play with an 8051 based development kit that I wrote about &lt;a href="http://www.skylark-software.com/2008/07/adventures-in-firmware-development-new.html"&gt;here&lt;/a&gt; and &lt;a href="http://www.skylark-software.com/2008/07/adventures-in-firmware-development-you.html"&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
I've had a passing interest in controlling things from my earliest days of leaning computers but have always been side tracked somewhat by the extra investment in hardware. Development kits have typically cost in the couple hundred dollar range and it's pretty easy to smoke them, so I've hesitated investing in anything. Recently I've become increasingly aware of the Arduino platform. I don't really know enough of all the details to write about them here, but basically it's an open source hardware/software platform for microcontroller development. Depending on features, they can be acquired for less than $10 on the low end to several tens of dollars on the high end. At this cost point, the high end is an order of magnitude cheaper than what I've seen most other development kits start at. This makes the thought of smoking something much more palatable. Destroying a $20 part because you hooked it up wrong is much easier to take than a $200 part.&lt;br /&gt;
&lt;br /&gt;
So, when my wife asked me what I wanted for Christmas this year, I had a ready answer: an Arduino starter kit. And she got me &lt;a href="http://www.adafruit.com/index.php?main_page=product_info&amp;cPath=17&amp;products_id=170"&gt;this one&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
So far I am quite pleased with it. It has everything listed on the web page and things seem to work well. The only assembly needed is to attach the controller board (with screws) and a breadboard (with double sided adhesive) to a clear acrylic base. For anyone putting one together, I recommend putting the controller board on first and then the breadboard second. Since the controller is held on with machine screws, it can only go in one location, with no wiggle room. The adhesive on the breadboard is permanent. There is no ability to move it once placed, but its location isn't as critical as the controller. I put the breadboard on first and didn't leave myself as much room as would have been ideal for the controller board. It would have been easier to do it the other way around. That minor issue aside, everything else is ready to go out of the box.&lt;br /&gt;
&lt;br /&gt;
There is a freely available IDE available that has to be downloaded from the internet. Once downloaded, there's no other internet requirement. The IDE is pretty bare bones. It provides a text editor and upload capability to the controller via USB. It has a window to allow serial communication with the controller if the software you've loaded on the controller is programmed  to communicate with it. Don't expect modern conveniences like code completion, debugging and the like. It's not there. Although, since it's open source, I'm sure if you wanted to make a patch to do that, others would appreciate it. :-)&lt;br /&gt;
&lt;br /&gt;
At this point, I have only experimented with some minor motor and LED control. One cool thing about the system is it has both digital I/O and analog input and PWM output baked into both the hardware and the software. Reading an analog signal is simply a matter of connecting it to one of the analog pins and in software doing something like "inValue = analogRead(0);" where inValue is a byte and the 0 is the pin number to read. The voltages on the pin can be from ground to +5V and the corresponding byte value will be 0 to 1024. Analog type output can be achieved with pulse width modulation. (I don't want to delve into the details of what this entails here. For more information on PWM, start &lt;a href="http://en.wikipedia.org/wiki/Pulse-width_modulation"&gt;here&lt;/a&gt; and &lt;a href="http://www.google.com/search?sourceid=chrome&amp;ie=UTF-8&amp;q=pulse+width+modulation"&gt;here&lt;/a&gt;.) This is doesn't work for all devices, but for many that one would want to control with a microcontroller, like motors and LEDs, it works well. This is done with a simple "analogWrite(value);" where value is in the range 0 to 255, 0 being off, 255 being full on and anything in between be a linear intermediate value (e.g. 64 is 25% on, 127 is 50% on, 192 is 75% on).&lt;br /&gt;
&lt;br /&gt;
I've got some things on order to play with and more ideas to experiment with than I know what to do with. Lots of things to learn and explore. It's so much fun to have a new toy.&lt;div class="blogger-post-footer"&gt;&lt;hr /&gt;  &lt;a href="http://skylark-software.com"&gt;Skylark Software&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1951153510791888567-2888593736621809992?l=www.skylark-software.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/T_JIs8KQLvmIEDmsc1u6Gog0tnU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/T_JIs8KQLvmIEDmsc1u6Gog0tnU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/T_JIs8KQLvmIEDmsc1u6Gog0tnU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/T_JIs8KQLvmIEDmsc1u6Gog0tnU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/SkylarkSoftware/~4/aQSUJ6UhaQU" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SkylarkSoftware/~3/aQSUJ6UhaQU/let-games-begin-my-own-microcontroller.html</link><author>noreply@blogger.com (Harley Pebley)</author><thr:total>4</thr:total><feedburner:origLink>http://www.skylark-software.com/2011/01/let-games-begin-my-own-microcontroller.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1951153510791888567.post-1949084685485208593</guid><pubDate>Fri, 03 Dec 2010 15:00:00 +0000</pubDate><atom:updated>2010-12-03T08:00:09.808-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">rant</category><category domain="http://www.blogger.com/atom/ns#">Programming</category><category domain="http://www.blogger.com/atom/ns#">design</category><category domain="http://www.blogger.com/atom/ns#">Debugging</category><title>DRY vs KISS</title><description>Two developers are playing poker. The chips are all on the table and it's time to show their hands. One throws down the DRY hand. The other throws down KISS. Which hand wins? Who gets to take the pot home?&lt;br /&gt;
&lt;br /&gt;
There are many guidelines in software development. These are two prominent ones: DRY and KISS. For those who haven't heard of them, DRY stands for Don't Repeat Yourself and KISS stands for Keep It Simple, Stupid.&lt;br /&gt;
&lt;br /&gt;
The underlying principle behind DRY is that there should be one authoritative source for any artifact in a piece of software. This can take different forms depending on the context. One example might be a constant literal. If a literal, for example a numeric value or a string value, exists more than one place in a program, it's a bad thing. The duplication should be removed and replaced with a named constant. The constant becomes the authoritative source for the value. This also has the side effect of making the software more readable if a good name is chosen because the meaning can be conveyed, not just the value. Another example is duplicated code. If lines of code are copied and pasted, there becomes more than one authority for the code's behavior. Instead, those duplicated lines should be put in a function that can be called from the various places the behavior is needed.&lt;br /&gt;
&lt;br /&gt;
The KISS principle is based on the idea that complexity makes code that's hard to understand, maintain and debug. Code that is hard to understand will have more bugs in it to begin with and take longer to get working properly. It will also be harder for the person who has to maintain it to make changes and hence will increase the cost of ownership over the lifetime of the product.&lt;br /&gt;
&lt;br /&gt;
On the surface, I think most developers will agree that both these principles are good. However, I think there is disagreement upon which one trumps the other.&lt;br /&gt;
&lt;br /&gt;
An argument could be made that removing duplication increases complexity. In the examples for DRY above, adding a function or constant declaration adds indirection. As you read the code, the value is not immediately obvious and the behavior is not readily apparent. You have to go somewhere or use some feature in the IDE to find the value or determine what the routine does. In addition to readability, as you write, you have extra work to make a separate function. It is much faster to simply copy what you need and paste it somewhere else.&lt;br /&gt;
&lt;br /&gt;
I understand these arguments. I know first hand the temptation to grab a section of code and paste it somewhere else. I know the pain of slowing down and having to think deeply about how to not make the duplicate copy of the code. Given all that...&lt;br /&gt;
&lt;h4&gt;DRY trumps KISS every time.&lt;/h4&gt;When I look at the long term maintainability, having one place where behavior or values or anything else is defined is always the better thing. I've experienced first hand maintenance of code with high levels of duplication. I have made changes in one place without knowing about the duplication and not also fixing the same code elsewhere. I have seen others do the same thing. The testing and validation in these scenarios can get very painful. When maintaining software and making changes, dealing with a single authority is much more accurate and faster, even with increased indirection.&lt;br /&gt;
&lt;br /&gt;
In addition to long term maintainability when behavior should be changed, not repeating yourself reduces the chance of copy and paste errors. More times than I care to count, I've found bugs where a block of code was copied and minor changes made throughout it. Missing even one thing that should be changed will result in insidious bugs setting up residence in your application. Many times these won't be caught until much later in the product's life-cycle, increasing the cost of fixing them.&lt;br /&gt;
&lt;br /&gt;
Just today I violated this principle... even after thinking "do I really want to do this?"... even with the draft of this article fresh in my mind... and I introduced a bug that took me a minute to figure out. I had these two lines:&lt;blockquote&gt;&lt;code&gt;const string name1 = "value one" ;&lt;br /&gt;
var value1 = !computeValueForName(name1);&lt;/code&gt;&lt;/blockquote&gt;That I duplicated and changed to this:&lt;blockquote&gt;&lt;code&gt;const string name2 = "value two" ;&lt;br /&gt;
var value2 = !computeValueForName(name1);&lt;/code&gt;&lt;/blockquote&gt;See the error? When I did, I promptly refactored this to:&lt;blockquote&gt;&lt;code&gt;var names = new [] {  "value1" , "value2" };&lt;br /&gt;
var values = from n in names select !computeValueForName(n);&lt;/code&gt;&lt;/blockquote&gt;So, yeah, when I see violations of DRY I have almost a compulsive need to fix it. How about you?&lt;div class="blogger-post-footer"&gt;&lt;hr /&gt;  &lt;a href="http://skylark-software.com"&gt;Skylark Software&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1951153510791888567-1949084685485208593?l=www.skylark-software.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/mQW6I-yT2IuIyKGBKYM3l8Rwp5Y/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/mQW6I-yT2IuIyKGBKYM3l8Rwp5Y/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/mQW6I-yT2IuIyKGBKYM3l8Rwp5Y/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/mQW6I-yT2IuIyKGBKYM3l8Rwp5Y/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/SkylarkSoftware/~4/BOTWUCcMehA" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SkylarkSoftware/~3/BOTWUCcMehA/dry-vs-kiss.html</link><author>noreply@blogger.com (Harley Pebley)</author><thr:total>0</thr:total><feedburner:origLink>http://www.skylark-software.com/2010/12/dry-vs-kiss.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1951153510791888567.post-3834926787772310523</guid><pubDate>Mon, 15 Nov 2010 13:00:00 +0000</pubDate><atom:updated>2010-11-15T06:00:02.657-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">rave</category><category domain="http://www.blogger.com/atom/ns#">usability</category><category domain="http://www.blogger.com/atom/ns#">design</category><category domain="http://www.blogger.com/atom/ns#">Apple</category><title>Apple Raves</title><description>About two months ago I &lt;a href="http://www.skylark-software.com/2010/09/apple-rants.html"&gt;ranted about some issues I had with my new Apple MacBook Pro&lt;/a&gt;. For the most part, after additional time with the machine, they are all pretty much still valid. I'm still not used to the keyboard layout; I keep reaching for keys that don't exist. The menus at the top of the screen still escape me.&lt;sup&gt;&lt;small&gt;&lt;a href="#AppleRaves1"&gt;[1]&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt; As for finding other machines on the network, that could be a bigger issue than it is for me. Once things are mapped, the O/S seems to do a decent job of finding them. As long as the network topology is stable, it's not a huge issue. It's simply an occasional annoyance rather than a day-in/day-out frustration. And finally, the stability isn't as bad as it first appeared. Now that things are setup and working, I haven't had any crashes or freezes. I don't think it's good as Windows or Linux, but it's not as bad as it first seemed.&lt;br /&gt;
&lt;br /&gt;
With that recap and update of what I don't like, this article is about what I do like. And there is plenty.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Battery life&lt;/h3&gt;The battery life on this thing is superb. I haven't actually timed it or have any hard data, but seat of the pants performance feels as good as any laptop I've had with much bigger and heavier batteries. If I was a real road warrior, the lack of being able to change batteries might be a problem, but in the last 10-plus years of using a laptop, I've really only needed a backup set of batteries a couple times. For my uses, if it lasts a day of off-and-on use, it's good. And this has done that and then several hours of continuous use in the evenings. Perhaps one of the reasons the battery lasts so long is because of the next item...&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Sleep/hibernate&lt;/h3&gt;I've never had a laptop that is so consistent in it's ability to go to sleep and wake up when needed. This issue has been one of the biggest ongoing technical flaws in all the other laptops I've had in the past. They were either slow enough at it or crashed regularly enough that I didn't use this feature very much. The Mac does it so smoothly and seamlessly that I do it quite frequently. This might be part of the reason my battery life is better: I'll close the lid and put it to sleep in cases where in the past I'd leave it on. For example, those times when I know I won't need it for five minutes but don't want to shutdown. I guess these periods of inactivity were using more battery than I gave them credit for and they added up so the difference is note-worthy.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Networking&lt;/h3&gt;Wow, what can I say about the networking connectivity. It just works. Flawlessly. Everytime. It finds and connects to networks easily and intuitively. Once I've connected to a network, it remembers it and reconnects again without hassle. I can be connected to one network, sleep the machine, go somewhere else with an already known network and begin working again as if nothing has changed. I never knew how much of a hassle network connectivity was until I didn't have the noise anymore.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Delightful surprises&lt;/h3&gt;I just noticed this the other day and it's an example of the subtle attention to detail that is throughout much of the system: the Finder's date column adjusts the format based on the width of the column. If the column is narrow, it shows mm/dd/yy. Widen it a bit and it shows mm/dd/yy hh:mm. Some more space and it starts using abbreviations. It continues giving more detail like this until everything is spelled out completely.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Summary&lt;/h3&gt;So, all in all, it's a really nice machine. It's not so much nicer I'd never own anything else and, as I mentioned, there are some real annoying "features" about it. On a scale of 1 to 10, I'd give it a good, solid 8. Fairly comparable to the other high-end Dell's I've had in the past.&lt;br /&gt;
&lt;hr/&gt;&lt;div id="AppleRaves1" style="margin-left:2em;text-indent:-2em"&gt;1. Literally, they escape my notice; I simply don't see the menus up at the top of the main screen. I'll be working with a program wondering how to do something, looking around frustrated. And then, when I'm about to give up thinking the s/w is brain dead, I remember to look at the top. This is particularly pronounced when working with multiple monitors. The menu isn't even on the same screen as the application.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;hr /&gt;  &lt;a href="http://skylark-software.com"&gt;Skylark Software&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1951153510791888567-3834926787772310523?l=www.skylark-software.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/hPCH1k7Zkldzrk5k2esR9qE64ak/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/hPCH1k7Zkldzrk5k2esR9qE64ak/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/hPCH1k7Zkldzrk5k2esR9qE64ak/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/hPCH1k7Zkldzrk5k2esR9qE64ak/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/SkylarkSoftware/~4/JldIf1A2gxQ" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SkylarkSoftware/~3/JldIf1A2gxQ/apple-raves.html</link><author>noreply@blogger.com (Harley Pebley)</author><thr:total>0</thr:total><feedburner:origLink>http://www.skylark-software.com/2010/11/apple-raves.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1951153510791888567.post-6947579713206429410</guid><pubDate>Thu, 09 Sep 2010 12:00:00 +0000</pubDate><atom:updated>2010-11-06T10:28:05.644-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">rant</category><category domain="http://www.blogger.com/atom/ns#">usability</category><category domain="http://www.blogger.com/atom/ns#">design</category><category domain="http://www.blogger.com/atom/ns#">Apple</category><title>Apple Rants</title><description>I first played with an Apple computer in the early '80s at a local computer store. My next experience was with a Macintosh an employer purchased to play on. Over the years, I've worked on mini-computers, S-100 based computers, PCs with various versions of DOS, Unix and Windows. Despite friendly jabs I may give friends, I don't really consider myself a computer or operating system bigot. I've watched the maturing of Apple computers from the side-lines, fairly impressed by the changes I've seen over the last 10 or so years. I have a number of friends who are Mac fans and have observed the improvements over their shoulders. I saw a lot of Apples as Windows machines at a recent Microsoft conference. More than once I've heard that the MacBook was the best Windows laptop around.&lt;br /&gt;&lt;br /&gt;Given all this, when I recently needed to get a new computer I decided to take the plunge and get a MacBook Pro. I was pretty excited to get something so different than my usual fare. It arrived last week and I've spent the better part of the weekend and last couple days configuring it and a new Windows server I got at the same time. Overall, I really like it. The hardware design, the look and feel, the fit and finish are superb. It feels really solid. It feels like a BMW or Mercedes compared to the Dell's Chevy or Ford feel. As good as the hardware is, the operating system software doesn't seem to match up. The following paragraphs rant about some of the issues I have with it.&lt;br /&gt;&lt;br /&gt;The biggest issue has to be the Copy/Cut/Paste key mappings. Why are they different than Windows and Linux? What was the reasoning that said they should do something different from the rest of the industry that has no real value? To be different? In my opinion, this is a major impediment to people new to OS X feeling comfortable with it. On &lt;a href="http://superuser.com/questions/28078/remap-copy-and-paste-shortcuts-on-a-mac"&gt;SuperUser.com&lt;/a&gt; I did find a hint to be able to remap the keys, so they now work as I expect. I wonder though how many people just put up with it as frustrated users.&lt;sup&gt;&lt;small&gt;&lt;a href="#AppleRants1"&gt;[1]&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;br /&gt;&lt;br /&gt;The next issues seems like a huge anachronism. Circa 1985, before windowing PC operating systems had multi-tasking, each application took over the screen. In those days, putting the Menu bar at the top of screen made sense. However, as soon as you could have more than one application open at a time and visible on screen, basic user experience guidelines dictate the menu bar should be with the window it controls, not at the top of the screen. Given their big emphasis on design in some areas, why Apple thinks violating basic user design principles of keeping similar functions close to where they're used as it relates to the menu bar completely escapes me.&lt;sup&gt;&lt;small&gt;&lt;a href="#AppleRants1"&gt;[2]&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;br /&gt;&lt;br /&gt;Microsoft has used the SMB protocol for computer discovery and file sharing for a long time. It has become the defacto standard. I find it incredible that there is no way to browse the network and find computers dynamically on the Mac. It seems one can only connect to a networked computer if you already know the name. And to connect to it you have to use a fairly cryptic "smb://computer_name:139" syntax. Really? ... Really? Linux has "just worked" in this regard for many years. And it's worked overall better than Windows itself has. It's about time Apple caught up to the real world.&lt;br /&gt;&lt;br /&gt;Finally, Snow Leopard just seems less stable than Linux and Windows have in a long time. Its stability feels like Windows did for the Windows 95 release. Several times in last couple days things have gotten wonky that were fixed by rebooting. A number of times when this happened, shutdown didn't work. It just hung after clearing the screen; I had to power down by holding the power button until it powered off. I can't remember the last time that happened on a Windows or Linux box.&lt;br /&gt;&lt;br /&gt;Given all these rants, I don't want to give the impression I don't like my new machine. It is speedy. It is solid physically. And really, overall, I haven't had a ton of problems. Perhaps the problems I have had are more remarkable and obvious given the cleanness of the rest of the system. I'm not yet ready to do as some have and install something else as the base operating system and run OS X in a virtual machine.&lt;br /&gt;&lt;hr/&gt;&lt;div id="AppleRants1" style="margin-left:2em;text-indent:-2em"&gt;1. More key mapping resources:&lt;br /&gt;&lt;a href="http://bigdiver.wordpress.com/2009/09/11/configure-homeend-key-bidings-on-mac-os-x/"&gt;Configure home/end key bindings on Mac OS X&lt;/a&gt;&lt;br /&gt;&lt;a href="http://blog.macromates.com/2005/key-bindings-for-switchers/"&gt;Key bindings for switchers&lt;/a&gt;&lt;br /&gt;&lt;a href="http://xahlee.org/emacs/osx_keybinding.html"&gt;OS X Keybinding&lt;/a&gt;&lt;br /&gt;&lt;a href="http://xahlee.org/emacs/osx_keybinding_action_code.html"&gt;OS X Keybinding action codes&lt;/a&gt;&lt;br /&gt;&lt;a href="http://xahlee.org/emacs/osx_keybinding_key_syntax.html"&gt;OS X Keybinding key syntax&lt;/a&gt;&lt;/div&gt;&lt;div id="AppleRants1" style="margin-left:2em;text-indent:-2em"&gt;2. See "The Structure Principle" at &lt;a href="http://en.wikipedia.org/wiki/Principles_of_User_Interface_Design"&gt;Principles of User Interface Design&lt;/a&gt;. Many people talk about this principle such as &lt;a href="http://www.forumone.com/blogs/post/design-principles-proximity"&gt;this one&lt;/a&gt; and &lt;a href="http://www.webdesignerdepot.com/2010/01/the-principle-of-proximity-in-web-design/"&gt;this one&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;hr /&gt;  &lt;a href="http://skylark-software.com"&gt;Skylark Software&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1951153510791888567-6947579713206429410?l=www.skylark-software.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/QUa5uq1tMjwnp-xx2HItbKoCooE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QUa5uq1tMjwnp-xx2HItbKoCooE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/QUa5uq1tMjwnp-xx2HItbKoCooE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QUa5uq1tMjwnp-xx2HItbKoCooE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/SkylarkSoftware/~4/o9eJMjlVqTc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SkylarkSoftware/~3/o9eJMjlVqTc/apple-rants.html</link><author>noreply@blogger.com (Harley Pebley)</author><thr:total>0</thr:total><feedburner:origLink>http://www.skylark-software.com/2010/09/apple-rants.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1951153510791888567.post-266886777011523288</guid><pubDate>Tue, 07 Sep 2010 16:17:00 +0000</pubDate><atom:updated>2010-09-07T10:23:37.266-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">HowTo</category><category domain="http://www.blogger.com/atom/ns#">installation</category><category domain="http://www.blogger.com/atom/ns#">Linux</category><category domain="http://www.blogger.com/atom/ns#">Apple</category><category domain="http://www.blogger.com/atom/ns#">networking</category><title>Synergy setup between a MacBook and Linux machine</title><description>I just got a new MacBook Pro a couple days ago. Wow, it's a nice machine. For my first Apple product, I'm pretty impressed. I have a couple things I don't like about it that I'll probably rant about some other time. But for today's post, I wanted to chronicle my adventure in getting it to be a &lt;a href="http://synergy-foss.org/"&gt;Synergy&lt;/a&gt; server for an old Dell Dimension running Ubuntu. All said, it was the most problematic software configuration I've had in a really long time, but in the end I got it working pretty well. I kind of reminded me of trying to sort out IRQ and DMA addresses way back in the dark ages.&lt;br /&gt;&lt;br /&gt;I first heard about Synergy a couple years ago when a friend of mine connected his iMac and Windows boxes together. For those who don't know, Synergy is an open source project that allows one machine's keyboard and mouse to be used on another machine in a seamless manner. The machine that has the keyboard and mouse physically connected is the server and the machine that only has a screen on it and uses the input devices from the other is the client. The two machines are connected through the network. So, this solution doesn't require any additional hardware than what the computers probably already have. Once configured, the mouse pointer can be moved off the side of one machine's screen onto another and the keyboard focus follows. It can also work with more than two machines. Any number of boxes can be setup as clients to use the common server.&lt;br /&gt;&lt;br /&gt;Official installation instructions can be found &lt;a href="http://synergy-foss.org/pm/projects/synergy/wiki/Setup"&gt;on the Synergy wiki&lt;/a&gt;. I followed them mostly. Below are some issues I ran into and how I worked around them.&lt;br /&gt;&lt;br /&gt;Step one was to download the software from the &lt;a href="http://synergy-foss.org/pm/projects/synergy/tabs/download"&gt;repository&lt;/a&gt;. For the Mac it came as a dmg file that installed without issue. For the Linux machine, it was available in both deb and rpm formats. Since I'm running Ubuntu, I loaded the deb file. It installed just fine too. In both cases, it put two applications in /usr/bin: the client, syngergyc, and the server, synergys.&lt;br /&gt;&lt;br /&gt;Step two was to configure the server. This is done through a text file. The instructions seem to imply that it is optional, but it isn't. This is the only way to configure the server. Another point not clear in the instructions is the configuration file is only needed on the server and can be anywhere and called anything. You specify the name, including the path, on the command line for the server.&lt;br /&gt;&lt;br /&gt;Somewhere I heard about GUI configuration tools; I thought it was on the setup page, but when I went to find it, I couldn't. Where ever I heard about them, I tried SynergyKM on the Mac. It was a dismal failure. It seemed to get confused and couldn't maintain its state very well so I eventually abandoned it, but not after wasting some time trying to get it to work. In the end, I just wrote the configuration file myself. It wasn't as hard as it first seemed. I called it /etc/synergy.&lt;br /&gt;&lt;br /&gt;I also found a GUI tool for the Linux client and tried using it. However it used a different version of Synergy and when the Ubuntu Software Center tried to install it, it somehow messed up the apt state files. Another weird problem. I haven't had apt files get messed up in quite a while. I had to go into aptitude and do some clean-up to repair things so the GUI tools would work properly again. In the clean-up I also removed the GUI tool and just handled setup manually in a terminal window.&lt;br /&gt;&lt;br /&gt;After installation and configuration, the next step is to run both the server and client in a terminal to test connectivity. My suggestion is to not skip this step. I thought I could and ran into some opaque problems that became obvious when I ran the software in a terminal. They all related to machine names used and my getting confused about which names to use where. By default, the instructions say the hostname is used, but that didn't really work too well for me on the Mac, so I ended up specifying my own names for the synergy connections. It took a bit for me to get this to work on both sides, mainly due to my own wrong assumptions about how things worked. When I ran things in a terminal, the error messages indicating my mis-configuration made short work of getting things sorted.&lt;br /&gt;&lt;br /&gt;So, I once things ran in two terminal windows, the next step was to start the software automatically at startup. On the old, deprecated site, there's an &lt;a href="http://synergy2.sourceforge.net/autostart.html"&gt;Autostart Guide&lt;/a&gt; and this is linked to from the &lt;a href="http://code.google.com/p/synergy-plus/wiki/Setup"&gt;code.google.com wiki setup page&lt;/a&gt; with some additional information. I didn't see either on the new, official site and had to do some experimentation using the information from these two pages to get everything working properly. I ran into several time consuming problems doing this.&lt;br /&gt;&lt;br /&gt;The first problem was a how to connect to the MacBook by name. The Synergy client needs either the IP address or the DNS name of the server in its command line. This makes sense from a client programming perspective. However, from a system administration perspective not so much. I'm using DHCP to assign IP addresses and as I have a small home network, I don't have a DNS server setup to handle local requests like this. The standard name resolution mechanism didn't work for me. I wanted to use the netbios name since it was available but it took a bit to figure out how to get it. In the end, I found the nmblookup command which, given the name will give some information, including the IP address. But, it's not in an incredibly useful format for scripts. I had pipe the output to grep to get just the line I wanted and then pipe that to cut to get just the IP address. Specifically the command looks like this:&lt;br /&gt;&lt;code&gt;nmblookup macbook_name | grep "&lt;" | cut -f 1 -d" "&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;With this in hand, I wrote a short bash script to look for a server and then connect to it once it found one. This is where I ran into my second problem. It's been a while since I've done any shell programming and I had to do a bunch of web searching to remind myself of the details. Everything indicated string equality could be done with either "==" or "=". As a C programmer, I defaulted to using "==". My script kept giving me unexpected operator errors on odd lines without operators. After commenting some lines out, I found the if statement at fault. On a whim, I changed the operator to be "=" and the problem went away.&lt;br /&gt;&lt;br /&gt;The final version of the script became this:&lt;br /&gt;&lt;pre class="code"&gt;&lt;code&gt;#!/bin/sh&lt;br /&gt;svr_ip=""&lt;br /&gt;until [ "$svr_ip" != "" ]&lt;br /&gt;do&lt;br /&gt;svr_ip=`nmblookup macbook_name | grep "&lt;" | cut -f 1 -d" "`&lt;br /&gt;     if [ "$svr_ip" = "" ]; then&lt;br /&gt;         sleep 2&lt;br /&gt;     fi&lt;br /&gt;  done&lt;br /&gt;synergyc $svr_ip&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;(Note: right now this will fail if the server reboots and gets a different IP address since once syngeryc starts, it continues running even when the server goes offline.)&lt;br /&gt;&lt;br /&gt;Once the script was done, I then followed the instructions to modify the gdm files, substituting my shell script for the synergyc call.&lt;br /&gt;&lt;br /&gt;When this was all working, my next step was to get the autostart working on the Mac. By and large, this went faster than the Linux side but not without its own problems.&lt;br /&gt;&lt;br /&gt;The first one was that the install location of the synergy software was different from the examples. So, the first time I tried it, it simply didn't do anything. There were no errors anywhere that I could find pointing to the problem. It was a matter of going through the script line by line until I found it.&lt;br /&gt;&lt;br /&gt;With the software's path corrected, I ran into the second problem. When I logged on, the screen went blank and I never got anything else. The menu bar never appeared. The dock never appeared. The desktop icons never appeared. I couldn't do anything. However, the mouse moved the cursor and it would move onto the Linux desktop. Ok, I knew it was running, but how to get my desktop back? As a new Mac user I had no clue.&lt;br /&gt;&lt;br /&gt;After a bit of searching, I found I could boot the installation CD and fire up Terminal to get to my system. I inserted the CD, held down the power button to turn the machine off and then held down the "C" key as I turned it back on. As advertised, it booted the CD and I found the terminal in the Utilities menu. I edited the script and added an ampersand to the end of the call to start the server so it would fork the process and run in a different thread. After rebooting, everything finally worked as expected.&lt;br /&gt;&lt;br /&gt;As I said up front, once I got it working, it works really well in spite of the problematic configuration. The only issues I've found are relatively minor: 1) copy/paste doesn't work between machines, 2) the screen saver on the server doesn't cause the screen saver on the client to start, 3) I haven't gotten it to work prior to logging onto the Mac and 4) the above noted problem if the server reboots and gets a different IP address. While it'd be nice if these worked, in the greater scheme of things, they are pretty minor failures and I'll live with them for now. I think with more time the last two can be overcome with simply configuration changes that I haven't figured out yet.&lt;div class="blogger-post-footer"&gt;&lt;hr /&gt;  &lt;a href="http://skylark-software.com"&gt;Skylark Software&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1951153510791888567-266886777011523288?l=www.skylark-software.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/lDdkfl5bggmasTukjiY4bMZ2M7Q/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/lDdkfl5bggmasTukjiY4bMZ2M7Q/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/lDdkfl5bggmasTukjiY4bMZ2M7Q/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/lDdkfl5bggmasTukjiY4bMZ2M7Q/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/SkylarkSoftware/~4/fI064Ihr0is" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SkylarkSoftware/~3/fI064Ihr0is/synergy-setup-between-macbook-and-linux.html</link><author>noreply@blogger.com (Harley Pebley)</author><thr:total>0</thr:total><feedburner:origLink>http://www.skylark-software.com/2010/09/synergy-setup-between-macbook-and-linux.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1951153510791888567.post-2619177154715679102</guid><pubDate>Tue, 15 Jun 2010 12:00:00 +0000</pubDate><atom:updated>2010-06-15T06:00:05.945-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Programming</category><category domain="http://www.blogger.com/atom/ns#">problem</category><category domain="http://www.blogger.com/atom/ns#">VisualStudio</category><category domain="http://www.blogger.com/atom/ns#">Microsoft</category><category domain="http://www.blogger.com/atom/ns#">.Net</category><title>Message Compiler errors and how I solved them</title><description>As part of my day job, for the last several weeks I have written a Windows Service in .Net 3.5. Today I did some clean-up of messages written to the EventLog. Because internally there are several parts to this service, I wanted to separate the messages using the Category field. After some searching of the web, it seems this isn't drop dead trivial. But, as it didn't seem terribly complex either, I decided to dive into the task.&lt;br /&gt;
&lt;br /&gt;
One of the requirements is that the text for the categories are in a resource DLL. Unfortunately, these aren't natively supported by the .Net framework. You have to manually create the files, compile them with two compilers and then link it into the DLL. Even though it consisted of several steps, it still seemed pretty straight forward based on the details on &lt;a href="blah blah blah"&gt;MSDN&lt;/a&gt;. Following the instructions, I created a simple .mc file and tried compiling it with mc.&lt;br /&gt;
&lt;br /&gt;
The Message Compiler emitted a bunch of errors:&lt;ul&gt;&lt;li&gt;invalid character (0x29)&lt;/li&gt;&lt;li&gt;invalid character (0x57)&lt;/li&gt;&lt;li&gt;invalid character (0x10)&lt;/li&gt;&lt;li&gt;Invalid message file token&lt;/li&gt;&lt;/ul&gt;Obviously something was wrong. Another web search revealed nothing. I tried to make minor changes to the file, reduced things to the bare minimum, but continued to get these errors. It seemed I had some odd characters in the file that none of the the editors I used revealed. Finally I used the command line "type" command and there they were: the Byte Order Marks. Arg. After some head scratching, I used the old text mode "edit" command and it revealed the characters. I easily deleted them and tried to compile. It worked! No errors!&lt;br /&gt;
&lt;br /&gt;
Of course I really wanted to edit the file in Visual Studio and so made a change to the newly edited file and saved it. VS kindly put the BOM right back in. It can be so annoyingly helpful. Yet more searching for a means of eliminating the BOM didn't reveal anything that I wanted to use. I found a script or two that I could install in the IDE, but I didn't want to force the rest of the team to have to do this. The more environmental things that have to be configured and maintained, the harder it is to setup a new development machine. After a bit of pouring through VS's Tool | Options, I found Text Editor | File Extensions. This allows you to define which editor to use for a given file type. I added the .mc extension and told it to use the User Control Editor. Sure enough, this editor didn't put the BOM in the file. While not ideal for the team environment, it is better than a script.&lt;br /&gt;
&lt;br /&gt;
So, these were some of the lessons I learned today working with Message Text Files and the Message Compiler. I hope it helps someone else.&lt;div class="blogger-post-footer"&gt;&lt;hr /&gt;  &lt;a href="http://skylark-software.com"&gt;Skylark Software&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1951153510791888567-2619177154715679102?l=www.skylark-software.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/GNoohUJVL5cEj5IVrVe_iG4MSlY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/GNoohUJVL5cEj5IVrVe_iG4MSlY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/GNoohUJVL5cEj5IVrVe_iG4MSlY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/GNoohUJVL5cEj5IVrVe_iG4MSlY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/SkylarkSoftware/~4/xEuR2TRnLwg" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SkylarkSoftware/~3/xEuR2TRnLwg/message-compiler-errors-and-how-i.html</link><author>noreply@blogger.com (Harley Pebley)</author><thr:total>5</thr:total><feedburner:origLink>http://www.skylark-software.com/2010/06/message-compiler-errors-and-how-i.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1951153510791888567.post-2545676181093555916</guid><pubDate>Wed, 24 Mar 2010 12:00:00 +0000</pubDate><atom:updated>2010-03-24T06:00:08.476-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Programming</category><category domain="http://www.blogger.com/atom/ns#">conference</category><category domain="http://www.blogger.com/atom/ns#">UtahCodeCamp</category><category domain="http://www.blogger.com/atom/ns#">recap</category><title>Utah Code Camp: Spring 2010</title><description>&lt;a href="http://www.utahcodecamp.com"&gt;Utah Code Camp&lt;/a&gt; is a free, day long software conference run by volunteers with workshops presented by local developers. This spring, the day is loaded with 47 workshops in 11 different tracks. The topics range from various Microsoft .Net technologies to open source projects and architecture to career development. The next camp is this Saturday.&lt;br /&gt;
&lt;br /&gt;
Several have been organized, but the first UCC I have been able to attend was last fall. The opening keynote was by Alistair Cockburn and he talked about &lt;a href="http://alistair.cockburn.us/Hexagonal+architecture"&gt;Hexagonal Architecture&lt;/a&gt;. This was followed by six workshop time slots with multiple options available. I chose to attend ones on WCF, Powershell, Microsoft's Multitouch API, new features of C# 4.0, usability, the WIX installer and finally Windows Azure.&lt;br /&gt;
&lt;br /&gt;
I'm looking forward to this event and encourage any developer in the Salt Lake City area to check it out. It's still up in the air if I'll make it. I hope I can.&lt;br /&gt;
&lt;br /&gt;
For those looking for more information, check out the &lt;a href="http://www.utahcodecamp.com"&gt;Utah Code Camp&lt;/a&gt; website or follow them on &lt;a href="http://twitter.com/utcodecamp/"&gt;Twitter&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;hr /&gt;  &lt;a href="http://skylark-software.com"&gt;Skylark Software&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1951153510791888567-2545676181093555916?l=www.skylark-software.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/cBG4u0wfyuOuhAAJLGAwvV0FY_k/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/cBG4u0wfyuOuhAAJLGAwvV0FY_k/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/cBG4u0wfyuOuhAAJLGAwvV0FY_k/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/cBG4u0wfyuOuhAAJLGAwvV0FY_k/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/SkylarkSoftware/~4/UmBqYOppGy8" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SkylarkSoftware/~3/UmBqYOppGy8/utah-code-camp-spring-2010.html</link><author>noreply@blogger.com (Harley Pebley)</author><thr:total>0</thr:total><feedburner:origLink>http://www.skylark-software.com/2010/03/utah-code-camp-spring-2010.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1951153510791888567.post-1093581345040543023</guid><pubDate>Fri, 11 Dec 2009 05:04:00 +0000</pubDate><atom:updated>2009-12-10T22:11:51.494-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">HowTo</category><category domain="http://www.blogger.com/atom/ns#">installation</category><category domain="http://www.blogger.com/atom/ns#">Linux</category><category domain="http://www.blogger.com/atom/ns#">VirtualBox</category><category domain="http://www.blogger.com/atom/ns#">Jolicloud</category><title>How to install Jolicloud in a VirtualBox</title><description>I ran across &lt;a href="http://www.jolicloud.com/"&gt;Jolicloud&lt;/a&gt; today as I surfed around the internet. It sounded like a competitor to Google's &lt;a href="http://www.chromium.org/chromium-os"&gt;Chromium operating system&lt;/a&gt; and sounded interesting. Just for investigation purposes, I wanted to install it in a &lt;a href="http://www.virtualbox.org/"&gt;VirtualBox&lt;/a&gt; virtual machine so went to Jolicloud's download page. It gave a page of instructions that indicated I needed to download an operating system specific application and an ISO file. The application would use the ISO file build a bootable thumb drive. This drive could then install Jolicloud on the target notebook.&lt;br /&gt;&lt;br /&gt;Not wanting to go through this hassle for a virtual machine, nor knowing if I could even boot a virtual machine with a thumb drive, I searched for instructions for a non-thumb drive install. I found several sites but apparently, they were for an earlier build that had some other bootstrap process. They mentioned using an .img file (which the current download doesn't have) and going through a number of different steps to convert it to something the VirtualBox software could read. These directions didn't seem to be appropriate for the current version. (These sites indicated they were for an Alpha release that required an invitation. At the time of this writing, the version is a PreBeta and does not require an invitation.)&lt;br /&gt;&lt;br /&gt;I let the problem percolate in the back of my brain for a bit as I worked on other things. At some point, I realized the current build uses an ISO file. I wondered, "What are the odds that image is bootable?" Figuring the odds were good, I downloaded all 600 megabytes of it.&lt;br /&gt;&lt;br /&gt;When the download finished, I used VirtualBox's normal creation wizard to create a simple virtual machine (512MB memory, 4GB virtual hard drive, Ethernet bridged to the host's NIC). I mounted the ISO image as the CD drive and set it as the boot drive with the virtual, empty hard drive second. When I started the machine, it booted just fine and presented a standard startup screen giving me several options, one of which was to install to the hard drive. From this point on, it proceeded as a typical install. The only things the install wanted from me were the language, keyboard layout, time zone and user information. When done, it shutdown. I unmounted the ISO file from the CD drive and turned the machine back on. Everything seems to be working perfectly so far. For whatever it's worth, it does seem to be faster than Chromium running in another, identically configured virtual machine.&lt;br /&gt;&lt;br /&gt;That's it. Very painless. Everything just worked.&lt;div class="blogger-post-footer"&gt;&lt;hr /&gt;  &lt;a href="http://skylark-software.com"&gt;Skylark Software&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1951153510791888567-1093581345040543023?l=www.skylark-software.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/aO65oRX4OJxVZSAS9KM3jSweDP0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/aO65oRX4OJxVZSAS9KM3jSweDP0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/aO65oRX4OJxVZSAS9KM3jSweDP0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/aO65oRX4OJxVZSAS9KM3jSweDP0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/SkylarkSoftware/~4/6PIWyt34KaM" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SkylarkSoftware/~3/6PIWyt34KaM/how-to-install-jolicloud-in-virtualbox.html</link><author>noreply@blogger.com (Harley Pebley)</author><thr:total>5</thr:total><feedburner:origLink>http://www.skylark-software.com/2009/12/how-to-install-jolicloud-in-virtualbox.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1951153510791888567.post-4384118714084294890</guid><pubDate>Fri, 23 Oct 2009 14:00:00 +0000</pubDate><atom:updated>2009-10-23T08:00:04.255-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">WPF</category><category domain="http://www.blogger.com/atom/ns#">problem</category><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">UI</category><category domain="http://www.blogger.com/atom/ns#">.Net</category><title>Canceling application shutdown in WPF</title><description>I hate "Are you sure" type dialog boxes. Gratuitous use of them in software makes me want to do violence to whoever thought it was a good idea to put it in. That said, there are a few times where they make sense. For example, the application I'm working on now controls an instrument that may have some expensive, hard to replace, chemistry in it. Stopping the application while the instrument is in use may result in moderate financial loss, so in this case, it does make sense to alert the user to a possible undesired outcome and make sure they really want to proceed with the action.&lt;br /&gt;
&lt;br /&gt;
The WPF Window class has a Closing event that fires when the window is closed. This event has an argument containing a Cancel property with a false default value. Setting this property to true inhibits the closing of the window. When this happens on the application’s MainWindow, this closing cancellation behavior applies to the application as a whole.&lt;br /&gt;
&lt;br /&gt;
Some time ago, our application had code put in to pop up an “Are you sure?” style dialog and set the event's property as appropriate. The problem was it worked for some pathways through the code but not others. The lot fell to me to investigate. There are four ways to close the application: the Alt-F4 key, the task bar's Close option, the Close button in the window's title bar and an Exit menu option. All the methods worked except the Exit menu.&lt;br /&gt;
&lt;br /&gt;
Digging into the code, the Exit method called the Shutdown method on the Application.Current object. This seemed like a reasonable thing to do and I went looking elsewhere for the problem. After spending time verifying there wasn't anything else odd in our code I came back to this method. On a hunch, I changed this to calling the Close method on Application.Current.MainWindow. This fixed the problem. I'm not sure why, but apparently the Shutdown method does something to inhibit the normal message processing of open windows.&lt;br /&gt;
&lt;br /&gt;
I know this is typical behavior and it fixes my application for now, but from a design standpoint, I'm not too sure I like this. It seems like application level shutdown code in the Window is at the wrong layer. The Application class has an Exit event that's analogous to the Window's Close event however, this does not allow canceling the operation. In my opinion, the Application class should have an Exiting event with a Cancel property on the argument, similar to the Window class' Closing event.&lt;br /&gt;
&lt;br /&gt;
In any case, if your application does not call the Closing event as you expect, first check to see how it's shutdown.&lt;div class="blogger-post-footer"&gt;&lt;hr /&gt;  &lt;a href="http://skylark-software.com"&gt;Skylark Software&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1951153510791888567-4384118714084294890?l=www.skylark-software.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/-bfNQryvXo1Go3eBWcn1qlc2-Yk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/-bfNQryvXo1Go3eBWcn1qlc2-Yk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/-bfNQryvXo1Go3eBWcn1qlc2-Yk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/-bfNQryvXo1Go3eBWcn1qlc2-Yk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/SkylarkSoftware/~4/uRM8faJVOC0" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SkylarkSoftware/~3/uRM8faJVOC0/canceling-application-shutdown-in-wpf.html</link><author>noreply@blogger.com (Harley Pebley)</author><thr:total>1</thr:total><feedburner:origLink>http://www.skylark-software.com/2009/10/canceling-application-shutdown-in-wpf.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1951153510791888567.post-6161395684951804712</guid><pubDate>Fri, 14 Aug 2009 17:06:00 +0000</pubDate><atom:updated>2009-08-14T11:06:28.211-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">binding</category><category domain="http://www.blogger.com/atom/ns#">WPF</category><category domain="http://www.blogger.com/atom/ns#">design</category><category domain="http://www.blogger.com/atom/ns#">C#</category><category domain="http://www.blogger.com/atom/ns#">ValueConverter</category><category domain="http://www.blogger.com/atom/ns#">.Net</category><title>How to display items from a collection in one line of a DataGrid</title><description>Typically, data structures map closely to their representation in the user interface and so most display widgets work pretty well in this situation. In WPF, DataContexts and bindings expect the relationship between their controls and the bound data to be fairly similar. Recently, I had a weird requirement that caused me trouble getting information on the screen due to a mismatch between the data model and the view.&lt;br /&gt;
&lt;h3&gt;Requirements&lt;/h3&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;For good reasons, the data needed to be modeled in a master-detail relationship. For equally good reasons, the user wanted this displayed on a single line in a grid control. I believe the model to be correct; I'm not too sure about the user interface. I understand the user's reasons for wanting a single line, but I expect that over time and as new features are added, they will want a change in how things are presented. Regardless of what happens in the future, for today, this is the current requirement that I had to implement.&lt;br /&gt;
&lt;br /&gt;
So, the data model looked something like this:&amp;nbsp;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_cRjIi2wRv70/SiWJE3atLVI/AAAAAAAAADY/U98rQvYmUuo/s1600-h/SmallClassDiagram.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_cRjIi2wRv70/SiWJE3atLVI/AAAAAAAAADY/U98rQvYmUuo/s400/SmallClassDiagram.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
And, with the assumption that there will not be more than one instance for any particular descendant type of TestItem in &lt;em&gt;Property3&lt;/em&gt;, the goal was to have a screen that looked like this:&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_cRjIi2wRv70/SiWKtbf7eHI/AAAAAAAAADo/-sR3E5zSEik/s1600-h/GoalScreen.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_cRjIi2wRv70/SiWKtbf7eHI/AAAAAAAAADo/-sR3E5zSEik/s400/GoalScreen.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;h3&gt;The problem&lt;/h3&gt;Setting up the data structures was no problem, nor was getting the master's data on the screen. I used a DataGrid from WPFTools and simple binding sufficed for &lt;em&gt;Property1&lt;/em&gt; and &lt;em&gt;Property2&lt;/em&gt;. But when it came to &lt;em&gt;PropertyA1&lt;/em&gt; and &lt;em&gt;PropertyB1&lt;/em&gt; I ran into problems. Reading the documentation for binding paths, I found I could use the slash character to indicate items in a collection. Going down this trail, I tried setting the paths for the last two columns to &lt;em&gt;Property3/PropertyA1&lt;/em&gt; and &lt;em&gt;Property3/PropertyB1&lt;/em&gt;. This sort of worked:&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_cRjIi2wRv70/SiWKn1MqAyI/AAAAAAAAADg/4o8uG6izYpQ/s1600-h/InitialScreen.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_cRjIi2wRv70/SiWKn1MqAyI/AAAAAAAAADg/4o8uG6izYpQ/s400/InitialScreen.png" /&gt;&lt;/a&gt;&lt;/div&gt;As shown above, the correct data is displayed, but only for the first item in the list. If the order of things in the list is changed, the data changes appropriately. Through the binding path, I could find no way to select different items from the list for different columns in the grid. Perhaps it can be done and I didn't find how, but understandably, this is an odd thing to try to do and it's not a surprise if the framework doesn't support it. &lt;a href="#CollectionBindingSource"&gt;(See CollectionBinding1 in the source code.)&lt;/a&gt;&lt;br /&gt;
&lt;h3&gt;Solution: IValueConverter&lt;/h3&gt;I thought about trying to put the data in the cells directly without binding and, while searching how to do this, was reminded of IValueConverter. From the examples, the standard way of using this is to simply convert between types or to control formatting. However, I realized I could create one that takes the entire list and pulls out from it a specific field.&lt;br /&gt;
&lt;br /&gt;
First, I changed the binding for the two problematic columns to be just &lt;em&gt;Property3&lt;/em&gt;. Then I created a new converter class for each property, and finally instantiated and assigned them to the columns' bindings. This resulted in a one-to-one relationship between converter classes and each property. The converters iterated the list until an entry of its expected type was found and then returned the field value it knew about. A converter for each property: ugly, but it worked! &lt;a href="#CollectionBindingSource"&gt;(See CollectionBinding2 in the source code.)&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
After proving the concept, I looked to clean it up a bit. The only differences between the classes was the type it was looking for and the property it returned. I realized these two things could be parameterized. I could change the converter to a generic class and then use the generic type in the loop. Also, I could pass a lambda expression to the constructor that would later be used in the loop to get the property value if the given type was found. I made these relatively minor changes, eliminating the multiple classes and making the strategy effective for my real world scenario. &lt;a href="#CollectionBindingSource"&gt;(See CollectionBinding3 in the source code.)&lt;/a&gt;&lt;br /&gt;
&lt;h3&gt;Final thoughts&lt;/h3&gt;Typically, converters are instantiated and referenced in the XAML code with just the implementation residing on the C# side. This works because the number of types are relatively small. My original implementation would probably work with this usage pattern, however, in the real world situation, with its one-to-one relationship between properties and converter classes, I would have an inordinate number of classes to have to manage. By moving the instantiation into C#, I can use a single class to handle the different types of objects in the list and the multiple properties in each type.&lt;br /&gt;
&lt;br /&gt;
&lt;div id="CollectionBindingSource"&gt;Source code for the three stages of development is available in a &lt;a href="http://www.fileden.com/files/2008/10/22/2153862/SkylarkSoftware/CollectionBinding.zip"&gt;zip file here.&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Any comments are welcome.&lt;div class="blogger-post-footer"&gt;&lt;hr /&gt;  &lt;a href="http://skylark-software.com"&gt;Skylark Software&lt;/a&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1951153510791888567-6161395684951804712?l=www.skylark-software.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/H9zx__6gLfvCt6HFxUmRKYGX84s/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/H9zx__6gLfvCt6HFxUmRKYGX84s/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/H9zx__6gLfvCt6HFxUmRKYGX84s/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/H9zx__6gLfvCt6HFxUmRKYGX84s/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/SkylarkSoftware/~4/jaBlg7enU3E" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/SkylarkSoftware/~3/jaBlg7enU3E/how-to-display-items-from-collection-in.html</link><author>noreply@blogger.com (Harley Pebley)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_cRjIi2wRv70/SiWJE3atLVI/AAAAAAAAADY/U98rQvYmUuo/s72-c/SmallClassDiagram.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://www.skylark-software.com/2009/08/how-to-display-items-from-collection-in.html</feedburner:origLink></item></channel></rss>

