<?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>Keyglove</title>
	<atom:link href="https://keyglove.net/feed/" rel="self" type="application/rss+xml" />
	<link>https://keyglove.net/</link>
	<description>Freedom in the Palm of Your Hand</description>
	<lastBuildDate>Sun, 29 Nov 2015 03:00:03 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.5</generator>
<site xmlns="com-wordpress:feed-additions:1">172652370</site>	<item>
		<title>Another Giant Refactoring Milestone</title>
		<link>https://keyglove.net/2015/11/28/another-giant-refactoring-milestone/</link>
					<comments>https://keyglove.net/2015/11/28/another-giant-refactoring-milestone/#comments</comments>
		
		<dc:creator><![CDATA[Jeff Rowberg]]></dc:creator>
		<pubDate>Sun, 29 Nov 2015 03:00:03 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[collaboration]]></category>
		<category><![CDATA[compiler]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[ide]]></category>
		<category><![CDATA[refactoring]]></category>
		<guid isPermaLink="false">https://keyglove.net/?p=1504</guid>

					<description><![CDATA[<p>Yes, I've once again rearranged (and in some cases, rewritten) the entire Keyglove codebase. It was totally worth it. My adventure with this huge refactoring endeavor started with a bug that I couldn't figure out. It made zero sense, and the behavior changed without any detectable reason based on seemingly unrelated code changes.</p>
<p>The post <a href="https://keyglove.net/2015/11/28/another-giant-refactoring-milestone/">Another Giant Refactoring Milestone</a> appeared first on <a href="https://keyglove.net">Keyglove</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Yes, I&#8217;ve once again rearranged (and in some cases, rewritten) the entire Keyglove codebase. It was totally worth it, for reasons I will outline in a moment. Before I do, I want to get to some housekeeping stuff.</p>
<p><span id="more-1504"></span>This is the first of a few could-have-been-backdated posts which chronicle the developments in the Keyglove project&#8217;s recent past, but which I didn&#8217;t write about at the time they occurred (oops). This miniseries of historical non-fiction covers the past 13 months or so, starting around the beginning of November 2014. &#8220;<em>Over a year, again?!</em>&#8221; I hear you cry. Indeed, and I apologize for another long period of silence—even though it fortunately wasn&#8217;t totally devoid of progress. For an extremely brief explanation, here&#8217;s a list of the &#8220;life stuff&#8221; that has happened during the same period of time:</p>
<ul>
<li>Bought a house</li>
<li>Had a child (which is to say, my wife did)</li>
<li>Moved into the aforementioned house</li>
<li>Employer got bought out by Silicon Labs</li>
<li>Unexpected family medical issues</li>
<li>Took a new job opportunity at Cypress</li>
</ul>
<p>I had no desire or intention of staying so silent, but&#8230;well, I&#8217;ll just say that it&#8217;s been quite a year.</p>
<p>Okay, back to the stuff you came here to read.</p>
<p>My adventure with this huge refactoring endeavor started with a bug that I couldn&#8217;t figure out. It made zero sense, and the behavior changed without any detectable reason based on seemingly unrelated code changes. My announcement to the world of this fact came in the form of this tweet:</p>
<blockquote class="twitter-tweet" lang="en">
<p lang="en" dir="ltr">Running into a strange bug that I think must be a memory leak. I found a workaround, but the behavior in both cases makes no sense. Argh&#8230;</p>
<p>&mdash; Keyglove (@keyglove) <a href="https://twitter.com/keyglove/status/528765631647449088">November 2, 2014</a></p></blockquote>
<p>After continued troubleshooting yielded no progress, I eventually <a href="http://forum.arduino.cc/index.php?topic=276412" target="_blank">posted my predicament to the Arduino Forum</a>.</p>
<blockquote><p>I am running into a problem which seems to have to do with the code execution pointer, and the behavior makes zero sense at all. There is a conditional statement which doesn&#8217;t match, and since the code it controls is only one line, I omitted the surrounding { } braces for brevity. This is a pattern that I have reused many other times all throughout this fairly complex project without any observable bad consequences. However, when I let the code run this way, execution apparently stops at that line&#8230;</p></blockquote>
<p>Three pages of sometimes maddening miscommunication or misinterpretation later, I got a startling revelation when the patient and wise Nick Gammon <a href="http://forum.arduino.cc/index.php?topic=276412.msg1947485#msg1947485" target="_blank">pointed me towards</a> a <a href="http://www.gammon.com.au/forum/?id=12625">pre-written resource he put together quite some time ago on Arduino project structuring</a>.</p>
<p>This was a big surprise to me, because the last I&#8217;d heard, Arduino&#8217;s IDE imposed some pretty weird restrictions on code structure (one of its presumed weaknesses), including that you could only have typical .cpp/.h source/header file pairings in included libraries, from the official &#8220;Libraries&#8221; folder. This meant that the main project had to be one .ino file and a big collection of header files, each of which actually had a both declaration and implementation code inside (typically a bad idea). Nick&#8217;s guide proved that this was an incorrect assumption on my part.</p>
<blockquote class="twitter-tweet" lang="en">
<p lang="en" dir="ltr">I&#039;ve just (!?) learned that Arduino sketches can be structured the same way most C++ projects are, with .cpp/.h pairs within the sketch.</p>
<p>&mdash; Keyglove (@keyglove) <a href="https://twitter.com/keyglove/status/529819861376327680">November 5, 2014</a></p></blockquote>
<blockquote class="twitter-tweet" lang="en">
<p lang="en" dir="ltr">This makes me more giddy than it probably should, despite (or because of?) the massive code restructuring that is about to take place.</p>
<p>&mdash; Keyglove (@keyglove) <a href="https://twitter.com/keyglove/status/529820113718214657">November 5, 2014</a></p></blockquote>
<p>After no small amount of work completely restructuring the whole Arduino project, I had all of the code back in line with conventional organization, and the inexplicable bug disappeared. <a href="http://forum.arduino.cc/index.php?topic=276412.msg1963180#msg1963180" target="_blank">Nick Gammon is my hero</a>.</p>
<p>I pushed the <a href="https://github.com/jrowberg/keyglove/commit/f7a1874f492d746ae9a3a480a1fc2cdde44cf61a" target="_blank">massive commit</a> to the Github repo as soon as I got it to compile and function as well as it had before the refactoring started&mdash;except for the fixed bug, of course. In addition to that fix, the new standardized code structure allows me to avoid some really strange &#8220;workaround gymnastics&#8221; that I had to include before. The order of <code>#include</code> lines in various places had been extremely delicate, with way too many compile-time dependencies built into the order of those lines. The new code is much safer, more obvious, and more forgiving. Three cheers for collaboration!</p>
<p>The post <a href="https://keyglove.net/2015/11/28/another-giant-refactoring-milestone/">Another Giant Refactoring Milestone</a> appeared first on <a href="https://keyglove.net">Keyglove</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://keyglove.net/2015/11/28/another-giant-refactoring-milestone/feed/</wfw:commentRss>
			<slash:comments>8</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1504</post-id>	</item>
		<item>
		<title>The Power of Glove, a Power Glove Documentary</title>
		<link>https://keyglove.net/2014/08/08/the-power-of-glove-a-power-glove-documentary/</link>
					<comments>https://keyglove.net/2014/08/08/the-power-of-glove-a-power-glove-documentary/#comments</comments>
		
		<dc:creator><![CDATA[Jeff Rowberg]]></dc:creator>
		<pubDate>Fri, 08 Aug 2014 12:30:51 +0000</pubDate>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[documentary]]></category>
		<category><![CDATA[kickstarter]]></category>
		<guid isPermaLink="false">https://keyglove.net/?p=1446</guid>

					<description><![CDATA[<p>I came across this gem of a Kickstarter project today, and I had to back it out of solidarity, shared interest, and an appreciation for historical innovation.</p>
<p>The post <a href="https://keyglove.net/2014/08/08/the-power-of-glove-a-power-glove-documentary/">The Power of Glove, a Power Glove Documentary</a> appeared first on <a href="https://keyglove.net">Keyglove</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>I came across this gem of a Kickstarter project today, and I had to back it out of solidarity, shared interest, and an appreciation for historical innovation.</p>
<p><span id="more-1446"></span></p>
<blockquote><p>Help us fund the final production stages of The Power of Glove, a feature documentary profiling the enigmatic NES controller that helped define a generation of gamers.</p>
<p>The Power Glove was a 1989 Nintendo controller that promised to forever change the way humankind interacted with technology. Originally released by Mattel, the Power Glove was the first mass-marketed, gesture-based video game controller, and its hype was immense.</p>
<p>Immediately after its release, however, gamers were disappointed by the Power Glove, and critics panned it as a worthless gimmick. Yet unlike many gimmicks and critical failures of the past, the Power Glove has not been simply swept under the rug. Over two decades after its release, the Power Glove continues to resonate with video gaming and technology fans, becoming the focus of art pieces, songs, videos, hacking projects, and other forms of cultural repurposing.</p>
<p>The Power of Glove is the story behind the legend and legacy of the Power Glove.</p></blockquote>
<p>I have no affiliation with these guys, but it looks like a fun project. $10 gets you the digital download. I&#8217;m looking forward to it.</p>
<p>The post <a href="https://keyglove.net/2014/08/08/the-power-of-glove-a-power-glove-documentary/">The Power of Glove, a Power Glove Documentary</a> appeared first on <a href="https://keyglove.net">Keyglove</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://keyglove.net/2014/08/08/the-power-of-glove-a-power-glove-documentary/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1446</post-id>	</item>
		<item>
		<title>Functional Bluetooth and Rewritten iWRAP Library</title>
		<link>https://keyglove.net/2014/08/08/functional-bluetooth-and-rewritten-iwrap-library/</link>
					<comments>https://keyglove.net/2014/08/08/functional-bluetooth-and-rewritten-iwrap-library/#comments</comments>
		
		<dc:creator><![CDATA[Jeff Rowberg]]></dc:creator>
		<pubDate>Fri, 08 Aug 2014 04:30:03 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Hardware]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[bluetooth]]></category>
		<category><![CDATA[wireless]]></category>
		<guid isPermaLink="false">https://keyglove.net/?p=1461</guid>

					<description><![CDATA[<p>The Bluetooth system has been one of those lingering features that I couldn't quite manage to nail down for one reason or another. No more! I've got a robust connection and data management system in place.</p>
<p>The post <a href="https://keyglove.net/2014/08/08/functional-bluetooth-and-rewritten-iwrap-library/">Functional Bluetooth and Rewritten iWRAP Library</a> appeared first on <a href="https://keyglove.net">Keyglove</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>The Bluetooth system has been one of those lingering features that I couldn&#8217;t quite manage to nail down for one reason or another. Well, no more! It&#8217;s working now. I&#8217;ve got a robust connection and data management system in place, built around the Bluegiga WT12 Bluetooth module and its powerful iWRAP firmware.</p>
<p><span id="more-1461"></span></p>
<p>The solution to this longstanding problem involved some yak shaving, within the overall context of Keyglove development. Here&#8217;s a brilliant and hilarious explanation of yak-shaving in animating GIF format:</p>
<p><img fetchpriority="high" decoding="async" src="https://keyglove.net/wp-content/uploads/2014/08/ibaDjk7AeIcvxv.gif" width="480" height="360" class="aligncenter" /></p>
<p>In short, I totally rewrote the <a href="https://github.com/jrowberg/iwrap" target="_blank">iWRAP parser library</a> that I began years ago in order to make it function properly and fit nicely with the Keyglove API structure. The end result of that effort is a cleaner and much more intuitive interface that I and anyone else can use to talk to Bluegiga&#8217;s classic Bluetooth modules, like the WT12 that I have in the Keyglove. While it technically stands on its own and isn&#8217;t part of the Keyglove firmware, it dovetails perfectly between both the Keyglove and my day job at Bluegiga, and it has already been useful for other people in other applications.</p>
<p>In short, the new iWRAP code cleaned up one of the messiest and most complex parts of the Keyglove firmware source, and is now both much easier to understand and much easier to maintain (not to mention the more important fact that it actually works).</p>
<p><a href="https://keyglove.net/wp-content/uploads/2014/08/arduino_iwrap_demo_generic1.png" rel="wp-prettyPhoto[1461]"><img decoding="async" src="https://keyglove.net/wp-content/uploads/2014/08/arduino_iwrap_demo_generic1-300x173.png" alt="arduino_iwrap_demo_generic[1]" width="300" height="173" class="aligncenter size-medium wp-image-1462" /></a></p>
<p>With the right configuration, the Keyglove can now automatically reconnect to one or more previously paired devices, even going so far as supporting simultaneous connections. This means, for instance, that you could connect to your PC and your smartphone at the same time, and have one set of touches trigger behavior on the PC while a different set controls the media functionality on your phone. Yep, it&#8217;s that flexible.</p>
<p>The post <a href="https://keyglove.net/2014/08/08/functional-bluetooth-and-rewritten-iwrap-library/">Functional Bluetooth and Rewritten iWRAP Library</a> appeared first on <a href="https://keyglove.net">Keyglove</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://keyglove.net/2014/08/08/functional-bluetooth-and-rewritten-iwrap-library/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1461</post-id>	</item>
		<item>
		<title>Keyglove API (KGAPI) Protocol Features</title>
		<link>https://keyglove.net/2014/08/07/keyglove-api-kgapi-protocol-features/</link>
					<comments>https://keyglove.net/2014/08/07/keyglove-api-kgapi-protocol-features/#respond</comments>
		
		<dc:creator><![CDATA[Jeff Rowberg]]></dc:creator>
		<pubDate>Fri, 08 Aug 2014 03:52:53 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[protocol]]></category>
		<guid isPermaLink="false">https://keyglove.net/?p=1457</guid>

					<description><![CDATA[<p>I've implemented a straightforward protocol that you can use to control the Keyglove (or at least the initial version of it). This Keyglove API, or "KGAPI", can be used both externally and internally.</p>
<p>The post <a href="https://keyglove.net/2014/08/07/keyglove-api-kgapi-protocol-features/">Keyglove API (KGAPI) Protocol Features</a> appeared first on <a href="https://keyglove.net">Keyglove</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>For those not already aware, I&#8217;ve been working on a straightforward protocol that you can use to control the Keyglove. This (or at least the initial version of it) is now complete. This Keyglove API, or &#8220;KGAPI&#8221;, is made up of the following basic types of communication:</p>
<ul>
<li><strong>Commands:</strong> sent to the Keyglove to make stuff happen</li>
<li><strong>Responses:</strong> sent back from the Keyglove after commands are sent, acknowledging or reporting errors</li>
<li><strong>Events:</strong> sent from the Keyglove when things happen that aren&#8217;t directly triggered by commands, such as touch sensor changes or new motion data</li>
</ul>
<p>This is the same kind of structure that you will find in many protocols used by hardware peripherals, so there&#8217;s nothing particularly special here.<br />
<span id="more-1457"></span></p>
<p>However, one important point to mention is that while you can use the KGAPI protocol from an external device like the PC to which you&#8217;ve connected the Keyglove, <strong>you can also use exactly the same &#8220;vocabulary&#8221; of commands, responses, and events right in your custom application code in the firmware</strong>. This gives you a <em>lot</em> of power and flexibility that you won&#8217;t find in other similar devices; rather than just making external control possible, the Keyglove implementation makes it as easy and intuitive as possible to tweak the firmware itself (remember <a href="https://keyglove.net/docs/arduino/application_8h_source.html" target="_blank">application.h</a>?), even going so far as to use the same command names, parameters, etc.</p>
<p>What does this mean practically? Let&#8217;s say that you write a Python script which talks to the Keyglove using KGAPI, and handles the &#8220;touch_status&#8221; event (which happens whenever any touch sensor changes state), and inside that event handler you use the &#8220;motion_set_mode&#8221; command to turn on and off the motion sensor based on the touch status. Rather than making the PC do that work, you could use the exact same set of commands and events to make that behavior part of the firmware itself.</p>
<p>You could further offload basically anything from the PC onto the Keyglove itself&#8211;touch interpretation, motion processing, Bluetooth connection automation, feedback, you name it&#8211;so the only thing the connected host sees is the actual control signals over the human input device (HID) interface. This is in fact how I assume many people will want to use the Keyglove, but this alone is too limiting. Not everyone has the same implementation vision as I do, and I want to empower as many different use cases as I possibly can with this platform. My last visit to Maker Faire powerfully communicated the importance of that goal to me, and now, it has become a reality.</p>
<p>Another feature worth mentioning is the ability to extend the KGAPI protocol with your own commands, responses, and events if desired. This is more than most people will want to mess with, probably, but for those who do, I&#8217;ve made every effort to make it easy. You can find reference code and comments in the <a href="https://github.com/jrowberg/keyglove/blob/master/keyglove/custom_protocol.h" target="_blank">custom_protocol.h</a> file.</p>
<p>I am still working on a KGAPI reference manual, but it isn&#8217;t quite ready yet. It&#8217;s coming along, but it&#8217;s still too bare. In the meantime, the previously linked documentation includes descriptions for all of the commands (functions beginning with &#8220;<strong>kg_cmd_&#8230;</strong>&#8220;), and there is a handy reference file for all of the possible event handlers you might need (the <a href="https://keyglove.net/docs/arduino/application__stubs_8h.html" target="_blank">application_stubs.h</a> file).</p>
<p>I also have a Python implementation of the whole API including a parser and a few test scripts, and I am working on a simple cross-platform graphical testing application, also written in Python and using the <a href="http://www.wxpython.org/" target="_blank">wxPython</a> GUI toolkit:</p>
<p><a href="https://keyglove.net/wp-content/uploads/2014/08/kgks20140803_keyglove_gui.png" rel="wp-prettyPhoto[1457]"><img decoding="async" src="https://keyglove.net/wp-content/uploads/2014/08/kgks20140803_keyglove_gui-300x225.png" alt="kgks20140803_keyglove_gui" width="300" height="225" class="aligncenter size-medium wp-image-1454" srcset="https://keyglove.net/wp-content/uploads/2014/08/kgks20140803_keyglove_gui-300x225.png 300w, https://keyglove.net/wp-content/uploads/2014/08/kgks20140803_keyglove_gui.png 600w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>This will be published as soon as I consider it to be stable. There are only a few fixes and additions remaining before it will reach that point. However, the core <a href="https://github.com/jrowberg/keyglove/blob/master/hostapps/python/kglib.py" target="_blank">KGLib parser library</a> and a <a href="https://github.com/jrowberg/keyglove/blob/master/hostapps/python/kglib_test_demo_serial.py" target="_blank">console-based test script</a> are already available on the Github repo.</p>
<p>The API itself is fundamentally defined in its entirety in JSON format, which should make it as easy as possible to work with the protocol and integrate in any way you choose into custom host applications.</p>
<p>The post <a href="https://keyglove.net/2014/08/07/keyglove-api-kgapi-protocol-features/">Keyglove API (KGAPI) Protocol Features</a> appeared first on <a href="https://keyglove.net">Keyglove</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://keyglove.net/2014/08/07/keyglove-api-kgapi-protocol-features/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1457</post-id>	</item>
		<item>
		<title>Shiny New Keyglove Firmware on Github</title>
		<link>https://keyglove.net/2014/08/07/shiny-new-keyglove-firmware-on-github/</link>
					<comments>https://keyglove.net/2014/08/07/shiny-new-keyglove-firmware-on-github/#respond</comments>
		
		<dc:creator><![CDATA[Jeff Rowberg]]></dc:creator>
		<pubDate>Fri, 08 Aug 2014 03:33:26 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[kit]]></category>
		<category><![CDATA[protocol]]></category>
		<guid isPermaLink="false">https://keyglove.net/?p=1451</guid>

					<description><![CDATA[<p>The development between now and my last post has been pretty significant. The biggest recent news is the updated and largely rewritten Arduino firmware source code that powers the microcontroller at the core of the Keyglove design.</p>
<p>The post <a href="https://keyglove.net/2014/08/07/shiny-new-keyglove-firmware-on-github/">Shiny New Keyglove Firmware on Github</a> appeared first on <a href="https://keyglove.net">Keyglove</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>The development between now and my last post has been pretty significant. I published a <a href="https://www.kickstarter.com/projects/jrowberg/keyglove-wearable-input-device/posts/938410" target="_blank">new Kickstarter project update</a> a few days ago, but I don&#8217;t want to fragment the news updates, so I&#8217;m (mostly) reproducing that content here.</p>
<p>The biggest news is the updated and largely rewritten Arduino firmware source code that powers the microcontroller at the core of the Keyglove design. Since this is an open-source project, it has always been my intention to publish the complete source so that anyone can understand or modify the functionality however they might wish to. However, I am a bit of a neat freak when it comes to code. Well, &#8220;a bit&#8221; may be an understatement. It&#8217;s hard for me to work with or around code that isn&#8217;t organized, and/or formatted, and/or documented well, and it&#8217;s even harder for me to publish it knowing that others may need or want to use it in their own designs. Before I feel good about handing something to the world, it must pass my own tests for organization, readability, and documentation.<br />
<span id="more-1451"></span></p>
<p>In light of this, a significant portion of my work on the Keyglove project over the last few months has been making all of my code consistent, splitting it up as logically as possible into modular files, and finally documenting the heck out of it. I am proud to say that these efforts have paid off, and I&#8217;ve published the not insignificant results to the <a href="https://github.com/jrowberg/keyglove/tree/master/keyglove" target="_blank">Github repo</a>, and all of the <a href="https://keyglove.net/docs/arduino">documentation</a> to go with it.</p>
<p><a href="https://keyglove.net/docs/arduino"><img loading="lazy" decoding="async" src="https://keyglove.net/wp-content/uploads/2014/08/kgks20140803_doxygen_main-300x183.png" alt="kgks20140803_doxygen_main" width="300" height="183" class="aligncenter size-medium wp-image-1453" /></a></p>
<p><a href="https://keyglove.net/docs/arduino/files.html"><img loading="lazy" decoding="async" src="https://keyglove.net/wp-content/uploads/2014/08/kgks20140803_doxygen_files-300x183.png" alt="kgks20140803_doxygen_files" width="300" height="183" class="aligncenter size-medium wp-image-1452" /></a></p>
<p>It&#8217;s great to write so-called &#8220;self-documenting&#8221; code, and I have tried to do that. I don&#8217;t want people to need to refer to documentation any more than is absolutely necessary, and well-written, well-commented code can go a long way. But at the same time, there is no substitute for good documentation. The code that makes perfect sense to me because I wrote it might make no sense at all to someone else. The documentation linked above is my initial attempt to make sure that doesn&#8217;t happen. It will undoubtedly be improved over time, but for now, it&#8217;s a good start.</p>
<p>So what exactly does the current published Keyglove firmware support?</p>
<ul>
<li><a href="https://www.pjrc.com/store/teensypp.html" target="_blank">Teensy++ 2.0</a> microcontroller</li>
<li>USB (wired) HID and serial connectivity</li>
<li>Bluetooth (wireless) HID and serial connectivity</li>
<li>Up to 37 touch sensors</li>
<li>MPU-6050 6-axis motion sensor</li>
<li>Blinking LED feedback</li>
<li>RGB LED feedback</li>
<li>Vibration motor feedback</li>
<li>Piezo buzzer feedback</li>
</ul>
<p>It is up to the user whether and how each component is used in the whole system. The firmware has been written as a generic platform that can do all kinds of things (including things I haven&#8217;t imagined), but doesn&#8217;t necessarily need to. The totally default non-customized behavior is that it boots into an &#8220;idle&#8221; state after running through the initial setup process, and then simply waits for instructions from an external host. But with only a few lines of code in one single file (<a href="https://keyglove.net/docs/arduino/application_8h_source.html" target="_blank">application.h</a> for the coders reading this), you can include any autonomous behavior you want, even going so far as to make host control totally unnecessary by putting all relevant application logic right on the Keyglove itself.</p>
<p>Think of it as a keyboard + mouse + joystick + motion sensor combo device which you can load your own custom code into, and/or fully control from another device. It&#8217;s extremely customizable, and frankly, I&#8217;m proud of how far the firmware has come and how clean it is now. (And, of course, the fact that it works as intended.)</p>
<p>The post <a href="https://keyglove.net/2014/08/07/shiny-new-keyglove-firmware-on-github/">Shiny New Keyglove Firmware on Github</a> appeared first on <a href="https://keyglove.net">Keyglove</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://keyglove.net/2014/08/07/shiny-new-keyglove-firmware-on-github/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1451</post-id>	</item>
		<item>
		<title>Digital I/O Touch Detection Code Improvements</title>
		<link>https://keyglove.net/2013/08/28/digital-io-touch-detection-code-improvements/</link>
					<comments>https://keyglove.net/2013/08/28/digital-io-touch-detection-code-improvements/#comments</comments>
		
		<dc:creator><![CDATA[Jeff Rowberg]]></dc:creator>
		<pubDate>Wed, 28 Aug 2013 21:52:29 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[efficiency]]></category>
		<category><![CDATA[touch]]></category>
		<guid isPermaLink="false">https://keyglove.net/?p=1416</guid>

					<description><![CDATA[<p>I have been working with the same basic approach to digital touch detection since the inception of the Keyglove. At first, this method of scanning to detect connectivity between arbitrary I/O pins without mechanical switches seemed wonderfully functional and easily implemented. However, it has a couple of now-obvious shortcomings, plus another not-so-obvious one which I am hoping that I diagnosed correctly.</p>
<p>The post <a href="https://keyglove.net/2013/08/28/digital-io-touch-detection-code-improvements/">Digital I/O Touch Detection Code Improvements</a> appeared first on <a href="https://keyglove.net">Keyglove</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>I have been working with the same basic approach to digital touch detection since the inception of the Keyglove. That process goes something like this:</p>
<ol>
<li>Pull all touch points to logic high</li>
<li>Select possible combination <em>[X, Y]</em> from touch definition array</li>
<li>Set point <em>[X]</em> low</li>
<li>Measure the level of point <em>[Y]</em>, and if it is low, then touch combination <em>[X, Y]</em> is active</li>
<li>Increment test combination index and go back to step #2 until complete</li>
</ol>
<p>At first, this method of scanning to detect connectivity between arbitrary I/O pins without mechanical switches seemed wonderfully functional and easily implemented. I used Arduino&#8217;s built-in <code>digitalWrite()</code> and <code>digitalRead()</code> functions, which was the simple solution. It was also plenty fast enough at the time. However, it has a couple of now-obvious shortcomings, plus another not-so-obvious one which I am hoping that I diagnosed correctly.<br />
<span id="more-1416"></span></p>
<ul>
<li>There&#8217;s a lot more bit flipping than there needs to be. For example, the &#8220;Y&#8221; sensor gets pulsed low five times during the course of all combination tests, and it only really needs to be pulsed once if the subsequent corresponding pin reads are all done in the right order.</li>
<li>The <code>digitalWrite()</code> and <code>digitalRead()</code> functions are <a href="http://www.billporter.info/2010/08/18/ready-set-oscillate-the-fastest-way-to-change-arduino-pins/">ridiculously slow compared to direct port manipulation</a> (~20 times slower).</li>
<li>The specific polling speed is generating some capacitance or crosstalk or I don&#8217;t even know what, but the end result is that I&#8217;m getting phantom touch reports when nothing is actually touching. The problem is far, far less likely to occur when I set the CPU to 4MHz instead of 8MHz, which is what leads me to believe it has to do with the polling frequency and pattern.</li>
</ul>
<p>My original I/O read loop looks like this:</p>
<pre><code>// loop through every possible 1-to-1 sensor combination and record levels
for (i = 0; i &lt; KG_BASE_COMBINATIONS; i++) {
    p1 = combinations[i][0];
    p2 = combinations[i][1];

    pinMode(p1, OUTPUT);    // change to OUTPUT mode
    digitalWrite(p1, LOW);  // bring LOW (default input level is HIGH)
    if (i &lt; 32) {
        // write value to sensors1
        if (digitalRead(p2) == LOW) bitSet(detect1, i);
    } else {
        // write value to sensors2
        if (digitalRead(p2) == LOW) bitSet(detect2, i - 32);
    }
    pinMode(p1, INPUT);     // reset to INPUT mode
    digitalWrite(p1, HIGH); // enable pullup
}
</code></pre>
<p>It produces pulses that are about 11.4 microseconds wide, and the whole cycle through all tests takes about 2 milliseconds (or ~20% of the 10ms-wide interval allowed for the entire board to run at 100 Hz):</p>
<p><a href="https://keyglove.net/wp-content/uploads/2013/07/keyglove_io_polling_loop.png" rel="wp-prettyPhoto[1416]"><img loading="lazy" decoding="async" src="https://keyglove.net/wp-content/uploads/2013/07/keyglove_io_polling_loop-1024x367.png" alt="keyglove_io_polling_loop" width="600" height="215" class="aligncenter size-large wp-image-1419" srcset="https://keyglove.net/wp-content/uploads/2013/07/keyglove_io_polling_loop-1024x367.png 1024w, https://keyglove.net/wp-content/uploads/2013/07/keyglove_io_polling_loop-300x108.png 300w, https://keyglove.net/wp-content/uploads/2013/07/keyglove_io_polling_loop-768x275.png 768w, https://keyglove.net/wp-content/uploads/2013/07/keyglove_io_polling_loop.png 1143w" sizes="auto, (max-width: 600px) 100vw, 600px" /></a></p>
<p>It&#8217;s really very clean and functional, and certainly a straightforward way to do it without a complete architecture shift and writing code that will only function with one specific Arduino or Teensy or Keyglove board design at a time. Well, honestly, 20% of a 10ms cycle is way too long for that functionality. Improving it is definitely worth writing some platform-specific code with a new architecture.</p>
<p>So I did.</p>
<p>The new code directly accesses the PIN and PORT registers that the AT90USB1286 provides (e.g. DDRB, PORTB, and PINB), and it will only work properly on that specific MCU. It also avoids any kind of abstracted pin definition array and runs through the entire complement of touch combinations manually in one long list. I&#8217;m not opposed to loops, of course, but it&#8217;s difficult to work efficiently with hardware registers at a bit level when using loops.</p>
<p>Here&#8217;s what one portion of the new code looks like, the part that checks all of the &#8220;Z&#8221; combinations:</p>
<pre>// check on Z combinations (PB5)
SET(DDRB, 5);       // set to OUTPUT
CLR(PORTB, 5);      // set to LOW
delayMicroseconds(3); // give the poor receiving pins a chance to change state
_pina = PINA; _pinf = PINF;
CLR(DDRB, 5);       // set to INPUT
SET(PORTB, 5);      // pull HIGH
if (!(_pinf &amp; (1 &lt;&lt; 2))) touches[3] |= 0x02;    // M (PF2)
if (!(_pinf &amp; (1 &lt;&lt; 3))) touches[3] |= 0x04;    // N (PF3)
if (!(_pinf &amp; (1 &lt;&lt; 4))) touches[3] |= 0x08;    // O (PF4)
if (!(_pina &amp; (1 &lt;&lt; 2))) touches[3] |= 0x10;    // P (PA2)
if (!(_pina &amp; (1 &lt;&lt; 1))) touches[3] |= 0x20;    // Q (PA1)
if (!(_pina &amp; (1 &lt;&lt; 0))) touches[3] |= 0x40;    // R (PA0)</pre>
<p>The approach here is streamlined in two different ways compared to the previous approach:</p>
<ol>
<li>Direct register access is used instead of <code>pinMode()</code>, <code>digitalRead()</code>, and <code>digitalWrite()</code>. This is MUCH faster.</li>
<li>Combinations are set and read in batches instead of one at a time. So all combinations that use &#8220;Z&#8221; are done at once by setting &#8220;Z&#8221; low and then individually reading the pin register bits for all other potentially affected pins. This means that instead of doing 240 pin mode/level change operations for all 60 combinations, I only have to do 11 (and even this could be reduced further). Also, because of point #1 here, each of those 11 actions executes about 20 times faster than each of the 240 actions before.</li>
</ol>
<p><strong>The bottom line is that the new approach completes the entire test in about 50 microseconds instead of 2 milliseconds. That is a speed increase by a factor of 40. Amazing.</strong></p>
<p>One interesting hiccup I had to work through was that although the code looked right and the majority of the touch combinations appeared to work, there were some that just would <em>not</em> register properly, even though they worked when I manually tied the failing pins to ground. The solution turned out to be that <code>delayMicroseconds(3)</code> call. The failing combinations involved, in every case, the input pins on the first port that I read after changing the logic level of the single output pin being tested. Since the <em>very</em> next call was to read the other port status, this executed so fast that the internal pin circuitry <strong>didn&#8217;t have enough time to detect the voltage change by the time I tried to read it</strong>. Go figure! Adding a tiny delay solved the problem instantly.</p>
<p>The above code (direct register polling) is what I have running now for development, but there is actually something more I need to do to improve it significantly: stop polling and use interrupts instead, at least while there are no active touches. This will allow the MCU to sleep for the vast majority of the time, greatly extending battery life. The downside to interrupts is that there is no easy way to detect exactly which <em>two</em> pins were connected together, unless you have a zillion different interrupts. I don&#8217;t, and I wouldn&#8217;t want to do that even if I could, because it&#8217;s too complicated given the other option. Instead, this will be the approach:</p>
<ol>
<li>Enable &#8220;falling edge&#8221; interrupts for a subset of pins (e.g. palm and thumb sensors), and pull them all high.</li>
<li>Set the rest of the pins to output/low.</li>
<li>When any of the interrupts are triggered, enter the polling loop to determine exactly which touches are active.</li>
<li>As soon as no more touches are active, stop polling and go back to interrupt-only.</li>
</ol>
<p>Even when actively in use, I expect that touches won&#8217;t be active for more than 20% of the time due to human dexterity and reaction time. Therefore, I expect this approach should let the MCU sleep for a <em>lot</em> of the time that the device is on.</p>
<p>The post <a href="https://keyglove.net/2013/08/28/digital-io-touch-detection-code-improvements/">Digital I/O Touch Detection Code Improvements</a> appeared first on <a href="https://keyglove.net">Keyglove</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://keyglove.net/2013/08/28/digital-io-touch-detection-code-improvements/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1416</post-id>	</item>
		<item>
		<title>Controlling Glass via Bluetooth with a Bluegiga WT12</title>
		<link>https://keyglove.net/2013/07/06/controlling-glass-via-bluetooth-with-a-bluegiga-wt12/</link>
					<comments>https://keyglove.net/2013/07/06/controlling-glass-via-bluetooth-with-a-bluegiga-wt12/#comments</comments>
		
		<dc:creator><![CDATA[Jeff Rowberg]]></dc:creator>
		<pubDate>Sat, 06 Jul 2013 17:21:13 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Hardware]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[bluetooth]]></category>
		<category><![CDATA[glass]]></category>
		<category><![CDATA[hid]]></category>
		<category><![CDATA[input]]></category>
		<guid isPermaLink="false">https://keyglove.net/?p=1380</guid>

					<description><![CDATA[<p>We're now one step closer to my ultimate goal of using the Keyglove as a wireless input device to control a wearable computer. The latest milestone is Bluetooth control of Glass using a Bluegiga WT12 module and the custom HID descriptor that I wrote about earlier.</p>
<p>The post <a href="https://keyglove.net/2013/07/06/controlling-glass-via-bluetooth-with-a-bluegiga-wt12/">Controlling Glass via Bluetooth with a Bluegiga WT12</a> appeared first on <a href="https://keyglove.net">Keyglove</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Here we are, one step closer to my ultimate goal of using the Keyglove as a wireless input device to control a wearable computer. For this installment of progress, the milestone is Bluetooth control of Glass, using a Bluegiga WT12 module and <a href="https://keyglove.net/2013/05/30/complex-bluetooth-hid-with-iwrap-and-the-bluegiga-wt12/">the custom HID descriptor that I wrote about earlier</a>. I won&#8217;t go into detail about what that descriptor does, since it&#8217;s all documented in the other post, but the short version is that it provides a keyboard, consumer page control (e.g. media), mouse, and raw bidirectional 16-byte packet transference.</p>
<p><span id="more-1380"></span></p>
<p>First, I wanted to see what I could easily find out about the Glass Bluetooth subsystem. So, I plugged in my <a href="http://www.inmojo.com/store/jeff-rowberg/item/wt12-bluetooth-breakout-board/">WT12 breakout</a> and an <a href="https://www.sparkfun.com/products/9873">FTDI board</a> for simple control from a host PC and opened Realterm. The Bluegiga iWRAP firmware running on the WT12 has a couple of commands that are useful for discovery, namely <strong>INQUIRY</strong> (find other Bluetooth devices) and </strong>SDP</strong> (service discovery protocol for finding out what a given device can actually do via Bluetooth).</p>
<p>In order to get glass into &#8220;discoverable&#8221; mode, all you have to do is go to the normal Glass Home Settings card, and swipe to the Bluetooth card. Glass will then be discoverable for a short while (probably 60 or 120 seconds, but I didn&#8217;t measure it).</p>
<p><a href="https://keyglove.net/wp-content/uploads/2013/07/droidAtScreen-264.png" rel="wp-prettyPhoto[1380]"><img loading="lazy" decoding="async" src="https://keyglove.net/wp-content/uploads/2013/07/droidAtScreen-264-300x168.png" alt="droidAtScreen-264" width="300" height="168" class="aligncenter size-medium wp-image-1410" /></a></p>
<p><a href="https://keyglove.net/wp-content/uploads/2013/07/droid@screen-7.png"><img loading="lazy" decoding="async" src="https://keyglove.net/wp-content/uploads/2013/07/droid@screen-7-300x168.png" alt="droid@screen-7" width="300" height="168" class="aligncenter size-medium wp-image-1408" /></a></p>
<p>Once it is discoverable, we can run an inquiry and SDP discovery from iWRAP. Here&#8217;s the basic inquiry/name response, including the Class of Device reported by Glass (running XE7 firmware):</p>
<pre>
<strong>in 10 name</strong>
INQUIRY_PARTIAL f8:8f:ca:24:5b:84 200714
INQUIRY 1
INQUIRY f8:8f:ca:24:5b:84 200714
NAME f8:8f:ca:24:5b:84 "Jeff Rowberg's Glass"
</pre>
<p>Pretty basic stuff. The MAC is unique to each device, and the name reported is based (apparently) on the Google account it&#8217;s set up with. The Class of Device can be reverse-engineered with the <a href="http://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html">CoD Generator</a>. 0x200714 works out to the following:</p>
<ul>
<li>Major service class: <strong>Audio (0x200000)</strong></li>
<li>Major device class: <strong>Wearable (0x700)</strong></li>
<li>Minor device class: <strong>Helmet (0x10)</strong>, <strong>Glasses (0x4)</strong></li>
</ul>
<p>This makes sense based on what Glass is, and what functionality it provides. It&#8217;s a wearable device, and it acts as a phone headset. That&#8217;s about it from a Bluetooth perspective, as far as I know.</p>
<p>Now we can try an SDP search for all reported services:</p>
<pre>
<strong>sdp f8:8f:ca:24:5b:84 1002 all</strong>
SDP f8:8f:ca:24:5b:84 &lt; I 0 I 10000 &gt; &lt; I 1 &lt; U 111e U 1203 &gt; &gt; &lt; I PROTOCOLDESCRIPTORLIST &lt; &lt; U L2CAP &gt; &lt; U RFCOMM I 0d &gt; &gt; &gt; &lt; I 5 &lt; U BROWSE &gt; &gt; &lt; I 9 &lt; &lt; U 111e I 105 &gt; &gt; &gt; &lt; I SERVICENAME S "Handsfree" &gt; &lt; I 311 I 1d &gt;
SDP f8:8f:ca:24:5b:84 &lt; I 0 I 10001 &gt; &lt; I 1 &lt; U f96647cf-7f25-4277-843d-f407b4192f8b &gt; &gt; &lt; I PROTOCOLDESCRIPTORLIST &lt; &lt; U L2CAP &gt; &lt; U RFCOMM I 0e &gt; &gt; &gt; &lt; I 5 &lt; U BROWSE &gt; &gt; &lt; I SERVICENAME S "Glass Identity" &gt;
SDP
</pre>
<p>This is a pretty sparse SDP list, but not too surprising based on the CoD above. They have the hands-free profile (HFP), a custom Glass Identity service (not sure how this works yet), and that&#8217;s it. Note that the SDP entries don&#8217;t specify everything the device supports, but only what it provides itself.</p>
<p>The next step is to pair with the device. However, this is where I ran into my first snag, and that is that Glass wouldn&#8217;t accept my pairing request when I tried from the iWRAP side:</p>
<pre>
<strong>pair f8:8f:ca:24:5b:84</strong>
SSP COMPLETE f8:8f:ca:24:5b:84 HCI_ERROR_AUTH_FAIL
PAIR f8:8f:ca:24:5b:84 FAIL
</pre>
<p>I thought maybe this was because it had an active link with my Nexus 4, but when I turned my phone&#8217;s Bluetooth system off to test this, the same thing happened. It <em>might</em> have worked if I completely unpaired my phone first, but I didn&#8217;t want to try that since it&#8217;s not a good solution anyway, and there are better alternatives with a bit of work. Apparently, the only thing you can easily do with it out of the box when it comes to Bluetooth is to pair it to a phone using the Hands-Free Profile and PAN profile (for Bluetooth tethering). Therefore, I had to follow the instructions in the <a href="https://developers.google.com/events/io/sessions/332704837">Voiding Your Warranty: Hacking Glass</a> session from Google I/O 2013. Fortunately, this only requires a couple of basic steps that did not in fact require voiding my warranty, or even rooting the device.</p>
<p>Here&#8217;s the process:</p>
<ol>
<li><a href="http://developer.android.com/sdk/installing/bundle.html">Install and set up the Android Developer Tools bundle</a> (a good Glass-oriented guide is <a href="http://glassdev.blogspot.com/2013/05/goole-glass-developers-jump-start.html">here</a>)</li>
<li><a href="http://appliedanalog.com/agw/?p=17">Install the ADB drivers modified to work with Glass</a> (a bit of a pain on Windows 8, since the modification makes them unsigned and <a href="http://www.addictivetips.com/windows-tips/how-to-install-any-digitally-unsigned-drivers-on-windows-8/">a special restart is required</a>)</li>
<li><a href="http://www.glassxe.com/2013/05/23/settings-apk-and-launcher2-apk-from-the-hacking-glass-session-at-google-io/">Install settings.apk and launcher2.apk using ADB</a></li>
</ol>
<p>For the purpose of documenting this process, I also installed the excellent and free <a href="http://droid-at-screen.ribomation.com/">Droid @ Screen</a> to capture Glass screenshots over ADB, as shown here and above:</p>
<p><a href="https://keyglove.net/wp-content/uploads/2013/07/droidAtScreen-1.png" rel="wp-prettyPhoto[1380]"><img loading="lazy" decoding="async" src="https://keyglove.net/wp-content/uploads/2013/07/droidAtScreen-1-300x168.png" alt="droidAtScreen-1" width="300" height="168" class="aligncenter size-medium wp-image-1387" /></a></p>
<p>Once the ADT/ADB setup is done and the new .apk files are installed, swiping all the way left on the Glass timeline and tapping to access the <strong>Settings</strong> card results in a new prompt, asking whether you want to use Glass Home or Launcher to complete the action.</p>
<p><a href="https://keyglove.net/wp-content/uploads/2013/07/droidAtScreen-29.png" rel="wp-prettyPhoto[1380]"><img loading="lazy" decoding="async" src="https://keyglove.net/wp-content/uploads/2013/07/droidAtScreen-29-300x168.png" alt="droidAtScreen-29" width="300" height="168" class="aligncenter size-medium wp-image-1388" /></a></p>
<p>Using Glass Home will take you to the normal timeline-based settings area, but selecting Launcher takes you a generic normal-looking Android home screen, with no icons.</p>
<p><a href="https://keyglove.net/wp-content/uploads/2013/07/droidAtScreen-32.png" rel="wp-prettyPhoto[1380]"><img loading="lazy" decoding="async" src="https://keyglove.net/wp-content/uploads/2013/07/droidAtScreen-32-300x168.png" alt="droidAtScreen-32" width="300" height="168" class="aligncenter size-medium wp-image-1389" /></a></p>
<p>Swipe and tap on the app tray icon to bring up the list of apps, of which on my device there are now three:</p>
<p><a href="https://keyglove.net/wp-content/uploads/2013/07/droidAtScreen-39.png" rel="wp-prettyPhoto[1380]"><img loading="lazy" decoding="async" src="https://keyglove.net/wp-content/uploads/2013/07/droidAtScreen-39-300x168.png" alt="droidAtScreen-39" width="300" height="168" class="aligncenter size-medium wp-image-1390" /></a></p>
<p>Selecting the new &#8220;Settings&#8221; app gives us the classic Android Settings view. Many of these items will generate an &#8220;Unexpected error&#8221; message followed by dumping you back in the app tray. However, the all-important <strong>Bluetooth</strong> section works, and that&#8217;s good because that is where we need to go.</p>
<p><a href="https://keyglove.net/wp-content/uploads/2013/07/droidAtScreen-49.png" rel="wp-prettyPhoto[1380]"><img loading="lazy" decoding="async" src="https://keyglove.net/wp-content/uploads/2013/07/droidAtScreen-49-300x168.png" alt="droidAtScreen-49" width="300" height="168" class="aligncenter size-medium wp-image-1391" /></a></p>
<p>From here, we can see currently paired devices (e.g. my Nexus 4), and we can discover and pair with other devices, which is what we need to do now.</p>
<p><a href="https://keyglove.net/wp-content/uploads/2013/07/droidAtScreen-51.png" rel="wp-prettyPhoto[1380]"><img loading="lazy" decoding="async" src="https://keyglove.net/wp-content/uploads/2013/07/droidAtScreen-51-300x168.png" alt="droidAtScreen-51" width="300" height="168" class="aligncenter size-medium wp-image-1392" /></a></p>
<p>Select and activate the &#8220;Search for devices&#8221; option to discover any visible Bluetooth devices nearby. In order for this to work, the Keyglove&#8217;s WT12 module has to be in discoverable mode. In iWRAP terms, this means <strong>PAGEMODE 3</strong>, or else <strong>PAGEMODE 4</strong> with no active connections. Fortunately for us, this is how I have it set up.</p>
<p><a href="https://keyglove.net/wp-content/uploads/2013/07/droidAtScreen-57.png" rel="wp-prettyPhoto[1380]"><img loading="lazy" decoding="async" src="https://keyglove.net/wp-content/uploads/2013/07/droidAtScreen-57-300x168.png" alt="droidAtScreen-57" width="300" height="168" class="aligncenter size-medium wp-image-1393" /></a></p>
<p>Since the Keyglove does show up as it should, all we have to do is select it and tap to pair. I have also configured it to use &#8220;just works&#8221; pairing mode, which doesn&#8217;t have man-in-the-middle protection enabled, but as a result means that neither side has to deal with any PIN codes.</p>
<p><a href="https://keyglove.net/wp-content/uploads/2013/07/droidAtScreen-92.png" rel="wp-prettyPhoto[1380]"><img loading="lazy" decoding="async" src="https://keyglove.net/wp-content/uploads/2013/07/droidAtScreen-92-300x168.png" alt="droidAtScreen-92" width="300" height="168" class="aligncenter size-medium wp-image-1394" /></a></p>
<p>Aaand, voila! We&#8217;re paired and connected with my combo HID descriptor and ready to have some fun.</p>
<p><a href="https://keyglove.net/wp-content/uploads/2013/07/droidAtScreen-200.png" rel="wp-prettyPhoto[1380]"><img loading="lazy" decoding="async" src="https://keyglove.net/wp-content/uploads/2013/07/droidAtScreen-200-300x168.png" alt="droidAtScreen-200" width="300" height="168" class="aligncenter size-medium wp-image-1395" /></a></p>
<p>At this point, now we issue a &#8220;<strong>SELECT 1</strong>&#8221; command to iWRAP running in the serial terminal to select the HID input link, then send raw reports or, for basic ASCII alphanumeric characters and space/backspace/enter, simply type them into the serial terminal (iWRAP translates these for you). The raw HID reports give you more control over exactly what is sent to the device, so I like to use those instead of the automatically &#8220;wrapped&#8221; ASCII characters.</p>
<p>While you can certainly send your everyday typed alphanumeric characters and symbols and things to Glass, the Glass Home interface makes it not all that useful at the moment. What I am mainly interested in is how to actually <em>control</em> Glass, to navigate through the timeline, select things, and trigger special actions like changing the volume, taking a picture, turning the projector on and off, etc. Through a lot of experimentation, I found that at least most of what I want to do is possible. I couldn&#8217;t find a HID report that would instantly snap a photo, but it is still quite possible that one exists&mdash;or that a specific combination would work. If anyone knows, I would love to hear from you.</p>
<p>The main reports that I wanted to test were non-alphanumeric keyboard codes and all of the Consumer Page reports I could try. I am sure that I didn&#8217;t manage to find all of the functionality possible, but I&#8217;ve got a good start. The keyboard reports are simple enough; each one is a single code, triggered by sending a report with that code in one of the six available key slots followed shortly (I used a 20ms delay) by a report with 0x00 in that same key slot. This effectively simulates a press and release. Remember from the last post that in iWRAP, the keyboard raw report format is this:</p>
<pre>
0x9F 0x0A 0xA1 0x01 [modifier] 0x00 [key1] [key2] [key3] [key4] [key5] [key6]
</pre>
<p>So, sending the &#8220;Enter&#8221; key (code = 0x28) looks like this:</p>
<pre>
0x9F 0x0A 0xA1 0x01 0x00 0x00 <strong>0x28</strong> 0x00 0x00 0x00 0x00 0x00
</pre>
<pre>
0x9F 0x0A 0xA1 0x01 0x00 0x00 <strong>0x00</strong> 0x00 0x00 0x00 0x00 0x00
</pre>
<p>Here are the relevant keyboard codes that I found to be useful in working with the timeline UI:</p>
<ul>
<li><code>0x28</code> &#8211; Enter (select)</li>
<li><code>0x29</code> &#8211; Escape (cancel/back)</li>
<li><code>0x4f</code> &#8211; D-pad Right</li>
<li><code>0x50</code> &#8211; D-pad Left</li>
<li><code>0x51</code> &#8211; D-pad Down</li>
<li><code>0x52</code> &#8211; D-pad Up</li>
<li><code>0x65</code> &#8211; Menu</li>
</ul>
<p>There aren&#8217;t that many, but with these actions, you can replace the vast majority tapping or swiping the side of Glass. (The new double-tap/hold that you can do in the XE7 web browser is one that I haven&#8217;t figured out yet.) The Menu report gives you access to the app&#8217;s menu, assuming it has one. There&#8217;s no other way to do this with Glass as far as I am aware, so there&#8217;s an added bonus: new functionality! Here&#8217;s an example of using the Menu report to access the wallpaper setting on the Launcher app, followed by basic D-pad selection:</p>
<p><a href="https://keyglove.net/wp-content/uploads/2013/07/droid@screen-3.png"><img loading="lazy" decoding="async" src="https://keyglove.net/wp-content/uploads/2013/07/droid@screen-3-300x168.png" alt="droid@screen-3" width="300" height="168" class="aligncenter size-medium wp-image-1403" /></a></p>
<p><a href="https://keyglove.net/wp-content/uploads/2013/07/droid@screen-4.png"><img loading="lazy" decoding="async" src="https://keyglove.net/wp-content/uploads/2013/07/droid@screen-4-300x168.png" alt="droid@screen-4" width="300" height="168" class="aligncenter size-medium wp-image-1404" /></a></p>
<p><a href="https://keyglove.net/wp-content/uploads/2013/07/droid@screen-5.png"><img loading="lazy" decoding="async" src="https://keyglove.net/wp-content/uploads/2013/07/droid@screen-5-300x168.png" alt="droid@screen-5" width="300" height="168" class="aligncenter size-medium wp-image-1405" /></a></p>
<p>So what about other shortcuts? For that, we look to Consumer Page reports. These have a different structure, if you recall:</p>
<pre>
0x9F 0x05 0xA1 0x02 [field1] [field2] [field3]
</pre>
<p>It&#8217;s set up for a 3-byte-wide set of bitfields instead of distinct key slots. The same concept for press/release cycles applies here though. Here are the relevant consumer page reports that I found to be useful for Glass:</p>
<ul>
<li><code>0x00 0x00 0x01</code> &#8211; Volume Up</li>
<li><code>0x00 0x00 0x02</code> &#8211; Volume Down</li>
<li><code>0x00 0x00 0x08</code> &#8211; Toggle projector on/off (no sounds generated)</li>
<li><code>0x00 0x08 0x00</code> &#8211; Home</li>
<li><code>0x00 0x16 0x00</code> &#8211; Projector off (w/sound, like escape/swipe down)</li>
</ul>
<p>These actions combined with the D-pad navigation and selection above give you the power to do just about anything with Glass remotely. More detail on Android-specific HID input can be found <a href="http://source.android.com/devices/tech/input/keyboard-devices.html">here</a>, though I haven&#8217;t fully grasped everything there myself yet. Here&#8217;s an example of volume control with the above reports:</p>
<p><a href="https://keyglove.net/wp-content/uploads/2013/07/droidAtScreen-621.png" rel="wp-prettyPhoto[1380]"><img loading="lazy" decoding="async" src="https://keyglove.net/wp-content/uploads/2013/07/droidAtScreen-621-300x168.png" alt="droidAtScreen-621" width="300" height="168" class="aligncenter size-medium wp-image-1398" /></a></p>
<p>But what about actual tapping, for controlling touch-based apps or accessing settings that you can&#8217;t get to with the D-pad? This is mainly useful for development/porting purposes, since an app designed with Glass in mind will by definition <em>not</em> rely much on touch in the way that apps designed for touchscreens are. Even so, having this ability would be handy.</p>
<p>This is where the 3rd report in our custom HID descriptor comes in: we can actually use the <em>mouse</em> in Android! Who knew? Yes, it might look a little odd, but it works just fine. You can send typical &#8220;click&#8221; actions (though I could not see any different behavior between different button values, e.g. left vs. right vs. middle), and you can send three axes of motion data for X/Y movement as well as scrolling. Here&#8217;s an example of accessing the detailed volume settings after clicking on the button on the right </p>
<p><a href="https://keyglove.net/wp-content/uploads/2013/07/droidAtScreen-671.png" rel="wp-prettyPhoto[1380]"><img loading="lazy" decoding="async" src="https://keyglove.net/wp-content/uploads/2013/07/droidAtScreen-671-300x168.png" alt="droidAtScreen-671" width="300" height="168" class="aligncenter size-medium wp-image-1399" /></a></p>
<p>There you have it, everyone. Complete control of Glass via Bluetooth HID is actually quite easy. Other than the initial pairing hurdle, it&#8217;s no more complicated than any other Bluetooth HID implementation. Now I just need to integrate the proof of concept code with the Keyglove firmware. This may be a bit of a challenge because there are a few different ways to do it&mdash;should I use pure touch controls (e.g. tap to &#8220;swipe&#8221; left or right), or touch + motion (e.g. tap to activate, move to navigate)? Or both? It&#8217;s a flexible platform, so it won&#8217;t be locked down in any case. I will try to configure it both ways and see what feels more natural.</p>
<p>The post <a href="https://keyglove.net/2013/07/06/controlling-glass-via-bluetooth-with-a-bluegiga-wt12/">Controlling Glass via Bluetooth with a Bluegiga WT12</a> appeared first on <a href="https://keyglove.net">Keyglove</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://keyglove.net/2013/07/06/controlling-glass-via-bluetooth-with-a-bluegiga-wt12/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1380</post-id>	</item>
		<item>
		<title>Complex Bluetooth HID Input with iWRAP and the Bluegiga WT12</title>
		<link>https://keyglove.net/2013/05/30/complex-bluetooth-hid-with-iwrap-and-the-bluegiga-wt12/</link>
					<comments>https://keyglove.net/2013/05/30/complex-bluetooth-hid-with-iwrap-and-the-bluegiga-wt12/#comments</comments>
		
		<dc:creator><![CDATA[Jeff Rowberg]]></dc:creator>
		<pubDate>Fri, 31 May 2013 01:33:58 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Hardware]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[bluetooth]]></category>
		<category><![CDATA[hid]]></category>
		<category><![CDATA[keyboard]]></category>
		<category><![CDATA[mouse]]></category>
		<guid isPermaLink="false">https://keyglove.net/?p=1365</guid>

					<description><![CDATA[<p>Thanks to Bluegiga's workhorse of a class 2 Bluetooth module and the latest iWRAP5 firmware with custom HID descriptor support, I have now been able to achieve the wireless capabilities I always hoped the Keyglove would have. Keyboard, mouse with scrolling support, consumer page reports, and raw HID packets for arbitrary data transmission.</p>
<p>The post <a href="https://keyglove.net/2013/05/30/complex-bluetooth-hid-with-iwrap-and-the-bluegiga-wt12/">Complex Bluetooth HID Input with iWRAP and the Bluegiga WT12</a> appeared first on <a href="https://keyglove.net">Keyglove</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Thanks to Bluegiga&#8217;s workhorse of a class 2 Bluetooth module and the latest iWRAP5 firmware with custom HID descriptor support, I have now been able to achieve the wireless capabilities I always hoped the Keyglove would have. Keyboard, mouse <em>with scrolling support</em>, consumer page reports, and raw HID packets for arbitrary data transmission. It isn&#8217;t fully integrated into the Keyglove code yet, and I&#8217;ve only tested it with manual control so far, but the firmware setup is solid. It&#8217;s now just a matter of translating the manual control I&#8217;ve already done into my codebase.<br />
<span id="more-1365"></span></p>
<p>The enabling factor here compared to the last time I tried this (quite some time ago) is the addition of custom descriptor support in iWRAP5. I don&#8217;t know of any other module which allows the degree of simple customizability in this area that the WT12 does. It was the best module I saw two years ago, and the new features are icing on the cake. (Yes, I have been working at Bluegiga since last October, but bear in mind I was singing this module&#8217;s praises long before that started.)</p>
<p>So how does this configuration actually work? There are three important pieces involved:</p>
<ol>
<li>Building the HID descriptor</li>
<li>Configuring iWRAP</li>
<li>Sending HID report packets</li>
</ol>
<p>Naturally, I will explain each in order.</p>
<h3>Building the HID descriptor</h3>
<p>To be honest, this is the part I am least confident about. I have learned a lot about HID descriptors, but only enough to be dangerous instead of simply clueless. In short, they are sent from a device to a host during the connection establishment phase so that the host will know what kind of data to expect from the device, how it will be formatted, and what it should do with it. A HID descriptor is built using a predefined binary &#8220;language&#8221; of sorts; data bytes either denote a field or setting, or else are the byte(s) contained within the previously denoted field or setting. There are many aspects to these definitions, and I don&#8217;t fully understand them all yet. It will be much better if I point you to the resources that were most helpful for me:</p>
<ul>
<li><a href="http://www.instructables.com/id/USB-Wii-Classic-Controller/step13/Bonus-Keyboard-and-Mouse/">Step 13 of Frank Zhao&#8217;s USB Wii Classic Controller Instructable</a></li>
<li><a href="http://www.frank-zhao.com/cache/hid_tutorial_1.php">Frank Zhao&#8217;s USnooBie HID Report tutorial</a> (way to go, Frank!)</li>
<li><a href="http://www.usb.org/developers/devclass_docs/HID1_11.pdf">The USB HID device class specification (PDF)</a></li>
<li><a href="http://www.usb.org/developers/devclass_docs/Hut1_12v2.pdf">The USB HID usage tables specification (PDF)</a></li>
<li><a href="http://www.usb.org/developers/hidpage#HID Descriptor Tool">The USB HID Descriptor Tool</a></li>
<li><a href="http://www.usblyzer.com/">USBlyzer</a> for complete descriptor analysis of an existing USB device</li>
<li>The raw HID descriptor structs found in PJRC&#8217;s <a href="http://www.pjrc.com/teensy/teensyduino.html">Teensyduino</a> source</li>
</ul>
<p>Actually, the first and last links ended up being the most practically useful to me. The others are good for cross-referencing things or getting into a detailed understanding. It&#8217;s a great list to get started with if you&#8217;re looking for HID development resources. Also, USBlyzer can be amazing if you are trying to mimic the behavior of an existing wired USB device, since it can show you both the descriptor structure as well as the actual HID report traffic.</p>
<p>But what&#8217;s all this about USB? Wasn&#8217;t the whole point of this to be all wireless and Bluetoothy and stuff? Well, it turns out that the important bits of device-specific USB HID descriptors pretty much apply directly to Bluetooth HID, because as best as I can tell, Bluetooth HID is basically USB HID wrapped in a wireless transport layer. It isn&#8217;t <em>exactly</em> the same, of course, but the most important pieces—namely, the HID descriptor and corresponding HID reports—match.</p>
<p>Now, what about Bluegiga&#8217;s HID documentation? There is a HID application note for iWRAP which is quite good if you are interested in single-function devices, or if you know what you are doing with descriptors. But if you&#8217;re only good at following directions <em>and</em> you want a combo device, it&#8217;s less obvious. <em>(I will be fixing this shortly, because now I can!)</em> There are example descriptors supplied for a standard keyboard, standard mouse (X/Y + 3 buttons), consumer page control (e.g. calculator and music controls), and a gamepad. But what if you want a keyboard/mouse/gamepad device all in one?</p>
<p>It turns out that this is really not difficult at all. There are two basic rules you have to follow:</p>
<ol>
<li>Take each individual descriptor and mash them all together into one big long one.</li>
<li>Make sure each report structure definition includes a &#8220;Report ID&#8221; byte (0x85) and unique value (0x01 or higher).</li>
</ol>
<p>The first one is easy. The second one is not so easy if you don&#8217;t know where the Report ID byte should go. Based on my tests, it needs to go <em>after</em> the innermost &#8220;Collection&#8221; start field (0xA1 0x<em>nn</em>) somewhere. I don&#8217;t know what the rule is exactly, but I put them (when they weren&#8217;t already there) immediately after this &#8220;Collection&#8221; start field. Each report needs its own unique ID so that the host device knows which kind of report you&#8217;re sending, whenever you send one. Pretty straightforward.</p>
<p>Here is the actual descriptor I put together for my successful test last night, in C struct form:</p>
<pre>static const uint8_t hid_descriptor_combined[] = {

    // KEYBOARD

    /****/ 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
    /****/ 0x09, 0x06, /* USAGE (Keyboard) */
    /****/ 0xa1, 0x01, /* COLLECTION (Application) */
    /******/ 0x05, 0x07, /* USAGE_PAGE (Keyboard) */
    /******/ 0x85, 0x01,   /* REPORT_ID (1) */
    /* 1 byte Modifier: Ctrl, Shift and other modifier keys, 8 in total */
    /******/ 0x19, 0xe0, /* USAGE_MINIMUM (kbd LeftControl) */
    /******/ 0x29, 0xe7, /* USAGE_MAXIMUM (kbd Right GUI) */
    /******/ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
    /******/ 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
    /******/ 0x75, 0x01, /* REPORT_SIZE (1) */
    /******/ 0x95, 0x08, /* REPORT_COUNT (8) */
    /******/ 0x81, 0x02, /* INPUT (Data,Var,Abs) */
    /* 1 Reserved byte */
    /******/ 0x95, 0x01,  /* REPORT_COUNT (1) */
    /******/ 0x75, 0x08, /* REPORT_SIZE (8) */
    /******/ 0x81, 0x01, /* INPUT (Cnst,Ary,Abs) */
    /* LEDs for num lock etc */
    /******/ 0x95, 0x05, /* REPORT_COUNT (5) */
    /******/ 0x75, 0x01, /* REPORT_SIZE (1) */
    /******/ 0x05, 0x08, /* USAGE_PAGE (LEDs) */
    /******/ 0x85, 0x01, /* REPORT_ID (1) */
    /******/ 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */
    /******/ 0x29, 0x05, /* USAGE_MAXIMUM (Kana) */
    /******/ 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
    /* Reserved 3 bits */
    /******/ 0x95, 0x01, /* REPORT_COUNT (1) */
    /******/ 0x75, 0x03, /* REPORT_SIZE (3) */
    /******/ 0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */
    /* Slots for 6 keys that can be pressed down at the same time */
    /******/ 0x95, 0x06, /* REPORT_COUNT (6) */
    /******/ 0x75, 0x08, /* REPORT_SIZE (8) */
    /******/ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
    /******/ 0x25, 0x65, /* LOGICAL_MAXIMUM (101) */
    /******/ 0x05, 0x07, /* USAGE_PAGE (Keyboard) */
    /******/ 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */
    /******/ 0x29, 0x65, /* USAGE_MAXIMUM (Keyboard Application) */
    /******/ 0x81, 0x00, /* INPUT (Data,Ary,Abs) */
    /****/ 0xc0, /* END_COLLECTION */

    // CONSUMER PAGE

    /****/ 0x05, 0x0c, /* USAGE_PAGE (Consumer) */
    /****/ 0x09, 0x01, /* USAGE (Consumer Control) */
    /****/ 0xa1, 0x01, /* COLLECTION (Application) */
    /******/ 0x85, 0x02, /* Report ID 2 */
    /******/ 0x05, 0x0c, /* USAGE_PAGE (Consumer) */
    /* 8 media player related keys */
    /******/ 0x15, 0x00, /* Logical Min 0 */
    /******/ 0x25, 0x01, /* Logical Max 1 */
    /******/ 0x09, 0xe9, /* Usage (8-bit), Volume Increment */
    /******/ 0x09, 0xea, /* Usage (8-bit), Volume Decrement */
    /******/ 0x09, 0xe2, /* Usage (8-bit), Mute */
    /******/ 0x09, 0xcd, /* Usage (8-bit), Play/Pause */
    /******/ 0x19, 0xb5, /* Usage Min (Scan Next Track, Scan Previous Track, Stop, Eject) */
    /******/ 0x29, 0xb8, /* Usage Max */
    /******/ 0x75, 0x01, /* Report Size */
    /******/ 0x95, 0x08, /* Report Count */
    /******/ 0x81, 0x02, /* Input type 2 */
    /* 8 application control keys */
    /******/ 0x0a, 0x8a, 0x01,/* Usage (16-bit), LSB first, e.g. this is 0x018a Email Reader */
    /******/ 0x0a, 0x21, 0x02,/* Usage (16-bit), Generic GUI Application Control Search */
    /******/ 0x0a, 0x2a, 0x02,/* Usage (16-bit), Application Control Bookmarks */
    /******/ 0x1a, 0x23, 0x02,/* Usage Min (16-bit), AC Home, Back, Forward, Stop, Refresh */
    /******/ 0x2a, 0x27, 0x02,/* Usage Max (16-bit) */
    /******/ 0x75, 0x01, /* Report Size */
    /******/ 0x95, 0x08, /* Report Count */
    /******/ 0x81, 0x02, /* Input type 2 */
    /* Application launch keys + record &amp; rewind */
    /******/ 0x0a, 0x83, 0x01,/* Usage (16-bit), Application Launch Generic Consumer Control */
    /******/ 0x0a, 0x96, 0x01,/* Usage (16-bit), AL Internet Browser */
    /******/ 0x0a, 0x92, 0x01,/* Usage (16-bit), AL Calculator */
    /******/ 0x0a, 0x9e, 0x01,/* Usage (16-bit), AL Terminal Lock / Screensaver */
    /******/ 0x0a, 0x94, 0x01,/* Usage (16-bit), AL Local Machine Browser */
    /******/ 0x0a, 0x06, 0x02,/* Usage (16-bit), AC Minimize */
    /******/ 0x09, 0xb2, /* Usage (8-bit), Record */
    /******/ 0x09, 0xb4, /* Usage (8-bit), Rewind */
    /******/ 0x75, 0x01, /* Report Size */
    /******/ 0x95, 0x08, /* Report Count */
    /******/ 0x81, 0x02, /* Input type 2 */
    /******/ 0xc0,      /* End Collection */

    // MOUSE

    0x05, 0x01,       // USAGE_PAGE (Generic Desktop)
    0x09, 0x02,       // USAGE (Mouse)
    0xa1, 0x01,       // COLLECTION (Application)
    0x09, 0x01,       //   USAGE (Pointer)
    0xa1, 0x00,       //   COLLECTION (Physical)
    0x85, 0x03,       //     REPORT_ID (3)
    0x05, 0x09,       //     USAGE_PAGE (Button)
    0x19, 0x01,       //     USAGE_MINIMUM (Button 1)
    0x29, 0x03,       //     USAGE_MAXIMUM (Button 3)
    0x15, 0x00,       //     LOGICAL_MINIMUM (0)
    0x25, 0x01,       //     LOGICAL_MAXIMUM (1)
    0x95, 0x03,       //     REPORT_COUNT (3)
    0x75, 0x01,       //     REPORT_SIZE (1)
    0x81, 0x02,       //     INPUT (Data,Var,Abs)
    0x95, 0x01,       //     REPORT_COUNT (1)
    0x75, 0x05,       //     REPORT_SIZE (5)
    0x81, 0x03,       //     INPUT (Cnst,Var,Abs)
    0x05, 0x01,       //     USAGE_PAGE (Generic Desktop)
    0x09, 0x30,       //     USAGE (X)
    0x09, 0x31,       //     USAGE (Y)
    0x09, 0x38,       //     USAGE (Wheel)
    0x15, 0x81,       //     LOGICAL_MINIMUM (-127)
    0x25, 0x7f,       //     LOGICAL_MAXIMUM (127)
    0x75, 0x08,       //     REPORT_SIZE (8)
    0x95, 0x03,       //     REPORT_COUNT (3)
    0x81, 0x06,       //     INPUT (Data,Var,Rel)
    0x05, 0x0c,       //     USAGE_PAGE (Consumer Devices)
    0x0a, 0x38, 0x02, //     USAGE (Undefined)
    0x95, 0x01,       //     REPORT_COUNT (1)
    0x81, 0x06,       //     INPUT (Data,Var,Rel)
    0xc0,             //   END_COLLECTION
    0xc0,              // END_COLLECTION

    // RAW 16-BYTE I/O

    0x06, 0xAB, 0xFF,   // Usage Page (Vendor-Defined 172)
    0x0A, 0x00, 0x02,   // Usage (Vendor-Defined 512)
    0xA1, 0x01,         // Collection (Application)
    0x85, 0x04,         /* REPORT_ID (4) */
    0x75, 0x08,         // Report Size (8)
    0x15, 0x00,         // Logical Minimum (0)
    0x26, 0xFF, 0x00,   // Logical Maximum (255)
    0x95, 0x10,         // Report Count (16)
    0x09, 0x01,         // Usage (Vendor-Defined 1)
    0x81, 0x02,         // Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
    0x95, 0x10,         // Report Count (16)
    0x09, 0x02,         // Usage (Vendor-Defined 2)
    0x91, 0x02,         // Output (Data,Var,Abs,NWrp,Lin,Pref,NNul,NVol,Bit)
    0xc0,               // End Collection
};</pre>
<p>Pardon the mix of comment formatting. I pulled these together from multiple sources and built one of them by hand. The structure of this descriptor is that the standard keyboard report has ID 1, consumer page report has ID 2, mouse report has ID 3, and raw generic 16-byte data packet has ID 4.</p>
<p>However, the above isn&#8217;t directly applicable to iWRAP configuration on the WT12 module, since iWRAP doesn&#8217;t use C structs as settings. This leads us to&#8230;</p>
<h3>Configuring iWRAP</h3>
<p>Luckily for all of us, the factory default iWRAP5 firmware—currently v5.0.1 build 620—supports all the HID customization we need. (It is also freely user-upgradable if you have or want a different build for whatever reason.) The default settings enable only the serial port profile (SPP), so we have to turn on the HID profile specifically, and write our descriptor. The maximum descriptor length is 255 bytes at the moment. For simplicity, here&#8217;s the full set of relevant initialization commands that I&#8217;m sending for the Keyglove&#8217;s Bluetooth module:</p>
<pre>SET BT NAME Keyglove
SET BT CLASS 00540
SET BT IDENT USB:1d50 6025 1.0.0 Keyglove Input Device
SET BT SSP 3 0
SET CONTROL CD 80 2 20
SET CONTROL ESCAPE - 40 1
SET PROFILE HID d 40 100 0 en 0409 Keyglove Input Device
HID SET F2 05010906A1010507850119E029E715002501750195088102950175088101950575010508850119012905910295017503910395067508150025650507190029658100C0050C0901A1018502050C1500250109E909EA09E209CD19B529B87501950881020A8A010A21020A2A021A23022A27027501950881020A83010A96010A92010A9E010A94010A060209B209B4750195088102C005010902A1010901A10085030509190129031500250195037501810295017505810305010930093109381581257F750895038106050C0A380295018106C0C006ABFF0A0002A10185047508150026FF00951009018102951009029102C0</pre>
<p>That ridiculously long &#8220;HID SET&#8221; line at the end is the descriptor itself. The lone preceding &#8220;F2&#8221; value is the length (in hex) of the whole thing, which is 242 bytes. I&#8217;m right at the edge of the size limit with this one.</p>
<p>Here&#8217;s a quick breakdown of these settings (see the iWRAP5 User Guide from Bluegiga for more detail):</p>
<ul>
<li style="margin-bottom: 1em">
<pre style="margin-bottom: 0.2em">SET BT NAME Keyglove</pre>
<p>&#8211; Sets the Bluetooth device friendly name</li>
<li style="margin-bottom: 1em">
<pre style="margin-bottom: 0.2em">SET BT CLASS 00540</pre>
<p>&#8211; Sets the device class to &#8220;keyboard&#8221; (<strong>important for iOS compatibility</strong>)</li>
<li style="margin-bottom: 1em">
<pre style="margin-bottom: 0.2em">SET BT IDENT USB:1d50 6025 1.0.0 Keyglove Input Device</pre>
<p>&#8211; Sets the VID/PID, version, and self-identifying description</li>
<li style="margin-bottom: 1em">
<pre style="margin-bottom: 0.2em">SET BT SSP 3 0</pre>
<p>&#8211; Enables PIN-less &#8220;just works&#8221; secure simple pairing</li>
<li style="margin-bottom: 1em">
<pre style="margin-bottom: 0.2em">SET CONTROL CD 80 2 20</pre>
<p>&#8211; Enables GPIO output signals for active link and DATA mode status</li>
<li style="margin-bottom: 1em">
<pre style="margin-bottom: 0.2em">SET CONTROL ESCAPE - 40 1</pre>
<p>&#8211; Enable GPIO input control for exiting DATA mode</li>
<li style="margin-bottom: 1em">
<pre style="margin-bottom: 0.2em">SET PROFILE HID d 40 100 0 en 0409 Keyglove Input Device</pre>
<p>&#8211; Sets the HID options to be a keyboard class device, English layout, no localization, version 1.0.0</li>
<li style="margin-bottom: 1em">
<pre style="margin-bottom: 0.2em">HID SET F2 ...</pre>
<p>&#8211; Explained above. Sets the actual HID descriptor.</li>
</ul>
<p>Not all of these are strictly necessary for the HID functionality I&#8217;m going for (e.g. the &#8220;SET CONTROL &#8230;&#8221; commands and BT NAME), but the rest are. Note also that all of these persist through power cycles, since all of them are stored in non-volatile memory. Once these settings are applied the first time, you must power-cycle the module or issue a &#8220;RESET&#8221; command to make them take effect—particularly the newly enabled HID profile and HID descriptor.</p>
<p>Now we&#8217;re ready to actually send some data.</p>
<h3>Sending HID report packets</h3>
<p>iWRAP uses a specific encapsulation format for sending raw HID packets. It will actually let you send basic ASCII keyboard characters as plain bytes over UART—so the byte &#8216;a&#8217; (0x61) sends the keyboard HID reports for pressing and releasing the &#8216;a&#8217; key—but only if you have the standard keyboard descriptor included at the beginning of your full HID descriptor. As it happens, we do. But full control only comes through the use of raw HID packets, so that&#8217;s what we&#8217;ll be using here. The raw HID format, as described in the iWRAP HID app note, is always of this form:</p>
<pre>0x9F [length] [data ... ... ...]</pre>
<p>Where 0x9F is the start-of-frame byte, [length] is how many data bytes follow, and [data &#8230;] is the actual data itself. So, for a 6-byte packet example, it might be formatted like this:</p>
<pre>0x9F 0x06 0xAA 0xBB 0xCC 0xDD 0xEE 0xFF</pre>
<p>The above packet is invalid given our descriptors, but it illustrates the point. Remember that we have four unique reports in our combo descriptor above, so there are four possible kinds of raw reports we might send:</p>
<ol>
<li>Keyboard
<pre>0x9F 0x0A 0xA1 <strong style="color: #F00">0x01</strong> [modifier] 0x00 [key1] [key2] [key3] [key4] [key5] [key6]</pre>
</li>
<li>Consumer page
<pre>0x9F 0x05 0xA1 <strong style="color: #F00">0x02</strong> [field1] [field2] [field3]</pre>
</li>
<li>Mouse
<pre>0x9F 0x07 0xA1 <strong style="color: #F00">0x03</strong> [buttons] [x-move] [y-move] [v-scroll] [h-scroll]</pre>
</li>
<li>Raw
<pre>0x9F 0x12 0xA1 <strong style="color: #F00">0x04</strong> [data1 ... data16]</pre>
</li>
</ol>
<p>Note the Report ID byte in <strong style="color: #F00">red</strong>. For testing purposes, I like using <a href="http://realterm.sourceforge.net/index.html#downloads_Download">Realterm</a> because (1) it&#8217;s free and (2) it makes sending or displaying binary data in hex format easier than anything else I&#8217;ve seen. The UI is definitely engineer-ish, but it doesn&#8217;t take too much getting used to, and it has some features that are very hard to do without in cases like these. Realterm has a &#8220;Send&#8221; tab where you can paste bytes in hex notation (either 0xAA or $AA) and then send them as binary data, which is excellent here.</p>
<p>One important thing to point out here is that for many operations that we tend to think of as a single action, like a keypress or mouse click, there are actually two things going on. One is the press and the other is the release. It is critical that you keep this in mind when sending raw reports. Pressing the &#8216;a&#8217; key is actually sending one report with the key down and another with no keys down. Here are some examples of each kind of descriptor:</p>
<h4>Press and release the &#8216;a&#8217; key</h4>
<pre style="margin-bottom: 0.2em">0x9F 0x0A 0xA1 0x01 0x00 0x00 0x04 0x00 0x00 0x00 0x00 0x00</pre>
<pre>0x9F 0x0A 0xA1 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00</pre>
<h4>Press and release the calculator button</h4>
<pre style="margin-bottom: 0.2em">0x9F 0x05 0xA1 0x02 0x00 0x00 0x04</pre>
<pre>0x9F 0x05 0xA1 0x02 0x00 0x00 0x00</pre>
<h4>Press and release the left mouse button</h4>
<pre style="margin-bottom: 0.2em">0x9F 0x07 0xA1 0x03 0x01 0x00 0x00 0x00 0x00</pre>
<pre>0x9F 0x07 0xA1 0x03 0x00 0x00 0x00 0x00 0x00</pre>
<h4>Send 16 bytes of raw data</h4>
<pre style="margin-bottom: 0.2em">0x9F 0x12 0xA1 0x04 0x00 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88 0x99 0xAA 0xBB 0xCC 0xDD 0xEE 0xFF</pre>
<p>(This is a single action and doesn&#8217;t require a &#8220;release&#8221; report)</p>
<p>This successful implementation of complex Bluetooth HID is an excellent next step in the Keyglove development. While the raw HID (as far as I know) is not accessible on iOS devices, this same combo descriptor and iWRAP configuration allows you to connect to a PC, Mac, Linux machine, iPhone, and Android phone—and, I assume and very much hope, Google Glass. We shall see in approximately 10 days.</p>
<p>Until then, have fun with your own Bluetooth HID projects, if you are so inclined!</p>
<p>The post <a href="https://keyglove.net/2013/05/30/complex-bluetooth-hid-with-iwrap-and-the-bluegiga-wt12/">Complex Bluetooth HID Input with iWRAP and the Bluegiga WT12</a> appeared first on <a href="https://keyglove.net">Keyglove</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://keyglove.net/2013/05/30/complex-bluetooth-hid-with-iwrap-and-the-bluegiga-wt12/feed/</wfw:commentRss>
			<slash:comments>13</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1365</post-id>	</item>
		<item>
		<title>Diving Back In, and Google Glass Plans</title>
		<link>https://keyglove.net/2013/05/04/diving-back-in-and-google-glass-plans/</link>
					<comments>https://keyglove.net/2013/05/04/diving-back-in-and-google-glass-plans/#comments</comments>
		
		<dc:creator><![CDATA[Jeff Rowberg]]></dc:creator>
		<pubDate>Sun, 05 May 2013 03:35:44 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">https://keyglove.net/?p=1356</guid>

					<description><![CDATA[<p>The last seven months have been somewhat of an unplanned hiatus from the Keyglove project. Now, I am absolutely determined to get back into working on it, for a few reasons.</p>
<p>The post <a href="https://keyglove.net/2013/05/04/diving-back-in-and-google-glass-plans/">Diving Back In, and Google Glass Plans</a> appeared first on <a href="https://keyglove.net">Keyglove</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>The last seven months have been somewhat of an unplanned hiatus from the Keyglove project. As I mentioned in <a href="http://www.kickstarter.com/projects/jrowberg/keyglove-wearable-input-device/posts/340775">my last Kickstarter project update</a> as well as a bit later in <a href="http://www.sectorfej.net/2013/01/01/happy-new-year-from-the-new-us-field-application-engineer-at-bluegiga/">a post on my personal blog</a>, my position at Bluegiga has been taking virtually all of my time. There is a lot more travel, and some odd hours due to the global nature of the business and the kind of support I need to do. This has been getting better over time though—the odd hours part, anyway—and I am absolutely determined to get back into working on the project, for a few reasons.<br />
<span id="more-1356"></span></p>
<p>For one thing, I have now passed the two-year anniversary of the successful Kickstarter campaign. It was one week ago today, in fact: April 27. That is a <em>tremendously</em> long time to wait, for all those of you who backed the project. I am continually encouraged by the ongoing support, and conversely by the conspicuous lack of impatience displayed despite the long, drawn-out development process and the painfully long silences at times (like over the last many months). I want to work on this project, and I want to do it <em>now</em>. This by itself is motivating.</p>
<p>For another thing, although I haven&#8217;t had much time to <em>work</em> on the Keyglove, I have still found myself thinking about it quite often and at times doing what could be accurately called brainstorming. Some of the ideas I&#8217;ve had should prove to be fruitful once I immerse myself in development again. A corresponding observation to this point is that I think it will be beneficial for me to begin again with the codebase and designs I already have, but with a relatively fresh viewpoint. It will be easy for me to objectively evaluate the systems I have already built and look for any areas which may benefit from certain changes or a re-imagined approach. This kind of analysis is easier to do when you haven&#8217;t been neck deep in the project for a while.</p>
<p>Third, there has been quite a bit of relevant innovation in the areas of wearable computing, wireless connectivity, battery technology, and low-power programmable microcontroller systems. Might it be worthwhile to incorporate an Arduino compatible ARM processor instead of the AT90USB MCU I have? Possibly. Bluetooth Low Energy for wireless comms? Very likely, at least as an option. Flexible PCBs? Maybe. New, tiny motion sensor? Sounds great. Bundling everything into a single FPGA? It could be done. The bottom line here is that six or seven months on the embedded system design timescale is significant. There is a lot that has happened in the world since then.</p>
<p>Perhaps the most personally exciting reason for me though is this:</p>
<p><a href="https://keyglove.net/wp-content/uploads/2013/05/projectglass_sectorfej_tweet.png" rel="wp-prettyPhoto[1356]"><img loading="lazy" decoding="async" class="aligncenter size-medium wp-image-1357" alt="projectglass_sectorfej_tweet" src="https://keyglove.net/wp-content/uploads/2013/05/projectglass_sectorfej_tweet-300x187.png" width="300" height="187" /></a></p>
<p>I managed to snag a slot on the new Google Glass Explorers group as part of the <a href="https://twitter.com/search?q=%23ifihadglass">#ifihadglass</a> contest that Google put on back in February. I am definitely more excited about this than is healthy for someone as far down the list of early adopters as I am (though I am still thankful that I&#8217;m on the list in the first place). My <a href="https://twitter.com/SectorFej/status/304267259772276736">entry tweet</a> was about combining it with the Keyglove, and <a href="https://twitter.com/projectglass/status/317531425035386880">their reply</a> came a little over a month later. I was (and am) ecstatic.</p>
<p>As it happens, I actually got to try a Glass device back towards the end of January of this year, while having dinner in San Francisco with a friend from college who is now way high up on the Glass development team. It was a pretty short demo, but I was completely enamored. Truth be told, I&#8217;d actually had a dream the night before about what it might be like, in subconscious anticipation of that eventuality. I truly can hardly wait for until my turn comes to get a development unit. This is exactly the platform for which I originally created the Keyglove. I don&#8217;t know when I will get mine, but I want the Keyglove to be ready to take full advantage of the opportunity.</p>
<p>In my opinion (and <a href="https://plus.google.com/+Scobleizer/posts/ZLV9GdmkRzS">others&#8217;</a>), Google Glass has tremendous potential. Augmented reality and instant contextual information has a value that we can&#8217;t accurately quantify yet. We don&#8217;t have enough data to predict with. Glass will allow innovative people to expand the range of possibilities, to give us ideas about things we will find invaluable which today we can&#8217;t even imagine since we don&#8217;t have a mental framework to put them on. I want the Keyglove to be right there along side this discovery process, solving the input challenge where Glass so (comparatively) eloquently solves the output/display problem of wearable technology.</p>
<p>So, while I&#8217;m waiting for Glass&#8230;what&#8217;s next?</p>
<p>I need to run through the <a href="https://keyglove.net/roadmap/">Roadmap</a> again and freshen things up a bit. Then I need to try compiling the last code snapshot I have and see exactly where I left things at the end of September. Then, I will read through the modular code structure I have and see if there are any structural changes to make right off the bat, or if I should go straight to fixing bugs and adding or completing features.</p>
<p>Begone, distractions! I have work to do!</p>
<p>The post <a href="https://keyglove.net/2013/05/04/diving-back-in-and-google-glass-plans/">Diving Back In, and Google Glass Plans</a> appeared first on <a href="https://keyglove.net">Keyglove</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://keyglove.net/2013/05/04/diving-back-in-and-google-glass-plans/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1356</post-id>	</item>
		<item>
		<title>VIDEO: Prototype D Autodesk Inventor COM API Demo</title>
		<link>https://keyglove.net/2012/07/26/video-prototype-d-autodesk-inventor-com-api-demo/</link>
					<comments>https://keyglove.net/2012/07/26/video-prototype-d-autodesk-inventor-com-api-demo/#comments</comments>
		
		<dc:creator><![CDATA[Jeff Rowberg]]></dc:creator>
		<pubDate>Thu, 26 Jul 2012 17:33:58 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Hardware]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[3d]]></category>
		<category><![CDATA[autodesk]]></category>
		<category><![CDATA[demo]]></category>
		<category><![CDATA[inventor]]></category>
		<category><![CDATA[kit]]></category>
		<category><![CDATA[video]]></category>
		<guid isPermaLink="false">https://keyglove.net/?p=1286</guid>

					<description><![CDATA[<p>Keyglove #10 &#8211; Prototype D Autodesk Inventor COM API Demo from Jeff Rowberg on Vimeo. This video demonstrates Keyglove Prototype D and the Keyglove Kit v0.4 PCB (v0.5 still pending design completion) along with the alpha Keyglove Manager app integrated with Autodesk Inventor using the COM API</p>
<p>The post <a href="https://keyglove.net/2012/07/26/video-prototype-d-autodesk-inventor-com-api-demo/">VIDEO: Prototype D Autodesk Inventor COM API Demo</a> appeared first on <a href="https://keyglove.net">Keyglove</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><a href="http://vimeo.com/46414304">Keyglove #10 &#8211; Prototype D Autodesk Inventor COM API Demo</a> from <a href="http://vimeo.com/sectorfej">Jeff Rowberg</a> on <a href="http://vimeo.com">Vimeo</a>.</p>
<p>This video demonstrates Keyglove Prototype D and the Keyglove Kit v0.4 PCB (v0.5 still pending design completion) along with the alpha Keyglove Manager app integrated with Autodesk Inventor using the COM API for true 3D input. This is just a sample of the kind of thing that can be done with the Keyglove. And, honestly, this isn&#8217;t even a very good demo due to the early stage of development of the Manager app and the loose mounting of the older revision of the PCB on the glove.<br />
<span id="more-1286"></span></p>
<p>The sensor connections to the controller board have also been wired into per-finger female headers, which means it&#8217;s far easier to swap in a new controller board whenever I update the design. I don&#8217;t have to find each individual pin connection and put them in the right order; it&#8217;s all conveniently broken out on the PCB, and I can just plug in each header into the six main connectors (thumb, four fingers, and palm). Now I just need to get that new PCB version fabricated so I can mount the board on the glove more easily.</p>
<p>The post <a href="https://keyglove.net/2012/07/26/video-prototype-d-autodesk-inventor-com-api-demo/">VIDEO: Prototype D Autodesk Inventor COM API Demo</a> appeared first on <a href="https://keyglove.net">Keyglove</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://keyglove.net/2012/07/26/video-prototype-d-autodesk-inventor-com-api-demo/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1286</post-id>	</item>
	</channel>
</rss>
