<?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>White Rose Engineering</title>
	<atom:link href="http://lackawanna.hackhut.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://lackawanna.hackhut.com</link>
	<description>Just another HackHut site</description>
	<lastBuildDate>Fri, 01 Feb 2013 19:11:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.5</generator>
		<item>
		<title>Training your PID</title>
		<link>http://lackawanna.hackhut.com/2013/01/30/training-your-pid/</link>
		<comments>http://lackawanna.hackhut.com/2013/01/30/training-your-pid/#comments</comments>
		<pubDate>Wed, 30 Jan 2013 22:04:39 +0000</pubDate>
		<dc:creator>lackawanna</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://lackawanna.hackhut.com/?p=536</guid>
		<description><![CDATA[<p>Control theory must be on the short list for the most important subject that no one talks about.  Break open a hobbyist robotics book and you are lucky if control systems are even mentioned.  Control systems run our cars, fire our multi-million dollar missiles, and keep our buildings at the right temperature.  The phase locked loops (PLLs) .....<br /><br /><a href="http://lackawanna.hackhut.com/2013/01/30/training-your-pid/">Read the Rest</a>]]></description>
			<content:encoded><![CDATA[<p>Control theory must be on the short list for the most important subject that no one talks about.  Break open a hobbyist robotics book and you are lucky if control systems are even mentioned.  Control systems run our cars, fire our multi-million dollar missiles, and keep our buildings at the right temperature.  The phase locked loops (PLLs) that set the frequency for our modern radios, televisions, and cellphones, and which have replaced countless analog tuned circuits, are just another PID based control system.</p>
<p>The old analog control systems, as well, have been silently replaced by their digital implementations.  Witness the number of &#8220;computers&#8221; inside a car or a jet fighter built today.  Control systems are now seemly everywhere and live in places you least suspect.</p>
<p>As for why control systems are not talked about, the mathematics is just hard.  Although real world examples of second order systems are abundant, such as a swinging pendulum, it is the math behind the dynamic behavior of a control loop which is amazingly obtuse.</p>
<p>That said it is possible to design a PID control without touching the complex math.  For this note I implemented a temperature control system that maintained a constant temperature on a simple resistor.</p>
<p><a href="http://lackawanna.hackhut.com/files/2013/01/testset.png" rel="lightbox[536]"><img class="alignnone size-full wp-image-537" src="http://lackawanna.hackhut.com/files/2013/01/testset.png" alt="" width="640" height="626" /></a></p>
<p>As you know there are three gain constants, one for each term used in a full PID control implementation.  The three terms are the Proportional, the Integral, and the Derivative.</p>
<p>The PID algorithm itself is very small.  To save space on my ATtiny13 I used shift multiplication instead of regular multiplication.  If the particular gain value is set to negative the term is ignored.</p>
<pre>int8_t p_gain;
int8_t i_gain;
int8_t d_gain;

static int16_t i_state, d_state;

void reset_pid ()
{
  i_state = 0;
  d_state = 0;
}

int16_t update_pid (int16_t error)
{
  int16_t drive = 0;

  drive += (p_gain &lt; 0 ? 0 : error &lt;&lt; p_gain);             // P term
  drive += (i_gain &lt; 0 ? 0 : (error + i_state) &gt;&gt; i_gain); // I term
  drive += (d_gain &lt; 0 ? 0 : (error - d_state) &lt;&lt; d_gain); // D term

  i_state += error;  // update I state
  d_state = error;   // update D state
  return drive;
}</pre>
<p>So how does one find the correct PID gain constants?  What should the sampling frequency for the loop be?  And an issue I faced with my own implementation, how much current should be switched through the heating element, the resistor.  Using some mathematical method is an option.  There is also the open source simulator Scilab.  And there is always the option of tuning the control loop the old analog way with a signal generator and oscilloscope.</p>
<p>There is another option though.  A great benefit from implementing a PID controller in software is that its state can be logged out, say, to a host computer through a serial port. In additional a step function can be simulated in software without ever having to use a signal generator.  A step function lets one see the loop&#8217;s dynamic behavior.  This is accomplished by changing the PID control&#8217;s set point, or target value, to another value a good distance away.  The article &#8220;PID Without a PhD&#8221; by Tim Wescott describes this particular method.</p>
<p>Below is my code for simulating a step function and then logging the sensor input temperature read by the PID algorithm.  The three gain constants are set beforehand.  The &#8220;ready&#8221; variable is set every quarter of a second by an interrupt handler.</p>
<pre>reset_pid();                          // clear the PID algorithm's state

for (ready=0, n=0; n&lt;300; n++) {      // do 300 iterations
  while (!ready) ; ready = 0;         // wait until time for a new sample

  temp = read_adc();                  // read the input temperature
  if (n == 0) target = temp + step;   // suddenly increase the set point
  drive = update_pid(target - temp);  // pass the error to the PID
  set_pwm(drive);                     // limit and set the PWM 

  put_char(',');                      // log the temperature
  put_hex(temp);                      // to the serial port
}

put_char('\n');</pre>
<p>Initially I only switched 60mA through a 1/4W 100ohm resistor, or about 360mW. This was not enough to raise the temperature by more than 4 degrees Celsius making it hard to ring the loop.  (Apparently a 1/4W resistor has a thermal resistance of about 12C/W.)  I decreased the resistor to 47ohms which increased the switched current to 125mA.  I was then able to raise its temperature by at most 10 degrees Celsius.  Now using a 5.4 degree Celsius step function, corresponding to an increase in value of 50 from the ADC, any ringing nicely stands out.</p>
<p>The IRF510 switching transistor fully turned itself on with a Rds of less than 1ohm with only a gate voltage of 5V.  This is  contrary to lore that such a low gate voltage will not work.  The drain was at 6V when off.  The switching caused a good amount of noise so a .1uF capacitor across the temperature sensor was needed otherwise the sensor was unusable.</p>
<p>Figure 1 shows the behavior of only the proportional term whose gain was varied from 1 to 7.  Ringing is clearly evident with the higher gains.</p>
<p><a href="http://lackawanna.hackhut.com/files/2013/01/figure1.png" rel="lightbox[536]"><img class="alignnone size-full wp-image-541" src="http://lackawanna.hackhut.com/files/2013/01/figure1.png" alt="" width="566" height="464" /></a></p>
<p>Figure 2 shows the behavior of only the integral term for various gain terms. The windup and winddown with the higher gains can be seen.  Please note that shift division is used to calculate the I term.</p>
<p><a href="http://lackawanna.hackhut.com/files/2013/01/figure2.png" rel="lightbox[536]"><img class="alignnone size-full wp-image-542" src="http://lackawanna.hackhut.com/files/2013/01/figure2.png" alt="" width="566" height="464" /></a></p>
<p>You might have noticed in figure 1 that the target value of 50 was never reached.  This is where the I term comes in.  The I term learns from the past. While the P term is concerned with the error in the present, the I term remembers the past to inform its current value.  The article &#8220;PID Control without Math&#8221; by Robert Lacoste explains why this is important.</p>
<p>So if you think your PID is broken because it is not resting on the right value, as I did, it is not.  The &#8220;loss&#8221; within the control system must be compensated by the I term as explained by Lacoste.  Figure 3 shows the result when the P and I term are combined.  The target value of 50 can now be reached.</p>
<p><a href="http://lackawanna.hackhut.com/files/2013/01/figure3.png" rel="lightbox[536]"><img class="alignnone size-full wp-image-543" src="http://lackawanna.hackhut.com/files/2013/01/figure3.png" alt="" width="566" height="464" /></a></p>
<p>While the I term looks back, the D terms looks to the future.  The D term senses the speed of the error and uses that to gauge how much drive to apply. Like riding a bike, it is better to coast to a stop than to slam the brakes. The D term as a result will dampen the response of the loop.  I was not able to get any meaningful data from runs using the D term alone.  Wescott says as much.  He recommends setting the gain for the P term to the lowest possible value. This was done for figure 4.  The runs have been visually staggered so the effect of the D term can be seen better.</p>
<p><a href="http://lackawanna.hackhut.com/files/2013/01/figure4.png" rel="lightbox[536]"><img class="alignnone size-full wp-image-544" src="http://lackawanna.hackhut.com/files/2013/01/figure4.png" alt="" width="566" height="464" /></a></p>
<p>From all these figures I picked the putative best gain constants, P=2, I=5, and D=5.  But to sure, I put together a final training round with 27 contenders.  The staggered results are given in figure 5.  From this the optimal PID gain constants appear to be now, P=1, I=5, and D=4.  This is quite a bit different from my first choice.  Nevertheless this is still not the best.  See later in the note.</p>
<p><a href="http://lackawanna.hackhut.com/files/2013/01/figure5.png" rel="lightbox[536]"><img class="alignnone size-full wp-image-548" src="http://lackawanna.hackhut.com/files/2013/01/figure5.png" alt="" width="566" height="687" /></a></p>
<p>With respect to the sampling rate, I found that a 1 second sampling rate for my heater was too long.  Any control loop will of course exhibit some delay and that delay probably needs to be observable by the PID control.  At least this was my conclusion.  A quarter second sampling rate allows for this.  The initial delay before the temperature starts rising at the beginning of the step function can be easily seen at this sampling rate.  A faster rate was not tested however because my software UART could not handle the speed.</p>
<p>The rule of thumb according to Wescott is that the sample time should be 1/10th to 1/100th of the settling time.  The settling time is the time it takes for the system (the transient response) to move to and remain within a certain percentage (say 10%) of a steady state value.</p>
<p>If the sampling rate, coupled with the thermal mass of the heating element, is functionally equivalent to the role the loop filter plays in a PLL then it will be the prime factor in the transient response of the PID control.  (I think that sounds right especially since F=ma as we remember.)  The transient response determines the settling time, the dampening ratio, the overshoot amount, the damped natural frequency, and the loop&#8217;s bandwidth.</p>
<p>With the second optimal solution above I found its settling time to be around 110 seconds or 440 times the sampling time.  So maybe it is not so optimal. Trying again from figure 5 and using the gain constants, P=3, I=5, and D=4, the settling time came out to be 21 seconds or 84 times the sampling time.  These are the gain constants I will use for my PID controller.  See figure 6.<br />
<a href="http://lackawanna.hackhut.com/files/2013/01/figure6.png" rel="lightbox[536]"><img class="alignnone size-full wp-image-550" src="http://lackawanna.hackhut.com/files/2013/01/figure6.png" alt="" width="566" height="464" /></a><br />
Going out on a mathematical limb and looking at figure 1, the damped natural frequency from the P=3 and P=4 runs is about 1/(128 samples) or 1/(32 seconds).  This is calculated from the ringing on these runs.  The equation for the damped natural frequency is the undamped natural frequency (that is the bandwidth of the control loop) times the square root of (1 &#8211; the damping factor squared).  Now estimating that the damping factor for my PID controller is around 0.8, my loop&#8217;s bandwidth can be calculated to be 0.05 Hz or 1/(20 seconds). My sampling rate is safely 80 times faster than this.</p>
<p>By the way, this leads me into another way to find the loop&#8217;s bandwidth. Since the damped natural frequency and undamped natural frequency approach each other as damping decreases, drive the loop into ringing with high gain and then use that ringing frequency as the bandwidth.</p>
<p>To sum up, training is key.  So put your PID controller through its paces and I will meet you at the track.</p>

<div class="hadsubmit">
<a href="mailto:tips@hackaday.com?subject=Training%20your%20PID&amp;body=I found an interesting project you may like. Here is the link: http%3A%2F%2Flackawanna.hackhut.com%2F2013%2F01%2F30%2Ftraining-your-pid%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/HaD-submit/had.png" title="Sumbit this to HackaDay" />
</a>
<a href="mailto:tips@hacknmod.com?subject=Training%20your%20PID&amp;body=I found an interesting project you may like. Here is the link: http%3A%2F%2Flackawanna.hackhut.com%2F2013%2F01%2F30%2Ftraining-your-pid%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/HaD-submit/hacknmod.png" title="Sumbit this to HacknMod" />
</a>
<a href="mailto:tips@lifehacker.com?subject=Training%20your%20PID&amp;body=I found an interesting project you may like. Here is the link: http%3A%2F%2Flackawanna.hackhut.com%2F2013%2F01%2F30%2Ftraining-your-pid%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/HaD-submit/lifehacker.png" title="Sumbit this to LifeHacker" />
</a>
</div>

<div class="jwsharethis">
<br />
<a href="mailto:?subject=Training%20your%20PID&amp;body=http%3A%2F%2Flackawanna.hackhut.com%2F2013%2F01%2F30%2Ftraining-your-pid%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/email.png" title="Share this page via Email" />
</a>
<a target="_blank" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Flackawanna.hackhut.com%2F2013%2F01%2F30%2Ftraining-your-pid%2F&amp;title=Training+your+PID">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/su.png" title="Share this page via Stumble Upon" />
</a>
<a target="_blank" href="http://digg.com/submit?url=http%3A%2F%2Flackawanna.hackhut.com%2F2013%2F01%2F30%2Ftraining-your-pid%2F&amp;title=Training+your+PID">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/digg.png" title="Share this page via Digg this" />
</a>
<a target="_blank" href="http://www.reddit.com/submit?url=http%3A%2F%2Flackawanna.hackhut.com%2F2013%2F01%2F30%2Ftraining-your-pid%2F&amp;title=Training+your+PID">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/reddit.png" title="Share this page via Reddit" />
</a>
<a target="_blank" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Flackawanna.hackhut.com%2F2013%2F01%2F30%2Ftraining-your-pid%2F&amp;t=Training+your+PID">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/fb.png" title="Share this page via Facebook" />
</a>
<a target="_blank" href="http://twitter.com/intent/tweet?text=I+like+http%3A%2F%2Flackawanna.hackhut.com%2F2013%2F01%2F30%2Ftraining-your-pid%2F&amp;title=Training+your+PID">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/twitter.png" title="Share this page via Twitter" />
</a>
</div>
]]></content:encoded>
			<wfw:commentRss>http://lackawanna.hackhut.com/2013/01/30/training-your-pid/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DTR-less Reset Circuitry for the AVR</title>
		<link>http://lackawanna.hackhut.com/2012/05/15/dtr-less-reset-circuitry-for-the-avr/</link>
		<comments>http://lackawanna.hackhut.com/2012/05/15/dtr-less-reset-circuitry-for-the-avr/#comments</comments>
		<pubDate>Tue, 15 May 2012 05:19:12 +0000</pubDate>
		<dc:creator>lackawanna</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://lackawanna.hackhut.com/?p=504</guid>
		<description><![CDATA[<p></p>
<p>The USART-based bootloader is probably the most popular way of burning code to the AVR.  The Arduino, for one, uses this method.  </p>
<p>For example say you were using a FTDI cable to talk to your Arduino.  First the USB connector end of the cable would go into your host computer.  The other end of the cable .....<br /><br /><a href="http://lackawanna.hackhut.com/2012/05/15/dtr-less-reset-circuitry-for-the-avr/">Read the Rest</a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://lackawanna.hackhut.com/files/2012/05/modembreakcircuit.png" rel="lightbox[504]"><img src="http://lackawanna.hackhut.com/files/2012/05/modembreakcircuit.png" alt="" width="501" height="357" class="alignnone size-full wp-image-505" /></a></p>
<p>The USART-based bootloader is probably the most popular way of burning code to the AVR.  The Arduino, for one, uses this method.  </p>
<p>For example say you were using a FTDI cable to talk to your Arduino.  First the USB connector end of the cable would go into your host computer.  The other end of the cable would then be plugged into the appropriate header of the Arduino.  The RXD line from the FTDI cable now connects to the AVR&#8217;s TXD pin.  The TXD line connects to the AVR&#8217;s RXD pin.  In this way, the software serial interface on the host computer is converted down to its wire line equivalent for communicating with the bootloader on the AVR.  Even the USB versions of the Arduino burn code effectively the same way &#8211; that is they still use a USART-based bootloader.  </p>
<p>But how do you reset the AVR so you can drop it into the bootloader and burn your code?  One way is to use a third wire from the serial port, namely the DTR signal wire, to do it.  The Arduino places a capacitor between the DTR signal and the AVR&#8217;s reset pin and its pull-up resistor.  When the DTR line is toggled a pulse is generated causing the pin to go low and the AVR to be reset.  Your own personal AVR circuits can be designed to use this method as well, using a pull-up resistor and capacitor.</p>
<p>However, this requires three wires, not including ground, as well as code on the host computer to toggle the DTR signal.</p>
<p>Instead of using three wires, the circuitry illustrated above uses only two: the TXD and RXD wires.   With this circuit the AVR is reset whenever a modem break is sent over the host&#8217;s TXD line.   The RST line goes directly from the 556 to the RESET pin of the AVR with no pull-up or capacitor in between.  </p>
<p>When prototyping saving one wire might not be worth it, but if your microcontrollers were to be remotely controlled or placed a good distance away from each other saving a wire might come in handy.  In addition your development board no longer needs either the pull-up resistor or the capacitor.</p>
<p>Here is a command sequence that you can use to reset and burn the AVR with this reset method.  Note, the ~# escape sequence sends a modem break over the serial port.</p>
<p>$ echo &#8216;~#~.&#8217; | cu -l /dev/ttyUSB0 -s 9600<br />
$ avrdude -c avrisp -b 9600 -P /dev/ttyUSB0 -p m328p [hexfile]</p>
<p>Unfortunately the &#8216;cu&#8217; command is slow to return the command line, so the alternate technique below is recommended.</p>
<p>$ echo &#8216;~#~!avrdude -c avrisp -b 9600 -P /dev/ttyUSB0 -p m328p [hexfile]&#8216; | cu -l /dev/ttyUSB0 -s 9600</p>
<p>Have fun!</p>

<div class="hadsubmit">
<a href="mailto:tips@hackaday.com?subject=DTR-less%20Reset%20Circuitry%20for%20the%20AVR&amp;body=I found an interesting project you may like. Here is the link: http%3A%2F%2Flackawanna.hackhut.com%2F2012%2F05%2F15%2Fdtr-less-reset-circuitry-for-the-avr%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/HaD-submit/had.png" title="Sumbit this to HackaDay" />
</a>
<a href="mailto:tips@hacknmod.com?subject=DTR-less%20Reset%20Circuitry%20for%20the%20AVR&amp;body=I found an interesting project you may like. Here is the link: http%3A%2F%2Flackawanna.hackhut.com%2F2012%2F05%2F15%2Fdtr-less-reset-circuitry-for-the-avr%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/HaD-submit/hacknmod.png" title="Sumbit this to HacknMod" />
</a>
<a href="mailto:tips@lifehacker.com?subject=DTR-less%20Reset%20Circuitry%20for%20the%20AVR&amp;body=I found an interesting project you may like. Here is the link: http%3A%2F%2Flackawanna.hackhut.com%2F2012%2F05%2F15%2Fdtr-less-reset-circuitry-for-the-avr%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/HaD-submit/lifehacker.png" title="Sumbit this to LifeHacker" />
</a>
</div>

<div class="jwsharethis">
<br />
<a href="mailto:?subject=DTR-less%20Reset%20Circuitry%20for%20the%20AVR&amp;body=http%3A%2F%2Flackawanna.hackhut.com%2F2012%2F05%2F15%2Fdtr-less-reset-circuitry-for-the-avr%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/email.png" title="Share this page via Email" />
</a>
<a target="_blank" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Flackawanna.hackhut.com%2F2012%2F05%2F15%2Fdtr-less-reset-circuitry-for-the-avr%2F&amp;title=DTR-less+Reset+Circuitry+for+the+AVR">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/su.png" title="Share this page via Stumble Upon" />
</a>
<a target="_blank" href="http://digg.com/submit?url=http%3A%2F%2Flackawanna.hackhut.com%2F2012%2F05%2F15%2Fdtr-less-reset-circuitry-for-the-avr%2F&amp;title=DTR-less+Reset+Circuitry+for+the+AVR">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/digg.png" title="Share this page via Digg this" />
</a>
<a target="_blank" href="http://www.reddit.com/submit?url=http%3A%2F%2Flackawanna.hackhut.com%2F2012%2F05%2F15%2Fdtr-less-reset-circuitry-for-the-avr%2F&amp;title=DTR-less+Reset+Circuitry+for+the+AVR">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/reddit.png" title="Share this page via Reddit" />
</a>
<a target="_blank" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Flackawanna.hackhut.com%2F2012%2F05%2F15%2Fdtr-less-reset-circuitry-for-the-avr%2F&amp;t=DTR-less+Reset+Circuitry+for+the+AVR">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/fb.png" title="Share this page via Facebook" />
</a>
<a target="_blank" href="http://twitter.com/intent/tweet?text=I+like+http%3A%2F%2Flackawanna.hackhut.com%2F2012%2F05%2F15%2Fdtr-less-reset-circuitry-for-the-avr%2F&amp;title=DTR-less+Reset+Circuitry+for+the+AVR">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/twitter.png" title="Share this page via Twitter" />
</a>
</div>
]]></content:encoded>
			<wfw:commentRss>http://lackawanna.hackhut.com/2012/05/15/dtr-less-reset-circuitry-for-the-avr/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Easy I2C: Pull-ups optional</title>
		<link>http://lackawanna.hackhut.com/2011/10/10/easy-i2c/</link>
		<comments>http://lackawanna.hackhut.com/2011/10/10/easy-i2c/#comments</comments>
		<pubDate>Mon, 10 Oct 2011 22:54:32 +0000</pubDate>
		<dc:creator>lackawanna</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://lackawanna.hackhut.com/?p=375</guid>
		<description><![CDATA[<p></p>
<p>The I2C interface is relatively uncomplicated to write for on the AVR, not withstanding all the details of the protocol and all the messages generated by the AVR hardware.  The more advanced AVR microcontrollers, support the I2C two wire interface &#8211; three wires if counting ground.  It is not called I2C in the Atmel documentation however.  Instead .....<br /><br /><a href="http://lackawanna.hackhut.com/2011/10/10/easy-i2c/">Read the Rest</a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://lackawanna.hackhut.com/files/2011/10/i2c.png" rel="lightbox[375]"><img src="http://lackawanna.hackhut.com/files/2011/10/i2c.png" alt="" width="505" height="400" class="alignnone size-full wp-image-502" /></a></p>
<p>The I2C interface is relatively uncomplicated to write for on the AVR, not withstanding all the details of the protocol and all the messages generated by the AVR hardware.  The more advanced AVR microcontrollers, support the I2C two wire interface &#8211; three wires if counting ground.  It is not called I2C in the Atmel documentation however.  Instead it is called the 2-wire Serial Interface (TWI). </p>
<p>So let&#8217;s begin.  First, the TWI interface needs to be initialized.  The TWI bit rate register (TWBR) and the TWI prescaler bits set the frequency of the bus.  The standard I2C bus runs at a frequency of 100 kHz.  I used a lower rate of 10 kHz to provide for a less critical design.</p>
<pre>
#define TWI_PRE     1       // my TWI prescaler value
#define TWI_FREQ    10000   // my TWI bit rate

TWBR = (F_CPU / TWI_FREQ - 16) / TWI_PRE / 2;  // set bit rate
TWSR = (0&lt;&lt;TWPS0);          // use a prescaler of one
</pre>
<p>Since the I2C bus can operate at relatively high speeds, the two bus lines need pull-up resistors that are external.  The internal pull-ups of AVR MCUs with their large resistances, as high as 50 kohms according to the documentation, would degrade the bandwidth of the bus.  Nevertheless I still choose to use internal pull-ups, but I did it at a cost of using a slower bus.  So the next step is to enable the internal pull-ups on the TWI clock (SCL) and data (SDA) pins.</p>
<pre>
#define SCL_PORT    PORTC   // pin assignments specific to the ATmega328p
#define SCL_BIT     PC5
#define SDA_PORT    PORTC
#define SDA_BIT     PC4

SCL_PORT |= _BV(SCL_BIT);   // enable pull up on TWI clock line
SDA_PORT |= _BV(SDA_BIT);   // enable pull up on TWI data line
</pre>
<p>If external pull-ups are used, Myke Predko recommends 1 kohm resistors for 400 kHz buses and 10 kohm resistors for 100 kHz buses.   Both TWI pins, SDA and SCL, operate using an open-drain design.  So, while the fall time of the signal is determined by the output impedance of the driver and the load capacitance of the bus, the rise time is determined by the resistance of the pull-up and the load capacitance.  The rise time of a TWI signal can therefore be calculated using the formula tr = 2.197 * R * C.  According to one source a rise time of 1/2 to 1/3 of a bit-time is adequate.</p>
<p>To initiate a TWI transmission, a TWI operation must be enabled (TWEN) and the TWI interrupt flag (TWINT) must be cleared.  This is done by setting the TWEN and TWINT bits in the TWI control register (TWCR).  This clearing of the TWI interrupt flag immediately starts a TWI transmission.  For certain TWI transmissions another bit has to be set.  For example, to send a START or STOP condition the TWSTA or TWSTO bit must be set in addition.</p>
<p>Once a TWI transmission is started, you need to wait for it to complete.  This can be done by polling the control register until the TWINT bit is set.  The status of the TWI transmission can then be checked by reading the TWI status register (TWSR).  For example, the routine twi_poll() below starts a transmission and then waits for the transmission to complete.</p>
<pre>
uint8_t twi_poll (uint8_t u)
{
  TWCR = u | _BV(TWINT) | _BV(TWEN);  // initiate a TWI transmission
  if (u == _BV(TWSTO)) return 0;      // don't poll if the STOP condition was sent
  while (!(TWCR &amp; _BV(TWINT))) ;      // wait for the interrupt flag to be set
  return (TWSR &amp; 0xf8);               // return the status code
}
</pre>
<p>The best analogy I can come up with to explain how to communicate with I2C perpherals is that you talk to them using packets.  There is a write packet and a read packet.  To perform a write transaction you send one write packet.  To perform a read transaction, you use two packets, one to write the command and the other to read the results.</p>
<p>The beginning of a packet is indicated by the START condition, or if you are in the middle of a transaction the RESTART condition.  The end of a packet is indicated by the STOP condition, or if you are again in the middle of a transaction the RESTART condition.  The STOP condition is important not only because it ends the transaction but also because it forces the TWI hardware to release the bus lines.</p>
<p>To begin a transaction, the START condition is first sent.  This is performed by setting the TWSTA bit in the TWI control register (TWCR).</p>
<pre>
u = twi_poll(_BV(TWSTA));
if (u != TW_START &amp;&amp; u != TW_REP_START) return 0;
</pre>
<p>Next the 7-bit slave address of the peripheral and another bit, the read/write 8-th bit, are loaded into the TWI data register.  The resulting 8-bit value is sent over the bus when the next TWI transmission is initiated.  When the addressed device receives this value, or any data byte, the device will ACK its reception by pulling the data bus low in the 9-th bit position.  If there is no acknowledgement, the code below releases the bus by jumping to code that sends a STOP condition and then errors out.  To begin writing bytes to the device first send the following:</p>
<pre>
TWDR = slave_address | TW_WRITE;
if (twi_poll(0) != TW_MT_SLA_ACK) goto release;
</pre>
<p>While there are a lot of other status codes to handle and the documentation gives a rather complex diagram of when and where they are generated, there is a definite sequence to it all, so if anything is not in the right order it usually means the transaction failed making it relatively straightforward to handle errors.</p>
<p>To write a byte over the TWI interface use:</p>
<pre>
TWDR = byte;
if (twi_poll(0) != TW_MT_DATA_ACK) goto release;
</pre>
<p>To change the direction of the transaction and start reading bytes now instead of writing them, the RESTART condition must be sent as well as the slave address of the device with the read/write bit set to read.</p>
<pre>
if (twi_poll(_BV(TWSTA)) != TW_REP_START) goto release;  // send RESTART
TWDR = slave_address | TW_READ;  // send SLA+R
if (twi_poll(0) != TW_MR_SLA_ACK) goto release;
</pre>
<p>To read a byte, now that the direction of the bus has changed, use:</p>
<pre>
if (twi_poll(_BV(TWEA)) != TW_MR_DATA_ACK) goto release;
byte = TWDR;
</pre>
<p>The TWEA bit tells the TWI interface on the AVR to acknowledge reception of the read byte by sending a ACK as the 9-th bit.  If, however, this is the last byte to be read, the TWI must respond by sending a NACK instead to say it is finished reading.  This is done by not setting the TWEA bit.  In this case to read a byte use:</p>
<pre>
if (twi_poll(0) != TW_MR_DATA_NACK) goto release;
byte = TWDR;
</pre>
<p>Lastly when the transaction is finished the STOP condition is sent releasing the bus.  This is performed by setting the TWSTO bit.</p>
<pre>
twi_poll(_BV(TWSTO));
</pre>
<p>As an example, to change the frequency of the signal generated by the Silicon Labs DS1077 chip, I use the following code where &#8220;m&#8221; is the prescaler value and &#8220;n&#8221; is the divider value of the signal frequency to generate.</p>
<pre>
#include &lt;compat/twi.h&gt;

uint8_t twi_poll (uint8_t u)
{
  TWCR = u | _BV(TWINT) | _BV(TWEN);  // initiate a TWI transmission
  if (u == _BV(TWSTO)) return 0;      // don't poll if the STOP condition was sent
  while (!(TWCR &amp; _BV(TWINT))) ;      // wait for the interrupt flag to be set
  return (TWSR &amp; 0xf8);               // return the status code
}

uint8_t twi_send16 (uint8_t sla, uint8_t cmd, uint8_t msb, uint8_t lsb)
{
  uint8_t u, status = 0;
  u = twi_poll(_BV(TWSTA));                    // send START
  if (u != TW_START &amp;&amp; u != TW_REP_START) return 0;
  TWDR = sla | TW_WRITE;                       // send SLA+W
  if (twi_poll(0) != TW_MT_SLA_ACK) goto release;
  TWDR = cmd;                                  // send command
  if (twi_poll(0) != TW_MT_DATA_ACK) goto release;
  TWDR = msb;                                  // send msb
  if (twi_poll(0) != TW_MT_DATA_ACK) goto release;
  TWDR = lsb;                                  // send lsb
  if (twi_poll(0) != TW_MT_DATA_ACK) goto release;
  status = 1;                                  // success
 release:
  twi_poll(_BV(TWSTO));                        // send STOP
  return status;
}

uint8_t twi_receive16  (uint8_t sla, uint8_t cmd, uint8_t *msb, uint8_t *lsb)
{
  uint8_t u, status = 0;
  u = twi_poll(_BV(TWSTA));                    // send START
  if (u != TW_START &amp;&amp; u != TW_REP_START) return 0;
  TWDR = sla | TW_WRITE;                       // send SLA+W
  if (twi_poll(0) != TW_MT_SLA_ACK) goto release;
  TWDR = cmd;                                  // send command
  if (twi_poll(0) != TW_MT_DATA_ACK) goto release;
  if (twi_poll(_BV(TWSTA)) != TW_REP_START) goto release; // send RESTART
  TWDR = sla | TW_READ;                        // send SLA+R
  if (twi_poll(0) != TW_MR_SLA_ACK) goto release;
  if (twi_poll(_BV(TWEA)) != TW_MR_DATA_ACK) goto release;
  *msb = TWDR;                                 // read msb
  if (twi_poll(0) != TW_MR_DATA_NACK) goto release;
  *lsb = TWDR;                                 // read lsb
  status = 1;                                  // success
 release:
  twi_poll(_BV(TWSTO));                        // send STOP
  return status;
}

...

#define DS1077_SLA  0xb0
#define DS1077_MUX  0x02
#define DS1077_DIV  0x01

if (!twi_send16(DS1077_SLA, DS1077_MUX, m&gt;&gt;1, m&lt;&lt;7)) return;
if (!twi_send16(DS1077_SLA, DS1077_DIV, n&gt;&gt;2, n&lt;&lt;6)) return; 
</pre>

<div class="hadsubmit">
<a href="mailto:tips@hackaday.com?subject=Easy%20I2C%3A%20Pull-ups%20optional&amp;body=I found an interesting project you may like. Here is the link: http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F10%2Feasy-i2c%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/HaD-submit/had.png" title="Sumbit this to HackaDay" />
</a>
<a href="mailto:tips@hacknmod.com?subject=Easy%20I2C%3A%20Pull-ups%20optional&amp;body=I found an interesting project you may like. Here is the link: http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F10%2Feasy-i2c%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/HaD-submit/hacknmod.png" title="Sumbit this to HacknMod" />
</a>
<a href="mailto:tips@lifehacker.com?subject=Easy%20I2C%3A%20Pull-ups%20optional&amp;body=I found an interesting project you may like. Here is the link: http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F10%2Feasy-i2c%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/HaD-submit/lifehacker.png" title="Sumbit this to LifeHacker" />
</a>
</div>

<div class="jwsharethis">
<br />
<a href="mailto:?subject=Easy%20I2C%3A%20Pull-ups%20optional&amp;body=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F10%2Feasy-i2c%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/email.png" title="Share this page via Email" />
</a>
<a target="_blank" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F10%2Feasy-i2c%2F&amp;title=Easy+I2C%3A+Pull-ups+optional">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/su.png" title="Share this page via Stumble Upon" />
</a>
<a target="_blank" href="http://digg.com/submit?url=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F10%2Feasy-i2c%2F&amp;title=Easy+I2C%3A+Pull-ups+optional">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/digg.png" title="Share this page via Digg this" />
</a>
<a target="_blank" href="http://www.reddit.com/submit?url=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F10%2Feasy-i2c%2F&amp;title=Easy+I2C%3A+Pull-ups+optional">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/reddit.png" title="Share this page via Reddit" />
</a>
<a target="_blank" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F10%2Feasy-i2c%2F&amp;t=Easy+I2C%3A+Pull-ups+optional">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/fb.png" title="Share this page via Facebook" />
</a>
<a target="_blank" href="http://twitter.com/intent/tweet?text=I+like+http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F10%2Feasy-i2c%2F&amp;title=Easy+I2C%3A+Pull-ups+optional">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/twitter.png" title="Share this page via Twitter" />
</a>
</div>
]]></content:encoded>
			<wfw:commentRss>http://lackawanna.hackhut.com/2011/10/10/easy-i2c/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Using V-USB and the HID Class (Part III of III)</title>
		<link>http://lackawanna.hackhut.com/2011/10/06/using-v-usb-and-the-hid-class-part-iiiiii/</link>
		<comments>http://lackawanna.hackhut.com/2011/10/06/using-v-usb-and-the-hid-class-part-iiiiii/#comments</comments>
		<pubDate>Thu, 06 Oct 2011 14:49:59 +0000</pubDate>
		<dc:creator>lackawanna</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://lackawanna.hackhut.com/?p=324</guid>
		<description><![CDATA[ Example Three
<p>Create a new example directory and set it up as before in example one.  Next edit usbconfig.h and change the values to the following.</p>

Set USB_CFG_HAVE_INTRIN_ENDPOINT to 1,
 set USB_CFG_DEVICE_CLASS to 0,
 set USB_CFG_INTERFACE_CLASS to 3,
 set USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH to 34, and
 set USB_CFG_IMPLEMENT_FN_WRITE to 1.

<p>The source code for example three is given in the download.</p>
<p>The report descriptor now .....<br /><br /><a href="http://lackawanna.hackhut.com/2011/10/06/using-v-usb-and-the-hid-class-part-iiiiii/">Read the Rest</a>]]></description>
			<content:encoded><![CDATA[<ol><strong> Example Three</strong></ol>
<p>Create a new example directory and set it up as before in example one.  Next edit usbconfig.h and change the values to the following.</p>
<ul>
<li>Set USB_CFG_HAVE_INTRIN_ENDPOINT to 1,</li>
<li> set USB_CFG_DEVICE_CLASS to 0,</li>
<li> set USB_CFG_INTERFACE_CLASS to 3,</li>
<li> set USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH to 34, and</li>
<li> set USB_CFG_IMPLEMENT_FN_WRITE to 1.</li>
</ul>
<p>The source code for example three is given in the download.</p>
<p>The report descriptor now includes an output report as well as an input report.  Lastly, compile and burn the firmware as done with the two previous examples.  The firmware creates a loop back like HID device.  The download also contains a simple host application, simple.c, to read and write this device.</p>
<p>As this host application is running, the debug output from the firmware should resemble the following figure below.</p>
<p><a href="http://lackawanna.hackhut.com/files/2011/10/example3.png" rel="lightbox[324]"><img src="http://lackawanna.hackhut.com/files/2011/10/example3.png" alt="" width="465" height="153" class="alignnone size-full wp-image-338" /></a></p>
<p>A word of caution, the first byte of the write buffer for the write() command in the host application is the output report&#8217;s “Report ID”.  A report descriptor provides for different types and sizes of reports through the use of a byte sized Report ID field.  This byte is sent as the first byte of a report.  If the first byte is zero, however, the write command does not send the first byte, instead the byte is skipped and only the remaining data in the buffer is transfered to the device.</p>
<ol><strong> Control Transfers</strong></ol>
<p>No more than 90% of any frame can be allocated for interrupt transfers.  Any time remaining is allocated to control transfers and after that bulk transfers.  See the figure below for an illustration on how control transfers work.</p>
<p><a href="http://lackawanna.hackhut.com/files/2011/10/control.png" rel="lightbox[324]"><img src="http://lackawanna.hackhut.com/files/2011/10/control.png" alt="" width="320" height="234" class="alignnone size-full wp-image-339" /></a></p>
<p>Since control transfers are not limited by a service interval or a data limit, their maximum data rate can be substantially more than an interrupt transfer.  Bulk transfers are even faster because they lack the overhead associated with control transfers.  Low-speed devices, however, are not allowed to use bulk transfers, nor does HID support them.  We can use a low level library, such as libusb, to get around this restriction though.</p>
<p>My experiments reveal that an 8 byte control transfer has a maximum data rate of around 14,000 bytes per second.  The rate doubles to 28,000 bytes per second for a 64 byte control transfer.  The upper limit appears to be around 32,000 bytes per second.</p>
<ol><strong> Handling OUT Transactions</strong></ol>
<p>The figure below illustrates the two ways V-USB handles OUT transactions.  One way is for control transfers and it involves writing a usbFunctionWrite() routine.  The other is for interrupt and bulk transfers and it involves writing a usbFunctionWriteOut() routine.</p>
<p>The usbFunctionWrite() routine is called by V-USB for any data phase OUT transactions addressed to control endpoint zero.  The routine should return a one when the data phase is complete.  Otherwise it should return a zero.  Returning a one causes a ZLP to be queued for the upcoming status phase of the control transfer.  However if a one is returned more than once during the same data phase the control transfer can fail.  This is because doing so might toggle the packet ID for the upcoming status phase to DATA1 which is invalid.</p>
<p><a href="http://lackawanna.hackhut.com/files/2011/10/out.png" rel="lightbox[324]"><img src="http://lackawanna.hackhut.com/files/2011/10/out.png" alt="" width="720" height="220" class="alignnone size-full wp-image-346" /></a></p>
<p>The usbFunctionWriteOut() routine on the other hand does not need to return anything.  V-USB simply relays the data from any OUT transaction not directed to control endpoint zero to this routine.  The endpoint number can be found in the variable, usbRxToken.</p>
<ol><strong> Interrupt OUT Endpoints</strong></ol>
<p>A HID interface can support interrupt transfers for output reports.  Since control transfers have some overhead, interrupt transfers are preferred for streaming data.  Plus by using both an interrupt IN endpoint and an interrupt OUT endpoint their two data rates can be equalized for better balance.  Without an interrupt OUT endpoint the host must rely on the SET_REPORT request to transfer data.  Unfortunately V-USB has no option for adding to the interface descriptor the endpoint descriptor required to tell the host about the interrupt OUT endpoint.</p>
<p>To get around this I have included a patch for it in order to make the next and last example clearer.  The patch, usbdrv.patch, is located in the download package.</p>
<ol><strong>Example Four</strong></ol>
<p>	Create a new example directory and set it up as we have done before.  But before copying and editing usbconfig.h, we must first patch the usbdrv directory.  Run “patch -p0 &lt; usbdrv.patch” in our directory to patch it.   The new patched version of usbconfig-prototype.h in usbdrv is then copied over as usbconfig.h. </p>
<p>	Edit this usbconfig.h after the preliminaries have been done  and change the values to the following. The source code for example four is again in the download.</p>
<ul>
<li>Set USB_CFG_HAVE_INTRIN_ENDPOINT to 1,
<li>set USB_CFG_DEVICE_CLASS to 0, 
<li>set USB_CFG_INTERFACE_CLASS to 3, 
<li>set USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH to 34, 
<li>set USB_CFG_IMPLEMENT_FN_WRITEOUT to 1, and 
<li>set USB_CFG_HAVE_INTROUT_ENDPOINT to 1. 
</ul>
<p>Using the simple host application from the last example, the debug output should resemble the following figure below.  </p>
<p><a href="http://lackawanna.hackhut.com/files/2011/10/example4.png" rel="lightbox[324]"><img src="http://lackawanna.hackhut.com/files/2011/10/example4.png" alt="" width="477" height="258" class="alignnone size-full wp-image-340" /></a></p>
<ol><strong>Conclusion</strong></ol>
<p>Bit-banging data communication interfaces might not be considered optimal especially an interface like USB running at 1.5Mhz.  However it was not until recently that on-chip USARTs became both ubiquitous and inexpensive on MCUs. Before then experimenters had to rely on software based solutions to fill the gap.  It is a mark of versatility and resourcefulness that led experimenters to take on the challenge, making do with what was available to accomplish their design.</p>
<p>It probably will not be very long before USB interfaces make it onto the chips that hobbyists hold dear like the ATmega328p.  At the moment innovative support chips such as the FT232RL USB-to-serial IC are very popular. While they provide an excellent way to interface to USB they hide away all the interesting details behind their serial ports. Even the very creative folks at Arduino have taken steps to ween themselves away from these support chips, replacing them with an open source LUFA ATmega8U2 version, albeit with the same functionality, in their UNO and Mega2560 boards.</p>
<p>For low speed USB communications the future is definitely in the direction of USB microcontroller based solutions.  USB serial interface engine chips, such as the Phillips PDIUSBD11 which uses a I2C serial interface and the National Semiconductor USBN9603 which uses a Microwire serial interface, are becoming a thing of the past. The only other options are USB devices that use a high-speed parallel interface to connect to the MCU.  This is not a solution that most experimenters will embrace.</p>
<p>My wish is that someone will eventually release an open source library dedicated to the HID interface supporting all the latest experimenter class USB microcontrollers that will come our way soon.  In the meantime hopefully the contributors to the Arduino project will enhance the firmware of their ATmega8U2 USB-to-serial IC to provide an USB-to-I2C feature as well, one that could provide for one or more HID based pipes off of it.</p>
<ol><strong>Footnotes </strong></ol>
<p>[*] Copyright 2011 George Magiros.  Use of source code subject to the GPLv3.  See <a href="http://gplv3.fsf.org/" />http://gplv3.fsf.org</a>.</p>
<ol><strong>Downloads </strong></ol>
<a class="downloadlink" href="http://lackawanna.hackhut.com/wp-content/plugins/download-monitor/download.php?id=7" title=" downloaded 251 times" >All Examples (251)</a>

<div class="hadsubmit">
<a href="mailto:tips@hackaday.com?subject=Using%20V-USB%20and%20the%20HID%20Class%20%28Part%20III%20of%20III%29&amp;body=I found an interesting project you may like. Here is the link: http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F06%2Fusing-v-usb-and-the-hid-class-part-iiiiii%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/HaD-submit/had.png" title="Sumbit this to HackaDay" />
</a>
<a href="mailto:tips@hacknmod.com?subject=Using%20V-USB%20and%20the%20HID%20Class%20%28Part%20III%20of%20III%29&amp;body=I found an interesting project you may like. Here is the link: http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F06%2Fusing-v-usb-and-the-hid-class-part-iiiiii%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/HaD-submit/hacknmod.png" title="Sumbit this to HacknMod" />
</a>
<a href="mailto:tips@lifehacker.com?subject=Using%20V-USB%20and%20the%20HID%20Class%20%28Part%20III%20of%20III%29&amp;body=I found an interesting project you may like. Here is the link: http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F06%2Fusing-v-usb-and-the-hid-class-part-iiiiii%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/HaD-submit/lifehacker.png" title="Sumbit this to LifeHacker" />
</a>
</div>

<div class="jwsharethis">
<br />
<a href="mailto:?subject=Using%20V-USB%20and%20the%20HID%20Class%20%28Part%20III%20of%20III%29&amp;body=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F06%2Fusing-v-usb-and-the-hid-class-part-iiiiii%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/email.png" title="Share this page via Email" />
</a>
<a target="_blank" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F06%2Fusing-v-usb-and-the-hid-class-part-iiiiii%2F&amp;title=Using+V-USB+and+the+HID+Class+%28Part+III+of+III%29">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/su.png" title="Share this page via Stumble Upon" />
</a>
<a target="_blank" href="http://digg.com/submit?url=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F06%2Fusing-v-usb-and-the-hid-class-part-iiiiii%2F&amp;title=Using+V-USB+and+the+HID+Class+%28Part+III+of+III%29">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/digg.png" title="Share this page via Digg this" />
</a>
<a target="_blank" href="http://www.reddit.com/submit?url=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F06%2Fusing-v-usb-and-the-hid-class-part-iiiiii%2F&amp;title=Using+V-USB+and+the+HID+Class+%28Part+III+of+III%29">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/reddit.png" title="Share this page via Reddit" />
</a>
<a target="_blank" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F06%2Fusing-v-usb-and-the-hid-class-part-iiiiii%2F&amp;t=Using+V-USB+and+the+HID+Class+%28Part+III+of+III%29">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/fb.png" title="Share this page via Facebook" />
</a>
<a target="_blank" href="http://twitter.com/intent/tweet?text=I+like+http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F06%2Fusing-v-usb-and-the-hid-class-part-iiiiii%2F&amp;title=Using+V-USB+and+the+HID+Class+%28Part+III+of+III%29">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/twitter.png" title="Share this page via Twitter" />
</a>
</div>
]]></content:encoded>
			<wfw:commentRss>http://lackawanna.hackhut.com/2011/10/06/using-v-usb-and-the-hid-class-part-iiiiii/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Using V-USB and the HID Class (Part II of III)</title>
		<link>http://lackawanna.hackhut.com/2011/10/06/using-v-usb-and-the-hid-class-part-ii/</link>
		<comments>http://lackawanna.hackhut.com/2011/10/06/using-v-usb-and-the-hid-class-part-ii/#comments</comments>
		<pubDate>Thu, 06 Oct 2011 06:36:52 +0000</pubDate>
		<dc:creator>lackawanna</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://lackawanna.hackhut.com/?p=254</guid>
		<description><![CDATA[ The HID Interface
<p>All HID interfaces are required to have one IN endpoint, besides the control endpoint zero.  If there is no IN endpoint, a HID device will not be created on the host.  This is so even if the HID interface does not send any input reports.  At least this is how the Linux kernel behaves.</p>
<p>In .....<br /><br /><a href="http://lackawanna.hackhut.com/2011/10/06/using-v-usb-and-the-hid-class-part-ii/">Read the Rest</a>]]></description>
			<content:encoded><![CDATA[<ol><strong> The HID Interface</strong></ol>
<p>All HID interfaces are required to have one IN endpoint, besides the control endpoint zero.  If there is no IN endpoint, a HID device will not be created on the host.  This is so even if the HID interface does not send any input reports.  At least this is how the Linux kernel behaves.</p>
<p>In addition all HID endpoints must use “interrupt transfers”.  If no interrupt IN endpoints exists, dmesg will display “couldn&#8217;t find an input interrupt endpoint”.  However, the Linux kernel is nice enough to change a “bulk transfer” IN endpoint to an interrupt transfer one to maintain compliance.</p>
<p>In order to set up the IN 1 endpoint buffer for the next IN transaction, the firmware calls the V-USB routine usbSetInterrupt(). The figure below provides an illustration of how this routine is used. It also shows how to handle an IN transaction for control endpoint zero.<br />
<a href="http://lackawanna.hackhut.com/files/2011/10/in.png" rel="lightbox[254]"><img class="alignnone size-full wp-image-276" src="http://lackawanna.hackhut.com/files/2011/10/in.png" alt="" width="700" height="220" /></a><br />
For a hidraw device all input reports must come over the interrupt IN endpoint.  Of course a control request can be made for the report.  The GET_REPORT control transfer request is used to do this.  But unless libusb or some other driver is used by the host application, we are out of luck since hidraw provides no support for making this request.</p>
<p>A HID interface may also have an interrupt OUT endpoint.  This endpoint is optional.  Just like how an interrupt IN endpoint is used to send input reports, an interrupt OUT endpoint is used to transfer output reports from the host to the device.  If an interrupt OUT endpoint is not provided by the interface then any output reports will be transferred using the SET_REPORT control transfer request.</p>
<ol><strong> Example Two</strong></ol>
<p>Again create a new example directory and set it up as done before in example one.  Next edit usbconfig.h and change the values to the following.</p>
<ul>
<li>Set USB_CFG_HAVE_INTRIN_ENDPOINT  to 1,</li>
<li> set USB_CFG_DEVICE_CLASS to 0,</li>
<li> set USB_CFG_INTERFACE_CLASS to 3, and</li>
<li> set USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH to 21.</li>
</ul>
<p>The source code for example two is given below.  Save it as main.c.</p>
<pre>#include &lt;avr/io.h&gt;
#include &lt;avr/wdt.h&gt;         // for wdt routines
#include &lt;avr/interrupt.h&gt;   // for sei()
#include &lt;util/delay.h&gt;      // for _delay_ms()

#include &lt;avr/pgmspace.h&gt;    // required by usbdrv.h
#include "usbdrv.h"
#include "oddebug.h"         // debug macros

/* USB report descriptor */
PROGMEM char usbHidReportDescriptor[] = {
  0x06, 0xa0, 0xff, // USAGE_PAGE (Vendor Defined Page 1)
  0x09, 0x01,       // USAGE (Vendor Usage 1)
  0xa1, 0x01,       // COLLECTION (Application)

  // Input Report
  0x09, 0x02,       // Usage ID - vendor defined
  0x15, 0x00,       // Logical Minimum (0)
  0x26, 0xFF, 0x00, // Logical Maximum (255)
  0x75, 0x08,       // Report Size (8 bits)
  0x95, 0x08,       // Report Count (8 fields)
  0x81, 0x02,       // Input (Data, Variable, Absolute)

  0xc0              // END_COLLECTION
};

void main_loop (void)
{
  static uchar n, inbuf[8];
  uchar i;
  if (usbInterruptIsReady()) {
    n += 1;
    if (n &gt; 8 ) n = 1;
    for (i=0; i&lt;n-1; i++) inbuf[i] = '0' + i;
    inbuf[i++] = '\n';
    usbSetInterrupt(inbuf, i);
  }
}

usbMsgLen_t usbFunctionSetup (uchar *data)
{
  return 0;
}

int main (void)
{
  wdt_disable();
  odDebugInit();
  usbInit();

  usbDeviceDisconnect();  // force re-enumeration
  _delay_ms(250);
  usbDeviceConnect();

  sei();                  // now enable interrupts
  for(;;){
    usbPoll();
    main_loop();
  }
}</pre>
<p>Compile the firmware.  But before burning it, copy the following file as 99-hidraw.rules to /etc/udev/rules.d, otherwise superuser access is required to read and write the hidraw device. This is a huge advantage over using libusb which always requires superuser access.</p>
<pre>KERNEL=="hidraw*", MODE="666"</pre>
<p>Once the firmware is burned and example two enumerates, a new HID device should of been created on the host computer. The output of dmesg, if everything worked, will say something like the following.</p>
<pre>generic-usb 0003:16C0:05DC.0001: hiddev0,hidraw0: USB HID v1.01 Device [obdev.at Template] on usb-0000:00:1d.7-4.1/input0</pre>
<p>To display the input reports of our USB device to the screen execute, “cat /dev/hidraw0”.</p>
<ol><strong>Polling of the Interrupt IN Endpoint</strong></ol>
<p>It is very interesting to note that no polling of the interrupt IN endpoint takes place until hidraw0 is read.  When the shell command is killed or the device node closed, the polling immediately stops.  This can be seen both in the debug output and by using an oscilloscope. Interrupt IN polling can also be triggered by the select() command and, interesting enough, by the write() command too.</p>
<p>Whether or not the host polls the interrupt endpoint continuously when there are no pending I/O operations, apparently depends on the design of the driver.  For example, the driver hiddev immediately starts polling once opened and will not stop even when closed.  This can be witnessed by executing and thenkilling “sudo hexdump /dev/usb/hiddev0”.</p>
<ol><strong>Reading Input Reports</strong></ol>
<p>One word of caution needs to be mentioned about hidraw.  When using the read() command make sure the number of bytes requested is equal to or greater than 8, the maximum packet size.  Otherwise the data in the rest of the packet may be lost.  The library libusb has a similar issue, any call to usb_interrupt_read() must set the number of bytes requested to 8 at most, but not less than the report size.</p>
<p>The figure below shows the additional requests that get tacked on compared to the previous example.  Three new SETUP requests are made, of which two are class requests, SET_IDLE and GET_REPORT, and the other is a standard GET_DESCRIPTOR request. The GET_DESCRIPTOR request for the report descriptor is handled automatically by the V-USB library.  Since the other two requests are class-specific they are handled in usbFunctionSetup().<br />
<a href="http://lackawanna.hackhut.com/files/2011/10/example2_enum.png" rel="lightbox[254]"><img class="alignnone size-full wp-image-277" src="http://lackawanna.hackhut.com/files/2011/10/example2_enum.png" alt="" width="495" height="119" /></a><br />
Unlike in the previous example where the recipient of the requests was always the device, for these three requests the recipient is an interface.  If there were multiple interfaces the firmware must determine which interface the request is intended for.  The interface number is passed in the wIndex field. Since we only use one interface in this example interface zero will always be the recipient.</p>
<p>The shell command lsusb prints out the following for example two.</p>
<p><a href="http://lackawanna.hackhut.com/files/2011/10/example2_lsusb.png" rel="lightbox[254]"><img class="alignnone size-full wp-image-278" src="http://lackawanna.hackhut.com/files/2011/10/example2_lsusb.png" alt="" width="436" height="393" /></a></p>
<p>It be should be noted that usbFunctionSetup() does not test for either request SET_IDLE or GET_REPORT, it simply returns the value zero in response.  This tells V-USB to reply with an “zero length packet” or ZLP.  In the GET_REPORT case, this means a ZLP will be sent back as the input report.  Since all future input reports in this example will be read through the HID interface&#8217;s interrupt IN 1 endpoint, responding back here with no data is appropriate.  It did not seem to upset the host device driver.</p>
<ol><strong> Control Transfer Direction</strong></ol>
<p>As a rule of thumb, any request that starts with the word GET has a “data transfer direction” from the device-to-host, as well as a data phase.  So if usbFunctionSetup() returns zero for any of these requests, a ZLP will be sent back as its data phase.  Some requests with the same data transfer direction do not have a data phase.  In this case, if a zero is returned causing a ZLP to be queued, the ZLP will never get sent to the host because of the lack of a data phase.</p>
<p>For a request, where the “data transfer direction” is going the other way, from the host-to-device, a ZLP reply means the request has been successfully completed.  This ZLP is sent out during the last phase of the control transfer called the “status phase”.  An example of such a request is SET_IDLE.  This request is mainly used to support an autorepeat capability on devices such as keyboards.  If this capability is not needed, the requests can be safely ignored. Nevertheless, a ZLP still must be returned during the status phase to say everything is fine.</p>
<ol><strong> The Report Descriptor</strong></ol>
<p>Report descriptors are confusing.  A good way of understanding them is to think of them in terms of a database table definition.  The Usage ID can be considered to be a field name. The actual content of the field can be considered to be an array of values.  The report size is the bit size of this value and the report count is the array size.  Lastly, the input, output, and feature tags create the actual field in the report.  For example, the report descriptor given in example two creates an input report with a single field.  The name of this field is 2 and it consists of an array of 8 values, each of which are 8-bits long.</p>
<p>There are complexities however, if the report provides a Minimum Usage ID and a Maximum Usage ID, it might create all those fields in the range.  The content of each field consists of just one value then.  There is also support for radio buttons with the Usages being the value, rather than the name, of a field.</p>
<p>As for what a Usage Page is, Usage IDs are organized into Usage Pages.  So a Usage Page might be Generic Desktop which has a Usage Page ID of 1 and contains Usages such as Mouse X and Y movements.</p>
<p>It should be mentioned that an input report must be defined in the report descriptor, otherwise hidraw will not return any data it might receive from its interrupt IN endpoint.  In other worlds, without an input report definition any read of the hidraw device by the host application will block forever.</p>
<ol><strong> Interrupt Transfers</strong></ol>
<p>The USB specification defines interrupt transfers as “small-data, low-frequency, bounded-latency communication” that are always unidirectional.   It is small-data because the most number of packets that can get sent is limited.  The figure below gives an indication of how much space each interrupt transfer takes up per frame.</p>
<p><a href="http://lackawanna.hackhut.com/files/2011/10/intr.png" rel="lightbox[254]"><img class="alignnone size-full wp-image-279" src="http://lackawanna.hackhut.com/files/2011/10/intr.png" alt="" width="320" height="234" /></a></p>
<p>My experiments place the maximum data rate of an interrupt endpoint at a 1,000 bytes per second, each way, when full 8-byte data packets are transfered.  The service interval used was 10ms.  This is the smallest interval allowed for low speed devices.  Service intervals are defined by the endpoint descriptor field, bInterval.  For a service interval of 100ms, the maximum data rate turned out to be 125 bytes per second.</p>
<ol><strong> USB Device Drivers</strong></ol>
<p>When using a HID device, the host application does not need to know which specific endpoint to read or write.  The device driver can figure this out by looking at the endpoint descriptors from the device.  As a result, input reports can be retrieved simply by using the driver&#8217;s read() command, no reference to the IN endpoint is required. Similarly, output reports can be sent to the device using the driver&#8217;s write() command.</p>
<p>If we look at the full output of dmesg from example two, we see that the kernel not only created a HID device but also loaded the HID core driver as well.</p>
<pre>generic-usb 0003:16C0:05DC.0001: hiddev0,hidraw0: USB HID v1.01 Device [obdev.at Template] on usb-0000:00:1d.7-4.1/input0
usbcore: registered new interface driver usbhid
usbhid: USB HID core driver</pre>
<p>The figure below gives a model, hopefully correct and based on the above output from dmesg, of the HID interface and the kernel device drivers that handle it.<br />
<a href="http://lackawanna.hackhut.com/files/2011/10/endpoint.png" rel="lightbox[254]"><img class="alignnone size-full wp-image-280" src="http://lackawanna.hackhut.com/files/2011/10/endpoint.png" alt="" width="720" height="220" /></a><br />
It should be noted that endpoint zero is shared across other device drivers including libusb. Unfortunately if, for example, endpoint 1 has been reserved in an endpoint descriptor to a HID interface, it cannot be shared with libusb, according to my experiments.  If libusb tries to read or write such an endpoint it will error out with a resource busy message.  This is may be different on Windows.  For vendor interfaces, the situation is different.  The libusb library can access the endpoint so long as there is an endpoint descriptor for it. Accessing an endpoint without an endpoint descriptor will error out with the message “error submitting URB: No such file or directory”.</p>
<p>There might be ways to get around this however.  The libusb host application can use control transfers to access any of the input or output reports.  But there is some overhead associated with this solution.  Another option is for the USB device to provide two interfaces, one for HID and the other for vendor.  To communicate with the device, the HID device can access the HID interface while the libusb based host application can access the vendor interface.</p>
<p>For a more detailed diagram of the internal operation of endpoints and interfaces, see the figure below which was taken from the USB specification.<br />
<a href="http://lackawanna.hackhut.com/files/2011/10/operation.png" rel="lightbox[254]"><img class="alignnone size-full wp-image-281" src="http://lackawanna.hackhut.com/files/2011/10/operation.png" alt="" width="671" height="601" /></a></p>
<ol><strong>Downloads </strong></ol>
<a class="downloadlink" href="http://lackawanna.hackhut.com/wp-content/plugins/download-monitor/download.php?id=8" title=" downloaded 350 times" >Example Two (350)</a>

<div class="hadsubmit">
<a href="mailto:tips@hackaday.com?subject=Using%20V-USB%20and%20the%20HID%20Class%20%28Part%20II%20of%20III%29&amp;body=I found an interesting project you may like. Here is the link: http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F06%2Fusing-v-usb-and-the-hid-class-part-ii%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/HaD-submit/had.png" title="Sumbit this to HackaDay" />
</a>
<a href="mailto:tips@hacknmod.com?subject=Using%20V-USB%20and%20the%20HID%20Class%20%28Part%20II%20of%20III%29&amp;body=I found an interesting project you may like. Here is the link: http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F06%2Fusing-v-usb-and-the-hid-class-part-ii%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/HaD-submit/hacknmod.png" title="Sumbit this to HacknMod" />
</a>
<a href="mailto:tips@lifehacker.com?subject=Using%20V-USB%20and%20the%20HID%20Class%20%28Part%20II%20of%20III%29&amp;body=I found an interesting project you may like. Here is the link: http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F06%2Fusing-v-usb-and-the-hid-class-part-ii%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/HaD-submit/lifehacker.png" title="Sumbit this to LifeHacker" />
</a>
</div>

<div class="jwsharethis">
<br />
<a href="mailto:?subject=Using%20V-USB%20and%20the%20HID%20Class%20%28Part%20II%20of%20III%29&amp;body=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F06%2Fusing-v-usb-and-the-hid-class-part-ii%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/email.png" title="Share this page via Email" />
</a>
<a target="_blank" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F06%2Fusing-v-usb-and-the-hid-class-part-ii%2F&amp;title=Using+V-USB+and+the+HID+Class+%28Part+II+of+III%29">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/su.png" title="Share this page via Stumble Upon" />
</a>
<a target="_blank" href="http://digg.com/submit?url=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F06%2Fusing-v-usb-and-the-hid-class-part-ii%2F&amp;title=Using+V-USB+and+the+HID+Class+%28Part+II+of+III%29">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/digg.png" title="Share this page via Digg this" />
</a>
<a target="_blank" href="http://www.reddit.com/submit?url=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F06%2Fusing-v-usb-and-the-hid-class-part-ii%2F&amp;title=Using+V-USB+and+the+HID+Class+%28Part+II+of+III%29">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/reddit.png" title="Share this page via Reddit" />
</a>
<a target="_blank" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F06%2Fusing-v-usb-and-the-hid-class-part-ii%2F&amp;t=Using+V-USB+and+the+HID+Class+%28Part+II+of+III%29">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/fb.png" title="Share this page via Facebook" />
</a>
<a target="_blank" href="http://twitter.com/intent/tweet?text=I+like+http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F06%2Fusing-v-usb-and-the-hid-class-part-ii%2F&amp;title=Using+V-USB+and+the+HID+Class+%28Part+II+of+III%29">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/twitter.png" title="Share this page via Twitter" />
</a>
</div>
]]></content:encoded>
			<wfw:commentRss>http://lackawanna.hackhut.com/2011/10/06/using-v-usb-and-the-hid-class-part-ii/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using V-USB and the HID Class (Part I of III)</title>
		<link>http://lackawanna.hackhut.com/2011/10/04/using-v-usb-and-the-hid-class-part-i/</link>
		<comments>http://lackawanna.hackhut.com/2011/10/04/using-v-usb-and-the-hid-class-part-i/#comments</comments>
		<pubDate>Tue, 04 Oct 2011 14:42:45 +0000</pubDate>
		<dc:creator>lackawanna</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://lackawanna.hackhut.com/?p=87</guid>
		<description><![CDATA[<p>
USB can be quite a complex interface to learn.  It is definitely not as easy to explain or as intuitive as the well known serial port.  The specification for USB is hundreds of pages long.  Books such as USB Complete by Jan Axelson and USB Design by Example by John Hyde are just as big.  There .....<br /><br /><a href="http://lackawanna.hackhut.com/2011/10/04/using-v-usb-and-the-hid-class-part-i/">Read the Rest</a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://lackawanna.hackhut.com/files/2011/10/circuit.png" rel="lightbox[87]"><img src="http://lackawanna.hackhut.com/files/2011/10/circuit.png" alt="" width="887" height="811" class="alignnone size-full wp-image-237" /></a><br />
USB can be quite a complex interface to learn.  It is definitely not as easy to explain or as intuitive as the well known serial port.  The specification for USB is hundreds of pages long.  Books such as <em>USB Complete</em> by Jan Axelson and <em>USB Design by Example</em> by John Hyde are just as big.  There are multiple “interface classes”, such as the Human Interface Device or HID class.  Hardware issues such as impedance matching, bus capacitance, and voltage level conversion must be taken into account.  So it is for good reason that many experimenters revert to the old serial port standby.  USB just does not seem to be worth the trouble.  Indeed I felt the same way until recently.</p>
<p>This does not need to be the case. USB can be understood with a modest amount of effort.  Indeed the interface logic was designed to be implemented using simple microcontrollers.  So for the experimenter learning USB should not be hard.  Nor is learning the HID class particularly difficult once the basic USB fundamentals are in place.</p>
<p>In fact, the HID class can do everything a serial port can do.  HID has the ability to create a basic bidirectional software pipe between the device and the host. It is over this pipe that “output reports” are written and “input reports” are read.  HID also provides for a kind of out-of-band signaling capability through its “feature reports”. Unfortunately the latest release of Ubuntu, specifically version 11.04, does not support feature reports using the HID “hidraw” device driver.</p>
<p>In addition, since a USB interface can be uniquely identified using some combination of vendor-ID, product-ID, vendor name, product name, serial number, interface number, and interface name, a specific USB interface can be easily located by the host application.  The user is no longer required to explicitly provide the directory path of the device node to use.  One way of accomplishing this is through the “udev” library on Linux. [1]</p>
<ol> <strong>Creating a Software Pipe using HID</strong></ol>
<p>HID is well known for its support for computer keyboards and mice.  These devices generate fixed-sized “reports” that are sent back to the host computer.  For minimal latency the reports are made small enough to fit within a single data packet.  For low speed USB devices the maximum data packet size is 8 bytes.  If low latency is less of a concern, reports longer than 8 bytes and spread over multiple data packets can be used.</p>
<p>On Linux there is a device driver called hidraw which supports raw reading and writing of these reports. The cross platform library “libusb” and the Windows API calls WriteFile() and ReadFile() are probably the only similar options for Windows. [2]  These raw drivers are best for creating a basic data pipe between the host application and the device.  Unfortunately the HID specification states that all reports must be fixed-size.   However, using hidraw and libusb, this requirement can be circumvented, allowing variable-sized packets to be sent.  These raw drivers are not strict about the fixed-size reporting requirement of HID.</p>
<p>Another option, one which will not break the HID specification, is to define a fixed size report which is the same size as the maximum packet size.   Any bytes not used in the report are filled with zeros.   This is how the “teensy” board implements a data pipe using its “HID Listener” program.  The teensy web site has the source code for this host application.  The application supports both Linux and Windows. [3]  Whichever method is used, the creation of a software pipe using HID and the software based “bit-banging” USB library V-USB is the subject of this note.</p>
<ol> <strong>The V-USB Library</strong></ol>
<p>V-USB is a USB firmware library written for the Atmel AVR. [4]  Because it is software based it is highly dependent on the accuracy and speed of the CPU clock.  Only certain clock speeds are supported.  They are 12.0Mhz, 12.8Mhz, 15.0Mhz, 16.0Mhz, 16.5Mhz, 18.0Mhz, and 20.0Mhz.  The AVR&#8217;s internal RC oscillator will work but only if it can be calibrated to within 1% of 12.8Mhz or 16.5Mhz. [5]  Other speeds require higher clock precision and must use a crystal.  A ceramic resonator is not stable enough to work, though I have not tried one to be sure.</p>
<p>USB uses a number of different physical socket types.  I will focus on the one most of us are familiar with.  It is called the standard A socket.  It is the connector commonly used on desktop computers.  Generic IC prototype boards with 2.5mm separation between holes are perfect for making a simple USB plug.  The socket and this DIY plug are illustrated in the figure below.</p>
<p><a href="http://lackawanna.hackhut.com/files/2011/10/connector.png" rel="lightbox[87]"><img src="http://lackawanna.hackhut.com/files/2011/10/connector.png" alt="" width="640" height="200" class="alignnone size-full wp-image-148" /></a></p>
<p>The center pins, 2 and 3, on socket A are separated by 2.0mm.  The outer pins are separated by 2.5mm.  This matches well enough for the board to work.  Just cut and file the board down, leaving four strips of pads.  The resulting tab should fit loosely into the USB socket.  A tighter fit is created by soldering No. 26 AWG solid wire to the pads.  The other ends of the wires can be conveniently connected to the AVR circuit.</p>
<ol> <strong> The Electrical Circuit</strong></ol>
<p>The V-USB Wiki offers the following three circuits, illustrated in the figure below, for interfacing to USB. [6] I added the pin names for connection to an ATmega328p.  Each circuit solves the voltage level conversion problem that USB has. Even though USB supplies a 5 volt line, the USB bus does not operate at 5 volts.  The maximum high level for the D+ and D- lines is 3.6 volts.  Since most experimenters power their circuits off 5 volts, the USB bus must somehow be driven with a lower voltage.</p>
<p><a href="http://lackawanna.hackhut.com/files/2011/10/hardware.png" rel="lightbox[87]"><img src="http://lackawanna.hackhut.com/files/2011/10/hardware.png" alt="" width="640" height="200" class="alignnone size-full wp-image-145" /></a></p>
<p>One solution is to reduce the AVR&#8217;s operating voltage.  Another option is to clamp the D+ and D- lines down using zener diodes.  There are other ways to perform level conversion.  Resistive dividers can be tasked into service.  For my circuit I simply used an external power supply set to 3.0 volts.  Unfortunately the AVR in my circuit runs at 16Mhz and this violates the maximum safe operating frequency for this voltage.  The maximum safe operating frequency at 3.0 volts is less than 14Mhz according to the datasheet.</p>
<p>In order to alert the host when a device is plugged in, one of the bus lines must be pulled up to at least 2.7 volts.  If the D- line is pulled up the host will recognize it as a low speed device.  For low speed devices D- is inverted and D+ is non-inverted, as their names indicate.  For full-speed it will be the opposite.  Since low speed is the only speed V-USB supports, a 1.5k ohm resistor is used to pull up D-.  Low speed runs at a clock speed of 1.5Mhz, while full speed runs at 12Mhz.   At the host end both lines are brought to ground through 15k ohm resistors.  The figure below illustrates this.</p>
<p><a href="http://lackawanna.hackhut.com/files/2011/10/connection.png" rel="lightbox[87]"><img src="http://lackawanna.hackhut.com/files/2011/10/connection.png" alt="" width="640" height="200" class="alignnone size-full wp-image-149" /></a></p>
<p>Together the 1.5k ohm pull-up resistor at the device and the 15k ohm resistor at the host make up a voltage divider.   The output of this divider should not be less that 2.7 volts.  If Vcc is set to 3.0 volts, the pull-up in combination with the 15k ohm resistor will present the host with a voltage of 15/(15+1.5)*3.0 = 2.73 volts.  If zener diodes are used to clamp down the line, the voltage can go even lower. It is best to check with a meter to make sure the D- line is at least 2.7 volts.  See the Hardware Considerations section of the V-USB Wiki for more information. [7]</p>
<ol> <strong> The Series Resistors</strong></ol>
<p>The USB specification gives a range for the “series damping resistance” to use for full-speed.  This resistance is the sum of the series resistor and the driver&#8217;s output impedance.  For low speed, however, no  series damping resistance values are provided.  It only gives a range of load capacitance to expect on the bus as well as a range for the minimum and maximum rise times required for the signal transitions.  (Since the specification only provides a downstream value for the load capacitance, I assumed the upstream value is the same.)</p>
<p>At full speed, ringing problem, such as overshoot and undershoot, can occur on the line.  These problems are caused by reflections on the cable.  The series resistors are used to damp these reflections down so they cannot affect any future bit transitions.  </p>
<p>As a general rule, a transmission line can viewed as a lumped circuit when the rise time is greater than four times the propagation delay for a given length of transmission line.  The USB specification states the propagation delay of a low-speed cable must be less than 18ns.  The minimum rise time of 75ns is more than four times this 18ns value.  So unless rise times are allowed to rise faster than 75ns, ringing issues should not be a problem.</p>
<p>So why use series resistors at low speed if they are not needed for damping?  I can think of three additional reasons.  They protect the output drivers from overload, they reduce cross-talk, and they prevent the bus rise times from rising faster than 75ns.</p>
<ol><strong>Overload Protection</strong></ol>
<p>The figure below shows the bus lines of my test circuit when the AVR is driving it.  The rise times are around 86ns.  The waveforms are also pretty symmetric relative to each other and the signals cross at about the same point. Symmetry is important for noise immunity.  The peak-to-peak voltage on D- is a bit lower than the voltage on the D+ line.  This can be attributed to the voltage divider consisting of the 68 ohm resistor and the 1.5k ohm pull up resistor on the device.  This causes a voltage difference of 68 / (68 + 1500) * (3 volts) = 130 mV to occur.</p>
<p><a href="http://lackawanna.hackhut.com/files/2011/10/DS0012.png" rel="lightbox[87]"><img src="http://lackawanna.hackhut.com/files/2011/10/DS0012.png" alt="" width="320" height="234" class="alignnone size-full wp-image-150" /></a></p>
<p>The figure below shows what the bus looks like the other way around when the host is driving it instead of the device.  The rise times are longer and the waveforms are less symmetric.  The crossing points do not line up as well as they did the other way.  The D- line is lower in  voltage which again can be attributed to the voltage divider action of the host&#8217;s series resistor and the pull up resistor at the device.  Since the voltage difference measured by the oscilloscope is 3.28 &#8211; 3.18 = 100mV, the series resistor at the host is probably 51 ohms. Overall average rise times are around 140ns.</p>
<p><a href="http://lackawanna.hackhut.com/files/2011/10/DS0019.png" rel="lightbox[87]"><img src="http://lackawanna.hackhut.com/files/2011/10/DS0019.png" alt="" width="320" height="234" class="alignnone size-full wp-image-151" /></a></p>
<p>An important calculation is the equivalent frequency of a particular rise time.  The formula for this is f = .349 / tr.  The equivalent frequency is not a new frequency component, of course.  The series resistance and the load capacitance, which together determine the rise time of the signal, only change the phase and amplitude of the signal, not the frequency.  The equivalent frequency is just the bandwidth of the signal.  It represents the high frequency 3-dB first-order cutoff point for its frequency components. So for a 300ns rise time, the equivalent frequency is .349 / 300ns = 1.2Mhz.  While for a 75ns rise time the equivalent frequency is .349 / 75ns = 4.7Mhz.</p>
<p>Using the range of load capacitance given by the USB specification, the reactance of the bus at the equivalent frequency can be calculated using the formula, 1 / (2 * pi * C * f).  This provides us with an indication of the average load the AVR&#8217;s output drivers will encounter during signal transitions.  This is, at the very least, what my simulations have suggested.</p>
<p>The driver current must peak at some point too.  Since the voltage across a capacitor cannot change instantaneously the current through the series resistor when the load end is shorted to ground must be the peak current.  Assuming the driver&#8217;s output impedance is 10 ohms, for a transition from ground to 3.0 volts through the 68 ohm resistor and the 10 ohm driver, the peak current is 3.0 / (68 + 10) = 38mA.</p>
<p>In an attempt to observe the peak and average current through the driver, I placed oscilloscope probes on both sides of the 68 ohm resistor on the D+ line.  The current through the resistor can be calculated from the voltage drop measured across it.  The subtraction math function was selected on the DSO to find the difference between the two channels.  The first two signal transitions were used as an error signal.  The voltage difference here should be zero since the host is driving the bus and there should be little current through the series resistors.  The later transitions however are of the AVR driving the bus.  Using the error signal the peak voltage drop across the resistor was estimated to be around 700mV.  The peak current delivered by the driver is then 700mV / 68 = 10ma.</p>
<p><a href="http://lackawanna.hackhut.com/files/2011/10/DS0023.png" rel="lightbox[87]"><img src="http://lackawanna.hackhut.com/files/2011/10/DS0023.png" alt="" width="320" height="234" class="alignnone size-full wp-image-152" /></a></p>
<ol><strong>Cross-Talk</strong></ol>
<p>We can model cross-talk with a capacitor connected across the two bus lines.  The equivalent frequency formula comes in handy here.  The lower the capacitive reactance across the lines, the greater will be the cross-talk.  A faster rise time will increase cross-talk since it has a higher equivalent frequency.  A higher equivalent frequency means there are larger amplitude frequency components in the signal that potentially can cross over and cause problems.  Since rise times are dependent on the RC time constant of the line, adding series resistance to the drivers&#8217; outputs will lengthen rise times.  This will reduce any cross-talk.</p>
<ol><strong>Limiting Rise Times</strong></ol>
<p>Rise times must not be faster than 75ns at low speed or else the lumped capacitance model will fail. The formula for calculating rise time is tr = 2.197 * R * C.  The value R is the parallel combination of the series resistance and the load resistance.  The value C is the load capacitance of the bus.  For the case where the device is driving the bus upstream, let R be the parallel combination of the load resistance and the 68 ohm resistor plus the 10 ohm output impedance of the driver.  If the load resistance of the D+ line is used then R equals (68 + 10) * 15000 / (68 + 10 + 15000) = 77.6 ohms.  Assuming the load capacitance is 600pF, the rise time will be 2.197 * 77.6 * 600pF = 102ns.</p>
<ol><strong>EMI</strong></ol>
<p>It should also be mentioned that according to the V-USB Wiki, electromagnetic interference (EMI) is a big problem for V-USB.  Good layout as well as proper decoupling of noise from the power supply is important to prevent glitches and spikes caused by EMI.  Long wires should not be directly connected to any AVR pins, especially long wires going to the I/O pins for D+ and D-. [8]</p>
<ol><strong> Triggering an Interrupt on the AVR</strong></ol>
<p>One of the lines, either D+ or D-, must be connected to a pin on the AVR with some interrupt capacity.  V-USB recommends the pin INT0 be used since it has the highest priority of any interrupt after RESET.  Typically the D+ line is used to trigger the interrupt even though the library firmware uses the D- line to actually decode the packets, The D- line contains an additional signal called the “keep alive signal”.  This signal is transmitted every millisecond as a short 2-bit long pulse.  If the D- line is used, the AVR will be interrupted every keep alive signal as well.  The figure below illustrates an active keep alive signal.  The start and end of a “frame” is delineated by this signal.</p>
<p><a href="http://lackawanna.hackhut.com/files/2011/10/keepalive.png" rel="lightbox[87]"><img src="http://lackawanna.hackhut.com/files/2011/10/keepalive.png" alt="" width="320" height="234" class="alignnone size-full wp-image-155" /></a></p>
<p>Unless there is a need to use the keep alive signal to provide a precision timing function or to support suspend mode, D+ should trigger the interrupt.  Using D+ worked successfully for my test circuit.  The other bus line, for example D-, must be connected to a pin on the same port that the interrupt trigger is on.</p>
<ol><strong> USB Packets </strong></ol>
<p>A USB packet is represented as a NRZ-Inverted signal.  The level of the signal, whether it is high or low, does not determine the bit sent, rather the transitions do.  A transition from low to high or high to low represents a zero bit, while no transition represents a one bit. In addition, bits are sent least significant bit first.  The same is true for bytes.  Least significant bytes are sent first.  See the figure below.</p>
<p><a href="http://lackawanna.hackhut.com/files/2011/10/packet.png" rel="lightbox[87]"><img src="http://lackawanna.hackhut.com/files/2011/10/packet.png" alt="" width="700" height="250" class="alignnone size-full wp-image-156" /></a></p>
<p>The 8-bit PID field identifies the type of packet.  Any fields after the PID field are specific to the class the packet belongs to.  There are four different packet classes.  The packet in the figure above belongs to the “token” class.  The other classes are “data”, “handshake”, and “special”.  The token class of packets have fields for device address, endpoint number, and CRC5. Every USB “transaction” starts with a packet from the token class.</p>
<p>The 7-bit address identifies the device which this packet and subsequent packets of the transaction are meant for.  A device is assigned an address upon being “enumerated” by the host immediately after being plugged in.</p>
<p>The 4-bit endpoint number is similar to a device sub-address.  It uniquely identifies which FIFO of the device the next packet is meant for.  There are a total of 32 FIFOs, 16 “IN” FIFOs and 16 “OUT” FIFOs, that a USB device potentially can have.  Sometimes these FIFOs are implemented using buffers instead. The USB specification calls them sources or sinks of information.  The specific token packet type, IN or OUT, and the value of the endpoint number field identifies which FIFO to use.  For the transaction given in the figure above the specific FIFO to retrieve the data from is “IN 1”.</p>
<p>The 5-bit CRC5 field is used to error check every bit in the packet after the PID field and up to the CRC5 field.  Unfortunately only the 18Mhz version of the V-USB library is fast enough to detect errors using the CRC field and respond back to the host in time with the proper handshake packet.</p>
<p>The last three bits of the packet represent the End Of Packet (EOP) signal.  The EOP is represented by a low state on both bus lines followed by the bus going into the J state.  For low speed the J state means the D- line is high and the D+ line is low.  The J state is the state the bus would be in if it were idle.</p>
<ol> <strong>Transactions</strong></ol>
<p>A transaction is the work horse of USB. A successful transfer is composed of three packets: a token packet, a data packet, and a handshake packet.  The IN transaction is probably the most familiar since it is the transaction used to transfer keystrokes and mouse movements back to the computer.  In the USB context, IN means input into the host computer.  This is how HID input reports are relayed to the host.  There is also an OUT transaction. Here OUT means output out of the host and into the device.  OUT transactions are used to send HID output reports, for example, to the device.  The figure below shows a keep alive signal and an IN transaction.</p>
<p><a href="http://lackawanna.hackhut.com/files/2011/10/phy.png" rel="lightbox[87]"><img src="http://lackawanna.hackhut.com/files/2011/10/phy.png" alt="" width="700" height="220" class="alignnone size-full wp-image-157" /></a><br />
If, for example, the “IN 3” FIFO has data in it for the host, the host can issue an IN transaction, with the endpoint number field set to 3 in the token packet, to retrieve it.  If the host wanted to send data to the “OUT 3” FIFO, the host can issue an OUT transaction setting the endpoint number field to 3 in the token packet and the data from the next packet will be placed into this FIFO.</p>
<p>If a host issues an IN transaction for a FIFO which is empty the device will respond with an NAK packet.  The figure below shows this in action.  With an OUT transaction the device might respond with a NAK if the destination FIFO is full.  It might also respond with a NAK if the data packet fails its CRC error check.</p>
<p><a href="http://lackawanna.hackhut.com/files/2011/10/nak.png" rel="lightbox[87]"><img src="http://lackawanna.hackhut.com/files/2011/10/nak.png" alt="" width="800" height="200" class="alignnone size-full wp-image-158" /></a></p>
<p>Two bus captures are illustrated.  The top capture is from a “control transfer” while the bottom one is from an “interrupt transfer”.  In the control transfer the host makes multiple attempts, one after the other, at getting the data.  After three attempts, I believe, it gives up and will try again in a later frame.  For interrupt transfers, one attempt in a frame is enough. The host will attempt the interrupt transfer again in a later frame.</p>
<ol><strong> Example One</strong></ol>
<p>Before we go further let us write our first code example.  There are a few initial steps that need to be completed before these examples will compile.  First create an example directory and copy over the usbdrv directory from the V-USB library. Next copy usbconfig-prototype.h from the usbdrv directory into our directory and rename it usbconfig.h.  After that, copy over one of the Makefiles from the firmware directory of any of the examples in the V-USB library.</p>
<p>Edit the Makefile, making sure the F_CPU value is set to the correct clock speed for the circuit and the DEVICE value is set to the right device name.  Also change DEBUG_LEVEL=0 to DEBUG_LEVEL=2 to enable V-USB&#8217;s debug output. The debug output will be sent out of the AVR&#8217;s USART at 19200 baud. Lastly change the port numbers in usbconfig.h to reflect the design of the circuit.  Specifically make sure the values for USB_CFG_DMINUS_BIT and USB_CFG_DPLUS_BIT are correct.</p>
<p>Since my circuit used a different pin number for the D- line, I changed the predefined value for USB_CFG_DMINUS_BIT to 3.   (FYI, I should of kept it at 4, the predefined value, and used PD4 for D- in my circuit since the pin also functions as the T0 input which can be utilized to check for any USB inactivity.)  In addition because I used an ATmega328p I changed the value for DEVICE to atmega328p.</p>
<p>The source code for main.c follows.</p>
<pre>#include &lt;avr/io.h&gt;
#include &lt;avr/wdt.h&gt;         // for wdt routines
#include &lt;avr/interrupt.h&gt;   // for sei()
#include &lt;util/delay.h&gt;      // for _delay_ms()

#include &lt;avr/pgmspace.h&gt;    // required by usbdrv.h
#include "usbdrv.h"
#include "oddebug.h"         // debug macros

usbMsgLen_t usbFunctionSetup (uchar *data)
{
  return 0;
}

int main (void)
{
  wdt_disable();
  odDebugInit();
  usbInit();

  usbDeviceDisconnect();  // force re-enumeration
  _delay_ms(250);
  usbDeviceConnect();

  sei();                  // now enable interrupts
  for(;;){
    usbPoll();
  }
}</pre>
<p>Execute the shell command “make hex” and main.hex should be created.  Setup a terminal program to receive any transmission from the AVR&#8217;s USART.  If the circuit is connected to a USB port the following debug output, shown in the figure below, should result as soon as the firmware is burned.</p>
<p><a href="http://lackawanna.hackhut.com/files/2011/10/example1_enum.png" rel="lightbox[87]"><img src="http://lackawanna.hackhut.com/files/2011/10/example1_enum.png" alt="" width="484" height="410" class="alignnone size-full wp-image-159" /></a></p>
<p>The only thing the firmware does in our example is “enumerate” the device to the host.  The V-USB library does this automatically.  The device is assigned a device address but no device drivers are associated with it.  All dmesg says is “usb 1-4.1: new low speed USB device using ehci_hcd and address 64”.  During enumeration the host requests a number of “descriptors” from the device: a device descriptor, a configuration descriptor, and a few string values.  These describe the device and what it can do.  At the end, the host tells the device to use the first configuration within its configuration descriptor.  Since our example only has one configuration the host picks that one.  USB devices rarely have more than one configuration.</p>
<p>Looking at the debug output in the figure above, each line represents a transaction.  The byte tag before the colon indicates the type and endpoint number of the transaction, while the bytes after the colon represent the data packet that was received by the device or which will be sent by the host.</p>
<p>The byte tag of 1d represents a SETUP transaction with an endpoint number field of zero.  A SETUP transaction resembles an OUT transaction but with a “request” embedded in the data packet that the host sends.  A SETUP packet is a token packet just like an IN or OUT packet and it leads off the transaction. The data packet of the SETUP transaction contains the actual request.  The request might be, for example, GET_DESCRIPTOR which responds back to the host with data for the descriptor asked for.</p>
<p>A byte tag of 20 represents an IN transaction with an endpoint number field of zero.  These IN transactions make up the response or “data phase” to the prior SETUP transaction.  OUT transactions over endpoint zero are also possible in order to support a data phase going in the other direction, from the host to the device.  What “data transfer direction” the data phase takes depends on the request.  Two requests that use a data phase to send data from the host to the device are SET_REPORT and SET_DESCRIPTOR.</p>
<p>Because endpoint zero responds to SETUP transactions, it is considered a “control endpoint” which handles “control transfers”.  A control endpoint is bidirectional and requires the use of two FIFOs.  For example, the control endpoint zero uses the two FIFOs with the same endpoint number of zero, specifically IN 0 and OUT 0.  A non-control endpoint, on the other hand, is unidirectional and uses only one FIFO.  In addition, endpoint zero always exits and is always a control endpoint.  In fact it is called the default control endpoint because device enumeration always takes place over it.</p>
<p>Looking at the debug output again, the first byte value after the colon for the IN transaction is the PID of the data packet.  There are two different PIDs, DATA0 and DATA1, for data packets.  The PIDs toggle back and forth in order to support the detection of any lost data packets.</p>
<p>The figure below shows the output of the shell command “lsusb”.  It provides a decoded view of the descriptors returned by the device.</p>
<p><a href="http://lackawanna.hackhut.com/files/2011/10/example1_lsusb.png" rel="lightbox[87]"><img src="http://lackawanna.hackhut.com/files/2011/10/example1_lsusb.png" alt="" width="493" height="510" class="alignnone size-full wp-image-160" /></a></p>
<ol><strong> Descriptors </strong></ol>
<p>The device descriptor tells the host how many configurations the device provides as well as the vendor and product information for the device.  While a device descriptor may give the class of the interfaces on the device, a value of zero in the bDeviceClass field defers such decisions to each interface individually.  My experiments indicate that the only non-zero class code that works here is the vendor-specific code of 0xff.</p>
<p>The configuration descriptor tells the host, among other things, how much power the device uses and how many interfaces it provides.  There must be one or more interfaces.  Though it is possible to say zero interfaces, this violates the USB specification.  Also dmesg complains with “config 1 has no interfaces?”</p>
<p>There is a 1-to-1 relationship between the devices on the host and interfaces on the device. So if, for example, the interface supports the HID class, a HID device will be created for it by the host HID device driver.  Interfaces provide a way to abstract the low-level endpoint based workings of USB.  An interface descriptor lays out its class, which endpoints it uses, and the transfer modes of each endpoint.  For example, by using the HID interface class, the host application does not need to know which endpoint numbers to communicate with.  The host application need only talk in terms of input, output and features reports.  The interface and the device driver already know which endpoints to use so this can be abstracted away.</p>
<p>In addition, by providing more than one interface on a device, each interface can perform a different function.  One interface might set itself up as a HID class to handle button presses.  Another interface might set itself up as an Audio class to handle microphone input and speaker output.   See the figure below.</p>
<p><a href="http://lackawanna.hackhut.com/files/2011/10/composite.png" rel="lightbox[87]"><img src="http://lackawanna.hackhut.com/files/2011/10/composite.png" alt="" width="720" height="220" class="alignnone size-full wp-image-163" /></a></p>
<p>For example, during my experiments I created two HID interfaces on the same device.  After enumeration the kernel created two HID devices with dmesg saying the following.</p>
<pre>usb 1-4.1: new low speed USB device using ehci_hcd and address 23
generic-usb 0003:16C0:05DC.000D: hiddev0,hidraw0: USB HID v1.01 Device [obdev.at Template] on usb-0000:00:1d.7-4.1/input0
generic-usb 0003:16C0:05DC.000E: hiddev0,hidraw1: USB HID v1.01 Device [obdev.at Template] on usb-0000:00:1d.7-4.1/input1</pre>
<p>Unfortunately a low speed device is limited in the number of endpoints it can use.  The USB specification states that a low speed device cannot use more than two endpoints beyond endpoint zero.  However, in my experiments using three endpoints at once the Linux kernel did not complain.</p>
<ol> <strong> The SETUP Transaction</strong></ol>
<p>The figure below illustrates an example data packet from an actual SETUP transaction.  A full request is given, not only, by the value in the Request field but by the request type (class, vendor, standard) and the request recipient (device, interface, endpoint) indicated in the Request Type field.  For example, the standard request SET_FEATURE, 03h, behaves differently depending upon whether the recipient is a device or an endpoint.  As another example, if the request type is set to vendor, the meaning of the other fields is up to the firmware.</p>
<p><a href="http://lackawanna.hackhut.com/files/2011/10/request.png" rel="lightbox[87]"><img src="http://lackawanna.hackhut.com/files/2011/10/request.png" alt="" width="720" height="220" class="alignnone size-full wp-image-164" /></a></p>
<p>A request with the request type set to class is a bit more involved.  The request recipient will likely be set to interface.  The wIndex field will then have to be referenced to determine exactly which interface number is the recipient.  If the referenced interface is of the HID class, a request value of 09h means the interface should execute the HID class request SET_REPORT.</p>
<p>The V-USB library by default handles all standard requests.  Any non-standard requests will be forwarded to the user defined function usbFunctionSetup().   The figure below illustrates how this forwarding works.</p>
<p><a href="http://lackawanna.hackhut.com/files/2011/10/setup.png" rel="lightbox[87]"><img src="http://lackawanna.hackhut.com/files/2011/10/setup.png" alt="" width="720" height="220" class="alignnone size-full wp-image-165" /></a></p>
<p>To gain a better understanding of how all of this works, the source code for usbDeviceSetup() in the library is very helpful.  The USB specification provides a list of all the standard requests and their arguments.  It should be noted that every request generated by example one were standard requests with the device set as the recipient.</p>
<p>(To be continued)</p>
<ol><strong>Downloads</strong></ol>
<p><a class="downloadlink" href="http://lackawanna.hackhut.com/wp-content/plugins/download-monitor/download.php?id=5" title=" downloaded 283 times" >Example One  (283)</a><br />
</p>
<ol><strong>Footnotes</strong></ol>
<p>[*] Copyright 2011 George Magiros.  Use of source code subject to the GPLv3.  See <a href="http://gplv3.fsf.org/" />http://gplv3.fsf.org</a>.<br />
[1] For sample code and a tutorial on locating USB devices using udev see <a href="http://www.signal11.us/oss/udev/" />http://www.signal11.us/oss/udev</a>.<br />
[2] The libusb library is located at <a href="http://www.libusb.org">http://www.libusb.org</a>.<br />
[3] Teensy is located at <a href="http://www.pjrc.com/teensy">http://www.pjrc.com/teensy</a>.<br />
[4] The V-USB library is located at <a href="http://www.obdev.at/products/vusb">http://www.obdev.at/products/vusb</a>.<br />
[5] See <a href="http://vusb.wikidot.com/examples">http://vusb.wikidot.com/examples</a> on how to calibrate the RC oscillator.<br />
[6] The V-USB Wiki is located at <a href="http://vusb.wikidot.com">http://vusb.wikidot.com</a>.<br />
[7] See <a href="http://vusb.wikidot.com/hardware">http://vusb.wikidot.com/hardware</a>.<br />
[8] See  <a href="http://vusb.wikidot.com/troubleshooting">http://vusb.wikidot.com/troubleshooting</a>.</p>

<div class="hadsubmit">
<a href="mailto:tips@hackaday.com?subject=Using%20V-USB%20and%20the%20HID%20Class%20%28Part%20I%20of%20III%29&amp;body=I found an interesting project you may like. Here is the link: http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F04%2Fusing-v-usb-and-the-hid-class-part-i%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/HaD-submit/had.png" title="Sumbit this to HackaDay" />
</a>
<a href="mailto:tips@hacknmod.com?subject=Using%20V-USB%20and%20the%20HID%20Class%20%28Part%20I%20of%20III%29&amp;body=I found an interesting project you may like. Here is the link: http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F04%2Fusing-v-usb-and-the-hid-class-part-i%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/HaD-submit/hacknmod.png" title="Sumbit this to HacknMod" />
</a>
<a href="mailto:tips@lifehacker.com?subject=Using%20V-USB%20and%20the%20HID%20Class%20%28Part%20I%20of%20III%29&amp;body=I found an interesting project you may like. Here is the link: http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F04%2Fusing-v-usb-and-the-hid-class-part-i%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/HaD-submit/lifehacker.png" title="Sumbit this to LifeHacker" />
</a>
</div>

<div class="jwsharethis">
<br />
<a href="mailto:?subject=Using%20V-USB%20and%20the%20HID%20Class%20%28Part%20I%20of%20III%29&amp;body=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F04%2Fusing-v-usb-and-the-hid-class-part-i%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/email.png" title="Share this page via Email" />
</a>
<a target="_blank" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F04%2Fusing-v-usb-and-the-hid-class-part-i%2F&amp;title=Using+V-USB+and+the+HID+Class+%28Part+I+of+III%29">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/su.png" title="Share this page via Stumble Upon" />
</a>
<a target="_blank" href="http://digg.com/submit?url=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F04%2Fusing-v-usb-and-the-hid-class-part-i%2F&amp;title=Using+V-USB+and+the+HID+Class+%28Part+I+of+III%29">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/digg.png" title="Share this page via Digg this" />
</a>
<a target="_blank" href="http://www.reddit.com/submit?url=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F04%2Fusing-v-usb-and-the-hid-class-part-i%2F&amp;title=Using+V-USB+and+the+HID+Class+%28Part+I+of+III%29">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/reddit.png" title="Share this page via Reddit" />
</a>
<a target="_blank" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F04%2Fusing-v-usb-and-the-hid-class-part-i%2F&amp;t=Using+V-USB+and+the+HID+Class+%28Part+I+of+III%29">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/fb.png" title="Share this page via Facebook" />
</a>
<a target="_blank" href="http://twitter.com/intent/tweet?text=I+like+http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F10%2F04%2Fusing-v-usb-and-the-hid-class-part-i%2F&amp;title=Using+V-USB+and+the+HID+Class+%28Part+I+of+III%29">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/twitter.png" title="Share this page via Twitter" />
</a>
</div>
]]></content:encoded>
			<wfw:commentRss>http://lackawanna.hackhut.com/2011/10/04/using-v-usb-and-the-hid-class-part-i/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>A Logic Analyzer using Audacity</title>
		<link>http://lackawanna.hackhut.com/2011/04/08/a-logic-analyzer-using-audacity/</link>
		<comments>http://lackawanna.hackhut.com/2011/04/08/a-logic-analyzer-using-audacity/#comments</comments>
		<pubDate>Fri, 08 Apr 2011 16:18:21 +0000</pubDate>
		<dc:creator>lackawanna</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://lackawanna.hackhut.com/?p=70</guid>
		<description><![CDATA[<p></p>
<p>If you are interested in observing digital data lines, such as the I2C bus, but do not have a logic analyzer &#8212; yet are lucky enough to still have a parallel port on your computer, this hack (I won&#8217;t say program) hopefully will help.  It captures the logic levels present at the input of the two data pins, D0 and .....<br /><br /><a href="http://lackawanna.hackhut.com/2011/04/08/a-logic-analyzer-using-audacity/">Read the Rest</a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://lackawanna.hackhut.com/files/2011/04/la.png" rel="lightbox[70]"><img class="alignnone size-full wp-image-80" src="http://lackawanna.hackhut.com/files/2011/04/la.png" alt="" width="622" height="316" /></a></p>
<p>If you are interested in observing digital data lines, such as the I2C bus, but do not have a logic analyzer &#8212; yet are lucky enough to still have a parallel port on your computer, this hack (I won&#8217;t say program) hopefully will help.  It captures the logic levels present at the input of the two data pins, D0 and D1, of your parallel port for 7 seconds.</p>
<p>Once done capturing it will write the pin data out as a raw unsigned 8-bit stereo audio file to the standard output.  You can then easily import and view it in, say, Audacity &#8211; which actually works extremely well.</p>
<p>One word of caution though, you must run this program once before attaching your circuit to the D0 and D1 pins since the parallel port data pins default to being outputs. The pins have to be converted over to inputs.  This is the first thing the hack does.  After that the data lines will remain in the input mode so you will only need to do it once at the beginning.</p>
<p>To build this analyzer, you can use a 25-pin RS232 cable. Pins 2 and 3 go to D0 and D1 and pin 20 goes to ground. On my computer, it is able to capture around 750,000 samples per second.</p>
<p>See <a class="downloadlink" href="http://lackawanna.hackhut.com/wp-content/plugins/download-monitor/download.php?id=4" title=" downloaded 263 times" >parallel port logic analyzer (263)</a></p>
<pre>#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;unistd.h&gt;
#include &lt;sys/io.h&gt;

#define samples   (5*1024*1024)
#define channels  2
#define base      0x378

static char log[samples];

int main(int argc, char *argv[])
{
 int i, n, c;
 if (ioperm(base,3,1)) fprintf(stderr, "ioperm() failed\n"), exit(1);
 n = inb(base+2);
 fprintf(stderr, "Data lines set as %s, changing to input\n",
         n &amp; (1&lt;&lt;5) ? "input" : "output");
 outb(n | (1&lt;&lt;5), base+2);   // set data lines as inputs
 for (n=0; n&lt;samples; n++) log[n] = inb(base);
 fprintf(stderr, "Writing out captured data...\n");
 for (n=0; n&lt;samples; n++) {
   for (i=0; i&lt;channels; i++) {
     c = ((log[n] &gt;&gt; i) &amp; 1) ? 224 : 32;
     putchar(c);
   }
 }
 return 0;
}
</pre>

<div class="hadsubmit">
<a href="mailto:tips@hackaday.com?subject=A%20Logic%20Analyzer%20using%20Audacity&amp;body=I found an interesting project you may like. Here is the link: http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F04%2F08%2Fa-logic-analyzer-using-audacity%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/HaD-submit/had.png" title="Sumbit this to HackaDay" />
</a>
<a href="mailto:tips@hacknmod.com?subject=A%20Logic%20Analyzer%20using%20Audacity&amp;body=I found an interesting project you may like. Here is the link: http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F04%2F08%2Fa-logic-analyzer-using-audacity%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/HaD-submit/hacknmod.png" title="Sumbit this to HacknMod" />
</a>
<a href="mailto:tips@lifehacker.com?subject=A%20Logic%20Analyzer%20using%20Audacity&amp;body=I found an interesting project you may like. Here is the link: http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F04%2F08%2Fa-logic-analyzer-using-audacity%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/HaD-submit/lifehacker.png" title="Sumbit this to LifeHacker" />
</a>
</div>

<div class="jwsharethis">
<br />
<a href="mailto:?subject=A%20Logic%20Analyzer%20using%20Audacity&amp;body=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F04%2F08%2Fa-logic-analyzer-using-audacity%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/email.png" title="Share this page via Email" />
</a>
<a target="_blank" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F04%2F08%2Fa-logic-analyzer-using-audacity%2F&amp;title=A+Logic+Analyzer+using+Audacity">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/su.png" title="Share this page via Stumble Upon" />
</a>
<a target="_blank" href="http://digg.com/submit?url=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F04%2F08%2Fa-logic-analyzer-using-audacity%2F&amp;title=A+Logic+Analyzer+using+Audacity">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/digg.png" title="Share this page via Digg this" />
</a>
<a target="_blank" href="http://www.reddit.com/submit?url=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F04%2F08%2Fa-logic-analyzer-using-audacity%2F&amp;title=A+Logic+Analyzer+using+Audacity">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/reddit.png" title="Share this page via Reddit" />
</a>
<a target="_blank" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F04%2F08%2Fa-logic-analyzer-using-audacity%2F&amp;t=A+Logic+Analyzer+using+Audacity">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/fb.png" title="Share this page via Facebook" />
</a>
<a target="_blank" href="http://twitter.com/intent/tweet?text=I+like+http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F04%2F08%2Fa-logic-analyzer-using-audacity%2F&amp;title=A+Logic+Analyzer+using+Audacity">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/twitter.png" title="Share this page via Twitter" />
</a>
</div>
]]></content:encoded>
			<wfw:commentRss>http://lackawanna.hackhut.com/2011/04/08/a-logic-analyzer-using-audacity/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Be self-reliant, compost</title>
		<link>http://lackawanna.hackhut.com/2011/04/08/24/</link>
		<comments>http://lackawanna.hackhut.com/2011/04/08/24/#comments</comments>
		<pubDate>Fri, 08 Apr 2011 12:12:11 +0000</pubDate>
		<dc:creator>lackawanna</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://lackawanna.hackhut.com/?p=24</guid>
		<description><![CDATA[<p></p>
<p>Composting might not be the geekiest thing at the moment &#8211; no iPhone apps currently exist for it from what I can determine.  Nevertheless it has been happening on this planet since organisms started living here and it is still very important.  30% of our waste is organic material which could be composted but unfortunately isn&#8217;t.</p>
<p>There are two processes that .....<br /><br /><a href="http://lackawanna.hackhut.com/2011/04/08/24/">Read the Rest</a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://lackawanna.hackhut.com/files/2011/04/hack.png" rel="lightbox[24]"><img class="alignnone size-full wp-image-63" src="http://lackawanna.hackhut.com/files/2011/04/hack.png" alt="" width="582" height="305" /></a></p>
<p>Composting might not be the geekiest thing at the moment &#8211; no iPhone apps currently exist for it from what I can determine.  Nevertheless it has been happening on this planet since organisms started living here and it is still very important.  30% of our waste is organic material which could be composted but unfortunately isn&#8217;t.</p>
<p>There are two processes that take place during composting.  First the organic matter undergoes aerobic decomposition, where bacteria and protozoa convert carbon and nitrogen into CO2 and cell structure, all the while generating a lot of heat in the process.  Then as the oxygen is depleted in the compost pile anaerobic fermentation begins to take over.  The living organisms now reduce nitrogen and carbon, without using oxygen, into organic acids, ammonia and methane.  Heat is released but not as much as before, around 20 times less.</p>
<p>For urban composting, the anaerobic, smelly stage should best be avoided.  This can be done by maximizing the time the aerobic stage has to decompose a pile.  In addition if the aerobic process completes too quickly this might be an indication that something is not quite right with the pile.  For example, there might be too much carbon in the mix, not enough nitrogen, or insufficient moisture.  Or it could simply indicate that the pile needs to be turned so the aerobic stage can be restarted again.</p>
<p><a href="http://lackawanna.hackhut.com/files/2011/04/carbon.png" rel="lightbox[24]"><img class="alignnone size-full wp-image-31" src="http://lackawanna.hackhut.com/files/2011/04/carbon.png" alt="" width="345" height="296" /></a></p>
<p><img src="///home/george/Desktop/composting.png" alt="" /></p>
<p>(from <a href="http://www.urban-composting.com/composting-tutorial.html">http://www.urban-composting.com/composting-tutorial.html</a>)</p>
<p>This is what my hack is intended to do.  It gives an indication of when the transition from aerobic to anaerobic happens and how long it takes.  It does this by monitoring the temperature of the pile and turning on a led when the pile is aerobicly decomposing and turning it off when the decomposition ends.</p>
<p>By measuring the temperature change as the pile heats up, stabilizes, and then falls back down to a lower temperature, the transition point can be identified.  Since a compost pile can vary in multiple ways including physical size, C:N ratio, moisture content, and particle size, the use of absolute temperature to identify the transition point is next to impossible without somehow gathering more information about the particular pile.  Instead a localized edge detection algorithm is used which relies, not on absolute temperature, but on the change in temperature of the pile over time.</p>
<p>The temperature sensor I used for my circuit is a metal can transistor I pulled out of my junk box &#8211; an old neglected 2N2222A &#8211; which was then soldered to a long copper tube which serves as the temperature probe.  The base and collector of the transistor are connected together while the emitter is grounded.  A 10k resistor is connected from Vcc to this junction.  The voltage across the transistor is measured using the AVR&#8217;s A-to-D converter to give a temperature observation.</p>
<p><a href="http://lackawanna.hackhut.com/files/2011/04/circuit.png" rel="lightbox[24]"><img class="alignnone size-full wp-image-27" src="http://lackawanna.hackhut.com/files/2011/04/circuit.png" alt="" width="280" height="250" /></a></p>
<p>As currently implemented this hack takes one temperature observation every ten minutes.  By averaging the temperature changes over 16 observations and then calculating the second derivative, a curvature value for the temperature movement is calculated.</p>
<p>When aerobic decomposition begins, the curvature value initially becomes positive as the temperature of the pile increases.  Once the curvature value passes a certain preset positive number which was determined experimentally, the aerobic process is considered to have begun and a led is turned on.  As the decomposition continues and the pile temperatures reach their maximum the curvature value will turn negative.  When the curvature becomes sufficiently negative, again experimentally determined, the hack now only needs to wait until the curvature value crosses over back to positive to consider the aerobic process done.  Eventually the oxygen is exhausted and the pile temperature comes down. The moment the curvature becomes positive again, the inflection point separating the transition from aerobic to anaerobic is considered reached and the led is turned off.</p>
<p>The graph below represents one of these experiment I performed using hot water to simulate a composting.  Here the curvature value is in blue and the A-to-D value (minus a constant and negated) is plotted in red.  The lowest value of the state plot represents when the led is turned off and the two higher state values represent when the led is turned on.</p>
<p><a href="http://lackawanna.hackhut.com/files/2011/04/experiment.png" rel="lightbox[24]"><img class="alignnone size-full wp-image-28" src="http://lackawanna.hackhut.com/files/2011/04/experiment.png" alt="" width="513" height="395" /></a></p>
<p>Depending upon the type of transistor or temperature sensor used, the preset values in the source code will likely need to be changed.  Since the measurement period and the number of observations to be averaged were also determined experimentally, a better sensor than a transistor might require less averaging or a shorter interval between observations, so these predefined values set in the source code would also need to be changed.</p>
<p>The ATmega328 based circuit I designed uses a 4MHz ceramic resonator for it&#8217;s clock.  If you wish to use the internal oscillator instead, the code can easily be changed to accommodate this by changing the predefined values in the source.  Please note, although there are two leds in the picture, only the red one is used by this hack &#8211; the green led should be ignored.  To compile type &#8220;make MCU_TARGET=atmega328p compost.hex&#8221;.</p>
<a class="downloadlink" href="http://lackawanna.hackhut.com/wp-content/plugins/download-monitor/download.php?id=3" title=" downloaded 283 times" >source code for compost.hex (283)</a>

<div class="hadsubmit">
<a href="mailto:tips@hackaday.com?subject=Be%20self-reliant%2C%20compost&amp;body=I found an interesting project you may like. Here is the link: http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F04%2F08%2F24%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/HaD-submit/had.png" title="Sumbit this to HackaDay" />
</a>
<a href="mailto:tips@hacknmod.com?subject=Be%20self-reliant%2C%20compost&amp;body=I found an interesting project you may like. Here is the link: http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F04%2F08%2F24%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/HaD-submit/hacknmod.png" title="Sumbit this to HacknMod" />
</a>
<a href="mailto:tips@lifehacker.com?subject=Be%20self-reliant%2C%20compost&amp;body=I found an interesting project you may like. Here is the link: http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F04%2F08%2F24%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/HaD-submit/lifehacker.png" title="Sumbit this to LifeHacker" />
</a>
</div>

<div class="jwsharethis">
<br />
<a href="mailto:?subject=Be%20self-reliant%2C%20compost&amp;body=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F04%2F08%2F24%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/email.png" title="Share this page via Email" />
</a>
<a target="_blank" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F04%2F08%2F24%2F&amp;title=Be+self-reliant%2C+compost">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/su.png" title="Share this page via Stumble Upon" />
</a>
<a target="_blank" href="http://digg.com/submit?url=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F04%2F08%2F24%2F&amp;title=Be+self-reliant%2C+compost">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/digg.png" title="Share this page via Digg this" />
</a>
<a target="_blank" href="http://www.reddit.com/submit?url=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F04%2F08%2F24%2F&amp;title=Be+self-reliant%2C+compost">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/reddit.png" title="Share this page via Reddit" />
</a>
<a target="_blank" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F04%2F08%2F24%2F&amp;t=Be+self-reliant%2C+compost">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/fb.png" title="Share this page via Facebook" />
</a>
<a target="_blank" href="http://twitter.com/intent/tweet?text=I+like+http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F04%2F08%2F24%2F&amp;title=Be+self-reliant%2C+compost">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/twitter.png" title="Share this page via Twitter" />
</a>
</div>
]]></content:encoded>
			<wfw:commentRss>http://lackawanna.hackhut.com/2011/04/08/24/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Hell-writing using a AVR keyer</title>
		<link>http://lackawanna.hackhut.com/2011/03/14/hello-world/</link>
		<comments>http://lackawanna.hackhut.com/2011/03/14/hello-world/#comments</comments>
		<pubDate>Mon, 14 Mar 2011 01:09:18 +0000</pubDate>
		<dc:creator>lackawanna</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://lackawanna.hackhut.com/?p=1</guid>
		<description><![CDATA[<p></p>
<p>There is no school like the old school and this fax technology from the 20&#8242;s using psycho-visual perception for image synchronization is just that.   A fax mark is represented by a carrier; and if there is no carrier there is no mark.  After a period of time, 7/122.5 seconds for the Feld-Hell standard, the tape is advanced and a .....<br /><br /><a href="http://lackawanna.hackhut.com/2011/03/14/hello-world/">Read the Rest</a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://lackawanna.hackhut.com/files/2011/03/hellwriting.png" rel="lightbox[1]"><img class="alignnone size-medium wp-image-15" src="http://lackawanna.hackhut.com/files/2011/03/hellwriting-300x133.png" alt="Image of Feld Hell decoding output" width="300" height="133" /></a></p>
<p>There is no school like the old school and this fax technology from the 20&#8242;s using psycho-visual perception for image synchronization is just that.   A fax mark is represented by a carrier; and if there is no carrier there is no mark.  After a period of time, 7/122.5 seconds for the Feld-Hell standard, the tape is advanced and a new column is started.   By double printing each column the decoder lets the mind visually synchronize the image.   So not only are the decoding and transmitter requirements kept simple but it works amazing well, allowing communication over noisy channels that otherwise might not be able to support it, say, using morse code.</p>
<div id="attachment_10" class="wp-caption alignnone" style="width: 310px"><a href="http://lackawanna.hackhut.com/files/2011/03/avr.png" rel="lightbox[1]"><img class="size-medium wp-image-10" src="http://lackawanna.hackhut.com/files/2011/03/avr-300x206.png" alt="image of AVR microcontroller soldered to a pc board" width="300" height="206" /></a><p class="wp-caption-text">AVR Keyer</p></div>
<p>This AVR keyer, written for the ATmega328, has both a key down signal to turn a carrier on and off and a keyed 1000 Hz tone for driving a modulator, a speaker, or the line-in of a sound card.     There are two key down pins for ease of interfacing.  One pin provides an active high key down signal (PD7/pin 13) and the other an active low (PB0/pin 14).  The keyed 1000 hz tone is provided by timer 0&#8242;s OCA pin (PD6/pin 12).</p>
<p>The message to be sent is actually hardcoded in the source code.  To change it you have to modify and recompile the source code.  The keyer will also send out any characters received over the AVR&#8217;s UART.  In addition you can change the speed of the transmission.  While Feld-Hell is ordinarily transmitted at 150 characters per minute, there is a much slower version of it called Slow-Feld which is used by beacons.  This mode can be enabled by changing the characters per minute value in the source code to 1.6455 from 150.</p>
<p>To decode standard Feld-Hell on Linux, Fldigi (<a href="http://www.w1hkj.com/Fldigi.html">http://www.w1hkj.com/Fldigi.html</a>) works very well.    IZ8BLY&#8217;s Windows software (<a href="http://xoomer.virgilio.it/aporcino/Hell/index.htm">http://xoomer.virgilio.it/aporcino/Hell/index.htm</a>) is also recommended.  It not only decodes Feld-Hell but also Slow-Feld, plus it can be run in Wine.  Note, Fldigi&#8217;s faster version of Slow-Feld is incompatible with IZ8BLY&#8217;s version.  (see <a href="http://www.qsl.net/zl1bpu/HELL/Modes.htm">http://www.qsl.net/zl1bpu/HELL/Modes.htm</a> about Slow-Feld and <a href="http://www.qsl.net/zl1bpu/HELL/Index.htm">http://www.qsl.net/zl1bpu/HELL/Index.htm</a> for an Intro to Hell)</p>
<a class="downloadlink" href="http://lackawanna.hackhut.com/wp-content/plugins/download-monitor/download.php?id=2" title=" downloaded 194 times" >AVR Feld Hell Keyer Source Code (194)</a>
<p>Unzip and to compile type &#8220;make MCU_TARGET=atmega328p feldhell.hex&#8221;</p>

<div class="hadsubmit">
<a href="mailto:tips@hackaday.com?subject=Hell-writing%20using%20a%20AVR%20keyer&amp;body=I found an interesting project you may like. Here is the link: http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F03%2F14%2Fhello-world%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/HaD-submit/had.png" title="Sumbit this to HackaDay" />
</a>
<a href="mailto:tips@hacknmod.com?subject=Hell-writing%20using%20a%20AVR%20keyer&amp;body=I found an interesting project you may like. Here is the link: http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F03%2F14%2Fhello-world%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/HaD-submit/hacknmod.png" title="Sumbit this to HacknMod" />
</a>
<a href="mailto:tips@lifehacker.com?subject=Hell-writing%20using%20a%20AVR%20keyer&amp;body=I found an interesting project you may like. Here is the link: http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F03%2F14%2Fhello-world%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/HaD-submit/lifehacker.png" title="Sumbit this to LifeHacker" />
</a>
</div>

<div class="jwsharethis">
<br />
<a href="mailto:?subject=Hell-writing%20using%20a%20AVR%20keyer&amp;body=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F03%2F14%2Fhello-world%2F">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/email.png" title="Share this page via Email" />
</a>
<a target="_blank" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F03%2F14%2Fhello-world%2F&amp;title=Hell-writing+using+a+AVR+keyer">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/su.png" title="Share this page via Stumble Upon" />
</a>
<a target="_blank" href="http://digg.com/submit?url=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F03%2F14%2Fhello-world%2F&amp;title=Hell-writing+using+a+AVR+keyer">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/digg.png" title="Share this page via Digg this" />
</a>
<a target="_blank" href="http://www.reddit.com/submit?url=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F03%2F14%2Fhello-world%2F&amp;title=Hell-writing+using+a+AVR+keyer">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/reddit.png" title="Share this page via Reddit" />
</a>
<a target="_blank" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F03%2F14%2Fhello-world%2F&amp;t=Hell-writing+using+a+AVR+keyer">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/fb.png" title="Share this page via Facebook" />
</a>
<a target="_blank" href="http://twitter.com/intent/tweet?text=I+like+http%3A%2F%2Flackawanna.hackhut.com%2F2011%2F03%2F14%2Fhello-world%2F&amp;title=Hell-writing+using+a+AVR+keyer">
<img src="http://lackawanna.hackhut.com/wp-content/plugins/jw-share-this/twitter.png" title="Share this page via Twitter" />
</a>
</div>
]]></content:encoded>
			<wfw:commentRss>http://lackawanna.hackhut.com/2011/03/14/hello-world/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
