<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4829924363554235528</id><updated>2012-02-12T11:37:40.882Z</updated><title type='text'>Embedded Adventures</title><subtitle type='html'>Changing the world...one microcontroller at a time</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>38</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-3591339460779518954</id><published>2011-08-05T14:41:00.002+01:00</published><updated>2011-08-05T14:43:57.035+01:00</updated><title type='text'>Aduino powered by PIC32</title><content type='html'>&lt;p&gt;Finally! Arduino sure seems to be ruling the hobbyist embedded market and we're finally able to bring a compatible platform on the Microchip side of the fence.  Not just that, these development platforms are based on the PIC32 microcontrollers, meaning that they have a true 32 bit core, and hence easily many, many times faster than your average Arduino board.&lt;/p&gt;&lt;p&gt;The ChipKit platform gives you all that's good about Arduino - hardware and software compatibility with "shields" (add-on boards) and the software libraries that make Arduino platforms easy to get started on - but with room to grow.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;a title="ChipKit" rel="lightbox" href="http://www.embeddedadventures.com/admin/images/uploaded_images/PLT_1005_600.jpg"&gt;&lt;img style="display: block; margin-left: auto; margin-right: auto;" title="ChipKit Uno32 Platform" src="http://www.embeddedadventures.com/admin/images/uploaded_images/PLT_1005_250.jpg" alt="PLT-1005 ChipKit Uno32 Development Platform" width="250" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;We'll be bringing you tutorials on how to use the platform and you'll be delighted to know that all the 3.3v Embedded Adventures modules will work with these platforms.  It's very exciting to have a platform that will get you started easily into the wonderful world of embedded electronics - and one that it truly powerful, meaning you won't outgrow it in a hurry!&lt;/p&gt;&lt;p&gt;&lt;br /&gt;We're carrying the &lt;a href="http://www.embeddedadventures.com/shopdetails/pid/111"&gt;Uno32&lt;/a&gt; and &lt;a href="http://www.embeddedadventures.com/shopdetails/pid/110"&gt;Max32&lt;/a&gt; platforms and look forward to hearing about what you're doing at yours.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-3591339460779518954?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/3591339460779518954/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=3591339460779518954' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/3591339460779518954'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/3591339460779518954'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2011/08/aduino-powered-by-pic32.html' title='Aduino powered by PIC32'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-2096599947993817097</id><published>2011-08-02T13:04:00.002+01:00</published><updated>2011-08-02T13:06:20.893+01:00</updated><title type='text'>New alphanumeric LED display - DSP-0801</title><content type='html'>&lt;p&gt;2 August 2011&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;It took six PCB revisions and countless tweaks until we were happy with it - but finally we're are delighted to present our latest product, the DSP-0801, an &lt;a href="http://www.embeddedadventures.com/shopdetails/pid/112"&gt;8 digit 14 segment alphanumeric display&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;a title="DSP-0801" rel="lightbox" href="http://www.embeddedadventures.com/admin/images/uploaded_images/DSP_0801_600.jpg"&gt;&lt;img style="display: block; margin-left: auto; margin-right: auto;" title="8 digit 14 segment alphanumeric display" src="http://www.embeddedadventures.com/admin/images/uploaded_images/DSP_0801_250.jpg" alt="DSP-0801 8 digit alpha display" width="250" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Powered by a PIC18F14K50 with two CAT4016 chips running the displays, this display is designed to make it easy to interface to.  You can talk to it over TTL serial at 115,200 bps, or via synchronous (clocked) serial, also allowing you to daisy chain modules together to create even bigger displays. Of course the firmware supplied does all this out of the box, but there's nothing stopping you replacing the firmware for your own nefarious purposes!  It could, for example, talk directly to a &lt;a href="http://www.embeddedadventures.com/shopdetails/pid/92"&gt;RTC / Temp sensor module&lt;/a&gt;, to display time and temperature - add a &lt;a href="http://www.embeddedadventures.com/shopdetails/pid/108"&gt;SoundOut module&lt;/a&gt; to make it a talking clock, or use all those digits to show the &lt;a href="http://www.embeddedadventures.com/shopdetails/pid/106"&gt;humidity&lt;/a&gt; with 24 bit accuracy.  There's a BoostBloader bootloader in built, or you can use the ICSP port to reprogram it with a &lt;a href="http://www.embeddedadventures.com/shopdetails/pid/61"&gt;PicKit2&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;The possibilities are endless!  Available in red, blue and yellow, and shipping now.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-2096599947993817097?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/2096599947993817097/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=2096599947993817097' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/2096599947993817097'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/2096599947993817097'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2011/08/2-august-2011-it-took-six-pcb-revisions.html' title='New alphanumeric LED display - DSP-0801'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-14908637979320832</id><published>2011-07-25T20:54:00.002+01:00</published><updated>2011-07-25T20:56:35.008+01:00</updated><title type='text'>24 bit MS5611 barometric pressure sensor / barometer back in stock</title><content type='html'>&lt;p&gt;25 July 2011&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;Our 24 bit &lt;a href="http://www.embeddedadventures.com/shopdetails/pid/106"&gt;MS5611 based barometric pressure sensor / barometer&lt;/a&gt; is back in stock.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;a title="24bit air pressure sensor" rel="lightbox" href="http://www.embeddedadventures.com/admin/images/uploaded_images/mod_1009_600.jpg"&gt;&lt;img style="display: block; margin-left: auto; margin-right: auto;" title="24bit air pressure sensor" src="http://www.embeddedadventures.com/admin/images/uploaded_images/mod_1009_250.jpg" alt="MOD-1009 MS5611 Air Pressure Sensor" width="250" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Thanks to everyone who has waited for backorders to be filled, we ran out of the last run very quickly!  We really appreciate your patience.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-14908637979320832?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/14908637979320832/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=14908637979320832' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/14908637979320832'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/14908637979320832'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2011/07/24-bit-ms5611-barometric-pressure.html' title='24 bit MS5611 barometric pressure sensor / barometer back in stock'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-2414702098181596582</id><published>2011-07-07T16:27:00.001+01:00</published><updated>2011-07-07T16:29:07.738+01:00</updated><title type='text'></title><content type='html'>&lt;p&gt;Need a sound module for your embedded project that can drive a speaker directly, has bucket loads of memory, and can play back audio samples on command? Do we have a product for you!  After much hunting and haggling and designing and testing, we present the &lt;a href="http://www.embeddedadventures.com/shopdetails/pid/108"&gt;MOD-1007 SoundOut&lt;/a&gt; audio module.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;a title="SoundOut Audio Module" rel="lightbox" href="http://www.embeddedadventures.com/admin/images/uploaded_images/MOD_1007_600.jpg"&gt;&lt;img style="display: block; margin-left: auto; margin-right: auto;" title="SoundOut Audio Module" src="http://www.embeddedadventures.com/admin/images/uploaded_images/MOD_1007_250.jpg" alt="MOD-1007 SoundOut Audio Module" width="250" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Compatible with the SOMO-14D module (at least, it uses the same playback chip - the pinout is slightly different), this module allows you to start sample playback using press buttons or using a synchronous (clocked) serial connection to your microcontroller, using an easy protocol.  Of course, the &lt;a href="http://www.embeddedadventures.com/pages/p/Tutorials/id/29"&gt;PicPack&lt;/a&gt; library already has sample code available if you need a hand. &amp;nbsp;The module plays back .AD4 files, which can be created from .MP3 or .WAV files using a utility provided.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-2414702098181596582?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/2414702098181596582/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=2414702098181596582' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/2414702098181596582'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/2414702098181596582'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2011/07/need-sound-module-for-your-embedded.html' title=''/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-1421323643533549571</id><published>2011-06-13T20:19:00.002+01:00</published><updated>2011-06-13T20:22:39.509+01:00</updated><title type='text'>Power up!</title><content type='html'>&lt;p&gt;Need 3.3V or 5V for your breadboard experiment or next project? The &lt;a href="http://www.embeddedadventures.com/shopdetails/pid/107"&gt;MOD-1011&lt;/a&gt; is just for you!  Throw up to 30V at it and it'll give you a nice, regulated supply at up to 1A - we've used low ESR tantalum capacitors to ensure superior regulation to what you normally get with your average breadboard power supply.&lt;/p&gt;&lt;br /&gt;&lt;a title="Power Supply Module" rel="lightbox" href="http://www.embeddedadventures.com/admin/images/uploaded_images/mod_1011_600.jpg"&gt;&lt;img style="display: block; margin-left: auto; margin-right: auto;" title="Power Supply Module" src="http://www.embeddedadventures.com/admin/images/uploaded_images/mod_1011_250.jpg" alt="MOD-1011 Power Supply Module" width="250" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-1421323643533549571?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/1421323643533549571/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=1421323643533549571' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/1421323643533549571'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/1421323643533549571'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2011/06/power-up.html' title='Power up!'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-6288573868552095883</id><published>2010-06-10T13:17:00.003+01:00</published><updated>2010-06-22T16:12:39.896+01:00</updated><title type='text'>New web site</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_bEFwpcEs1Go/TCDSar6TJdI/AAAAAAAAAEI/Xa9QpeXq1NA/s1600/EA_logo_72dpiRGB.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 74px;" src="http://4.bp.blogspot.com/_bEFwpcEs1Go/TCDSar6TJdI/AAAAAAAAAEI/Xa9QpeXq1NA/s320/EA_logo_72dpiRGB.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5485615702042944978" /&gt;&lt;/a&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;Please pop over to our shiny new web site at&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://www.embeddedadventures.com"&gt;www.embeddedadventures.com&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://www.embeddedadventures.com"&gt;&lt;/a&gt;Looking forward to seeing you soon!&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-6288573868552095883?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/6288573868552095883/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=6288573868552095883' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/6288573868552095883'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/6288573868552095883'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2010/06/coming-soon.html' title='New web site'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_bEFwpcEs1Go/TCDSar6TJdI/AAAAAAAAAEI/Xa9QpeXq1NA/s72-c/EA_logo_72dpiRGB.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-7376759526726423500</id><published>2009-12-02T17:37:00.003Z</published><updated>2009-12-02T17:41:57.845Z</updated><title type='text'>SOMO-14D audio module</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_bEFwpcEs1Go/SxamV4tDphI/AAAAAAAAADg/2URf5nWR7lM/s1600-h/logic.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 320px; height: 156px;" src="http://3.bp.blogspot.com/_bEFwpcEs1Go/SxamV4tDphI/AAAAAAAAADg/2URf5nWR7lM/s320/logic.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5410694897261061650" /&gt;&lt;/a&gt;&lt;br /&gt;The Somo 14D is a cute little module from 4D - plays audio files you put on a micro SD card.  Aside from some difficulties with the brand of card you use, it kind of worked... but wouldn't play the files I requested.&lt;br /&gt;&lt;br /&gt;Now, bring in the Logic tool.  Honestly, I can't believe I didn't buy this or something like this years ago.&lt;br /&gt;&lt;br /&gt;Turns out this module is very particular also about the timing of commands you send it.  The clock pulses have to be 200us.  And that's exactly what I had in my code:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;void somo_14d_send_data(uns16 data) {&lt;br /&gt; &lt;br /&gt; // Signal start&lt;br /&gt; clear_pin(somo_14d_clk_port, somo_14d_clk_pin);&lt;br /&gt; delay_ms(2); // tSTART = 2ms&lt;br /&gt; &lt;br /&gt; for (uns8 count = 0; count &lt; 16; count++) {&lt;br /&gt;  if (data.15) {&lt;br /&gt;   set_pin(somo_14d_data_port, somo_14d_data_pin);&lt;br /&gt;  } else {&lt;br /&gt;   clear_pin(somo_14d_data_port, somo_14d_data_pin);&lt;br /&gt;  }&lt;br /&gt;  delay_us(1);  // tDS = 1us&lt;br /&gt;  set_pin(somo_14d_clk_port, somo_14d_clk_pin);&lt;br /&gt;  delay_us(200); // tCH = 200us&lt;br /&gt;  clear_pin(somo_14d_clk_port, somo_14d_clk_pin);&lt;br /&gt;  delay_us(200); // tCL = 200us&lt;br /&gt;  data = data &lt;&lt; 1;&lt;br /&gt; }&lt;br /&gt; // Signal end&lt;br /&gt; set_pin(somo_14d_clk_port, somo_14d_clk_pin);&lt;br /&gt; delay_ms(2); // tSTOP = 2ms&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;All looks perfectly okay, right?&lt;br /&gt;&lt;br /&gt;Now look at what Logic says.  The pulse is actually about 100us.  Half the...hang on.  In my config.h I had the clock rate of the chip at 20Mhz when in fact it's running at 40Mhz.  Ha!  Once again, Logic to the rescue.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-7376759526726423500?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/7376759526726423500/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=7376759526726423500' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/7376759526726423500'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/7376759526726423500'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2009/12/somo-14d-audio-module.html' title='SOMO-14D audio module'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_bEFwpcEs1Go/SxamV4tDphI/AAAAAAAAADg/2URf5nWR7lM/s72-c/logic.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-1214038980151868778</id><published>2009-10-29T16:01:00.022Z</published><updated>2009-10-29T16:35:23.455Z</updated><title type='text'>Smashing Pumpkins</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_bEFwpcEs1Go/Sum_d0xYPYI/AAAAAAAAAC0/55PnX38XvT8/s1600-h/SMASH-16.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 320px; height: 207px;" src="http://3.bp.blogspot.com/_bEFwpcEs1Go/Sum_d0xYPYI/AAAAAAAAAC0/55PnX38XvT8/s320/SMASH-16.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5398056147483114882" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Combine hobby electronics, photography and fruit and vegetables dropped from a second floor balcony, what do you get?&lt;br /&gt;&lt;br /&gt;My brother does fun stuff with cameras for a living - see &lt;a href="http://www.seesawphoto.com.au"&gt;www.seesawphoto.com.au&lt;/a&gt; - but we decided to combine his photography skills and equipment and some gear from Sparkfun and the PicPack library to see if we couldn't smash a few things up.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_bEFwpcEs1Go/Sum_M_o3tRI/AAAAAAAAACk/d3BjB8KLeIM/s1600-h/SMASH-13.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 320px; height: 218px;" src="http://2.bp.blogspot.com/_bEFwpcEs1Go/Sum_M_o3tRI/AAAAAAAAACk/d3BjB8KLeIM/s320/SMASH-13.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5398055858342442258" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;What could be more fun than smashing eggs, watermelons and pumpkins all in the name of a good photo?&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.sparkfun.com/commerce/images/products/PIC-MT-0_i_ma.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 188px; height: 188px;" src="http://www.sparkfun.com/commerce/images/products/PIC-MT-0_i_ma.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;The trick of course is to capture the image just at the right moment.  We rigged up a &lt;a href="http://www.sparkfun.com/commerce/product_info.php?products_id=8669"&gt;microphone&lt;/a&gt; to a &lt;a href="http://www.sparkfun.com/commerce/product_info.php?products_id=26"&gt;Pic demo board&lt;/a&gt; (which rather nicely has buttons, an LCD display, and a relay to trigger the flash.  We grabbed a wired connection to a camera-mounted flash - wired that to the relay output from the board and then used that to trigger Paul's top knotch professional studio flash gear.  The microphone was wired to the analogue input and sampled as quickly as the Pic could manage it.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_bEFwpcEs1Go/Sum_Vx8H_9I/AAAAAAAAACs/D-2d8FJiuPI/s1600-h/SMASH-15.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 320px; height: 212px;" src="http://2.bp.blogspot.com/_bEFwpcEs1Go/Sum_Vx8H_9I/AAAAAAAAACs/D-2d8FJiuPI/s320/SMASH-15.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5398056009283928018" /&gt;&lt;/a&gt;&lt;br /&gt;Knocking together the Pic application didn't take long with the library functions.  The buttons allowed a configurable delay in milliseconds between hearing sound and triggering the flash, and sound sensitivity.  Of course some experimentation was required here - more things to smash!  In the end we built an audible delay in so that we had a chance to "arm" the system, then get out of the way before the pumpkins came down.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_bEFwpcEs1Go/Sum_jyLpmGI/AAAAAAAAAC8/mtWQ1ndQ6Xk/s1600-h/SMASH-17.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 320px; height: 198px;" src="http://4.bp.blogspot.com/_bEFwpcEs1Go/Sum_jyLpmGI/AAAAAAAAAC8/mtWQ1ndQ6Xk/s320/SMASH-17.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5398056249867212898" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I think you'll agree the photos are pretty fun. Source code will be published in the next drop of PicPack.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-1214038980151868778?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/1214038980151868778/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=1214038980151868778' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/1214038980151868778'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/1214038980151868778'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2009/10/smashing-pumpkins.html' title='Smashing Pumpkins'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_bEFwpcEs1Go/Sum_d0xYPYI/AAAAAAAAAC0/55PnX38XvT8/s72-c/SMASH-16.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-522483154381762886</id><published>2009-01-26T11:54:00.002Z</published><updated>2009-01-26T12:02:28.534Z</updated><title type='text'>PicPack 2.0 released</title><content type='html'>Now available... Including better USB documentation and a cracking USB serial (CDC) demo.&lt;br /&gt;&lt;br /&gt;You can download from the right hand side "download" window.&lt;br /&gt;&lt;br /&gt;You can also get PicPack from GitHub - updated regularly.&lt;br /&gt;&lt;br /&gt;Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-522483154381762886?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/522483154381762886/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=522483154381762886' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/522483154381762886'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/522483154381762886'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2009/01/picpack-20-released.html' title='PicPack 2.0 released'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-8583730812399954426</id><published>2009-01-26T10:46:00.002Z</published><updated>2009-01-26T12:00:01.755Z</updated><title type='text'>USB Part 5 – Using the USB Serial library</title><content type='html'>Now that we’ve explored some of the ins and outs of the PicPack USB library, it’s time to look at a more complex and probably more useful example.  Up until now we’ve relied on using serial ports to act as our debug interface.  It would be nice if we could use USB for this purpose entirely?  This is where the Communication Device Class (CDC) comes in.&lt;br /&gt;&lt;br /&gt;The CDC covers many things, including the thing that we’re interested in, a connection to a modem-like device.  In fact, we define our “modem” as so dumb it can’t even make calls on a phone line – which sounds pretty much like a serial port to me.&lt;br /&gt;&lt;br /&gt;If you want to get cracking, open up the usb_serial project in the demos\usb_serial directory.  It’s all set for burning into a 18f4550 on a board like the TechToys USB demo board.  If you burn the .hex file, then plug your device into a PC, it will ask for a driver file.  Just point the install program at the picpack_cdc.inf file in the tools\usb_cdc_inf directory.  For reasons best known to Microsoft, Windows requires this file, even though all it says is “this is a standard USB serial port”.  Go figure.  Linux doesn’t require any sort of driver information at all.&lt;br /&gt;&lt;br /&gt;Using the PicPack CDC routines is pretty easy.  You can use them just like you’ve been using the pic_serial routines up til now.&lt;br /&gt;&lt;br /&gt;In your system setup routine, put:&lt;br /&gt;&lt;pre name="code" class="c:nocontrols:nogutter"&gt;&lt;br /&gt;// Setup Communication Device Class routines&lt;br /&gt;usb_cdc_setup();&lt;br /&gt;&lt;br /&gt;// Setup USB&lt;br /&gt;usb_setup();&lt;br /&gt;&lt;br /&gt;// Turn on interrupts&lt;br /&gt;turn_usb_ints_on();&lt;br /&gt;turn_global_ints_on();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In your interrupt service routine you will need to include:&lt;br /&gt;&lt;pre name="code" class="c:nocontrols:nogutter"&gt;&lt;br /&gt;usb_handle_isr();  &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;which handles both reception and transmission.&lt;br /&gt;&lt;br /&gt;In your main() routine, kick off USB negotiations using:&lt;br /&gt;&lt;pre name="code" class="c:nocontrols:nogutter"&gt;&lt;br /&gt;usb_enable_module()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You can wait for the negotiations to finish using&lt;br /&gt;&lt;pre name="code" class="c:nocontrols:nogutter"&gt;&lt;br /&gt;while (usb_configured == 0) {&lt;br /&gt;  delay_ms(250);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;We’ll use the callback that’s triggered when the configuration is complete to set the usb_configured variable:that we were checking in that last loop:&lt;br /&gt;&lt;pre name="code" class="c:nocontrols:nogutter"&gt;&lt;br /&gt;void usb_device_configured_callback() {&lt;br /&gt; usb_configured = 1;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And that’s it.  Once the link is up, you can use the usb_cdc_ routines like usb_cdc_putc just like their pic_serial equivalents.  In fact, aside from these routines, you can see that the complete program looks remarkably similar to the pic_serial demo itself.&lt;br /&gt;&lt;br /&gt;You can #define USB_DEBUG and CDC_DEBUG in the config.h file if you’d like to get more detail on the USB process itself.   This is handy if you want to understand how the CDC class code and the PicPack USB stack itself work.&lt;br /&gt;&lt;br /&gt;In the next tutorial we’ll delve a bit deeper into the CDC routines. The CDC is a more complex example than our previous USB joy mouse which sent data in only one direction, and didn’t make use of class control transfers and multiple endpoints.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-8583730812399954426?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/8583730812399954426/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=8583730812399954426' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/8583730812399954426'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/8583730812399954426'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2009/01/usb-part-5-using-usb-serial-library.html' title='USB Part 5 – Using the USB Serial library'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-1719200275629096845</id><published>2009-01-12T11:59:00.004Z</published><updated>2009-01-12T13:00:14.678Z</updated><title type='text'>USB part 4 – Inner workings of the PicPack USB stack</title><content type='html'>This tutorial covers the main USB functionality and how the library actually goes about setting up the pic to carry out USB transactions and transfers. You don’t need to understand exactly how all this happens, but it’s helpful to know what the functions do and how to use them.  &lt;br /&gt;&lt;br /&gt;Our first point is to setup the USB sub-system.  As is our convention with the PicPack library, naturally, you call the usb_setup routine:&lt;br /&gt;&lt;span style=";font-family:courier new;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;void usb_setup() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;usb_state = st_POWERED; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;Our state is now powered, meaning that we have power applied over the USB bus. The next task is to initialise the hardware:&lt;br /&gt;&lt;span style=";font-family:courier new;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// init hardware&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;clear_bit(ucfg, UTRDIS);    // enable internal tranceiver&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;Most designs involving pics use the internal transceiver.  You can connect the pic to an external piece of hardware, or connect it directly to the chip itself.  Here we assume that you’re doing the direct connection.  USB has (as of version 2.0) three speeds – low speed (around 1Mbps), full speed (around 12Mbs) and high speed (around 480Mbps).  The pics that we’re playing with only operate in the low/full range, meaning that we have to select between low and full speed.&lt;br /&gt;&lt;span style=";font-family:courier new;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;set_bit(ucfg, FSEN);    // clear for low speed, set for high speed&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;In all the examples here, we select full speed.  There’s no reason not to, really, and as it happens, selecting full speed gives us many more choices for clock frequency selection.  More about that in a later tutorial.&lt;br /&gt;&lt;br /&gt;USB indicates its speed request by pull-ups on the data pins.  The pic hardware can do this function for us (meaning we don’t need to include external pull-up resistors), providing we enable the on-chip pull-ups:&lt;br /&gt;&lt;span style=";font-family:courier new;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;set_bit  (ucfg, UPUEN);    // enable on-chip pull-ups&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;The pic USB Serial Interface Engine (SIE) can double buffer transfers, meaning that one buffer is being used by the SIE while the other is available to the microcontroller.   This means faster transfer at the cost of more complex code.  In the initial PicPack library, we switch double buffering off, for the sake of simplicity:&lt;br /&gt;&lt;span style=";font-family:courier new;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;clear_bit(ucfg, PPB1);        // disable double buffering&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;clear_bit(ucfg, PPB0);    &lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Finally, we set up end point 0 ready to receive and send control transfers:&lt;br /&gt;&lt;span style=";font-family:courier new;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;set_bit(uep0,   EPHSHK);    // EP0 handshaking on&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;set_bit(uep0,   EPOUTEN);    // EP0 OUT enable &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;set_bit(uep0,   EPINEN);     // EP0 IN enable &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;clear_bit(uep0, EPCONDIS);    // EP0 control transfers on (and IN and OUT)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;Here we enable handshaking (required for control transfers – and all endpoints type except isochronous), enable OUT (from host) and IN (to host) transfers, and enable control transfers on this endpoint.&lt;br /&gt;&lt;br /&gt;Due to a bug in the BoostC compiler that prevents compile time initialisation of structures that don’t point to char*, we need some run-time initialisation of this structure.&lt;br /&gt;&lt;span style=";font-family:courier new;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ep_out_bd_location[0] = &amp;amp;bd0out;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;This continues for all buffer descriptors for IN and OUT endpoints.&lt;br /&gt;&lt;br /&gt;In order to kick off interrupts for the USB module, in our main program we turn on interrupts from the USB module:&lt;br /&gt;&lt;span style=";font-family:courier new;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;turn_usb_ints_on();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;turn_global_ints_on();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;Finally, to actually start the USB module doing its things, we call usb_enable_module().&lt;br /&gt;&lt;span style=";font-family:courier new;"&gt;&lt;br /&gt;void usb_enable_module() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;uir = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;set_bit(ucon, USBEN);    // enable USB serial interface engine (SIE)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;usb_state = st_DEFAULT;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Here we clear any previously triggered interrupts, enable the USB SIE module and set our state to Default.&lt;br /&gt;&lt;br /&gt;It’s at this point that all the fun starts.  The SIE now attaches to the bus by pulling one of the data lines high, and negotiations begin.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-1719200275629096845?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/1719200275629096845/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=1719200275629096845' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/1719200275629096845'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/1719200275629096845'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2009/01/usb-part-4-inner-workings-of-picpack.html' title='USB part 4 – Inner workings of the PicPack USB stack'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-8358157229010488641</id><published>2009-01-09T13:26:00.002Z</published><updated>2009-01-09T13:47:30.667Z</updated><title type='text'>USB Part 3 – Configuring the PicPack USB library</title><content type='html'>As a personal preference, I think that state machines are evil and should be avoided like the plague.  Mostly this is because of my view the source code should show precisely what should happen.  State machines are different, since they show what should happen under certain circumstances and they specifically hide the workings of the “machine” as a whole.  It means that the understanding of how the whole system works is in fact “outside of the code”.  You need to know something beyond what is written to comprehend what happens and why.  This makes debugging these systems extremely difficult.&lt;br /&gt;&lt;br /&gt;Despite my misgivings, state machines are excellent at enabling us to create hardware cheaply since it doesn’t need to understand about what it is doing or why – it just needs to respond quickly.  This is (unfortunately) the world we find ourselves in when we start playing with USB.&lt;br /&gt;&lt;br /&gt;Let’s have a look at how pic devices, in combination with the PicPack library handle the tangled web that is USB.  Our first port of call is the config.h file, which is where the PicPack library finds all its configuration details – and the USB library is no exception.  Let’s pull apart the USB section from the Joy Mouse demo. &lt;br /&gt;&lt;span style=";font-family:courier new;font-size:70%;"&gt;&lt;br /&gt;#define USB_HIGHEST_EP 1&lt;/span&gt;&lt;br /&gt;In order to configure the appropriate data structures, the library needs to know what the highest end point number will be.  In this case, it’s endpoint 1.&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:70%;"&gt;&lt;br /&gt;// #define USB_SELF_POWERED&lt;br /&gt;#define USB_BUS_POWERED&lt;/span&gt;&lt;br /&gt;Is the device powered from the USB supply? Select your option here.  This changes what the pic reports upstream when queried.&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:70%;"&gt;&lt;br /&gt;#define USB_EP0_OUT_SIZE    8&lt;br /&gt;#define USB_EP0_OUT_ADDR    0x0500&lt;br /&gt;#define USB_EP0_IN_SIZE        8&lt;br /&gt;#define USB_EP0_IN_ADDR    0x0508&lt;br /&gt;&amp;nbsp;&amp;nbsp;#define USB_EP1_IN_SIZE        8&lt;br /&gt;#define USB_EP1_IN_ADDR    0x0510&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Here it starts to get a little more complex.  Each endpoint for IN and OUT transactions has its own buffer.  For each endpoint IN and endpoint OUT you need to decide how big transactions can be, and where the buffer will be located.  You’ll need to check out the datasheet for your particular pic.  In the case of the 18f4550, 0x0500 is a good place to start all the buffers.  You can see they run sequentially from there.  Eight bytes is just plenty for a mouse.  Since we have only an IN endpoint 1 (no OUT), we only declare the IN.&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:70%;"&gt;&lt;br /&gt;//#define USB_CALLBACK_ON_SOF&lt;br /&gt;// if you define it, you'll need to include this routine in your code:&lt;br /&gt;// void usb_SOF_callback(uns16 frame) {&lt;br /&gt;//    }&lt;/span&gt;&lt;br /&gt;Each 1ms, the USB starts a new “frame”.  If you want a nice clean 1ms wake up call without having to use timers, define USB_CALLBACK_ON_SOF and create a function called usb_SOF_callback in your code.&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:70%;"&gt;&lt;br /&gt;//#define USB_CALLBACK_ON_DEVICE_CONFIGURED&lt;br /&gt;// if you define it, you'll need to include this routine in your code:&lt;br /&gt;// void usb_device_configured_callback() {&lt;br /&gt;//    }&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;USB has a state called “configured”.  It means that the host has chosen a particular configuration (usually it has a choice of just one) and the PicPack library has set up the endpoints ready for action.  If you’d like to get notified when this state occurs, define USB_CALLBACK_ON_DEVICE_CONFIGURED in your code and declare usb_device_configured_callback() in your code.&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:70%;"&gt;&lt;br /&gt;#define USB_CALLBACK_ON_CLASS_CTRL&lt;br /&gt;// if you define it, you'll need to include these routines in your code:&lt;br /&gt;//void usb_handle_class_ctrl_read_callback();    &lt;br /&gt;//void usb_handle_class_ctrl_write_callback(uns8 *data, uns16 count);&lt;br /&gt;//void usb_handle_class_request_callback(setup_data_packet sdp);&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;A number of different types of devices are defined by the USB standard.  These are known as class compliant devices.  Just to keep things fun, USB handles some transactions for class devices over endpoint 0 using control transfers.  While the Joy Mouse demo does indeed handle class control transfers, it doesn’t do a lot with them.  For a more complex example, including how to send data back to the host after it has made a request using a control transfer and assuming class ownership of the control transfer, see the serial (CDC) PicPack demo which we’ll cover in the next tutorial.&lt;br /&gt;&lt;br /&gt;If your device needs to handle class control transfers, then define USB_CALLBACK_ON_CLASS_CTRL and declare the appropriate functions.  Note that usb_handle_class_request_callback will be called when a class request has been received and needs action; usb_handle_class_ctrl_read_callback will be called when a transaction sending data to the host (IN) has completed, and usb_handle_class_ctrl_write_callback will be called when a transaction receiving data from the host has occurred.&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:70%;"&gt;&lt;br /&gt;//#define USB_EP_DATA_CALLBACK&lt;br /&gt;// if you define it, you'll need to include these routines in your code:&lt;br /&gt;//void usb_ep_data_out_callback(uns8 end_point, uns8 *buffer_location, uns16 byte_count);&lt;br /&gt;//void usb_ep_data_in_callback(uns8 end_point, uns16 byte_count);&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;To handle data transactions that occur over endpoints other than endpoint 0, that is, non-control transfers, define USB_EP_DATA_CALLBACK.  When a successful data transaction has occurred that received data from the host (OUT), usb_ep_data_out_callback will be called.  You’ll be told the endpoint number, where the buffer is and how many bytes were transferred.  Note that the endpoint will not be re-primed (armed) until you return from this function.  When a successful data transaction has occurred that sent data to the host (IN), usb_ep_data_in_callback will  be called.  The Joy Mouse demo doesn’t use either of these functions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-8358157229010488641?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/8358157229010488641/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=8358157229010488641' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/8358157229010488641'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/8358157229010488641'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2009/01/usb-part-3-configuring-picpack-usb.html' title='USB Part 3 – Configuring the PicPack USB library'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-7864851396998017048</id><published>2008-12-12T12:41:00.002Z</published><updated>2008-12-12T12:42:24.066Z</updated><title type='text'>See Saw Photo</title><content type='html'>A quick note to let people know that if you need the best photographers in Brisbane Australia, go straight to &lt;a href="http://www.seesawphoto.com.au"&gt;See Saw Photo&lt;/a&gt; - run by my brother and his wife.  Their portfolio is amazing, and if you appreciate good photos, it's worth a look just for that.&lt;br /&gt;&lt;br /&gt;A new USB tutorial coming soon!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-7864851396998017048?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/7864851396998017048/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=7864851396998017048' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/7864851396998017048'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/7864851396998017048'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2008/12/see-saw-photo.html' title='See Saw Photo'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-2140795092866361908</id><published>2008-08-05T10:08:00.003+01:00</published><updated>2008-08-05T10:16:37.895+01:00</updated><title type='text'>USB Part 2 - The Joy Mouse</title><content type='html'>In this example, I’m going to show the use of the library with the TechToys USB experimenter’s board.  This is a great board to try these sorts of experiments with – it has an SD card slot to play with mass storage class devices (along with understanding the SD card protocol) and a 5 way joystick, supporting up, down, left, right and select.  This allows us to simulate a mouse with our joystick.  Since the mouse is part of the USB specification that Windows supports without (third party) drivers, this is a nice way to get our feet wet with USB without having to do any hard work on the Windows side.  You could also prototype this circuit using a 18f4550 pic on a breadboard with a few switches if you preferred.&lt;br /&gt;&lt;br /&gt;Let’s look firstly at the way we handle delivering the descriptors to the host.   Pull up the usb_joy_mouse demo and have a look in the usb_config_mouse.c file.  Here’s where all the mouse specific stuff sits to hide it away from the main program.&lt;pre class='code'&gt;&lt;br /&gt;void usb_get_descriptor_callback(uns8 descriptor_type,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;uns8 descriptor_num,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;uns8 **rtn_descriptor_ptr,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;uns16 *rtn_descriptor_size) {&lt;/pre&gt;You have to supply a usb_get_descriptor_callback function in your program.  The PicPack library will call it when it has received a request for a particular descriptor.  Your job is to return a pointer to where to find the descriptor, and how big the descriptor is.&lt;br /&gt;&lt;br /&gt;The standard descriptors are defined in pic_usb.h.  Here’s the device descriptor:&lt;pre class='code'&gt;&lt;br /&gt;typedef struct _device_descriptor {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;uns8    length,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;descriptor_type;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;uns16    usb_version;    // BCD&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;uns8    device_class,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;device_subclass,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;device_protocol;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;uns8    max_packet_size_ep0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;uns16    vendor_id,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;product_id,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;device_release;    // BCD&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;uns8    manufacturer_string_id,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;product_string_id,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;serial_string_id,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;num_configurations;&lt;br /&gt;} device_descriptor;&lt;/pre&gt;Now, the descriptors really are just a chunk of bytes, so you don’t need to use proper C structs like this to hold them.  You could happily use a string of bytes and return a pointer to that along with the length.  The reason we use C structs here is that you are much less likely to make a mistake getting things working.  Once you have things working, feel free to replace the C structs with data structures that take less space or are based in ROM (with appropriate changes to the library).  As always, my motto is get things working, then get them working smaller/faster.  Did you know you can hang Windows by plugging in a device with a dodgy descriptor in it?  I didn’t, until I started this USB work.  Believe me, it’s a frustrating exercise!  Who would have thought that Windows would be so easily duped?  So, in these examples, we always use the structs to ensure we have everything right in the descriptors&lt;br /&gt;&lt;br /&gt;Now, back in usb_config_mouse.c, we define our device descriptor like this:&lt;pre class='code'&gt;&lt;br /&gt;device_descriptor my_device_descriptor = {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sizeof(my_device_descriptor),     // 18 bytes long&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dt_DEVICE,     // DEVICE 01h&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0x0110,    // usb version 1.10&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0,        // class&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0,        // subclass&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0,        // protocol&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8,        // max packet size for end point 0&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0x04d8,    // Microchip's vendor&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0x000C,    // Microchip's product&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0x0200, // version 2.0 of the product&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1,        // string 1 for manufacturer&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2,        // string 2 for product&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0,        // string 3 for serial number&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1        // number of configurations&lt;br /&gt;};&lt;/pre&gt;In our get descriptor callback function, here’s where we return this data:&lt;pre class='code'&gt;&lt;br /&gt;void usb_get_descriptor_callback(uns8 descriptor_type, uns8 descriptor_num,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;uns8 **rtn_descriptor_ptr, uns16 *rtn_descriptor_size) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;uns8 *descriptor_ptr;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;uns16 descriptor_size;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;descriptor_ptr = (uns8 *) 0;    // this means we didn't find it&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;switch (descriptor_type) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case dt_DEVICE:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;serial_print_str(" Device ");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;descriptor_ptr = (uns8 *)&amp;amp;amp;my_device_descriptor;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;descriptor_size = sizeof(my_device_descriptor);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&lt;br /&gt;&lt;/pre&gt;Notice that we use temporary variables for the descriptor pointer and its size.  It’s only at the end of the function that we copy these into the rtn_descriptor_ptr and rtn_descriptor_size.  This saves instructions since the pic instruction set doesn’t make it particularly easy to deal with double-dereferenced data.&lt;br /&gt;&lt;br /&gt;Have a look through the rest of the function.  You can see how we return descriptors for the device, but also notice how when the host requests the configuration descriptor, it actually gets sent the configuration descriptor, the endpoint descriptors along with any class descriptors as well!  The function also returns string descriptors, which are used to identify the device in nice plain language.  Note that the string descriptors are in Unicode – a 16 bit value for each character.  Luckily for us, in English, all you need to do is at a \0 null to each character.  To be fair, almost all USB devices have only English string descriptors.&lt;br /&gt;&lt;br /&gt;Once enumeration has finished, it is simply a matter of sending data when we want to indicate that the mouse has moved or a button has been pressed.  The trick with all USB transfers is that you need to put the data into a buffer before it is requested.  In this case, it is not so much of a problem since the pic will NAK any request for data when the endpoint has not been “primed” (or “armed” – all data loaded into the buffer and the pic USB engine informed that it now has control of the buffer).&lt;br /&gt;&lt;br /&gt;The host will ask for data at the interval specified in the descriptors.  This does mean that there’s a time gap between when we want to send data and when it actually gets requested.  This is the side-effect of a system where the host controls all the transfers.  This latency is not going to be noticed for mice or keyboards, but can make a difference for time-critical transfers like MIDI data or even serial data.  You can send a bunch of data really quickly – but only so often.&lt;br /&gt;&lt;br /&gt;In any case, getting back to the joy mouse, notice that we&lt;pre class='code'&gt;&lt;br /&gt;clear_bit(intcon2, RBPU);&lt;br /&gt;&lt;/pre&gt;which turns on the weak pull-up resistors for port B inputs, which we then make inputs by:&lt;pre class='code'&gt;&lt;br /&gt;make_input(JOY_PORT, UP_PIN);&lt;br /&gt;make_input(JOY_PORT, DOWN_PIN);&lt;br /&gt;make_input(JOY_PORT, LEFT_PIN);&lt;br /&gt;make_input(JOY_PORT, RIGHT_PIN);&lt;br /&gt;make_input(JOY_PORT, CENTER_PIN);&lt;br /&gt;&lt;/pre&gt;and kick off the whole USB excitement by:&lt;pre class='code'&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;usb_setup();&lt;br /&gt;&lt;/pre&gt;Nothing will happen from a USB perspective until we enable the USB module:&lt;pre class='code'&gt;&lt;br /&gt;usb_enable_module();&lt;/pre&gt;This routine allows you to “soft-insert” the device.  It can be plugged in, powered and running, but only when you enable the USB serial interface module, will the USB side of things kick into life.&lt;br /&gt;&lt;br /&gt;When there has actually been some joystick movement or the select button pressed or released, this data is sent to the PC using the usb_send_data routine:&lt;pre class='code'&gt;usb_send_data(1, (uns8 *)&amp;amp;amp;buffer, 3, /*first*/ 0); // ep 1&lt;/pre&gt;&lt;br /&gt;The first parameter is the endpoint number.  In this case, we’re sending data from endpoint 1.  We also pass a pointer to the buffer, the size of the buffer, and a helper to indicate whether this transfer is the first one.  This is important since USB uses two alternating packet types (DATA0 and DATA1) when sending data so that it knows if one was lost.  The PicPack library sets up endpoints so that you normally don’t need to know if you’re sending the first packet or not (the data packet type is set to the DATA1 one on initialisation, so that before the first packet is sent, it is toggled to become DATA0.  However, there may be occasions that you need to force the packet data type back to DATA0, in which case, pass 1 for the last parameter.&lt;br /&gt;&lt;br /&gt;The JoyMouse implements everything USB-wise that is absolutely required, and nothing that isn’t.  You can plug a JoyMouse into both Windows and Linux and it will work perfectly fine. In the next tutorial, we’ll dig a little deeper into the PicPack usb library.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-2140795092866361908?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/2140795092866361908/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=2140795092866361908' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/2140795092866361908'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/2140795092866361908'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2008/08/usb-part-2-joy-mouse-in-this-example-im.html' title='USB Part 2 - The Joy Mouse'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-8113643153636042859</id><published>2008-07-28T10:10:00.001+01:00</published><updated>2008-07-28T10:10:59.556+01:00</updated><title type='text'>USB part 1 - Introduction</title><content type='html'>The USB consortium claims that there are about 2 billion USB devices in the world.  I think they’re wrong. I think it’s easily ten times that.  It is truly one of the few universal success stories for interconnection between devices and computers.&lt;br /&gt;&lt;br /&gt;When you have a look at the USB specification however, and its implementation for particular devices, you don’t have to read too much to realise that the specification has an extremely confusing nomenclature and even the standard “class” definitions work in different ways to each other.  The other practical aspect that makes USB work difficult is that because everything happens in real time and we’re utilising fundamentally slow devices.  So in order to make things happen quickly, everything is set up in advance, and then we’re told about the result after the fact.  For example, we don’t get a request for some data, then make a call somehow to make that data available to the host.  In fact, what happens is that we make the data available in advance of the host requesting it, and we find out afterwards that it grabbed it.&lt;br /&gt;&lt;br /&gt;This means that USB debugging is a pretty tricky business.  I don’t mean to dissuade you from having a go – the examples in the PicPack library work should make it pretty easy for you to get up and going pretty quickly, especially if all you need is some sort of serial connection.  A lot of work has gone into the USB portion of the PicPack library to get things working and make it easy for you to incorporate USB functionality into your products.&lt;br /&gt;&lt;br /&gt;But first, we need to understand a little about USB.&lt;br /&gt;&lt;br /&gt;I’m not going to go into a full explanation here – there’s tonnes of information on the web and if you’re even vaguely serious about the topic, grab yourself a copy of Jan Axelson’s USB Complete book.  It’s one of the best computer books I’ve ever bought.  What I am going to do here is to cover the basics so you have enough information to work with.&lt;br /&gt;&lt;br /&gt;First of all, the way that the USB system works entails the PC (or host) making requests, and the devices giving responses.  Even when devices have something they need to send to the host, the host has to ask for it first.  In this way, all the devices can share a common bus – they only speak when spoken to.&lt;br /&gt;&lt;br /&gt;If you’re familiar at all with TCP/IP you’ll know that a device has an IP address (eg 192.168.1.3) and address are allocated (like DCHP) to each device.  Given that a PC and its devices is a closed system, addresses start at 1 and go up to 127.  This is the device number.&lt;br /&gt;&lt;br /&gt;In TCP/IP, and each address is broken up into a number of “ports”.  In USB land, this concept of ports is called “endpoints”,   Endpoint 0 is a special endpoint; its purpose is (generally) to exchange information about the device itself.  Other endpoints have purposes based on the device functionality.  An endpoint can receive data from the host (called an OUT endpoint) or send data to the host (called an IN endpoint).  These “in” and “out” definitions are named from the perspective of the host.&lt;br /&gt;&lt;br /&gt;Endpoint 0 is a bidirectional pipe and must exist for every USB device.  There can be up to 16 endpoints, but generally only a couple beyond endpoint 0 are ever actually used.&lt;br /&gt;&lt;br /&gt;The USB system, like many systems that are designed by committee, covers many possibilities that are not often used in real life.  Each device can have a number of different “configurations” of which the host can chose which one to use.  While the information supplied as part of the configuration is important, I can’t think of many devices that have multiple configurations (a mobile phone may well use this if it can be a mass storage device or a modem depending on what is requested).&lt;br /&gt;&lt;br /&gt;A given configuration can have a number of “interfaces”.  In the USB serial port emulator for example, there is an interface that handles the control of the port itself (ie, baud rate, stop bits etc) and an interface for the actual exchange of RS-232 data.  Each of these interfaces are associated with one or more of the endpoints available.&lt;br /&gt;&lt;br /&gt;In summary – a device has (usually) one configuration, which has at least one interface, which has associated with it one or more endpoints.&lt;br /&gt;&lt;br /&gt;When a USB device is first plugged in, the host and the device go through a process known as “enumeration”.  This is how the host finds out about the capabilities of the device and loads whatever drivers are required; the device can also find out how the host wants to handle things.  Enumeration takes place using what are called “control transfers”.  These are the most complex aspect of anything to do with USB programming.  Thankfully, the PicPack library handles the difficult parts of this for you.&lt;br /&gt;&lt;br /&gt;Enumeration involves the delivery to the host of data structures that describe what a device is and how it works.  These structures are called “descriptors”.  You’ll find descriptors for the device as a whole, the configuration(s), interfaces and the end points themselves.  Depending on the particular device, there are often extra descriptors that are specific to a particular class of device (eg, a serial port emulation, or a human interface device).&lt;br /&gt;&lt;br /&gt;Like most of the PicPack components, pic_usb does the hard work of handling the common cases, leaving you to implement the logic that makes your device different from everything else.  In the next tutorial, we’ll look at how the library works.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-8113643153636042859?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/8113643153636042859/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=8113643153636042859' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/8113643153636042859'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/8113643153636042859'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2008/07/usb-part-1-introduction.html' title='USB part 1 - Introduction'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-1271992968390912028</id><published>2008-07-22T09:47:00.002+01:00</published><updated>2008-07-22T09:49:21.715+01:00</updated><title type='text'>New PicPack - with USB support - RC1</title><content type='html'>I've made available the first release candidate for the new version of the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;PicPack&lt;/span&gt; library.  It has support for &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;USB&lt;/span&gt; pics, including examples of a mouse and a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;USB&lt;/span&gt; serial port.&lt;br /&gt;&lt;br /&gt;It needs some tidying up, documenting and no doubt, bug fixes, but I wanted to make it available to the adventurous to have a play with and give me some feedback - much appreciated guys.&lt;br /&gt;&lt;br /&gt;Enjoy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-1271992968390912028?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/1271992968390912028/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=1271992968390912028' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/1271992968390912028'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/1271992968390912028'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2008/07/new-picpack-with-usb-support-rc1.html' title='New PicPack - with USB support - RC1'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-131393958874927365</id><published>2008-06-15T16:01:00.006+01:00</published><updated>2008-12-09T08:54:30.760Z</updated><title type='text'>New toys - Maplin Mobile Power Pack</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_bEFwpcEs1Go/SFUvtkRvghI/AAAAAAAAAB4/ivnLVa6-03g/s1600-h/pack1.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 155px; height: 199px;" src="http://1.bp.blogspot.com/_bEFwpcEs1Go/SFUvtkRvghI/AAAAAAAAAB4/ivnLVa6-03g/s320/pack1.jpg" alt="" id="BLOGGER_PHOTO_ID_5212124603629928978" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;I found a neat device in Maplin the other day.  It's meant to be a power pack for recharging things like your phone or your iPod.  It's very slim and has a mini-B USB plug which is used for charging the pack and also as an outlet to charge your phone etc.  The specifications say that it's 2000mAh, which given the output is 5v, is not bad at all.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;But was it really giving 2000mAh at 5V? Well, there's only one way to find out...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Aha! It's 2000mAh at 3.7v.... Just as I thought. Then there's a boost circuit to bump it up to 5v.  So, I make it at ab&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_bEFwpcEs1Go/SFUv_0WCaiI/AAAAAAAAACA/nF-P54bdYAU/s1600-h/IMGP4822.JPG"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 283px; height: 187px;" src="http://1.bp.blogspot.com/_bEFwpcEs1Go/SFUv_0WCaiI/AAAAAAAAACA/nF-P54bdYAU/s320/IMGP4822.JPG" alt="" id="BLOGGER_PHOTO_ID_5212124917180557858" border="0" /&gt;&lt;/a&gt;out 1480mAh at 5v (actually it would be somewhat less due to it not being 100% efficient).  Still, that's not a bad little power pack.&lt;br /&gt;&lt;br /&gt;It also comes with a very small mains charger - which also has a mini-B USB connector on it.&lt;br /&gt;&lt;br /&gt;They're on sale at the moment for £9.99, which is pretty good for a mains 5V supply, and 5V battery source.  I bought three, since I knew that their real purpose in life was not in fact to recharge iPods, but really....to power prototyping boards!&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_bEFwpcEs1Go/SFUxsHH004I/AAAAAAAAACI/plBiLCLuYf8/s1600-h/IMGP4823.JPG"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://4.bp.blogspot.com/_bEFwpcEs1Go/SFUxsHH004I/AAAAAAAAACI/plBiLCLuYf8/s400/IMGP4823.JPG" alt="" id="BLOGGER_PHOTO_ID_5212126777647092610" border="0" /&gt;&lt;/a&gt;See Maplin's website for the &lt;a href="http://www.maplin.co.uk/Search.aspx?criteria=n62fx&amp;amp;source=15&amp;amp;SD=Y"&gt;N62FX&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-131393958874927365?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/131393958874927365/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=131393958874927365' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/131393958874927365'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/131393958874927365'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2008/06/new-toys-maplin-mobile-power-pack.html' title='New toys - Maplin Mobile Power Pack'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_bEFwpcEs1Go/SFUvtkRvghI/AAAAAAAAAB4/ivnLVa6-03g/s72-c/pack1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-6904017282763040057</id><published>2008-05-19T14:24:00.013+01:00</published><updated>2008-05-21T13:47:44.199+01:00</updated><title type='text'>18. All meshed up – Part 4 – Working in code</title><content type='html'>Finally, we’ll have a look at how the packet routines are called.  The best place to start is the pic_packet.h file, where we find the definitions of the config parameters and status messages.  Pull up the packet demo project and open the pic_packet.h file.  Here are the things we need to set in our config.h:&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;&lt;br /&gt;// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -&lt;br /&gt;&lt;br /&gt;// pic_packet defines&lt;br /&gt;&lt;br /&gt;// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;You’ll need as big a transmit queue as possible, but this really depends on how many close nodes you’ll have in the mesh:&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;&lt;br /&gt;#define PKT_TX_QUEUE_SIZE 5&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The “Seen List”, is surprisingly, a list of all the packets that we have seen (that are destined for us).  The smaller the seen list, the more likely that we’ll think that a packet is new when it’s not, that is, the smaller the seen list, the more likely we’ll see duplicate packets.&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;&lt;br /&gt;#define PKT_SEEN_LIST_SIZE 5&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Send Max Tries is the number of times a node will try and send a packet to the destination.  The first time is always a direct send, after that, all other tries are routed sends.  Of course, higher retry counts mean the packet spends more time taking up space in the TX queue as well.&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;&lt;br /&gt;#define PKT_SEND_MAX_TRIES 4&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;As we’ll see later, the tick time for packet fun should be about 0.25ms.  In the packet example we set a resend delay of 10,000 ticks – or about 2.5 seconds.  In real life, this is way too large, but for demo purposes, it allows us to understand how the packet network works.  You should set this delay based on the speed of transmission and the possible number of hops in your mesh to the destination node.  Remember, even in ideal conditions you need to transmit the packet through three intermediaries to the destination, then the destination node needs to send a packet back in the same way.  It should be as small as possible, of course, but the best value will be found by experimentation.&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;&lt;br /&gt;#define PKT_RESEND_TICK_DELAY 10000&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The payload is the data that actually makes it to the other end.  This delivery system is designed to handle small messages – not large data transfers. 8 bytes might not sound like a lot, but for controlling lights, sending temperature readings, time and date and status checks, it’s really plenty.  It’s a stack bigger than what X10 can move around.  You can, of course make this as large as your given transceiver can cope with.  The protocol we’ll layer on top of the packet network, however, expects a payload size of at least 8.&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100;"  &gt;&lt;br /&gt;#define PKT_PAYLOAD_SIZE 8&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;There are a couple of callbacks that are not enabled in this demo, but can be defined when you want your code to control a little more of what goes on. You can get a call back when a send fails:&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;&lt;br /&gt;// Define if you want to get a callback on send failure&lt;br /&gt;// #define PKT_CALLBACK_ON_SEND_FAILED&lt;br /&gt;// if you define it, you'll need to include this routine in your code:&lt;br /&gt;// void pkt_send_failed_callback(uns16 dest_addr, uns16 pkt_id) {&lt;br /&gt;//    }&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Or when a send succeeds:&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;&lt;br /&gt;// Define if you want to get a callback on send success&lt;br /&gt;// #define PKT_CALLBACK_ON_SEND_SUCCEEDED&lt;br /&gt;// if you define it, you'll need to include this routine in your code:&lt;br /&gt;// void pkt_send_succeeded_callback(uns16 dest_addr, uns16 pkt_id) {&lt;br /&gt;//    }&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The packet delivery system expects at this stage to be running on a Nordic nRF2401A or a nRF24L01 chip.  You can mix these interchangeably on the same network, but a given node can of course use only use one or the other.  Define one of them here:&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;&lt;br /&gt;// define one or other of these:&lt;br /&gt;#define PKT_USE_2401A&lt;br /&gt;//#define PKT_USE_24L01&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;And lastly, define the level of debug you want.  Note that more debug means more serial_print_str statements, which means much larger code size.&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;&lt;br /&gt;// define if you want debug&lt;br /&gt;//#define PKT_DEBUG&lt;br /&gt; // define if you want high amounts of debug&lt;br /&gt;//#define PKT_DEBUG_HIGH&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;I’m assuming here that you also have #defines in the config.h file for the RF chipset – this has been covered in a previous tutorial.&lt;br /&gt;&lt;br /&gt;Unlike other PicPack libraries we’ve used before, there’s no “setup” routine for the packet library.  The setup routine normally gets the ports and pins set up correctly as inputs or outputs, ready for communication with the outside world.  This library talks to the world via the RF library, so it doesn’t need to set up any ports and pins itself.  It does have an “init” routine though, which is used in a library to get any internal data set to the right values and initialise communication with a device so that it’s ready for use.&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;&lt;br /&gt;pkt_init(my_addr, last_pkt);&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;pkt_init gets the packet delivery system ready for use.  It stores the address given as the local node’s address, and also stores the last pkt ID.  All the transmit and last seen queues are cleared and everything is set ready for packet reception or delivery.&lt;br /&gt;&lt;br /&gt;So what happens when a chunk of RF data actually arrives?  Well, assuming we’re using a SparkFun Terminal Development Node (TDN), you’ll remember that we tied the DR1 line to the PortB, pin 0.&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;&lt;br /&gt;set_bit(intcon, INTE);    // Enable interrupts on rb0&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The default for the port B, pin 0 interrupt is that it is triggered on a rising edge, that is, when the input signal goes from low to high.  Perfect for us, so no changes are required here.&lt;br /&gt;&lt;br /&gt;In the packet demo, a routine called configure_pkt() does the work of getting the packet delivery system in order, ready for us.&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;&lt;br /&gt;void configure_pkt() {&lt;br /&gt;uns16 my_addr;&lt;br /&gt;uns16 last_pkt;&lt;br /&gt;    my_addr = eeprom_read(EE_MY_ADDR_H);&lt;br /&gt;    my_addr &amp;lt;&amp;lt;= 8;&lt;br /&gt;    my_addr |= eeprom_read(EE_MY_ADDR_L);&lt;br /&gt;    last_pkt = eeprom_read(EE_MY_LAST_PKT_ID_H);&lt;br /&gt;    last_pkt &amp;lt;&amp;lt;= 8;&lt;br /&gt;    last_pkt |= eeprom_read(EE_MY_LAST_PKT_ID_L);&lt;br /&gt;    serial_print_str("My addr: ");&lt;br /&gt;    serial_print_int_hex_16bit(my_addr);&lt;br /&gt;    serial_print_nl();&lt;br /&gt;    serial_print_str("Last pkt: ");&lt;br /&gt;    serial_print_int_hex_16bit(last_pkt);&lt;br /&gt;    serial_print_nl();&lt;br /&gt;    pkt_init(my_addr, last_pkt);&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Essentially, this just pulls the address and last packet ID sent from the eeprom and calls pkt_init.  It also prints out the local address and last packet ID – not essential, but very, very handy!   Okay, so the packet system is all ready for use, let’s see what happens when the nRF2401A lets us know that a packet has arrived.  It does this by taking the IRQ line high, which results in the INT (Port B, pin 0) being triggered.  Here’s the interrupt routine:&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;&lt;br /&gt;void interrupt( void ) {&lt;br /&gt;    timer_handle_0_isr();&lt;br /&gt;        if ( test_bit(intcon, INTF) ) {&lt;br /&gt;            if (pkt_receive_level &amp;lt; MAX_PACKET_QUEUE) {    // if we're not already processing a receive&lt;br /&gt;                  if (pkt_receive_level == 0) {&lt;br /&gt;                        pic_rf_receive(rf_rx_buffer, PKT_PACKET_SIZE);&lt;br /&gt;                  } else {&lt;br /&gt;                      pic_rf_receive(rf_rx_buffer2, PKT_PACKET_SIZE);&lt;br /&gt;                }&lt;br /&gt;                pkt_receive_level++;&lt;br /&gt;          } else {&lt;br /&gt;                dropped_packet++;&lt;br /&gt;          }  &lt;br /&gt;          clear_bit( intcon, INTF);&lt;br /&gt;      }    // pkt available interrupt&lt;br /&gt;        serial_handle_tx_isr();&lt;br /&gt;      serial_handle_rx_isr();&lt;br /&gt;     }&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The PKT_FLAG_RESEND is used to indicate that you want the system to resend the packet if it doesn’t get through, up to the maximum number of tries you’ve set in your config.h file.  This is the usual case.  In normal circumstances, it’s only acknowledgements that get sent using PKT_FLAG_NO_RESEND – and these are taken care of automatically.&lt;br /&gt;&lt;br /&gt;That’s it! Not much code required to build your own meshed packet network.  Next exciting episode, we’ll look at how we can put an application layer on top of this system for the purpose of delivering actual data across the network.  We’ll turn a SparkFun TDN into a remote temperature sensor and display the temperature on the base station on an LCD screen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-6904017282763040057?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/6904017282763040057/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=6904017282763040057' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/6904017282763040057'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/6904017282763040057'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2008/05/17-all-meshed-up-part-4-working-in-code.html' title='18. All meshed up – Part 4 – Working in code'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-799931940360313460</id><published>2008-05-16T12:53:00.003+01:00</published><updated>2008-05-16T13:22:06.432+01:00</updated><title type='text'>PicPack 1.2 released</title><content type='html'>PicPack 1.2 has been released! You'll need this version for the complete packet tutorial.&lt;br /&gt;&lt;br /&gt;Many thanks to Peter Lawson in sunny South Australia who helped tirelessly getting the BoostBloader running on a new class of Pic chips.  With his help, the BoostBloader now supports 16f88, 16f876a, 16f877a, 18f252, 18f452, 18f2620, and 18f4520.  It should be quite easy to add other pics as well, I'll write a tutorial about doing that shortly.&lt;br /&gt;&lt;br /&gt;Enjoy!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:courier new;" &gt;Version 1.2&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:courier new;" &gt;-----------&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;16 May 2008&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:courier new;" &gt;pic_pack_lib&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ds1631.c&lt;br /&gt;&lt;br /&gt;Rewrote to use i2c base library&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;packet.c\.h&lt;br /&gt;&lt;br /&gt;General update, documentation, a few logic errors fixed,&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; new callbacks, functions better named&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;pic_serial.c\.h&lt;br /&gt;&lt;br /&gt;Added 16bit hex print routine&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;Pic_utils.c\.h&lt;br /&gt;Added support for 18f452 for turn_analog_inputs_off()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;protocol.h&lt;br /&gt;&lt;br /&gt;Tidied up, moved to bit positions to indicate capabilities,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  expanded relay and dimmer options &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:courier new;" &gt;demos&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;packet&lt;br /&gt;&lt;br /&gt;All new meshed packet demo, based on SparkFun Terminal Development&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  Node (TDN), but will work on your breadboard of course as well. See tutorial &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;on the website&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:courier new;" &gt;Boostbloader/Screamer&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Support for pics that have a write chunk smaller than 16 bytes (older 18f types)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-799931940360313460?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/799931940360313460/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=799931940360313460' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/799931940360313460'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/799931940360313460'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2008/05/picpack-12-released.html' title='PicPack 1.2 released'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-8229866278101267454</id><published>2008-05-16T09:49:00.006+01:00</published><updated>2008-12-09T08:54:31.140Z</updated><title type='text'>17. All meshed up – Part 3 – Packet chatting</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_bEFwpcEs1Go/SDQZPI1oJWI/AAAAAAAAABM/r8NVHAFOYqs/s1600-h/tdn.jpg"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer;" src="http://3.bp.blogspot.com/_bEFwpcEs1Go/SDQZPI1oJWI/AAAAAAAAABM/r8NVHAFOYqs/s320/tdn.jpg" alt="" id="BLOGGER_PHOTO_ID_5202811217380910434" border="0" /&gt;&lt;/a&gt;Enough theory.  Let’s get our delivery network on the road.  Rather than look at the code in this episode (boring), let’s jump straight in and get our nodes chatting.  Time enough to see how the code works later.&lt;br /&gt;&lt;br /&gt;The packet demo is designed to run on the Sparkfun Terminal Development Nodes (TDNs), which are a very handy piece of gear for testing this all out.  They have an RS232 connection on one end, a socket for the nRF2401a / nRF24L01 module on the other and a 16f88 in the middle plus a few leds, which help us know a little of what’s going on.  Of course you can run this demo on a breadboard with an nRF module or if you’re feeling adventurous, write some code to support a different RF module all together.  There are a bunch out there, do send your code in to include in the library if you get something working.  I’m pretty interested in seeing some of the CC2500-based modules going, which are similar in nature to the Nordic ones (but are cheaper and have carrier detection – hooray!) or the modules from the fabulous Futurlec (even cheaper, carrier detection but fascinatingly obscure datasheets – fun!).&lt;br /&gt;&lt;br /&gt;For the purpose of this experiment, however, I’ll assume you’ve got a couple of SparkFun TDN (Terminal Development Node) and Nordic modules and a couple of serial ports (USB to serial converters will work fine) or a couple of computers with a serial port each.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_bEFwpcEs1Go/SDQYkI1oJVI/AAAAAAAAABE/SK7uNRH_EFs/s1600-h/square_pad.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://3.bp.blogspot.com/_bEFwpcEs1Go/SDQYkI1oJVI/AAAAAAAAABE/SK7uNRH_EFs/s320/square_pad.jpg" alt="" id="BLOGGER_PHOTO_ID_5202810478646535506" border="0" /&gt;&lt;/a&gt;The first step, naturally, is to get Boostbloader downloaded onto the 16f88 on each TDN.  You’ll need the little mini adapter from SparkFun in order to reach their mini-ICSP connector.  See the 5 holes together in the middle of the board? That's the ICSP "socket".  Make sure you work out which way round the connector goes – pin 1 is designated by the square pad.  The datasheet shows how this is connected, but it’s a pain having to check the datasheet every time you want to use the ICSP connector. Remember: 1 is square.&lt;br /&gt;&lt;br /&gt;Once this is done and you’ve confirmed the Boostbloader is doing its thing by downloading a flashing-led test app of your choice (a see the PicPack demo directory if you’re feeling unadventurous), it’s time to look at the packet demo and how it works.  Download the “packet” demo into the 16f88 and get ready for some wireless magic.&lt;br /&gt;&lt;br /&gt;The 256 bytes of EEPROM in the 16f88 is a great place for a small amount of persistent data. In this example we use it for storing the address of the node, and the ID of the last packet sent.&lt;br /&gt;&lt;br /&gt;In the mini terminal mode, there are several commands that we’ll use to control the node. The first is the “w” command, which allows you to set EEPROM bytes at runtime.  The first two digits specify the memory location and the third and fourth digits specify the value you want to set it to. “w0523”, for example, sets EEPROM location 0x05 to the value of 0x23 (all values in hex).  In our case, we want to set the address of the node and the last sent packet ID like this: &lt;pre class="code"&gt;&lt;br /&gt;w0000&lt;enter&gt;&lt;br /&gt;w0101&lt;enter&gt;&lt;br /&gt;w02ff&lt;enter&gt;&lt;br /&gt;w03ff&lt;enter&gt;&lt;/enter&gt;&lt;/enter&gt;&lt;/enter&gt;&lt;/enter&gt;&lt;/pre&gt;You only need to do this once.  The first two memory locations (00 and 01) store the local address; in this case we’re storing a 16 bit value of 0x0001.  The third and fourth EEPROM memory locations hold the ID of the last packet we sent.  In a more complete example later on, we’ll see how we update this with the last packet ID over time.  For the moment, setting it to 0xffff as we do here is fine.  This means the first packet this node sends will have an ID of 0x0000, so this is great for understanding what’s going on.&lt;br /&gt;&lt;br /&gt;Set your other node to an address of something else other than 0x0001 (I suggest 0x0002), and also set its last sent packet ID to 0xffff.&lt;br /&gt;&lt;br /&gt;Right, so now you have two nodes up and running and ready to communicate.  One is set to address 0x0001 and the other is set to 0x0002.  You can check that these addresses are stored correctly by resetting the TDN (by pressing the reset button) and seeing the serial terminal program come up with something like:&lt;pre class="code"&gt;&lt;br /&gt;My addr: 01&lt;br /&gt;Last pkt: 65535&lt;br /&gt; Pkt demo&lt;br /&gt;&lt;17:10:36&gt;&lt;br /&gt;&lt;/pre&gt;Now it’s time to send a payload from one to the other.  Here we’ll send a dummy payload that in future we’ll use to query the temperature on another node.  Don’t worry about what’s in the payload for the moment, we’re more interested in seeing a packet make it’s way to the destination and get an acknowledgement back.  Go to the terminal connected to your 0x0001 node and type:&lt;pre class="code"&gt;&lt;br /&gt;s02&amp;lt;enter&amp;gt;&lt;/pre&gt;This sets the “send to” (destination) address to 0x0002.  This demo is slightly slack by only allowing 8 bit address entry, but I’m sure this won’t bother you with only two nodes right now. This setting of the send address needs to be done whenever you boot.&lt;br /&gt;&lt;br /&gt;Now, let’s send a packet. Type:&lt;pre class="code"&gt;&lt;br /&gt;x&amp;lt;enter&amp;gt;&lt;/pre&gt;This should send a packet to the specified destination address (0x0002).  Since we only have two nodes right now and hopefully they’re quite close, you should find that node 0x0002 responds pretty much immediately.  This is what you should see on the node 0x0001 terminal:&lt;pre class="code"&gt;&lt;br /&gt;&amp;gt;s02&lt;br /&gt;S: 2&lt;br /&gt;&amp;gt;x&lt;br /&gt;&amp;gt;Send...&amp;lt;Snd good to 0002 id 0000&amp;gt;  RX:5&lt;/pre&gt;And here’s what you should see on the node 0x0002 terminal:&lt;pre class="code"&gt;&lt;br /&gt; &amp;lt;&amp;lt;s: 01p: 06 01 FF FF FF FF BF FF &amp;gt;&amp;gt;  RX:3 &lt;/pre&gt;So what’s the deal about these numbers?  The demo prints out the return values from the functions that get called.  We won’t worry about the functions themselves and what they do right now, but we will look at these values, since they reveal the inner workings of the system.  Have a look at pic_packet.h for the #define definitions.&lt;br /&gt;&lt;br /&gt;RX:3 - A value of ‘3’ on reception means “PKT_STATUS_PKT_IS_FOR_ME”.  It’s a real packet and we haven’t seen it before.  We can happily act on this packet.  In this demo our “acting” on this packet just involves printing it out to see what we’ve got.  You can see the packet was sent from a source address of 01, and had a payload of 06 01 FF FF FF FF BF FF.&lt;br /&gt;&lt;br /&gt;RX: 5 - A value of ‘5’ on reception means “PKT_STATUS_PKT_IS_FACK_FOR_ME”.  It means we’ve received an acknowledgement and found that it is for a packet we’ve sent.  That is, we have successfully confirmed delivery of a packet. Woohoo! We’ve just sent our first packet.&lt;br /&gt;&lt;br /&gt;If everything is correct and there are no transmission problems, these are pretty much the only values that you’re going to see with a two-node mesh.  Not much of a mesh, really.  However, we can simulate what happens in the mesh to help us understand how it works in this simple case.  Do note that in this example, the delay between retries has been set deliberately, excruciatingly large so that you can clearly see what’s going on.&lt;br /&gt;&lt;br /&gt;Set the sending (destination) address of the 0x0001 node to a node that you know is not on your network (eg, 0x0003) by typing:&lt;pre class="code"&gt;&lt;br /&gt;s03&amp;lt;enter&amp;gt;&lt;/pre&gt;Now from the 0x0001 node try and send a packet to node addressed 0x0003 by typing:&lt;pre class="code"&gt;&lt;br /&gt;x&amp;lt;enter&amp;gt;&lt;/pre&gt;Now, remember from our previous tutorial that we will first try and send to node 0x0003 directly (a “direct send”).  You’ll see that node 0x0002 reports a status of PKT_STATUS_DIRECT_SEND (6).  This means that it has received the packet, but will not rebroadcast it since the originating node tried to send it directly (no routing).&lt;br /&gt;&lt;br /&gt;Since the first packet never got to its destination (an acknowledgement was  not received), the node will try to send it again.  On the next try however, our node 0x0001 will try and route the packet via anyone that’s listening (a “routed send”).  In this simple case, we know that node 0x0002 is listening.  Node 0x0002 should respond with PKT_STATUS_NEED_TO_REBROADCAST (9).  So 0x0002 rebroadcasts to try and get it to 0x0003 (of course, it doesn’t know that 0x0003 doesn’t exist on our little network).&lt;br /&gt;&lt;br /&gt;Now here’s where it gets a bit tricky, but once you’ve got your head around this, you’ll be well on your way to understanding how this all works.&lt;br /&gt;&lt;br /&gt;To recap up to this point:&lt;br /&gt;&lt;br /&gt;0x0001 has tried to send directly to 0x0003&lt;br /&gt;0x0002 saw it and printed PKT_STATUS_DIRECT_SEND (6) showing that it decided to ignore the packet (it saw that it’s a direct send not destined for itself)&lt;br /&gt;…in time…&lt;br /&gt;0x0001 tried again, this time routing via anyone that’s listening (not a direct send)&lt;br /&gt;0x0002 saw it and responded PKT_STATUS_NEED_TO_REBROADCAST (9), and rebroadcast the packet out to anyone listening (hopefully it can reach 0x0003, or at least someone closer to 0x0003)&lt;br /&gt;&lt;br /&gt;Now at this point, 0x0001 should receive this rebroadcast.  But it’s the one that sent the packet in the first place!  So it should respond with PKT_STATUS_I_AM_SENDER (2) and ignore the packet.&lt;br /&gt;&lt;br /&gt;Finally, 0x0001 will give up, printing out &lt;pre class="code"&gt;&lt;br /&gt;&amp;lt;Send failed to 0003 id 0001&amp;gt;&lt;/pre&gt;to show that we’ve had a failed send.&lt;br /&gt;&lt;br /&gt;This confirms that 0x0002 has tried to pass the packet on deeper into the mesh, and also confirmed that 0x0001 is happily ignoring this bounce-back. Of course since our imaginary 0x0003 never received the packet, our originating node will try once more.  Our plucky little node 0x0002 tries again to forward on into the mesh, but alas, the packet never makes it. If you have no friends, they’re not going to answer, not matter how many times you call.&lt;br /&gt;&lt;br /&gt;Clear this is all complete overkill for two nodes (although you do get retries and acknowledged delivery for free).  Once you get three or more nodes where some nodes can’t see all the others, I hope you’ll see how powerful this can be for delivering short messages.  Next time we’ll have a look at the calls into this library and how they work, finishing our series on the provided packet delivery system works – then later we’ll also cover some implementations of the system, in the first instance delivering temperature data from different nodes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-8229866278101267454?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/8229866278101267454/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=8229866278101267454' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/8229866278101267454'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/8229866278101267454'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2008/05/all-meshed-up-part-3-packet-chatting.html' title='17. All meshed up – Part 3 – Packet chatting'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_bEFwpcEs1Go/SDQZPI1oJWI/AAAAAAAAABM/r8NVHAFOYqs/s72-c/tdn.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-1937034099490490057</id><published>2008-05-13T16:52:00.003+01:00</published><updated>2008-05-21T13:47:11.615+01:00</updated><title type='text'>16. All meshed up - Part 2 - Packet network basics</title><content type='html'>Now we’ve worked out how to get a chunk of data from one place to another without any wires, it’s time to look at how the PicPack packet network actually works.  In the next enthralling instalment we’ll get the actual packet network up and running in code.&lt;br /&gt;&lt;br /&gt;Okay, so here’s the problem I was trying to solve.  How do you get a message to a device on the other side of the house, reliably?  The distance (with brick walls) is going to be too great for a given, cheap, RF transceiver to reach, but we’re pretty much guaranteed to have devices in between the two – so could we use those as relays?  It would be pretty nice not to have to configure the network (ie, direct exactly how the network gets messages from one place to another) - since the network may change and configuration of little hardware devices is difficult from the other side of the planet.&lt;br /&gt;&lt;br /&gt;So what I wanted was effectively a meshed packet network.  But there’s a catch.  We want to do this as cheaply as possible, not using devices with large chunks of memory, but on something like a 16f88 – 4k instructions, 384 bytes of RAM. Could it be done?&lt;br /&gt;&lt;br /&gt;The trick here is working out a way to discover network routes automatically in small amounts of code.  My first thought was a method by which nodes could ask their neighbours if they knew about the node we wanted to talk to.  And then if they didn’t know, they could ask their neighbours.  Once we had the route, we could store it. Great, so now we’re storing a routing table.  And how long do we store it before we throw it out and have to rediscover again when something has changed? Timewise, by the time we’ve asked all our neighbours to ask their neigbours about the node I want to send to, collected the responses, sorted them, then sent the message, well, this is all getting complicated and memory intensive, along with the next ice age having kicked off.&lt;br /&gt;&lt;br /&gt;Well, it’s all about tradeoffs, as we know from other tutorials. So here’s our strategy.  If our destination node is within range, we’ll send it directly.  It then sends an acknowledgement so we know it arrived safely.  If it’s not within range, we get everyone that can hear us to broadcast the message.  Hopefully, it will be in range of them, and we’ll get an acknowledgement back. In fact, we’ll allow up to three “hops” of rebroadcasts before giving up.&lt;br /&gt;&lt;br /&gt;This does mean we’re going to have a lot of traffic bouncing around at times.  We minimise this by the three hop rule and also by checking to see we haven’t seen this packet recently (if we have, just ignore it).  It will also mean that a packet may find its way by several means to the destination address.  We cope with this by sending an acknowledge back for the first one, and then acting on the packet.  If another copy of the same packet arrives – we realise that the packet has already been received and don’t act on the packet, but we do send another acknowledge back, since this one may have come a second time because the originator didn’t get our first acknowledge.&lt;br /&gt;&lt;br /&gt;It all sounds a little complex, but in use you just set your local address and start sending out packets.  It’s a good project to show how the various parts of the PicPack we’ve seen so far come together.  And despite all this complexity, we have a meshed packet RF network in 3k of code.  Not bad.  That leaves you with at least another 1k of code to actually do something with those packets.&lt;br /&gt;&lt;br /&gt;Next time we'll have a look at the code that gets the packet network up and running.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-1937034099490490057?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/1937034099490490057/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=1937034099490490057' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/1937034099490490057'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/1937034099490490057'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2008/05/15-all-meshed-up-part-2-packet-network.html' title='16. All meshed up - Part 2 - Packet network basics'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-3176069115011838043</id><published>2008-05-06T11:31:00.007+01:00</published><updated>2008-12-09T08:54:31.368Z</updated><title type='text'>15. All meshed up - Part 1 - RF comms</title><content type='html'>I mean, really. Who doesn’t want to create their own wireless, meshed packet delivery network?  This stuff is just, like, cool.&lt;br /&gt;&lt;br /&gt;This project all began when my elderly but still energetic parents rebuilt their house and decided in a moment of weakness to allow me to design the lighting and control systems. So naturally I had all the light switches installed as X10 controllers and all the lights themselves connected via X10 lamp dimmers.  Then a bunch of X10 PIR sensors send movement information to the house controller PC via a third party receiver.  Then as you walk through the house the lights come on when you’re in the room and the controller PC also knows which lights are on.&lt;br /&gt;&lt;br /&gt;So it goes in theory.  In practice, every now and then an X10 lamp dimmer dies which is a total pain – they’re mounted in the wall cavities after all.  Sometimes the modules forget their settings, and the X10 protocol doesn’t actually make it all the way through the house, despite adding an expensive module that’s meant to relay and amplify the signals.  And with me living in London and them in Australia, it’s all a little difficult when it goes wrong.  Still, it’s cool being able to control their lights from the other side of the planet.&lt;br /&gt;&lt;br /&gt;My plan was to replace the unreliable X10 controllers and lamp dimmers with RF modules.  Of course you could never guarantee that the modules could talk to each other directly, my parents have internal brick walls that really wreak havoc with anything wireless.  So the network would need to be resilient to this type of problem.&lt;br /&gt;&lt;br /&gt;And as soon as you start creating something like this, you start to see lots of ways it could be used.  Temperature and humidity sensors, real time clock information, movement sensors… you name it!&lt;br /&gt;&lt;br /&gt;I did look at Zigbee of course, and that’s great in theory, but the most popular modules require a star network with controllers and don’t actually do proper meshing. Besides, I thought it would be fun to design my own.&lt;br /&gt;&lt;br /&gt;I started out with the Sparkfun nrf2041a modules and a couple of their Serial Development Node (version 1).  These are designed to work together and the SDNs provide translation of signals to RS232, a 16f88 pic on board and spot to plug a 2401a module straight into.  Perfect!&lt;br /&gt;&lt;br /&gt;The first chunk of work was to get the actual Nordic transceiver nrf2401a chips working and chatting away to each other.  Let’s look at that first, and then in the next article, look at how the packet delivery network works.&lt;br /&gt;&lt;br /&gt;The PicPack library supports both the nRF2401A and the nRFL01 chips, seamlessly and simultaneously on the same network. We’ll have a look at the 2401a here.  Open up the packet_demo project.&lt;br /&gt;&lt;br /&gt;Naturally the first thing you need to define the ports and pins used to communicate with the 2401a in your config.h file:&lt;pre class="code"&gt;&lt;br /&gt;// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -&lt;br /&gt;// pic_rf include&lt;br /&gt;// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -&lt;br /&gt;// For SFE_TDN_V1 board&lt;br /&gt;#define rf_ce_port PORTA&lt;br /&gt;#define rf_ce_pin  6&lt;br /&gt;#define rf_dr1_port PORTA&lt;br /&gt;#define rf_dr1_pin  3&lt;br /&gt;#define rf_cs_port PORTA&lt;br /&gt;#define rf_cs_pin 0&lt;br /&gt;#define rf_data_port PORTA&lt;br /&gt;#define rf_data_pin 2&lt;br /&gt;#define rf_clk1_port PORTA&lt;br /&gt;#define rf_clk1_pin 1&lt;/pre&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_bEFwpcEs1Go/SDQXwI1oJUI/AAAAAAAAAA8/EkhbUhqpR7k/s1600-h/link.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://3.bp.blogspot.com/_bEFwpcEs1Go/SDQXwI1oJUI/AAAAAAAAAA8/EkhbUhqpR7k/s320/link.jpg" alt="" id="BLOGGER_PHOTO_ID_5202809585293337922" border="0" /&gt;&lt;/a&gt;These are the ports and pins used by the SparkFun Terminal Development Node modules.  There is, however, a catch.  In their ultimate wisdom, the SparkFun guys (bless ‘em) wired the DR1 output from the 2401a to port a, pin 3.  The DR1 “Data Ready 1” output goes high when a packet has been received.  Now, this doesn’t seem like much of an issues, except that we’d really like to interrupt whatever the pic is doing at the time when a packet arrives.  All this polling to find out what’s going on stuff is just silly.  So you’ll need to wire the porta pin 3 to port b pin 0.  It’s easy, you just need to install a “link” in the alternative connector on the board.  You can see from the picture that it's the second and fourth holes on the second row back that need linking.&lt;br /&gt;&lt;br /&gt;So, the first thing you need to do, as usual, is run the setup routine that’s part of the library to set the ports and pins to be the right inputs or outputs:&lt;pre class="code"&gt;&lt;br /&gt;pic_rf_setup();&lt;br /&gt;&lt;/pre&gt;Then, as usual, you’ll need to actually initialise the hardware itself for use.  The trickiest part about using the 2401a is that it pretty much sits there like a dead duck until you get the configuration right, and then it springs into life.  Until then, you really have no idea what you’ve got wrong.  PicPack provides two routines for configuring your 2401a.  We’ll look at the more verbose one first.  You need to setup the rf_config struct with all the settings you care about – then pass a pointer to it to the pic_rf_init() routine.  Let’s work through the config.&lt;pre class="code"&gt;&lt;br /&gt;rf_config my_config;&lt;br /&gt;&lt;/pre&gt;The Nordic transceivers can receive on two (or more) channels at once.  We don’t care about this for our purposes, so we set the payload size (or width, in bits) to zero.&lt;pre class="code"&gt;&lt;br /&gt;rf_config my_config;&lt;br /&gt;&lt;/pre&gt;For our primary channel, we do care – it has to be the same size as (in this case) our packet size.&lt;pre class="code"&gt;&lt;br /&gt;my_config.payload_width_ch1 = PKT_PACKET_SIZE * 8;&lt;br /&gt;&lt;/pre&gt;Here we fill in the address for channel 2, although it’s actually not important want you do or don’t do with these values:&lt;pre class="code"&gt;&lt;br /&gt;my_config.address_ch2[0] = 0xf0;&lt;br /&gt;my_config.address_ch2[1] = 0xf0;&lt;br /&gt;my_config.address_ch2[2] = 0xf0;&lt;br /&gt;my_config.address_ch2[3] = 0xf0;&lt;br /&gt;my_config.address_ch2[4] = 0xf0;&lt;br /&gt;&lt;/pre&gt;When it comes to the channel 1 address, we do care.  Here’s the default address for Nordic chips, and in this case, we’re using address 0xE7E7E7.  We specify two more bytes than we need just for completeness.&lt;pre class="code"&gt;&lt;br /&gt;my_config.address_ch1[0] = 0b11100111; // addr starts here&lt;br /&gt;my_config.address_ch1[1] = 0b11100111;&lt;br /&gt;my_config.address_ch1[2] = 0b11100111;&lt;br /&gt;my_config.address_ch1[3] = 0b11100111; // only used three but fill&lt;br /&gt;my_config.address_ch1[4] = 0b11100111; // ...for the fun of it&lt;br /&gt;&lt;/pre&gt;In order to tell the chip we’re using 3 byte addresses, we set the address_width to 24 (8*3).&lt;pre class="code"&gt;&lt;br /&gt;my_config.address_width = 24; // (6 bits valid)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;We want to have a 16 bit CRC check on the packet.  This is how the chip tells a real packet from noise in the air.  At 1 Mbps you’d be amazed how often noise turns out to give correct CRC values with 8 bit CRCs.  16 bit CRC is much better, but is still not 100%.  That’s why the PicPack library has its own check byte as well.&lt;pre class="code"&gt;&lt;br /&gt;set_bit(my_config.options, OP_LONG_CRC);&lt;br /&gt;&lt;/pre&gt;Now we enable having a CRC as part of the transmission:&lt;pre class="code"&gt;&lt;br /&gt;set_bit(my_config.options, OP_ENABLE_CRC);&lt;br /&gt;&lt;/pre&gt;Turn off the second channel:&lt;pre class="code"&gt;&lt;br /&gt;clear_bit(my_config.options, OP_ENABLE_CH2);&lt;br /&gt;&lt;/pre&gt;Shockburst is the name Nordic gives for clocking your packet in to the chip and then sending it out on-air at the correct bit rate in one go.&lt;pre class="code"&gt;&lt;br /&gt;set_bit(my_config.options, OP_ENABLE_SHOCKBURST);&lt;br /&gt;&lt;/pre&gt;You can turn this bit off to enable 250kbps rate, which does give slightly longer range. 1 Mbps gives you less chance of packet collisions, which is why I recommend it (as well as giving compatibility with the nrf24L01 chip).&lt;pre class="code"&gt;&lt;br /&gt;set_bit(my_config.options, OP_ENABLE_1_MBPS);&lt;br /&gt;&lt;/pre&gt;On the SparkFun boards, they’re wired up with a 16Mhz crystal, which is why we choose that option here:&lt;pre class="code"&gt;&lt;br /&gt;// (3 bits valid) -&amp;gt; 16Mhz&lt;br /&gt;my_config.crystal = 0b011;&lt;br /&gt;&lt;/pre&gt;You have two bits (4 levels) of output power:&lt;pre class="code"&gt;&lt;br /&gt;// (2 bits valid) 11 -&amp;gt; max power!&lt;br /&gt;my_config.output_power = 0b11;&lt;br /&gt;&lt;/pre&gt;We can choose any of a gazillion channels, and the Nordic chip can hop around then quite quickly. Still, at this stage of the library, we pick one at the start and leave it at that.   I thought it would be good to look at a frequency hopping algorithm, but this does get hard when you have a meshed network.  Fine when it’s one on one, but when there’s three or more units, how does everyone keep in sync?  If you have any ideas, I’d love to hear them. In the mean time:&lt;pre class="code"&gt;&lt;br /&gt;my_config.channel = 2;     // (7 bits valid)&lt;br /&gt;&lt;/pre&gt;Last but not least, we put the chip into the receive mode:&lt;pre class="code"&gt;&lt;br /&gt;set_bit(my_config.options, OP_ENABLE_RECEIVE);&lt;br /&gt;&lt;/pre&gt;And then with a little flourish, call the routine that takes this information and passed it to the 2401a to get it initialised.&lt;pre class="code"&gt;&lt;br /&gt;pic_rf_init(&amp;amp;my_config);&lt;br /&gt;&lt;/pre&gt;As you can imagine, this programmatic way of telling the Nordic chip what to do is easy to understand and gives you the ability to change things at run time.  You’ll also realise that this does take a chunk of code (and hence flash) to do all this.  If all you want to do is set the config right at the start and not change it after that (other than the channel) then you can use the quick method:&lt;pre class="code"&gt;&lt;br /&gt;pic_rf_quick_init("\x00\xa8\xf0\xf0\xf0\xf0\xf0&lt;br /&gt;   \xe7\xe7\xe7\xe7\xe7\x63\x6f\x05",&lt;br /&gt;                  2, 1);&lt;br /&gt;&lt;/pre&gt;This does exactly what the previous chunk of code did.  The ‘2’ parameter is the channel number, and ‘1’ turns the receiver on.  To generate this config string, use the nrf2401a_config.pl script in the tools directory.  You don’t need to know anything about perl (other than having it installed somewhere!) – just edit the file and run it to get it to spit out the config string.&lt;br /&gt;&lt;br /&gt;So how do you go about sending data across the link? Well, here’s how the packet routines do it:&lt;pre class="code"&gt;&lt;br /&gt;void pkt_send_packet(rf_packet *packet) {&lt;br /&gt;  // +3 for RF address (fixed)&lt;br /&gt;uns8 tx_buffer[PKT_PACKET_SIZE + 3];&lt;br /&gt;uns8 count;&lt;br /&gt;tx_buffer[0] = 0b11100111; // address&lt;br /&gt;tx_buffer[1] = 0b11100111; // address&lt;br /&gt;tx_buffer[2] = 0b11100111; // address&lt;br /&gt;for (count = 0; count &amp;lt; PKT_PACKET_SIZE; count++) {&lt;br /&gt;  tx_buffer[count+3] = packet-&amp;gt;a[count];&lt;br /&gt;}&lt;br /&gt;pic_rf_transmit(tx_buffer, PKT_PACKET_SIZE + 3);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;You can see it’s as simple as whacking the destination address on the start.  In the case of the packet network, we’re assuming everyone’s on the same address.  Of course, you could use these routines to direct your data to a particular node directly using this addressing.&lt;br /&gt;&lt;br /&gt;Receiving data is only slightly more complicated. Since we’ve wired up the DR1 line to the port B, pin 0, it means that we can use an interrupt to detect when the nRF2401a wants to tell us something.  This is much better than having to poll for data all the time.  The 16f88 has two ways of detecting interrupts, but the one we want is when port B, pin 0 goes high. It’s set up like this:&lt;pre class="code"&gt;&lt;br /&gt;make_input(PORTB, 0);&lt;br /&gt;set_bit(intcon, INTE);&lt;br /&gt;&lt;/pre&gt;You’ll need to turn interrupts on as well:&lt;pre class="code"&gt;&lt;br /&gt;turn_global_ints_on();&lt;br /&gt;&lt;/pre&gt;In your interrupt() routine you can use something like this:&lt;pre class="code"&gt;&lt;br /&gt;if ( test_bit(intcon, INTF) ) {&lt;br /&gt;pic_rf_receive(rf_rx_buffer, MY_BUFFER_SIZE);&lt;br /&gt;clear_bit( intcon, INTF);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Notice how you test for the interrupt flag being set, respond if necessary, and then clear the flag.&lt;br /&gt;&lt;br /&gt;That’s all there is to it.  Next tutorial we’ll start looking at how to create a packet network on top of the RF communication we’ve set up here.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-3176069115011838043?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/3176069115011838043/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=3176069115011838043' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/3176069115011838043'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/3176069115011838043'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2008/05/14-all-meshed-up-part-1-rf-comms.html' title='15. All meshed up - Part 1 - RF comms'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_bEFwpcEs1Go/SDQXwI1oJUI/AAAAAAAAAA8/EkhbUhqpR7k/s72-c/link.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-5252034495151845108</id><published>2008-04-29T12:33:00.005+01:00</published><updated>2008-05-19T15:59:43.990+01:00</updated><title type='text'>14. Of Ports and Pins and SFRs</title><content type='html'>Up until now, I’ve conveniently skipped over how the PicPack libray handles the read-before-write problem on low to mid range pics, or even what this issue is really all about.  It provides a simple solution to a complicated problem, but it bears explaining since you’ll learn how these devices work under the covers. &lt;br /&gt;&lt;br /&gt;On Microchip micocontrollers, like many similar devices, allow you to make a given pin either an input, or an output.  And you can change this programmatically at runtime as well – handy talking to some devices over a bi-directional data line.  There’s some circuitry that can detect if there’s a high or low value present on a pin and also what’s known as a data latch attached to the same pins. The data latch is an output device that holds the value you give it until you change it.&lt;br /&gt;&lt;br /&gt;The problem with Microchip pic devices prior to the 18f range is two fold – firstly that the output latch isn’t readable and secondly that all outputs are done at the port (not pin) level.  What this means is that when you just want to change one output pin in a port from one value to another, the chip doesn’t know what the current values on the other pins are.  Say you’ve set pin 1 to high previously, and now you want to change pin 2 to a high as well.  It doesn’t have any record of what the previous value of pin 1 was set to (remember, the data latch isn’t readable) and all outputs to the latch happen at a port level (so it has to write values to all the pins in a port at once).  The way the chip gets around this is called “read before write”.  It reads the value on all the pins in the port (that is, the actual value present on the physical pins of the pin), then changes the pin you’re interested in, and then writes the whole port back again.&lt;br /&gt;&lt;br /&gt;So, in our example, it should read a high value on pin 1 (since this is what the latch is outputting), change the value on pin 2 to high and write them both (and the other pins in the port of course) back to the latch, resulting in pin 1 and pin 2 set to high values.&lt;br /&gt;&lt;br /&gt;That all sounds fair enough. It’s clearly a bit of a pain, but surely the output of the latch is the same as what you told it to output, so what’s the problem?  Well, in theory that’s perfectly true – but in practice, it doesn’t work like that.  Imagine that as part of your circuit you have a capacitor connected between your output pin and ground.  The reason why you’d do this isn’t important right now.  You can imagine that when you set that pin high, it’s going to take some actual real life time to get to the point of actually reading at a high level. Maybe just microseconds, but still, some time.  Now imagine if you set this pin high then, very quickly, set another pin high.  Your capacitor laden pin is going to be read and the chip may decide that in fact that pin is low at the moment since the capacitor hasn’t charged to the high level.&lt;br /&gt;&lt;br /&gt;Eek! That means that the pin is going to get written back as a low! Disaster!  In fact, it doesn’t just happen if you have something capacitor-like attached to the pin, it can happen even with a set of leds and resistors.  What to do?&lt;br /&gt;&lt;br /&gt;The answer is to simulate the readable latch that we don’t have.  The PicPack library provides a “shadow” port that it writes changes to before copying it to the whole port.  Of course this results in slightly more code – instead of a one instruction bit-set you end up with three.  As I’ve learnt with microcontrollers, everything is a compromise.  Presumably Microchip saved some money by not having a readable latch in these devices, but it costs you an extra couple of instructions to guarantee the value on an individual pin.  The 18f devices (and onwards) have a readable and writable data latch that makes this problem redundant, but without needing to make any chances, the PicPack library makes your code transparently portable between these devices even though 16f devices don’t have a readable data latch.&lt;br /&gt;&lt;br /&gt;At the end of the day you can use the PicPack routines without having to worry about what’s happening under the covers – and this makes your code more portable and readable as well. It’s worth explaining how PicPack achieves this without taking too many instructions, and even without having to tell it how many ports your device has.&lt;br /&gt;&lt;br /&gt;Open up the include file for the chip you’re working on at the moment.  This example uses the 16f88, which for me, is located at c:\Program Files\SourceBoost\include\pic16f88.h.&lt;br /&gt;&lt;br /&gt;Pics have a memory space for RAM which includes clumps of “magic” memory locations that do things when you read to them or write to them.  These locations are called Special Function Registers or SFRs.  You write to a port, for example, by writing a value to a SFR that results in the port being changed. &lt;br /&gt;&lt;br /&gt;BoostC include files define the address of these SFRs, and then define a variable that is located at that address.  That means that when you set that variable, you are writing data to that memory address – which means writing data to the SFR which causes the chip to do something.&lt;br /&gt;&lt;br /&gt;I’m being long-winded about this because it is actually quite confusing until you get your head around it.&lt;br /&gt;&lt;br /&gt;Have a look at the include file.  You’ll find the definition of our port locations:&lt;pre class="'code'"&gt;#define PORTA                 0x0005&lt;br /&gt;#define PORTB                 0x0006&lt;br /&gt;&lt;/pre&gt;Notice that the PORTA and PORTB are in capitals.  Later on, you’ll see in the same include file:&lt;pre class='code'&gt;volatile char porta                  @PORTA;&lt;br /&gt;volatile char portb                  @PORTB;&lt;/pre&gt;So, here we define two global variables, porta and portb that happen to reside at the right place that if you read or write to the variable, you end up reading or write the similarly named SFR.  Do you see how the variables use lower case letters, but the actual address is in capitals?  Thankfully SourceBoost provide these pre-made include files for just about every pic out there.  They’re choice of capital vs lower case is somewhat in contrast to other pic compilers, and sometimes the variable names and address locations aren’t even the same as what is in the data sheet for the same pic, just by way of warning.  As I’ve said, portability is relative these days, even if we’re all talking C.&lt;br /&gt;&lt;br /&gt;Now, all the “bits” of the SFRs are defined in here as well – so you can, for example, set the timer 0 interrupt enable bit of the intcon SFR by using:&lt;pre class='code'&gt;intcon.TMR0IE = 1;&lt;/pre&gt;This is bit setting notation is handy for single pins, but I prefer the more portable macro that SourceBoost provides:&lt;pre class='code'&gt;set_bit(intcon, TMR0IE);&lt;/pre&gt;It results in the same code generated, but it means you could port to a different compiler (or microcontroller vendor if need be) more easily.&lt;br /&gt;&lt;br /&gt;Now, you can see here we’re setting bit 5 of the intcon variable (actually memory location 0x000b).  This is all okay, since SFRs beyond ports don’t have real-life outputs and hence don’t suffer from the read-before-write problem.&lt;br /&gt;&lt;br /&gt;In order to make sure we generate as little code as possible, PicPack sets up an array at the same location as the port and tris SFRs in the pic_utils.h file:&lt;pre class='code'&gt;volatile uns8 port_array[NUMBER_PORTS] @PORTA;&lt;br /&gt;volatile uns8 tris_array[NUMBER_PORTS] @TRISA;&lt;/pre&gt;The tris SFRs are used to set whether a pin is an input (1) or an output (0). “Tris” comes from the (copyrighted) word tri-state, since a pin can be an output at high, an output at low, or an input (and high impedance).  You’ll see shortly that you don’t even need to worry about this tris malarkey either with the pic_utils library.&lt;br /&gt;&lt;br /&gt;These declarations don’t use any memory up – they just make it handy when we’re moving things around.  We also declare the shadow array:&lt;br /&gt;&lt;pre class='code'&gt;extern uns8 port_shadow[NUMBER_PORTS];&lt;/pre&gt;&lt;br /&gt;The NUMBER_PORTS define has already been calculated for you, earlier in pic_utils.h.  The actual useful functions are defined like this:&lt;pre class='code'&gt;#define set_pin(port, pin) \&lt;br /&gt;&amp;nbsp;set_bit(port_shadow[port - PORTA], pin); \&lt;br /&gt;&amp;nbsp;port_array[port - PORTA] = port_shadow[port - PORTA];&lt;/pre&gt;So our set_pin routine just works out which shadow location it needs to change, then copies the whole byte to the port at the right location.  Through a great deal of experimentation, I’ve found that this results in the smallest amount of generated code.  Even though it looks like we have lots of calculations to do, if we’re using known ports and pins then the compiler does what’s called “constant folding” and all the calculations are done as the code is compiled, not at run time.&lt;br /&gt;&lt;br /&gt;So, to set bit 5 of porta, you need to:&lt;pre class='code'&gt;set_pin(PORTA, 5);&lt;/pre&gt;Note that this is set_pin, and not set_bit, which is the generic macro for manipulating any byte.  Set_pin and its friends are only for actions on ports.&lt;br /&gt;&lt;br /&gt;This is why you’ll see these sort of #defines that you provide in your config.h:&lt;pre class='code'&gt;#define i2c_scl_port PORTC&lt;br /&gt;#define i2c_sda_port PORTC&lt;br /&gt;#define i2c_scl_pin  3&lt;br /&gt;#define i2c_sda_pin  4&lt;/pre&gt;You can see the PORTC in capitals here.  Once you’ve defined it, you can use i2c_scl_port and i2c_scl_pin and it’s much more readable form the code what you’re talking about.  In addition, if you decide to move where the hardware’s connected to, all you need to is update it in one place in the config.h.&lt;br /&gt;&lt;br /&gt;The routines that are provided are:&lt;pre class='code'&gt;set_pin(port_sfr_addr, pin)&lt;br /&gt;clear_pin(port_sfr_addr, pin)&lt;br /&gt;toggle_pin(port_sfr-addr, pin)&lt;/pre&gt;These work exactly as you’d expect, all buffered and safe from read-before-write problems.  There are a couple of other handy functions as well:&lt;pre class='code'&gt;test_pin(port_sfr_addr, pin)&lt;/pre&gt;returns the value of the pin (given it’s an input) allowing you to use the same naming convention for your input ports as well as outputs, eg:&lt;pre class='code'&gt;set_pin(PORTA, 1);&lt;br /&gt;if (test_pin(PORTA, 2) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// do something&lt;br /&gt;}&lt;/pre&gt;You can also change a pin to a given value, eg,&lt;pre class='code'&gt;change_pin(port_sfr_addr, pin, value)&lt;/pre&gt;like:&lt;pre class='code'&gt;#define MY_VALUE 1&lt;br /&gt;&amp;nbsp;&amp;nbsp;change_pin(PORTA, 2, MY_VALUE);&lt;/pre&gt;Now, because of the way code is generated for pics, when you’re using constants for the pin and port values, these #defines give you nice, simple code.  When you’re using variables, however, it does end up with more code.  At that point, you’re generally better off using these set of functions:&lt;pre class='code'&gt;set_pin_var(port_sfr_addr, pin)&lt;br /&gt;clear_pin_var(port_sfr_addr, pin)&lt;br /&gt;toggle_pin_var(port_sfr_addr, pin)&lt;br /&gt;change_pin_var(port_sfr_addr, pin, value)&lt;/pre&gt;These functions actually use subroutines instead of inline code, but will result in less code overall if you want to do things like:&lt;pre class='code'&gt;uns8 my_pin;&lt;br /&gt;&amp;nbsp;&amp;nbsp;my_pin = 5;&lt;br /&gt;set_pin_var(PORTA, my_pin);&lt;/pre&gt;It’s a subtle difference, and it other environments, (eg programming for PCs) you wouldn’t even bother make the distinction.  When every byte counts though, it’s worth making the effort.  Of course, this uses another stack level – so you may wish to swap code size for stack level and use the set_pin version nevertheless.&lt;br /&gt;&lt;br /&gt;As a general note, I’m pretty sure none of the PicPack library actually uses the set_pin_var family of functions.  You’ll probably find that you generally know what pin you need to change well in advance – ie, at compile time.&lt;br /&gt;&lt;br /&gt;Finally, these routines also make it easy (and beautifully clear in your code) to make pins either inputs or outputs:&lt;pre class='code'&gt;make_input(port_sfr_addr, pin)&lt;br /&gt;make_output(port_sfr_addr, pin)&lt;/pre&gt;&lt;br /&gt;Again, this allows you to do things like this:&lt;br /&gt;&lt;pre class='code'&gt;make_output(PORTA, 3);&lt;br /&gt;set_pin(PORTA, 3);&lt;/pre&gt;Notice how you don’t even need to know anything about tris bits and it is quite obvious what’s meant to be going on.&lt;br /&gt;&lt;br /&gt;By way of summary, for the imaginary rt373 device, define your ports and pins in your config.h like this:&lt;pre class='code'&gt;#define tr373_data_port PORTB&lt;br /&gt;#define tr373_data_pin 1&lt;br /&gt;#define tr373_clk_port PORTB&lt;br /&gt;#define tr373_clk_pin 1&lt;/pre&gt;And then you can do things like this:&lt;pre class='code'&gt;#include “pic_utils.h”&lt;br /&gt;&amp;nbsp;&amp;nbsp;// setup ports and pins&lt;br /&gt;make_input(tr373_data_port, tr373_data_pin);&lt;br /&gt;make_output(tr373_clk_port, tr373_clk_pin);&lt;br /&gt;&amp;nbsp;&amp;nbsp;// clock in the first value&lt;br /&gt;clear_pin(tr373_clk_port, tr373_clk_pin);&lt;br /&gt;set_pin(tr373_clk_port, tr373_clk_pin);&lt;br /&gt;my_value = test_pin(tr373_data_port, tr373_data_pin);&lt;/pre&gt;…and so on.  Easy!  Note that while the PicPack library currently doesn’t do anything differently for PIC18 devices, the routines are perfectly portable between the devices without any code or even config changes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-5252034495151845108?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/5252034495151845108/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=5252034495151845108' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/5252034495151845108'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/5252034495151845108'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2008/04/13-of-ports-and-pins-and-sfrs.html' title='14. Of Ports and Pins and SFRs'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-6730057867421316665</id><published>2008-04-28T09:20:00.001+01:00</published><updated>2008-04-28T09:23:48.451+01:00</updated><title type='text'>PicPack 1.1 released</title><content type='html'>The latest version of the PicPack is now released.&lt;br /&gt;&lt;br /&gt;This includes more documentation on units, packet demo (tutorial coming soon) and fixes for boostbloader.&lt;br /&gt;&lt;br /&gt;Note the function in the packet demo that allows you to press "download" on screamer to update your software without having to hardware-reset the pic.  Very neat!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-6730057867421316665?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/6730057867421316665/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=6730057867421316665' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/6730057867421316665'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/6730057867421316665'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2008/04/picpack-11-released.html' title='PicPack 1.1 released'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-8427402728356307249</id><published>2008-04-22T13:54:00.004+01:00</published><updated>2008-04-22T13:59:14.298+01:00</updated><title type='text'>13. It's about time</title><content type='html'>Following on from our discussions on getting the temperature via i2c, we’ll look at talking to a real time clock chip such as the ds1307.  It’s a little more complicated than just getting the temperature – but mostly because there’s just more data available.  The way we interact with the chip is very similar.&lt;br /&gt;&lt;br /&gt;Now, you might ask why we need a separate chip to look after the time.  Why can’t we do it all on our pic with our nifty timer routines?  Well, we could.  In fact, you can even drive one of the timers from an external crystal designed for handling real time clock type problems.  There are, however, some good reasons to keep it all separate.&lt;br /&gt;&lt;br /&gt;The first is that the DS1307 has support for battery backup – from a 3v CR2032 or similar, which will run it for 10 years or more.  That’s effectively lifetime of the device.  So when the device as a whole is powered off, the time will still be current.  The other neat aspect is that the DS1307 has a bunch of non volatile RAM slots left over (56 byte to be exact) which we can use for our own nefarious purposes.  You could use a pic that has no EEPROM (these are generally a lot cheaper) and store your info in the DS1307.  Neat!&lt;br /&gt;&lt;br /&gt;In any case, it’s a good example of another external device we can talk to over the i2c buss.  You could connect a DS1307 and an LN75 on the same buss and talk to them both using only two wires.&lt;br /&gt;&lt;br /&gt;Open up the ds1307 demo project.  You’ll notice that in our configure_system routine we have:&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;rtc_setup();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This in turn calls i2c_setup() to configure port and pins as inputs or outputs as appropriate, ready for communication.&lt;br /&gt;&lt;br /&gt;In request_time() we do some simple requests:&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;minutes = rtc_get_minutes();&lt;br /&gt;hours   = rtc_get_hours();&lt;br /&gt;seconds = rtc_get_seconds();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And print out the result.  All pretty easy so far.&lt;br /&gt;&lt;br /&gt;It gets a little more tricky in process_rx() which allows us to enter commands like:&lt;br /&gt;&lt;br /&gt;sm23 &lt;enter&gt; &lt;enter&gt;&lt;br /&gt;&lt;br /&gt;over a serial connection, to set the minutes to 23.  The same goes for hours and seconds, using&lt;br /&gt;&lt;br /&gt;sh12 &lt;enter&gt;&lt;enter&gt;&lt;br /&gt;and&lt;br /&gt;ss04 &lt;enter&gt;&lt;enter&gt;&lt;br /&gt;&lt;br /&gt;If you have a look at ds1307.c, you’ll notice that most of the routines are simply wrappers around the i2c routines.  Some add a little bit of value, by masking out bits, but even then, they’re mostly one liners.  This brings us to the challenge of programming such limited devices – you’ve really got a choice between stack size and code size.  If you use a sub routine only once – then it’s probably worth turning it into a #define or using the inline keyword.  That means the code it uses gets placed in the actual location it’s used, and you save a stack position.  In 16f88 devices, there are only 8 places in the stack.  If you use interrupts then you’ll use 1 when an interrupt is called, even before you call any subroutines.  So you need to make sure the stack never exceeds the interrupt level + main program level.  If you do exceed this, on the 16f88 it will happily wrap the stack around and you’ll have lost the first stack position.  In reality, this normally results in generally strange behaviour.  If your program is using interrupts, and sometimes crashes, prints out strange repetitive things to the serial port or seems to jump back to the boostbloader, then you’ve probably got a stack overflow.&lt;br /&gt;&lt;br /&gt;You can check to see if this is possible by looking at the BoostC output.  It will print out a quiet little warning that you’ve exceeded the maximum stack level if everything happens at once (remember, BoostC knows about the whole program structure at the start, but it can’t know if the interrupt happens at the deepest main program stack position).  I keep getting caught in this – strange behaviour, start putting serial_print_str in to find out exactly where it crashes (strange, those routines have worked for ages)  - only to discover that there’s a potential stack overflow lurking around.&lt;br /&gt;&lt;br /&gt;Sourceboost provides some very handy tools for find out what to do here.  If you press the Code button on the tool bar and open out the pane that the code shows in, you can see the entire call tree of the program.  This feature is worth the price of Sourceboost alone – you can easily see which tree branches are the longest and start to do something about them.&lt;br /&gt;&lt;br /&gt;The Function Info pane shows more information about each subroutine so you can see which ones are chomping up flash memory and RAM.  My only wish here is in a future version that the #Global line will be expandable.  I’d love to see where the global variables that are taking up RAM are coming from.  The assembly tab then gives you a fantastic rundown of what assembly BoostC has come up with for your routines – and gives you the chance to optimise this.  Often you have to be quite crafty to reduce your flash and RAM footprint.  Sometimes its just tonnes of serial_print_str statements.&lt;br /&gt;&lt;br /&gt;So, if you find that the ds1631 demo is too big for your chosen pic, the easiest way to trim it down is to take out or simplify some of the serial_print_str statements.  The main program “help” printout would be a good place to start.&lt;br /&gt;&lt;/enter&gt;&lt;/enter&gt;&lt;/enter&gt;&lt;/enter&gt;&lt;/enter&gt;&lt;/enter&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-8427402728356307249?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/8427402728356307249/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=8427402728356307249' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/8427402728356307249'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/8427402728356307249'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2008/04/its-about-time.html' title='13. It&apos;s about time'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-7472029375766511464</id><published>2008-04-19T13:19:00.004+01:00</published><updated>2008-04-19T13:43:38.065+01:00</updated><title type='text'>12. Which Pic?</title><content type='html'>If you’re anything like me, you’ll have had a look at the Microchip web site and been completely overwhelmed by the choices available to you.  There are literally thousands of types of pics.  How do you choose?&lt;br /&gt;&lt;br /&gt;To some extent that depends what you want to do with it, but that’s not a very helpful answer.  What I think is more important as you get started is using chips that make development easy.  Once you’ve got something developed, if you were to actually take it to market, you’d simply choose the cheapest pic that had all the features you needed – and microchip’s web site includes tools for searching based on all sorts of criteria.&lt;br /&gt;&lt;br /&gt;I think the essential things are &lt;br /&gt;a) A hardware UART (serial port)&lt;br /&gt;b) Plenty of flash memory for instructions&lt;br /&gt;c) Support for the tools you use - not all hardware programmers support all pics!&lt;br /&gt;&lt;br /&gt;If you’re starting out, I think the best pic to get going with is the fabulous 16f88.  It’s got 4k words of instructions, which is plenty for experimenting with.  It has 256 bytes of EEPROM for settings, 384 bytes of RAM and ports A and B.  It runs at 8Mhz using the internal oscillator, giving you 2 mips and can run at 5 mips with a 20Mhz crystal.  It can actually run an entire multi-hop meshed RF connection in 4k, but only just.&lt;br /&gt;&lt;br /&gt;Once you start to run out of memory, flip over to the 16f876A.  This guy has 8k words of instructions and because it has more pins, it has an extra port C.  Other than that, it’s pretty similar.&lt;br /&gt;&lt;br /&gt;The Sure PicDem2 board has an 18f4520 on board – this baby has 16k words of instructions, 1536 bytes of RAM and can run at 10 mips on a 10Mhz crystal. Sweet!  Since I want to use the Olimex boards for experimenting without having to do surface mount, I’m also looking at the 18f2620, which stores 32k words of instructions, 3986 bytes of RAM and 1024 bytes of EEPROM. That’s one seriously pimped up pic.  I’ll post when I’ve got the boostloader working on it.&lt;br /&gt;&lt;br /&gt;Avoid any pic with 12 bit instructions.  Most 16f pics have 14 bit instructions, all 18f guys have 16 bit instructions.  I got a bunch of the funky Sure 5x7 LED array displays, with a view to reprogramming the pic on the back, but it turns out to be a 16f57, which BoostC doesn’t support as it has 12 bit instructions.&lt;br /&gt;&lt;br /&gt;Printing things out to the serial port chews up instructions like you wouldn’t believe.  I think it’s better to have plenty of Flash and not have to spend time cutting your program down just to get it working – once you’ve got it working, that’s the time for optimising.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-7472029375766511464?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/7472029375766511464/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=7472029375766511464' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/7472029375766511464'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/7472029375766511464'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2008/04/which-pic.html' title='12. Which Pic?'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-8353231572802853982</id><published>2008-04-19T12:35:00.002+01:00</published><updated>2008-04-19T12:46:45.552+01:00</updated><title type='text'>11. It's hot in here</title><content type='html'>I think now’s the time to start interacting with other devices – and the one we’re going to start with will tell us what the temperature is.  It’s a great opportunity to learn about the i2c protocol, how to interface with other devices and what a decimal place really means.&lt;br /&gt;&lt;br /&gt;The chip of our choosing is the LM75, which like most of these sort of devices has many compatible versions from many manufacturers. Grab hold of a copy of the &lt;a href="http://www.national.com/mpf/LM/LM75.html"&gt;datasheet&lt;/a&gt; for this guy.  You’ll notice that it’s an 8 pin device.  3 pins define the address of the device – so you can have up to 8 all connected together and yet address them individually.  It has two modes, “shutdown” and “normal”, where shutdown mode will put the device into a low power sleep mode, and normal mode will convert the temperature every 100ms.  It has two registers that we care about, the config register and the temperature register.  The 8 bit config register is, naturally, where the config bits are stored.  The 16 bit temperature register is where the temperature gets put every 100ms.  The datasheet specifies that you can read the temperature safely at any time without any fear that it will be corrupted by another temperature measurement while you’re actually getting the register sent to you.&lt;br /&gt;&lt;br /&gt;The LM75 uses a protocol called &lt;a href="http://www.nxp.com/acrobat_download/literature/9398/39340011.pdf"&gt;“i2c”&lt;/a&gt;, although it’s actually I “squared” C and stands for inter intergrated circuit.  I write it without the superscript “2”.  You might also see referred to as IIC and some chips use it without referring to this name at all.  Presumably their lawyers told them to keep quiet. In any case, it’s a very neat way of communicating bi-directionally with different devices with only signal two wires.  You can have several devices on the “buss” and distinguish between them.  It even has modes where there can be several devices making requests (acting as the “master” in i2c speak), however, personally I think this is reasonably unlikely to happen in practice.  The devices you make requests upon, in our case the LM75, are said to be in “slave” mode.  They just do as they’re told.&lt;br /&gt;&lt;br /&gt;Now, most pics that you’ll come across have some sort of i2c hardware inbuilt.  This means they can handle a lot of the hard work themselves.  The unfortunate fact is that mostly this is only as a slave and not as a master.  To be fair, it’s pretty easy to implement master mode in firmware and you don’t get a lot of advantages out of doing it in hardware (presumably some code space).  In any case, looking at the software implementation gives you a chance to understand how the protocol really works.&lt;br /&gt;&lt;br /&gt;My intention here is not to cover the i2c protocol itself – there are tonnes of stuff on the net about this, and an excellent article in a recent edition of the excellent Silicon Chip magazine.  If you’re into electronics at all, go subscribe to this magazine and support the Australian economy.&lt;br /&gt;&lt;br /&gt;What I do want to cover is the use of the picpack library, which as you would expect by now, implements enough of the i2c protocol to get you talking with your LM75 or other i2c device but keeps you protected from any read-before-write problems on 16f devices.  Once you have the “temperature” data in your hand, it’s also interesting to see what needs to be done to turn it into something worth displaying – and what that really means.&lt;br /&gt;&lt;br /&gt;Open up the lm75 demo in the demos directory and have a look.  You’ll see that since the lm75 library is built on top of the i2c library, you need to include the i2c.c file in your project as well.  Have a look at the config.h:&lt;br /&gt;&lt;br /&gt;&lt;pre class='code'&gt;&lt;br /&gt;// - - - - - - - - - - - - - - - - - - - -&lt;br /&gt;// pic_serial defines&lt;br /&gt;// - - - - - - - - - - - - - - - - - - - -&lt;br /&gt;#define SERIAL_TX_BUFFER_SIZE 16&lt;br /&gt;#define SERIAL_RX_BUFFER_SIZE 4&lt;br /&gt;//#define SERIAL_DEBUG_ON&lt;br /&gt;// - - - - - - - - - - - - - - - - - - - -&lt;br /&gt;// pic i2c defines&lt;br /&gt;// - - - - - - - - - - - - - - - - - - - -&lt;br /&gt;#define i2c_scl_port PORTC&lt;br /&gt;#define i2c_sda_port PORTC&lt;br /&gt;#define i2c_scl_pin  3&lt;br /&gt;#define i2c_sda_pin  4&lt;br /&gt;// - - - - - - - - - - - - - - -&lt;br /&gt;// General platform definitions&lt;br /&gt;// - - - - - - - - - - - - - - -&lt;br /&gt;#define PLATFORM_TYPE SURE_PICDEM_2&lt;br /&gt;#define PLATFORM_CLOCK 12000000&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;There’s the usual serial defines at the top, followed by the i2c defines.  In this case, the project is ready to go on the Sure electronics Picdem 2 board – a great board for getting into 18f chips, LCD and temperature.  We’ll talk about prototyping boards a little later on.  Don’t forget to set your platform clock correctly, both for the serial communications and also for the delays used by the i2c routines.&lt;br /&gt;&lt;br /&gt;Pack in lm75_demo.c, notice that getting the lm75 talking is as simple as:&lt;br /&gt;&lt;br /&gt;&lt;pre class='code'&gt;&lt;br /&gt;lm75_setup();&lt;br /&gt;lm75_set_config(LM75_ADDRESS, LM75_NORMAL);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Remember that each lm75 has its own address – the LM75_ADDRESS define is at the top of the file.  Make sure you match it correctly to the LM75 address you set on your hardware (the Sure picdem2 board has it set to zero).  In lm75_setup() the ports and pins are set up to communicate hardware-wise with the device.  lm75_set_config sets the config register to the normal mode (ie, not shutdown).  This isn’t really necessary since this is the default state, but hey, it’s a demo and we need to demo something!&lt;br /&gt;&lt;br /&gt;The serial communication parts of the program are set up to read the temperature when you press t and &lt;enter&gt;, and read the config register when you press c and &lt;enter&gt;.  Reading the config register is pretty boring, but it does prove it works.  Reading &lt;br /&gt;the temperature is a little more interesting.&lt;br /&gt;&lt;br /&gt;To read the temperature all you need to do is call:&lt;br /&gt;&lt;br /&gt;&lt;pre class='code'&gt;&lt;br /&gt;raw_temp = lm75_get_temp(LM75_ADDRESS); &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The LM75 gives you an 11 bit temperature reading via a 16 bit number.  The first 8 bits are the integer part, the following 3 bits are the “decimal” part.  So we have three “bits” of decimal resolution.  That means each bit represents a value of 0.125.  If we take the second set of 8 bit, rotate it left by 5 bits, we’ll end up with those 3 bits right aligned in the byte.  That makes it easier to process.  So, if the left-most byte is 25, and the right most byte (after shifting) is 3, then the reading is 25.375.  Now, that sounds like a pretty precise reading.  What I haven’t mentioned until now is that according to the datasheet, the LM75 is accurate +/- 2 degrees C.  So our reading could really be anywhere between 23.375 or 27.375.  That’s pretty broad – and you start to realise that three bits of accuracy are pretty meaningless – especially when you convert them to base 10.&lt;br /&gt;&lt;br /&gt;The lm75_demo.c includes two routines to convert the three bits to one or two base-10 decimal places through essentially a look up table.  You can work our how I’ve calculated the values (multiplying 0.125 and then rounding).  Note that given that we’ve only got 8 values available to us with three bits, you can’t even accurately represent 1 base-10 decimal place!  Still, we’re just displaying the temperature here, so I’m not going to get hung up about it.  The PicPack library includes support for the DS1307 chip, which has +/- 0.5 degree accuracy as 12 bit resolution, but we’ll be exploring that a little later.&lt;br /&gt;&lt;br /&gt;&lt;pre class='code'&gt;&lt;br /&gt;PIC terminal&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;19:55:57&amp;gt;&lt;br /&gt;Commands:&lt;br /&gt;t - Request temp&lt;br /&gt;c - Request config&lt;br /&gt;t&lt;br /&gt;&amp;gt;Requesting temp.&lt;br /&gt;Raw temp = 0x1AE0&lt;br /&gt;Temp = 26.88&lt;br /&gt;Temp = 26.9&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The other aspect that I’ve left out of this demo as an exercise for the viewer is the fact we are blatantly ignoring negative readings.  These are represented as twos complement numbers, about which there’s plenty of information on the web.  If you come up with some cool routines to process negative numbers, send them in and we’ll include them in the library for everyone to use.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-8353231572802853982?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/8353231572802853982/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=8353231572802853982' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/8353231572802853982'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/8353231572802853982'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2008/04/11-its-hot-in-here.html' title='11. It&apos;s hot in here'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-1157830022517464085</id><published>2008-04-16T15:58:00.002+01:00</published><updated>2008-04-16T16:06:15.825+01:00</updated><title type='text'>10. On Display</title><content type='html'>Eventually, you’ll want your microcontroller to communicate with the outside world without needing to be tethered to a computer.  LCDs are a great way to do this, and given almost all the character-based LCDs are based on the HD44780 chipset, or at least a compatible protocol, it’s pretty easy to get these guys going.  There’s also a great range of sizes – from cute 2 line 8 character displays to 4 line 40 character monsters.  As long as its character based as opposed to graphical, the picpack LCD routines will get you up and running quickly.&lt;br /&gt;&lt;br /&gt;There are stacks and stacks of example code out on the net on talking to LCDs.  Go wild, go crazy – if these routines don’t help you then feel free to grab something else.  The nice thing about the picpack routines is that they work the same way as the others, and always protect you from read-before-write problems.  The only area I think the LCD routines needs expanding is in the area of setting character generator ram (you can do this already, but it’s a bit clunky) and supporting 4 line 40 character displays. These are really just two 2 line by 40 character displays with an extra chip enable line to select between the two “displays”.  I’ve got one of these beasties, so I’ll add support for it eventually.&lt;br /&gt;&lt;br /&gt;Some notes on getting LCDs working from the electronics side.  Most of them run at 5v.  So if you are running your pic at 3.3v, you’ll need a separate 5v rail to run the LCD.  Check the datasheet for your LCD (if it has one!), but you will probably be able to connect the data pins directly to the pin despite the expected level difference.  Check your pic datasheet to ensure that it has 5v tolerant pins, and that the LCD thinks that a logic “1” is as low as 3.3v.&lt;br /&gt;&lt;br /&gt;If you’re running your pic at 5v, this will not be a problem.  Either way, you’ll need a resistor to reduce the current for the backlight if your display has one.  You can’t just whack 5v in there – check the LCD datasheet, match the resistor to the current required (there are plenty of web sites on the net that will help you calculate the resistor value).  Or, at least stick something in there, 330R would be a good start.&lt;br /&gt;&lt;br /&gt;Lastly, a trap for new players is the contrast adjustment.  You can get everything else right, but if you don’t have a variable contrast adjustment, then you’re not going to get anything visible on the LCD.  A 10k variable resistor, tied between ground and Vdd allows you to connect the contrast input (normally labelled as Vee) to a value between 0 and 5v.  You’ll need to play around with the adjustment once you get it connected up and something allegedly displayed.&lt;br /&gt;&lt;br /&gt;Now, on to the software.&lt;br /&gt;&lt;br /&gt;Have a look at the lcd_demo project in the lcd directory.  Note that in the config.h, you’ll see not only settings for the serial connection (which we’ll use to control the LCD) and the platform settings (make sure you set your clock frequency correctly) but also port and pin settings for the LCD.  LCDs can communicate using an “8bit” mode or a “4bit” mode.  Either way, you still need three other pins (RS, RW and E) to communicate, so at a minimum you need 7 pins.  Personally, I’d rather have more pins free to do something else.  Sparkfun produces a serial backpack that allows connection to LCDs with only one pin – unfortunately, it uses asynchronous serial communication, which means you either have to give up your serial port for debugging, or bit-bang your own serial routines.  One day I’ll get around to rewriting the backpack code to take a synchronous serial connection (ie, two pins).  It looks like a fun little development platform in any case.  In the mean time, you can connect to an LCD directly using 7 pins. Platforms like the Sure PicDem 2 board will also work with the pickpack LCD library, even though they’re wired for 8 bit connections.  This will actually free 4 pins for other uses.&lt;br /&gt;&lt;br /&gt;Have a look at the configure_system routine.  Notice that they only new calls are to:&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;    lcd_setup();    // Setup the pins (output / input)&lt;br /&gt;    lcd_init ();    // Configure chip ready for display&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;You’ll find that most of the picpack libraries have a “setup” routine for the device they’re talking to.  This always sets up the configured ports and pins for input or output as required.  Note that they expect that all pins are digital pins, so you’ll need to call turn_analog_inputs_off() yourself.   The “init” routines actually initialise the hardware ready for use.  In this case, lcd_init configures the LCD for 4 bit operation, clears the display and puts the cursor in the top left corner.&lt;br /&gt;&lt;br /&gt;LCD communication takes place in one of two ways.  It accepts either commands (which do something) or data (which put data into either the screen buffer RAM or the character generator RAM).  You can see examples of commands in the main() routine:&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;    lcd_write_command(LCD_CLEAR_DISP);    // clear the display&lt;br /&gt;    lcd_write_command(LCD_RETURN_HOME);    // cursor back to the beginning&lt;br /&gt;    lcd_write_command(LCD_LINE1);    // goto line 1&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;and sending data as well:&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;      lcd_write_data_str("PicPack LCD demo");    // print welcome message&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Note that the LCD_LINE1 is simply a command to choose the display RAM location – so you can position the cursor further along the line like this:&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;    // goto line 1, 6th character&lt;br /&gt;    lcd_write_command(LCD_LINE1 + 5); position&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you get the example project onto a pic, you can issue commands in your terminal program to clear the display or return the cursor home by typing the letter c and &lt;enter&gt;, or h and &lt;enter&gt;, respectively.  Pressing 1 and enter or 2 and &lt;enter&gt; will move the cursor to the beginning of the first line or second line.  Typing t followed by a string (anything you like) followed by &lt;enter&gt; will print your string to the LCD.&lt;br /&gt;&lt;br /&gt;The program starts by putting a string on the first line of your display to confirm everything is working.&lt;br /&gt;&lt;br /&gt;Neat!  There’s not much more to it than that, but it does open the pic up to start making its own display and telling the world what’s going on.&lt;br /&gt;&lt;/enter&gt;&lt;/enter&gt;&lt;/enter&gt;&lt;/enter&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-1157830022517464085?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/1157830022517464085/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=1157830022517464085' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/1157830022517464085'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/1157830022517464085'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2008/04/10-on-display.html' title='10. On Display'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-3279005400501724018</id><published>2008-04-14T10:27:00.006+01:00</published><updated>2008-04-14T10:55:31.554+01:00</updated><title type='text'>9. It's about time</title><content type='html'>It soon becomes apparent when working with microcontrollers, that things happening at the right time is crucial to things working at all. In this tutorial we explore timers and some tools to help timing events.&lt;br /&gt;&lt;br /&gt;Pic microcontrollers generally have at least one timer, and often three.  These are generally registers that will clock over once per instruction cycle, and when they flip over (from 0xff to 0x00) they can generate an interrupt.  Of course, counting from 0 to 255 (0xff) at 8 Mhz, which is 2 mips, isn’t very long – and you’re not going to get much done in between each interrupt!  256 clocks at 2 mips is 0.000128 seconds – or 128 microseconds. Not very long at all. So to make it easier to timer longer periods, some timers are 16 bit (65536 clocks at 2 mips is 0.032768 seconds) and most timers allow for something called a prescaler.  The prescaler in an independent counter that divides down the clock so the timer is incremented less often.  They’re always in powers of two, so you’ll see them in ratios like 1 to 2, or 1 to 4, or 1 to 8 and so on.  In the case of a 1 to 2 prescaler setting for example, it results in the timer counting up every 2 clock cycles, not every clock cycle.  1 to 4 results in the timer counting up every 4 clock cycles, and so on.&lt;br /&gt;&lt;br /&gt;The picpack library contains several tools for manipulating timers and keeping track of timings.  The first tool is a set of routines found in the pic_timer library, for setting up and starting timers.  The second is the pic_tick library, which makes it easier to work out how much time has elapsed between events.  Later on in this series, you’ll see how important these concepts are when we create our own meshed packet RF network.  But for now, we’ll just see how these timers work.&lt;br /&gt;&lt;br /&gt;Open up the tick_demo project.  There’s two parts to using timers with the picpack library.  The first is manipulating the timer hardware itself.  Have a look at the tick_demo.c file, and the configure_system routine:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;#ifdef _PIC18&lt;br /&gt;timer_setup_0(TIMER_16BIT_MODE, TIMER_PRESCALER_OFF, 0xffff - 3000 + 13);    // 1ms at 12Mhz&lt;br /&gt;//timer_setup_0(TIMER_16BIT_MODE, TIMER_PRESCALER_1_TO_2, 0xffff - 1500 + 7);    // 1ms at 12Mhz&lt;br /&gt;//timer_setup_0(TIMER_16BIT_MODE, TIMER_PRESCALER_1_TO_8, 0xffff - 375 + 1);    // 1ms at 12Mhz&lt;br /&gt;#endif   &lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;In this example, we are assuming that the clock is running at 12Mhz and we’re using an 18f type of pic, which has a 16 bit mode for timer 0. Knowing that each instruction takes 4 clock cycles, we would expect this to take 3000 clocks.  The first (commented out) line takes that stance – the timer counts up from the value given, so we need to subtract the 3000 from 0xffff.  Note there’s an extra 13 added due to the number of instructions taken to get everything processed, the fact the sometimes updating the timer actually stops the timer for a few clocks on some chips.  Of course, if we were using the prescaler at 1 to 2, we would only need 1500 clocks – and less compensation.  At 1 to 8, we only need 625.  The timer is going to be more accurate at the lowest prescalar value (ie, off) – since you can compensate very accurately.  By the time you’re at 1 to 8, you’ve got a compensation level 8 times as coarse.  Still, unless your clock needs to be mission critical (ie, actually running a real time clock), any of these will be close enough (within 10 clocks of the required value, which is 2.5 microseconds.  The timer routines adjust where they can – given your value, they will adjust the next timer loop if the pic has been busy while the timer interrupt occurred and didn’t get to it as quickly as it did the last time through the loop.  This means that while one timer interrupt might take slightly longer than you expected, the next one will be automatically shortened to compensate.  So on average, it’s pretty accurate and errors don’t get compounded.&lt;br /&gt;&lt;br /&gt;Now, have a look at the pic 16 version:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;code&gt;&lt;br /&gt;#ifdef _PIC16&lt;br /&gt;&lt;br /&gt;timer_setup_0(TIMER_8BIT_MODE, TIMER_PRESCALER_1_TO_8, 0xff - 250 - 1);    // 1ms at 8Mhz&lt;br /&gt;&lt;br /&gt;#endif&lt;br /&gt;&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Even though the 16f devices don’t have a 16 bit timer 0 (they have 16 bit timer1 and timer2 modules however), we can pass in the same types of parameters as the 18f equivalent routines.  If we assume that we have a 16f device running at 8Mhz, then we’re looking for 2000 clock cycles to make up 1 ms.  Counting to 255 isn’t going to get us far – so we have to employ the prescaler.  And if we set it to 1 to 8, then counting to 250 x 8 = 2000 clock cycles, give or take.  Of course, as we know, there’s not much room for correction at the 1 to 8 prescaler level.  However, for most cases, this should be accurate enough.  When you’re using timers, once you’ve set them up (as above), you’ll need to start them, as in the main routine:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;code&gt;&lt;br /&gt;timer_start_0();    // kick that timer off...&lt;br /&gt;&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You can also use timer_stop_0() to stop the timer temporarily, with 18f devices you can do just that, stop the timer.  With 16f devices, the timer doesn’t have an “off”, so we just turn the timer 0 interrupts off instead.&lt;br /&gt;&lt;br /&gt;Right, so now we’ve got a 1ms timer, what can we do with it?  Well, let’s say we want to do something every second.  Or see how long it’s been since a particular event has occurred.  This is where the pic_tick library comes into play.  Back in tick_demo.c, have a look at the interrupt routine:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;code&gt;&lt;br /&gt;void interrupt() {&lt;br /&gt;&lt;br /&gt;  timer_handle_0_isr();&lt;br /&gt;    serial_handle_tx_isr();&lt;br /&gt;    serial_handle_rx_isr();&lt;br /&gt;&lt;br /&gt;}    &lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;There’s the serial handlers, as usual, but also the timer_handle_0_isr() routine – which takes care of timer 0.  Note that in your code somewhere, you need to include a routine called timer_0_callback() like this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;code&gt;&lt;br /&gt;void timer_0_callback() {&lt;br /&gt;     handle_tick();&lt;br /&gt;}  &lt;br /&gt;&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Every timer 0 interrupt, this routine will get called.  In this case, we call handle_tick() – which increments the pic_tick “tick” counter.  So we know our “ticks” in this program are every 1ms.  The ticks are counted using a 16 bit counter, with some neat routines to help work out timings.&lt;br /&gt;&lt;br /&gt;Now, let’s say we want to do something every 1 second.  That’s 1,000 ms.  Have a look in the main() routine:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;code&gt;&lt;br /&gt;test_tick = tick_get_count();    // find out what we're up to&lt;br /&gt;if (tick_calc_diff(tick_marker, test_tick) &gt;= 1000) {    // 1000 - it's a second&lt;br /&gt;     serial_print_str(" &lt;ting!&gt; ");    // print something out&lt;br /&gt;     tick_marker = test_tick;    // reset to find next 1000&lt;br /&gt;}&lt;br /&gt;&lt;/ting!&gt;&lt;/code&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Tick_get_count() gets the current tick value.  Then tick_calc_diff is used to calculate how many ticks there are between tick_marker and test_tick.  It’s assumed that the first parameter occurs earlier in time than the second.  The routine works even if the tick count wraps around 0xffff.  If the difference is greater than or equal to 1000, then we print something out, include the tick count we’re up to.  Then we reset tick_marker to the current tick count.&lt;br /&gt;&lt;br /&gt;Why &gt;= 1000? Why not just == 1000? Well, you can imagine that if the pic is busy doing something else, even if it’s in the main loop, then it may well be that the ticks creep past 1000, in which case, our next print out will happen after it wraps around 0xffff again, obviously not as good as just being out by 1 tick or so.  Note when you run this application however, that since our main loop is pretty simple, we almost never miss the 1000 mark and print out our Ting! on time.&lt;br /&gt;&lt;br /&gt;Have a go at tick_demo and see how accurate it is for yourself.  Make sure you adjust the timer_setup_0 values for your clock speed.  You shouldn’t have to adjust the ‘13’ etc, just the main number, eg, 3000 or in the case of the 16f device, 250.  If you were running at 20Mhz, on a 16f88, so an 8 bit timer0, can you work out what prescalar and starting value you would need to get pretty close to 1ms?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-3279005400501724018?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/3279005400501724018/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=3279005400501724018' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/3279005400501724018'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/3279005400501724018'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2008/04/8-its-about-time.html' title='9. It&apos;s about time'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-1664207423218123582</id><published>2008-04-12T12:42:00.003+01:00</published><updated>2008-04-12T12:54:54.277+01:00</updated><title type='text'>8. Serial ports</title><content type='html'>&lt;p class="MsoNormal"&gt;If you had to generalise about what’s the best feature and the worst feature of&lt;span style=""&gt;  &lt;/span&gt;pic microcontrollers, I’d have to say the best thing is that any decent model of chip has a serial port (UART) built into the hardware.&lt;span style=""&gt;  &lt;/span&gt;The worst thing is that the PWM modules suck (normally, there’s just one.&lt;span style=""&gt;  &lt;/span&gt;And even if they have an “enhanced” PWM module, it’s design for driving stepper motor H-bridges, meaning that the “four” outputs are really just two with the second one driven the opposite way).&lt;span style=""&gt;  &lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal"&gt;Anyway, the serial port rocks.&lt;span style=""&gt;  &lt;/span&gt;It means you can print things out, find out what your code is doing, debugging the old fashioned “printf” way.&lt;span style=""&gt;  &lt;/span&gt;You can even issue commands to the code and have it respond, very easily. It really does make writing programs for the pic a pleasure.&lt;span style=""&gt;  &lt;/span&gt;Sure, you can get into the hardware debugging stuff, and I’ve got an ICD2 on it’s way to have a play with – I’ll let you know what it’s like – which allows you to step through code, put in break points, monitor variables etc.&lt;span style=""&gt;  &lt;/span&gt;Still, with ICD you lose two pins, a chunk of memory and stack space.&lt;span style=""&gt;  &lt;/span&gt;I’m sure for some nasty hardware problems it could be very handy, in fact, when I was developing the serial library it could have been very useful.&lt;span style=""&gt;  &lt;/span&gt;Still, now that it’s done, it makes debugging very easy.&lt;span style=""&gt;  &lt;/span&gt;The routines are well tested and very solid.&lt;span style=""&gt;  &lt;/span&gt;They ran “out of the box” when I moved on to 18f chips as well. And best of all, you can print something out, it goes into the fifo buffer and gets shunted out the serial port at the appropriate rate.&lt;span style=""&gt;  &lt;/span&gt;Meanwhile, your program continues on executing and full speed.&lt;/p&gt;    &lt;p class="MsoNormal"&gt;So, onto using the serial port.&lt;span style=""&gt;  &lt;/span&gt;Firstly, it’s a TTL serial port – meaning that you can’t whack the tx and rx pins of the pic straight into serial port of your PC.&lt;span style=""&gt;  &lt;/span&gt;You need to adapt the polarity and voltage levels.&lt;span style=""&gt;  &lt;/span&gt;There’s a couple of easy ways to do that.&lt;span style=""&gt;  &lt;/span&gt;I use the sparkful serial module – I’ve used the RS232 Shifter &lt;st1:stockticker st="on"&gt;SMD&lt;/st1:stockticker&gt; module, but the other rs232 modules will work just as well.&lt;span style=""&gt;  &lt;/span&gt;These are great for breadboards.&lt;span style=""&gt;  &lt;/span&gt;Alternatively, you can use the Olimex boards that have a proper &lt;st1:stockticker st="on"&gt;MAX&lt;/st1:stockticker&gt;232 chip on board with all the associated capacitors.&lt;span style=""&gt;  &lt;/span&gt;These are used to bump up the serial port voltages to +/- 12v, which is the standard.&lt;span style=""&gt;  &lt;/span&gt;Most serial ports these days will work perfectly well at 5v however.&lt;span style=""&gt;  &lt;/span&gt;On the Olimex board you’ll need to wire the serial port output / input to the tx / rx pins on the pic.&lt;span style=""&gt;  &lt;/span&gt;Don’t worry about the RTS/DTR pin, it’s not necessary.&lt;/p&gt;    &lt;p class="MsoNormal"&gt;You should have no problems with any of these serial port connections with &lt;st1:stockticker st="on"&gt;USB&lt;/st1:stockticker&gt; serial port adapters.&lt;span style=""&gt;  &lt;/span&gt;So on to the software.&lt;/p&gt;    &lt;p class="MsoNormal"&gt;The serial port on pics, like most microcontrollers, is driven by the clock that the pic is running at.&lt;span style=""&gt;  &lt;/span&gt;As such, there’s not really the concept of “baud rate” or “bits per second”, or bps, at least, at the hardware level.&lt;span style=""&gt;  &lt;/span&gt;Everything is divided down from the clock rate.&lt;span style=""&gt;  &lt;/span&gt;The 16f range of pics have an 8 bit clock divider, and a “fast” and “not so fast” setting. &lt;span style=""&gt; &lt;/span&gt;Have a look at the datasheet for your pic – the section is titled “Addressable universal synchronous asynchronous receiver transmitter”. &lt;span style=""&gt; &lt;/span&gt;And you wonder why I stick to calling it “serial port”.&lt;span style=""&gt;  &lt;/span&gt;We don’t care about synchronous serial ports, they require a clock, and serial ports on PCs are asynchronous anyway. &lt;span style=""&gt; &lt;/span&gt;Notice that there’s a setting for High speed and Low speed, based on the BRGH bit of the TXSTA register. &lt;span style=""&gt; &lt;/span&gt;Hunt down the baud rate formula.&lt;span style=""&gt;  &lt;/span&gt;You’ll see that you can calculate the baud rate based on the BRGH setting, the SPBRG divider and the clock frequency.&lt;/p&gt;    &lt;p class="MsoNormal"&gt;When BRGH = 0 (Low Speed) the baud rate = FOSC/(64(SPBRG + 1))&lt;/p&gt;  &lt;p class="MsoNormal"&gt;When BRGH = 1 (High Speed) the baud rate = FOSC/(16(SPBRG + 1))&lt;/p&gt;    &lt;p class="MsoNormal"&gt;Thankfully the picpack serial port routines take away a lot of the pain.&lt;span style=""&gt;  &lt;/span&gt;Who wants to calculate these values anyway?&lt;span style=""&gt;  &lt;/span&gt;For all the popular serial port values and clock frequencies, the work has been done for you.&lt;/p&gt;    &lt;p class="MsoNormal"&gt;Load up the serial_demo project and have a look at the config.h file. &lt;span style=""&gt; &lt;/span&gt;You’ll start to see that most things you configure in a picpack project are done through the config.h file. &lt;span style=""&gt; &lt;/span&gt;&lt;/p&gt;        &lt;p face="courier new" class="MsoNormal"&gt;// - - - - - - - - - - - - - - - - - - - - &lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;// pic_serial defines&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;// - - - - - - - - - - - - - - - - - - - - &lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;        &lt;p face="courier new" class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;br /&gt;#define SERIAL_TX_BUFFER_SIZE 16&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;#define SERIAL_RX_BUFFER_SIZE 4&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;//#define SERIAL_DEBUG_ON&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;          &lt;p face="courier new" class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;// - - - - - - - - - - - - - - -&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;// General platform definitions&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;#define PLATFORM_TYPE breadboard&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;#define PLATFORM_CLOCK 12000000&lt;/p&gt;    &lt;p class="MsoNormal"&gt;The pic_serial defines are pretty obvious – you set the fifo buffer sizes for transmitted and received characters with the SERIAL_TX_BUFFER_SIZE and the SERIAL_RX_BUFFER_SIZE. &lt;span style=""&gt; &lt;/span&gt;Since the picpack serial routines are completely interrupt driven, we need a buffer to store things on the way in or way out, until your routines get around the handling them. &lt;span style=""&gt; &lt;/span&gt;Remember you need a TX buffer big enough that everything can sit there until it gets transmitted – which only occurs while interrupts are running. &lt;span style=""&gt; &lt;/span&gt;If you print out lots of stuff while in an interrupt service routine (and this means interrupts are off), it will pile up here until interrupts get turned back on and the characters can be pumped out. &lt;span style=""&gt; &lt;/span&gt;All this means is that you need a big enough buffer.&lt;span style=""&gt;  &lt;/span&gt;Otherwise the pic will appear to hang, when really what it’s doing is waiting for the buffer to empty, but it’s never going to since it’s only going to get serviced when (you guessed it) interrupts are running.&lt;/p&gt;    &lt;p class="MsoNormal"&gt;&lt;o:p&gt;&lt;/o:p&gt;It’s nothing you need to worry about until several projects down the track you’ve defined a really small buffer and are wondering why things stop working! For the moment, and generally, it won’t be a problem.&lt;/p&gt;    &lt;p class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;Set your platform type and clock speed in cycles per second – the example here is 12Mhz, but if you’re using a 16f88 with internal clock, for example, you’ll need to set this to 8000000, of course.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Have a look at serial_demo.c&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;      &lt;p face="courier new" class="MsoNormal"&gt;// configure_system&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;//&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;// Get the pic ready for everything we want to do&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;  &lt;p face="courier new" class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p style="font-family: courier new;" class="MsoNormal"&gt;void configure_system() {&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;  &lt;p style="font-family: courier new;" class="MsoNormal"&gt;&lt;span style=""&gt;            &lt;/span&gt;&lt;span style=""&gt;    &lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;    &lt;p style="font-family: courier new;" class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;        &lt;p style="font-family: courier new;" class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;      &lt;p style="font-family: courier new;" class="MsoNormal"&gt;&lt;span style=""&gt;            &lt;/span&gt;    kill_interrupts();&lt;span style=""&gt;          &lt;/span&gt;// turn off interrupts just in case&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;   turn_analog_inputs_off();&lt;span style=""&gt;       &lt;/span&gt;// kill those pesky analogue inputs&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;   serial_setup(BRGH_HIGH_SPEED, SPBRG_9600);&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;   turn_peripheral_ints_on();&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;   turn_global_ints_on();&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;  &lt;p style="font-family: courier new;" class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;In the configure_system routine, we set things up.&lt;span style=""&gt;  &lt;/span&gt;I always turn off interrupts at the start, just in case, along with turning analog inputs off. &lt;span style=""&gt; &lt;/span&gt;In this demo, it’s not strictly necessary, but always good practice unless you need them. &lt;span style=""&gt; &lt;/span&gt;See the serial_setup routine?&lt;span style=""&gt;  &lt;/span&gt;It makes it easy. &lt;span style=""&gt; &lt;/span&gt;Always use the BRGH_HIGH_SPEED setting if you’re using the pic_serial defines for the baud rate. &lt;span style=""&gt; &lt;/span&gt;Then just pop in the baud rate, and if you’ve set your PLATFORM_CLOCK rate correctly, you’re all set to go with no calculations!&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;After that, we turn on peripheral interrupts (which includes the serial port module), and global interrupts (which is the overarching control on whether interrupts are on or off).&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Our interrupt routine is as easy as this:&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p style="font-family: courier new;" class="MsoNormal"&gt;void interrupt() {&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;  &lt;p style="font-family: courier new;" class="MsoNormal"&gt;&lt;span style=""&gt;            &lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;    &lt;p style="font-family: courier new;" class="MsoNormal"&gt;&lt;span style=""&gt;            &lt;/span&gt;&lt;span style=""&gt;            &lt;/span&gt;    serial_handle_tx_isr();&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;   serial_handle_rx_isr();&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;  &lt;p style="font-family: courier new;" class="MsoNormal"&gt;}&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Picpack does all the hard work for you.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;The process_rx routine is where we respond to typed commands – in this case, we can type something in and press enter to get the pic to respond. &lt;span style=""&gt; &lt;/span&gt;Very simple commands are used here, but you can see how you could query anything, at any time, just by typing a request.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Now we’re ready to start getting some serial port action.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p style="font-family: courier new;" class="MsoNormal"&gt;&lt;span style=""&gt;            &lt;/span&gt;serial_print_str("\n\nPIC terminal\n");&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Is as easy as it gets for printing out strings.&lt;span style=""&gt;  &lt;/span&gt;Use &lt;span style="font-family:courier new;"&gt;serial_print_int&lt;/span&gt; for 16 bit unsigned integers, and &lt;span style="font-family:courier new;"&gt;serial_print_int_hex&lt;/span&gt; for printing 8 bit hex numbers. &lt;span style=""&gt; &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;So, compile the program, bootload it into your pic and start trying out some of those commands.&lt;span style=""&gt;  &lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-1664207423218123582?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/1664207423218123582/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=1664207423218123582' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/1664207423218123582'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/1664207423218123582'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2008/04/serial-ports.html' title='8. Serial ports'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-4743463805645526355</id><published>2008-04-08T22:14:00.000+01:00</published><updated>2008-04-08T22:15:17.437+01:00</updated><title type='text'>7. Bootloading</title><content type='html'>The picpack bootloader is based on the Sparkfun bootloader / screamer combination, which in turn is based on other bootloaders.  I’ve got it working on two 16f variety chips and two 18f variety – and others shouldn’t be too hard to get working.  If you do get it working on other types, please send me your settings so everyone can take use them.&lt;br /&gt;&lt;br /&gt;Here, I’m going to assume you have a 16f88 chip.&lt;br /&gt;&lt;br /&gt;Grab the 16f88 boostbloader hex file, program your pic.  To get the serial connections going you’ll need to have some sort of conversion hardware to get it to rs232 levels – I use the sparkfun module, and the Olimex boards have it built in (but not connected).&lt;br /&gt;&lt;br /&gt;Run up the screamer application (which is the windows program that sends your program to the pic) and select your com port.  Select a .hex file to download (say, the flasher program from the last tutorial) and choose download.  Reset your pic, either by powering it on, or using your MCLR reset button. &lt;br /&gt;&lt;br /&gt;The pic will boot, send a byte to the screamer application to indicate it’s ready to accept a new program.  Screamer will then send the contents of the .hex file – the boostbloader program will store the program in flash, and then execute it.    If screamer doesn’t respond, it will then go and run the last program that was downloaded.&lt;br /&gt;&lt;br /&gt;It really should be that easy.  The nice thing about the screamer app, is that when you’ve finished the download, it can flip to the terminal page, and then you can see what the pic is doing by using the serial library, printing out statements, variables, etc.  It’s all very neat and a great way to debug programs.&lt;br /&gt;&lt;br /&gt;The other thing to remember is that using a bootloader, you don’t need to worry about config bits, since these are already programmed as part of the booloader itself being put into the chip.  Of course, if you need something in the config changed, you do need to compile and re-download yourself a custom bootloader, but you’ll get pretty comfortable with all this soon.&lt;br /&gt;&lt;br /&gt;So hopefully you’re now at the point of having your leds flash again, but this time under bootloader control.  You won’t need to pull your pic out of circuit and put it in a zif socket anymore, or power it down to use ICSP. Life is great.&lt;br /&gt;&lt;br /&gt;Now it’s time to start doing more exciting things than just flash leds, cool as this is.  Our first point of call is to create a terminal program so you can type commands and get your pic to respond. On to the next tutorial…&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-4743463805645526355?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/4743463805645526355/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=4743463805645526355' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/4743463805645526355'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/4743463805645526355'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2008/04/7-bootloading.html' title='7. Bootloading'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-8626717113831006669</id><published>2008-04-08T20:01:00.000+01:00</published><updated>2008-04-08T22:14:13.818+01:00</updated><title type='text'>6. Chip Programming</title><content type='html'>Now, if you want to get this running in hardware, it’s time to talk about how to program the real chips.  There’s essentially three ways of doing that.&lt;br /&gt;&lt;br /&gt;The first, and definitely easiest (and generally most reliable) way is to plonk your chip in a ZIF-socketed programmer and use a windows program to communicate with the programmer board.  Generally these programmers use USB these days, which is pretty handy.  It does mean that you need to remove the chip from whatever its in though, in order to program it.&lt;br /&gt;&lt;br /&gt;The second way, which is essentially the same as the first, is to use an ICSP.  The In-Circuit Serial Programmer is just a fancy way of defining the pins that need connecting in order to program the device.  On pics there is a clock and data line, Vdd (positive supply), ground and most likely a “higher voltage” programming line as well. If you put 12v or so on the Vpp line, the chip will wake up in programming mode, allowing you to read and write flash, eeprom and “config” settings. As you can imagine, in option one, these connections where made directly with the chip.  With an ICSP “socket” you can leave the chip in place and still program it.  You do need to generally disconnect the main supply, however.&lt;br /&gt;&lt;br /&gt;The third way which is definitely the fastest and most convenient is to use a bootloader.  This is a small program that is resident in your pic that communicates with a pc-based application in order to download the real program you want to store (and run).   Of course, in order to get this bootloader in there in the first place, you have to use method one or two – after that you can use a bootloader.  This is actually quite neat, since most bootloaders use a serial interface to work, you can quickly download a program over the serial port and then immediately see the results of it.  Any debug can be done over the serial link as well, making the process very neat.&lt;br /&gt;&lt;br /&gt;In the direct programming methods (one and two) you’ll also need to set config options for the pic.  These are also known as “fuses”, even though I’m pretty sure these days they’re just a chunk of memory like everything else.  They do have the distinction however of allowing the functionality of the pic to change before it actually starts running a program.  An example is the MCLR pin – which can often either be a digital IO pin, or a pin which when connected to ground, resets the pic.  Clearly the chip needs to know which is the correct option before it actually starts executing a program.&lt;br /&gt;&lt;br /&gt;18f chips tend to have richer (that is, more complex) sets of config bits than the 16f series.  However, the main flags to be concerned with are:&lt;br /&gt;&lt;br /&gt;Oscillator – do you want the chip to run with an internal clock , or ouse an external crystal (with associated circuitry, usually just two caps and the crystal.&lt;br /&gt;&lt;br /&gt;MCLR – usally it’s nice to have a press button reset, so this is handy to leave on, unless you need the IO.  You’ll need to tie the pin to Vdd via a resistor, with the button pulling it to ground when pressed. Tip: Don’t leave MCLR floating (ie, unconnected), otherwise the chip will be in a constant state of resetting and never actually do anything.  If the pin is configured as an IO pin, of course you don’t need to worry about this.&lt;br /&gt;&lt;br /&gt;Watchdog timer – pics can set a watchdog timer to reset the chip if there’s a problem.  Turn this off for the moment.&lt;br /&gt;&lt;br /&gt;Just about everything else can be switched off, at least, in these early days.&lt;br /&gt;&lt;br /&gt;In SourceBoost, you set the config bytes with the data pragma:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;#pragma DATA _CONFIG, _CP_OFF &amp;amp; _CCP1_RB0 &amp;amp; _DEBUG_OFF &amp;amp; _WRT_PROTECT_OFF &amp;amp; _CPD_OFF &amp;amp; _LVP_OFF &amp;amp; _PWRTE_OFF &amp;amp; _WDT_OFF &amp;amp; _PWRTE_ON &amp;amp; _BODEN_OFF &amp;amp;_MCLR_ON &amp;amp; _INTRC_IO  &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Have a look through the include file for your pic (eg, pic16f88.h) in the sourceboost include directory to see the options for your pic.  Match this with what you want from your datasheet, and “&amp;amp;” them altogether.  This is the config for the 16f88 pic, a very handy general purpose chip.  It’s got 4k words of flash, 256 bytes of EEPROM and 384 bytes of RAM.&lt;br /&gt;&lt;br /&gt;You’ll need a pic, run Vdd to 5 volts and Vss to ground, attach a led to one of the pins (in this case, we’re going to use RA0) and route the led to ground via a resistor – 330R should do it.  Route MCLR to Vdd via a resistor (say 10k).  Take the .hex file generated by the compiler, use your programming utility to program the pic and see if you can get that led flashing.&lt;br /&gt;&lt;br /&gt;Once you’re this far, you’re reading to get a bootloader going.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-8626717113831006669?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/8626717113831006669/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=8626717113831006669' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/8626717113831006669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/8626717113831006669'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2008/04/6-chip-programming.html' title='6. Chip Programming'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-9191634018435577793</id><published>2008-04-07T21:48:00.004+01:00</published><updated>2008-04-19T13:19:29.537+01:00</updated><title type='text'>4. Compilers</title><content type='html'>You can, of course, program pics in assembly language.  There are people out there who will tell you that to get the real power out of these little dudes you need to program them in assembly.  These people are insane and need medical help.  Pick a higher level language and use it.  Once you have to start worrying about jumping between code pages and variables in different pages of ram, you’ll dump assembly as fast as very fast thing.&lt;br /&gt;&lt;br /&gt;I use the SourceBoost compiler.  It’s got great support, isn’t expensive compared with some of them out there and has free (albeit limited) trial versions.  There are lots of other C compilers out there for pics.  Of course, you can choose whichever compiler you like and best of luck – C ain’t as portable as it used to be, especially in the world of embedded compilers.  It’s not that hard though, so if you use something else, then you’ll be able to make use of the stuff here.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-9191634018435577793?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/9191634018435577793/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=9191634018435577793' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/9191634018435577793'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/9191634018435577793'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2008/04/4compilers.html' title='4. Compilers'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-7733729597213316680</id><published>2008-04-07T21:48:00.003+01:00</published><updated>2008-04-07T21:50:17.832+01:00</updated><title type='text'>5. Your first pic program</title><content type='html'>Okay, so let’s get some leds flashing.   First we’ll get a virtual led flashing – then go for the real thing.&lt;br /&gt;&lt;br /&gt;Open up the flash project in adventures\flash.  Add a led from the plugins menu, configure it to use portb.  Pics have a concept of ports – really it’s just a way of distinguishing all the pins from one another. Instead of having IO pins 1 through 24, they’re broken up into “ports”.  Nothing magic about them, other than the fact you can write to a whole port at once if you want (ie, change or read all 8 pins in one instruction.&lt;br /&gt;&lt;br /&gt;Compile the program by pressing F7.  Hit the debug button (it looks like a little bug) Hit F5 to run the program.  And watch, in astonishment as the led flashes. Very. Slowly.&lt;br /&gt;&lt;br /&gt;Actually the real hardware runs a lot faster.  Before we get some hardware going, lets have a look at what this program does.  Pull up flash.c. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;/* Flasher! &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;A good little test program that flashes leds..&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;*/&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;#include "pic_utils.h"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Pic_utils.h includes a bunch of handy stuff, and I include it every time.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;#pragma CLOCK_FREQ 8000000&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This tells the compiler how fast you expect the clock to be running.  This is so the linker can generate a “delay” routine for you that matches your clock speed.  Delays are really carefully crafted loops.  We really only know how long 250ms is by knowing the clock rate and how make clock cycles a given set of instructions take to execute.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;#define flash_port PORTB&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;#define flash_pin  0&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Get into the habit using #defines wherever and whenever you can.  It means that you can make simple hardware changes (like using port a instead of port b) by doing equally simple software changes (changing the #define) instead of having to find every instance of port b when you are referring to your flashing led pin, and changing them.  Believe me, you’ll be thanking me for this later.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;void interrupt () {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Pics have at least one, if not two, interrupt routines that are executed upon certain events happening, like a timer going off or a serial character being received or a pin changing level.  We don’t do anything with it here – but I include so that if we’re using a bootloader, everything will be at the right location in memory. More on this later.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;void flash() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    toggle_pin(flash_port, flash_pin);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;}     &lt;/span&gt;  &lt;br /&gt;&lt;br /&gt;This is where the heavy lifting is done.  We just flip the output of this pin to high if it’s low and low if it’s high every time this function is called.   Toggle_pin is a pic_utils routine, which we’ll explore more a little later.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;void main() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    turn_off_analog_inputs();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    make_output(flash_port, flash_pin);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    while (1) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;        flash();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;        delay_ms(250);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;        delay_ms(250);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    }        &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The main routine has a couple of interesting things in it.  Firstly, some ports can be analog inputs or digital inputs, and by default they start out life when booted as analog inputs.  So this nifty routine fixes that for our purposes.  Then we set the flash port / pin combination to be a digital output (the default, once it’s no longer an analogue input, is a digital input).  Mind you, not all pins can be an analogue input, but just turning them all into digital pins at the start means we don’t have to do datasheet hunting at this stage of the game.&lt;br /&gt;&lt;br /&gt;Finally, in our main loop we flip the led, then wait 500ms before doing it all again. Forever.  Seeing that the led should light every second or so, you get a feeling how much slower the hardware emulator is running than the real hardware.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-7733729597213316680?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/7733729597213316680/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=7733729597213316680' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/7733729597213316680'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/7733729597213316680'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2008/04/5-your-first-pic-program.html' title='5. Your first pic program'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-4687881933922203839</id><published>2008-04-07T21:43:00.002+01:00</published><updated>2008-04-07T21:47:52.040+01:00</updated><title type='text'>3. Take your pic</title><content type='html'>These series of tutorials cover the Microchip pic family of microcontrollers.  There are many other types of microcontrollers.  If any of those take your fancy, you’ll find that beyond the specifics, a lot of what you learn here will apply for those ones as well.  I happened to stumble into pics first and once you’ve made the investment into programmers, and prototyping gear and compilers and code, it’s hard to switch.  Maybe I’ll try another variety someday – a lot of people talk positively about the AVR family for example.  Whatever.  This is about Microchip pics.  Go fight your religious wars elsewhere.&lt;br /&gt;&lt;br /&gt;You can get pic chips with as few as six pins and as many as, well, lots.  Hundreds even.  The smaller varieties have less memory and less functionality, and they’re cheaper obviously as well.  I think the 16 and 18 series are the most fun – they’re a good platform to build on and once you have something working, you can port it to a smaller pic if you want something cheaper.&lt;br /&gt;&lt;br /&gt;So what’s in these little guys?  Each pic has some flash memory, it may have some eeprom memory as well.  It has a number of hardware blocks that might be as simple as some inputs and outputs or as complex as a full blown USB implementation.&lt;br /&gt;&lt;br /&gt;These two different types of memory are important.  There’s normally lots of flash compared with much less eeprom memory.  Flash is cheap, and hence big, eeprom is expensive.  Flash can be overwritten 10,000 times.  Eeprom can be overwritten a million times.  So you can see that flash is good for programs, eeprom is good for settings, configuration, storing things that change.&lt;br /&gt;&lt;br /&gt;In terms of pins on the chip itself, two are reserved for power.  Many  pics run at 5 volts (eg 16f88) at high clock speeds, or a more expensive variety (eg 16lf88) that runs as low as 2 volts.  At those lower voltages however, often you can’t clock them as fast.&lt;br /&gt;&lt;br /&gt;Speaking of clocks, with hardware it’s often all about timing.  Knowing precisely how fast the pic is running turns out to be quite important (although I spend a fair amount of time trying to avoid timing issues).  As such, the most accurate way to clock a pic is via a crystal, plus two small capacitors which help stabilise the oscillator circuit.  This does take up two pins, however, and given that pins on these babies are often limited, microchip give you the option of running an internal clock instead.  The internal clock is an RC clock – meaning it’s based on the charging time of a capacitor.  Since capacitors are harder to make accurately than crystals, the timing is not as precise.  Still, you get two pins back.  A trade off.&lt;br /&gt;&lt;br /&gt;Unfortunately for us, pics take four oscillator cycles to process one instruction.  That means that when you’re running with an internal clock (often 8Mhz), you’re running at 2 million instructions per second (mips).  That’s one instruction every 1 / 2,000,000 seconds, or every 0.5 microseconds, or 500 nanoseconds.  Sounds fast until you actually try to do something even vaguely complicated Then you’ll be scraping for every mip you can get your hands on.  And that’s because it’s a RISC device – a reduced instruction set.  These little guys only have one register and have no concept of numbers bigger than 255.  It turns out that you can get quite a lot out of these simple instructions though, including 32 bit numbers and floating point math, but my point is there’s no fdiv instruction here – you need to do quite a few instructions to accomplish anything much. Oh, and that’s not quite the full story either – some instructions take two instructions to execute – that is, 8 clock cycles.   Still, for the purpose of this experiment, we’ll just blindly assume that 4 clock cycles is enough of a sacrifice to make.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-4687881933922203839?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/4687881933922203839/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=4687881933922203839' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/4687881933922203839'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/4687881933922203839'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2008/04/3-take-your-pic.html' title='3. Take your pic'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-8142965779817499735</id><published>2008-04-07T21:42:00.000+01:00</published><updated>2008-04-07T21:43:03.603+01:00</updated><title type='text'>2. Microcontrollers</title><content type='html'>&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&lt;/o:p&gt;These days we have devices that don’t just have four gates in them, they have tens and hundreds of thousands of gates.&lt;span style=""&gt;  &lt;/span&gt;So much so that these devices can run a series of simple instructions.&lt;span style=""&gt;  &lt;/span&gt;A lot of the external circuitry that was required in the past is simply not necessary.&lt;span style=""&gt;  &lt;/span&gt;As I always suspected, software has taken over the world.&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;    &lt;p class="MsoNormal"&gt;&lt;o:p&gt;&lt;/o:p&gt;Making software is a creative act, and like writing music, I’m always astonished at the fact that you essentially creating something from nothing.&lt;span style=""&gt;  &lt;/span&gt;Now that microcontrollers are cheap enough for anyone to play with, it means that all those complicated little electronic things can now be created out of software, not hardware.&lt;span style=""&gt;  &lt;/span&gt;And creating it out of software means that we are creating these things out of nothing.&lt;span style=""&gt;  &lt;/span&gt;Astonishing.&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&lt;/o:p&gt;Anyway, enough philosophy.&lt;span style=""&gt;  &lt;/span&gt;Let’s make some leds flash.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-8142965779817499735?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/8142965779817499735/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=8142965779817499735' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/8142965779817499735'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/8142965779817499735'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2008/04/2-microcontrollers.html' title='2. Microcontrollers'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-9106480282628356067</id><published>2008-04-07T21:40:00.002+01:00</published><updated>2008-12-09T08:54:31.906Z</updated><title type='text'>1. Introduction</title><content type='html'>&lt;p class="MsoNormal"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_bEFwpcEs1Go/SCybnY1oJSI/AAAAAAAAAAs/-gYEpQBnt-s/s1600-h/285081870_4ab67ac2af_o.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 248px; height: 167px;" src="http://4.bp.blogspot.com/_bEFwpcEs1Go/SCybnY1oJSI/AAAAAAAAAAs/-gYEpQBnt-s/s320/285081870_4ab67ac2af_o.jpg" alt="" id="BLOGGER_PHOTO_ID_5200702770690663714" border="0" /&gt;&lt;/a&gt;When I grew up, I was fascinated by electronics.&lt;span style=""&gt;  &lt;/span&gt;I had one of those 150-in-one kits, where components could be hooked up by connecting wires between springs.&lt;span style=""&gt;  &lt;/span&gt;Each spring had a number.&lt;span style=""&gt;  &lt;/span&gt;I didn’t really understand what everything actually did.&lt;span style=""&gt;  &lt;/span&gt;I just followed the instructions.&lt;span style=""&gt;  &lt;/span&gt;Connect 12-15-25-3.&lt;span style=""&gt;  &lt;/span&gt;And so on.&lt;span style=""&gt;  &lt;/span&gt;After 20 minutes, you had a working siren, or an AM radio, or a light detector.&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;    &lt;p class="MsoNormal"&gt;&lt;o:p&gt;&lt;/o:p&gt;Eventually I started to buy electronic magazines.&lt;span style=""&gt;  &lt;/span&gt;Back in those days occasionally the magazines would include a printed circuit board on the front panel.&lt;span style=""&gt;  &lt;/span&gt;One of the first kits I made was a space invaders game.&lt;span style=""&gt;  &lt;/span&gt;That’s what they called it. There was a vertical row of leds, and the leds would light in succession from top to bottom.&lt;span style=""&gt;  &lt;/span&gt;The idea was to press a button when the lowest led was lit, there by killing the space invader.&lt;span style=""&gt;  &lt;/span&gt;If you did that, then your score (which was indicated at the top of the board in a binary form, again in leds) increased by one.&lt;span style=""&gt;  &lt;/span&gt;The second last led was red – if you pressed the button when that led was lit, then your score went back down to zero.&lt;span style=""&gt;  &lt;/span&gt;It was a really simple game, but it took four or five integrated circuits from the 4000 series and a bunch of other components to make it work.&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&lt;/o:p&gt;Years later I’m still making leds light up.&lt;span style=""&gt;  &lt;/span&gt;Trust me, getting this all working is quite a challenge the first time.&lt;span style=""&gt;  &lt;/span&gt;It’s a great feeling when you finally get that led flashing…&lt;/p&gt;&lt;p class="MsoNormal"&gt;- Photo thanks to Chris Glass&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-9106480282628356067?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/9106480282628356067/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=9106480282628356067' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/9106480282628356067'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/9106480282628356067'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2008/04/1introduction.html' title='1. Introduction'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_bEFwpcEs1Go/SCybnY1oJSI/AAAAAAAAAAs/-gYEpQBnt-s/s72-c/285081870_4ab67ac2af_o.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4829924363554235528.post-1622568974695859174</id><published>2008-03-31T13:22:00.004+01:00</published><updated>2008-03-31T13:28:05.732+01:00</updated><title type='text'>Welcome!</title><content type='html'>I first became interested in embedded systems while working for a broadcaster in Australia.  While working for a software company in London, we needed to develop a motion activated remote control - and with nobody else willing to take it on, I thought, how hard can it be?&lt;br /&gt;&lt;br /&gt;Microcontroller programming is a lot of fun - there's something nice and clean about such small, simple environments.  You can do things with microcontrollers that interact with the real world, LEDs, LCDs, buttons, GPS devices, temperature sensors, RF connections and more.  After a while, you start to realise how many things around the home are actually run by microcontrollers... They really do run the planet these days.&lt;br /&gt;&lt;br /&gt;In any case, I created this blog to post the things I do and share the code I write.&lt;br /&gt;&lt;br /&gt;My microcontroller of choice is the Microchip PIC, which has a lot of support out there on the net.  If someone hasn't got the code you need already, then there's bound to be something close.&lt;br /&gt;&lt;br /&gt;I use the &lt;a href="http://www.sourceboost.com"&gt;Sourceboost &lt;/a&gt;development environment in C.  It's a great compiler with fantastic support from the guys to made it.  All the examples here use it.&lt;br /&gt;&lt;br /&gt;Hopefully this web site will help you on your embedded adventure.  I've had a lot of fun building little things that do stuff - I hope you will too.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4829924363554235528-1622568974695859174?l=embeddedadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://embeddedadventures.blogspot.com/feeds/1622568974695859174/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4829924363554235528&amp;postID=1622568974695859174' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/1622568974695859174'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4829924363554235528/posts/default/1622568974695859174'/><link rel='alternate' type='text/html' href='http://embeddedadventures.blogspot.com/2008/03/welcome.html' title='Welcome!'/><author><name>Ian Harris</name><uri>http://www.blogger.com/profile/15487144968961769398</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
