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

<channel>
	<title>geeks have feelings</title>
	<atom:link href="http://www.geekshavefeelings.com/feed" rel="self" type="application/rss+xml" />
	<link>http://www.geekshavefeelings.com</link>
	<description>xo wang</description>
	<lastBuildDate>Thu, 29 Dec 2011 20:44:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>STRIP DINING PHILOSOPHERS</title>
		<link>http://www.geekshavefeelings.com/posts/strip-dining-philosophers</link>
		<comments>http://www.geekshavefeelings.com/posts/strip-dining-philosophers#comments</comments>
		<pubDate>Mon, 28 Nov 2011 17:08:52 +0000</pubDate>
		<dc:creator>Xo Wang</dc:creator>
				<category><![CDATA[All]]></category>
		<category><![CDATA[Life]]></category>

		<guid isPermaLink="false">http://www.geekshavefeelings.com/?p=1002</guid>
		<description><![CDATA[A GAME FOR ALL AGES RULES: ACQUIRE FORK TO THE RIGHT OF YOU AS WELL AS FORK TO THE LEFT OF YOU. EAT PASTA. REMOVE AN ARTICLE OF CLOTHING. REPEAT. RELATED: STRIP RUSSIAN ROULETTE. NO, NOT WITH A GUN.]]></description>
			<content:encoded><![CDATA[<p>A GAME FOR ALL AGES</p>
<p>RULES: ACQUIRE FORK TO THE RIGHT OF YOU AS WELL AS FORK TO THE LEFT OF YOU. EAT PASTA. REMOVE AN ARTICLE OF CLOTHING. REPEAT.</p>
<p><a href="http://en.wikipedia.org/wiki/Dining_philosophers_problem"><img src="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/11/fork-640x480.jpg" alt="" title="NEVER LOOK AT A FORK THE SAME WAY AGAIN" width="640" height="480" class="alignnone size-large wp-image-1003" /></a></p>
<p>RELATED: STRIP RUSSIAN ROULETTE. NO, NOT WITH A GUN.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.geekshavefeelings.com/posts/strip-dining-philosophers/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bringing up Corntroller</title>
		<link>http://www.geekshavefeelings.com/posts/bringing-up-corntroller</link>
		<comments>http://www.geekshavefeelings.com/posts/bringing-up-corntroller#comments</comments>
		<pubDate>Sat, 22 Oct 2011 18:36:33 +0000</pubDate>
		<dc:creator>Xo Wang</dc:creator>
				<category><![CDATA[All]]></category>
		<category><![CDATA[Corntroller]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[chibios]]></category>
		<category><![CDATA[corntroller]]></category>
		<category><![CDATA[elec.engr]]></category>
		<category><![CDATA[stm32]]></category>

		<guid isPermaLink="false">http://www.geekshavefeelings.com/?p=984</guid>
		<description><![CDATA[I compensate for my engineering mistakes with bigger engineering mistakes. -Me Every new board needs an &#8220;LED blink&#8221; program. It&#8217;s basically a Hello, world! for embedded engineers. Thing is, I put two seven-segment LED arrays on Corntroller, my brushless motor controller, so my LED blink program got a little bit fan-çay: The displays were the [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>I compensate for my engineering mistakes with bigger engineering mistakes. -Me</p></blockquote>
<p>Every new board needs an &#8220;LED blink&#8221; program. It&#8217;s basically a <a href="http://en.wikipedia.org/wiki/Hello_world_program" title="Hello, World!" target="_blank">Hello, world!</a> for embedded engineers. Thing is, I put two seven-segment LED arrays on <a href="http://www.geekshavefeelings.com/posts/category/all/work/corntroller" title="Corntroller" target="_blank">Corntroller</a>, my brushless motor controller, so my LED blink program got a little bit fan-çay:</p>
<p><iframe width="640" height="360" src="http://www.youtube.com/embed/r41xsRYGjas?rel=0&amp;hd=1" frameborder="0" allowfullscreen></iframe></p>
<p>The displays were the first things I wanted to program anyways (USB is next). Among other things, you can display hexadecimal digits on them, which is pretty straightforward from a code perspective:</p>
<pre class="brush: cpp; title: ; notranslate">static struct SevenSegmentDisplay {
public:
	SevenSegmentDisplay(GPIO_TypeDef *gpio, uint8_t offset) :
			gpio(gpio), offset(offset) {
	}

	void showHex(uint8_t x) {
		palClearPort(gpio, 0xF7 &lt;&lt; offset);
		palSetPort(gpio, charLUT[x % 16] &lt;&lt; offset);
	}

	void setDP(bool dp) {
		palWritePad(gpio, offset + 3, dp);
	}

protected:
	GPIO_TypeDef * const gpio;
	const uint8_t offset;

	static const uint8_t charLUT[16];
} red(GPIOD, 8), green(GPIOE, 0);

const uint8_t SevenSegmentDisplay::charLUT[16] = {
		0x77, 0x14, 0xB3, 0xB6,
		0xD4, 0xE6, 0xE7, 0x34,
		0xF7, 0xF6, 0xF5, 0xC7,
		0x63, 0x97, 0xE3, 0xE1
};</pre>
<p>Making that lookup table was the hardest part. Most code is written for &#8220;abcdefg&#8221; bit order, but my LEDs were bit-swizzled since I rearranged my lines to have a cleaner layout. This just meant I needed different bit patterns:</p>
<p><code>// - GFABPCDE<br />
// 0 01110111<br />
// 1 00010100<br />
// 2 10110011<br />
// 3 10110110<br />
// 4 11010100<br />
// 5 11100110<br />
// 6 11100111<br />
// 7 00110100<br />
// 8 11110111<br />
// 9 11110110<br />
// A 11110101<br />
// b 11000111<br />
// C 01100011<br />
// d 10010111<br />
// E 11100011<br />
// F 11100001</code></p>
<p>For a clean layout, it&#8217;s totally worth it.</p>
<p><a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/sevenseg.png"><img src="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/sevenseg-640x504.png" alt="" title="Lines of awesome" width="640" height="504" class="alignnone size-large wp-image-990" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.geekshavefeelings.com/posts/bringing-up-corntroller/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Assembly-izing Tassel</title>
		<link>http://www.geekshavefeelings.com/posts/assembly-izing-tassel</link>
		<comments>http://www.geekshavefeelings.com/posts/assembly-izing-tassel#comments</comments>
		<pubDate>Thu, 20 Oct 2011 05:19:30 +0000</pubDate>
		<dc:creator>Xo Wang</dc:creator>
				<category><![CDATA[All]]></category>
		<category><![CDATA[Corntroller]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[corntroller]]></category>
		<category><![CDATA[elec.engr]]></category>
		<category><![CDATA[stm32]]></category>

		<guid isPermaLink="false">http://www.geekshavefeelings.com/?p=938</guid>
		<description><![CDATA[Tasssel: the extra &#8216;s&#8217; is for &#8220;scattering&#8221; Work continues on Corntroller, my vaguely retarded version of Shane&#8217;s sweet brushless motor controller. I got my Digi-Key order last week and started assembling the board at the Graphics/Visualization/Usability (GVU) Prototyping Lab, the sister lab to the Georgia Tech Invention Studio1, and home to my favorite hot-air reflow [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>Tasssel: the extra &#8216;s&#8217; is for &#8220;scattering&#8221;</p></blockquote>
<p>Work continues on <a href="http://www.geekshavefeelings.com/posts/corn-troller-tassel" title="Corn-Troller: Tassel">Corntroller</a>, my vaguely retarded version of <a href="http://scolton.blogspot.com/search/label/3ph" title="Shane's 3ph duo v3" target="_blank">Shane&#8217;s sweet brushless motor controller</a>.</p>
<p>I got my Digi-Key order last week and started assembling the board at the <a href="https://wiki.cc.gatech.edu/gvu/index.php/PrototypingLab" title="GVU Prototyping Lab" target="_blank">Graphics/Visualization/Usability (GVU) Prototyping Lab</a>, the sister lab to the <a href="http://inventionstudio.gatech.edu/" title="Invention Studio" target="_blank">Georgia Tech Invention Studio</a><sup><a href="http://www.geekshavefeelings.com/posts/assembly-izing-tassel#footnote_0_938" id="identifier_0_938" class="footnote-link footnote-identifier-link" title="At least in sweet, sweet funding">1</a></sup>, and home to my favorite hot-air reflow station on campus for prototyping.</p>
<p>Now the thing about reflow soldering is that it perfectly captures the sights, sounds, and smells of hell.</p>
<p>What else but hell would make you sit in place, hunched over for hours, as electric fire brings tears to your eyes and solder paste brimstone pierces your nostrils? Bright incandescent lighting, smoldering soldering irons, and in the case of the GVU reflow station, a 50-decibel electric pump all magnify the feeling of burning alive in invidious flames of divine wrath.</p>
<p><iframe width="640" height="360" src="http://www.youtube.com/embed/fyt_DEAbSOU?rel=0&amp;hd=1" frameborder="0" allowfullscreen></iframe></p>
<p>But the GVU version of surface mount hell is actually pretty legit. The aforementioned electric pump is hooked up to a precision solenoid valve gas dispenser (controlled by a foot pedal), which in turn feeds pressurized air into a hand-held tube of leaded solder paste. Hit the foot pedal, and a small and carefully controlled bit of gray goop flows out.</p>
<p>The setup basically lets you do manual pick and place assembly. Less efficient for small and medium runs than <a href="http://www.sparkfun.com/tutorials/58" title="Sparkfun Solder Paste Stenciling tutorial" target="_blank">solder paste stenciling</a>, but way less setup time and a lot more fun<sup><a href="http://www.geekshavefeelings.com/posts/assembly-izing-tassel#footnote_1_938" id="identifier_1_938" class="footnote-link footnote-identifier-link" title="No, not really">2</a></sup>. It&#8217;s perfect for prototyping a new board.</p>
<p>Now I ended up shooting video instead of taking too many pictures, so bear with my video screenshots here.</p>
<p>To make life easier, I assemble components under a 10×/30× stereo microscope with tweezers in one hand, solder paste dispenser in the other, and foot on the foot pedal.</p>
<p><a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/microscope_pnp.jpg"><img src="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/microscope_pnp-640x360.jpg" alt="" title="Microscope pick&#039;n&#039;place (you totally can&#039;t see my new faux hawk in this photo)" width="640" height="360" class="alignnone size-large wp-image-944" /></a></p>
<p>At 10× you can see the particles in the solder paste.</p>
<p><a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/DSC01646.jpg"><img src="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/DSC01646-640x425.jpg" alt="" title="7-segment closeup, unreflown" width="640" height="425" class="alignnone size-large wp-image-947" /></a></p>
<p>After assembly, I preheat the board over a <a href="http://www.zeph.com/smdpreheater.htm" title="No One Knows More About Preheating PCB's Than Zephyrtronics!" target="_blank">Zephyrtronics&#8230; board preheater</a>.</p>
<p><a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/board_preheater.jpg"><img src="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/board_preheater-640x360.jpg" alt="" title="Its uses include, and is limited to, board preheating" width="640" height="360" class="alignnone size-large wp-image-949" /></a></p>
<p>I&#8217;m not even making this up. This thing emulates the flat &#8220;warm-up&#8221; period of the reflow temperature profile you&#8217;d use in a full reflow oven. In addition, it has a <em>genius</em> &#8220;cool&#8221; mode during which it draws air down (instead of blowing hot air up), using ambient air to cool the board (&#8220;ramp-down&#8221;). No more blowing on the board until your face is red and your tongue is covered with flakes of solder.</p>
<p><a href="http://www.allegromicro.com/en/corporate/environment/faqs.asp#Q14"><img src="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/pbReflowProfile.gif" alt="" title="Allegro&#039;s recommended reflow profile" width="508" height="283" class="alignnone size-full wp-image-950" /></a></p>
<p>It even comes with a sweet PCB jig to hold your board at just the right height above the pre-heater.</p>
<p><a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/DSC01636.jpg"><img src="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/DSC01636-640x425.jpg" alt="" title="Preheat" width="640" height="425" class="alignnone size-large wp-image-948" /></a></p>
<p>After that, you pretty much just apply heat like a normal person.</p>
<p><a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/hotairgun.jpg"><img src="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/hotairgun-640x360.jpg" alt="" title="Lefrowing" width="640" height="360" class="alignnone size-large wp-image-951" /></a></p>
<p>You may notice that in addition to unpopulated inertial sensors, there are also two funny-looking solder bridges.</p>
<p><a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/ze_germans.jpg"><img src="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/ze_germans-640x425.jpg" alt="" title="Laßt uns froh sein!" width="640" height="425" class="alignnone size-large wp-image-952" /></a></p>
<p>You have ze Germans to blame for that. Had I the European-styled schematic symbols für a <a href="http://en.wikipedia.org/wiki/Choke_(electronics)#Common-mode_choke" title="Common mode choke" target="_blank">common-mode choke</a> ge-used, which had I the wrong orientation for the part ge-using. I think.</p>
<p>In other words, I managed to short my input power leads across a pair of inductors.</p>
<p><a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/eurotraschematic.png"><img src="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/eurotraschematic-640x373.png" alt="" title="eurotraschematic" width="640" height="373" class="alignnone size-large wp-image-963" /></a></p>
<p>Not that that surprises me in the least; I&#8217;ve managed to build almost every circuit I&#8217;ve ever designed to have a short from power to ground. Heck, this is the probably the highest impedance short I&#8217;ve gotten on a first-try board in the past two years.</p>
<p>Actually, maybe the footprint I was using for my <a href="http://katalog.we-online.de/kataloge/eisos/media/pdf/744232261.pdf" title="WE-CNS_1206" target="_blank">Würth-Elektronik common-mode choke</a> just had a mistake in pin assignments. But I like to chalk it up to cultural differences, since it&#8217;s 34% more hilarious that way.</p>
<p>At any rate, I ended up skipping the choke completely using solder bridges; I get less noise immunity, but hey, nobody&#8217;s perfect and I&#8217;m not sure if it would&#8217;ve even helped at all.</p>
<p>At this point, it was time to try out the logic power supply. With fingers crossed, I hook up the bench power supply to the <em>V+</em> and <em>V-</em> power pads and hit the switch.</p>
<p>Nothing.</p>
<p>Turns out when soldering leads to the V- pad while &#8220;e-testing&#8221; the board, I had broken one of the traces from the pad.</p>
<p><a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/DSC01649.jpg"><img src="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/DSC01649-640x425.jpg" alt="" title="Oops" width="640" height="425" class="alignnone size-large wp-image-954" /></a></p>
<p>Oops.</p>
<p>I haven&#8217;t made a soldering boo-boo this bad in years, but whatever. I briefly considered running a little green wire over the trace<sup><a href="http://www.geekshavefeelings.com/posts/assembly-izing-tassel#footnote_2_938" id="identifier_2_938" class="footnote-link footnote-identifier-link" title="I hear in some Asian electrical engineering tria- circles, using more than 三 (3) little green wires is a shame to the engineer&amp;#8217;s family and results in decapita- ritual de-accreditation">3</a></sup>, but then realized that I tented over all my vias with soldermask<sup><a href="http://www.geekshavefeelings.com/posts/assembly-izing-tassel#footnote_3_938" id="identifier_3_938" class="footnote-link footnote-identifier-link" title="Yeah. On a first-version prototype. Balls, suckas.">4</a></sup> and couldn&#8217;t airwire even if I wanted to.</p>
<p>Instead I just ripped up the soldermask with an X-acto knife under 30× magnification and then solder bridged the shorn copper. <em>Like a boss.</em></p>
<p><a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/DSC01651.jpg"><img src="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/DSC01651-300x199.jpg" alt="" title="Scrape scrape scrape" width="300" height="199" class="alignnone size-medium wp-image-955" /></a> <a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/DSC01652.jpg"><img src="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/DSC01652-300x199.jpg" alt="" title="Solder solder solder" width="300" height="199" class="alignnone size-medium wp-image-956" /></a></p>
<p>Now I was getting a sweet 3.304V out of my LT3970 circuit from an input of 4V all the way up to 31V, which was as high as the power supply could go. Not really sure why this mattered, since I&#8217;ll always be putting 5V into the board, but whatever.</p>
<p>But why the heck am I posting about such minor minutiae as fixing a broken trace when I should be plopping down code like a pro? Well, because performing board bringup<sup><a href="http://www.geekshavefeelings.com/posts/assembly-izing-tassel#footnote_4_938" id="identifier_4_938" class="footnote-link footnote-identifier-link" title="&amp;#8220;Performing board bringup&amp;#8221; sounds way cooler than &amp;#8220;bringing up&amp;#8221;">5</a></sup> on an STM32-based board like this is an (necessary) act of distilled masochism, and I avoid it like a plague even when I&#8217;m already <em>working on the board to begin with</em>. I mean, hell, the software you use with the popular GCC/GDB ARM toolchain is called <a href="http://openocd.sourceforge.net/" title="OpenOCD" target="_blank">OpenOCD</a>.</p>
<p><a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/openocd.png"><img src="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/openocd-640x335.png" alt="" title="Open... OCD?" width="640" height="335" class="alignnone size-large wp-image-958" /></a></p>
<p>So I plug my board into my <a href="http://www.olimex.com/dev/arm-usb-tiny-h.html" title="ARM-USB-TINY-H" target="_blank">Olimex ARM-USB-TINY-H</a> and then pray to Tony Stark to guide my board to a successful JTAG interrogation.</p>
<pre>C:\Users\Xo>"C:\Program Files (x86)\OpenOCD-0.4.0\bin\openocd.exe" -f interface\olimex-arm-usb-tiny-h.cfg -f target\stm32.cfg
Open On-Chip Debugger 0.5.0-dev-00753-g422e9f9-dirty (2011-02-14-13:06)
Licensed under GNU GPL v2
For bug reports, read

http://openocd.berlios.de/doc/doxygen/bugs.html

Info : only one transport option; autoselect 'jtag'
1000 kHz
adapter_nsrst_delay: 100
jtag_ntrst_delay: 100
Info : device: 6 "2232H"
Info : deviceID: 364511274
Info : SerialNumber: OLTQ5QMÖA
Info : Description: Olimex OpenOCD JTAG ARM-USB-TINY-H A
Info : max TCK change to: 30000 kHz
Info : clock speed 1000 kHz
Info : JTAG tap: stm32.cpu tap/device found: 0x3ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x3)
Info : JTAG tap: stm32.bs tap/device found: 0x06430041 (mfg: 0x020, part: 0x6430, ver: 0x0)
Warn : JTAG tap: stm32.bs       UNEXPECTED: 0x06430041 (mfg: 0x020, part: 0x6430, ver: 0x0)
Error: JTAG tap: stm32.bs  expected 1 of 5: 0x06412041 (mfg: 0x020, part: 0x6412, ver: 0x0)
Error: JTAG tap: stm32.bs  expected 2 of 5: 0x06410041 (mfg: 0x020, part: 0x6410, ver: 0x0)
Error: JTAG tap: stm32.bs  expected 3 of 5: 0x16410041 (mfg: 0x020, part: 0x6410, ver: 0x1)
Error: JTAG tap: stm32.bs  expected 4 of 5: 0x06414041 (mfg: 0x020, part: 0x6414, ver: 0x0)
Error: JTAG tap: stm32.bs  expected 5 of 5: 0x06418041 (mfg: 0x020, part: 0x6418, ver: 0x0)
Error: Trying to use configured scan chain anyway...
Warn : Bypassing JTAG setup events due to errors
Info : stm32.cpu: hardware has 6 breakpoints, 4 watchpoints</pre>
<p>&#8220;hardware has 6 breakpoints, 4 watchpoints&#8221; is actually what I expect to see, making this by far my most successful board bringup to date. But wait, what are those errors? Why isn&#8217;t my device (<code>0x06430041</code>) being recognized? Let&#8217;s take a look at the <code>stm32.cfg</code> script:</p>
<pre class="brush: bash; first-line: 43; highlight: [43,44]; title: ; notranslate">    # See STM Document RM0008
    # Section 29.6.2
    # Low density devices, Rev A
    set _BSTAPID1 0x06412041
    # Medium density devices, Rev A
    set _BSTAPID2 0x06410041
    # Medium density devices, Rev B and Rev Z
    set _BSTAPID3 0x16410041
    # High density devices, Rev A
    set _BSTAPID4 0x06414041
    # Connectivity line devices, Rev A and Rev Z
    set _BSTAPID5 0x06418041</pre>
<p>Oops, my STM32F103VG XL-density microcontroller isn&#8217;t in there. The comments mention Section 29.6.2 of RM0008, the STM32F1x Family Reference Manual. In section 31.6.2 (dotdotdot) of the <a href="http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/REFERENCE_MANUAL/CD00171190.pdf" title="Reference manual" target="_blank">newest version of RM0008</a><sup><a href="http://www.geekshavefeelings.com/posts/assembly-izing-tassel#footnote_5_938" id="identifier_5_938" class="footnote-link footnote-identifier-link" title="As of 2011/10/19">6</a></sup>, we see that <code>0x06430041</code> is Revision A of XL-density devices.</p>
<p>So I need a more recent version of OpenOCD that has the newer STM32 devices. Crap.</p>
<p>See, I use the default vanilla FTDI drivers for my Olimex, presumably so I can use the Virtual COM Port driver for the broken-out UART the ARM-USB-TINY-H doesn&#8217;t have. Yeah, I&#8217;m dumb. But OpenOCD doesn&#8217;t support those drivers out of the box; licensing issues prevent binary distributors like <a href="http://www.freddiechopin.info/index.php/en/download/category/4-openocd" title="Freddie Chopin's OpenOCD builds" target="_blank">Freddie Chopin</a> from making available binaries compatible with regular FTDI drivers. Instead most people use <a href="http://www.intra2net.com/en/developer/libftdi/" title="libftdi" target="_blank">libftdi</a> and <a href="http://www.libusb.org/wiki/libusb-win32" title="libusb-win32" target="_blank">libusb-win32</a> for hardware interfacing on Windows.</p>
<p>So I gotta build OpenOCD myself to make it work? God damn it; what is this, Linux?</p>
<p>Let&#8217;s just say <code>$ ./configure --prefix=/cygdrive/c/Users/Xo/Desktop/ocd-build/out --enable-maintainer-mode --disable-werror --disable-shared --enable-ft2232_ftd2xx --with-ftd2xx-win32-zipdir=/cygdrive/c/Users/Xo/Desktop/ocd-build/ftd2xx CC="gcc -mno-cygwin"</code><sup><a href="http://www.geekshavefeelings.com/posts/assembly-izing-tassel#footnote_6_938" id="identifier_6_938" class="footnote-link footnote-identifier-link" title="Yeah, that really is for my benefit only. How did you guess?">7</a></sup></p>
<p>With my new OpenOCD <code>0.6.0-dev</code> build, I got a fully successful JTAG scan, and the OpenOCD GDB server is now open for business:</p>
<pre>C:\Users\Xo>openocd -c "gdb_port 2222" -c "telnet_port 4444" -f "C:/Progra~2/OpenOCD/interface/olimex-arm-usb-tiny-h.cfg" -f "C:/Progra~2/OpenOCD/target/stm32f1x.cfg"
Open On-Chip Debugger 0.6.0-dev (2011-10-19-22:04)
Licensed under GNU GPL v2
For bug reports, read

http://openocd.sourceforge.net/doc/doxygen/bugs.html

Info : only one transport option; autoselect 'jtag'
1000 kHz
adapter_nsrst_delay: 100
jtag_ntrst_delay: 100
cortex_m3 reset_config sysresetreq
Info : device: 6 "2232H"
Info : deviceID: 364511274
Info : SerialNumber: OLTQ5QMÖA
Info : Description: Olimex OpenOCD JTAG ARM-USB-TINY-H A
Info : max TCK change to: 30000 kHz
Info : clock speed 1000 kHz
Info : JTAG tap: stm32.cpu tap/device found: 0x3ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x3)
Info : JTAG tap: stm32.bs tap/device found: 0x06430041 (mfg: 0x020, part: 0x6430, ver: 0x0)
Info : stm32.cpu: hardware has 6 breakpoints, 4 watchpoints</pre>
<p>lol @ <code>C:/Progra~2</code>. Because this thing <em>f—ing breaks</em> if I don&#8217;t.</p>
<ol class="footnotes"><li id="footnote_0_938" class="footnote">At least in sweet, sweet <a href="http://support.cc.gatech.edu/resources/technology-fees/tech-fee.inventionlab.2.pdf" title="Tech Fee request" target="_blank">funding</a></li><li id="footnote_1_938" class="footnote">No, not really</li><li id="footnote_2_938" class="footnote">I hear in some Asian electrical engineering <del datetime="2011-10-20T03:21:26+00:00">tria-</del> circles, using more than 三 (3) little green wires is a shame to the engineer&#8217;s family and results in <del datetime="2011-10-20T03:21:26+00:00">decapita-</del> ritual de-accreditation</li><li id="footnote_3_938" class="footnote">Yeah. On a first-version prototype. <em>Balls</em>, suckas.</li><li id="footnote_4_938" class="footnote">&#8220;Performing board bringup&#8221; sounds way cooler than &#8220;bringing up&#8221;</li><li id="footnote_5_938" class="footnote">As of 2011/10/19</li><li id="footnote_6_938" class="footnote">Yeah, that really is for my benefit only. How did you guess?</li></ol>]]></content:encoded>
			<wfw:commentRss>http://www.geekshavefeelings.com/posts/assembly-izing-tassel/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Corn-Troller: Tassel</title>
		<link>http://www.geekshavefeelings.com/posts/corn-troller-tassel</link>
		<comments>http://www.geekshavefeelings.com/posts/corn-troller-tassel#comments</comments>
		<pubDate>Wed, 12 Oct 2011 09:23:33 +0000</pubDate>
		<dc:creator>Xo Wang</dc:creator>
				<category><![CDATA[All]]></category>
		<category><![CDATA[Corntroller]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[corntroller]]></category>
		<category><![CDATA[elec.engr]]></category>
		<category><![CDATA[ev]]></category>
		<category><![CDATA[stm32]]></category>

		<guid isPermaLink="false">http://www.geekshavefeelings.com/?p=920</guid>
		<description><![CDATA[Looking around at the hoppin&#8217; electric vehicle scene happening at certain institutions, I realized that pretty soon I&#8217;d be playing catch-up to more than just Jamo when it comes stuff-strutting unless I started building something ridiculous, and quickly too. So in typical son-of-an-accountant behavior, instead of building my own scooter, I decided to go the [...]]]></description>
			<content:encoded><![CDATA[<p>Looking around at the <a href="http://www.youtube.com/watch?v=b4W3iYRPeX4?hd=1" target="_blank">hoppin&#8217; electric vehicle scene</a> happening at <a title="GT Invention Studio" href="http://inventionstudio.gatech.edu/" target="_blank">certain</a> <a title="MITERS" href="http://miters.mit.edu/" target="_blank">institutions</a>, I realized that pretty soon I&#8217;d be playing catch-up to more than just <a href="http://thevariableconstant.blogspot.com/" target="_blank">Jamo</a> when it comes stuff-strutting unless I started building something ridiculous, and quickly too.</p>
<p>So in typical son-of-an-accountant behavior, instead of building my own scooter, I decided to go the manic whacky sneaky route and build something to sell to the scooter builders. So now I&#8217;m announcing the corniest, trolliest brushless motor controller of them all: <em>Corntroller</em>.</p>
<p><a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/corntroller_text.jpg"><img class="alignnone size-large wp-image-922" title="Corntroller" src="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/corntroller_text-640x425.jpg" alt="" width="640" height="425" /></a></p>
<p>Corntroller is a result of me completely ripping off <a title="Shane's motor controllers" href="http://scolton.blogspot.com/p/motor-controllers.html" target="_blank">Shane Colton</a> and <a title="Dan's Brushless DC motor controller board" href="http://danstrother.com/2011/01/12/brushless-dc-motor-controller-board/" target="_blank">Dan Strother</a> to build an extremely feature-bloated brushless motor controller. All of the following will be devoted to driving just a single motor:</p>
<ul>
<li>Modular corn-inspired design, stacking a logic board (called <em>Tassel</em>) onto a power board (called <em>HexHusk</em>)</li>
<li>10V–45V operation with two switching regulators for logic power (<a title="LT3991" href="http://www.linear.com/product/LT3991" target="_blank">LT3991-5</a>, <a title="LT3970" href="http://www.linear.com/product/LT3970" target="_blank">LT3970-3.3</a>)</li>
<li>At least 40A of current capacity through <a title="GWM160-0055X1" href="http://ixdev.ixys.com/DataSheet/GWM160-0055X1.pdf" target="_blank">IXYS GWM160-0055X1</a> 3-phase MOSFET power modules</li>
<li>Way too much processing power from a 100-pin <a title="STM32F103VG" href="http://www.st.com/internet/mcu/product/247492.jsp" target="_blank">STM32F103VG</a>, one of the top parts in the STM32 F1 series of ARM Cortex M3 microcontrollers</li>
<li>Full voltage and current sensing on everything (motor phases and power bus), so I can implement vector control or sensorlessness</li>
<li>Compact three-phase N-channel FET driving through dedicated gate driver IC (<a href="http://www.allegromicro.com/en/Products/Part_Numbers/4935/" target="_blank">A4935</a>)</li>
<li>Motor hall sensor inputs to microcontroller capture timer</li>
<li>microSD card slot interfaced through SDIO (not MMC over SPI) for <a title="*cough*" href="http://scolton.blogspot.com/2010/09/midi-for-your-motor.html" target="_blank">datalogging</a></li>
<li>Full speed USB interface&#8230; just because</li>
<li>Two 7-segment LED displays&#8230; also just because</li>
<li>Full 9-degrees-of-measure IMU (accelerometer, gyroscope, magnetometer) with the some of the best dumb<sup><a href="http://www.geekshavefeelings.com/posts/corn-troller-tassel#footnote_0_920" id="identifier_0_920" class="footnote-link footnote-identifier-link" title="Read: non-intelligent, where &amp;#8220;intelligent&amp;#8221; is a technical term">1</a></sup> MEMS sensors (<a href="http://www.bosch-sensortec.com/content/language1/downloads/BST-BMA180-FL000-03.pdf" title="BMA180" target="_blank">BMA180</a>, <a href="http://invensense.com/mems/gyro/tripleaxis.html" title="IMU3000" target="_blank">IMU3000</a>, <a href="http://www.magneticsensors.com/three-axis-digital-compass.php" title="HMC5883L" target="_blank">HMC5883L</a>) available&#8230; just $@#%ing because</li>
</ul>
<p>I&#8217;m only half-joking about that last one; I designed <em>Tassel</em>, the logic board on Corntroller, as a replacement for my (yet to be written up) <em>Maizure</em> Cortex M3/MEMS sensors board. Maizure has served as my general dev board, and its successor is so full featured and has such overspec&#8217;d components because of that. But, I can choose to not populate components for unused features. So when Tassel is used as a part of Corntroller, it will not have its 3-axis MEMS sensor footprints populated<sup><a href="http://www.geekshavefeelings.com/posts/corn-troller-tassel#footnote_1_920" id="identifier_1_920" class="footnote-link footnote-identifier-link" title="Or maybe it will&amp;#8230; what electric vehicle could use an IMU?  ">2</a></sup>.</p>
<p>By the way, I started naming my projects after corn. Just—you guessed it—because.</p>
<p><a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/tassel_text.jpg"><img class="alignnone size-large wp-image-923" title="Tassel" src="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/tassel_text-640x426.jpg" alt="" width="640" height="426" /></a></p>
<p>Tassel was laid out with only surface mount components (preferring 0603<sup><a href="http://www.geekshavefeelings.com/posts/corn-troller-tassel#footnote_2_920" id="identifier_2_920" class="footnote-link footnote-identifier-link" title="That&amp;#8217;s 6 mils by 3 mils or 0.006&Prime;&times;0.003&Prime;">3</a></sup> chip resistors and capacitors), all on the top side. Layout was actually fairly straightforward, since a lot of the work required just routing directly from STM32 pins to headers (which I could reassign anyways).</p>
<p>The hard part was figuring out which peripherals I could route <em>out of the STM32</em>. The original plan was to use a 48-pin device; this grew to 64-pin and then 100-pin as I realized that all the &#8220;good&#8221; peripherals I wanted in the STM32 were actually sharing the same pins.</p>
<p>For example, USART1 and TIM1 (with its useful three-phase complemented PWM with software deadtime insertion) shared the same pins. I had to spend a solid week assigning pins to their functionalities, restarting all over each time I had to up the pin count and move to a bigger device. Through all of this I also had to make sure to fan everything out properly so wires route cleanly from µC pin to headers and devices.</p>
<p>That&#8217;s really how I ended up with 7-segment displays; switching to 100 pins meant I had a lot of I/O pins left over that I didn&#8217;t want to go to waste. With the decimal point, each <a href="http://www.kingbrightusa.com/category.asp?catalog%5Fname=LED&#038;category%5Fname=KC0%2E2in+1%2DDigit" title="Kingbright 10-SMD ACS 7-segment LED display" target="_blank">Kingbright 0.2&#8243; display</a> fills up 8 pins: perfect for half a GPIO port, and thus nice to control in software.</p>
<p>Plus, 7-segment displays and resistor arrays are way easier to solder than individual 0805 LEDs and 0603 resistors.</p>
<p>So I ended up with a long list of nets to route well before even starting a schematic in <a title="CadSoft - EAGLE" href="http://www.cadsoftusa.com/" target="_blank">EAGLE</a> (see appendix)!</p>
<p><a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/tassel_layout.png"><img src="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/tassel_layout-640x383.png" alt="" title="Tassel layout" width="640" height="383" class="alignnone size-large wp-image-927" /></a></p>
<p>Since Maizure had a bit of problems with noise and stability, I made Tassel a four-layer design. This means extra layers of copper on which to route signals, but more importantly to serve as ground planes for surface signals. This isn&#8217;t necessarily <em>needed</em>, but it certainly lends me extra noise immunity I figure I&#8217;d want on such a densely routed board.</p>
<p>A four-layer design meant I had way fewer choices in PCB fabrication: I went with <a title="Laen's group order" href="http://www.dorkbotpdx.org/wiki/pcb_order" target="_blank">Dorkbot Portland&#8217;s group PCB order</a>, but also considered <a title="4PCB $66 each" href="http://www.4pcb.com/index.php?load=content&amp;page_id=131" target="_blank">4PCB&#8217;s/Advanced Circuits&#8217;s $66 each service</a> and <a title="BatchPCB 4-layer" href="http://batchpcb.com/index.php/Faq#what_are_the_pcb_rules" target="_blank">BatchPCB&#8217;s 4-layer group order</a>. For me, DorkbotPDX just turned out to be the best bang for the buck.</p>
<p><a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/DSC01582.jpg"><img src="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/DSC01582-640x425.jpg" alt="" title="Tassel in the wind" width="640" height="425" class="alignnone size-large wp-image-930" /></a></p>
<p>Why do I just have photos of unpopulated boards? Because (a) they&#8217;re pretty and (b) I sent these out before I finished designing the power stage, in an attempt to pipeline the prototyping process. I wanted to send these out, complete HexHusk, order parts for both from Digi-Key, and have the components before Tassel&#8217;s boards arrived. That didn&#8217;t happen&#8230; the Digi-Key order is just now in the mail. Guess I failed at pipelining.</p>
<p>Design files for everything and a HexHusk post are coming. I promise.</p>
<p><strong>Appendix</strong><br />
Partial pin assignments:</p>
<pre>Outputs
=======
# Q1
15 PC0 V_P
16 PC1 V_A
17 PC2 V_B
18 PC3 V_C
23 PA0 I_A
24 PA1 I_B
25 PA2 I_P

# Q2
26 PA3 AN_0
29 PA4 SPI1_NSS
30 PA5 SPI1_SCK
31 PA6 SPI1_MISO
32 PA7 SPI1_MOSI
- V+
- V-

- 3.3V
39 PE8 PWM1~ # remap
40 PE9 PWM1 # remap
41 PE10 PWM2~ # remap
42 PE11 PWM2 # remap
43 PE12 PWM3~ # remap
44 PE13 PWM3 # remap

# Q3
68 PA9 USART1_TX
69 PA10 USART1_RX
# Q4
86 PD5 H1 # 5V
87 PD6 H2 # 5V
88 PD7 H3 # 5V
92 PB6 I2C1_SCL
93 PB7 I2C1_SDA

JTAG
====
- 3.3V
PB4 JTRST
PA15 JTDI
PA13 JTMS
PA14 JTCK
PB3 JTDO
NRST RESET
- V-

USB
===
PA11 USB_D-
PA12 USB_D+
- V+
- V-

SDIO
====
PC8 SDIO_D0
PC9 SDIO_D1
PC10 SDIO_D2
PC11 SDIO_D3
PC12 SDIO_CK
PD2 SDIO_CMD

MEMS
====
PB10 I2C2_SCL
PB11 I2C2_SDA
PB12 SPI2_NSS
PB13 SPI2_SCK
PB14 SPI2_MISO
PB15 SPI2_MOSI</pre>
<ol class="footnotes"><li id="footnote_0_920" class="footnote">Read: non-intelligent, where &#8220;intelligent&#8221; is a <a href="http://en.wikipedia.org/wiki/Intelligent_sensor" title="WP: Intelligent sensor" target="_blank">technical term</a></li><li id="footnote_1_920" class="footnote">Or maybe it will&#8230; what electric vehicle could use an IMU? <img src='http://www.geekshavefeelings.com/x/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </li><li id="footnote_2_920" class="footnote">That&#8217;s 6 mils by 3 mils or 0.006″×0.003″</li></ol>]]></content:encoded>
			<wfw:commentRss>http://www.geekshavefeelings.com/posts/corn-troller-tassel/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>5V to 3.3V with Preferred Resistors</title>
		<link>http://www.geekshavefeelings.com/posts/5v-to-3-3v-with-preferred-resistors</link>
		<comments>http://www.geekshavefeelings.com/posts/5v-to-3-3v-with-preferred-resistors#comments</comments>
		<pubDate>Sun, 02 Oct 2011 00:33:26 +0000</pubDate>
		<dc:creator>Xo Wang</dc:creator>
				<category><![CDATA[All]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[elec.engr]]></category>
		<category><![CDATA[resistor]]></category>
		<category><![CDATA[resistor.divider]]></category>

		<guid isPermaLink="false">http://www.geekshavefeelings.com/?p=893</guid>
		<description><![CDATA[What do you do when you want to scale a 5V analog signal to 3.3V? You build a resistor divider, possibly with an op amp-based voltage follower to drive low impedance loads. But what resistors do you buy for your resistor bridge? You want resistance values of some multiple of 1.7 to 3.3, but resistors [...]]]></description>
			<content:encoded><![CDATA[<p>What do you do when you want to scale a 5V analog signal to 3.3V? You build a resistor divider, possibly with an op amp-based voltage follower to drive low impedance loads.</p>
<p><a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/microchip_en026368.pdf.png"><img src="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/10/microchip_en026368.pdf-300x152.png" alt="" title="microchip_en026368.pdf" width="300" height="152" class="alignnone size-medium wp-image-917" /></a></p>
<p>But what resistors do you buy for your resistor bridge? You <em>want</em> resistance values of some multiple of 1.7 to 3.3, but resistors come in <a title="Resistor decades" href="http://www.logwell.com/tech/components/resistor_values.html">preferred values</a>, which are mathemagicatically spaced out resistance scales.</p>
<p>None of the &#8220;nice&#8221; E24 values that are multiples of 170 or 330 really work (330 exists, but not 170; there&#8217;s a 510 but no 990; and 680 but no 1320).</p>
<p>There&#8217;s gotta be some kind of ideal combination of preferred-value resistors that give me either the perfect 5V to 3.3V divider, or at least minimizes the error. Well, I wasn&#8217;t about to do all 24² combinations of upper/lower resistors by hand and for some reason Google couldn&#8217;t find it for me, so I wrote a <del>script</del> C++0x program to uh&#8230; do it for me<sup><a href="http://www.geekshavefeelings.com/posts/5v-to-3-3v-with-preferred-resistors#footnote_0_893" id="identifier_0_893" class="footnote-link footnote-identifier-link" title="Actually, the code runs in O(N * log N) time rather than O(N&sup2;) time: given some high-side resistance, I run a binary search on which low-side resistor value gives the best divider. I loop over all high-side resistances.">1</a></sup>.</p>
<p>So what are the results for each EIA resistor value series?</p>
<pre>E12 best: r1 = 180, r2 = 330 (-5.556%)
E24 best: r1 = 470, r2 = 910 (-0.258%)
E48 best: r1 = 825, r2 = 1600 (-0.092%)
E96 best: r1 = 491, r2 = 953 (-0.012%)
E192 best: r1 = 102, r2 = 198 (+0.000%)</pre>
<p>Those error percentages are for voltage drop over the top half of the resistor divider, not for the resulting voltages. For example, the 180 &amp; 330 combo would have an error of <img src='http://s.wordpress.com/latex.php?latex=%5Cleft%28%5Cfrac%7B330%7D%7B180%20%2B%20330%7D%20%5Cdiv%20%5Cfrac%7B3.3%7D%7B5%7D%20-%201%5Cright%29%20%5Ctimes%20100%5C%25%20%3D%20-1.96%5C%25&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\left(\frac{330}{180 + 330} \div \frac{3.3}{5} - 1\right) \times 100\% = -1.96\%' title='\left(\frac{330}{180 + 330} \div \frac{3.3}{5} - 1\right) \times 100\% = -1.96\%' class='latex' />. Not bad for parts you can get at RadioShack.</p>
<p>It turns E192 does have a perfect combo, but it&#8217;s not like E192-series resistors are available from Digi-Key. However, you can get E96 resistors to build a divider with only -0.0042% error, which will have so much error due to <a href="http://www.edn.com/article/509250-7_solution.php">the bimodal distribution of binned resistor values</a> that the time you&#8217;ve spent on making it &#8220;correct&#8221; would be completely wasted.</p>
<p>Damn.</p>
<h2>Appendix: &#8216;Dat code</h2>
<pre class="brush: cpp; title: ; notranslate">
/*
 * 2011 Xo Wang
 * I hereby release this into the public domain, something about merchantability, blah blah. If you use it, it'd be nice to let me know.
 *
 * You'd be an idiot to use this; it does many things very wrong for the sake of expedient solution-getting.
 */

#include &lt;algorithm&gt; // &lt;3 lower_bound, &lt;3 set_union
#include &lt;iostream&gt;
#include &lt;limits&gt;
#include &lt;string&gt;
#include &lt;vector&gt;

#include &lt;cstdlib&gt;

static double error(const double r1, const double r2) {
	return (r2 * 1.7) / (r1 * 3.3) - 1.0;
}

static void process_series(const std::string &amp;name, const std::vector&lt;int&gt; series) {
	using namespace std;

	int min_error_r1 = 0;
	int min_error_r2 = 0;
	double min_error = numeric_limits&lt;double&gt;::max();
	for_each(series.begin(), series.end(), [&amp;](const int r1) {
		// find nearest resistance
		const double r2_wanted = r1 * (3.3 / 1.7);
		// r_wanted is too large, so scale it down by ten when searching
		const bool r2_wanted_10x = r2_wanted &gt; series.back();
		const auto r2_higher_iter = lower_bound(series.begin(), series.end(), r2_wanted_10x ? r2_wanted * 0.1 : r2_wanted);

		// nearest two resistance values
		const int r2_higher = r2_wanted_10x ? *r2_higher_iter * 10 : *r2_higher_iter;
		const int r2_lower = [=]() -&gt; int {
			if (r2_higher == series[0] * 10) {
				return series.back();
			}
			return r2_wanted_10x ? *(r2_higher_iter - 1) * 10 : *(r2_higher_iter - 1);
		}();

		if (fabs(min_error) &gt; fabs(error(r1, r2_lower))) {
			min_error = error(r1, r2_lower);
			min_error_r1 = r1;
			min_error_r2 = r2_lower;
		}

		if (fabs(min_error) &gt; fabs(error(r1, r2_higher))) {
			min_error = error(r1, r2_higher);
			min_error_r1 = r1;
			min_error_r2 = r2_higher;
		}

		//cout &lt;&lt; &quot;  r1 = &quot; &lt;&lt; r1 &lt;&lt; &quot;, r2 = { &quot; &lt;&lt;
		//		r2_lower &lt;&lt; &quot; (&quot; &lt;&lt; error(r1, r2_lower) * 100 &lt;&lt; &quot;%), &quot; &lt;&lt;
		//		r2_higher &lt;&lt; &quot; (+&quot; &lt;&lt; error(r1, r2_higher) * 100 &lt;&lt; &quot;%) }\n&quot;;
	});

	cout &lt;&lt; name &lt;&lt; &quot; best: r1 = &quot; &lt;&lt; min_error_r1 &lt;&lt; &quot;, r2 = &quot; &lt;&lt; min_error_r2 &lt;&lt;
			&quot; (&quot; &lt;&lt; (min_error &gt; 0 ? &quot;+&quot; : &quot;&quot;) &lt;&lt; min_error * 100 &lt;&lt; &quot;%)\n&quot;;
}

static std::vector&lt;int&gt; merge_series(const std::vector&lt;int&gt; &amp;s1, const std::vector&lt;int&gt; &amp;s2) {
	using namespace std;
	vector&lt;int&gt; out_series(s1.size() + s2.size());
	auto last = set_union(s1.begin(), s1.end(), s2.begin(), s2.end(), out_series.begin());
	out_series.resize(distance(out_series.begin(), last));
	return out_series;
}

int main() {
	using namespace std;

	const vector&lt;int&gt; E12 = { 100, 120, 150, 180, 220, 270, 330, 390, 470, 560, 680, 820 };
	const vector&lt;int&gt; E24 = { 100, 110, 120, 130, 150, 160, 180, 200, 220, 240, 270, 300, 330, 360, 390, 430, 470,
			510, 560, 620, 680, 750, 820, 910 };
	const vector&lt;int&gt; E48 = { 100, 105, 110, 115, 121, 127, 133, 140, 147, 154, 162, 169, 178, 187, 196, 205, 215,
			226, 237, 249, 261, 274, 287, 301, 316, 332, 348, 365, 383, 402, 422, 442, 464, 487, 511, 536, 562, 590,
			619, 649, 681, 715, 750, 787, 825, 866, 909, 953 };
	const vector&lt;int&gt; E96 = { 100, 102, 105, 107, 110, 113, 115, 118, 121, 124, 127, 130, 133, 137, 140, 143, 147,
			150, 154, 158, 162, 165, 169, 174, 178, 182, 187, 191, 196, 200, 205, 210, 215, 221, 226, 232, 237, 243,
			249, 255, 261, 267, 274, 280, 287, 294, 301, 309, 316, 324, 332, 340, 348, 357, 365, 374, 383, 392, 402,
			412, 422, 432, 442, 453, 464, 475, 487, 491, 511, 523, 536, 549, 562, 576, 590, 604, 619, 634, 649, 665,
			681, 698, 715, 732, 750, 768, 787, 806, 825, 845, 866, 887, 909, 931, 959, 976 };
	const vector&lt;int&gt; E192 = { 100, 101, 102, 104, 105, 106, 107, 109, 110, 111, 113, 114, 115, 117, 118, 120, 121,
			123, 124, 126, 127, 129, 130, 132, 133, 135, 137, 138, 140, 142, 143, 145, 147, 149, 150, 152, 154, 156,
			158, 160, 162, 164, 165, 167, 169, 172, 174, 176, 178, 180, 182, 184, 187, 189, 191, 193, 196, 198, 200,
			203, 205, 208, 210, 213, 215, 218, 221, 223, 226, 229, 232, 234, 237, 240, 243, 246, 249, 252, 255, 258,
			261, 264, 267, 271, 274, 277, 280, 284, 287, 291, 294, 298, 301, 305, 309, 312, 316, 320, 324, 328, 332,
			336, 340, 344, 348, 352, 357, 361, 365, 370, 374, 379, 383, 388, 392, 397, 402, 407, 412, 417, 422, 427,
			432, 437, 442, 448, 453, 459, 464, 470, 475, 481, 487, 493, 499, 505, 511, 517, 523, 530, 536, 542, 549,
			556, 562, 569, 576, 583, 590, 597, 604, 612, 619, 626, 634, 642, 649, 657, 665, 673, 681, 690, 698, 706,
			715, 723, 732, 741, 750, 759, 768, 777, 787, 796, 806, 816, 825, 835, 845, 856, 866, 876, 887, 898, 909,
			920, 931, 942, 953, 965, 976, 988 };

	cout.setf(ios::fixed, ios::floatfield);
	cout.precision(3);
	process_series(&quot;E12&quot;, E12);
	vector&lt;int&gt; series = merge_series(E12, E24);
	process_series(&quot;E24&quot;, series);
	series = merge_series(series, E48);
	process_series(&quot;E48&quot;, series);
	series = merge_series(series, E96);
	process_series(&quot;E96&quot;, series);
	series = merge_series(series, E192);
	process_series(&quot;E192&quot;, series);

	return EXIT_SUCCESS;
}
</pre>
<ol class="footnotes"><li id="footnote_0_893" class="footnote">Actually, the code runs in O(N * log N) time rather than O(N²) time: given some high-side resistance, I run a binary search on which low-side resistor value gives the best divider. I loop over all high-side resistances.</li></ol>]]></content:encoded>
			<wfw:commentRss>http://www.geekshavefeelings.com/posts/5v-to-3-3v-with-preferred-resistors/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Still Alive</title>
		<link>http://www.geekshavefeelings.com/posts/still-alive</link>
		<comments>http://www.geekshavefeelings.com/posts/still-alive#comments</comments>
		<pubDate>Fri, 23 Sep 2011 07:11:05 +0000</pubDate>
		<dc:creator>Xo Wang</dc:creator>
				<category><![CDATA[All]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[elec.engr]]></category>
		<category><![CDATA[ev]]></category>

		<guid isPermaLink="false">http://www.geekshavefeelings.com/?p=885</guid>
		<description><![CDATA[No, seriously, I&#8217;m not dead.]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/09/tassel.png"><img src="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/09/tassel-640x396.png" alt="" title="Tassel" width="640" height="396" class="alignnone size-large wp-image-886" /></a></p>
<p>No, seriously, I&#8217;m not dead.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.geekshavefeelings.com/posts/still-alive/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Glide Board Survey</title>
		<link>http://www.geekshavefeelings.com/posts/glide-board-survey</link>
		<comments>http://www.geekshavefeelings.com/posts/glide-board-survey#comments</comments>
		<pubDate>Mon, 07 Feb 2011 04:57:47 +0000</pubDate>
		<dc:creator>Xo Wang</dc:creator>
				<category><![CDATA[All]]></category>
		<category><![CDATA[Life]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[elec.engr]]></category>
		<category><![CDATA[gatech]]></category>
		<category><![CDATA[inventure]]></category>

		<guid isPermaLink="false">http://www.geekshavefeelings.com/?p=855</guid>
		<description><![CDATA[So I&#8217;m in a team for the 2011 InVenture Prize at Georgia Tech. I&#8217;d like to get some market research done for my team&#8217;s product, the Glide Board. Here&#8217;s a demo video: Here&#8217;s what the next prototype looks like. Note the compact size, the modern Bauhaus &#8220;function over form&#8221; styling, and lack of a hand [...]]]></description>
			<content:encoded><![CDATA[<p>So I&#8217;m in a team for the <a href="http://inventureprize.gatech.edu/">2011 InVenture Prize at Georgia Tech</a>. I&#8217;d like to get some market research done for my team&#8217;s product, the Glide Board. Here&#8217;s a demo video:<br />
<iframe title="YouTube video player" width="640" height="390" src="http://www.youtube.com/embed/xvfUIxusPZw" frameborder="0" allowfullscreen></iframe></p>
<p>Here&#8217;s what the next prototype looks like. Note the compact size, the modern Bauhaus &#8220;function over form&#8221; styling, and lack of a hand controller: all control is done by <em>simply leaning</em>.<br />
<a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/02/Glider-Proto-B.8bit.png"><img src="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/02/Glider-Proto-B.8bit-640x400.png" alt="" title="Glider Prototype 2.0" width="640" height="400" class="alignnone size-large wp-image-878" /></a><br />
The final product may look even better!</p>
<p><iframe src="https://spreadsheets0.google.com/embeddedform?formkey=dFVjTE44cHItMExrbi1ld19GNkNMOWc6MQ" width="760" height="820" frameborder="0">Loading&#8230;</iframe></p>
<p>If you&#8217;re completely unsure about prices, here are some related products:</p>
<table>
</tr>
<td>
		<a href="http://www.amazon.com/EMAD-Electric-Skateboards-SS600-Skateboard/dp/B002Y7120Y"><br />
<h2><strong>$550</strong> EMAD Electric Skateboard</h2>
<p>		<img alt="" src="http://ecx.images-amazon.com/images/I/31KZ-m8UPkL._SL500_AA280_.jpg" title="EMAD"/></a>
	</td>
<td>
		<a href="http://www.amazon.com/Razor-13112430-E200-Electric-Scooter/dp/B000BYCC0Q"><br />
<h2><strong>$160</strong> Razor E200 Electric Scooter</h2>
<p>		<img alt="" src="http://ecx.images-amazon.com/images/I/41HVQRQECAL._SL500_AA280_.jpg" title="Razor E200"/></a>
	</td>
</tr>
</tr>
<td>
		<a href="http://www.amazon.com/Sector-Professional-Complete-Longboard-Skateboard/dp/B001K3D3L4"><br />
<h2><strong>$190</strong> Sector 9 Longboard</h2>
<p>		<img alt="" src="http://ecx.images-amazon.com/images/I/41pHvOGOHIL._SL500_AA280_.jpg" title="Sector 9"/></a>
	</td>
<td>
		<a href="http://www.amazon.com/Segway-i2-Personal-Transporter/dp/B0012Y5AVC"><br />
<h2><strong>$6200</strong> Segway i2 Personal Transporter</h2>
<p>		<img alt="" src="http://ecx.images-amazon.com/images/I/41VmzAnovPL._SL500_AA280_.jpg" title="Segway"/></a>
	</td>
</tr>
</tr>
<td>
		<a href="http://www.alteredelectricskateboards.com/wombat_250.htm"><br />
<h2><strong>$300</strong> Altered Wombat Electric Skateboard</h2>
<p>		<img alt="" src="http://www.alteredelectricskateboards.com/site_images/products/WOMBAT250REG.jpg" title="Altered Wombat 250" width="280"/></a>
	</td>
<td>
		<a href="http://www.alteredelectricskateboards.com/thedrop_600.htm"><br />
<h2><strong>$760</strong> Altered Drop Electric Skateboard</h2>
<p>		<img alt="" src="http://www.alteredelectricskateboards.com/site_images/products/TheDrop600ZebrawoodREG.jpg" title="Altered The Drop" width="280"/></a>
	</td>
</tr>
</table>
<p>Also check out another styling option from Jamo:<br />
<a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/02/Glider-Proto-B.jgo_.jpg"><img src="http://www.geekshavefeelings.com/x/wp-content/uploads/2011/02/Glider-Proto-B.jgo_-640x360.jpg" alt="" title="Glider Prototype 2.0 Alt Style" width="640" height="360" class="alignnone size-large wp-image-879" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.geekshavefeelings.com/posts/glide-board-survey/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Venn Diagram (Spoiler: Quaternions)</title>
		<link>http://www.geekshavefeelings.com/posts/venn-diagram-spoiler-quaternions</link>
		<comments>http://www.geekshavefeelings.com/posts/venn-diagram-spoiler-quaternions#comments</comments>
		<pubDate>Wed, 01 Dec 2010 08:26:31 +0000</pubDate>
		<dc:creator>Xo Wang</dc:creator>
				<category><![CDATA[All]]></category>
		<category><![CDATA[Life]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[avionics]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[comp.sci]]></category>
		<category><![CDATA[graphics]]></category>
		<category><![CDATA[opengl]]></category>
		<category><![CDATA[quaternions]]></category>

		<guid isPermaLink="false">http://www.geekshavefeelings.com/?p=829</guid>
		<description><![CDATA[I figure all geek blogs need some sort of Venn diagram to illustrate some super insightful facts of life, so I decided to go meta and do one about my interests blog. So I&#8217;m pretty sure I haven&#8217;t blogged about quaternions yet, so here goes: god damn quaternions. Also, no blood for Euler. I&#8217;m no [...]]]></description>
			<content:encoded><![CDATA[<p>I figure all geek blogs need some sort of Venn diagram to illustrate some super insightful facts of life, so I decided to go meta and do one about my <del datetime="2010-12-01T08:12:08+00:00">interests</del> blog.</p>
<p><a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2010/12/VennDiagramTitle1.png"><img class="aligncenter size-large wp-image-840" title="Venn Diagram Title" src="http://www.geekshavefeelings.com/x/wp-content/uploads/2010/12/VennDiagramTitle1-640x376.png" alt="" width="640" height="376" /></a></p>
<p>So I&#8217;m pretty sure I haven&#8217;t blogged about quaternions yet, so here goes: god damn quaternions.</p>
<p>Also, <em>no blood for Euler</em>. I&#8217;m no hippie, but we need to reduce our dependence on Euler angles and move on to a more modern, sustainable representation of orientation with no singularities. I&#8217;m not willing to send off young American men and women to die just for the sake of your decadent way of determining attitude.</p>
<p>Here&#8217;s a sneak preview of what I&#8217;m doing these days (besides everything else):</p>
<p><a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2010/12/quatrain_sneak_lofi.png"><img class="aligncenter size-full wp-image-833" title="quatrain_sneak_lofi" src="http://www.geekshavefeelings.com/x/wp-content/uploads/2010/12/quatrain_sneak_lofi.png" alt="" width="720" height="502" /></a></p>
<p>It&#8217;s a really simple simulation framework for nonlinear recursive estimation filters for attitude determination. Like &#8220;<a title="Raxo" href="http://www.geekshavefeelings.com/projects/raxo">dynamically-compiled rasterizing software renderer</a>,&#8221; this doesn&#8217;t actually mean anything, but I&#8217;m still looking for a good acronym. If I throw in &#8220;orientation,&#8221; I get enough letters for &#8220;NOFEAR,&#8221; but &#8220;nonlinear orientation filter estimation attitude recursive&#8221; makes no sense.</p>
<p>By the way, the screenshot above looks crappy because I made it look crappy; I wanted to post a second screenshot later and claim that I made mad improvements to the visualizer. It actually looked pretty decent prior to the lo-fi&#8217;ing:</p>
<p><a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2010/12/quatrain_sneak_hifi.png"><img class="aligncenter size-full wp-image-835" title="quatrain_sneak_hifi" src="http://www.geekshavefeelings.com/x/wp-content/uploads/2010/12/quatrain_sneak_hifi.png" alt="" width="720" height="502" /></a></p>
<p>Yeah, so I just failed at lying for fun and profit. Oh well. Though I really do need a better model for orientation visualization than the <a href="http://en.wikipedia.org/wiki/Utah_teapot">Ohio waterspout</a><sup><a href="http://www.geekshavefeelings.com/posts/venn-diagram-spoiler-quaternions#footnote_0_829" id="identifier_0_829" class="footnote-link footnote-identifier-link" title="Credit to my friend TH for the name">1</a></sup>&#8230;</p>
<p>I&#8217;ve got a big pset due in 8 hours and an exam in 6 hours, so I guess I better stop write-crastinating.</p>
<p>God damn quaternions. ♥</p>
<ol class="footnotes"><li id="footnote_0_829" class="footnote">Credit to my friend TH for the name</li></ol>]]></content:encoded>
			<wfw:commentRss>http://www.geekshavefeelings.com/posts/venn-diagram-spoiler-quaternions/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>whois apple.com</title>
		<link>http://www.geekshavefeelings.com/posts/whois-apple-com</link>
		<comments>http://www.geekshavefeelings.com/posts/whois-apple-com#comments</comments>
		<pubDate>Wed, 01 Dec 2010 05:36:24 +0000</pubDate>
		<dc:creator>Xo Wang</dc:creator>
				<category><![CDATA[All]]></category>
		<category><![CDATA[Life]]></category>

		<guid isPermaLink="false">http://www.geekshavefeelings.com/?p=846</guid>
		<description><![CDATA[Hey what? xw@pewter:~$ whois apple.com Whois Server Version 2.0 Domain names in the .com and .net domains can now be registered with many different competing registrars. Go to http://www.internic.net for detailed information. APPLE.COM.WWW.BEYONDWHOIS.COM APPLE.COM.WAS.PWNED.BY.M1CROSOFT.COM APPLE.COM.MORE.INFO.AT.WWW.BEYONDWHOIS.COM APPLE.COM.IS.OWN3D.BY.NAKEDJER.COM APPLE.COM.IS.0WN3D.BY.GULLI.COM APPLE.COM.BEYONDWHOIS.COM APPLE.COM.AT.WWW.BEYONDWHOIS.COM APPLE.COM &#8230; xw@pewter:~$ whois google.com Whois Server Version 2.0 Domain names in the .com and .net [...]]]></description>
			<content:encoded><![CDATA[<p>Hey what?</p>
<blockquote><p>xw@pewter:~$ whois apple.com</p>
<p>Whois Server Version 2.0</p>
<p>Domain names in the .com and .net domains can now be registered<br />
with many different competing registrars. Go to http://www.internic.net<br />
for detailed information.</p>
<p>APPLE.COM.WWW.BEYONDWHOIS.COM<br />
APPLE.COM.WAS.PWNED.BY.M1CROSOFT.COM<br />
APPLE.COM.MORE.INFO.AT.WWW.BEYONDWHOIS.COM<br />
APPLE.COM.IS.OWN3D.BY.NAKEDJER.COM<br />
APPLE.COM.IS.0WN3D.BY.GULLI.COM<br />
APPLE.COM.BEYONDWHOIS.COM<br />
APPLE.COM.AT.WWW.BEYONDWHOIS.COM<br />
APPLE.COM</p>
<p>&#8230;</p>
<p>xw@pewter:~$ whois google.com</p>
<p>Whois Server Version 2.0</p>
<p>Domain names in the .com and .net domains can now be registered<br />
with many different competing registrars. Go to http://www.internic.net<br />
for detailed information.</p>
<p>GOOGLE.COM.ZZZZZZZZZZZZZ.GET.ONE.MILLION.DOLLARS.AT.WWW.UNIMUNDI.COM<br />
GOOGLE.COM.ZZZZZZ.THE.BEST.WEBHOSTING.AT.WWW.FATUCH.COM<br />
GOOGLE.COM.ZZZZZ.GET.LAID.AT.WWW.SWINGINGCOMMUNITY.COM<br />
GOOGLE.COM.ZOMBIED.AND.HACKED.BY.WWW.WEB-HACK.COM<br />
GOOGLE.COM.ZNAET.PRODOMEN.COM<br />
GOOGLE.COM.YUCEKIRBAC.COM<br />
GOOGLE.COM.YUCEHOCA.COM<br />
GOOGLE.COM.WORDT.DOOR.VEEL.WHTERS.GEBRUIKT.SERVERTJE.NET<br />
GOOGLE.COM.VN<br />
GOOGLE.COM.UY<br />
GOOGLE.COM.UA<br />
GOOGLE.COM.TW<br />
GOOGLE.COM.TR<br />
GOOGLE.COM.SUCKS.FIND.CRACKZ.WITH.SEARCH.GULLI.COM<br />
GOOGLE.COM.SPROSIUYANDEKSA.RU<br />
GOOGLE.COM.SERVES.PR0N.FOR.ALLIYAH.NET<br />
GOOGLE.COM.SANATATEA-NOASTRA.COM<br />
GOOGLE.COM.SA<br />
GOOGLE.COM.PE<br />
GOOGLE.COM.P2NK-AJA.COM<br />
GOOGLE.COM.MX<br />
GOOGLE.COM.LASERPIPE.COM<br />
GOOGLE.COM.IS.SHIT.SQUAREBOARDS.COM<br />
GOOGLE.COM.IS.NOT.HOSTED.BY.ACTIVEDOMAINDNS.NET<br />
GOOGLE.COM.IS.HOSTED.ON.PROFITHOSTING.NET<br />
GOOGLE.COM.IS.APPROVED.BY.NUMEA.COM<br />
GOOGLE.COM.HICHINA.COM<br />
GOOGLE.COM.HAS.LESS.FREE.PORN.IN.ITS.SEARCH.ENGINE.THAN.SECZY.COM<br />
GOOGLE.COM.ESJUEGOS.NET<br />
GOOGLE.COM.DO<br />
GOOGLE.COM.CO<br />
GOOGLE.COM.CN<br />
GOOGLE.COM.BR<br />
GOOGLE.COM.BEYONDWHOIS.COM<br />
GOOGLE.COM.AU<br />
GOOGLE.COM.AR<br />
GOOGLE.COM.AFRICANBATS.ORG<br />
GOOGLE.COM</p>
<p>&#8230;</p>
<p>xw@pewter:~$ whois microsoft.com</p>
<p>Whois Server Version 2.0</p>
<p>Domain names in the .com and .net domains can now be registered<br />
with many different competing registrars. Go to http://www.internic.net<br />
for detailed information.</p>
<p>MICROSOFT.COM.ZZZZZZZZZZZZZZZZZZ.THE.BEST.WEBHOSTING.AT.WWW.FATUCH.COM<br />
MICROSOFT.COM.ZZZZZZZZZZZZZZZZZZ.IM.ELITE.WANNABE.TOO.WWW.PLUS613.NET<br />
MICROSOFT.COM.ZZZZZZZZZZZZZZZZZZ.GET.ONE.MILLION.DOLLARS.AT.WWW.UNIMUNDI.COM<br />
MICROSOFT.COM.ZZZZZZ.MORE.DETAILS.AT.WWW.BEYONDWHOIS.COM<br />
MICROSOFT.COM.ZZZZZ.GET.LAID.AT.WWW.SWINGINGCOMMUNITY.COM<br />
MICROSOFT.COM.ZZZOMBIED.AND.HACKED.BY.WWW.WEB-HACK.COM<br />
MICROSOFT.COM.ZZZ.IS.0WNED.AND.HAX0RED.BY.SUB7.NET<br />
MICROSOFT.COM.WILL.BE.SLAPPED.IN.THE.FACE.BY.MY.BLUE.VEINED.SPANNER.NET<br />
MICROSOFT.COM.WILL.BE.BEATEN.WITH.MY.SPANNER.NET<br />
MICROSOFT.COM.WAREZ.AT.TOPLIST.GULLI.COM<br />
MICROSOFT.COM.TOTALLY.SUCKS.S3U.NET<br />
MICROSOFT.COM.SOFTWARE.IS.NOT.USED.AT.REG.RU<br />
MICROSOFT.COM.SHOULD.GIVE.UP.BECAUSE.LINUXISGOD.COM<br />
MICROSOFT.COM.RAWKZ.MUH.WERLD.MENTALFLOSS.CA<br />
MICROSOFT.COM.OHMYGODITBURNS.COM<br />
MICROSOFT.COM.MORE.INFO.AT.WWW.BEYONDWHOIS.COM<br />
MICROSOFT.COM.MATCHES.THIS.STRING.AT.KEYSIGNERS.COM<br />
MICROSOFT.COM.LOVES.ME.KOSMAL.NET<br />
MICROSOFT.COM.LIVES.AT.SHAUNEWING.COM<br />
MICROSOFT.COM.IS.NOT.YEPPA.ORG<br />
MICROSOFT.COM.IS.NOT.HOSTED.BY.ACTIVEDOMAINDNS.NET<br />
MICROSOFT.COM.IS.IN.BED.WITH.CURTYV.COM<br />
MICROSOFT.COM.IS.HOSTED.ON.PROFITHOSTING.NET<br />
MICROSOFT.COM.IS.A.STEAMING.HEAP.OF.FUCKING-BULLSHIT.NET<br />
MICROSOFT.COM.IS.A.MESS.TIMPORTER.CO.UK<br />
MICROSOFT.COM.HAS.A.PRESENT.COMING.FROM.HUGHESMISSILES.COM<br />
MICROSOFT.COM.FILLS.ME.WITH.BELLIGERENCE.NET<br />
MICROSOFT.COM.CAN.GO.FUCK.ITSELF.AT.SECZY.COM<br />
MICROSOFT.COM.ARE.GODDAMN.PIGFUCKERS.NET.NS-NOT-IN-SERVICE.COM<br />
MICROSOFT.COM</p>
<p>&#8230;</p></blockquote>
<p>Is somebody spamming our WHOIS records?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.geekshavefeelings.com/posts/whois-apple-com/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>HÄRDBÖRD: Interesting Bits</title>
		<link>http://www.geekshavefeelings.com/posts/hardbord-interesting-bits</link>
		<comments>http://www.geekshavefeelings.com/posts/hardbord-interesting-bits#comments</comments>
		<pubDate>Mon, 25 Oct 2010 02:05:26 +0000</pubDate>
		<dc:creator>Xo Wang</dc:creator>
				<category><![CDATA[All]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[comp.sci]]></category>
		<category><![CDATA[elec.engr]]></category>
		<category><![CDATA[gatech]]></category>
		<category><![CDATA[hardbord]]></category>

		<guid isPermaLink="false">http://www.geekshavefeelings.com/?p=776</guid>
		<description><![CDATA[OK, so I need to get better at blogging on caffeine. I spent about four times the amount of time writing the last blog post on HÄRDBÖRD than I did working on the stuff described in it. And let&#8217;s face it, what I described were my personal insecurities about electronics hacking becoming more popular &#38; [...]]]></description>
			<content:encoded><![CDATA[<p>OK, so I need to get better at blogging on caffeine. I spent about four times the amount of time writing the last blog post on HÄRDBÖRD than I did working on the stuff described in it. And let&#8217;s face it, what I described were my personal insecurities about electronics hacking becoming more popular &amp; accessible, making my own talents less sexy to the laywoman (and layman). That, and a ghetto DAC with three passive components hooked up. Big whoop. So here&#8217;s the next part, with actual interesting stuff.</p>
<h2>Transmitten</h2>
<p>would be a great name if my setup involved some sort of sensory glove and I hadn&#8217;t brutalized the German language, but it doesn&#8217;t and I have&#8230;</p>
<h2>The transmitter</h2>
<p>I could explain the design, but I think this video is more helpful (though not <em>very</em> helpful):</p>
<p><a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2010/10/controllertest_720p.mp4">HÄRDBÖRD: Interesting Bits</a></p>
<p>I think it&#8217;s fairly obvious what I was trying to do here, though poor camerawork <em>cough</em>jamison<em>cough</em> kind of obscured how moving the joystick on the Nunchuk controlled Jamison&#8217;s three-pound battlebot, Cake. Wirelessly. Anyways, a series of dysconscious design decisions led to the following desired specs:</p>
<ul>
<li>Wireless control of the BÖRDs</li>
<li>Wii Nunchuk as the human interface</li>
<li>Some sort of reliable 2.4GHz link (radio hardware with a protocol stack built in)</li>
</ul>
<p>Everything else fell into place right after that. I grabbed two pairs of the lowest-end Xbee radio transceivers as well as the cheapest USB adapters and breakout boards I could find for them. &#8220;O Captain,&#8221; you cry, &#8220;that&#8217;ll be from Sparkfun, right?&#8221;</p>
<p>Yeah no, Sparkfun is for tools, man. They were so much better when they were underground. &lt;/hípster&gt;</p>
<p>Surprisingly enough, <a href="http://www.parallax.com/">Parallax</a> has Xbees at the same price as Digi-Key/Mouser, $3 breakout adapter boards<sup><a href="http://www.geekshavefeelings.com/posts/hardbord-interesting-bits#footnote_0_776" id="identifier_0_776" class="footnote-link footnote-identifier-link" title="With pin headers, Montresor! Sparkfun sells only headers at the same cost.">1</a></sup>, and a $20 USB breakout<sup><a href="http://www.geekshavefeelings.com/posts/hardbord-interesting-bits#footnote_1_776" id="identifier_1_776" class="footnote-link footnote-identifier-link" title="Really a USB to serial adapter + LDO regulator with an Xbee footprint.">2</a></sup>. And you thought they&#8217;re those overpriced backwards BASIC Stamp kids who supposedly got superseded by the Arduino clusterfugue<sup><a href="http://www.geekshavefeelings.com/posts/hardbord-interesting-bits#footnote_2_776" id="identifier_2_776" class="footnote-link footnote-identifier-link" title="OK, they are. But still. SUPPLIES!">3</a></sup>.</p>
<p>The rest of the article is about the technical hacks I used in software to reduce complexity, part count, cost, etc. Boring stuff.</p>
<h2>Nunchuk</h2>
<p>First off, it&#8217;s <em>&#8220;nunchuk</em>.&#8221; Not &#8220;nunchuck,&#8221; which is what you do in a convent.</p>
<p>Secondly, these things are an awesome addition to any project requiring an analog joystick, two buttons, and a three axis gyro, mounted in an overly ergonomic housing with Apple aesthetics and Nintendo unbreakability. Take care not to drop them though—you might break the floor. Nunchuks can be accessed through a simple I²C interface, exposed physically through six spring contacts in the connector for which <a href="http://todbot.com/blog/2008/02/18/wiichuck-wii-nunchuck-adapter-available/">simple adapters</a> are available.</p>
<p>Keep in mind that the Nunchuks have gold-plated spring contacts and there is a tin finish on those adapters. This causes some sort of galvanic reaction and you get a lot of streaky black residue on both after a few months of use. Ew.</p>
<p>Now, I haven&#8217;t written straight C for a while now, so I wondered what sort of twisted interface code I&#8217;d come up with to grab data off of these things. Oddly enough I didn&#8217;t screw up the external interface that badly:</p>
<pre class="brush: cpp; light: true; title: ; notranslate">typedef struct {
	uint8 joyX;
	uint8 joyY;
	uint16 accelX;
	uint16 accelY;
	uint16 accelZ;
	uint8 buttonZ;
	uint8 buttonC;
} NunchukData_t;

void nunchukInit(void);
int nunchukReadData(void);
NunchukData_t nunchukGetData(void);
void nunchukPrintData(void);</pre>
<p>Yeah, so if you were to use my code, you&#8217;d see a C struct for the data output and four self-explanatory functions. Clean and simple.</p>
<p>However, my implementation in the source file (attached) is way shakier, involving GCC attributes, bitfields, and anonymous union-nested anonymous structs. But hey, that&#8217;s how I roll when I want to decode binary data. First I define this&#8230; <em>thing</em>:</p>
<pre class="brush: cpp; light: true; title: ; notranslate">typedef struct __attribute__((__packed__)) {
	union {
		struct {
			uint8 joyX;
			uint8 joyY;
			uint8 accelX_HI;
			uint8 accelY_HI;
			uint8 accelZ_HI;
			uint8 buttonZ   : 1;
			uint8 buttonC   : 1;
			uint8 accelX_LO : 2;
			uint8 accelY_LO : 2;
			uint8 accelZ_LO : 2;
		};

		uint8 buffer[6];
	};
} NunchukRegisters_t;</pre>
<p>What is that supposed to achieve? Well, it&#8217;s basically a 6-byte long C struct which corresponds to the bit patterns read off of the Nunchuk. Based on <a href="http://www.windmeadow.com/node/42">reading materials</a>, I know that the data is encoded/ciphered by the byte, and all the decoded data is swizzled together to save bandwidth.</p>
<p>Thus, I have a <a href="http://en.wikipedia.org/wiki/Union_(computer_science)">union</a> between the aforementioned struct and a size 6 byte array so I can fill up and decode the struct in a per-byte fashion, just by looping over the unioned array. The <code>__attribute__((__packed__))</code> is just an futile, unnecessary hint to my compiler to make sure it doesn&#8217;t pad out my struct with extraneous bytes.</p>
<p>How do I use this struct? Now this is the beautiful part:</p>
<pre class="brush: cpp; light: true; title: ; notranslate">int nunchukReadData(void) {
	NunchukRegisters_t nunchukRegs; // allocate space
	readNI2C1(NUNCHUK_ADDR, nunchukRegs.buffer, 6); // read from nunchuk

	int i;
	for(i = 0; i &lt; 6 ; i++) { // decode by byte
		nunchukRegs.buffer[i] = nunchukByteDecode(nunchukRegs.buffer[i]);
	}
	// assemble raw data
	nunchukData.joyX = nunchukRegs.joyX;
	nunchukData.joyY = nunchukRegs.joyY;
	nunchukData.accelX = (nunchukRegs.accelX_HI &lt;&lt; 2) | nunchukRegs.accelX_LO;
	nunchukData.accelY = (nunchukRegs.accelY_HI &lt;&lt; 2) | nunchukRegs.accelY_LO;
	nunchukData.accelZ = (nunchukRegs.accelZ_HI &lt;&lt; 2) | nunchukRegs.accelZ_LO;
	nunchukData.buttonZ = !nunchukRegs.buttonZ;
	nunchukData.buttonC = !nunchukRegs.buttonC;

	DELAY_US(50); // comm delay so nunchuk doesn't complain
	nunchukRequestData(); // signal nunchuk to read sensors again
	return 1;
}</pre>
<p>Notice how the unioning lets me fill up the registers without janky casting, and the bitfields in the nested anonymous prevents me from having to shift or mask off bits in order to decode the Nunchuk registers into my output data struct. For <a href="http://www.atom.com/funny_videos/haha_america/">comparative delta</a>, this is how the &#8220;<a href="http://todbot.com/arduino/sketches/WiichuckDemo/nunchuck_funcs.h">reference implementation</a>&#8221; looks on the Arduino:</p>
<pre class="brush: cpp; light: true; title: ; notranslate">// from http://todbot.com/arduino/sketches/WiichuckDemo/nunchuck_funcs.h
int joy_x_axis = nunchuck_buf[0];
int joy_y_axis = nunchuck_buf[1];
int accel_x_axis = nunchuck_buf[2]; // * 2 * 2;
int accel_y_axis = nunchuck_buf[3]; // * 2 * 2;
int accel_z_axis = nunchuck_buf[4]; // * 2 * 2;

int z_button = 0;
int c_button = 0;

// byte nunchuck_buf[5] contains bits for z and c buttons
// it also contains the least significant bits for the accelerometer data
// so we have to check each bit of byte outbuf[5]
if((nunchuck_buf[5] &gt;&gt; 0) &amp; 1)
	z_button = 1;
if((nunchuck_buf[5] &gt;&gt; 1) &amp; 1)
	c_button = 1;

if((nunchuck_buf[5] &gt;&gt; 2) &amp; 1)
	accel_x_axis += 2;
if((nunchuck_buf[5] &gt;&gt; 3) &amp; 1)
	accel_x_axis += 1;

if((nunchuck_buf[5] &gt;&gt; 4) &amp; 1)
	accel_y_axis += 2;
if((nunchuck_buf[5] &gt;&gt; 5) &amp; 1)
	accel_y_axis += 1;

if((nunchuck_buf[5] &gt;&gt; 6) &amp; 1)
	accel_z_axis += 2;
if((nunchuck_buf[5] &gt;&gt; 7) &amp; 1)
	accel_z_axis += 1;</pre>
<p>Yeah&#8230; I&#8217;d rather have nested anonymous structs than line after line of nasty bit twiddling. Let&#8217;s ignore the fact that the above example is a snippet of application code, while my decoding was library code, making it instantly superior from a software engineering standpoint. That is, the programmer who uses my code can pick up and run with an interface which is decoupled from how bits are swizzled by the Nunchuk. But, the coder above would have to reference a couple of websites to write her own decoding routines before <code>printf</code>&#8216;ing the data, for example.</p>
<h2>Non-volatile storage</h2>
<p>If there&#8217;s one thing I&#8217;m unhappy about with my choice of microcontroller, it&#8217;s that it doesn&#8217;t have built-in data EEPROM. EEPROM is flash memory, which is non-volatile—its contents are retained even when powered off. Most decent PICs have, in addition to RAM and program memory flash (where all your code is stored), a piece of data EEPROM acting as a memory-mapped peripheral which you can use as if it were an external EEPROM chip over SPI or I²C. The dsPIC33 family does not have this<sup><a href="http://www.geekshavefeelings.com/posts/hardbord-interesting-bits#footnote_3_776" id="identifier_3_776" class="footnote-link footnote-identifier-link" title="Though dsPIC30 does, for some reason.">4</a></sup>.</p>
<p>But I still want my non-volatile storage, so I can store Nunchuk calibration data in the transmitter. How? We write it to the program flash. To make a long story short, this is a fairly complicated procedure which was achieved by using Microchip&#8217;s <a href="http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&amp;nodeId=2680&amp;dDocName=en538000">Data EEPROM Emulation library</a>, which turns unused program flash space into software-addressable EEPROM blocks. It even spreads writes over different blocks of allocated program flash in order to reduce wear on the EEPROM cells.</p>
<p>Trouble was, this library had some fairly odd software engineering practices, like putting way too much internals in a public header. It also used a separate unit of assembly language routines so the library could use specific instructions for flash reads and writes, when they could have been done in inline assembly, or even better, compiler built-in functions. It&#8217;s not like your assembly is more portable when you put it in a separate file, Microchip. :\</p>
<p>My modifications and simplifications to the library are attached to this post.</p>
<h2>The protocol</h2>
<p>RC control is essentially packeted data; each piece of data you send is a full state of what motors/LEDs should be doing what, with no dependence on past or future data. Xbees provide you with a bidirectional stream (yes, I know it&#8217;s packets underneath) rather than a packet interface like <a href="http://www.sparkfun.com/commerce/categories.php?c=114">Nordic radios</a>. For those who grok teh nets, it&#8217;s more TCP and less UDP.</p>
<p>So, I hacked up a protocol that took advantage of both: use escape characters and base64 encoding to represent binary packets, and human-readable ASCII which is ignored by the receiver.</p>
<p>First I define a data structure. Starting to see a pattern?</p>
<pre class="brush: cpp; light: true; title: ; notranslate">typedef struct {
	union {
		struct {
			uint16 speed;
			uint8 reversed;
			uint8 brake;
		};
		uint8 buffer[4];
	};
} FluffyData_t;</pre>
<p><code>FluffyData_t</code><sup><a href="http://www.geekshavefeelings.com/posts/hardbord-interesting-bits#footnote_4_776" id="identifier_4_776" class="footnote-link footnote-identifier-link" title="H&Auml;RDB&Ouml;RD used to be called Fluffy, in case you&amp;#8217;re wondering about the name.">5</a></sup> is the information the receiver cares about: speed, direction, and whether to brake. This is put through a base64 encode<sup><a href="http://www.geekshavefeelings.com/posts/hardbord-interesting-bits#footnote_5_776" id="identifier_5_776" class="footnote-link footnote-identifier-link" title="Note the byte array union again, which is great for doing binary transforms like b64 encoding.">6</a></sup>, and surrounded with non-base64 escape characters, ^ and $, into a 10-byte ASCII string.</p>
<p>Now, everything outside of those escape chars can be easily parsed out on the receiving end. So, now we have easily-decoded binary data represented as ASCII so it doesn&#8217;t screw with our terminals, and we can stick &#8220;comments&#8221; into the stream so we can peek in and read debug output.</p>
<p>For example, this is what actually goes through my Xbees:</p>
<pre class="brush: plain; light: true; title: ; notranslate">(Accel) x: 664, y: 450, z: 612 (Joystick) x: 148, y: 196 (Button) z: 1, c: 0
(fluffy) speed: 46260, reversed: 0, brake: 0
^tLQAAA==$
(Accel) x: 664, y: 450, z: 614 (Joystick) x: 148, y: 197 (Button) z: 1, c: 0
(fluffy) speed: 47031, reversed: 0, brake: 0
^t7cAAA==$</pre>
<p>That&#8217;s right, most of it is human readable. Only a tiny fraction of it is for the machine. This is called taking advantage of the bandwidth.</p>
<p>On the receiver end, it&#8217;s trivial to listen for a ^ character, start decoding base64 into another FluffyData_t struct, and then stop decoding upon receiving a $ character. Of course I am oversimplifying data integrity issues here, which are remedied in my design with a few simple checks and CRC16 checksums.</p>
<h2>Code listings</h2>
<ul>
<li><a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2010/10/nunchuk.c">nunchuk.c</a></li>
<li><a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2010/10/nunchuk.h">nunchuk.h</a></li>
<li><a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2010/10/DEE-Emulation-16-bit.c">DEE Emulation 16-bit.c</a></li>
<li><a href="http://www.geekshavefeelings.com/x/wp-content/uploads/2010/10/DEE-Emulation-16-bit.h">DEE Emulation 16-bit.h</a></li>
</ul>
<p>Note that I use the excellent <a href="http://www.reesemicro.com/Home/pic24-software-library-collection">Reese/Jones/Bruce library for PIC24 &amp; dsPIC33</a> as my hardware interface library, which is referenced in the nunchuk.c code for I²C routines.</p>
<ol class="footnotes"><li id="footnote_0_776" class="footnote">With pin headers, Montresor! Sparkfun sells <em>only</em> headers at the same cost.</li><li id="footnote_1_776" class="footnote">Really a USB to serial adapter + LDO regulator with an Xbee footprint.</li><li id="footnote_2_776" class="footnote">OK, they are. But still. <em>SUPPLIES!</em></li><li id="footnote_3_776" class="footnote">Though dsPIC30 does, for some reason.</li><li id="footnote_4_776" class="footnote">HÄRDBÖRD used to be called Fluffy, in case you&#8217;re wondering about the name.</li><li id="footnote_5_776" class="footnote">Note the byte array union again, which is great for doing binary transforms like b64 encoding.</li></ol>]]></content:encoded>
			<wfw:commentRss>http://www.geekshavefeelings.com/posts/hardbord-interesting-bits/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
<enclosure url="http://www.geekshavefeelings.com/x/wp-content/uploads/2010/10/controllertest_720p.mp4" length="8562953" type="video/mp4" />
		</item>
	</channel>
</rss>
<!-- 0.9505sec -->
<!-- Dynamic page generated in 1.203 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2012-02-06 04:13:28 -->
<!-- Compression = gzip -->
