<?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-8909459762367220480</id><updated>2012-02-12T14:12:25.111-08:00</updated><category term='puredata'/><category term='pokey'/><category term='lasers'/><category term='pic'/><category term='lego'/><category term='ftdi vnc2 vinculo vnclo vinculum vinclo review'/><category term='launchpad'/><category term='reason'/><category term='midi'/><category term='spectrum diy'/><category term='solid state tesla coil'/><category term='electronics'/><title type='text'>Stuff and Nonsense</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>34</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-5613140055788321318</id><published>2012-02-08T14:42:00.000-08:00</published><updated>2012-02-10T14:43:55.551-08:00</updated><title type='text'>Digital POV clock working! mostly</title><content type='html'>Well, without too much pain, its just about working!&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://i.ytimg.com/vi/kPdYpST_yoE/0.jpg" height="266" width="320"&gt;&lt;param name="movie" value="http://www.youtube.com/v/kPdYpST_yoE?version=3&amp;f=user_uploads&amp;c=google-webdrive-0&amp;app=youtube_gdata" /&gt;&lt;param name="bgcolor" value="#FFFFFF" /&gt;&lt;embed width="320" height="266"  src="http://www.youtube.com/v/kPdYpST_yoE?version=3&amp;f=user_uploads&amp;c=google-webdrive-0&amp;app=youtube_gdata" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;br /&gt;Here is how I went about it, which might help you if you want to make one yourself...&lt;br /&gt;&lt;br /&gt;When you pick a drive to use, make sure it has four conductors going to the motor ("Y configuration") rather than three ("Delta configuration") if you want to use the TDA5140A/TDA5144 to drive it. The conductors are likely to be on a tiny flexible ribbon going into the motor on the back of the board.&lt;br /&gt;&lt;br /&gt;Get yourself a proper Torx driver to take out the screws holding the drive together (you can work around it with other things but you will drive yourself crazy). Remove the PCB from the back, being careful not to damage the ribbon going to the motor. Remove the metal front cover, remembering that there are usually a few screws hidden behind labels. Less brute force, more patience :o)&lt;br /&gt;&lt;br /&gt;Remove the head and magnets by taking out screws. Take out the central screw of from the hub and take off the platter. You might be unlucky and have a platter which sits very low to the backplane. You might need to improvise to jack it up a bit to leave space behind from the leds, or you could combine parts from a couple of drives (as I did) to get the best combination. Another thought is to cut windows for the LEDs in the aluminium backplane, but that seems like a lot of effort!&lt;br /&gt;&lt;br /&gt;My&amp;nbsp;replacement&amp;nbsp;platter &amp;nbsp;was cut out of FR4 single sided copper clad board using a 70mm holesaw. A smaller holesaw (19mm I think) was used to cut out the centre, which was then filed to snugly fit the hub of the 2.5" laptop drive. The digits were actually laid out in EAGLE (PCB designer) since it was the only package I had to hand which let you type in rotation angles for characters. This worked OK, but a decent vector drawing package will have more interesting font options. The platter was etched just like a PCB.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-YKuduYZNMyc/TzGzblhEfiI/AAAAAAAACVI/0LcrVg_WWAU/s1600/DSC00014+%25282%2529.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://2.bp.blogspot.com/-YKuduYZNMyc/TzGzblhEfiI/AAAAAAAACVI/0LcrVg_WWAU/s320/DSC00014+%25282%2529.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;It was challenge to fit LEDs and section dividers in the few mm of room behind the platter. My solution was to use SMD components and mount them on flexible kapton copper clad board (awesome stuff) which I picked up on eBay. Just press and peel and etch it as a normal PCB. The finished result, with components on, is only a mm or two in height and can be shaped with scissors and a knife, then glued down in the space under the platter. I made the light dividers from a bit of card cut with a knife and glued to the flexible board.&lt;br /&gt;&lt;br /&gt;To index the rotation I used a reflective surface sensor (Osram SFH9202) which detects the passing of &amp;nbsp;a piece of white paper stuck to the back of the platter. I used a strip of matt black insulation tape to give decent contrast on the rim of the platter (FR4 is a bit shiny).&lt;br /&gt;I was a bit worried that the sensor seemed to be getting hot. I am still not convinced this is right, but looking at the data sheet they do dissipate 80mW, and I tried 3 of them and they all did it, so maybe this is right (it hasn't blown up yet!)&lt;br /&gt;&lt;br /&gt;The sensor output is quite "analog" and doesn't, by itself, give a nice sharp switching signal. I should have shopped more carefully since Osram do the same sensor with a built in Schmitt trigger output. Still, I had some CD40106 &amp;nbsp;Schmitt trigger inverter chips so I used one of those to give me a clean logic output and it seems to work fine now.&lt;br /&gt;&lt;br /&gt;The main board was designed in EAGLE and etched on SRBP using some cheap toner transfer film from a chinese ebay shop. This film is great! it works better than the much more expensive press'n'peel blue and seems less fussy about your ironing technique (i have none). Another first was to etch this with Hydrochloric Acid and Hydrogen Peroxide mixture rather than Ferric Chloride. It is very fast and resulted in less erosion of tracks under the toner, but it also resulted in a nasty lingering chlorine smell pervading the house.&lt;br /&gt;&lt;br /&gt;I really enjoy working with SMDs these days, but I used to be terrified of them. Those tiny surface mount components have many advantages: They tend to be cheaper, your boards can be much smaller and need less drilling, and the result is actually really satisfying. I'd say the most important things are magnification (I use a 10x &amp;nbsp;loupe) a decent iron with a small tip (e.g. 0.4 or 0.8mm needle tip), fine solder (e.g. 0.015"), tweezers and a flux pen. Most important of all is practice and expecting it to all go wrong at least a couple of times before you get on a roll with it. Then you'll never look back :)&lt;br /&gt;&lt;br /&gt;I'll admit I used solder paste for a couple of the components (the LEDs and their resistors, the two tiny resistor networks, the 16MHz&amp;nbsp;resonator for the Atmega328). I used a hot air tool to reflow the paste. Everything else was done with an iron. The LEDs, resistors and small caps are 0805 size.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-LmT2nx-RFoY/TzGxVc4LIFI/AAAAAAAACUk/s5kdUVWUiCU/s1600/DSC00018+%25282%2529.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://1.bp.blogspot.com/-LmT2nx-RFoY/TzGxVc4LIFI/AAAAAAAACUk/s5kdUVWUiCU/s320/DSC00018+%25282%2529.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;I have a small stock of M41T100 realtime clock chips in SOIC8 packages (from an ebay bargain) and I used one of these on this project, with a backup battery.&lt;br /&gt;&lt;br /&gt;The MCU is an Atmega328 set up with Arduino bootloader. The code is all Arduino stuff. The Arduino drives the LEDs through a ULN2803 transistor array, since these LEDs are powered in groups of 3 and draw something like 30mA each, which would be too much to drive directly from the Arduino digital output pins.&lt;br /&gt;&lt;br /&gt;Last but certainly not least, the hard drive motor is driven by a TDA5144.&amp;nbsp;A word of warning - Don't think you can put power to a hard disk motor and it will spin. These are brushless motors and need electronics to make them work.&amp;nbsp;If you want to try any HDD motor project I recommend you invest in a special IC for it. The Philips TDA5140A and TDA5144 have been perfect for the job in my experience (The TDA5140 - without the A - seems more finicky to get working). You can certainly make your own brushless DC motor controller, but that is a project by itself and I prefer to jump in with the fun stuff :)&lt;br /&gt;&lt;br /&gt;Something I was glad I did was to add isolation jumpers to the board so I could power up the Arduino stuff without the motor starting, and vice-versa.&lt;br /&gt;&lt;br /&gt;Code and EAGLE files can be found here&lt;br /&gt;&lt;a href="https://github.com/hotchk155/DigiPovClock"&gt;https://github.com/hotchk155/DigiPovClock&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-5613140055788321318?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/5613140055788321318/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2012/02/digital-pov-clock-working-mostly.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/5613140055788321318'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/5613140055788321318'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2012/02/digital-pov-clock-working-mostly.html' title='Digital POV clock working! mostly'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-YKuduYZNMyc/TzGzblhEfiI/AAAAAAAACVI/0LcrVg_WWAU/s72-c/DSC00014+%25282%2529.JPG' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-6371507781803881311</id><published>2012-02-01T02:10:00.000-08:00</published><updated>2012-02-11T11:53:42.439-08:00</updated><title type='text'>POV Digital Clock on 2.5" HDD Platter</title><content type='html'>Just starting this project, which again uses a 2.5" laptop drive.&lt;br /&gt;&lt;br /&gt;Last year I made a POV "slot" clock on a HDD platter, inspired by other peoples projects I saw online. Around the same time saw an excellent project on YouTube where someone had made a digital POV clock by spinning a set of digit-shaped windows, in front of a row of LEDs. By illuminating each LED when the appropriate digit was in front of it, a row of digits can be displayed... aka a digital clock (http://www.youtube.com/watch?v=7Qyawcw-ots)&lt;br /&gt;&lt;br /&gt;That project used a 3.5" drive and it looked like the digits were actually laser or plasma cut into the metal platter itself. I decided to make an easier version by etching the digits into a piece of FR4 copper clad board to replace the platter. FR4 (the fibreglass PCB backing material) is quite translucent so it should transfer the light nicely from LEDs placed behind it.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-M91Wjq9rI84/TykPdzuIsGI/AAAAAAAACTk/_M3CCL8KSxY/s1600/DSC00005%25281%2529.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://2.bp.blogspot.com/-M91Wjq9rI84/TykPdzuIsGI/AAAAAAAACTk/_M3CCL8KSxY/s320/DSC00005%25281%2529.JPG" width="225" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;So far I just have the platter made. I am using a 2.5" laptop drive and the space behind the platter is very limited, so I will probably place the LEDs on flexible kapton copper-clad sheet and put a row of windows cut in plastic sheet over the top to stop cross-illumination.&lt;br /&gt;&lt;br /&gt;I'll spin the disk using the same TDA5144 circuit I used in the previous project but&amp;nbsp;I'm not sure about indexing yet... there is not really space on the platter to cut a slot for a photointerrupter, and a magnet on the disk (for a fixed hall sensor) would need a counterweight and might not fit. I might try an IR reflective sensor here, but need to play with them a bit first as I've not used them before.&lt;br /&gt;&lt;br /&gt;Keep ya posted!&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-6371507781803881311?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/6371507781803881311/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2012/02/pov-digital-clock-on-25-hdd-platter.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/6371507781803881311'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/6371507781803881311'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2012/02/pov-digital-clock-on-25-hdd-platter.html' title='POV Digital Clock on 2.5&quot; HDD Platter'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-M91Wjq9rI84/TykPdzuIsGI/AAAAAAAACTk/_M3CCL8KSxY/s72-c/DSC00005%25281%2529.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-4285076982133327034</id><published>2012-02-01T01:51:00.000-08:00</published><updated>2012-02-10T14:59:55.429-08:00</updated><title type='text'>POV Fun With 2.5" Hard Disk Drives</title><content type='html'>I picked up a few faulty laptop drives cheap on ebay to take to bits and use for POV projects. I haven't finished them yet, but have been tinkering over time and will post my progress as I go.&lt;br /&gt;&lt;br /&gt;For the first one I wanted to put a row of SMD LEDs on the platter itself (or at least on a bit of PCB replacing the platter). The problem is powering the thing... I still need to play with inductively coupled coils for power transfer, but for now I decided to use batteries.&lt;br /&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-d_wolD4f1Lc/TykLvzYpHoI/AAAAAAAACTY/_7kv-XYynkM/s1600/DSC00044.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="240" src="http://4.bp.blogspot.com/-d_wolD4f1Lc/TykLvzYpHoI/AAAAAAAACTY/_7kv-XYynkM/s320/DSC00044.JPG" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;With CR1216's and 1117 regulator&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;I started with a couple of CR1216 cells in holders - they balanced pretty well when the disk span up and it didn't vibrate too much. Unfortunately when I built up the rest of the circuit I hit a problem.. the LEDs would start up fine but after a few seconds they had faded down to nothing. Fresh batteries - same thing.&lt;br /&gt;&lt;br /&gt;CR1216's are 3V lithium batteries (putting out about 3.3V) so I had a 1117 5V regulator on board to give me 5V for the PIC16F688 and the LEDs. I wondered if the current draw was reducing the battery EMF right down below the drop-out voltage of the reg so basically nothing got through the regulator. However when I removed the regulator from the circuit exactly the same thing happened. I guess CR1216's just don't have the oomph for running these high power LEDs :o(&lt;br /&gt;&lt;br /&gt;Then I removed the CR1216 holders and put a couple of LR44 holder in their places. LR44's are alkaline button cells at 1.5V and they are a bit bigger than the CR1216's so I worried a bit about their mass on the spinning disk, but it seemed I could get away with that and they didn't fly off or anything (well, maybe just the once..)&lt;br /&gt;&lt;br /&gt;The other concern was the lower voltage. I would get 3V instead of 5V to power the LEDs, so would they light properly? They did :o) However, the 3144 hall-effect switch I was going to use for indexing needs 4.2V minimum so I could not use that. Therefore I am currently able to get some pretty, but not stable, patterns while I wait for some new hall switches to arrive (with 3V minimum supply).&lt;br /&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-Ht7W4eOl-oI/TycHKsbVAMI/AAAAAAAACR8/TGqSFcbd1GI/s1600/DSC00064.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="240" src="http://1.bp.blogspot.com/-Ht7W4eOl-oI/TycHKsbVAMI/AAAAAAAACR8/TGqSFcbd1GI/s320/DSC00064.JPG" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;With LR44's and reg removed&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;Once I have the new hall switch I should be able to index the position of the disk using a magnet fixed below it, then I want to display text on the platter. This is really a test... the PIC doesn't have the memory to do much and the batteries probably wont last that long, but I hope to make another with external power (either with a brush to the back of the platter - there is continuity through the hub which makes that easier - or by inductive coupling)&lt;br /&gt;&lt;br /&gt;This clip shows it in action. The data is just a binary counter for something to display, but its pretty&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="https://picasaweb.google.com/lh/photo/oNvZVqccUmsyFlJO_3c4P9MTjNZETYmyPJy0liipFm0?feat=embedwebsite"&gt;&lt;img src="https://lh4.googleusercontent.com/-N8K1xbD0Oiw/TycJEWa_nPI/AAAAAAAACS0/Yp02Z64Uv3E/s288/platterpov-1.m4v.jpg" height="216" width="288" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="font-family:arial,sans-serif; font-size:11px; text-align:right"&gt;From &lt;a href="https://picasaweb.google.com/105009608886388132613/POVOnLaptopHddPlatter?authuser=0&amp;feat=embedwebsite"&gt;POV on laptop hdd platter&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-4285076982133327034?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/4285076982133327034/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2012/02/pov-fun-with-25-hard-disk-drives.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/4285076982133327034'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/4285076982133327034'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2012/02/pov-fun-with-25-hard-disk-drives.html' title='POV Fun With 2.5&quot; Hard Disk Drives'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-d_wolD4f1Lc/TykLvzYpHoI/AAAAAAAACTY/_7kv-XYynkM/s72-c/DSC00044.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-7706797849876217501</id><published>2012-01-08T06:21:00.000-08:00</published><updated>2012-01-24T16:34:59.184-08:00</updated><title type='text'>Midi-izing the Reissue Stylophone</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;A while back I did a "midi conversion" of a couple of Stylophones (The original analog model). I did this by removing the Stylophone electronics and leaving just the stylus, keyboard and resistor ladder. Using the keyboard as a voltage divider its then possible to connect the stylus to an analog input of a microcontroller (such as Arduino) and read the analog voltage to work out which note is being touched, then send out MIDI note data accordingly.&lt;br /&gt;&lt;br /&gt;There are a few problems with this approach:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The stylus, keyboard and resistor ladder need to be disconnected from the rest of the stylophone circuitry... Looking at the stylophone schematic the best I could do was a minimum of three connections to break. It wouldn't be possible to have the original sound at the same time as MIDI doing it this way.&lt;/li&gt;&lt;li&gt;As with any mapping from an analog voltage to a range of discrete values there is a risk that a bit of dirt or grime on the keyboard will add enough resistance to cause the wrong note to be mapped. Not good!&lt;/li&gt;&lt;li&gt;Original Stylophones are classic bits of kit and ripping the guts out of them doesn't feel right. Also they aint getting any cheaper.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Since I had a couple of "reissue" Stylophones I picked up on ebay I decided to see if they might prove a better bet for a conversion...&lt;br /&gt;&lt;br /&gt;The first problem was getting inside the thing... while the old Stylophone closed with a clip-on back, the new one is &lt;b&gt;&lt;i&gt;glued shut &lt;/i&gt;&lt;/b&gt;and getting it open without breaking any of the plastic is easier said than done.&lt;br /&gt;&lt;br /&gt;Expecting similar nasty cost cutting inside I was actually surprised to find how much is actually in these things. There are no less than four separate circuit boards all individually screwed down to the case and connected with wires (although they are crappy wires with joints that snap when touched)&lt;br /&gt;&lt;br /&gt;Removing the boards from the case I found there is the obligatory&amp;nbsp;chip-on-board&amp;nbsp;"black blob" and a few SMD components on the main board. As I expected these new Stylophones do away with the analog tone generator circuit in favour of some custom chip that presumably digitally creates the sound.&amp;nbsp;There is also a through-hole soldered amplifier board and separate carriers for the power/vibrato switches and volume pot.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-4gxDeMaqkBU/Twmljy4DX6I/AAAAAAAACQA/gF2Wc5vztfU/s1600/DSC00161.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://3.bp.blogspot.com/-4gxDeMaqkBU/Twmljy4DX6I/AAAAAAAACQA/gF2Wc5vztfU/s320/DSC00161.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Those chip-on-board blobs are usually heart-sinkingly unhackable and the sight of one usually spells the end of any thoughts of doing anything interesting. However I was intrigued to see that there was a separate trace from each keyboard pad to the blob, and checking the stylus I found it was wired directly to the +4.5V supply.... so could it be that we had a digital inputs line for each keyboard pad, with some pull-down resistance? That would almost be too good to be true... but true, it was!&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;So why is that good? well microcontrollers like the Arduino love to read digital (i.e. ON/OFF) inputs. These are nice and reliable without the dirty connection issues of analog inputs, but&amp;nbsp;not only that, you can "piggy back" your inputs off the original input lines (since you are just reading a voltage, not drawing a current). What this means is that you can read the notes being played, while the Stylophone circuit is still attached to the keyboard and playing normally. Also you should be able to get an Arduino to actually play the Stylophone, by feeding ON (logic HIGH) values into the lines... but I might leave that till another day :)&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-a3y2Ll_Eg1k/TwmlmGw99vI/AAAAAAAACQI/Z8m5FYTJAMo/s1600/DSC00248.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"&gt;&lt;img border="0" height="240" src="http://4.bp.blogspot.com/-a3y2Ll_Eg1k/TwmlmGw99vI/AAAAAAAACQI/Z8m5FYTJAMo/s320/DSC00248.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Even better, the board has an exposed pads on each line perfect for carefully soldering a wire to. So thats the good bit. The bad news is that there are 20 of these input lines... thats a lot of wiring and is enough to use up all the inputs on a Arduino board...&lt;br /&gt;&lt;br /&gt;I decided to use 74HC165 shift registers to read the keyboard and cut down the number of input lines needed. These chips each read 8 inputs then send the data out in a serial stream. By chaining these together, any number of inputs can be read with just 3 wires to the Arduino (one to "capture" then inputs then a "clock" and data line for reading the data).&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-jW_eHf-LvtI/Twmlo3sG43I/AAAAAAAACQQ/fml4QHPZjlE/s1600/DSC00259.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"&gt;&lt;img border="0" height="240" src="http://4.bp.blogspot.com/-jW_eHf-LvtI/Twmlo3sG43I/AAAAAAAACQQ/fml4QHPZjlE/s320/DSC00259.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Using fiddly surface mount components it was possible to fit 3 of these shift registers on a board that would fit underneath the Stylophone main board, keeping it out of the way and snugly held to stop it shaking around.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-05VvUCCtitY/Twmlq9GcPpI/AAAAAAAACQY/cYh_qAs1jIs/s1600/DSC00265.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"&gt;&lt;img border="0" height="240" src="http://1.bp.blogspot.com/-05VvUCCtitY/Twmlq9GcPpI/AAAAAAAACQY/cYh_qAs1jIs/s320/DSC00265.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;An Arduino Nano would fit in the Stylophone case, but I decided to use a custom SMD board since I wanted to add an KXPS5 accelerometer to detect tilt (for pitch bend). I also added another 74HC165 shift register to the chain for reading additional inputs from a row of tactile switches mounted to the back of the Stylophone. A 5mm RGB on the front allows a "mode" to be indicated.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-RwTthAwN2VQ/Twmls3m3CNI/AAAAAAAACQg/EFujO0jZu3w/s1600/DSC00292.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"&gt;&lt;img border="0" height="240" src="http://2.bp.blogspot.com/-RwTthAwN2VQ/Twmls3m3CNI/AAAAAAAACQg/EFujO0jZu3w/s320/DSC00292.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;And it worked... mostly. I am having some issues with the accelerometer which may be down to a bad connection (those things are a bitch to solder!) but the keyboard reading and MIDI is working pretty well. Hopefully it will all be finished soon. Watch this space!&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-OodfnsV06OQ/TwmlvoBKxPI/AAAAAAAACQo/RdSIaOOXuPM/s1600/DSC00293.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"&gt;&lt;img border="0" height="240" src="http://2.bp.blogspot.com/-OodfnsV06OQ/TwmlvoBKxPI/AAAAAAAACQo/RdSIaOOXuPM/s320/DSC00293.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;UPDATE: I finally found out why the accelerometer wasn't working... even in analog output mode on the&amp;nbsp;KXPS5&amp;nbsp;it is neccessary to set the "enable" input high only AFTER the chip is powered up (at least 1ms after). I had tied the enable input high on my etched board, d'oh! Failure to do this makes the analog outputs go mental... I only found this out after I decided to ditch my homebrew board and use an Arduino Nano in there.&amp;nbsp;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-7706797849876217501?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/7706797849876217501/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2012/01/midi-izing-reissue-stylophone.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/7706797849876217501'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/7706797849876217501'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2012/01/midi-izing-reissue-stylophone.html' title='Midi-izing the Reissue Stylophone'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-4gxDeMaqkBU/Twmljy4DX6I/AAAAAAAACQA/gF2Wc5vztfU/s72-c/DSC00161.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-4731456623561722271</id><published>2011-12-03T03:35:00.001-08:00</published><updated>2011-12-03T05:18:08.686-08:00</updated><title type='text'>Flashing LED Christmas Card Project</title><content type='html'>This is a DIY project to create a flashing christmas card based on a 555 timer. I did a project like this many moons ago at school, and when my local hackspace, Build Brighton, were thinking of seasonal electronics projects we could offer in workshops I decided to try to recreate this idea.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://i.ytimg.com/vi/IF9ZOUNUX6s/0.jpg" height="266" width="320"&gt;&lt;param name="movie" value="http://www.youtube.com/v/IF9ZOUNUX6s?version=3&amp;f=user_uploads&amp;c=google-webdrive-0&amp;app=youtube_gdata" /&gt;&lt;param name="bgcolor" value="#FFFFFF" /&gt;&lt;embed width="320" height="266"  src="http://www.youtube.com/v/IF9ZOUNUX6s?version=3&amp;f=user_uploads&amp;c=google-webdrive-0&amp;app=youtube_gdata" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;br /&gt;The circuit is a basic "astable" circuit (which&amp;nbsp;simply&amp;nbsp;means it oscillates between states). In this case we use the venerable 555 timer integrated circuit to make a square wave oscillator with a frequency of a second or two.&lt;br /&gt;&lt;br /&gt;The output of the oscillator circuit goes to 0V, stays there a while, then flips up to 9V, stays there a while then flips back to 0V and repeats again. When the output is 9V it lights up a set of LEDs. The "clever" bit is that when the output is 0V a second set of LEDs light up, because those LEDs are already connected to 9V (i.e. "positive") on their other side, and get connected to 0V (i.e. "negative") when the output of the oscillator goes down to 0V. The end result is that the two sets of LEDs flash alternately.&lt;br /&gt;&lt;br /&gt;I found a small current flows even between the "high" output of the 555 and the 9V supply, so the LEDs are never completely off but flash from dim to bright (but in some ways that looks even nicer :o)&lt;br /&gt;&lt;br /&gt;The parts needed for this project are&lt;br /&gt;&lt;br /&gt;8 x identical "standard" LEDs&lt;br /&gt;1 x&amp;nbsp;"standard"&amp;nbsp;LED for top of tree (can be same type as above, but you might want a different colour)&lt;br /&gt;9 x 220 ohm resistors for the LEDs (typically 220 ohms but you might want to experiment with higher or slightly lower values to get the brightness levels you want. I used 100 ohm resistors on my red LEDs and a 470 ohm on the blue led)&lt;br /&gt;1 x&amp;nbsp;555 timer IC (e.g NE555)&lt;br /&gt;1 x 10M (10 mega-ohm) resistor&lt;br /&gt;1 x&amp;nbsp;470k (470 kilo-ohm) resistor&lt;br /&gt;1 x 10nF (0.01uF) ceramic capacitor&lt;br /&gt;1 x 100nF (0.1uF) ceramic capacitor&lt;br /&gt;1 x PP3 battery snap connector&lt;br /&gt;1 x PP3 battery&lt;br /&gt;Some connecting wire (e.g. 1 meter or less of thin equipment wire)&lt;br /&gt;&lt;br /&gt;You can build this by poking the component legs through holes punched in the card, then soldering them on the back. This is kind of fiddly but it wouldn't be quite the same end result to build it on a board.&lt;br /&gt;&lt;br /&gt;The following diagram shows the connections from the INSIDE of the card (i.e. the side you see when soldering). Click to enlarge&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-hE6xk2Zi-3M/TtohZBcFemI/AAAAAAAACPk/TWVkzeFqcQ0/s1600/flashing+card.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://1.bp.blogspot.com/-hE6xk2Zi-3M/TtohZBcFemI/AAAAAAAACPk/TWVkzeFqcQ0/s400/flashing+card.gif" width="332" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;When putting the 555 IC on the card make sure that you insert it through the front of the card with pin 1 at the top (the end of the chip with pin 1 will be marked with a notch or dimple).&lt;br /&gt;&lt;br /&gt;The LEDs must be inserted the right way round for this project to work. The anode (+) side of the LED is marked by a longer leg and the cathode (-) has a flattened edge to the lens. Use the + symbols next to the LEDs in the diagram above to make sure you put them in the right way round and remember the diagram shows the BACK of the circuit!&lt;br /&gt;&lt;br /&gt;The resistors and capacitors have no specific polarity and can be soldered either way round.&lt;br /&gt;&lt;br /&gt;Don't heat components for too long when soldering. LEDs are particularly sensitive to overheating and it probably won't do the 555 a lot of good either. It helps to bend leads together (so they stay joined by themselves) before soldering so you can be quick with the heat.&lt;br /&gt;&lt;br /&gt;My card was particularly utilitarian, but I'm sure you can make it look much nicer :) sticking a sheet of card over the wiring hides the mess and strengthens it all. It would be good to see other peoples results!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-PQ6tv2En4sc/TtoTLLsUMlI/AAAAAAAACPM/2gRFXtbaBy8/s1600/card1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="208" src="http://2.bp.blogspot.com/-PQ6tv2En4sc/TtoTLLsUMlI/AAAAAAAACPM/2gRFXtbaBy8/s320/card1.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-u2QW22C5yfM/TtoTMISO3ZI/AAAAAAAACPU/nK5nSkdRnAs/s1600/card2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="202" src="http://1.bp.blogspot.com/-u2QW22C5yfM/TtoTMISO3ZI/AAAAAAAACPU/nK5nSkdRnAs/s320/card2.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-rrgR8TTKMPo/TtoTT1ecBFI/AAAAAAAACPc/7g9RmvSoKW4/s1600/card3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="193" src="http://4.bp.blogspot.com/-rrgR8TTKMPo/TtoTT1ecBFI/AAAAAAAACPc/7g9RmvSoKW4/s320/card3.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-4731456623561722271?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/4731456623561722271/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2011/12/flashing-led-christmas-card-project.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/4731456623561722271'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/4731456623561722271'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2011/12/flashing-led-christmas-card-project.html' title='Flashing LED Christmas Card Project'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-hE6xk2Zi-3M/TtohZBcFemI/AAAAAAAACPk/TWVkzeFqcQ0/s72-c/flashing+card.gif' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-6838546950791104984</id><published>2011-11-05T07:06:00.000-07:00</published><updated>2011-11-05T12:21:45.669-07:00</updated><title type='text'>Lost in Maths! (2D Sound location with 4 sensors)</title><content type='html'>This post is about my ongoing project to do fast 2D sound location on a ping pong table, this is some ideas I've been having and wanted to share - since I need some help!&lt;br /&gt;&lt;br /&gt;Ok here's the problem... we have a rectangular area ABCD and somewhere in that area (point X) there is an event that produces a sound (e.g. a ping pong ball strikes the surface). This results in sound waves travelling outwards to the corners where they are picked up by sound detectors.&lt;br /&gt;&lt;br /&gt;The first sound to be picked up at each sensor arrives at a time that obviously depends on that sensor's distance from the original sound. Lets call the times tA, tB, tC, tD. (Each sensor will pick up reverberations and echoes after the original sound, but its the first "edge" of the sound we're interested in)&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-FoQsFAvOYFA/TrU7hrRDZEI/AAAAAAAACLg/nNkitafreRk/s1600/Image3.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="192" src="http://2.bp.blogspot.com/-FoQsFAvOYFA/TrU7hrRDZEI/AAAAAAAACLg/nNkitafreRk/s320/Image3.gif" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Now since we don't know when the original sound happens (we only detect it when it got to the closest sensor) we don't actually know the real values of tA, tB, tC, tD but we get relative times from the first sensor. In this case X is closest to D, &amp;nbsp;the sound reached D first. The time we read at each sensor A,B,C is relative to tD. Graphically this can be shown like this (each red line is reduced by distance XD)&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-q_WkyCW0xHQ/TrU7hDSKGyI/AAAAAAAACLc/6HF8_VGif1g/s1600/Image2.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="192" src="http://2.bp.blogspot.com/-q_WkyCW0xHQ/TrU7hDSKGyI/AAAAAAAACLc/6HF8_VGif1g/s320/Image2.gif" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Now we can use these reduced distances to define circles based on the points A,B,C and D (radius at D is initially zero)&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-tQf51pE2FAU/TrU7iKtrsLI/AAAAAAAACLo/iT2cQAFRnwg/s1600/Image4.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="192" src="http://3.bp.blogspot.com/-tQf51pE2FAU/TrU7iKtrsLI/AAAAAAAACLo/iT2cQAFRnwg/s320/Image4.gif" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;As pointer out by Arduino forum member Necromancer on&amp;nbsp;&lt;a href="http://arduino.cc/forum/index.php?topic=52583.0"&gt;http://arduino.cc/forum/index.php?topic=52583.0&lt;/a&gt;&amp;nbsp;we can find X &amp;nbsp;geometrically by progressively increasing the radii of the circles at A,B,C and D by the same amounts until all the circles intersect at a single point. At this point we have added back the unknown distance XD and the circles intersect at point X as shown below.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-RRyYnM8ylTE/TrU7iouPGOI/AAAAAAAACLw/6oFzwgQg9eg/s1600/Image5.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="192" src="http://1.bp.blogspot.com/-RRyYnM8ylTE/TrU7iouPGOI/AAAAAAAACLw/6oFzwgQg9eg/s320/Image5.gif" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;The problem is that this iterative calculation of circle intersections is processing-heavy and would probably take too long to solve on a microcontroller to be responsive enough for my application. However I started thinking about getting a "head start" by doing some simple calculation to get the initial increment where all the circles intersect for the first time, and go forward from there.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Here's what I mean.... point Q is a point on the line AC which is equal distances from the points where the initial circles around A and C cross AC.&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-3G24LW2Irno/TrU7i0iRqPI/AAAAAAAACL4/HaDzi3GcGKw/s1600/Image6.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="192" src="http://2.bp.blogspot.com/-3G24LW2Irno/TrU7i0iRqPI/AAAAAAAACL4/HaDzi3GcGKw/s320/Image6.gif" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The actual coordinates of Q aren't needed, we just need to know how much to increase the radii of the circles around A and C so that they intersect at the first time (which will happen at Q)&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-zETQfi-A4mY/TrU7j9krMfI/AAAAAAAACME/XjD1mgKkjnc/s1600/Image7.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="192" src="http://3.bp.blogspot.com/-zETQfi-A4mY/TrU7j9krMfI/AAAAAAAACME/XjD1mgKkjnc/s320/Image7.gif" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;The calculation is simply the length of AC minus the radii of the two circles, all divided by two. If we calculate this value and add it to the radii of the circles they will meet at Q.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;If we do the same calculation for lines AB, BC, CD, AD, AC, BD we'll get 6 different values that we should increase circle radii by make them intersect. We can just take the largest of all the 6 values and apply that as the base value by which the radii of all the circles should be increased to get to the initial point where all the circles intersect.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;This will not neccessarily be &amp;nbsp;point X... we might need to interatively expand the circles a bit more to make them all intersect at the same point. However we got a big head start and so far we've just done simple arithmetic.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;I made a simple program where I could click with the mouse to simulate the values arriving at the 4 sensors., then applied the above calculations... in many cases the results are very close to the final point X. For example:&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-IRxjZ5EqAPo/TrU7k9CvSMI/AAAAAAAACMM/rS2tWKUg1uM/s1600/Image8.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="207" src="http://1.bp.blogspot.com/-IRxjZ5EqAPo/TrU7k9CvSMI/AAAAAAAACMM/rS2tWKUg1uM/s320/Image8.gif" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;In other places the accuracy is not so spot-on, but it looks like some kind of simple averaging of the points of intersection might give a position good enough for what I want, and without having to iteratively apply complex calculations (like square roots), so it should be pretty fast.&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-LwS5eKR_tU8/TrU7l2vEn1I/AAAAAAAACMQ/rhVbcSgNkXI/s1600/Image9.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="207" src="http://4.bp.blogspot.com/-LwS5eKR_tU8/TrU7l2vEn1I/AAAAAAAACMQ/rhVbcSgNkXI/s320/Image9.gif" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-0VgMIIBbgtI/TrU7mJeHVqI/AAAAAAAACMY/51Lo5Diz2uE/s1600/Image10.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="207" src="http://4.bp.blogspot.com/-0VgMIIBbgtI/TrU7mJeHVqI/AAAAAAAACMY/51Lo5Diz2uE/s320/Image10.gif" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Only three sensors are strictly required for multilateration, however I found that adding the fourth sensor made a massive difference to the accuracy of the above calculation.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;The next step is to calculate the points of intersection and give it a try with some averaging, to see if I can avoid the iterative method.&amp;nbsp;However I'm not a mathemetician, so if anyone has a better idea, please let me know!&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;Update: &lt;/b&gt;OK, I gave the averaging thing a try. This clip shows my test program using these calculations to track the mouse pointer. The tracking is not perfect and there are a couple of places (vertical midpoint of the area, towards left and right side) where it is worst, but I think this is good enough (especially given that my sensors won't be perfect!).&amp;nbsp;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;The program displays the fours circles calculated as above. The final calculated position is displayed by the red crosshairs&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;object width="320" height="266" class="BLOG_video_class" id="BLOG_video-c323aa229a4dc4cf" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="flashvars" value="flvurl=http://v12.nonxt4.googlevideo.com/videoplayback?id%3Dc323aa229a4dc4cf%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1331450557%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D593226AFF41EFEF98485721EF92BCB22BC05D1.519B90B00A62AC27FC76546EF2BBE0BA1C7E88E0%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3Dc323aa229a4dc4cf%26offsetms%3D5000%26itag%3Dw160%26sigh%3D4OEI9Y6D4yugXdvsrKRtlj-ztpc&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"width="320" height="266" bgcolor="#FFFFFF"flashvars="flvurl=http://v12.nonxt4.googlevideo.com/videoplayback?id%3Dc323aa229a4dc4cf%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1331450557%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D593226AFF41EFEF98485721EF92BCB22BC05D1.519B90B00A62AC27FC76546EF2BBE0BA1C7E88E0%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3Dc323aa229a4dc4cf%26offsetms%3D5000%26itag%3Dw160%26sigh%3D4OEI9Y6D4yugXdvsrKRtlj-ztpc&amp;autoplay=0&amp;ps=blogger"allowFullScreen="true" /&gt;&lt;/object&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;The process is as follows:&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;1. Firstly I need to simulate the sensor inputs, so I take the position of the mouse pointer, calculate distance to each corner and then subtract the minimum distance from all the others. The results (tA, tB, tC, tD) are representative of time or arrival info from real sensors.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;2. For each edge, and the two diagonals I get the length of the line (area width, height or diagonal distance) and subtract the relative arrival times for the points at each end.&amp;nbsp;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;offset1 = (width - tA - tB)/2&lt;/div&gt;&lt;div style="text-align: left;"&gt;offset2 = (width - tC - tD)/2&lt;/div&gt;&lt;div style="text-align: left;"&gt;offset3 = (height - tA - tD)/2&lt;/div&gt;&lt;div style="text-align: left;"&gt;offset4 = (height - tB - tC)/2&lt;/div&gt;&lt;div style="text-align: left;"&gt;offset5 = (diagonal - tA - tC)/2&lt;/div&gt;&lt;div style="text-align: left;"&gt;offset6 = (diagonal - tB - tD)/2&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;Now take the maximum of these 6 values:&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;offset = max(offset1,offset2,offset3,offset4,offset5,offset6)&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;now calculate the circle radius by adding the offset to each time.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;rA = tA + offset&lt;/div&gt;&lt;div style="text-align: left;"&gt;rB = tB + offset&lt;/div&gt;&lt;div style="text-align: left;"&gt;rC = tC + offset&lt;/div&gt;&lt;div style="text-align: left;"&gt;rD = tD + offset&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;now calculate the intersection points of all pairs of circles. I used the C code example from here&amp;nbsp;&amp;nbsp;http://paulbourke.net/geometry/2circle/&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;There are six pairs of circles, AB, AC, AD, BC, BD, CD. Not all may intersect (ignore pairs which do not intersect). Otherwise we get 2 insection points (which may be identical if circles just touch) for each pair of circles. Lets say that for each pair of circles we can get two intersection points P and P'&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;For each pair of points P and P', one will be closest to our target point and the other should be discarded. The way I did this was to calculate the average of all the points, then go back through the list selecting the point from each pair that was closest to the calculated average point and then averaging just these "closest points".&amp;nbsp;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;ie. Take the first "rough" average of all points P and P' - lets call is (Xave, Yave), then recalculate the average position using either P or P' from each pair based on the condition:&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;b&gt;if&amp;nbsp;(Xp - Xave)^2 +&amp;nbsp;(Yp - Yave)^2 &amp;nbsp;&amp;gt;&amp;nbsp;(Xp' - Xave)^2 +&amp;nbsp;(Yp' - Yave)^2&amp;nbsp;&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;b&gt;then use point P'&amp;nbsp;&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;b&gt;else use point P&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;The resulting average (X , Y) is the final calculated point.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;Better accuracy would be got by interatively increasing rA, rB, rC and rD and recalculating the intersection points until they are at their closest to each other. However I don't think I need this - the sensor input is unlikely to be so accurate it would benefit from this.... and I think it would be computationally expensive due to calling sqrt( ) many times and therefore slow.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;Once again I'm no mathematician and I'd be grateful for any advice here!&lt;/div&gt;&lt;div style="text-align: left;"&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/8909459762367220480-6838546950791104984?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/6838546950791104984/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2011/11/lost-in-maths.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/6838546950791104984'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/6838546950791104984'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2011/11/lost-in-maths.html' title='Lost in Maths! (2D Sound location with 4 sensors)'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-FoQsFAvOYFA/TrU7hrRDZEI/AAAAAAAACLg/nNkitafreRk/s72-c/Image3.gif' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-5147668800132742597</id><published>2011-10-12T13:27:00.000-07:00</published><updated>2011-10-13T15:06:31.717-07:00</updated><title type='text'>Musical ping-pong tables and 2d multilateration</title><content type='html'>I'm currently trying to help out a local artist who is building an Interactive Ping-Pong Table, where each bounce of the ball generates a musical sound which depends on the position of the bounce.&lt;br /&gt;&lt;br /&gt;I thought it should be possible to do this without drastically changing the table (i.e. without chopping the surface up) by using 3 piezo disks and an Arduino or PIC to time the arrival of the pulse at each disk and work out the position of the ball. It all sounded pretty easy, and an interesting project. Its certainly been interesting, but I'll think twice in future before deciding something is easy before I've properly thought &amp;nbsp;it through :o)&lt;br /&gt;&lt;br /&gt;I found pretty quickly that some kind of amplification is needed.. the piezo disks are pretty sensitive to a sounds close by but not so great for something the other end of a table. First of all I tried to boost the level using 4069 inverter chips (I got that idea from Nicholas Collins' book - Handmade electronic music) since I've never really understood op amps and didn't want to get into all that dual supply rubbish. In my initial circuit I used an NPN Darlington transistor on the output of the amplifier stage to generate the logic pulse.&lt;br /&gt;&lt;br /&gt;It kind of worked, but I was finding that the MCU would hang when an interrupt-on-change interrupt was being fired by multiple sensors. I also had a problem with the output getting stuck on (I think this might have been due to supply noise, noise picked up on a long wire to the piezo, and an overly sensitive amp stage). I &amp;nbsp;think the hang thing might have been due to noisy outputs triggering a rapid train of interrupts than the poor PIC could not handle. I have an IKA Logic analyser and using this I could see a mad train of pulses coming from sound waveform, echoes, supply noise whatever... I don't really know, but the PIC didn't like it.&lt;br /&gt;&lt;br /&gt;Searching about for ideas online I read about running op-amps like LM358 from a single supply, which seemed to be a better way to do things than using logic chips as amps. I also saw how a 555 monostable circuit can be used to clean up a dirty pulse by keeping an output high for a timed period as soon as the first edge of the input pulse comes in, so the train of pulses from reverberations and so on get masked by a nice clean extended output pulse... nice and friendly for MCU interrupt pins.&lt;br /&gt;&lt;br /&gt;The resulting circuit seems to work pretty well, even though it still seems a bit complicated. Maybe it is a case of over-engineering, but I learned a lot and it does at least work pretty well. Using SMDs I can also get it on a board about the same size as the piezo disk so it can sit on top.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-l-2NqKOEF70/TpX17gnNX_I/AAAAAAAACJc/jqmbPNdnf64/s1600/scem.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="129" src="http://2.bp.blogspot.com/-l-2NqKOEF70/TpX17gnNX_I/AAAAAAAACJc/jqmbPNdnf64/s320/scem.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-fV4YfDDd13M/TpX2Xj37-fI/AAAAAAAACJk/rE4Iw1ZxZfI/s1600/DSC00006%25282%2529.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="300" src="http://3.bp.blogspot.com/-fV4YfDDd13M/TpX2Xj37-fI/AAAAAAAACJk/rE4Iw1ZxZfI/s400/DSC00006%25282%2529.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;For some reason I thought the maths behind working out a point from timing would be easy..and it is in one dimension with 2 sensors...&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://i.ytimg.com/vi/qWb2FRY5Na4/0.jpg" height="266" width="320"&gt;&lt;param name="movie" value="http://www.youtube.com/v/qWb2FRY5Na4?version=3&amp;f=user_uploads&amp;c=google-webdrive-0&amp;app=youtube_gdata" /&gt;&lt;param name="bgcolor" value="#FFFFFF" /&gt;&lt;embed width="320" height="266"  src="http://www.youtube.com/v/qWb2FRY5Na4?version=3&amp;f=user_uploads&amp;c=google-webdrive-0&amp;app=youtube_gdata" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;However working in 2 dimensions with 3 sensors seems to be a completely different kettle of fish... the technique is called Multilateration and there have been entire research papers written about it :o) The problem is that all the timing readings you're working with are relative... its more complicated than I &amp;nbsp;thought to get back to an actual position. Maybe I can simplify things, since my sensors will be arranged in the corners of a rectangular area and I can always calibrate them at the start by tapping the corners of the table. Or maybe some dirty trial and error approach will be good enough... Anway thats the next step... wish me luck..!&lt;br /&gt;&lt;br /&gt;Here is the source code used in this clip&lt;br /&gt;&lt;br /&gt;&lt;pre style="background: #ffffff; color: black;"&gt;&lt;span style="color: dimgrey;"&gt;// SOURCEBOOST C&lt;/span&gt;&lt;br /&gt;&lt;span style="color: dimgrey;"&gt;// PIC16F688&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #004a43;"&gt;#&lt;/span&gt;&lt;span style="color: #004a43;"&gt;include &lt;/span&gt;&lt;span style="color: maroon;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #40015a;"&gt;system.h&lt;/span&gt;&lt;span style="color: maroon;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #004a43;"&gt;#&lt;/span&gt;&lt;span style="color: #004a43; font-weight: bold;"&gt;pragma &lt;/span&gt;&lt;span style="color: #bb7977; font-weight: bold;"&gt;DATA _CONFIG, _MCLRE_OFF&amp;amp;_WDT_OFF&amp;amp;_INTRC_OSC_NOCLKOUT&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #004a43;"&gt;#&lt;/span&gt;&lt;span style="color: #004a43; font-weight: bold;"&gt;pragma &lt;/span&gt;&lt;span style="color: #bb7977; font-weight: bold;"&gt;CLOCK_FREQ 8000000&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #004a43;"&gt;#&lt;/span&gt;&lt;span style="color: #004a43;"&gt;define&lt;/span&gt;&lt;span style="color: #004a43;"&gt; SENSEA            0b00010000&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #004a43;"&gt;#&lt;/span&gt;&lt;span style="color: #004a43;"&gt;define&lt;/span&gt;&lt;span style="color: #004a43;"&gt; SENSEB            0b00100000&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #004a43;"&gt;#&lt;/span&gt;&lt;span style="color: #004a43;"&gt;define&lt;/span&gt;&lt;span style="color: #004a43;"&gt; SENSE_MASK        &lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #004a43;"&gt;SENSEA&lt;/span&gt;&lt;span style="color: #808030;"&gt;|&lt;/span&gt;&lt;span style="color: #004a43;"&gt;SENSEB&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: maroon; font-weight: bold;"&gt;typedef&lt;/span&gt; &lt;span style="color: maroon; font-weight: bold;"&gt;unsigned&lt;/span&gt; &lt;span style="color: maroon; font-weight: bold;"&gt;char&lt;/span&gt; byte&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: dimgrey;"&gt;// INITIALISE SERIAL PORT FOR MIDI&lt;/span&gt;&lt;br /&gt;&lt;span style="color: maroon; font-weight: bold;"&gt;void&lt;/span&gt; init_usart&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: purple;"&gt;{&lt;/span&gt;&lt;br /&gt;    pir1&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #008c00;"&gt;1&lt;/span&gt; &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;1&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;    &lt;span style="color: dimgrey;"&gt;//TXIF transmit enable&lt;/span&gt;&lt;br /&gt;    pie1&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #008c00;"&gt;1&lt;/span&gt; &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;    &lt;span style="color: dimgrey;"&gt;//TXIE no interrupts&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    baudctl&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #008c00;"&gt;4&lt;/span&gt; &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;        &lt;span style="color: dimgrey;"&gt;// synchronous bit polarity &lt;/span&gt;&lt;br /&gt;    baudctl&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #008c00;"&gt;3&lt;/span&gt; &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;1&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;        &lt;span style="color: dimgrey;"&gt;// enable 16 bit brg&lt;/span&gt;&lt;br /&gt;    baudctl&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #008c00;"&gt;1&lt;/span&gt; &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;        &lt;span style="color: dimgrey;"&gt;// wake up enable off&lt;/span&gt;&lt;br /&gt;    baudctl&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #008c00;"&gt;0&lt;/span&gt; &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;        &lt;span style="color: dimgrey;"&gt;// disable auto baud detect&lt;/span&gt;&lt;br /&gt;        &lt;br /&gt;    txsta&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #008c00;"&gt;6&lt;/span&gt; &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;    &lt;span style="color: dimgrey;"&gt;// 8 bit transmission&lt;/span&gt;&lt;br /&gt;    txsta&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #008c00;"&gt;5&lt;/span&gt; &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;1&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;    &lt;span style="color: dimgrey;"&gt;// transmit enable&lt;/span&gt;&lt;br /&gt;    txsta&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #008c00;"&gt;4&lt;/span&gt; &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;    &lt;span style="color: dimgrey;"&gt;// async mode&lt;/span&gt;&lt;br /&gt;    txsta&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #008c00;"&gt;2&lt;/span&gt; &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;    &lt;span style="color: dimgrey;"&gt;// high baudrate BRGH&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    rcsta&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #008c00;"&gt;7&lt;/span&gt; &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;1&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;    &lt;span style="color: dimgrey;"&gt;// serial port enable&lt;/span&gt;&lt;br /&gt;    rcsta&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #008c00;"&gt;6&lt;/span&gt; &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;    &lt;span style="color: dimgrey;"&gt;// 8 bit operation&lt;/span&gt;&lt;br /&gt;    rcsta&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #008c00;"&gt;4&lt;/span&gt; &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;    &lt;span style="color: dimgrey;"&gt;// enable receiver&lt;/span&gt;&lt;br /&gt;        &lt;br /&gt;    spbrgh &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;        &lt;span style="color: dimgrey;"&gt;// brg high byte&lt;/span&gt;&lt;br /&gt;    spbrg &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;15&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;        &lt;span style="color: dimgrey;"&gt;// brg low byte (31250)    &lt;/span&gt;&lt;br /&gt;&lt;span style="color: purple;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: maroon; font-weight: bold;"&gt;enum&lt;/span&gt; &lt;span style="color: purple;"&gt;{&lt;/span&gt;&lt;br /&gt;    READY&lt;span style="color: #808030;"&gt;,&lt;/span&gt;&lt;br /&gt;    LISTENING&lt;span style="color: #808030;"&gt;,&lt;/span&gt;&lt;br /&gt;    TIMING&lt;span style="color: #808030;"&gt;,&lt;/span&gt;&lt;br /&gt;    TIMEOUT&lt;br /&gt;&lt;span style="color: purple;"&gt;}&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;byte remaining&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: maroon; font-weight: bold;"&gt;long&lt;/span&gt; timeA&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: maroon; font-weight: bold;"&gt;long&lt;/span&gt; timeB&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;byte state&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: maroon; font-weight: bold;"&gt;void&lt;/span&gt; &lt;span style="color: maroon; font-weight: bold;"&gt;interrupt&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt; &lt;span style="color: maroon; font-weight: bold;"&gt;void&lt;/span&gt; &lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: purple;"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: dimgrey;"&gt;// check for interrupt on change&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: maroon; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;intcon&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt; &lt;span style="color: dimgrey;"&gt;// IOCA fired&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: purple;"&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: dimgrey;"&gt;// are any of the signals we're waiting&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: dimgrey;"&gt;// for now ready for us?&lt;/span&gt;&lt;br /&gt;        byte savePortA &lt;span style="color: #808030;"&gt;=&lt;/span&gt; porta&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;        byte whichSensor &lt;span style="color: #808030;"&gt;=&lt;/span&gt; savePortA &lt;span style="color: #808030;"&gt;&amp;amp;&lt;/span&gt; remaining&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: maroon; font-weight: bold;"&gt;unsigned&lt;/span&gt; &lt;span style="color: maroon; font-weight: bold;"&gt;long&lt;/span&gt; thisTime&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: maroon; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;whichSensor&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: purple;"&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: maroon; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;state &lt;span style="color: #808030;"&gt;=&lt;/span&gt;&lt;span style="color: #808030;"&gt;=&lt;/span&gt; LISTENING&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: purple;"&gt;{&lt;/span&gt;&lt;br /&gt;                &lt;span style="color: dimgrey;"&gt;// start the timer&lt;/span&gt;&lt;br /&gt;                t1con&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #008c00;"&gt;0&lt;/span&gt; &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;1&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;                thisTime &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;                state &lt;span style="color: #808030;"&gt;=&lt;/span&gt; TIMING&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: purple;"&gt;}&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: maroon; font-weight: bold;"&gt;else&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: purple;"&gt;{&lt;/span&gt;&lt;br /&gt;                &lt;span style="color: dimgrey;"&gt;// grab the current time&lt;/span&gt;&lt;br /&gt;                thisTime &lt;span style="color: #808030;"&gt;=&lt;/span&gt; tmr1h &lt;span style="color: #808030;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #808030;"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color: #008c00;"&gt;8&lt;/span&gt; &lt;span style="color: #808030;"&gt;|&lt;/span&gt; tmr1l&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: purple;"&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;br /&gt;            &lt;span style="color: dimgrey;"&gt;// Grab times from sensors&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: maroon; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;!&lt;/span&gt;&lt;span style="color: #808030;"&gt;!&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;whichSensor &lt;span style="color: #808030;"&gt;&amp;amp;&lt;/span&gt; SENSEA&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;br /&gt;                timeA &lt;span style="color: #808030;"&gt;=&lt;/span&gt; thisTime&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: maroon; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;!&lt;/span&gt;&lt;span style="color: #808030;"&gt;!&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;whichSensor &lt;span style="color: #808030;"&gt;&amp;amp;&lt;/span&gt; SENSEB&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;br /&gt;                timeB &lt;span style="color: #808030;"&gt;=&lt;/span&gt; thisTime&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;                &lt;br /&gt;            &lt;span style="color: dimgrey;"&gt;// clear bits for the sensors we &lt;/span&gt;&lt;br /&gt;            &lt;span style="color: dimgrey;"&gt;// already have&lt;/span&gt;&lt;br /&gt;            remaining &lt;span style="color: #808030;"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #808030;"&gt;~&lt;/span&gt;savePortA&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: maroon; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;!&lt;/span&gt;remaining&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: purple;"&gt;{&lt;/span&gt;&lt;br /&gt;                intcon&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #008c00;"&gt;3&lt;/span&gt; &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;            &lt;span style="color: dimgrey;"&gt;// ioca off&lt;/span&gt;&lt;br /&gt;                state &lt;span style="color: #808030;"&gt;=&lt;/span&gt; READY&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: purple;"&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: purple;"&gt;}&lt;/span&gt;        &lt;br /&gt;        &lt;br /&gt;        &lt;span style="color: dimgrey;"&gt;// clear interrupt fired flag&lt;/span&gt;&lt;br /&gt;        intcon&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #008c00;"&gt;0&lt;/span&gt; &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: purple;"&gt;}&lt;/span&gt;    &lt;br /&gt;&lt;span style="color: purple;"&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;br /&gt;&lt;span style="color: #3f5fbf;"&gt;////////////////////////////////////////////////////////////&lt;/span&gt;&lt;br /&gt;&lt;span style="color: dimgrey;"&gt;// SEND A MIDI BYTE&lt;/span&gt;&lt;br /&gt;&lt;span style="color: maroon; font-weight: bold;"&gt;void&lt;/span&gt; &lt;span style="color: #400000;"&gt;send&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: maroon; font-weight: bold;"&gt;unsigned&lt;/span&gt; &lt;span style="color: maroon; font-weight: bold;"&gt;char&lt;/span&gt; c&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: purple;"&gt;{&lt;/span&gt;&lt;br /&gt;    txreg &lt;span style="color: #808030;"&gt;=&lt;/span&gt; c&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: maroon; font-weight: bold;"&gt;while&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;!&lt;/span&gt;txsta&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #008c00;"&gt;1&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: purple;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #3f5fbf;"&gt;////////////////////////////////////////////////////////////&lt;/span&gt;&lt;br /&gt;&lt;span style="color: dimgrey;"&gt;// NOTE MESSAGE&lt;/span&gt;&lt;br /&gt;&lt;span style="color: maroon; font-weight: bold;"&gt;void&lt;/span&gt; sendNote&lt;span style="color: #808030;"&gt;(&lt;/span&gt;byte channel&lt;span style="color: #808030;"&gt;,&lt;/span&gt; byte note&lt;span style="color: #808030;"&gt;,&lt;/span&gt; byte value&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: purple;"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #400000;"&gt;send&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: green;"&gt;0x90&lt;/span&gt; &lt;span style="color: #808030;"&gt;|&lt;/span&gt; channel&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #400000;"&gt;send&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;note&lt;span style="color: #808030;"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color: green;"&gt;0x7f&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #400000;"&gt;send&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;value&lt;span style="color: #808030;"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color: green;"&gt;0x7f&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: purple;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: maroon; font-weight: bold;"&gt;void&lt;/span&gt; &lt;span style="color: #400000;"&gt;main&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: purple;"&gt;{&lt;/span&gt; &lt;br /&gt;    &lt;span style="color: dimgrey;"&gt;// osc control / 8MHz / internal&lt;/span&gt;&lt;br /&gt;    osccon         &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="background-attachment: initial; background-clip: initial; background-color: #dd0000; background-image: initial; background-origin: initial; color: white; font-style: italic; font-weight: bold;"&gt;0b01110001&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;br /&gt;    &lt;span style="color: dimgrey;"&gt;// comparator off&lt;/span&gt;&lt;br /&gt;    cmcon0         &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;7&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;                      &lt;br /&gt;    &lt;br /&gt;    &lt;span style="color: dimgrey;"&gt;// configure io&lt;/span&gt;&lt;br /&gt;    trisa         &lt;span style="color: #808030;"&gt;=&lt;/span&gt; SENSE_MASK&lt;span style="color: purple;"&gt;;&lt;/span&gt;                  &lt;br /&gt;    trisc         &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="background-attachment: initial; background-clip: initial; background-color: #dd0000; background-image: initial; background-origin: initial; color: white; font-style: italic; font-weight: bold;"&gt;0b00000000&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;              &lt;br /&gt;    ansel         &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="background-attachment: initial; background-clip: initial; background-color: #dd0000; background-image: initial; background-origin: initial; color: white; font-style: italic; font-weight: bold;"&gt;0b00000000&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;    porta        &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="background-attachment: initial; background-clip: initial; background-color: #dd0000; background-image: initial; background-origin: initial; color: white; font-style: italic; font-weight: bold;"&gt;0b00000000&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;    portc        &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="background-attachment: initial; background-clip: initial; background-color: #dd0000; background-image: initial; background-origin: initial; color: white; font-style: italic; font-weight: bold;"&gt;0b00000000&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: dimgrey;"&gt;// initialise MIDI comms&lt;/span&gt;&lt;br /&gt;    init_usart&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: dimgrey;"&gt;// &lt;/span&gt;&lt;br /&gt;    t1con &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="background-attachment: initial; background-clip: initial; background-color: #dd0000; background-image: initial; background-origin: initial; color: white; font-style: italic; font-weight: bold;"&gt;0b00000000&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span style="color: dimgrey;"&gt;// interrupt on change porta.4&lt;/span&gt;&lt;br /&gt;    ioca &lt;span style="color: #808030;"&gt;=&lt;/span&gt; SENSE_MASK&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;    intcon&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #008c00;"&gt;7&lt;/span&gt; &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;1&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;    intcon&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #008c00;"&gt;3&lt;/span&gt; &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;    intcon&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #008c00;"&gt;0&lt;/span&gt; &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    byte note &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: maroon; font-weight: bold;"&gt;for&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: purple;"&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: dimgrey;"&gt;// Prepare to listen&lt;/span&gt;&lt;br /&gt;        timeA&lt;span style="color: #808030;"&gt;=&lt;/span&gt;&lt;span style="color: green;"&gt;0xffff&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;        timeB&lt;span style="color: #808030;"&gt;=&lt;/span&gt;&lt;span style="color: green;"&gt;0xffff&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;        remaining &lt;span style="color: #808030;"&gt;=&lt;/span&gt; SENSE_MASK&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;        state &lt;span style="color: #808030;"&gt;=&lt;/span&gt; LISTENING&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;        t1con&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #008c00;"&gt;0&lt;/span&gt; &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;            &lt;span style="color: dimgrey;"&gt;// reset the timer&lt;/span&gt;&lt;br /&gt;        tmr1h&lt;span style="color: #808030;"&gt;=&lt;/span&gt;&lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;        tmr1l&lt;span style="color: #808030;"&gt;=&lt;/span&gt;&lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;        intcon&lt;span style="color: #808030;"&gt;.&lt;/span&gt;&lt;span style="color: #008c00;"&gt;3&lt;/span&gt; &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;1&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;            &lt;span style="color: dimgrey;"&gt;// ioca on&lt;/span&gt;&lt;br /&gt;        &lt;br /&gt;        &lt;span style="color: dimgrey;"&gt;// wait to start timing&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: maroon; font-weight: bold;"&gt;while&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;LISTENING &lt;span style="color: #808030;"&gt;=&lt;/span&gt;&lt;span style="color: #808030;"&gt;=&lt;/span&gt; state&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;br /&gt;        &lt;span style="color: dimgrey;"&gt;// wait to complete timing&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: maroon; font-weight: bold;"&gt;while&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;TIMING &lt;span style="color: #808030;"&gt;=&lt;/span&gt;&lt;span style="color: #808030;"&gt;=&lt;/span&gt; state&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: purple;"&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: maroon; font-weight: bold;"&gt;unsigned&lt;/span&gt; &lt;span style="color: maroon; font-weight: bold;"&gt;long&lt;/span&gt; timeNow &lt;span style="color: #808030;"&gt;=&lt;/span&gt; tmr1h &lt;span style="color: #808030;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #808030;"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color: #008c00;"&gt;8&lt;/span&gt; &lt;span style="color: #808030;"&gt;|&lt;/span&gt; tmr1l&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: maroon; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;timeNow &lt;span style="color: #808030;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color: green;"&gt;0x8000&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;br /&gt;                state &lt;span style="color: #808030;"&gt;=&lt;/span&gt; TIMEOUT&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: purple;"&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;br /&gt;        &lt;span style="color: maroon; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;TIMEOUT &lt;span style="color: #808030;"&gt;=&lt;/span&gt;&lt;span style="color: #808030;"&gt;=&lt;/span&gt; state&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: purple;"&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: dimgrey;"&gt;// ignore the interrupt if it does &lt;/span&gt;&lt;br /&gt;            &lt;span style="color: dimgrey;"&gt;// not register on all the sensors&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: purple;"&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: maroon; font-weight: bold;"&gt;else&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: purple;"&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: maroon; font-weight: bold;"&gt;long&lt;/span&gt; x&lt;span style="color: #808030;"&gt;=&lt;/span&gt;&lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: dimgrey;"&gt;// i know i'm getting reading of up to 5000 'cos I printed &lt;/span&gt;&lt;br /&gt;            &lt;span style="color: dimgrey;"&gt;// them to serial port... you might get something different&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: maroon; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;timeA &lt;span style="color: #808030;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color: #008c00;"&gt;5000&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt; &lt;br /&gt;                timeA &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;5000&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: maroon; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;timeB &lt;span style="color: #808030;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color: #008c00;"&gt;5000&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt; &lt;br /&gt;                timeB &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;5000&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: maroon; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;timeA&lt;span style="color: #808030;"&gt;)&lt;/span&gt; &lt;br /&gt;                x &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;5000&lt;/span&gt; &lt;span style="color: #808030;"&gt;+&lt;/span&gt; timeA&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: maroon; font-weight: bold;"&gt;else&lt;/span&gt; &lt;span style="color: maroon; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;timeB&lt;span style="color: #808030;"&gt;)&lt;/span&gt; &lt;br /&gt;                x &lt;span style="color: #808030;"&gt;=&lt;/span&gt; &lt;span style="color: #008c00;"&gt;5000&lt;/span&gt; &lt;span style="color: #808030;"&gt;-&lt;/span&gt; timeB&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: maroon; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;x&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: purple;"&gt;{&lt;/span&gt;&lt;br /&gt;                note &lt;span style="color: #808030;"&gt;=&lt;/span&gt; x&lt;span style="color: #808030;"&gt;/&lt;/span&gt;&lt;span style="color: #008c00;"&gt;100&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt; &lt;span style="color: dimgrey;"&gt;// is is in range 0-10000 so move this to MIDI range 0-100&lt;/span&gt;&lt;br /&gt;                sendNote&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: #808030;"&gt;,&lt;/span&gt; note&lt;span style="color: #808030;"&gt;,&lt;/span&gt; &lt;span style="color: #008c00;"&gt;127&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span style="color: purple;"&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: purple;"&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;br /&gt;        &lt;span style="color: dimgrey;"&gt;// delay (I think delay_ms function needs timer1)&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: maroon; font-weight: bold;"&gt;int&lt;/span&gt; i&lt;span style="color: #808030;"&gt;=&lt;/span&gt;&lt;span style="color: #008c00;"&gt;1000&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: maroon; font-weight: bold;"&gt;while&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #808030;"&gt;+&lt;/span&gt;&lt;span style="color: #808030;"&gt;+&lt;/span&gt;i&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;        &lt;br /&gt;        &lt;span style="color: maroon; font-weight: bold;"&gt;if&lt;/span&gt;&lt;span style="color: #808030;"&gt;(&lt;/span&gt;note&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: purple;"&gt;{&lt;/span&gt;&lt;br /&gt;            sendNote&lt;span style="color: #808030;"&gt;(&lt;/span&gt;&lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: #808030;"&gt;,&lt;/span&gt; note&lt;span style="color: #808030;"&gt;,&lt;/span&gt; &lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: #808030;"&gt;)&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;            note&lt;span style="color: #808030;"&gt;=&lt;/span&gt;&lt;span style="color: #008c00;"&gt;0&lt;/span&gt;&lt;span style="color: purple;"&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: purple;"&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: purple;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: purple;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-5147668800132742597?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/5147668800132742597/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2011/10/musical-ping-pong-tables-and.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/5147668800132742597'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/5147668800132742597'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2011/10/musical-ping-pong-tables-and.html' title='Musical ping-pong tables and 2d multilateration'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-l-2NqKOEF70/TpX17gnNX_I/AAAAAAAACJc/jqmbPNdnf64/s72-c/scem.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-3032124435063845143</id><published>2011-09-12T14:48:00.001-07:00</published><updated>2011-09-12T14:49:06.872-07:00</updated><title type='text'>POV message fan project update</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Got a bit of time this evening to test out the LED array I made yesterday for the Build Brighton message fan..&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;object width="320" height="266" class="BLOG_video_class" id="BLOG_video-fb30ae181402ad9" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="flashvars" value="flvurl=http://v3.nonxt5.googlevideo.com/videoplayback?id%3D0fb30ae181402ad9%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1331450557%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D77AFC03DA8439E2D5EC104E055FF2650D02E6761.34BBA9B4089BF6B308D234C8BC7D723A124617EB%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3Dfb30ae181402ad9%26offsetms%3D5000%26itag%3Dw160%26sigh%3DaGu0gad62tAgOrI2-mvMVLPy7uY&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"width="320" height="266" bgcolor="#FFFFFF"flashvars="flvurl=http://v3.nonxt5.googlevideo.com/videoplayback?id%3D0fb30ae181402ad9%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1331450557%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D77AFC03DA8439E2D5EC104E055FF2650D02E6761.34BBA9B4089BF6B308D234C8BC7D723A124617EB%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3Dfb30ae181402ad9%26offsetms%3D5000%26itag%3Dw160%26sigh%3DaGu0gad62tAgOrI2-mvMVLPy7uY&amp;autoplay=0&amp;ps=blogger"allowFullScreen="true" /&gt;&lt;/object&gt;&lt;/div&gt;&lt;br /&gt;The thin wire-wrapping wires are soldered to a scrap &amp;nbsp;of veroboard for test connections , and the code is running on a PIC16F688.&amp;nbsp;The shift regs are wired to share common clock lines, but each has its own serial data line, so all LED data can be loaded in 8 clock pulses so refresh should be nice and fast in the final thing.&lt;br /&gt;&lt;br /&gt;Everything seemed to work first time, amazingly! These water clear RGB LEDs are nice and bright, but its possible to see the individual red/green/blue elements more than you would in a diffused LED (e.g. when you display yellow you can see the red and green elements rather than a single yellow point). I'm hopeful this won't be a problem when the thing is spinning and viewed from a distance.&lt;br /&gt;&lt;br /&gt;My 100 ohm series resistance is rather low when the LEDs are run continuously but in the past I've found a low-ish resistance like this to be good when pulsing the LEDs quickly in a POV display. Still - I'll have to try to make sure the LEDs dont get left on 100% duty for a long time just in case they don't like the current.&lt;br /&gt;&lt;br /&gt;I also mounted the board to the fan! With the help of some heavy duty double sided tape (for sticking carpets down) and cyanoacrylate superglue to hold the LEDs in the holes it seems to be pretty sturdy... famous last words...&lt;br /&gt;&lt;br /&gt;Next step is to build a microcontroller board small enough to fit into the hub of the fan, then we (me and the Rev's Neil and Dave from BuildBrighton) need to get it power (via a pair of coils) and data (hopefully a modulated signal riding on the power)... and so the fun will really start!&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-u26oGrShcTY/Tm58v6BbBsI/AAAAAAAACH0/SQIMZtTZGUw/s1600/DSC00047.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://4.bp.blogspot.com/-u26oGrShcTY/Tm58v6BbBsI/AAAAAAAACH0/SQIMZtTZGUw/s320/DSC00047.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-zDMvGFuKhCE/Tm586LzDYvI/AAAAAAAACH4/hbmtW2s3efk/s1600/DSC00050.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://2.bp.blogspot.com/-zDMvGFuKhCE/Tm586LzDYvI/AAAAAAAACH4/hbmtW2s3efk/s320/DSC00050.JPG" width="240" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-XU5C0YYNuFY/Tm59FqZYeXI/AAAAAAAACH8/3cFzX4rRD7s/s1600/DSC00043.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://3.bp.blogspot.com/-XU5C0YYNuFY/Tm59FqZYeXI/AAAAAAAACH8/3cFzX4rRD7s/s320/DSC00043.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-3032124435063845143?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/3032124435063845143/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2011/09/pov-message-fan-project-update.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/3032124435063845143'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/3032124435063845143'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2011/09/pov-message-fan-project-update.html' title='POV message fan project update'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-u26oGrShcTY/Tm58v6BbBsI/AAAAAAAACH0/SQIMZtTZGUw/s72-c/DSC00047.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-4966328500936734734</id><published>2011-09-11T14:12:00.000-07:00</published><updated>2011-09-12T02:41:55.570-07:00</updated><title type='text'>Home made flexible circuit boards</title><content type='html'>I got a couple of pieces of flexible copper-clad kapton sheet from ebay a few weeks back, and just got round to trying it out....&lt;br /&gt;&lt;br /&gt;We have a new project at Build Brighton hackspace to make a POV fan to display SMS text messages sent to it. There is a long way to go, but one of the first steps is to make the LED array to be fitted to a fan blade. This needs to be as light and compact as possible, but I also wanted it to have sixteen 5mm RGB LEDs (thats a total of 48 LEDs to drive). SMD shift registers and resistors, together with a flexible (but more importantly thin and light) board seemed just the ticket.&lt;br /&gt;&lt;br /&gt;I expected the sheets to be horrible to work with, and a nightmare for lifted traces, but actually it all went pretty well. I designed the layout for 8LEDs in EAGLE and then edited the image to double up the number of LEDS (my free version of EAGLE doesn't allow a layout big enough). I used press-n-peel blue toner-transfer film in my old HP LaserJet 1000 printer and ironed the toner onto the copper-clad film (just as I do for rigid PCBs) and etched in ferric chloride. Some gentle cleaning with fine steel wool and the result was pretty good.&lt;br /&gt;&lt;br /&gt;I've had a bit of practice with hand-soldering SMDs.. I use a 0.4mm needle tip and a high temp (400 celsius) with 0.015" silver bearing solder. The high temp helps zap the solder without heating the part for too long, as long as you're quick. I do all the work through a 10x loupe and make a lot of use of tweezers and a flux pen, and to be honest I actually quite enjoy it!&lt;br /&gt;&lt;br /&gt;There are 48 x 0805 resistors on the board and six 74HC595D shift registers, each with a 100nF 0805 bypass cap. The 5mm through hole RBG LEDs were surface mounted along the edge of the board and the shift regs were wired up with Kynar wire-wrap flex (I decided not to risk drilling the film). I used a wooden jig to space and hold the LEDs for soldering.&lt;br /&gt;&lt;br /&gt;I had a handy roll of kapton tape which I used to insulate the ground track so it didn't short on the LED anodes passing right above it. Since the tape is heat resistant it behaved itself while the LEDs were soldered. This solved an otherwise tricky routing problem.&lt;br /&gt;&lt;br /&gt;Soldering went fine, though it was obvious that things heat up much more quickly on the film than they would on a solid PCB, and solder stays molten longer since the heat has nowhere to go. I also think I should use a lower temp as the backing did seem to be getting slightly warped, but nothing serious.&lt;br /&gt;&lt;br /&gt;However everything seemed to go OK and my first experience of making a flexible board went pretty well!&lt;br /&gt;&lt;br /&gt;As for the POV fan project, I will keep ya posted&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-FqiOuP58uXM/Tm0jVhXbAZI/AAAAAAAACGU/V1MsLrxfT4A/s1600/DSC00004%25281%2529.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://2.bp.blogspot.com/-FqiOuP58uXM/Tm0jVhXbAZI/AAAAAAAACGU/V1MsLrxfT4A/s320/DSC00004%25281%2529.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-Ju52h3tx8Cs/Tm0jkb7w65I/AAAAAAAACGY/rUqSTW5xmiw/s1600/DSC00008%25281%2529.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://3.bp.blogspot.com/-Ju52h3tx8Cs/Tm0jkb7w65I/AAAAAAAACGY/rUqSTW5xmiw/s320/DSC00008%25281%2529.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-MNOUBNwe2BI/Tm0jyVOhjoI/AAAAAAAACGc/t8oNbFzScHo/s1600/DSC00013%25281%2529.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://2.bp.blogspot.com/-MNOUBNwe2BI/Tm0jyVOhjoI/AAAAAAAACGc/t8oNbFzScHo/s320/DSC00013%25281%2529.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-dstgzVaFBAE/Tm0j_k83fiI/AAAAAAAACGg/J7XDt5JWOoE/s1600/DSC00017%25281%2529.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://3.bp.blogspot.com/-dstgzVaFBAE/Tm0j_k83fiI/AAAAAAAACGg/J7XDt5JWOoE/s320/DSC00017%25281%2529.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-4966328500936734734?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/4966328500936734734/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2011/09/home-made-flexible-circuit-boards.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/4966328500936734734'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/4966328500936734734'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2011/09/home-made-flexible-circuit-boards.html' title='Home made flexible circuit boards'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-FqiOuP58uXM/Tm0jVhXbAZI/AAAAAAAACGU/V1MsLrxfT4A/s72-c/DSC00004%25281%2529.JPG' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-6241089213131341337</id><published>2011-07-04T14:54:00.000-07:00</published><updated>2011-07-04T15:02:22.731-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='solid state tesla coil'/><title type='text'>Solid State Tesla Coil Fun</title><content type='html'>A solid state tesla coil is one that uses transistors to switch the primary coil voltage (instead of a spark gap or mechanical contacts). Using transistors also makes it straightforward to get the coil to spark at specific frequencies (e.g. to play a specific musical note). You can also make a simple feedback loop driven by an antenna picking up the EM field, which can automatically "tune" the coil to run it at its resonant frequency.&lt;br /&gt;&lt;br /&gt;Anyway -&amp;nbsp;a few months ago I made a solid state tesla coil based on &lt;a href="http://stevehv.4hv.org/SSTC5.htm"&gt;Steve Ward's design&lt;/a&gt;. I put it in a box made of acrylic sheets and hot glue which had a couple of flaws - namely lack of shielding of the logic ICs (like the 555-based oscillator which drives the coil) against the strong electric field - so the coil fried its own electronics! and the other flaw.. well it fell to bits basically :)&lt;br /&gt;&lt;br /&gt;I always meant to resurrect it in a more appropriate metal case and decided to go for some cool 1.5mm aluminium treadplate (not realising how hard it is to bend that stuff with any accuracy). My recently acquired jigsaw and drill press meant I was able to put together a box made of MDF sheets and&amp;nbsp;pine mouldings&amp;nbsp;which actually looks mostly OK :) The secondary is magnet wire (about 800 turns) wound on a PVC drain pipe, topped with a steel sphere garden ornament.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-tqj_jgr4VaI/ThI246YylwI/AAAAAAAAB60/wwAdvtJHHyA/s1600/tesla2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" i$="true" src="http://2.bp.blogspot.com/-tqj_jgr4VaI/ThI246YylwI/AAAAAAAAB60/wwAdvtJHHyA/s320/tesla2.jpg" width="247" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Steve Wards circuit is designed to run at 120VAC US mains. I built mine using uprated MOSFETs, caps and bridge to run at 240VAC UK mains supply, but I'm still being a chicken and running the primary through a step down transformer at 30VAC. Once I've played with different drive circuits I will probably add cooling fans and give it a try on higher voltages via a variac. But, before I blow it all up, I'm going to play with it some more and try controlling it via MIDI.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-G4RcpQL33To/ThI2v_woiDI/AAAAAAAAB6w/FJHo6DpfXiY/s1600/sstc.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" i$="true" src="http://1.bp.blogspot.com/-G4RcpQL33To/ThI2v_woiDI/AAAAAAAAB6w/FJHo6DpfXiY/s320/sstc.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;First off I had to work out how to get the coil to play a tune. I already had a little PIC circuit that could play &lt;a href="http://hotchk155.blogspot.com/2010/01/diy-annoying-greetings-card.html"&gt;a dodgy version of "Captain Pugwash"&lt;/a&gt; on a piezo sounder. I tried Using an opto-isolator driven by the PIC's square wave output to replace the 555 timer output in Steve Ward's circuit and it worked.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://0.gvt0.com/vi/HdBoE39Ch-g/0.jpg" height="266" width="320"&gt;&lt;param name="movie" value="http://www.youtube.com/v/HdBoE39Ch-g&amp;fs=1&amp;source=uds" /&gt;&lt;param name="bgcolor" value="#FFFFFF" /&gt;&lt;embed width="320" height="266"  src="http://www.youtube.com/v/HdBoE39Ch-g&amp;fs=1&amp;source=uds" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Before I plug any MIDI leads into it I need to make a fibre optic connection. I think the EM field around the coil would induce a voltage in any wiring that wouldn't be too kind to a MIDI keyboard or soundcard. Working on that bit now....&lt;br /&gt;&lt;br /&gt;Something else I had a go at was an "ion windmill"... this is simply an "S"-shaped bit of bent wire that can spin around a vertical wire stuck to the top of the coil. When the coil is on, the electrons streaming from the tips of the wire drive it round!&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://3.gvt0.com/vi/yd5Tv-yzI5M/0.jpg" height="266" width="320"&gt;&lt;param name="movie" value="http://www.youtube.com/v/yd5Tv-yzI5M&amp;fs=1&amp;source=uds" /&gt;&lt;param name="bgcolor" value="#FFFFFF" /&gt;&lt;embed width="320" height="266"  src="http://www.youtube.com/v/yd5Tv-yzI5M&amp;fs=1&amp;source=uds" type="application/x-shockwave-flash"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-6241089213131341337?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/6241089213131341337/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2011/07/solid-state-tesla-coil-fun.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/6241089213131341337'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/6241089213131341337'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2011/07/solid-state-tesla-coil-fun.html' title='Solid State Tesla Coil Fun'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-tqj_jgr4VaI/ThI246YylwI/AAAAAAAAB60/wwAdvtJHHyA/s72-c/tesla2.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-8426176242255716155</id><published>2011-06-16T09:19:00.000-07:00</published><updated>2011-06-17T01:37:29.085-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ftdi vnc2 vinculo vnclo vinculum vinclo review'/><title type='text'>FTDI's Vinculo Development Board: A Review</title><content type='html'>I was lucky enough to get involved in the Farnell/element14 'road test' programme, where individual electronic hobbyists get a chance to review (and keep) cool hardware items from Farnell.&lt;br /&gt;&lt;br /&gt;If you don't know it already, element14 (&lt;a href="http://www.element14.com/"&gt;www.element14.com&lt;/a&gt;) is a community/networking site for electronics professionals and hobbyists, run by the electronic components supplier Farnell...&lt;br /&gt;&lt;br /&gt;Last year I was lucky enough to attend a really useful free Eagle (PCB Design Tool) course run by element14, and earlier this year my local hackspace, BuildBrighton, reached the final of the Great Global Hackspace Challenge which was sponsored (very generously) by element14.&lt;br /&gt;&lt;br /&gt;While other suppliers might give out samples and freebies to industry, its refreshing that Farnell/element14 really do seem to be actively targetting and supporting the electronics hobbyist/hacker community - and so I am more than happy to sing their praises here.&lt;br /&gt;&lt;br /&gt;Anyway, back to my road testing... I chose to review the &lt;a href="http://uk.farnell.com/jsp/displayProduct.jsp?sku=1872599"&gt;VNCLO-START1 kit&lt;/a&gt;&amp;nbsp;from&amp;nbsp;&lt;a href="http://uk.farnell.com/ftdi/"&gt;FTDI&lt;/a&gt;. This kit is made up of a USB development board and a separate programmer/debugger board and the current cost on Farnell's web site is a little under £28.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-ZD16lklQRB8/TfovAfZrCiI/AAAAAAAAB6c/v0nttuc_fZ4/s1600/VNCLO-START1-FTDI-FNT-LRG.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="184" src="http://2.bp.blogspot.com/-ZD16lklQRB8/TfovAfZrCiI/AAAAAAAAB6c/v0nttuc_fZ4/s320/VNCLO-START1-FTDI-FNT-LRG.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The development board is branded the Vinco/Vinclo/Vinculo/Vnclo (it seems that FTDI aren't sure about the name yet, but I will call it “Vinculo”) containing the 64-pin version of FTDI's VNC2 'Vinculum' USB Host/Slave chip. &lt;br /&gt;&lt;br /&gt;Very interestingly, FTDI have given the board the same form factor as an Arduino Uno, including pin-compatible Arduino shield header sockets and even an on-board ADC chip to provide the six analog inputs. This means that you should be able to make use of existing Arduino shields (add on boards) with the Vinculo, which is a clever move by FTDI.&lt;br /&gt;&lt;br /&gt;The Vinculo can emulate an Arduino because it's on-board VNC2 chip is so much more than just a USB controller... its a fully fledged MCU. In fact it's a very powerful one, with a 16-bit core, 256kB of Flash, 16kB of RAM and 48Mhz clock among some other nice features... This makes it substantially more powerful that the AVR chip on the Arduino....And that’s before we get on to its USB support: Two full speed USB ports, each individually configurable as host or slave!&lt;br /&gt;&lt;br /&gt;So, we're talking an impressive piece of silicon (and a reasonably priced one, with the&lt;a href="http://uk.farnell.com/ftdi/vnc2-64l1b/controller-usb-vinculum-ii-64lqfp/dp/1863858"&gt; 64-pin VNC2&lt;/a&gt; chips selling on Farnell's site for just over £3, which is cheaper than the Atmega328). &lt;br /&gt;&lt;br /&gt;I am planning to use VNC2 chips in two projects I have in the pipeline:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The first to USB-host a Novation Launchpad keypad controller and run a suite of animation/MIDI-input apps. The idea is to make a standalone version of my 'playpad' MIDI controller projects.&lt;/li&gt;&lt;li&gt;The second is as the 'brain' of my laser projector, where I need a high speed USB device to push coordinate data from a PC to a pair of DACs driving laser-projector galvos. Using a VNC2 means I can use a single chip (no need for separate USB chip and MCU) while avoiding the slowness of a polled USB stack implemented in software.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;The Vinculo board seems like the perfect way to prototype these projects... so how to get started?&lt;br /&gt;&lt;br /&gt;FTDI have a free, downloadable developer toolchain for the VNC2. This works with the VNC2 programmer/debugger to allow programming and interactive debugging of the Vinculo. And I really do mean interactive debugging... single stepping, breakpoints, watches and so on... controlled via USB to the debug board.. put that in your Arduino pipe and smoke it :)&lt;br /&gt;&lt;br /&gt;So that's all good news, but once I got started I found a few problems with the developer tools which made me think FTDI may not be quite there yet...&lt;br /&gt;&lt;br /&gt;First of all I was unable to use the IDE on my desktop computer (where I do all my coding) because of a strange display problem with the source code editor window - all the text becomes garbled and unreadable each time the window scrolls. I reported this to FTDI support who quickly got back with a 'That’s strange, we'll look into it' kind of response but no fix as yet. However, luckily my laptop doesn't get the same issue so I could move on.&lt;br /&gt;&lt;br /&gt;The second issue I found was stability of the IDE, particularly during debug sessions but even some times when compiling, the IDE would stop responding and needs to be killed in task manager and restarted.&lt;br /&gt;&lt;br /&gt;Moving on, I played a bit with some of the provided sample code. The Vinculo is not FTDI's first VNC2 evaluation board, and some of the sample code is for the older eval board, which has different pin to connector mappings, meaning that the older sample programs don't work on the Vinculo without modifications. For example the UART (used by the sample programs for debug output) has moved.&lt;br /&gt;&lt;br /&gt;Luckily the remapping can be done in software.... a very nice feature of the VNC2 is that all the IO's go through a programmable multiplexer, so IO functions can be assigned to pins of your choosing. However the need to reassign IO's just to get the sample programs to work isn't what you want when you're first starting with a new device.&lt;br /&gt;&lt;br /&gt;Another niggle is that while there are sample programs provided to demonstrate standard Arduino stuff (blinking LED, PWM examples and so on) what is glaringly lacking are any USB code examples that will work, without modification, on the Vinculo.&amp;nbsp;Since USB is the attraction of Vinculo over vanilla Arduino I think this is something FTDI need to work on to make the board attractive to Arduino fans... I am still trying to work out how to modify the USB examples to get them running on Vinculo, and its not been straightforward.&lt;br /&gt;&lt;br /&gt;On a more positive note, something FTDI have done is to create a simple application framework that should appeal to Arduino coders by presenting an Arduino-like syntax....&amp;nbsp;For example, when using the supplied main.c in your Vinculo project you define the Arduino standard entry points 'setup' and 'loop'.&lt;br /&gt;&lt;br /&gt;Arduino-likey function wrappers like digitalOut() are provided, and libraries like Serial are emulated with structures containing function pointers, so familiar Arduino syntax like Serial.begin(9600); can be used....&amp;nbsp;Its just syntactic sugar, since behind the scenes the VNC2 API functions are being called, and its not 100% compatible (don't expect your Arduino code to 'just work' on Vinculo). However, it's a nice idea and will certainly appeal to Arduino developers. And you are still free to simply ignore it and work directly with the VNC2 API if you prefer.&lt;br /&gt;&lt;br /&gt;FTDI also have a variety of documentation for online download, which I am still working my way through. I have to say the information seem to be a bit 'scattered' over many different application notes, but at least it mostly seems to be there. Its just a bit daunting and confusing when you first get started.&lt;br /&gt;&lt;br /&gt;In conclusion, I have to say I'm very excited by this hardware. The VNC2 is a powerful and flexible chip, and the Vinculo is a great prototyping board, encompassing some innovative ideas by FTDI. &lt;br /&gt;&lt;br /&gt;However, at the moment I think much could be improved in the accompanying development software package. For me it has been a uphill struggle, and I think that Arduino users who are not experienced coders may fall at the first hurdle with this.. that is until FTDI can iron out the IDE issues and provide a more consistent and usable set of Vinculo code samples.&lt;br /&gt;&lt;br /&gt;This &lt;i&gt;is &lt;/i&gt;a new product though, so I have hopes that these things will improve soon with software patches.&lt;br /&gt;&lt;br /&gt;A couple of other things that would be nice are&lt;br /&gt;&lt;ul&gt;&lt;li&gt;That Arduino staple - The always-useful pin 13 LED&lt;/li&gt;&lt;li&gt;The ability to direct debug text output over the same USB cable that runs the debugger, where is can perhaps show up as a virtual COM port on the host PC (like on the mbed).&lt;/li&gt;&lt;/ul&gt;I will post again soon with my progress applying the Vinculo/VNC2 to my own projects... watch this space!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-8426176242255716155?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/8426176242255716155/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2011/06/ftdis-vinculo-development-board-review.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/8426176242255716155'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/8426176242255716155'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2011/06/ftdis-vinculo-development-board-review.html' title='FTDI&apos;s Vinculo Development Board: A Review'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-ZD16lklQRB8/TfovAfZrCiI/AAAAAAAAB6c/v0nttuc_fZ4/s72-c/VNCLO-START1-FTDI-FNT-LRG.jpg' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-5313152168484036857</id><published>2011-06-06T13:03:00.000-07:00</published><updated>2011-06-06T13:34:35.866-07:00</updated><title type='text'>Solenoid Percussion for BuildBrighton's Noise Toys Event</title><content type='html'>&lt;div style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none;"&gt;Video by Barnoid (&lt;a href="http://www.flickr.com/photos/barnoid/"&gt;http://www.flickr.com/photos/barnoid/&lt;/a&gt;)&lt;/div&gt;&lt;object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" data="http://www.flickr.com/apps/video/stewart.swf?v=71377" height="225" type="application/x-shockwave-flash" width="400"&gt; &lt;param name="flashvars" value="intl_lang=en-us&amp;photo_secret=5c5e512f82&amp;photo_id=5800707271"&gt;&lt;/param&gt;&lt;param name="movie" value="http://www.flickr.com/apps/video/stewart.swf?v=71377"&gt;&lt;/param&gt;&lt;param name="bgcolor" value="#000000"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;embed type="application/x-shockwave-flash" src="http://www.flickr.com/apps/video/stewart.swf?v=71377" bgcolor="#000000" allowfullscreen="true" flashvars="intl_lang=en-us&amp;photo_secret=5c5e512f82&amp;photo_id=5800707271" height="225" width="400"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" data="http://www.flickr.com/apps/video/stewart.swf?v=71377" height="225" type="application/x-shockwave-flash" width="400"&gt; &lt;param name="flashvars" value="intl_lang=en-us&amp;photo_secret=34cb55b484&amp;photo_id=5801230292"&gt;&lt;/param&gt;&lt;param name="movie" value="http://www.flickr.com/apps/video/stewart.swf?v=71377"&gt;&lt;/param&gt;&lt;param name="bgcolor" value="#000000"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;embed type="application/x-shockwave-flash" src="http://www.flickr.com/apps/video/stewart.swf?v=71377" bgcolor="#000000" allowfullscreen="true" flashvars="intl_lang=en-us&amp;photo_secret=34cb55b484&amp;photo_id=5801230292" height="225" width="400"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Last monday, &lt;a href="http://www.buildbrighton.com/blog/"&gt;BuildBrighton&lt;/a&gt; (my local hackspace) along with &lt;a href="http://playgroupbrighton.org/"&gt;Playgroup&lt;/a&gt; (Brighton arts and events collective), ran “Noise Toys”... a day of making noisy gadgets in a local pub, anyone welcome – as part of the Brighton festival fringe.&lt;br /&gt;&lt;br /&gt;At BB we were intending to provide a selection of “sound sculptures” around the place, but in the end we only managed a couple, which included my Lava-Lamp modulated synthesiser and an “interactive solenoid percussion” thing, which I'll give you the low-down on here&lt;br /&gt;&lt;br /&gt;My idea was to have some MIDI triggered solenoid percussion (similar to &lt;/a&gt;&lt;a href="http://hotchk155.blogspot.com/2010/10/solenoid-drum-machine.html"&gt;http://hotchk155.blogspot.com/2010/10/solenoid-drum-machine.html&lt;/a&gt;) together with some kind of control surface to allow passing punters to control the solenoids and make little tunes and rhythms. &lt;br /&gt;&lt;br /&gt;I thought it would be fun to use my Novation Launchpad to control the solenoids. &lt;br /&gt;&lt;br /&gt;The Launchpad is a grid of illuminated buttons that is intended as a controller for Ableton Live (music app), but like most things it can be hacked :) &lt;br /&gt;&lt;br /&gt;A while back I made a little Windows-based program to run a “rain storm” sequencer on the Launchpad (as seen on &lt;a href="http://www.youtube.com/watch?v=ZgMDTJce9D8"&gt;http://www.youtube.com/watch?v=ZgMDTJce9D8&lt;/a&gt;). Basically this was a simple step sequencer where notes are triggered by pressing buttons on the Launchpad and they “fall” - only sounding when they hit the bottom of grid. Pressing buttons on the lower row toggles them between Green (notes in the column are played then cycled back to top of grid) and Red (note plays once and does not cycle)&lt;br /&gt;&lt;br /&gt;To add to the challenge (and because I needed the laptop to run Reason for the Lava Lamps) I thought it would be nice to be able to run the rain storm sequencer without the computer....&lt;br /&gt;&lt;br /&gt;The Launchpad is a USB device (it doesn't have 5-pin MIDI connectors) so something would be needed to work as a “USB host” to allow a program running on a microcontroller (Arduino, PIC etc) to listen out for button presses and to control the Launchpad lights while sending out MIDI notes to trigger the solenoids. &lt;br /&gt;&lt;br /&gt;I'd thought about making my Launchpad into a standalone MIDI controller before, and I had been looking at the FTDI VNC2 USB host chip (more about that later) but first of all I decided to try out the Sure Electronics USB HID Host Module which is based around a PIC and is a little short of £10 on eBay including the postage. &lt;br /&gt;&lt;br /&gt;Sure's board is a nice little module, with 0.1” headers for the PICKit programmer and for serial comms with other application hardware. It also has a USB Type-A (host) socket and couple of addressable LED's. The on-board PIC24FJ256GB110 supports “USB On the go” (OTG) which means it can act as a USB host. Sure's web-site has downloadable source code for a firmware app, based Microchip's own open-source USB host stack, that will host a standard USB mouse or keyboard. &lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-trkFDOi9xJA/Te00Jx4SbBI/AAAAAAAAB6Q/sm4NPPAQxpM/s1600/hidhost.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-trkFDOi9xJA/Te00Jx4SbBI/AAAAAAAAB6Q/sm4NPPAQxpM/s1600/hidhost.jpg" t8="true" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The only disappointment here is that only a minimal set of I/Os from the PIC are bought out through the headers which limits applications of the board since most of the PICs I/Os are inaccessible. Still, its a nice handy board and reasonably priced. But will it work with the Launchpad? &lt;br /&gt;&lt;br /&gt;The Launchpad is not a standard USB MIDI or HID device. Rather it has a custom interface using two interrupt endpoints. This can be accommodated on the PIC with a couple of mods to the “Generic” device driver code from Microchips stack. It was my first time working with USB hosting and with 16-bit PICs so it was a learning experience.&lt;br /&gt;&lt;br /&gt;When used under Windows via the Novation drivers, the Launchpad shows up as a MIDI device and is controlled by sending it MIDI note and controller info to toggle the LEDs. When Launchpad's buttons are pressed, it spits out MIDI notes/controllers which an application can act on. &lt;br /&gt;&lt;br /&gt;So that the MIDI interface from Windows but exactly is happening on the USB wire? Well, a quick bit of trace code on the PIC showed that exactly the same MIDI bytes are being passed between the USB endpoints, making it nice and easy to drive the Launchpad from an embedded USB host like the PIC. Thankyou, Novation!&lt;br /&gt;&lt;br /&gt;So on to the Rainstorm sequencer program, which I wanted to run on the same PIC. The sequencer code itself is pretty simple, but there are some complications when using Microchip's USB host stack which meant it took a while to get it working....&lt;br /&gt;&lt;br /&gt;The main gotcha for me was that USB I/O operations need to be first initiated then polled for completion (or they can send completion events). However, to keep the stack ticking, the app must poll it via a “USBTasks” function. Without this polling, the stack does nothing and I/O will not complete. Ok, so just call USBTasks all over the place right? No sireeee, not if you don't want to end up in a confusing re-entrant mess and watch the PIC collapse in a heap.&lt;br /&gt;&lt;br /&gt;In fact you need to be careful not to make USBTasks call anywhere but the top level loop, and to make sure that the application attempts just one USB I/O operation between USBTasks calls. One result of this is that long sequences of USB I/Os can become painfully slow to complete. With the Rainstorm sequencer I found that it became very sluggish at responding to input when there were more than a couple of dozen notes in play.&lt;br /&gt;&lt;br /&gt;I am looking forward to trying this on the FTDI VNC2 chip which has the USB stack and application running in separate threads and should be able to get much better throughput.&lt;br /&gt;&lt;br /&gt;OK – back to the fun and games! So the UART from the PIC is broken out to the header on the Sure Electronics board, and with the code changed to set up the correct MIDI baud rate and remove all other UART debug output from the code I could just stick on a 5-pin DIN socket via a couple of 220R resistors and I was sending MIDI.&lt;br /&gt;&lt;br /&gt;On the other end of the MIDI connection I had a breadboard with a PIC16F688 receiving MIDI through a 6N138 isolator and triggering 8 digital outputs (each mapped to a MIDI note from the sequencer). Each output goes through a 1K resistor to a TIP120 NPN power transistor which directly drives a solenoid. The solenoids need about 18 volts to work properly so there's a 7805 and smoothing caps between the 18V side and the 5V logic side. I also had a hefty cap (2200uF) smoothing the 18V side since the solenoids can cause some big voltage dips when they fire all at once and this can reset the PIC. The schematic is available &lt;a href="http://hotchk155.blogspot.com/2010/10/solenoid-drum-machine.html"&gt;here&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Once all the electronics was working it was time for the art... and unfortunately I didn't leave myself much time for that bit. I ended up gathering up milk bottles and hammering together a wooden frame for them to sit on, all the night before the gig. I had for some reason assumed that milk bottles, tuned with water, would make a pleasing “xylophone” effect... I hadn't really anticipated the the terrifying wall of machine gun clinking that they actually threw out. &lt;br /&gt;&lt;br /&gt;Hmmm, well, there is always next time :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-5313152168484036857?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/5313152168484036857/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2011/06/solenoid-percussion-for-buildbrightons.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/5313152168484036857'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/5313152168484036857'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2011/06/solenoid-percussion-for-buildbrightons.html' title='Solenoid Percussion for BuildBrighton&apos;s Noise Toys Event'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-trkFDOi9xJA/Te00Jx4SbBI/AAAAAAAAB6Q/sm4NPPAQxpM/s72-c/hidhost.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-203574470544401462</id><published>2011-05-05T02:04:00.000-07:00</published><updated>2011-05-05T02:50:48.462-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='spectrum diy'/><title type='text'>Adding a composite output to a ZX Spectrum</title><content type='html'>Tonight at &lt;a href="http://www.buildbrighton.com/blog/"&gt;BuildBrighton&lt;/a&gt;&amp;nbsp;we have Sinclair night! One problem that we have is that the Spectrum, ZX81 etc (and a lot of other 1980's home computers) do not have composite video output sockets but rather were designed to run on an analog TV set tuned to the correct channel to pick up their signal. Analog TV sets are getting a bit hard to find these days, so this is an inconvenience...&lt;br /&gt;&lt;br /&gt;Many&amp;nbsp;years back I got&amp;nbsp;my Spectrum to run on an old greenscreen mono monitor I was given. I don't have that speccy any more but decided to try the same trick on a spec I picked up on eBay earlier this year. With a composite output it is possible to hook it up to most modern TVs and many computer monitors.&lt;br /&gt;&lt;br /&gt;Well, technically there is nothing to it... the Spectrum already has the composite signal (it is fed into the UHF modulator box that converts it to a TV signal) so its just a matter of getting the signal to the outside world. &lt;br /&gt;&lt;br /&gt;I already had a 3.5mm mono jack to coaxial video lead from an Olympus digital camera (its the lead for showing your pics on the TV set) so I decided to simply add a 3.5mm socket so I could use the same lead.&lt;br /&gt;&lt;br /&gt;The modulator is the nice little tin box on the inside of the Specc's TV connector. &lt;strong&gt;Take care when lifting the lid off the speccy or you might accidentally pull out the keyboard ribbons&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-fUf-Xe40i20/TcJmY53zbvI/AAAAAAAAB5c/QfuRtjc2DkM/s1600/DSC00167.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" j8="true" src="http://4.bp.blogspot.com/-fUf-Xe40i20/TcJmY53zbvI/AAAAAAAAB5c/QfuRtjc2DkM/s320/DSC00167.JPG" width="240" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div align="left" class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&amp;nbsp;Connect the SIGNAL (jack plug tip) to the connection going into the box furthest back from the TV socket (on my speccy it had a white plastic insulator). Connect GROUND (jack plug barrel) to the metal box itself, using solder to make sure you get a good connection.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-IIO-khU8eLQ/TcJmhUmmBUI/AAAAAAAAB5g/2KvltshxgPk/s1600/DSC00171.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" j8="true" src="http://2.bp.blogspot.com/-IIO-khU8eLQ/TcJmhUmmBUI/AAAAAAAAB5g/2KvltshxgPk/s320/DSC00171.JPG" width="240" /&gt;&lt;/a&gt;&lt;/div&gt;&amp;nbsp;Fit the socket... ah hot glue, how thee makes a craftsman of any pleb!&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-SfnuBpRNKb0/TcJmqDZZihI/AAAAAAAAB5k/1kTFsJsKOEQ/s1600/DSC00173.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" j8="true" src="http://3.bp.blogspot.com/-SfnuBpRNKb0/TcJmqDZZihI/AAAAAAAAB5k/1kTFsJsKOEQ/s320/DSC00173.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;... get out the swiss army knife and scratch a groove to accomodate the socket in the lid so it can close&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-EKnyaszSoMQ/TcJmysaoVCI/AAAAAAAAB5o/iDMyFHVyvXU/s1600/DSC00176.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" j8="true" src="http://1.bp.blogspot.com/-EKnyaszSoMQ/TcJmysaoVCI/AAAAAAAAB5o/iDMyFHVyvXU/s320/DSC00176.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;And the proof of the pudding... a "Specbook"&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-KxP6J0-aMtw/TcJm7v9VeCI/AAAAAAAAB5s/1j22S4qRnOk/s1600/DSC00177.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" j8="true" src="http://4.bp.blogspot.com/-KxP6J0-aMtw/TcJm7v9VeCI/AAAAAAAAB5s/1j22S4qRnOk/s320/DSC00177.JPG" width="240" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-203574470544401462?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/203574470544401462/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2011/05/adding-composite-output-to-zx-spectrum.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/203574470544401462'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/203574470544401462'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2011/05/adding-composite-output-to-zx-spectrum.html' title='Adding a composite output to a ZX Spectrum'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-fUf-Xe40i20/TcJmY53zbvI/AAAAAAAAB5c/QfuRtjc2DkM/s72-c/DSC00167.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-7333721293811398952</id><published>2010-12-19T09:03:00.000-08:00</published><updated>2010-12-19T09:43:38.310-08:00</updated><title type='text'>Battlezone With Lasers Part 2</title><content type='html'>Still an ongoing project to play Atari Battlezone via a laser projector (for no other reason than I like a challenge :)). &lt;br /&gt;&lt;br /&gt;I stumbled for a long time over pushing data fast enough to a microcontroller, with a USB serial port proving too slow and a USB isosynchronous device being very complicated to program. Now I am using an mbed microcontroller board (with a decent amount of RAM and fast clock) to receive data and drive the DACs, and with the ethernet support of the mbed, I am able to send data over a TCP socket, which seems to be plenty fast enough.&lt;br /&gt;&lt;br /&gt;The mbed's speed and RAM also allowed me to do a lot of the number crunching on the microcontroller (in particular the plotting of lines) so all I need is to push the lists of vertices to the mbed and it will generate "in between" points along a line (required so that the laser galvos can be moved a bit more incrementally - and with less probems of intertia -than just throwing them at the raw vertices. Also means I can keep plotting a frame while the next one arrives.&lt;br /&gt;&lt;br /&gt;The "hard bit" - the actual Battlezone game - is actually easy, since I am using the wonderful open-source MAME emulator and was simply able to locate the vector display emulation code and hook my stuff into it. Luckily Battlezone does output vectors with decent continuity (i.e. where lines join up they tend to be sent consecutively, which saved me sorting list into some kind of optimised plot order). So basically my hooks in the MAME vector code just convert the floating point vector coordinates into 12 bit integer values (for my ADC) and flag "move" vs "draw" actions. Then the list can be dumped to the TCP socket at the end of the refresh cycle. At the moment I am only outputting every 10th frame to let the microcontroller breathe.&lt;br /&gt;&lt;br /&gt;On the mbed side I am using a MCP4922 12-bit dual Digital to Analog Converter (DAC) with SPI serial interface, which can easily be driven from the mbed. The DACs drive a 20kpps Galvo set purchased from ebay (about £100 including PSU and drivers). I also have a 6N139 opto isolator driving the TTL blanking for the laser (a 50mW green DPSS module from Aixiz). &lt;br /&gt;&lt;br /&gt;I am still working on the mbed code... at the moment I use a kind of double buffering with 2x16kb buffers, one of which can receive the frame buffer from TCP/IP socket while the mbed is plotting the other. Between plots the mbed checks if the receive frame is complete and switches the buffers if this is the case.&lt;br /&gt;&lt;br /&gt;The frame rate I can plot is too slow, and I need to work out how to make it better.&amp;nbsp; I need to force delays during plotting to allow the mechanical galvos to catch up with the driver signal. These are all &amp;lt;1ms but they add up and reduce the frame rate. Also the lines are "plotted" with "in-between" point calculation to try to keep galvo movement rate reasonable. I need to work out the best combination of delays and divisions to get the best plot with the best framerate. I am also thinking about recognising the text at the top of the display (status text and scanner) and missing them out of the plot (text kills the plot rate)&lt;br /&gt;&lt;br /&gt;Still a work in progress, but fun!&lt;br /&gt;&lt;br /&gt;&lt;object width="480" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/8RUx0SUqvYs?fs=1&amp;amp;hl=en_GB"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/8RUx0SUqvYs?fs=1&amp;amp;hl=en_GB" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-7333721293811398952?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/7333721293811398952/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2010/12/battlezone-with-lasers-part-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/7333721293811398952'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/7333721293811398952'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2010/12/battlezone-with-lasers-part-2.html' title='Battlezone With Lasers Part 2'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-5093638058445093451</id><published>2010-11-27T04:20:00.000-08:00</published><updated>2010-11-27T04:20:35.357-08:00</updated><title type='text'>Tesla coil diary - part 2</title><content type='html'>&lt;a href="http://3.bp.blogspot.com/_rn0sSfRNtpI/TPDxuzUEjNI/AAAAAAAABzc/P3ovb-Z9TCA/s1600/spark.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="304" ox="true" src="http://3.bp.blogspot.com/_rn0sSfRNtpI/TPDxuzUEjNI/AAAAAAAABzc/P3ovb-Z9TCA/s320/spark.JPG" width="320" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;I've been playing on and off with the coil for the last couple of months, but the first test a few weeks ago was a little bit disappointing, only managing sparks of 6" or so and then only to ground (no air streamer breakout event with a breakout point﻿ on the top)&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;At first I thought the problem was positioning of the primary coil tap (i.e. change the number of active turns on the bottom coil) but I still could not get any better than 6" sparks to ground. Then I started to play with the spark gap and found that using a spacer to force a larger gap between the lengths of copper&amp;nbsp;tube making up my static gap, the sparks improved a bit. That is until the spacers caught fire :)&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;So, I decided to try with a simple rotary spark gap and holy crap did it make a difference! Here it is... &lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;img border="0" height="320" ox="true" src="http://4.bp.blogspot.com/_rn0sSfRNtpI/TPDxsUmNdcI/AAAAAAAABzY/vl134ZmkPMY/s320/gap.JPG" width="304" /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;I used 5mm acrylic sheet as a base material and a nominal 3000rpm shaded pole motor running at 240VAC. In theory 3000rpm is 50 revs per second. With the spark gap opening twice per rev (i.e. presenting at zero and 180 degrees) this should give 100 breaks a second I think... in theory this is perfect for discharging the capacitor bank just as it reaches maximum charge twice (positive and negative) on each mains AC 50Hz cycle.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Thats the theory, but its not a proper synchronous motor and the load of the spinning gaps looks likely slow it down a bit... if I get on to tuning things further I might try to work out its actual RPM. The motor is fitted to a base plate which can be rotated so the phase (i.e. when in mains cycle the breaks happen) can be changed, but I think this is really only going to be of value if the break rate really is 100Hz. I haven't played with moving the motor yet, something for another day.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Well... here are the results, without any serious attempt at tuning the primary tap. &lt;/div&gt;&lt;object height="385" width="480"&gt;&lt;param name="movie" value="http://www.youtube.com/v/je4yGiBGmuc?fs=1&amp;amp;hl=en_GB"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/je4yGiBGmuc?fs=1&amp;amp;hl=en_GB" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Some other recent additions are a Terry Filter (safety spark gap and surge filter which protects the Neon Sign Transformer getting fried)&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_rn0sSfRNtpI/TPDxrS6jPNI/AAAAAAAABzU/rvwhLnOzehs/s1600/filter.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" ox="true" src="http://3.bp.blogspot.com/_rn0sSfRNtpI/TPDxrS6jPNI/AAAAAAAABzU/rvwhLnOzehs/s320/filter.jpg" width="284" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;And a wooden base for it all to sit on&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_rn0sSfRNtpI/TPDxwLiz9zI/AAAAAAAABzg/3xcAQBUYWcc/s1600/tc.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" ox="true" src="http://2.bp.blogspot.com/_rn0sSfRNtpI/TPDxwLiz9zI/AAAAAAAABzg/3xcAQBUYWcc/s320/tc.JPG" width="233" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;When I was packing it all up I was rather perturbed to receive small electric shocks every time I touched the secondary connections. At first I thought I had done something dumb like leave the mains connected or that the primary capacitors had remained charged somehow. However I got shocks handling the secondary even after I had completely removed it from the rest of the setup and I think the PVC pipe and/or the varnish layer were storing a static charge which leaked slowly over to the copper wire. The outside of the varnish certainly had a static charge like a TV screen right after the coil had been run. Interesting!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-5093638058445093451?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/5093638058445093451/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2010/11/tesla-coil-diary-part-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/5093638058445093451'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/5093638058445093451'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2010/11/tesla-coil-diary-part-2.html' title='Tesla coil diary - part 2'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_rn0sSfRNtpI/TPDxuzUEjNI/AAAAAAAABzc/P3ovb-Z9TCA/s72-c/spark.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-7032381824372087014</id><published>2010-10-24T11:57:00.000-07:00</published><updated>2010-10-24T12:43:28.092-07:00</updated><title type='text'>Solenoid Drum Machine</title><content type='html'>Just a quick project to try out some new push solenoids...&lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/YtjFoV0afuY?fs=1&amp;amp;hl=en_GB&amp;amp;rel=0"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/YtjFoV0afuY?fs=1&amp;amp;hl=en_GB&amp;amp;rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;Based on PIC16F688 and building on the MIDI input code used on my earlier POKEY project&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_rn0sSfRNtpI/TMSBBFFVSPI/AAAAAAAABy8/6KXbAs9On6U/s1600/picrelays.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="283" nx="true" src="http://2.bp.blogspot.com/_rn0sSfRNtpI/TMSBBFFVSPI/AAAAAAAABy8/6KXbAs9On6U/s400/picrelays.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;include &amp;lt;system.h&amp;gt;&lt;br /&gt;#include &amp;lt;memory.h&amp;gt;&lt;br /&gt;&lt;br /&gt;#pragma DATA _CONFIG, _MCLRE_OFF &amp; _WDT_OFF &amp; _INTRC_OSC_NOCLKOUT&lt;br /&gt;#pragma CLOCK_FREQ 8000000&lt;br /&gt;typedef unsigned char byte;&lt;br /&gt;&lt;br /&gt;// define the pins&lt;br /&gt;//#define P_LED     portc.0&lt;br /&gt;&lt;br /&gt;// MIDI defs&lt;br /&gt;#define MIDIMSG(b) ((b)&amp;gt;&amp;gt;4)&lt;br /&gt;#define MIDICHAN(b) ((b)&amp;0xf)&lt;br /&gt;#define MIDIMSG_NOTEON    0x09&lt;br /&gt;#define MIDIMSG_NOTEOFF    0x08&lt;br /&gt;&lt;br /&gt;// MIDI message registers&lt;br /&gt;byte runningStatus = 0;&lt;br /&gt;int numParams = 0;&lt;br /&gt;byte midiParams[2] = {0};&lt;br /&gt;&lt;br /&gt;#define SZ_RXBUFFER 20&lt;br /&gt;byte rxBuffer[SZ_RXBUFFER];&lt;br /&gt;byte rxHead = 0;&lt;br /&gt;byte rxTail = 0;&lt;br /&gt;int tmr[4] = {0};&lt;br /&gt;&lt;br /&gt;////////////////////////////////////////////////////////////&lt;br /&gt;// INTERRUPT HANDLER CALLED WHEN CHARACTER RECEIVED AT&lt;br /&gt;// SERIAL PORT&lt;br /&gt;void interrupt( void )&lt;br /&gt;{&lt;br /&gt;// check if this is serial rx interrupt&lt;br /&gt;if(pir1.5)&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// get the byte&lt;br /&gt;byte b = rcreg;&lt;br /&gt;&lt;br /&gt;// calculate next buffer head&lt;br /&gt;byte nextHead = (rxHead + 1);&lt;br /&gt;if(nextHead &amp;gt;= SZ_RXBUFFER)&lt;br /&gt;{&lt;br /&gt;nextHead -= SZ_RXBUFFER;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// if buffer is not full&lt;br /&gt;if(nextHead != rxTail)&lt;br /&gt;{&lt;br /&gt;// store the byte&lt;br /&gt;rxBuffer[rxHead] = b;&lt;br /&gt;rxHead = nextHead;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;////////////////////////////////////////////////////////////&lt;br /&gt;// INITIALISE SERIAL PORT FOR MIDI&lt;br /&gt;void init_usart()&lt;br /&gt;{&lt;br /&gt;pir1.1 = 1;        //TXIF&lt;br /&gt;pir1.5 = 0;        //RCIF&lt;br /&gt;&lt;br /&gt;pie1.1 = 0;        //TXIE         no interrupts&lt;br /&gt;pie1.5 = 1;        //RCIE         interrupt on receive&lt;br /&gt;&lt;br /&gt;baudctl.4 = 0;    // SCKP        synchronous bit polarity&lt;br /&gt;baudctl.3 = 1;    // BRG16    enable 16 bit brg&lt;br /&gt;baudctl.1 = 0;    // WUE        wake up enable off&lt;br /&gt;baudctl.0 = 0;    // ABDEN    auto baud detect&lt;br /&gt;&lt;br /&gt;txsta.6 = 0;    // TX9        8 bit transmission&lt;br /&gt;txsta.5 = 1;    // TXEN        transmit enable&lt;br /&gt;txsta.4 = 0;    // SYNC        async mode&lt;br /&gt;txsta.3 = 0;    // SEDNB    break character&lt;br /&gt;txsta.2 = 0;    // BRGH        high baudrate&lt;br /&gt;txsta.0 = 0;    // TX9D        bit 9&lt;br /&gt;&lt;br /&gt;rcsta.7 = 1;    // SPEN     serial port enable&lt;br /&gt;rcsta.6 = 0;    // RX9         8 bit operation&lt;br /&gt;rcsta.5 = 1;    // SREN     enable receiver&lt;br /&gt;rcsta.4 = 1;    // CREN     continuous receive enable&lt;br /&gt;&lt;br /&gt;spbrgh = 0;        // brg high byte&lt;br /&gt;spbrg = 15;        // brg low byte (31250)&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;byte rxInc(byte *pbIndex)&lt;br /&gt;{&lt;br /&gt;// any data in the buffer?&lt;br /&gt;if((*pbIndex) == rxHead)&lt;br /&gt;return 0;&lt;br /&gt;&lt;br /&gt;// move to next char&lt;br /&gt;if(++(*pbIndex) &amp;gt;= SZ_RXBUFFER)&lt;br /&gt;(*pbIndex) -= SZ_RXBUFFER;&lt;br /&gt;return 1;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;////////////////////////////////////////////////////////////&lt;br /&gt;// RECEIVE MIDI MESSAGE&lt;br /&gt;// Return the status byte or 0 if nothing complete received&lt;br /&gt;// caller must check midiParams array for byte 1 and 2&lt;br /&gt;byte receiveMessage()&lt;br /&gt;{&lt;br /&gt;// buffer overrun error?&lt;br /&gt;if(rcsta.1)&lt;br /&gt;{&lt;br /&gt;rcsta.4 = 0;&lt;br /&gt;rcsta.4 = 1;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// any data in the buffer?&lt;br /&gt;if(rxHead == rxTail)&lt;br /&gt;return 0;&lt;br /&gt;&lt;br /&gt;// peek at next char in buffer&lt;br /&gt;byte rxPos = rxTail;&lt;br /&gt;byte q = rxBuffer[rxPos];&lt;br /&gt;&lt;br /&gt;// is it a channel msg&lt;br /&gt;if((q&amp;0x80)&amp;gt;0)&lt;br /&gt;{&lt;br /&gt;runningStatus = 0;&lt;br /&gt;switch(q&amp;0xf0)&lt;br /&gt;{&lt;br /&gt;case 0x80: //  Note-off  2  key  velocity&lt;br /&gt;case 0x90: //  Note-on  2  key  veolcity&lt;br /&gt;case 0xA0: //  Aftertouch  2  key  touch&lt;br /&gt;case 0xB0: //  Continuous controller  2  controller #  controller value&lt;br /&gt;case 0xC0: //  Patch change  2  instrument #&lt;br /&gt;case 0xE0: //  Pitch bend  2  lsb (7 bits)  msb (7 bits)&lt;br /&gt;runningStatus = q;&lt;br /&gt;numParams = 2;&lt;br /&gt;break;&lt;br /&gt;case 0xD0: //  Channel Pressure  1  pressure&lt;br /&gt;runningStatus = q;&lt;br /&gt;numParams = 1;&lt;br /&gt;break;&lt;br /&gt;case 0xF0: //  (non-musical commands) - ignore all data for now&lt;br /&gt;return q;&lt;br /&gt;}&lt;br /&gt;// step over the message&lt;br /&gt;if(!rxInc(&amp;rxPos))&lt;br /&gt;return 0;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// do we have an active channel message&lt;br /&gt;if(runningStatus)&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// read params&lt;br /&gt;for(int thisParam = 0; thisParam &amp;lt; numParams; ++thisParam)&lt;br /&gt;{&lt;br /&gt;midiParams[thisParam] = rxBuffer[rxPos];&lt;br /&gt;if(!rxInc(&amp;rxPos))&lt;br /&gt;return 0;&lt;br /&gt;}&lt;br /&gt;// commit removal of message&lt;br /&gt;rxTail = rxPos;&lt;br /&gt;return runningStatus;&lt;br /&gt;}&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt;// remove char from the buffer&lt;br /&gt;rxInc(&amp;rxTail);&lt;br /&gt;return q;&lt;br /&gt;}&lt;br /&gt;return 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;void main()&lt;br /&gt;{&lt;br /&gt;// osc control / 8MHz / internal&lt;br /&gt;osccon = 0b01110001;&lt;br /&gt;&lt;br /&gt;// timer0... configure source and prescaler&lt;br /&gt;cmcon0 = 7;&lt;br /&gt;&lt;br /&gt;// enable serial receive interrupt&lt;br /&gt;intcon = 0b11000000;&lt;br /&gt;pie1.5 = 1;&lt;br /&gt;&lt;br /&gt;// configure io&lt;br /&gt;trisa = 0b00010000;&lt;br /&gt;trisc = 0b00110000;&lt;br /&gt;ansel = 0b00000000;&lt;br /&gt;&lt;br /&gt;porta=0;&lt;br /&gt;portc=0;&lt;br /&gt;memset(tmr,0,sizeof(tmr));&lt;br /&gt;&lt;br /&gt;// initialise MIDI comms&lt;br /&gt;init_usart();&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// loop forever&lt;br /&gt;for(;;)&lt;br /&gt;{&lt;br /&gt;// get next MIDI note&lt;br /&gt;byte msg = receiveMessage();&lt;br /&gt;if(msg)&lt;br /&gt;{&lt;br /&gt;byte note = midiParams[0];&lt;br /&gt;if(note &amp;gt;= 48 &amp;&amp; note &amp;lt; 52)&lt;br /&gt;{&lt;br /&gt;int which = note-48;&lt;br /&gt;// 0x90 note on&lt;br /&gt;// 0x80 note ff&lt;br /&gt;if((msg &amp; 0xf0) == 0x90)&lt;br /&gt;{&lt;br /&gt;tmr[which] = 200;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;for(int i=0;i&amp;lt;4;++i)&lt;br /&gt;{&lt;br /&gt;if(tmr[i] &amp;gt; 0)&lt;br /&gt;tmr[i]--;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;porta.2 = (tmr[0]&amp;gt;0)?1:0;&lt;br /&gt;portc.0 = (tmr[1]&amp;gt;0)?1:0;&lt;br /&gt;portc.1 = (tmr[2]&amp;gt;0)?1:0;&lt;br /&gt;portc.2 = (tmr[3]&amp;gt;0)?1:0;&lt;br /&gt;}&lt;br /&gt;}&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-7032381824372087014?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/7032381824372087014/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2010/10/solenoid-drum-machine.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/7032381824372087014'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/7032381824372087014'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2010/10/solenoid-drum-machine.html' title='Solenoid Drum Machine'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_rn0sSfRNtpI/TMSBBFFVSPI/AAAAAAAABy8/6KXbAs9On6U/s72-c/picrelays.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-3949601235875980244</id><published>2010-09-18T13:04:00.000-07:00</published><updated>2010-09-18T13:58:36.512-07:00</updated><title type='text'>Tesla Coil Diary - Part 1</title><content type='html'>I've wanted to own a Tesla coil pretty much since I knew what one was, but I always thought it would be a bit difficult to make and possibly a little bit dangerous... Anyway, I decided to bite the bullet and started gathering the bits a couple of months back and actually started the building of it a couple of weeks ago after I got the courage to fire up the 10kV Neon Sign Transformer I got off ebay. &lt;br /&gt;&lt;br /&gt;I got all the information and many great tips of websites of other coilers and have borrowed many ideas. I will try to remember and credit as much as I can.&lt;br /&gt;&lt;br /&gt;I started off by getting this neon transformer &lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_rn0sSfRNtpI/TJUQY2RrcvI/AAAAAAAAByk/aPjFfIDor5Q/s1600/P9181230.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" qx="true" src="http://2.bp.blogspot.com/_rn0sSfRNtpI/TJUQY2RrcvI/AAAAAAAAByk/aPjFfIDor5Q/s320/P9181230.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;its a 10kV 50mA F.A.R.T. (oh the fun!) Resinblock. Here is my first try out of it, making a Jacobs ladder from coat hanger wire....&lt;br /&gt;&lt;object height="385" width="480"&gt;&lt;param name="movie" value="http://www.youtube.com/v/YjWZp07FlDY?fs=1&amp;amp;hl=en_GB&amp;amp;rel=0"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/YjWZp07FlDY?fs=1&amp;amp;hl=en_GB&amp;amp;rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;So far so good... &lt;br /&gt;&lt;br /&gt;After a bit of online reading I eventually decided to wind my secondary coil on 125mm PVC ducting pipe (After deciding the 68mm drainpipe I first bought was just too wimpy). I got a nice 2Kg reel of 0.71mm magnet wire from ebay and got winding. I initially rigged up a motor driven jig to wind the wire but ended up&amp;nbsp;winding by hand so I could keep a good tension on the wire (The motor came in very useful later while varnishing). I wound 800 turns in a couple of hours then put on about 5 coats of polyurethane gloss varnish. I used kapton tape to secure the outer windings (I owe &lt;a href="http://deepfriedneon.com/"&gt;http://deepfriedneon.com/&lt;/a&gt; for many tips I used ... given my DIY prowess, without this information I would have ended in disaster I am sure)&lt;br /&gt;&lt;br /&gt;Here is&amp;nbsp;my winding rig...&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_rn0sSfRNtpI/TJUQPaRcsvI/AAAAAAAABx0/XvxrUJvsfeM/s1600/P9041174.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" qx="true" src="http://1.bp.blogspot.com/_rn0sSfRNtpI/TJUQPaRcsvI/AAAAAAAABx0/XvxrUJvsfeM/s320/P9041174.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;I was quite pleased with the end result, which looked nicely like something from a B-movie mad scientists lab.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;I originally bought 6mm microbore copper tubing to make my primary coil, but realised that I had not bought enough, and it was rather too expensive to go and buy&amp;nbsp;another, longer length, so I looked around for alternatives and found some 4.75mm solid aluminium wire at the much better price of £12 for 20 metres. The wire was a lot softer and easier to kink than I expected and at first I wasn't too happy with the result. But after some reworking I think its OK. Here is the result (set on MDF with acrylic stands secured with nylon zipties)&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div align="left" class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_rn0sSfRNtpI/TJUQUYiCfxI/AAAAAAAAByM/CO2_q-AXbsc/s1600/P9181217.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" qx="true" src="http://3.bp.blogspot.com/_rn0sSfRNtpI/TJUQUYiCfxI/AAAAAAAAByM/CO2_q-AXbsc/s320/P9181217.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;I managed about 17 turns. I think I need to tap the coil after about&amp;nbsp;10 turns based on what Tesla Coil CAD told me - but I thought it would be good to have the extra tunability offered by the extra coils&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;For the top load I&amp;nbsp;got some 10mm semi-rigid aluminium ducting hose (as is a coiler traditional I believe) and set it between two 34cm steel trays from the local 99p shop (these have to be the best bargain of this build!). This whole procedure was more difficult than it probably sounds... I needed to bolt the trays together first, with a wood spacer, then use tensioned strips of gaffer tape to hold the 2 plates parallel to each other. Then I threaded a rubber bungee cord through the flexible duct and after putting&amp;nbsp;the ducting&amp;nbsp;around the rim of the trays I hooked up the bungee and spread the out ducting round the rim until it joined up. I used a bit of flexible plastic sheet to make a sleeve to put inside one end of the ducting and help join the ends together. A bit of aluminium tape joined the ends, then more aluminimum tape to secure the ducting on the rim of the trays (helpful tips from &lt;a href="http://www.hvtesla.com/toroid.html"&gt;http://www.hvtesla.com/toroid.html&lt;/a&gt;)&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div align="left" class="separator" style="clear: both; text-align: center;"&gt;﻿&lt;a href="http://1.bp.blogspot.com/_rn0sSfRNtpI/TJUQWNe1ZZI/AAAAAAAAByU/GJJFqwwWOxw/s1600/P9181219.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" qx="true" src="http://1.bp.blogspot.com/_rn0sSfRNtpI/TJUQWNe1ZZI/AAAAAAAAByU/GJJFqwwWOxw/s320/P9181219.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;It might not be the best looking toroid, but it does look pretty meaty and mean!&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Next steps are to&amp;nbsp;add a strike rail to the primary (finally getting some use out of that microbore copper pipe), build a chassis (in progress - out of chipboard and softwood) and add fittings to secure it all together properly without danger of it collapsing. In the mean time here are the parts stacked on top of each other for a photo opportunity....&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://3.bp.blogspot.com/_rn0sSfRNtpI/TJUQXg6dWlI/AAAAAAAAByc/IdgBiQgBg88/s1600/P9181228.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" qx="true" src="http://3.bp.blogspot.com/_rn0sSfRNtpI/TJUQXg6dWlI/AAAAAAAAByc/IdgBiQgBg88/s320/P9181228.jpg" /&gt;&lt;/a&gt;&lt;a href="http://1.bp.blogspot.com/_rn0sSfRNtpI/TJUh6_GS4AI/AAAAAAAABy0/kkI6XFdMke8/s1600/P9181229.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" qx="true" src="http://1.bp.blogspot.com/_rn0sSfRNtpI/TJUh6_GS4AI/AAAAAAAABy0/kkI6XFdMke8/s320/P9181229.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;And so onto the electrics... I threw caution to the wind and got some Cornell Dubilier 942C20P15K-F capacitors, which a bit of online research seemed to indicate were THE choice for a good coil, even though they are not cheap, especially when factoring postage from US to UK. My capacitor bank has 28 of these 0.15uF, 2000V capacitors arranged in two parallel strings of 14. I mounted them on clear acrylic and wired them up with 1M bleeder resistors using high current wire taken from a set of car jump leads. &lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://2.bp.blogspot.com/_rn0sSfRNtpI/TJUQSZFtGmI/AAAAAAAAByE/OP3i4BlUO6I/s1600/P9181215.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" qx="true" src="http://2.bp.blogspot.com/_rn0sSfRNtpI/TJUQSZFtGmI/AAAAAAAAByE/OP3i4BlUO6I/s320/P9181215.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;I just made my spark gap this weekend... I initially intended making a cylindrical "Richard Quick" type design but I preferred the idea I saw on a web site (which I would credit if I could find it again) where the multiple copper tubes are laid out side by side on the top of a box, and air is drawn through them by fans mounted on the ends of the box. Airflow keeps the gaps cool, but also sucks away ionised air from the gaps and quenches the sparks more quickly, which (so I read) results in better operation of the coil.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;I made the spark gap box from acrylic sheets with an 85mm 240VAC fans (from Maplin) mounted at each end. 10 copper tubes of 15mm diameter and 90mm length form the gap. Two&amp;nbsp;layers of kapton tape at each end of each copper tube provide spacing of ~0.4mm between tubes when they are laid side by side. Connection is made (at the moment) by a plug of compressed aluminium foil around which is wound the connection wire (car jump lead) inside the two "terminal" tubes. I am not sure how well this arrangment is going to work... we shall see.. The tubes are not permanently attached to the box, so my idea is that the number of tubes included in the gap can be varied by moving one of the tubes to which the wire is attached (the other being fixed at one side) by simply removing and shuffling the tubes.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://3.bp.blogspot.com/_rn0sSfRNtpI/TJUQRL1_tdI/AAAAAAAABx8/H0GbWpm4h0c/s1600/P9181212.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" qx="true" src="http://3.bp.blogspot.com/_rn0sSfRNtpI/TJUQRL1_tdI/AAAAAAAABx8/H0GbWpm4h0c/s320/P9181212.jpg" /&gt;&lt;/a&gt;&lt;a href="http://3.bp.blogspot.com/_rn0sSfRNtpI/TJUauvJdaYI/AAAAAAAABys/ZlArhUSU1gg/s1600/P9181211.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" qx="true" src="http://3.bp.blogspot.com/_rn0sSfRNtpI/TJUauvJdaYI/AAAAAAAABys/ZlArhUSU1gg/s320/P9181211.gif" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;I still need to complete build of the Terry Filter circuit (which I hope will protect the neon transformer from voltage surges) as well as the structural bits and pieces, however I hope I can get this thing up and running before too much longer. Watch this space for the results....&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&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/8909459762367220480-3949601235875980244?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/3949601235875980244/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2010/09/tesla-coil-diary-part-1.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/3949601235875980244'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/3949601235875980244'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2010/09/tesla-coil-diary-part-1.html' title='Tesla Coil Diary - Part 1'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_rn0sSfRNtpI/TJUQY2RrcvI/AAAAAAAAByk/aPjFfIDor5Q/s72-c/P9181230.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-2875499208451469625</id><published>2010-06-30T13:43:00.000-07:00</published><updated>2010-07-18T07:34:44.437-07:00</updated><title type='text'>DIY Boss PC-2 / Amdek PCK100 Analog Percussion Synth</title><content type='html'>Back at the end of the 80's I went in a music shop in London and on impulse I bought this wierd BOSS box that made weird bloopy noises... a PC-2 Percussion Synthesizer. It wasn't a difficult decision at the time since it only&amp;nbsp;cost me £10 brand new boxed (I think they were trying to get rid of them) and it came with a free brand new BOSS HC-2 Hand Clapper pedal, although that seemed even less useful (though the guy did a good sales pitch involving a tale about a&amp;nbsp;friend with no arms who had trouble applauding at gigs... :o)&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_rn0sSfRNtpI/TCuq3ypaZNI/AAAAAAAABOk/NsjC7eRkZUg/s1600/022a_1%5B1%5D.JPG" imageanchor="1" style="cssfloat: left; margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" ru="true" src="http://3.bp.blogspot.com/_rn0sSfRNtpI/TCuq3ypaZNI/AAAAAAAABOk/NsjC7eRkZUg/s200/022a_1%5B1%5D.JPG" width="162" /&gt;&lt;/a&gt;&lt;a href="http://4.bp.blogspot.com/_rn0sSfRNtpI/TCutCrwANOI/AAAAAAAABO8/8_sRJDIyG6A/s1600/8.JPG" imageanchor="1" style="cssfloat: right; margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" ru="true" src="http://4.bp.blogspot.com/_rn0sSfRNtpI/TCutCrwANOI/AAAAAAAABO8/8_sRJDIyG6A/s200/8.JPG" width="181" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Apart from a bit of novelty value I gotta be honest they didn't get a lot of use... I think the HC-2 got chucked during a house cleanout and the PC-2 was sold on ebay a few years back (and was amazed to get £100 for it). Well now I am kicking myself and wished I'd held on to these two collectables. &lt;br /&gt;&lt;br /&gt;So when I saw the schematic of the Amdek PCK100 online (actually a kit form of the PC-2 sold by a Roland affiliate) I decided to try to make one and once again re-live boingy noise heaven.&lt;br /&gt;&lt;object width="480" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/MZTptROKFOI&amp;hl=en_US&amp;fs=1&amp;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/MZTptROKFOI&amp;hl=en_US&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;On the&amp;nbsp;page &lt;a href="http://www.effectsdatabase.com/model/amdek/pck100"&gt;http://www.effectsdatabase.com/model/amdek/pck100&lt;/a&gt; where I found the schematic I also found a photo of the PCB and decided to try to use it directly. With some manipulation in Paint Shop Pro and the use of Press'n'Peel PCB etching film I was able to make a copy of the board and after working out some workarounds (e.g. using BA6110 instead of ultra-rare BA662A VCA chip) I actually got it to work.. So in case you're interested ..here is how I did it&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;1) I started off with this photo of the track side of the original PCB&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_rn0sSfRNtpI/TCuql00q0fI/AAAAAAAABNM/ngLvzejSWBQ/s1600/1.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" ru="true" src="http://3.bp.blogspot.com/_rn0sSfRNtpI/TCuql00q0fI/AAAAAAAABNM/ngLvzejSWBQ/s320/1.gif" /&gt;&lt;/a&gt;&lt;/div&gt;2) Turned to mono, upped the contrast, then very carefully use the "eraser" tool to ensure there are good clean gaps between all the tracks &lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_rn0sSfRNtpI/TCuqnCsPR1I/AAAAAAAABNU/YzR3-xzyKUo/s1600/2.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" ru="true" src="http://1.bp.blogspot.com/_rn0sSfRNtpI/TCuqnCsPR1I/AAAAAAAABNU/YzR3-xzyKUo/s320/2.gif" /&gt;&lt;/a&gt;&lt;/div&gt;3) Marked drill holes with circles&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_rn0sSfRNtpI/TCuqoLSRDKI/AAAAAAAABNc/OwiUI5iBH-g/s1600/3.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" ru="true" src="http://3.bp.blogspot.com/_rn0sSfRNtpI/TCuqoLSRDKI/AAAAAAAABNc/OwiUI5iBH-g/s320/3.gif" /&gt;&lt;/a&gt;&lt;/div&gt;4) Drop colour depth to 2 colours&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_rn0sSfRNtpI/TCuqoY7doDI/AAAAAAAABNk/rjfF05jnEQQ/s1600/4.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" ru="true" src="http://4.bp.blogspot.com/_rn0sSfRNtpI/TCuqoY7doDI/AAAAAAAABNk/rjfF05jnEQQ/s320/4.gif" /&gt;&lt;/a&gt;&lt;/div&gt;5) Negative image and a few embellishments and its ready to press'n'peel&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_rn0sSfRNtpI/TCuqpKTSgOI/AAAAAAAABNs/RsoAUBRHjrA/s1600/5.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" ru="true" src="http://4.bp.blogspot.com/_rn0sSfRNtpI/TCuqpKTSgOI/AAAAAAAABNs/RsoAUBRHjrA/s320/5.gif" /&gt;&lt;/a&gt;&lt;/div&gt;6) Laser printed etch-resist transferred to copper clad board using a hot iron&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_rn0sSfRNtpI/TCuqysFcTTI/AAAAAAAABN0/y-c50I9masQ/s1600/6.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" ru="true" src="http://4.bp.blogspot.com/_rn0sSfRNtpI/TCuqysFcTTI/AAAAAAAABN0/y-c50I9masQ/s320/6.gif" /&gt;&lt;/a&gt;&lt;/div&gt;7) Etched, drilled and trimmed ready for components&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_rn0sSfRNtpI/TCuq5EZzmVI/AAAAAAAABOs/t_zISRL_TB0/s1600/pp.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" ru="true" src="http://1.bp.blogspot.com/_rn0sSfRNtpI/TCuq5EZzmVI/AAAAAAAABOs/t_zISRL_TB0/s320/pp.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;I mounted the board inside a project box from Maplin. By the way I have a thing for Dymo embossed label&amp;nbsp;tape :)&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_rn0sSfRNtpI/TCuq25sSSKI/AAAAAAAABOU/1zEHK4n95k4/s1600/9.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" ru="true" src="http://3.bp.blogspot.com/_rn0sSfRNtpI/TCuq25sSSKI/AAAAAAAABOU/1zEHK4n95k4/s320/9.JPG" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_rn0sSfRNtpI/TCuq1-pFCUI/AAAAAAAABOM/4j3rF2ChAag/s1600/8.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" ru="true" src="http://2.bp.blogspot.com/_rn0sSfRNtpI/TCuq1-pFCUI/AAAAAAAABOM/4j3rF2ChAag/s320/8.JPG" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_rn0sSfRNtpI/TCuq1Pi4tYI/AAAAAAAABOE/K5BdYloBu8U/s1600/7.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" ru="true" src="http://2.bp.blogspot.com/_rn0sSfRNtpI/TCuq1Pi4tYI/AAAAAAAABOE/K5BdYloBu8U/s320/7.JPG" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;The Amdek user guide gives info on some mods to the board (VCO wave form change, mod waveform change) which I added toggle switches for. Usually the Sweep control is a center tap pot.. I didn't have one so I instead rigged up a DPDT toggle and a resistor to a normal pot so that the same effect could be acheived (although I am not sure it works so well)&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;The original board calls for a Roland BA662A VCA chip... you won't find one! you can use a similar BA6110 chip but the pinout is different. I found the following worked&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;socket 1 connect to BA6110 pin# 4&lt;/li&gt;&lt;li&gt;socket 2 connect to BA6110 pin# 2&lt;/li&gt;&lt;li&gt;socket 3 connect to BA6110 pin# 1&lt;/li&gt;&lt;li&gt;socket 4 no connection. BA6110 pin#3 connected to GND (pin 5)&lt;/li&gt;&lt;li&gt;socket 5 connect to BA6110 pin#5&lt;/li&gt;&lt;li&gt;socket 6 connect to BA6110 pin#6&lt;/li&gt;&lt;li&gt;socket 7 connect to BA6110 pin#7&lt;/li&gt;&lt;li&gt;socket 8 connect to BA6110 pin#8&lt;/li&gt;&lt;li&gt;socket 9 connect to BA6110 pin#9&lt;/li&gt;&lt;/ul&gt;Click below to get the full size PCB template to use directly. See the link at start of article for schematic, photo of top of the board and original PCK100 kit instructions&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_rn0sSfRNtpI/TCuvHKPnI2I/AAAAAAAABPE/UQrGMQFsFss/s1600/final.gif" imageanchor="1" style="clear: left; cssfloat: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="153" ru="true" src="http://1.bp.blogspot.com/_rn0sSfRNtpI/TCuvHKPnI2I/AAAAAAAABPE/UQrGMQFsFss/s200/final.gif" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-2875499208451469625?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/2875499208451469625/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2010/06/diy-boss-pc-2-amdek-pck100-analog.html#comment-form' title='18 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/2875499208451469625'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/2875499208451469625'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2010/06/diy-boss-pc-2-amdek-pck100-analog.html' title='DIY Boss PC-2 / Amdek PCK100 Analog Percussion Synth'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_rn0sSfRNtpI/TCuq3ypaZNI/AAAAAAAABOk/NsjC7eRkZUg/s72-c/022a_1%5B1%5D.JPG' height='72' width='72'/><thr:total>18</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-944645025055730217</id><published>2010-05-11T15:30:00.000-07:00</published><updated>2010-05-12T00:23:00.447-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pic'/><category scheme='http://www.blogger.com/atom/ns#' term='lasers'/><title type='text'>Battlezone with lasers</title><content type='html'>This is a project I've had simmering on the back burner for a while. Still at the early stages but thought it might be fun to keep track of each step here &lt;br /&gt;&lt;br /&gt;A few months back I got a 20kps laser scanner galvo set off ebay with the intention of making my own laser projector and a vision of using it to play some old vector arcade games... particularly my old fave Atari Battlezone. The arcade game bit seemed pretty easy, since you can play BZ on the open source MAME emulator so I thought I could hook into the vector terminal emulation.&lt;br /&gt;&lt;br /&gt;I found the asynchronous UART on an Arduino board was not quite fast enough to cope with the data... dropping bits all over the place, so I&amp;nbsp;started looking at a USB conneciton to a PIC2455. As a SourceBoost C user I was not able to find any&amp;nbsp;easy to understand USB CDC (Communication Device Class,&amp;nbsp;a.k.a serial port)&amp;nbsp;implementations for the PIC&amp;nbsp;- so I decided to make my own, leaning heavily on sample code I found online.&lt;br /&gt;&lt;br /&gt;Well I finally got to the point where my PIC would connect via USB show up as a COM port and be easy to access from a Windows program. Then I hooked up an 12-bit SPI dual DAC and connected it to the galvo setup and tried the first random hacking into MAMEs vector module.&lt;br /&gt;&lt;br /&gt;I didn't expect it to work first time, and didn't! but my impatient hacking did produce some interesting squiggles at about 2 fps. I needed to use a long exposure photograph to actually make sense of it, but eventually I recognised a couple of parts of the display and got quite excited that the concept was proved!&lt;br /&gt;&lt;br /&gt;The coordinate handling is obviously messed up and the image is wrapping on itself multiple times, also there is no attempt at blanking yet - so there are stray lines all over. The big job will be to find some way to optimise the render list to stop throwing the galvos all over the place and improve on the 2 fps refresh!&lt;br /&gt;&lt;br /&gt;As you can see I have a long way to go!&lt;br /&gt;&lt;br /&gt;Here is the plot showing the bits I recognised&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_rn0sSfRNtpI/S-nat6PQ1hI/AAAAAAAABMs/t6JbyxiCsxc/s1600/bz2.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_rn0sSfRNtpI/S-nat6PQ1hI/AAAAAAAABMs/t6JbyxiCsxc/s320/bz2.gif" tt="true" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Here is an actual MAME screen showing what it should look like&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div align="center" class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://2.bp.blogspot.com/_rn0sSfRNtpI/S-nap4Qv35I/AAAAAAAABMk/X6RiEfQWhV8/s1600/bz.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_rn0sSfRNtpI/S-nap4Qv35I/AAAAAAAABMk/X6RiEfQWhV8/s320/bz.gif" tt="true" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div align="center" class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div align="center" class="separator" style="clear: both; text-align: left;"&gt;If things improve I will post an update!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-944645025055730217?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/944645025055730217/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2010/05/battlezone-with-lasers.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/944645025055730217'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/944645025055730217'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2010/05/battlezone-with-lasers.html' title='Battlezone with lasers'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_rn0sSfRNtpI/S-nat6PQ1hI/AAAAAAAABMs/t6JbyxiCsxc/s72-c/bz2.gif' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-7037459326301655925</id><published>2010-05-03T06:31:00.000-07:00</published><updated>2010-05-03T06:42:57.870-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='puredata'/><title type='text'>Webcam motion detection to midi with puredata</title><content type='html'>another experiment with puredata, webcam image is passed through pix_movement object and a pix_blob turns the result into two midi note streams which are sent into reason via midi yoke. the image is the output of the pix_movement (difference between frames) &lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/uE-ZMmt8zYs&amp;hl=en_US&amp;fs=1&amp;rel=0"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/uE-ZMmt8zYs&amp;hl=en_US&amp;fs=1&amp;rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;I put the pd patch at http://sites.google.com/site/skriyl/Home/pd-projects (motion noise.pd)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_rn0sSfRNtpI/S97Q9YpU-zI/AAAAAAAABMc/GJm2zmA8s7Y/s1600/motion+noise.gif"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 306px; height: 400px;" src="http://2.bp.blogspot.com/_rn0sSfRNtpI/S97Q9YpU-zI/AAAAAAAABMc/GJm2zmA8s7Y/s400/motion+noise.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5467036750680750898" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The patch outputs on midi channels 1 and 2. I used midi yoke and PD's midi output, then piped this into propellerheads reason, where you can use the "advanced midi" to set up midi bus A then lock down channels 1 and 2 to specific instruments in the rack. I used an NNXT with glockenspiel patch and nn19 with strings patch&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-7037459326301655925?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/7037459326301655925/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2010/05/webcam-motion-detection-to-midi-with.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/7037459326301655925'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/7037459326301655925'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2010/05/webcam-motion-detection-to-midi-with.html' title='Webcam motion detection to midi with puredata'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_rn0sSfRNtpI/S97Q9YpU-zI/AAAAAAAABMc/GJm2zmA8s7Y/s72-c/motion+noise.gif' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-4325674778095299838</id><published>2010-05-02T03:37:00.000-07:00</published><updated>2010-05-02T03:49:26.935-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='puredata'/><title type='text'>First play with PureData</title><content type='html'>I was thinking about making a midi "harp" and thought of trying with a webcam, using puredata to analyse the images and generate midi/sounds. This is the first time I have played with PD and I don't really know what I am doing with it yet... you'll see I am not quite there with the midi harp yet, but I am impressed with how quickly you can get something fun working in PD&lt;br /&gt;&lt;br /&gt;&lt;object width="480" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/SSHHI7ztPbQ&amp;hl=en_US&amp;fs=1&amp;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/SSHHI7ztPbQ&amp;hl=en_US&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Here is the PD sketch, which I got to by hacking about with one of the GEM tutorial sketches&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_rn0sSfRNtpI/S91WeGvYgfI/AAAAAAAABMU/RCr6Y-lGSwM/s1600/webcamnoise.gif"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 268px; height: 400px;" src="http://4.bp.blogspot.com/_rn0sSfRNtpI/S91WeGvYgfI/AAAAAAAABMU/RCr6Y-lGSwM/s400/webcamnoise.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5466620597903065586" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-4325674778095299838?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/4325674778095299838/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2010/05/first-play-with-puredata.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/4325674778095299838'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/4325674778095299838'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2010/05/first-play-with-puredata.html' title='First play with PureData'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_rn0sSfRNtpI/S91WeGvYgfI/AAAAAAAABMU/RCr6Y-lGSwM/s72-c/webcamnoise.gif' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-6396044202944033257</id><published>2010-04-22T08:35:00.000-07:00</published><updated>2010-05-02T03:48:08.525-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='reason'/><title type='text'>Matrix feedback in Reason</title><content type='html'>&lt;p&gt;How to do something like this...&lt;/p&gt;&lt;p&gt;&lt;object height="364" width="445"&gt;&lt;param name="movie" value="http://www.youtube.com/v/VV3RLuQZjrI&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x2b405b&amp;amp;color2=0x6b8ab6&amp;amp;border=1"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/VV3RLuQZjrI" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="445" height="364"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;A great thing about Reason is that it allows you to wire a continuous input (like a CV, MIDI CC#, Mod wheel etc) to pattern changes on something like the Matrix sequencer or Redrum. You can't do this directly (there is no pattern change CV input) but you can do it via the "programmer" in the combinator. This is a great thing to experiment with...especially if the patterns are different beat lengths/step values and you layer a few of them . In one of my other clips I used MIDI CC# signals generated by a Lavalamp to randomly switch patterns on a set of Redrum modules. &lt;/p&gt;&lt;p&gt;In the above above clip I have 3 matrix sequences driving each other, which can result in some random sounding patterns which repeat over long periods and can descend into chaos with one small tweak.. eventually arriving at a new repeating cycle (of course you need to drive one or more sound modules like NNXT etc with the matrix outputs to be able to hear anything...)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Start by making a Combinator...&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_rn0sSfRNtpI/S9Bt6dIJy5I/AAAAAAAABLc/Xf5ujQ_Zyhc/s1600/Image1.gif"&gt;&lt;img id="BLOGGER_PHOTO_ID_5462987199019076498" style="WIDTH: 320px; CURSOR: hand; HEIGHT: 166px" alt="" src="http://1.bp.blogspot.com/_rn0sSfRNtpI/S9Bt6dIJy5I/AAAAAAAABLc/Xf5ujQ_Zyhc/s320/Image1.gif" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;Inside the combinator, create 3 matrix sequencers.&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_rn0sSfRNtpI/S9Bt60fA5_I/AAAAAAAABLk/t7owc5U_gmw/s1600/Image2.gif"&gt;&lt;img id="BLOGGER_PHOTO_ID_5462987205288978418" style="WIDTH: 320px; CURSOR: hand; HEIGHT: 214px" alt="" src="http://2.bp.blogspot.com/_rn0sSfRNtpI/S9Bt60fA5_I/AAAAAAAABLk/t7owc5U_gmw/s320/Image2.gif" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;Wire Curve CV output from each Matrix Rotary inputs 1,2,3 on the combinator. Ensure these are only connections between matrixes (-ices?) and combinator&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_rn0sSfRNtpI/S9Bt7pb-rBI/AAAAAAAABLs/njAa_oemNG0/s1600/Image3.gif"&gt;&lt;img id="BLOGGER_PHOTO_ID_5462987219503328274" style="WIDTH: 262px; CURSOR: hand; HEIGHT: 320px" alt="" src="http://3.bp.blogspot.com/_rn0sSfRNtpI/S9Bt7pb-rBI/AAAAAAAABLs/njAa_oemNG0/s320/Image3.gif" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;Click the "show programmer" button. Click on Matrix 1 and next to "Rotary 2" source select "Pattern Select" target. For Matrix 2 map Rotary 3 to pattern select, For Matrix 3 map Rotary 1 to pattern select&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_rn0sSfRNtpI/S9Bt7zLh07I/AAAAAAAABL0/I451F-z8Rr0/s1600/Image4.gif"&gt;&lt;img id="BLOGGER_PHOTO_ID_5462987222118683570" style="WIDTH: 320px; CURSOR: hand; HEIGHT: 125px" alt="" src="http://3.bp.blogspot.com/_rn0sSfRNtpI/S9Bt7zLh07I/AAAAAAAABL0/I451F-z8Rr0/s320/Image4.gif" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;Flip to Curve view on each matrix and draw a few random curves (Randomize pattern option can be good). Start the Matrixes and click randomly on their pattern screens. Soon they should be flicking between patterns almost at random&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_rn0sSfRNtpI/S9Bt8MGelcI/AAAAAAAABL8/i2ZS8wadrsI/s1600/Image5.gif"&gt;&lt;img id="BLOGGER_PHOTO_ID_5462987228808385986" style="WIDTH: 320px; CURSOR: hand; HEIGHT: 178px" alt="" src="http://1.bp.blogspot.com/_rn0sSfRNtpI/S9Bt8MGelcI/AAAAAAAABL8/i2ZS8wadrsI/s320/Image5.gif" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;Wire the Gate and Note CV outputs of one or more matrix to a sound module such as NNXT. &lt;a href="http://3.bp.blogspot.com/_rn0sSfRNtpI/S9BuFwVhVUI/AAAAAAAABMM/E-qe4nWZbRI/s1600/Image7.gif"&gt;&lt;img id="BLOGGER_PHOTO_ID_5462987393153979714" style="WIDTH: 274px; CURSOR: hand; HEIGHT: 320px" alt="" src="http://3.bp.blogspot.com/_rn0sSfRNtpI/S9BuFwVhVUI/AAAAAAAABMM/E-qe4nWZbRI/s320/Image7.gif" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt;Flip the matrixes to note mode and click at random on the screens. Change pattern lengths and note resolutions, try the "randomize pattern" option. After a while things should be getting pretty freaked out&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_rn0sSfRNtpI/S9BuD6i27GI/AAAAAAAABME/X3rmrS8YPNU/s1600/Image6.gif"&gt;&lt;img id="BLOGGER_PHOTO_ID_5462987361534536802" style="WIDTH: 320px; CURSOR: hand; HEIGHT: 237px" alt="" src="http://4.bp.blogspot.com/_rn0sSfRNtpI/S9BuD6i27GI/AAAAAAAABME/X3rmrS8YPNU/s320/Image6.gif" border="0" /&gt;&lt;/a&gt;&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/8909459762367220480-6396044202944033257?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/6396044202944033257/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2010/04/matrix-feedback-in-reason.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/6396044202944033257'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/6396044202944033257'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2010/04/matrix-feedback-in-reason.html' title='Matrix feedback in Reason'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_rn0sSfRNtpI/S9Bt6dIJy5I/AAAAAAAABLc/Xf5ujQ_Zyhc/s72-c/Image1.gif' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-768651197183069395</id><published>2010-03-23T14:48:00.000-07:00</published><updated>2010-05-12T00:23:15.389-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pic'/><category scheme='http://www.blogger.com/atom/ns#' term='midi'/><title type='text'>Pre programmed PICs</title><content type='html'>Following some requests, I have listed pre-programmed PICs on ebay for a couple of my projects. If there is much interest (and its not all a massive hassle) I might also look into getting some PCBs made up and putting kits together&lt;br /&gt;For now here are the PICs &lt;a href="http://cgi.ebay.co.uk/ws/eBayISAPI.dll?ViewItem&amp;amp;item=150426687494"&gt;http://cgi.ebay.co.uk/ws/eBayISAPI.dll?ViewItem&amp;amp;item=150426687494&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-768651197183069395?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/768651197183069395/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2010/03/pre-programmed-pics.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/768651197183069395'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/768651197183069395'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2010/03/pre-programmed-pics.html' title='Pre programmed PICs'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-2379719592284519409</id><published>2010-03-23T13:41:00.000-07:00</published><updated>2010-05-12T00:22:47.603-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pic'/><category scheme='http://www.blogger.com/atom/ns#' term='midi'/><category scheme='http://www.blogger.com/atom/ns#' term='pokey'/><title type='text'>POKEY sound chip experiments</title><content type='html'>The Atari POKEY was the classic soundchip in the Atari 8-bit home computers and many 1980's arcade games. This clip shows some of my experiments in driving a POKEY from MIDI. A PIC receives MIDI data and two 74HC595 shift registers are used to assemble the 12 lines of bus data for the POKEY so it can be driven from a humble 14 pin PIC16F688. A 6N139 isolator is placed between MIDI in from PC and the PIC's serial input. The POKEY is clocked at 2MHz from the PIC's internal clock output.&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/PCysUWx4rCI&amp;hl=en_US&amp;fs=1&amp;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/PCysUWx4rCI&amp;hl=en_US&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;I am using REAPER to sequence some MIDI files I found on the internet. Credit goes out to the authors of these MIDI files.. also to YouTube member little-scale, whose clips inspired me to poke about with the POKEY in the first place, and Bryan Edewaard, whose crib sheet I could not have done this without.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Here is the schematic for the circuit as built on breadboard (I am working on neater, stripboard based version)&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_rn0sSfRNtpI/S6kn0RIzhUI/AAAAAAAABLU/9LuaSsMqcQo/s1600-h/picpokey.png"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5451932602815710530" src="http://4.bp.blogspot.com/_rn0sSfRNtpI/S6kn0RIzhUI/AAAAAAAABLU/9LuaSsMqcQo/s320/picpokey.png" style="cursor: hand; height: 256px; width: 320px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;And the source code for SOURCEBOOST C on the PIC16F688&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;#include &amp;lt;system.h&amp;gt;&lt;br /&gt;&lt;br /&gt;#include &amp;lt;memory.h&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// PIC CONFIG (_INTRC_OSC_CLKOUT is needed so we output clock&lt;br /&gt;&lt;br /&gt;// clock signal on pin 3)&lt;br /&gt;&lt;br /&gt;#pragma DATA _CONFIG, _MCLRE_OFF &amp;amp; _WDT_OFF &amp;amp; _INTRC_OSC_CLKOUT&lt;br /&gt;&lt;br /&gt;#pragma CLOCK_FREQ 8000000&lt;br /&gt;&lt;br /&gt;typedef unsigned char byte;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// define the pins&lt;br /&gt;&lt;br /&gt;#define P_DATA portc.0 &lt;br /&gt;&lt;br /&gt;#define P_SHCK portc.2 &lt;br /&gt;&lt;br /&gt;#define P_STCK portc.1 &lt;br /&gt;&lt;br /&gt;#define P_POKEY portc.3&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// define "pure" tone sound mode. Other settings&lt;br /&gt;&lt;br /&gt;// of bits 4-7 will add varying levels of distortion&lt;br /&gt;&lt;br /&gt;#define POKEY_SOUNDMODE 0b10100000&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// MIDI defs&lt;br /&gt;&lt;br /&gt;#define MIDIMSG(b) ((b)&amp;gt;&amp;gt;4)&lt;br /&gt;&lt;br /&gt;#define MIDICHAN(b) ((b)&amp;amp;0xf) &lt;br /&gt;&lt;br /&gt;#define MIDIMSG_NOTEON 0x09&lt;br /&gt;&lt;br /&gt;#define MIDIMSG_NOTEOFF 0x08&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// structure for managing channel info&lt;br /&gt;&lt;br /&gt;typedef struct &lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;byte midiNote; // triggered MIDI note&lt;br /&gt;&lt;br /&gt;byte note; // POKEY divider value&lt;br /&gt;&lt;br /&gt;byte volume; // volume (bits 0-3)&lt;br /&gt;&lt;br /&gt;byte count; // playing duration counter&lt;br /&gt;&lt;br /&gt;} CHANNEL;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// Buffer to hold state of 4 POKEY voice channels&lt;br /&gt;&lt;br /&gt;CHANNEL chan[4] = {0};&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// MIDI message registers&lt;br /&gt;&lt;br /&gt;byte runningStatus = 0;&lt;br /&gt;&lt;br /&gt;byte midiParams[2] = {0};&lt;br /&gt;&lt;br /&gt;byte numParams = 0;&lt;br /&gt;&lt;br /&gt;byte thisParam = 0;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// Divider values for POKEY channels&lt;br /&gt;&lt;br /&gt;byte notes[48] = {&lt;br /&gt;&lt;br /&gt;250, // C#2&lt;br /&gt;&lt;br /&gt;236, // D2&lt;br /&gt;&lt;br /&gt;222, // D#2&lt;br /&gt;&lt;br /&gt;210, // E2&lt;br /&gt;&lt;br /&gt;198, // F2&lt;br /&gt;&lt;br /&gt;187, // F#2&lt;br /&gt;&lt;br /&gt;177, // G2&lt;br /&gt;&lt;br /&gt;167, // G#2&lt;br /&gt;&lt;br /&gt;157, // A2&lt;br /&gt;&lt;br /&gt;148, // A#2&lt;br /&gt;&lt;br /&gt;140, // B2&lt;br /&gt;&lt;br /&gt;132, // C3&lt;br /&gt;&lt;br /&gt;125, // C#3&lt;br /&gt;&lt;br /&gt;118, // D3&lt;br /&gt;&lt;br /&gt;111, // D#3&lt;br /&gt;&lt;br /&gt;105, // E3&lt;br /&gt;&lt;br /&gt;99, // F3&lt;br /&gt;&lt;br /&gt;94, // F#3&lt;br /&gt;&lt;br /&gt;88, // G3&lt;br /&gt;&lt;br /&gt;83, // G#3&lt;br /&gt;&lt;br /&gt;79, // A3&lt;br /&gt;&lt;br /&gt;74, // A#3&lt;br /&gt;&lt;br /&gt;70, // B3&lt;br /&gt;&lt;br /&gt;66, // C4&lt;br /&gt;&lt;br /&gt;62, // C#4&lt;br /&gt;&lt;br /&gt;59, // D4&lt;br /&gt;&lt;br /&gt;56, // D#4&lt;br /&gt;&lt;br /&gt;52, // E4&lt;br /&gt;&lt;br /&gt;50, // F4&lt;br /&gt;&lt;br /&gt;47, // F#4&lt;br /&gt;&lt;br /&gt;44, // G4&lt;br /&gt;&lt;br /&gt;42, // G#4&lt;br /&gt;&lt;br /&gt;39, // A4&lt;br /&gt;&lt;br /&gt;37, // A#4&lt;br /&gt;&lt;br /&gt;35, // B4&lt;br /&gt;&lt;br /&gt;33, // C5&lt;br /&gt;&lt;br /&gt;31, // C#5&lt;br /&gt;&lt;br /&gt;29, // D5&lt;br /&gt;&lt;br /&gt;28, // D#5&lt;br /&gt;&lt;br /&gt;26, // E5&lt;br /&gt;&lt;br /&gt;25, // F5&lt;br /&gt;&lt;br /&gt;23, // F#5&lt;br /&gt;&lt;br /&gt;22, // G5&lt;br /&gt;&lt;br /&gt;21, // G#5&lt;br /&gt;&lt;br /&gt;20, // A5&lt;br /&gt;&lt;br /&gt;19, // A#5&lt;br /&gt;&lt;br /&gt;18, // B5&lt;br /&gt;&lt;br /&gt;17 // C6&lt;br /&gt;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;// INITIALISE SERIAL PORT FOR MIDI&lt;br /&gt;&lt;br /&gt;void init_usart()&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;pir1.1 = 1; //TXIF &lt;br /&gt;&lt;br /&gt;pir1.5 = 0; //RCIF&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;pie1.1 = 0; //TXIE no interrupts&lt;br /&gt;&lt;br /&gt;pie1.5 = 0; //RCIE no interrupts&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;baudctl.4 = 0; // SCKP synchronous bit polarity &lt;br /&gt;&lt;br /&gt;baudctl.3 = 1; // BRG16 enable 16 bit brg&lt;br /&gt;&lt;br /&gt;baudctl.1 = 0; // WUE wake up enable off&lt;br /&gt;&lt;br /&gt;baudctl.0 = 0; // ABDEN auto baud detect&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;txsta.6 = 0; // TX9 8 bit transmission&lt;br /&gt;&lt;br /&gt;txsta.5 = 1; // TXEN transmit enable&lt;br /&gt;&lt;br /&gt;txsta.4 = 0; // SYNC async mode&lt;br /&gt;&lt;br /&gt;txsta.3 = 0; // SEDNB break character&lt;br /&gt;&lt;br /&gt;txsta.2 = 0; // BRGH high baudrate &lt;br /&gt;&lt;br /&gt;txsta.0 = 0; // TX9D bit 9&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;rcsta.7 = 1; // SPEN serial port enable&lt;br /&gt;&lt;br /&gt;rcsta.6 = 0; // RX9 8 bit operation&lt;br /&gt;&lt;br /&gt;rcsta.5 = 1; // SREN enable receiver&lt;br /&gt;&lt;br /&gt;rcsta.4 = 1; // CREN continuous receive enable&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;spbrgh = 0; // brg high byte&lt;br /&gt;&lt;br /&gt;spbrg = 15; // brg low byte (31250) &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;// RECEIVE MIDI MESSAGE&lt;br /&gt;&lt;br /&gt;// Return the status byte or 0 if nothing complete received&lt;br /&gt;&lt;br /&gt;// caller must check midiParams array for byte 1 and 2&lt;br /&gt;&lt;br /&gt;byte receiveMessage()&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// loop until there is no more data or&lt;br /&gt;&lt;br /&gt;// we receive a full message&lt;br /&gt;&lt;br /&gt;for(;;)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// buffer overrun error?&lt;br /&gt;&lt;br /&gt;if(rcsta.1)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;rcsta.4 = 0;&lt;br /&gt;&lt;br /&gt;rcsta.4 = 1;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// poll for a MIDI byte&lt;br /&gt;&lt;br /&gt;if(!pir1.5)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// no data ready&lt;br /&gt;&lt;br /&gt;return 0;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// read the character&lt;br /&gt;&lt;br /&gt;byte q = rcreg;&lt;br /&gt;&lt;br /&gt;pir1.5 = 0;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// is it a channel msg&lt;br /&gt;&lt;br /&gt;if((q&amp;amp;0x80)&amp;gt;0)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;numParams = 0;&lt;br /&gt;&lt;br /&gt;thisParam = 0; &lt;br /&gt;&lt;br /&gt;switch(q&amp;amp;0xf0)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;case 0x80: // Note-off 2 key velocity &lt;br /&gt;&lt;br /&gt;case 0x90: // Note-on 2 key veolcity &lt;br /&gt;&lt;br /&gt;case 0xA0: // Aftertouch 2 key touch &lt;br /&gt;&lt;br /&gt;case 0xB0: // Continuous controller 2 controller # controller value &lt;br /&gt;&lt;br /&gt;case 0xC0: // Patch change 2 instrument # &lt;br /&gt;&lt;br /&gt;case 0xE0: // Pitch bend 2 lsb (7 bits) msb (7 bits) &lt;br /&gt;&lt;br /&gt;runningStatus = q;&lt;br /&gt;&lt;br /&gt;numParams = 2;&lt;br /&gt;&lt;br /&gt;break;&lt;br /&gt;&lt;br /&gt;case 0xD0: // Channel Pressure 1 pressure &lt;br /&gt;&lt;br /&gt;runningStatus = q;&lt;br /&gt;&lt;br /&gt;numParams = 1;&lt;br /&gt;&lt;br /&gt;break;&lt;br /&gt;&lt;br /&gt;case 0xF0: // (non-musical commands) - ignore all data for now &lt;br /&gt;&lt;br /&gt;runningStatus = 0;&lt;br /&gt;&lt;br /&gt;return q; &lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// else do we have a channel message?&lt;br /&gt;&lt;br /&gt;else if(runningStatus)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// fill in next command parameter&lt;br /&gt;&lt;br /&gt;midiParams[thisParam++] = q;&lt;br /&gt;&lt;br /&gt;if(thisParam&amp;gt;=numParams)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// return the command&lt;br /&gt;&lt;br /&gt;thisParam = 0;&lt;br /&gt;&lt;br /&gt;return runningStatus;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;return 0;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;// DRIVE DATA OUT TO SHIFT REGISTERS&lt;br /&gt;&lt;br /&gt;// m is a bit mask to highest bit in the data&lt;br /&gt;&lt;br /&gt;void dataOut(byte d, byte m)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;while(m)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// shift clock low&lt;br /&gt;&lt;br /&gt;P_SHCK = 0;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// data out&lt;br /&gt;&lt;br /&gt;P_DATA = (d&amp;amp;m)?1:0;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// shift clock high&lt;br /&gt;&lt;br /&gt;P_SHCK = 1;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// shift the mask&lt;br /&gt;&lt;br /&gt;m&amp;gt;&amp;gt;=1;&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;// WRITE ADDRESS AND DATA TO POKEY&lt;br /&gt;&lt;br /&gt;void writePokey(byte address, byte data)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// store clock low&lt;br /&gt;&lt;br /&gt;P_STCK = 0;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// fill the shift regs&lt;br /&gt;&lt;br /&gt;dataOut(address,0x08);&lt;br /&gt;&lt;br /&gt;dataOut(data,0x80);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// store clock high&lt;br /&gt;&lt;br /&gt;P_STCK = 1; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// pulse POKEY chip enable line&lt;br /&gt;&lt;br /&gt;P_POKEY = 0;&lt;br /&gt;&lt;br /&gt;delay_us(100);&lt;br /&gt;&lt;br /&gt;P_POKEY = 1;&lt;br /&gt;&lt;br /&gt;delay_us(100);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;// POKEY RESET SEQUENCE&lt;br /&gt;&lt;br /&gt;void resetPokey()&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// fill all locations with 0&lt;br /&gt;&lt;br /&gt;for(int i=0;i&amp;lt;16;++i)&lt;br /&gt;&lt;br /&gt;writePokey(i, 0);&lt;br /&gt;&lt;br /&gt;// reset sequence&lt;br /&gt;&lt;br /&gt;writePokey(0x0f, 3);&lt;br /&gt;&lt;br /&gt;writePokey(0x09, 1);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;// HANDLE MIDI NOTE TRIGGER (ON OR OFF)&lt;br /&gt;&lt;br /&gt;// MANAGES THE 4 VOICES&lt;br /&gt;&lt;br /&gt;void handleNote(byte midiNote, byte midiVelocity)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;int iAlreadyPlaying = -1;&lt;br /&gt;&lt;br /&gt;int iFree = -1;&lt;br /&gt;&lt;br /&gt;int iSteal = -1;&lt;br /&gt;&lt;br /&gt;int iUpdatePOKEY = -1;&lt;br /&gt;&lt;br /&gt;int iLongestPlay = -1;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// map 7-bit MIDI velocity to 4-bit POKEY volume&lt;br /&gt;&lt;br /&gt;byte volume = midiVelocity &amp;gt;&amp;gt; 3;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// scan through the 4 channels&lt;br /&gt;&lt;br /&gt;for(int i=0;i&amp;lt;4;++i)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// incremement play duration counter for this&lt;br /&gt;&lt;br /&gt;// channel. we use this counter to detect which &lt;br /&gt;&lt;br /&gt;// note has been playing longest if we need to &lt;br /&gt;&lt;br /&gt;// steal a channel&lt;br /&gt;&lt;br /&gt;chan[i].count++; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// check if the note is already playing on channel&lt;br /&gt;&lt;br /&gt;if(chan[i].midiNote == midiNote)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;iAlreadyPlaying = i;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// else is channel spare?&lt;br /&gt;&lt;br /&gt;else if(!chan[i].midiNote)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;iFree = i;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// else is channel the longest playing channel?&lt;br /&gt;&lt;br /&gt;else if(chan[i].count &amp;gt; iLongestPlay)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;iLongestPlay = chan[i].count;&lt;br /&gt;&lt;br /&gt;iSteal = i;&lt;br /&gt;&lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// already got a channel playing this note?&lt;br /&gt;&lt;br /&gt;if(iAlreadyPlaying &amp;gt; 0 )&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// need to stop a note?&lt;br /&gt;&lt;br /&gt;if(!volume)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// turn a note off&lt;br /&gt;&lt;br /&gt;chan[iAlreadyPlaying].midiNote = 0;&lt;br /&gt;&lt;br /&gt;chan[iAlreadyPlaying].note = 0;&lt;br /&gt;&lt;br /&gt;chan[iAlreadyPlaying].volume = 0;&lt;br /&gt;&lt;br /&gt;chan[iAlreadyPlaying].count = 0;&lt;br /&gt;&lt;br /&gt;iUpdatePOKEY = iAlreadyPlaying; &lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// else check we have a nonzero volume. We will ignore&lt;br /&gt;&lt;br /&gt;// zero volume requests against any note that is not already&lt;br /&gt;&lt;br /&gt;// playing&lt;br /&gt;&lt;br /&gt;else if(volume&amp;gt;0)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// convert from MIDI note to index in the notes[] array&lt;br /&gt;&lt;br /&gt;byte note = midiNote;&lt;br /&gt;&lt;br /&gt;while(note&amp;lt;37) note+=12; // 37 is lowest MIDI note we map&lt;br /&gt;&lt;br /&gt;while(note&amp;gt;84) note-=12; // 84 is highest MIDI note we map&lt;br /&gt;&lt;br /&gt;note-=37; // convert to array index value&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// got a free channel?&lt;br /&gt;&lt;br /&gt;if(iFree&amp;gt;0)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// use it&lt;br /&gt;&lt;br /&gt;chan[iFree].midiNote = midiNote;&lt;br /&gt;&lt;br /&gt;chan[iFree].note = notes[note];&lt;br /&gt;&lt;br /&gt;chan[iFree].volume = volume;&lt;br /&gt;&lt;br /&gt;chan[iFree].count = 0;&lt;br /&gt;&lt;br /&gt;iUpdatePOKEY = iFree;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// else steal a channel from another note&lt;br /&gt;&lt;br /&gt;else if(iSteal&amp;gt;0)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;chan[iSteal].midiNote = midiNote;&lt;br /&gt;&lt;br /&gt;chan[iSteal].note = notes[note];&lt;br /&gt;&lt;br /&gt;chan[iSteal].volume = volume;&lt;br /&gt;&lt;br /&gt;chan[iSteal].count = 0;&lt;br /&gt;&lt;br /&gt;iUpdatePOKEY = iSteal;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// do we need to tell the POKEY anything?&lt;br /&gt;&lt;br /&gt;if(iUpdatePOKEY &amp;gt; 0)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// make it so!&lt;br /&gt;&lt;br /&gt;writePokey(0 + iUpdatePOKEY*2, chan[iUpdatePOKEY].note); &lt;br /&gt;&lt;br /&gt;writePokey(1 + iUpdatePOKEY*2, POKEY_SOUNDMODE|chan[iUpdatePOKEY].volume); &lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;void main()&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;// osc control / 8MHz / internal&lt;br /&gt;&lt;br /&gt;osccon = 0b01110001;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// timer0... configure source and prescaler&lt;br /&gt;&lt;br /&gt;cmcon0 = 7; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// configure io&lt;br /&gt;&lt;br /&gt;trisa = 0b00010000; &lt;br /&gt;&lt;br /&gt;trisc = 0b00110000; &lt;br /&gt;&lt;br /&gt;ansel = 0b00000000;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// initialise MIDI comms&lt;br /&gt;&lt;br /&gt;init_usart();&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// reset the POKEY&lt;br /&gt;&lt;br /&gt;resetPokey(); &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// loop forever&lt;br /&gt;&lt;br /&gt;for(;;)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// get next MIDI note&lt;br /&gt;&lt;br /&gt;byte msg = receiveMessage();&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// handle note on/off (transpose down 1 octave)&lt;br /&gt;&lt;br /&gt;if(MIDIMSG_NOTEON == MIDIMSG(msg))&lt;br /&gt;&lt;br /&gt;handleNote(midiParams[0]-12, midiParams[1]);&lt;br /&gt;&lt;br /&gt;else if(MIDIMSG_NOTEOFF == MIDIMSG(msg))&lt;br /&gt;&lt;br /&gt;handleNote(midiParams[0]-12, 0);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-2379719592284519409?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/2379719592284519409/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2010/03/pokey-sound-chip-experiments.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/2379719592284519409'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/2379719592284519409'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2010/03/pokey-sound-chip-experiments.html' title='POKEY sound chip experiments'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_rn0sSfRNtpI/S6kn0RIzhUI/AAAAAAAABLU/9LuaSsMqcQo/s72-c/picpokey.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-1545154320150025191</id><published>2010-03-16T02:32:00.000-07:00</published><updated>2010-05-12T00:21:49.757-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='electronics'/><category scheme='http://www.blogger.com/atom/ns#' term='pic'/><category scheme='http://www.blogger.com/atom/ns#' term='midi'/><title type='text'>Hand-cranked MIDI sequencer from a baked bean can</title><content type='html'>One empty baked bean tin, some lego and a stack of little magnets... stick magnets on the tin and slide them about to 'program' the sequencer, then grab hold of the 'transport control' and crank away.... The breadboard contains 5 hall-effect switches and a PIC16F688 to generate MIDI note on/off information. This is piped to Reason in the first half of the clip and to a Dave Smith Mopho synth in the second half. &lt;br /&gt;I reckon with a baked bean tin about 16ft in diameter and about 25,000 magnets you could dump your sequencer software.. and you'd be getting some good aerobic exercise to boot :o) &lt;br /&gt;&lt;br /&gt;&lt;object height="385" width="480"&gt;&lt;param name="movie" value="http://www.youtube.com/v/47ijWfiIMT8&amp;hl=en_US&amp;fs=1&amp;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/47ijWfiIMT8&amp;hl=en_US&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Here is the schematic (if you make one, note that hall effect switches need the magnet to be the right way round.. if it does not trigger, flip the magnet over)&lt;/b&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_rn0sSfRNtpI/S59Qb1SAY8I/AAAAAAAABKs/9qMX7NzsotE/s1600-h/beantin.png"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5449162513230881730" src="http://1.bp.blogspot.com/_rn0sSfRNtpI/S59Qb1SAY8I/AAAAAAAABKs/9qMX7NzsotE/s320/beantin.png" style="cursor: hand; display: block; height: 158px; margin: 0px auto 10px; text-align: center; width: 320px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;And the code (SourceBoost C... NOTE: you'll need programmer hardware like PICKit2 to burn the program to the PIC chip)&lt;/b&gt;&lt;br /&gt;// HALL SENSOR TO MIDI NOTES&lt;br /&gt;&lt;br /&gt;// J.Hotchkiss Mar2010&lt;br /&gt;&lt;br /&gt;#include &amp;lt;system.h&amp;gt;&lt;br /&gt;&lt;br /&gt;#include &amp;lt;memory.h&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// PIC CONFIG&lt;br /&gt;&lt;br /&gt;#pragma DATA _CONFIG, _MCLRE_OFF&amp;amp;_WDT_OFF&amp;amp;_INTRC_OSC_NOCLKOUT&lt;br /&gt;&lt;br /&gt;#pragma CLOCK_FREQ 8000000&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;#define P_SENSE1 porta.5&lt;br /&gt;&lt;br /&gt;#define P_SENSE2 portc.2&lt;br /&gt;&lt;br /&gt;#define P_SENSE3 portc.1&lt;br /&gt;&lt;br /&gt;#define P_SENSE4 portc.0&lt;br /&gt;&lt;br /&gt;#define P_SENSE5 porta.2&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;typedef unsigned char byte;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// INITIALISE SERIAL PORT FOR MIDI&lt;br /&gt;&lt;br /&gt;void init_usart()&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;pir1.1 = 1; //TXIF transmit enable&lt;br /&gt;&lt;br /&gt;pie1.1 = 0; //TXIE no interrupts&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;baudctl.4 = 0; // synchronous bit polarity &lt;br /&gt;&lt;br /&gt;baudctl.3 = 1; // enable 16 bit brg&lt;br /&gt;&lt;br /&gt;baudctl.1 = 0; // wake up enable off&lt;br /&gt;&lt;br /&gt;baudctl.0 = 0; // disable auto baud detect&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;txsta.6 = 0; // 8 bit transmission&lt;br /&gt;&lt;br /&gt;txsta.5 = 1; // transmit enable&lt;br /&gt;&lt;br /&gt;txsta.4 = 0; // async mode&lt;br /&gt;&lt;br /&gt;txsta.2 = 0; // high baudrate BRGH&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;rcsta.7 = 1; // serial port enable&lt;br /&gt;&lt;br /&gt;rcsta.6 = 0; // 8 bit operation&lt;br /&gt;&lt;br /&gt;rcsta.4 = 0; // enable receiver&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;spbrgh = 0; // brg high byte&lt;br /&gt;&lt;br /&gt;spbrg = 15; // brg low byte (31250) &lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;// SEND A MIDI BYTE&lt;br /&gt;&lt;br /&gt;void send(unsigned char c)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;txreg = c;&lt;br /&gt;&lt;br /&gt;while(!txsta.1);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;// CONTINUOUS CONTROLLER MESSAGE&lt;br /&gt;&lt;br /&gt;void sendController(byte channel, byte controller, byte value)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;send(0xb0 | channel);&lt;br /&gt;&lt;br /&gt;send(controller&amp;amp;0x7f);&lt;br /&gt;&lt;br /&gt;send(value&amp;amp;0x7f);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;// NOTE MESSAGE&lt;br /&gt;&lt;br /&gt;void startNote(byte channel, byte note, byte value)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;send(0x90 | channel);&lt;br /&gt;&lt;br /&gt;send(note&amp;amp;0x7f);&lt;br /&gt;&lt;br /&gt;send(value&amp;amp;0x7f);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;void main()&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;// osc control / 8MHz / internal&lt;br /&gt;&lt;br /&gt;osccon = 0b01110001;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// timer0... configure source and prescaler&lt;br /&gt;&lt;br /&gt;option_reg = 0b10000011;&lt;br /&gt;&lt;br /&gt;cmcon0 = 7; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;porta=0;&lt;br /&gt;&lt;br /&gt;wpua=0;&lt;br /&gt;&lt;br /&gt;portc=0;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// configure io&lt;br /&gt;&lt;br /&gt;trisa = 0b00100100; &lt;br /&gt;&lt;br /&gt;trisc = 0b00001111; &lt;br /&gt;&lt;br /&gt;ansel = 0b00000000;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// initialise MIDI comms&lt;br /&gt;&lt;br /&gt;init_usart();&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// Set up the MIDI notes for each sensor&lt;br /&gt;&lt;br /&gt;byte note[5] = {60,62,64,65,66};&lt;br /&gt;&lt;br /&gt;// byte note[5] = {36,37,38,39,40}; // For Reason REDRUM&lt;br /&gt;&lt;br /&gt;byte sense[5] = {0};&lt;br /&gt;&lt;br /&gt;for(;;)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;if(P_SENSE1 != sense[0])&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;startNote(0, note[0], P_SENSE1? 0:127);&lt;br /&gt;&lt;br /&gt;sense[0] = P_SENSE1;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;if(P_SENSE2 != sense[1])&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;startNote(0, note[1], P_SENSE2? 0:127);&lt;br /&gt;&lt;br /&gt;sense[1] = P_SENSE2;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;if(P_SENSE3 != sense[2])&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;startNote(0, note[2], P_SENSE3? 0:127);&lt;br /&gt;&lt;br /&gt;sense[2] = P_SENSE3;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;if(P_SENSE4 != sense[3])&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;startNote(0, note[3], P_SENSE4? 0:127);&lt;br /&gt;&lt;br /&gt;sense[3] = P_SENSE4;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;if(P_SENSE5 != sense[4])&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;startNote(0, note[4], P_SENSE5? 0:127);&lt;br /&gt;&lt;br /&gt;sense[4] = P_SENSE5;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-1545154320150025191?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/1545154320150025191/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2010/03/hand-cranked-midi-sequencer-from-baked.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/1545154320150025191'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/1545154320150025191'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2010/03/hand-cranked-midi-sequencer-from-baked.html' title='Hand-cranked MIDI sequencer from a baked bean can'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_rn0sSfRNtpI/S59Qb1SAY8I/AAAAAAAABKs/9qMX7NzsotE/s72-c/beantin.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-5872209006912301699</id><published>2010-03-06T04:11:00.000-08:00</published><updated>2010-05-12T00:22:19.643-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='electronics'/><category scheme='http://www.blogger.com/atom/ns#' term='pic'/><category scheme='http://www.blogger.com/atom/ns#' term='midi'/><title type='text'>MIDI Guitar on Stripboard... Kind of</title><content type='html'>Somewhere between the Omnichord and the Stylophone lies this thing... simple but suprisingly effective... a PIC16F688 microcontroller, 2 shift registers IC's, 36 switches and a bunch of wire. The buttons select major/minor/maj7/min7/7/dim/aug chords based on any root note, and you "strum" across 3-4 octaves of notes from the chord by touching bits of exposed wire with a "stylus". The output is all MIDI (circuit makes no sound by itself) and Reason is being used here for sounds. &lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/k0HWD1l-Nm0&amp;hl=en_US&amp;fs=1&amp;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/k0HWD1l-Nm0&amp;hl=en_US&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Note - If you are new to PIC stuff and want to make your own version of this project, remember you will need some way to program the PIC chip (its like a tiny computer and it comes without any software installed). The code is included below, but you'll need to compile it (using the free SourceBoost compiler) and "burn" it to the PIC... you can buy a programmer (e.g. PICkit2) or maybe borrow one. If there is enough demand I might be able to provide pre-programmed PIC16F688's for this, or my other PIC projects. Drop me a message if you'd be interested.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_rn0sSfRNtpI/S5JHOJWTIpI/AAAAAAAABJs/9lLsIwhxCUY/s1600-h/P3068960.JPG"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5445493207797539474" src="http://4.bp.blogspot.com/_rn0sSfRNtpI/S5JHOJWTIpI/AAAAAAAABJs/9lLsIwhxCUY/s320/P3068960.JPG" style="cursor: hand; display: block; height: 245px; margin: 0px auto 10px; text-align: center; width: 320px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Schematic&lt;/b&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_rn0sSfRNtpI/S5JK_cs8GoI/AAAAAAAABKE/-CXU6prKXvE/s1600-h/strum2.png"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5445497353341246082" src="http://2.bp.blogspot.com/_rn0sSfRNtpI/S5JK_cs8GoI/AAAAAAAABKE/-CXU6prKXvE/s320/strum2.png" style="cursor: hand; display: block; height: 227px; margin: 0px auto 10px; text-align: center; width: 320px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The business end...&lt;/b&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_rn0sSfRNtpI/S5JHeeJVgwI/AAAAAAAABJ0/Cdrq3vTSgBE/s1600-h/P3068970.JPG"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5445493488258220802" src="http://3.bp.blogspot.com/_rn0sSfRNtpI/S5JHeeJVgwI/AAAAAAAABJ0/Cdrq3vTSgBE/s320/P3068970.JPG" style="cursor: hand; display: block; height: 233px; margin: 0px auto 10px; text-align: center; width: 320px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The mess on the back...&lt;/b&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_rn0sSfRNtpI/S5JHwsYwDiI/AAAAAAAABJ8/Ohb272F771o/s1600-h/P3068966.JPG"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5445493801318616610" src="http://3.bp.blogspot.com/_rn0sSfRNtpI/S5JHwsYwDiI/AAAAAAAABJ8/Ohb272F771o/s320/P3068966.JPG" style="cursor: hand; display: block; height: 245px; margin: 0px auto 10px; text-align: center; width: 320px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;How it works (if you are interested)...&lt;/b&gt;&lt;br /&gt;It's the tried and trusted principle of the keyboard matrix - the 74HC595 IC's are "shift registers" which are simply used to scan a single "on" bit across 16 lines, one at a time (all 16 are used for the stylus, the first 12 are used for the columns of the kepad). The program running on the PIC chip reads the voltage coming back from each row of the keypad and also from the stylus. Since the program knows which one of the 16 shift register outputs it has switched "on" at any moment in time it then knows which buttons are pressed / which "strings" the stylus is touching at any moment in time by which input lines (if any) it reads the voltage back on. The rest is down to the program code to convert this info into MIDI notes and send them to a synth. One other important things are the 10k "pull down" resistors on each of the 3 keyboard rows and the stylus line... they make sure that an unconnected line settles at 0V rather than reading spurious random values.&lt;br /&gt;&lt;br /&gt;The source code&lt;br /&gt;// STRUM CHORD CONTROLLER&lt;br /&gt;&lt;br /&gt;// (c) 2010 J.Hotchkiss&lt;br /&gt;&lt;br /&gt;// SOURCEBOOST C FOR PIC16F688&lt;br /&gt;&lt;br /&gt;#include &amp;lt;system.h&amp;gt;&lt;br /&gt;&lt;br /&gt;#include &amp;lt;memory.h&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// PIC CONFIG&lt;br /&gt;&lt;br /&gt;#pragma DATA _CONFIG, _MCLRE_OFF&amp;amp;_WDT_OFF&amp;amp;_INTRC_OSC_NOCLKOUT&lt;br /&gt;&lt;br /&gt;#pragma CLOCK_FREQ 8000000&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// Define pins&lt;br /&gt;&lt;br /&gt;#define P_CLK porta.2&lt;br /&gt;&lt;br /&gt;#define P_DS portc.0&lt;br /&gt;&lt;br /&gt;#define P_STYLUS portc.1&lt;br /&gt;&lt;br /&gt;#define P_HEARTBEAT portc.2&lt;br /&gt;&lt;br /&gt;#define P_KEYS1 portc.3&lt;br /&gt;&lt;br /&gt;#define P_KEYS2 porta.4&lt;br /&gt;&lt;br /&gt;#define P_KEYS3 porta.5&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;typedef unsigned char byte;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// Chord types&lt;br /&gt;&lt;br /&gt;enum {&lt;br /&gt;&lt;br /&gt;CHORD_NONE,&lt;br /&gt;&lt;br /&gt;CHORD_MAJ,&lt;br /&gt;&lt;br /&gt;CHORD_MIN,&lt;br /&gt;&lt;br /&gt;CHORD_DOM7,&lt;br /&gt;&lt;br /&gt;CHORD_MAJ7,&lt;br /&gt;&lt;br /&gt;CHORD_MIN7,&lt;br /&gt;&lt;br /&gt;CHORD_AUG,&lt;br /&gt;&lt;br /&gt;CHORD_DIM&lt;br /&gt;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// special note value&lt;br /&gt;&lt;br /&gt;#define NO_NOTE 0xff&lt;br /&gt;&lt;br /&gt;//byte silent[1] = {NO_NOTE};&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// Define the chord structures&lt;br /&gt;&lt;br /&gt;byte maj[3] = {0,4,7};&lt;br /&gt;&lt;br /&gt;byte min[3] = {0,3,7};&lt;br /&gt;&lt;br /&gt;byte dom7[4] = {0,4,7,10};&lt;br /&gt;&lt;br /&gt;byte maj7[4] = {0,4,7,11};&lt;br /&gt;&lt;br /&gt;byte min7[4] = {0,3,7,10};&lt;br /&gt;&lt;br /&gt;byte dim[3] = {0,3,6};&lt;br /&gt;&lt;br /&gt;byte aug[3] = {0,3,8};&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// Define the MIDI root notes mapped to each key&lt;br /&gt;&lt;br /&gt;byte roots[16]={36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51};&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// bit mapped register of which strings are currently connected&lt;br /&gt;&lt;br /&gt;// to the stylus (notes triggered when stylus breaks contact&lt;br /&gt;&lt;br /&gt;// with the strings)&lt;br /&gt;&lt;br /&gt;unsigned long strings =0;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// Notes for each string&lt;br /&gt;&lt;br /&gt;byte notes[16] = {0};&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// current chord type&lt;br /&gt;&lt;br /&gt;byte lastChordType = CHORD_NONE;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// current root note&lt;br /&gt;&lt;br /&gt;byte lastRoot = NO_NOTE;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;// INITIALISE SERIAL PORT FOR MIDI&lt;br /&gt;&lt;br /&gt;void init_usart()&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;pir1.1 = 1; //TXIF transmit enable&lt;br /&gt;&lt;br /&gt;pie1.1 = 0; //TXIE no interrupts&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;baudctl.4 = 0; // synchronous bit polarity &lt;br /&gt;&lt;br /&gt;baudctl.3 = 1; // enable 16 bit brg&lt;br /&gt;&lt;br /&gt;baudctl.1 = 0; // wake up enable off&lt;br /&gt;&lt;br /&gt;baudctl.0 = 0; // disable auto baud detect&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;txsta.6 = 0; // 8 bit transmission&lt;br /&gt;&lt;br /&gt;txsta.5 = 1; // transmit enable&lt;br /&gt;&lt;br /&gt;txsta.4 = 0; // async mode&lt;br /&gt;&lt;br /&gt;txsta.2 = 0; // high baudrate BRGH&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;rcsta.7 = 1; // serial port enable&lt;br /&gt;&lt;br /&gt;rcsta.6 = 0; // 8 bit operation&lt;br /&gt;&lt;br /&gt;rcsta.4 = 0; // enable receiver&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;spbrgh = 0; // brg high byte&lt;br /&gt;&lt;br /&gt;spbrg = 15; // brg low byte (31250) &lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;// SEND A MIDI BYTE&lt;br /&gt;&lt;br /&gt;void send(unsigned char c)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;txreg = c;&lt;br /&gt;&lt;br /&gt;while(!txsta.1);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;// CONTINUOUS CONTROLLER MESSAGE&lt;br /&gt;&lt;br /&gt;void sendController(byte channel, byte controller, byte value)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;P_HEARTBEAT = 1;&lt;br /&gt;&lt;br /&gt;send(0xb0 | channel);&lt;br /&gt;&lt;br /&gt;send(controller&amp;amp;0x7f);&lt;br /&gt;&lt;br /&gt;send(value&amp;amp;0x7f);&lt;br /&gt;&lt;br /&gt;P_HEARTBEAT = 0; &lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;// NOTE MESSAGE&lt;br /&gt;&lt;br /&gt;void startNote(byte channel, byte note, byte value)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;P_HEARTBEAT = 1;&lt;br /&gt;&lt;br /&gt;send(0x90 | channel);&lt;br /&gt;&lt;br /&gt;send(note&amp;amp;0x7f);&lt;br /&gt;&lt;br /&gt;send(value&amp;amp;0x7f);&lt;br /&gt;&lt;br /&gt;P_HEARTBEAT = 0; &lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;// CALCULATE NOTES FOR A CHORD SHAPE AND MAP THEM&lt;br /&gt;&lt;br /&gt;// TO THE STRINGS&lt;br /&gt;&lt;br /&gt;void changeToChord(int root, int which)&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;int i,j,len=0;&lt;br /&gt;&lt;br /&gt;byte *struc = maj; &lt;br /&gt;&lt;br /&gt;byte chord[16];&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;if(CHORD_NONE == which || NO_NOTE == root)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// stop playing&lt;br /&gt;&lt;br /&gt;for(i=0;i&amp;lt;16;++i)&lt;br /&gt;&lt;br /&gt;chord[i] = NO_NOTE;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;else&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// select the correct chord shape&lt;br /&gt;&lt;br /&gt;switch(which)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;case CHORD_MIN:&lt;br /&gt;&lt;br /&gt;struc = min;&lt;br /&gt;&lt;br /&gt;len = sizeof(min);&lt;br /&gt;&lt;br /&gt;break;&lt;br /&gt;&lt;br /&gt;case CHORD_DOM7:&lt;br /&gt;&lt;br /&gt;struc = dom7;&lt;br /&gt;&lt;br /&gt;len = sizeof(dom7);&lt;br /&gt;&lt;br /&gt;break;&lt;br /&gt;&lt;br /&gt;case CHORD_MAJ7:&lt;br /&gt;&lt;br /&gt;struc = maj7;&lt;br /&gt;&lt;br /&gt;len = sizeof(maj7);&lt;br /&gt;&lt;br /&gt;break;&lt;br /&gt;&lt;br /&gt;case CHORD_MIN7:&lt;br /&gt;&lt;br /&gt;struc = min7;&lt;br /&gt;&lt;br /&gt;len = sizeof(min7);&lt;br /&gt;&lt;br /&gt;break;&lt;br /&gt;&lt;br /&gt;case CHORD_AUG:&lt;br /&gt;&lt;br /&gt;struc = aug;&lt;br /&gt;&lt;br /&gt;len = sizeof(aug);&lt;br /&gt;&lt;br /&gt;break;&lt;br /&gt;&lt;br /&gt;case CHORD_DIM:&lt;br /&gt;&lt;br /&gt;struc = dim;&lt;br /&gt;&lt;br /&gt;len = sizeof(dim);&lt;br /&gt;&lt;br /&gt;break;&lt;br /&gt;&lt;br /&gt;case CHORD_MAJ:&lt;br /&gt;&lt;br /&gt;default:&lt;br /&gt;&lt;br /&gt;struc = maj;&lt;br /&gt;&lt;br /&gt;len = sizeof(maj);&lt;br /&gt;&lt;br /&gt;break;&lt;br /&gt;&lt;br /&gt;break;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// fill the chord array with MIDI notes&lt;br /&gt;&lt;br /&gt;int from = 0;&lt;br /&gt;&lt;br /&gt;for(i=0;i&amp;lt;16;++i)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;chord[i] = root+struc[from]; &lt;br /&gt;&lt;br /&gt;if(++from &amp;gt;= len)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;root+=12;&lt;br /&gt;&lt;br /&gt;from = 0;&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;// stop previous notes from playing if they are not a &lt;br /&gt;&lt;br /&gt;// part of the new chord&lt;br /&gt;&lt;br /&gt;for(i=0;i&amp;lt;16;++i)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;if(notes[i] != NO_NOTE)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// check to see if it is part of the new chord&lt;br /&gt;&lt;br /&gt;byte foundIt = 0;&lt;br /&gt;&lt;br /&gt;for(j=0;j&amp;lt;16;++j)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;if(chord[j] == notes[i])&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;foundIt = true;&lt;br /&gt;&lt;br /&gt;break;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// if not, then make sure its not playing&lt;br /&gt;&lt;br /&gt;if(!foundIt) &lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;startNote(0, notes[i], 0);&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;// store the new chord&lt;br /&gt;&lt;br /&gt;for(i=0;i&amp;lt;16;++i)&lt;br /&gt;&lt;br /&gt;notes[i] = chord[i];&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;// POLL KEYBOARD MATRIX AND STRINGS&lt;br /&gt;&lt;br /&gt;void pollIO()&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// clock a single bit into the shift register&lt;br /&gt;&lt;br /&gt;P_CLK = 0;&lt;br /&gt;&lt;br /&gt;P_DS = 1; &lt;br /&gt;&lt;br /&gt;P_CLK = 1;&lt;br /&gt;&lt;br /&gt;P_DS = 0; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// get ready to scan&lt;br /&gt;&lt;br /&gt;int root = NO_NOTE;&lt;br /&gt;&lt;br /&gt;int chordType = CHORD_NONE;&lt;br /&gt;&lt;br /&gt;unsigned long b = 1;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// scan for each string&lt;br /&gt;&lt;br /&gt;for(int i=0;i&amp;lt;16;++i)&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;// clock pulse to shift the bit (note that&lt;br /&gt;&lt;br /&gt;// the first bit does not appear until the&lt;br /&gt;&lt;br /&gt;// second clock pulse, since we tied shift and store&lt;br /&gt;&lt;br /&gt;// clock lines together)&lt;br /&gt;&lt;br /&gt;P_CLK = 0; &lt;br /&gt;&lt;br /&gt;P_CLK = 1;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// did we get a signal back on any of the &lt;br /&gt;&lt;br /&gt;// keyboard scan rows?&lt;br /&gt;&lt;br /&gt;if(P_KEYS1 || P_KEYS2 || P_KEYS3)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// have we decided on the root note yet?&lt;br /&gt;&lt;br /&gt;if(NO_NOTE == root)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// look up the root note&lt;br /&gt;&lt;br /&gt;root = roots[15-i];&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// get the correct chord shape&lt;br /&gt;&lt;br /&gt;switch(&lt;br /&gt;&lt;br /&gt;(P_KEYS1? 0b100:0)|&lt;br /&gt;&lt;br /&gt;(P_KEYS2? 0b010:0)|&lt;br /&gt;&lt;br /&gt;(P_KEYS3? 0b001:0))&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;case 0b111:&lt;br /&gt;&lt;br /&gt;chordType = CHORD_AUG;&lt;br /&gt;&lt;br /&gt;break;&lt;br /&gt;&lt;br /&gt;case 0b110:&lt;br /&gt;&lt;br /&gt;chordType = CHORD_DIM;&lt;br /&gt;&lt;br /&gt;break;&lt;br /&gt;&lt;br /&gt;case 0b100:&lt;br /&gt;&lt;br /&gt;chordType = CHORD_MAJ;&lt;br /&gt;&lt;br /&gt;break;&lt;br /&gt;&lt;br /&gt;case 0b101:&lt;br /&gt;&lt;br /&gt;chordType = CHORD_MAJ7;&lt;br /&gt;&lt;br /&gt;break;&lt;br /&gt;&lt;br /&gt;case 0b010:&lt;br /&gt;&lt;br /&gt;chordType = CHORD_MIN;&lt;br /&gt;&lt;br /&gt;break;&lt;br /&gt;&lt;br /&gt;case 0b011:&lt;br /&gt;&lt;br /&gt;chordType = CHORD_MIN7;&lt;br /&gt;&lt;br /&gt;break;&lt;br /&gt;&lt;br /&gt;case 0b001:&lt;br /&gt;&lt;br /&gt;chordType = CHORD_DOM7;&lt;br /&gt;&lt;br /&gt;break;&lt;br /&gt;&lt;br /&gt;default:&lt;br /&gt;&lt;br /&gt;chordType = CHORD_NONE;&lt;br /&gt;&lt;br /&gt;break;&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;// now check whether we got a signal&lt;br /&gt;&lt;br /&gt;// back from the stylus (meaning that&lt;br /&gt;&lt;br /&gt;// it's touching this string)&lt;br /&gt;&lt;br /&gt;byte whichString = 15-i;&lt;br /&gt;&lt;br /&gt;if(P_STYLUS)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// string is being touched... was&lt;br /&gt;&lt;br /&gt;// it being touched before?&lt;br /&gt;&lt;br /&gt;if(!(strings &amp;amp; b))&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// stop the note playing (if&lt;br /&gt;&lt;br /&gt;// it is currently playing). When &lt;br /&gt;&lt;br /&gt;// stylus is touching a string it&lt;br /&gt;&lt;br /&gt;// is "damped" and does not play&lt;br /&gt;&lt;br /&gt;// till contact is broken&lt;br /&gt;&lt;br /&gt;if(notes[whichString] != NO_NOTE)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;startNote(0, notes[whichString], 0);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// remember this string is being touched&lt;br /&gt;&lt;br /&gt;strings |= b;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// stylus not touching string now, but was it &lt;br /&gt;&lt;br /&gt;// touching the string before?&lt;br /&gt;&lt;br /&gt;else if(strings &amp;amp; b)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// start a note playing&lt;br /&gt;&lt;br /&gt;if(notes[whichString] != NO_NOTE)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;startNote(0, notes[whichString], 127);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// remember string is not being touched&lt;br /&gt;&lt;br /&gt;strings &amp;amp;= ~b;&lt;br /&gt;&lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// shift the masking bit &lt;br /&gt;&lt;br /&gt;b&amp;lt;&amp;lt;=1;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// has the chord changed?&lt;br /&gt;&lt;br /&gt;if(chordType != lastChordType || root != lastRoot)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// change to the new chord&lt;br /&gt;&lt;br /&gt;lastChordType = chordType;&lt;br /&gt;&lt;br /&gt;lastRoot = root;&lt;br /&gt;&lt;br /&gt;changeToChord(root, chordType);&lt;br /&gt;&lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;void main()&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&lt;br /&gt;// osc control / 8MHz / internal&lt;br /&gt;&lt;br /&gt;osccon = 0b01110001;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// timer0... configure source and prescaler&lt;br /&gt;&lt;br /&gt;option_reg = 0b10000011;&lt;br /&gt;&lt;br /&gt;cmcon0 = 7; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// configure io&lt;br /&gt;&lt;br /&gt;trisa = 0b00110000; &lt;br /&gt;&lt;br /&gt;trisc = 0b00001010; &lt;br /&gt;&lt;br /&gt;ansel = 0b00000000;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// initialise MIDI comms&lt;br /&gt;&lt;br /&gt;init_usart();&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// initialise the notes array&lt;br /&gt;&lt;br /&gt;memset(notes,NO_NOTE,sizeof(notes));&lt;br /&gt;&lt;br /&gt;for(;;)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;// and now just repeatedly&lt;br /&gt;&lt;br /&gt;// check for input&lt;br /&gt;&lt;br /&gt;pollIO();&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-5872209006912301699?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/5872209006912301699/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2010/03/midi-guitar-on-stripboard-kind-of.html#comment-form' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/5872209006912301699'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/5872209006912301699'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2010/03/midi-guitar-on-stripboard-kind-of.html' title='MIDI Guitar on Stripboard... Kind of'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_rn0sSfRNtpI/S5JHOJWTIpI/AAAAAAAABJs/9lLsIwhxCUY/s72-c/P3068960.JPG' height='72' width='72'/><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-8058532681917423734</id><published>2010-02-28T10:19:00.000-08:00</published><updated>2010-02-28T10:35:19.155-08:00</updated><title type='text'>When Lava met Mopho</title><content type='html'>I got a new toy! an Mopho analog synth from Dave Smith Instruments. First use.. a companion to my MIDI lavalamp to free it up from PC based soft synths. Since my original MIDI lavalamp project was based on a standard Arduino, I decided this time to make a quick little module for it using a PIC16F688 (my current weapon of choice)&lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/X5wKCsHCSJk&amp;hl=en_US&amp;fs=1&amp;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/X5wKCsHCSJk&amp;hl=en_US&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Here is the circuit on stripboard&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_rn0sSfRNtpI/S4q1YXuo4ZI/AAAAAAAABJM/_97fjYZcs-k/s1600-h/P2288935.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 200px;" src="http://2.bp.blogspot.com/_rn0sSfRNtpI/S4q1YXuo4ZI/AAAAAAAABJM/_97fjYZcs-k/s320/P2288935.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5443362529921786258" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;...the mess on the back...&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_rn0sSfRNtpI/S4q1f6cbtlI/AAAAAAAABJU/WGhpbg0VnRU/s1600-h/P2288937.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 173px;" src="http://3.bp.blogspot.com/_rn0sSfRNtpI/S4q1f6cbtlI/AAAAAAAABJU/WGhpbg0VnRU/s320/P2288937.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5443362659499750994" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;...and the schematic...&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_rn0sSfRNtpI/S4q1mR8AE0I/AAAAAAAABJc/fefHDHEwXAU/s1600-h/piclava.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 142px;" src="http://2.bp.blogspot.com/_rn0sSfRNtpI/S4q1mR8AE0I/AAAAAAAABJc/fefHDHEwXAU/s320/piclava.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5443362768885388098" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;... the lamp is wired up as described on &lt;a href="http://sites.google.com/site/skriyl/Home/lava-lamp-midi-controller"&gt;this post&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;... and the PIC source code is included below (SourceBoost compiler)&lt;br /&gt;&lt;br /&gt;#include &amp;lt;system.h&amp;gt;&lt;br /&gt;&lt;br&gt;#include &amp;lt;memory.h&amp;gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;#define ANA_0 0b00000000&lt;br /&gt;&lt;br&gt;#define ANA_1 0b00000100&lt;br /&gt;&lt;br&gt;#define ANA_2 0b00001000&lt;br /&gt;&lt;br&gt;#define ANA_3 0b00001100&lt;br /&gt;&lt;br&gt;#define ANA_4 0b00010000&lt;br /&gt;&lt;br&gt;#define ANA_5 0b00010100&lt;br /&gt;&lt;br&gt;#define ANA_6 0b00011000&lt;br /&gt;&lt;br&gt;#define ANA_7 0b00011100&lt;br /&gt;&lt;br&gt;#define ADC_MAX 6&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;#define P_HEARTBEAT  porta.5&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;#pragma DATA _CONFIG, _MCLRE_OFF&amp;amp;_WDT_OFF&amp;amp;_INTRC_OSC_NOCLKOUT&lt;br /&gt;&lt;br&gt;#pragma CLOCK_FREQ 8000000&lt;br /&gt;&lt;br&gt;#define ADC_AQUISITION_DELAY 10&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;typedef unsigned char byte;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;enum {&lt;br /&gt;&lt;br&gt; ADC_CONNECT,&lt;br /&gt;&lt;br&gt; ADC_ACQUIRE,&lt;br /&gt;&lt;br&gt; ADC_CONVERT    &lt;br /&gt;&lt;br&gt;};&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;void init_usart()&lt;br /&gt;&lt;br&gt;{&lt;br /&gt;&lt;br&gt; pir1.1 = 1; //TXIF transmit enable&lt;br /&gt;&lt;br&gt; pie1.1 = 0; //TXIE no interrupts&lt;br /&gt;&lt;br&gt; &lt;br /&gt;&lt;br&gt; baudctl.4 = 0;  // synchronous bit polarity &lt;br /&gt;&lt;br&gt; baudctl.3 = 1;  // enable 16 bit brg&lt;br /&gt;&lt;br&gt; baudctl.1 = 0;  // wake up enable off&lt;br /&gt;&lt;br&gt; baudctl.0 = 0;  // disable auto baud detect&lt;br /&gt;&lt;br&gt;  &lt;br /&gt;&lt;br&gt; txsta.6 = 0; // 8 bit transmission&lt;br /&gt;&lt;br&gt; txsta.5 = 1; // transmit enable&lt;br /&gt;&lt;br&gt; txsta.4 = 0; // async mode&lt;br /&gt;&lt;br&gt; txsta.2 = 0; // high baudrate BRGH&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt; rcsta.7 = 1; // serial port enable&lt;br /&gt;&lt;br&gt; rcsta.6 = 0; // 8 bit operation&lt;br /&gt;&lt;br&gt; rcsta.4 = 0; // enable receiver&lt;br /&gt;&lt;br&gt;  &lt;br /&gt;&lt;br&gt; spbrgh = 0;  // brg high byte&lt;br /&gt;&lt;br&gt; spbrg = 15;  // brg low byte (31250) &lt;br /&gt;&lt;br&gt;}&lt;br /&gt;&lt;br&gt;  &lt;br /&gt;&lt;br&gt;void send(unsigned char c)&lt;br /&gt;&lt;br&gt;{&lt;br /&gt;&lt;br&gt; txreg = c;&lt;br /&gt;&lt;br&gt; while(!txsta.1);&lt;br /&gt;&lt;br&gt;}&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;void sendController(byte channel, byte controller, byte value)&lt;br /&gt;&lt;br&gt;{&lt;br /&gt;&lt;br&gt; P_HEARTBEAT = 1;&lt;br /&gt;&lt;br&gt; send(0xb0 | channel);&lt;br /&gt;&lt;br&gt; send(controller&amp;amp;0x7f);&lt;br /&gt;&lt;br&gt; send(value&amp;amp;0x7f);&lt;br /&gt;&lt;br&gt; P_HEARTBEAT = 0; &lt;br /&gt;&lt;br&gt;}&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;byte adcInput[ADC_MAX] = {ANA_2, ANA_3, ANA_4, ANA_5, ANA_6, ANA_7};&lt;br /&gt;&lt;br&gt;byte adcInitComplete = 0;&lt;br /&gt;&lt;br&gt;int adcResult[ADC_MAX] = {-1,-1,-1,-1,-1,-1};&lt;br /&gt;&lt;br&gt;int adcIndex = 0;&lt;br /&gt;&lt;br&gt;int adcState = ADC_CONNECT;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;////////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br&gt;// &lt;br /&gt;&lt;br&gt;// doADC&lt;br /&gt;&lt;br&gt;//&lt;br /&gt;&lt;br&gt;// State machine for running the ADC and updating the adcResult&lt;br /&gt;&lt;br&gt;// array with the result from each analog input&lt;br /&gt;&lt;br&gt;//&lt;br /&gt;&lt;br&gt;void doADC()&lt;br /&gt;&lt;br&gt;{&lt;br /&gt;&lt;br&gt; switch(adcState)&lt;br /&gt;&lt;br&gt; {&lt;br /&gt;&lt;br&gt;  // Connect ADC to the correct analog input&lt;br /&gt;&lt;br&gt;  case ADC_CONNECT:   &lt;br /&gt;&lt;br&gt;   adcon0=0b10000001 | adcInput[adcIndex];&lt;br /&gt;&lt;br&gt;   tmr0 = 0;&lt;br /&gt;&lt;br&gt;   adcState = ADC_ACQUIRE;&lt;br /&gt;&lt;br&gt;   // fall through&lt;br /&gt;&lt;br&gt;   &lt;br /&gt;&lt;br&gt;  // Waiting for a delay while the ADC input settles&lt;br /&gt;&lt;br&gt;  case ADC_ACQUIRE:&lt;br /&gt;&lt;br&gt;   if(tmr0 &amp;gt; ADC_AQUISITION_DELAY)&lt;br /&gt;&lt;br&gt;   {&lt;br /&gt;&lt;br&gt;    // Start the conversion&lt;br /&gt;&lt;br&gt;    adcon0.1=1;&lt;br /&gt;&lt;br&gt;    adcState = ADC_CONVERT;    &lt;br /&gt;&lt;br&gt;   }&lt;br /&gt;&lt;br&gt;   break;&lt;br /&gt;&lt;br&gt;   &lt;br /&gt;&lt;br&gt;  // Waiting for the conversion to complete&lt;br /&gt;&lt;br&gt;  case ADC_CONVERT:&lt;br /&gt;&lt;br&gt;   if(!adcon0.1)&lt;br /&gt;&lt;br&gt;   {&lt;br /&gt;&lt;br&gt;    // store the result&lt;br /&gt;&lt;br&gt;    adcResult[adcIndex] = (((int)adresh)&amp;lt;&amp;lt;8)|adresl;    &lt;br /&gt;&lt;br&gt;    &lt;br /&gt;&lt;br&gt;    // and prepare for the next ADC&lt;br /&gt;&lt;br&gt;    if(++adcIndex&amp;gt;=ADC_MAX)&lt;br /&gt;&lt;br&gt;    {&lt;br /&gt;&lt;br&gt;     adcIndex = 0;&lt;br /&gt;&lt;br&gt;     adcInitComplete = 1;&lt;br /&gt;&lt;br&gt;    }&lt;br /&gt;&lt;br&gt;    adcState = ADC_CONNECT;    &lt;br /&gt;&lt;br&gt;   }&lt;br /&gt;&lt;br&gt;   break;&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;#define BUFLEN 8&lt;br /&gt;&lt;br&gt;typedef struct  &lt;br /&gt;&lt;br&gt;{&lt;br /&gt;&lt;br&gt;  char midiChannel;&lt;br /&gt;&lt;br&gt;  char midiController;  &lt;br /&gt;&lt;br&gt;  int minADC;&lt;br /&gt;&lt;br&gt;  int maxADC;&lt;br /&gt;&lt;br&gt;  char currentValue;  &lt;br /&gt;&lt;br&gt;  char history[BUFLEN];&lt;br /&gt;&lt;br&gt;} CONTROLLER;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;CONTROLLER controllers[ADC_MAX] = {0};&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;void initInput(int which, byte channel, byte controller)&lt;br /&gt;&lt;br&gt;{&lt;br /&gt;&lt;br&gt; controllers[which].midiChannel = channel;&lt;br /&gt;&lt;br&gt; controllers[which].midiController = controller;&lt;br /&gt;&lt;br&gt; controllers[which].minADC = -1;&lt;br /&gt;&lt;br&gt; controllers[which].maxADC = -1;&lt;br /&gt;&lt;br&gt; controllers[which].currentValue = -1;&lt;br /&gt;&lt;br&gt;}&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;void checkInput(int which)&lt;br /&gt;&lt;br&gt;{&lt;br /&gt;&lt;br&gt;   // pointer to the controllers&lt;br /&gt;&lt;br&gt;  CONTROLLER *p = &amp;amp;controllers[which];&lt;br /&gt;&lt;br&gt;  &lt;br /&gt;&lt;br&gt;  // read the raw analog value 0-1023&lt;br /&gt;&lt;br&gt;  int adc = adcResult[which];&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;  // remember highest and lowest values&lt;br /&gt;&lt;br&gt;  if((p-&amp;gt;minADC == -1) || (p-&amp;gt;minADC &amp;gt; adc))&lt;br /&gt;&lt;br&gt;      p-&amp;gt;minADC = adc;&lt;br /&gt;&lt;br&gt;  if((p-&amp;gt;maxADC == -1) || (p-&amp;gt;maxADC &amp;lt; adc))&lt;br /&gt;&lt;br&gt;      p-&amp;gt;maxADC = adc;&lt;br /&gt;&lt;br&gt;         &lt;br /&gt;&lt;br&gt;  // get the range of known readings&lt;br /&gt;&lt;br&gt;  int range = p-&amp;gt;maxADC - p-&amp;gt;minADC;     &lt;br /&gt;&lt;br&gt;  if(range &amp;lt; 1)&lt;br /&gt;&lt;br&gt;     range = 1;&lt;br /&gt;&lt;br&gt;         &lt;br /&gt;&lt;br&gt;  // scale the current value into the range&lt;br /&gt;&lt;br&gt;  // NB no floating point support...&lt;br /&gt;&lt;br&gt;  int newValue = (127*(adc - p-&amp;gt;minADC))/range;&lt;br /&gt;&lt;br&gt;              &lt;br /&gt;&lt;br&gt;  // add the value into the history buffer&lt;br /&gt;&lt;br&gt;  long smoothed = 0;&lt;br /&gt;&lt;br&gt;  for(int j=0; j&amp;lt;BUFLEN-1;++j)&lt;br /&gt;&lt;br&gt;  {&lt;br /&gt;&lt;br&gt;    p-&amp;gt;history[j] = p-&amp;gt;history[j+1];&lt;br /&gt;&lt;br&gt;    smoothed += p-&amp;gt;history[j];&lt;br /&gt;&lt;br&gt;  }&lt;br /&gt;&lt;br&gt;  p-&amp;gt;history[BUFLEN-1] = newValue;&lt;br /&gt;&lt;br&gt;  smoothed += newValue;&lt;br /&gt;&lt;br&gt;  smoothed /= BUFLEN;&lt;br /&gt;&lt;br&gt;              &lt;br /&gt;&lt;br&gt;  // has the value changed?&lt;br /&gt;&lt;br&gt;  if(smoothed != p-&amp;gt;currentValue)&lt;br /&gt;&lt;br&gt;  {&lt;br /&gt;&lt;br&gt;  sendController(p-&amp;gt;midiChannel, p-&amp;gt;midiController, smoothed);&lt;br /&gt;&lt;br&gt;     p-&amp;gt;currentValue= smoothed;&lt;br /&gt;&lt;br&gt;  }&lt;br /&gt;&lt;br&gt;}&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;void main()&lt;br /&gt;&lt;br&gt;{ &lt;br /&gt;&lt;br&gt; int i;&lt;br /&gt;&lt;br&gt; &lt;br /&gt;&lt;br&gt; // osc control / 8MHz / internal&lt;br /&gt;&lt;br&gt; osccon = 0b01110001;&lt;br /&gt;&lt;br&gt; &lt;br /&gt;&lt;br&gt; // timer0... configure source and prescaler&lt;br /&gt;&lt;br&gt; option_reg = 0b10000011;&lt;br /&gt;&lt;br&gt; cmcon0 = 7;                      &lt;br /&gt;&lt;br&gt; &lt;br /&gt;&lt;br&gt; // configure io&lt;br /&gt;&lt;br&gt; trisa = 0b00001010;               &lt;br /&gt;&lt;br&gt;    trisc = 0b00001111;              &lt;br /&gt;&lt;br&gt; ansel = 0b11111100;&lt;br /&gt;&lt;br&gt;      &lt;br /&gt;&lt;br&gt; // turn on the ADC&lt;br /&gt;&lt;br&gt; adcon1=0b00100000; //fOSC/32&lt;br /&gt;&lt;br&gt; adcon0=0b10000001; // Right justify / Vdd / AD on&lt;br /&gt;&lt;br&gt; &lt;br /&gt;&lt;br&gt; // initialise MIDI comms&lt;br /&gt;&lt;br&gt; init_usart();&lt;br /&gt;&lt;br&gt; &lt;br /&gt;&lt;br&gt; // Initialise the controllers&lt;br /&gt;&lt;br&gt; initInput(0, 0, 1);&lt;br /&gt;&lt;br&gt; initInput(1, 0, 2);&lt;br /&gt;&lt;br&gt; initInput(2, 0, 4);&lt;br /&gt;&lt;br&gt; initInput(3, 0, 7);&lt;br /&gt;&lt;br&gt; initInput(4, 0, 11);&lt;br /&gt;&lt;br&gt; initInput(5, 0, 74);&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt; adcInitComplete = 0;&lt;br /&gt;&lt;br&gt; for(;;)&lt;br /&gt;&lt;br&gt; {&lt;br /&gt;&lt;br&gt;  doADC();&lt;br /&gt;&lt;br&gt;  if(adcInitComplete)&lt;br /&gt;&lt;br&gt;  {   &lt;br /&gt;&lt;br&gt;   for(i=0;i&amp;lt;ADC_MAX;++i)&lt;br /&gt;&lt;br&gt;    checkInput(i);&lt;br /&gt;&lt;br&gt;   adcInitComplete = 0;   &lt;br /&gt;&lt;br&gt;   delay_ms(20);&lt;br /&gt;&lt;br&gt;  }&lt;br /&gt;&lt;br&gt; }&lt;br /&gt;&lt;br&gt;}&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-8058532681917423734?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/8058532681917423734/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2010/02/when-lava-met-mopho.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/8058532681917423734'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/8058532681917423734'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2010/02/when-lava-met-mopho.html' title='When Lava met Mopho'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_rn0sSfRNtpI/S4q1YXuo4ZI/AAAAAAAABJM/_97fjYZcs-k/s72-c/P2288935.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-9166906626926238759</id><published>2010-02-21T09:21:00.000-08:00</published><updated>2010-02-21T10:18:34.572-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pic'/><category scheme='http://www.blogger.com/atom/ns#' term='midi'/><title type='text'>Stylophone MIDI controller</title><content type='html'>A few months ago I used an Arduino clone board to send MIDI messages out of a Stylophone. I always intended to take it to the next level and get another Stylophone (preferably a broken one) and rip out the guts to fit all the electronics inside, and also add a few buttons and pots for perfomance controllers.&lt;br /&gt;&lt;br /&gt;Well, I finally got round to it. This time I am using a PIC16F688 microcontroller.. this little monkey only has 14 pins and costs a mere £1 yet it has a built in clock, serial port and ADC, which means its pretty much the *only* component needed in this project (with the exception of a couple of resistors and switches). &lt;br /&gt;&lt;br /&gt;I added a pitchbend pot, a modwheel and a pot to control the note velocity. And pushbuttons to shift octaves and "hold" a MIDI note (basically force the code to forget to send note-off message so the last note rings on after lifting the stylus). This allows a kind of polyphonic drone out of the usually strictly monophonic stylophone.&lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/nM-nKULjpiI&amp;hl=en_US&amp;fs=1&amp;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/nM-nKULjpiI&amp;hl=en_US&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;I will include the code below. I wont bother with a schematic, but the wiring to the PIC16F688 is as follows&lt;br /&gt;&lt;br /&gt;pin 1 - 5 volt supply&lt;br /&gt;2 - octave UP momentary switch (other side of switch connected to ground)&lt;br /&gt;3 - octave DOWN momentary switch (other side of switch connected to ground)&lt;br /&gt;6 - to pin 5 of MIDI out socket via a 220R resistor. Pin 4 of the socket is pulled up to 5V via another 220R resitor&lt;br /&gt;7 - wiper of PITCHBEND pot (100k). Pot terminal between from ground/+5V&lt;br /&gt;8 - wiper of VELOCITY pot (100k). Pot terminal between from ground/+5V&lt;br /&gt;9 - to the stylus. Also pulled up to +5v via 470k resistor&lt;br /&gt;10 - activity LED via 1k resistor&lt;br /&gt;11 - wiper of MOD WHEEL pot (100k). Pot terminal between from ground/+5V&lt;br /&gt;13 - HOLD NOTE momentary switch (other side of switch connected to ground)&lt;br /&gt;14 - to ground&lt;br /&gt;&lt;br /&gt;If you want to run it from a PP3 you'll need a 5V voltage regulator. You also need to connect the stylophone keyboard/resistor ladder between 0V and 5V and you will need to set up the scale[] array based on the ADC values you get from each pad on *your* stylophone keyboard (which are almost certainly different to mine)&lt;br /&gt;&lt;br /&gt;A few photos&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_rn0sSfRNtpI/S4FwjT3ephI/AAAAAAAABIQ/RHwVrl05wAQ/s1600-h/st4.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://3.bp.blogspot.com/_rn0sSfRNtpI/S4FwjT3ephI/AAAAAAAABIQ/RHwVrl05wAQ/s320/st4.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5440753576770971154" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_rn0sSfRNtpI/S4Fwd0dOd_I/AAAAAAAABII/wowGkgTru5U/s1600-h/st3.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://1.bp.blogspot.com/_rn0sSfRNtpI/S4Fwd0dOd_I/AAAAAAAABII/wowGkgTru5U/s320/st3.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5440753482440013810" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_rn0sSfRNtpI/S4FwVd_gMII/AAAAAAAABIA/Y1MR21_GwJM/s1600-h/st2.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 255px;" src="http://1.bp.blogspot.com/_rn0sSfRNtpI/S4FwVd_gMII/AAAAAAAABIA/Y1MR21_GwJM/s320/st2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5440753338970812546" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_rn0sSfRNtpI/S4FwNjpBwFI/AAAAAAAABH4/3sH29SnYBro/s1600-h/st1.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 237px;" src="http://3.bp.blogspot.com/_rn0sSfRNtpI/S4FwNjpBwFI/AAAAAAAABH4/3sH29SnYBro/s320/st1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5440753203048202322" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;// MIDI STYLOPHONE.. PIC16F688.. (c) 2010 hotchk155&lt;br /&gt;&lt;br&gt;// SourceBoost C&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;// Header files&lt;br /&gt;&lt;br&gt;#include &amp;lt;system.h&amp;gt;&lt;br /&gt;&lt;br&gt;#include &amp;lt;memory.h&amp;gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;#pragma DATA _CONFIG, _MCLRE_OFF &amp;amp; _WDT_OFF &amp;amp; _INTRC_OSC_NOCLKOUT&lt;br /&gt;&lt;br&gt;#pragma CLOCK_FREQ 8000000&lt;br /&gt;&lt;br&gt;typedef unsigned char byte;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;#define MIDI_A    45  // default root note&lt;br /&gt;&lt;br&gt;#define NO_NOTE   0x7f // means stylus &amp;quot;off keyboard&amp;quot;&lt;br /&gt;&lt;br&gt;#define NUM_PADS   20  // number of stylophone pads  &lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;#define BUTTON_DEBOUNCE 10  // debounce octave buttons&lt;br /&gt;&lt;br&gt;#define ADC_AQUISITION_DELAY 10 // settling time for ADC&lt;br /&gt;&lt;br&gt;#define PBD_TOL   16  // tolerance applied to pitchbend ADC&lt;br /&gt;&lt;br&gt;#define MOD_TOL   5  // tolerance applied to modulation ADC&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;// Digital pins&lt;br /&gt;&lt;br&gt;#define P_HEARTBEAT  portc.0 // activity LED&lt;br /&gt;&lt;br&gt;#define P_UP   porta.5 // octave UP button&lt;br /&gt;&lt;br&gt;#define P_DN   porta.4 // octave DOWN button&lt;br /&gt;&lt;br&gt;#define P_HOLD   porta.0 // note hold button&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;// Analog pin mappings&lt;br /&gt;&lt;br&gt;#define ANA_MOD 0b00001000  // AN2 - MOD WHEEL&lt;br /&gt;&lt;br&gt;#define ANA_KBD 0b00010100 // AN5 - KEYBOARD STYLUS&lt;br /&gt;&lt;br&gt;#define ANA_VEL 0b00011100 // AN6 - VELOCITY&lt;br /&gt;&lt;br&gt;#define ANA_PBD 0b00011000 // AN7 - PITCHBEND&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;// define the four analog inputs&lt;br /&gt;&lt;br&gt;enum {&lt;br /&gt;&lt;br&gt; ADC_KBD,&lt;br /&gt;&lt;br&gt; ADC_VEL,&lt;br /&gt;&lt;br&gt; ADC_MOD,&lt;br /&gt;&lt;br&gt; ADC_PBD,&lt;br /&gt;&lt;br&gt; ADC_MAX&lt;br /&gt;&lt;br&gt;};&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;// for the state machine which read analog inputs&lt;br /&gt;&lt;br&gt;enum {&lt;br /&gt;&lt;br&gt; ADC_CONNECT,&lt;br /&gt;&lt;br&gt; ADC_ACQUIRE,&lt;br /&gt;&lt;br&gt; ADC_CONVERT    &lt;br /&gt;&lt;br&gt;};&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;// define the ADC readings for each stylophone key pad. This&lt;br /&gt;&lt;br&gt;// is likely to be different if you make your own circuit, so&lt;br /&gt;&lt;br&gt;// you will need to work out your own ADC values&lt;br /&gt;&lt;br&gt;int scale[NUM_PADS+1] = {&lt;br /&gt;&lt;br&gt; 0x000,&lt;br /&gt;&lt;br&gt; 0x043,&lt;br /&gt;&lt;br&gt; 0x081,&lt;br /&gt;&lt;br&gt; 0x0b9,&lt;br /&gt;&lt;br&gt; 0x0ed,&lt;br /&gt;&lt;br&gt; 0x110,&lt;br /&gt;&lt;br&gt; 0x149,&lt;br /&gt;&lt;br&gt; 0x172,&lt;br /&gt;&lt;br&gt; 0x199,&lt;br /&gt;&lt;br&gt; 0x1bd,&lt;br /&gt;&lt;br&gt; 0x1df,&lt;br /&gt;&lt;br&gt; 0x1ff,&lt;br /&gt;&lt;br&gt; 0x21c,&lt;br /&gt;&lt;br&gt; 0x238,&lt;br /&gt;&lt;br&gt; 0x252,&lt;br /&gt;&lt;br&gt; 0x26b,&lt;br /&gt;&lt;br&gt; 0x281,&lt;br /&gt;&lt;br&gt; 0x298,&lt;br /&gt;&lt;br&gt; 0x2ab,&lt;br /&gt;&lt;br&gt; 0x2c0,&lt;br /&gt;&lt;br&gt; 0x3ff&lt;br /&gt;&lt;br&gt;};&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;// midi note at bottom of scale (can be shifted&lt;br /&gt;&lt;br&gt;// up and down by an octave at a time)&lt;br /&gt;&lt;br&gt;char baseNote = MIDI_A;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;// data used by doADC function&lt;br /&gt;&lt;br&gt;byte adcInput[ADC_MAX] = {ANA_KBD, ANA_VEL, ANA_MOD, ANA_PBD};&lt;br /&gt;&lt;br&gt;byte adcInitComplete = 0;&lt;br /&gt;&lt;br&gt;int adcResult[ADC_MAX] = {-1,-1,-1,-1};&lt;br /&gt;&lt;br&gt;int adcIndex = 0;&lt;br /&gt;&lt;br&gt;int adcState = ADC_CONNECT;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;////////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br&gt;// &lt;br /&gt;&lt;br&gt;// init_usart&lt;br /&gt;&lt;br&gt;//&lt;br /&gt;&lt;br&gt;// Initialise the PIC16F688 USART (serial port) according to the&lt;br /&gt;&lt;br&gt;// requirements of sending MIDI traffic&lt;br /&gt;&lt;br&gt;//&lt;br /&gt;&lt;br&gt;void init_usart()&lt;br /&gt;&lt;br&gt;{&lt;br /&gt;&lt;br&gt; pir1.1 = 1; //TXIF transmit enable&lt;br /&gt;&lt;br&gt; pie1.1 = 0; //TXIE no interrupts&lt;br /&gt;&lt;br&gt; &lt;br /&gt;&lt;br&gt; baudctl.4 = 0;  // synchronous bit polarity &lt;br /&gt;&lt;br&gt; baudctl.3 = 1;  // enable 16 bit brg&lt;br /&gt;&lt;br&gt; baudctl.1 = 0;  // wake up enable off&lt;br /&gt;&lt;br&gt; baudctl.0 = 0;  // disable auto baud detect&lt;br /&gt;&lt;br&gt;  &lt;br /&gt;&lt;br&gt; txsta.6 = 0; // 8 bit transmission&lt;br /&gt;&lt;br&gt; txsta.5 = 1; // transmit enable&lt;br /&gt;&lt;br&gt; txsta.4 = 0; // async mode&lt;br /&gt;&lt;br&gt; txsta.2 = 0; // high baudrate BRGH&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt; rcsta.7 = 1; // serial port enable&lt;br /&gt;&lt;br&gt; rcsta.6 = 0; // 8 bit operation&lt;br /&gt;&lt;br&gt; rcsta.4 = 0; // enable receiver&lt;br /&gt;&lt;br&gt; &lt;br /&gt;&lt;br&gt; spbrgh = 0;  // brg high byte&lt;br /&gt;&lt;br&gt; spbrg = 15;  // brg low byte (31250 baud) &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;// send&lt;br /&gt;&lt;br&gt;//&lt;br /&gt;&lt;br&gt;// Send a single byte out on the serial port&lt;br /&gt;&lt;br&gt;//&lt;br /&gt;&lt;br&gt;void send(byte c)&lt;br /&gt;&lt;br&gt;{&lt;br /&gt;&lt;br&gt; txreg = c;&lt;br /&gt;&lt;br&gt; while(!txsta.1);&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;// sendController&lt;br /&gt;&lt;br&gt;//&lt;br /&gt;&lt;br&gt;// Send a MIDI continous controller message&lt;br /&gt;&lt;br&gt;//&lt;br /&gt;&lt;br&gt;void sendController(byte channel, byte controller, byte value)&lt;br /&gt;&lt;br&gt;{&lt;br /&gt;&lt;br&gt; P_HEARTBEAT = 1;&lt;br /&gt;&lt;br&gt; send(0xb0 | channel);&lt;br /&gt;&lt;br&gt; send(controller&amp;amp;0x7f);&lt;br /&gt;&lt;br&gt; send(value&amp;amp;0x7f);&lt;br /&gt;&lt;br&gt; P_HEARTBEAT = 0; &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;// startNote&lt;br /&gt;&lt;br&gt;//&lt;br /&gt;&lt;br&gt;// Send a MIDI note on message (or note off if 0 velocity)&lt;br /&gt;&lt;br&gt;//&lt;br /&gt;&lt;br&gt;void startNote(byte channel, byte note, byte velocity)&lt;br /&gt;&lt;br&gt;{&lt;br /&gt;&lt;br&gt; P_HEARTBEAT = 1;&lt;br /&gt;&lt;br&gt; send(0x90 | channel);&lt;br /&gt;&lt;br&gt; send(note&amp;amp;0x7f);&lt;br /&gt;&lt;br&gt; send(velocity&amp;amp;0x7f);&lt;br /&gt;&lt;br&gt; P_HEARTBEAT = 0; &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;// pitchBend&lt;br /&gt;&lt;br&gt;//&lt;br /&gt;&lt;br&gt;// Send a MIDI pitchbend message (14 data bits)&lt;br /&gt;&lt;br&gt;//&lt;br /&gt;&lt;br&gt;void pitchBend(byte channel, int value) {&lt;br /&gt;&lt;br&gt;  P_HEARTBEAT = 1;&lt;br /&gt;&lt;br&gt;  byte msb = (value&amp;gt;&amp;gt;7)&amp;amp;0x7f;&lt;br /&gt;&lt;br&gt;  byte lsb = value&amp;amp;0x7f;&lt;br /&gt;&lt;br&gt;  send(0xE0 | channel);&lt;br /&gt;&lt;br&gt;  send(lsb);&lt;br /&gt;&lt;br&gt;  send(msb);&lt;br /&gt;&lt;br&gt;  P_HEARTBEAT = 0;&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;// doADC&lt;br /&gt;&lt;br&gt;//&lt;br /&gt;&lt;br&gt;// State machine for running the ADC and updating the adcResult&lt;br /&gt;&lt;br&gt;// array with the result from each analog input. This function is &lt;br /&gt;&lt;br&gt;// called periodically and keeps the adcResult[] array updated so&lt;br /&gt;&lt;br&gt;// other code can just check the array rather than making direct&lt;br /&gt;&lt;br&gt;// calls to the ADC&lt;br /&gt;&lt;br&gt;//&lt;br /&gt;&lt;br&gt;void doADC()&lt;br /&gt;&lt;br&gt;{&lt;br /&gt;&lt;br&gt; switch(adcState)&lt;br /&gt;&lt;br&gt; {&lt;br /&gt;&lt;br&gt;  // Connect ADC to the correct analog input&lt;br /&gt;&lt;br&gt;  case ADC_CONNECT:   &lt;br /&gt;&lt;br&gt;   adcon0=0b10000001 | adcInput[adcIndex];&lt;br /&gt;&lt;br&gt;   tmr0 = 0;&lt;br /&gt;&lt;br&gt;   adcState = ADC_ACQUIRE;&lt;br /&gt;&lt;br&gt;   // fall through&lt;br /&gt;&lt;br&gt;   &lt;br /&gt;&lt;br&gt;  // Waiting for a delay while the ADC input settles&lt;br /&gt;&lt;br&gt;  // - this is neededs or you can get garbage readings&lt;br /&gt;&lt;br&gt;  // as the ADC transitions between one input voltage&lt;br /&gt;&lt;br&gt;  // and another. The TMR0 (timer 0) register is used for&lt;br /&gt;&lt;br&gt;  // timings this&lt;br /&gt;&lt;br&gt;  case ADC_ACQUIRE:&lt;br /&gt;&lt;br&gt;   if(tmr0 &amp;gt; ADC_AQUISITION_DELAY)&lt;br /&gt;&lt;br&gt;   {&lt;br /&gt;&lt;br&gt;    // Start the conversion&lt;br /&gt;&lt;br&gt;    adcon0.1=1;&lt;br /&gt;&lt;br&gt;    adcState = ADC_CONVERT;    &lt;br /&gt;&lt;br&gt;   }&lt;br /&gt;&lt;br&gt;   break;&lt;br /&gt;&lt;br&gt;   &lt;br /&gt;&lt;br&gt;  // Waiting for the conversion to complete&lt;br /&gt;&lt;br&gt;  case ADC_CONVERT:&lt;br /&gt;&lt;br&gt;   if(!adcon0.1)&lt;br /&gt;&lt;br&gt;   {&lt;br /&gt;&lt;br&gt;    // store the result. Note that the PIC16F688 has&lt;br /&gt;&lt;br&gt;    // a 10 bit ADC so we need to form a 10 bit value&lt;br /&gt;&lt;br&gt;    // from ADRESH and ADRESL&lt;br /&gt;&lt;br&gt;    adcResult[adcIndex] = (((int)adresh)&amp;lt;&amp;lt;8)|adresl;    &lt;br /&gt;&lt;br&gt;    &lt;br /&gt;&lt;br&gt;    // and prepare for the next ADC&lt;br /&gt;&lt;br&gt;    if(++adcIndex&amp;gt;=ADC_MAX)&lt;br /&gt;&lt;br&gt;    {&lt;br /&gt;&lt;br&gt;     adcIndex = 0;&lt;br /&gt;&lt;br&gt;     &lt;br /&gt;&lt;br&gt;     // flag that each ADC has been read at least&lt;br /&gt;&lt;br&gt;     // one time, so adcResult now contains valid&lt;br /&gt;&lt;br&gt;     // information&lt;br /&gt;&lt;br&gt;     adcInitComplete = 1;&lt;br /&gt;&lt;br&gt;    }&lt;br /&gt;&lt;br&gt;    adcState = ADC_CONNECT;    &lt;br /&gt;&lt;br&gt;   }&lt;br /&gt;&lt;br&gt;   break;&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;// getNote&lt;br /&gt;&lt;br&gt;//&lt;br /&gt;&lt;br&gt;// Map ADC values from the stylus to MIDI note values by &lt;br /&gt;&lt;br&gt;// looking for the scale[] entry which lies closest to the&lt;br /&gt;&lt;br&gt;// input value&lt;br /&gt;&lt;br&gt;//&lt;br /&gt;&lt;br&gt;char getNote(int input)&lt;br /&gt;&lt;br&gt;{&lt;br /&gt;&lt;br&gt;    for(int i = 0; i &amp;lt; NUM_PADS; ++i)&lt;br /&gt;&lt;br&gt;    {&lt;br /&gt;&lt;br&gt;      int lo = 0;&lt;br /&gt;&lt;br&gt;      int hi = 0x3ff;&lt;br /&gt;&lt;br&gt;      if(i&amp;gt;0)&lt;br /&gt;&lt;br&gt;      {&lt;br /&gt;&lt;br&gt;        lo = (scale[i-1] + scale[i]) / 2;&lt;br /&gt;&lt;br&gt;      }&lt;br /&gt;&lt;br&gt;      if(i&amp;lt;NUM_PADS)&lt;br /&gt;&lt;br&gt;      {&lt;br /&gt;&lt;br&gt;        hi = (scale[i] + scale[i+1]) / 2;&lt;br /&gt;&lt;br&gt;      }&lt;br /&gt;&lt;br&gt;      if(input &amp;gt;=lo &amp;amp;&amp;amp; input &amp;lt;=hi)&lt;br /&gt;&lt;br&gt;      {&lt;br /&gt;&lt;br&gt;        if(i==NUM_PADS)&lt;br /&gt;&lt;br&gt;          return NO_NOTE;&lt;br /&gt;&lt;br&gt;        return baseNote+i;&lt;br /&gt;&lt;br&gt;      }&lt;br /&gt;&lt;br&gt;    }&lt;br /&gt;&lt;br&gt;    return NO_NOTE;&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;// main&lt;br /&gt;&lt;br&gt;//&lt;br /&gt;&lt;br&gt;// Where program starts running!&lt;br /&gt;&lt;br&gt;//&lt;br /&gt;&lt;br&gt;void main()&lt;br /&gt;&lt;br&gt;{ &lt;br /&gt;&lt;br&gt; // osc control / 8MHz / internal&lt;br /&gt;&lt;br&gt; osccon = 0b01110001;&lt;br /&gt;&lt;br&gt; &lt;br /&gt;&lt;br&gt; // timer0... configure source and prescaler&lt;br /&gt;&lt;br&gt; // port A weak pull ups enabled&lt;br /&gt;&lt;br&gt; option_reg = 0b00000011;&lt;br /&gt;&lt;br&gt; &lt;br /&gt;&lt;br&gt; // enable pull ups on each button&lt;br /&gt;&lt;br&gt; wpua = 0b00110001;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt; // turn off the comparator to allow digital IO on CIO pins&lt;br /&gt;&lt;br&gt; cmcon0 = 7;               &lt;br /&gt;&lt;br&gt; &lt;br /&gt;&lt;br&gt; // set data direction on each pin       &lt;br /&gt;&lt;br&gt; trisa = 0b00110101;              &lt;br /&gt;&lt;br&gt; trisc = 0b00001110;              &lt;br /&gt;&lt;br&gt; &lt;br /&gt;&lt;br&gt; // set up the analog input pins&lt;br /&gt;&lt;br&gt; ansel = 0b11100100;&lt;br /&gt;&lt;br&gt;  &lt;br /&gt;&lt;br&gt; // turn on the ADC&lt;br /&gt;&lt;br&gt; adcon1=0b00100000; //fOSC/32&lt;br /&gt;&lt;br&gt; adcon0=0b10000001; // Right justify / Vdd / AD on&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt; // start up the serial port&lt;br /&gt;&lt;br&gt; init_usart();&lt;br /&gt;&lt;br&gt; &lt;br /&gt;&lt;br&gt; // ensure that the initial aquisition is completed&lt;br /&gt;&lt;br&gt; // for all analog inputs that we're using&lt;br /&gt;&lt;br&gt; adcInitComplete = 0;&lt;br /&gt;&lt;br&gt; while(!adcInitComplete)&lt;br /&gt;&lt;br&gt;  doADC();&lt;br /&gt;&lt;br&gt; &lt;br /&gt;&lt;br&gt; &lt;br /&gt;&lt;br&gt; //char buttons = 0;&lt;br /&gt;&lt;br&gt; char debounce = 0; &lt;br /&gt;&lt;br&gt; char lastNote = NO_NOTE;&lt;br /&gt;&lt;br&gt; int lastPitchBend = -1;&lt;br /&gt;&lt;br&gt; int lastModWheel = -1;&lt;br /&gt;&lt;br&gt; int value;&lt;br /&gt;&lt;br&gt; int diff;&lt;br /&gt;&lt;br&gt; for(;;)&lt;br /&gt;&lt;br&gt; {&lt;br /&gt;&lt;br&gt;  // the debounce variable makes sure that user&lt;br /&gt;&lt;br&gt;  // has release buttons for a period of time before&lt;br /&gt;&lt;br&gt;  // a new press on the button can be registered.&lt;br /&gt;&lt;br&gt;  // handles possibility of &amp;quot;switch bounce&amp;quot;&lt;br /&gt;&lt;br&gt;  &lt;br /&gt;&lt;br&gt;  // Buttons are pulled up and touch ground when &lt;br /&gt;&lt;br&gt;  // pressed, so the pin reads low when the button&lt;br /&gt;&lt;br&gt;  // is being pressed&lt;br /&gt;&lt;br&gt;  if(debounce &amp;gt; 0)&lt;br /&gt;&lt;br&gt;  {&lt;br /&gt;&lt;br&gt;   if(P_UP&amp;amp;&amp;amp;P_DN)&lt;br /&gt;&lt;br&gt;    --debounce;&lt;br /&gt;&lt;br&gt;   &lt;br /&gt;&lt;br&gt;  }&lt;br /&gt;&lt;br&gt;  else&lt;br /&gt;&lt;br&gt;  {   &lt;br /&gt;&lt;br&gt;   if(!P_UP)&lt;br /&gt;&lt;br&gt;   {&lt;br /&gt;&lt;br&gt;    // octave shift UP&lt;br /&gt;&lt;br&gt;    if(baseNote &amp;lt; 103)&lt;br /&gt;&lt;br&gt;     baseNote+=12;&lt;br /&gt;&lt;br&gt;    debounce = BUTTON_DEBOUNCE;&lt;br /&gt;&lt;br&gt;   }&lt;br /&gt;&lt;br&gt;   else if(!P_DN)&lt;br /&gt;&lt;br&gt;   {&lt;br /&gt;&lt;br&gt;    // octave shift DOWN&lt;br /&gt;&lt;br&gt;    if(baseNote &amp;gt; 12)&lt;br /&gt;&lt;br&gt;     baseNote-=12;&lt;br /&gt;&lt;br&gt;    debounce = BUTTON_DEBOUNCE;&lt;br /&gt;&lt;br&gt;   }&lt;br /&gt;&lt;br&gt;  }&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;  // poll the ADCs&lt;br /&gt;&lt;br&gt;  doADC();&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;  // check for a new note being played&lt;br /&gt;&lt;br&gt;  char note = getNote(adcResult[ADC_KBD]);&lt;br /&gt;&lt;br&gt;  if(note != lastNote)&lt;br /&gt;&lt;br&gt;  {&lt;br /&gt;&lt;br&gt;   // do we need to kill the previous note?&lt;br /&gt;&lt;br&gt;   if(lastNote != NO_NOTE &amp;amp;&amp;amp; P_HOLD)&lt;br /&gt;&lt;br&gt;   {&lt;br /&gt;&lt;br&gt;    // make it so!&lt;br /&gt;&lt;br&gt;    startNote(0,lastNote,0);&lt;br /&gt;&lt;br&gt;   }&lt;br /&gt;&lt;br&gt;   // is a new note playing (rather than stylus&lt;br /&gt;&lt;br&gt;   // removed from keyboard?)&lt;br /&gt;&lt;br&gt;   if(note != NO_NOTE)&lt;br /&gt;&lt;br&gt;   {&lt;br /&gt;&lt;br&gt;    // play a note with appropriate velocity&lt;br /&gt;&lt;br&gt;    char velocity = (adcResult[ADC_VEL]&amp;gt;&amp;gt;3)&amp;amp;0x7f;&lt;br /&gt;&lt;br&gt;    startNote(0,note,velocity);&lt;br /&gt;&lt;br&gt;   }&lt;br /&gt;&lt;br&gt;   lastNote = note;    &lt;br /&gt;&lt;br&gt;  }&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;  // check for change in pitchbend which is &lt;br /&gt;&lt;br&gt;  // outside the &amp;quot;noise&amp;quot; tolerance&lt;br /&gt;&lt;br&gt;  value = adcResult[ADC_PBD];&lt;br /&gt;&lt;br&gt;  diff = value - lastPitchBend;&lt;br /&gt;&lt;br&gt;  if(diff*diff &amp;gt; (PBD_TOL*PBD_TOL))&lt;br /&gt;&lt;br&gt;  {&lt;br /&gt;&lt;br&gt;   // Send MIDI pitchbend.. this has a 14-bit&lt;br /&gt;&lt;br&gt;   // data value&lt;br /&gt;&lt;br&gt;   pitchBend(0, value&amp;lt;&amp;lt;4); &lt;br /&gt;&lt;br&gt;   lastPitchBend = value;&lt;br /&gt;&lt;br&gt;  }&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;  // check for change in modwheel which is &lt;br /&gt;&lt;br&gt;  // outside the &amp;quot;noise&amp;quot; tolerance&lt;br /&gt;&lt;br&gt;  value = adcResult[ADC_MOD]&amp;gt;&amp;gt;3;&lt;br /&gt;&lt;br&gt;  diff = value - lastModWheel;&lt;br /&gt;&lt;br&gt;  if(diff*diff &amp;gt; (MOD_TOL*MOD_TOL))&lt;br /&gt;&lt;br&gt;  {&lt;br /&gt;&lt;br&gt;   // Send MIDI continuous controller message&lt;br /&gt;&lt;br&gt;   // for controller #1 (mod wheel) which has&lt;br /&gt;&lt;br&gt;   // 7 bit data value&lt;br /&gt;&lt;br&gt;   sendController(0, 1, value);&lt;br /&gt;&lt;br&gt;   lastModWheel = value;&lt;br /&gt;&lt;br&gt;  } &lt;br /&gt;&lt;br&gt; }&lt;br /&gt;&lt;br&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-9166906626926238759?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/9166906626926238759/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2010/02/stylophone-midi-controller.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/9166906626926238759'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/9166906626926238759'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2010/02/stylophone-midi-controller.html' title='Stylophone MIDI controller'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_rn0sSfRNtpI/S4FwjT3ephI/AAAAAAAABIQ/RHwVrl05wAQ/s72-c/st4.JPG' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-7962873746348145781</id><published>2010-02-10T13:03:00.000-08:00</published><updated>2010-02-10T13:19:38.409-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='electronics'/><category scheme='http://www.blogger.com/atom/ns#' term='pic'/><title type='text'>DIY Games Console</title><content type='html'>Another PIC project... this one using a 14-pin 16F688 and playing a version of "Breakout". I might see if I can get a convincing version of "Space Invaders" to run on that 8x8 matrix too....&lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/Hkp1e93d4Us&amp;hl=en_US&amp;fs=1&amp;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/Hkp1e93d4Us&amp;hl=en_US&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Usual setup of 74HC595 shift registers (x3) and ULN2803 NPN transistor arrays (x2). Columns are driven directly thru 100R resistors from one of the 595's... rows alternate red LEDs/green LEDs and are driven via 2 x chained 595's (data out from one goes to data in on the other) which in turn drive the NPN arrays, so only 5 I/O's from the MCU are needed to drive the display.. &lt;br /&gt;&lt;br /&gt;- Data in for the 595 driving the columns&lt;br /&gt;- Shift clock for the 595 driving the columns&lt;br /&gt;- Data in for the first of chained 595's driving the rows&lt;br /&gt;- Shift clock for the pair of 595's driving the columns&lt;br /&gt;- Store clock line for all 3 x 595's&lt;br /&gt;&lt;br /&gt;There are 4 buttons: 3 are connected to PIC I/O for controlling game (only 2 used for Breakout game) and other is MCU reset (grounds MCLR#). 12k pull up resistors on all 4 lines.&lt;br /&gt;&lt;br /&gt;The piezo buzzer is connected to the remaining I/O via a 0.1uF capacitor.&lt;br /&gt;&lt;br /&gt;The LED matrix was from Sure Electronics (on eBay).. I got 10 of them for about £10. It is red/green but by driving both you get orange.&lt;br /&gt;&lt;br /&gt;Here is the PIC code&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;#include&amp;nbsp;&amp;lt;system.h&amp;gt;&lt;br /&gt;#include&amp;nbsp;&amp;lt;memory.h&amp;gt;&lt;br /&gt;&lt;br /&gt;//&amp;nbsp;Config&amp;nbsp;bits&lt;br /&gt;#pragma&amp;nbsp;DATA&amp;nbsp;_CONFIG,&amp;nbsp;_WDT_OFF&amp;nbsp;&amp;&amp;nbsp;_INTRC_OSC_NOCLKOUT&amp;nbsp;&lt;br /&gt;&lt;br /&gt;//&amp;nbsp;Clock&amp;nbsp;freq&amp;nbsp;(for&amp;nbsp;SourceBoost&amp;nbsp;delayt&amp;nbsp;functions)&lt;br /&gt;#pragma&amp;nbsp;CLOCK_FREQ&amp;nbsp;8000000&lt;br /&gt;&lt;br /&gt;typedef&amp;nbsp;unsigned&amp;nbsp;char&amp;nbsp;byte;&lt;br /&gt;&lt;br /&gt;//&amp;nbsp;define&amp;nbsp;IO&amp;nbsp;ports&lt;br /&gt;#define&amp;nbsp;P_STORE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; porta.2&lt;br /&gt;#define&amp;nbsp;P_DT_ROW&amp;nbsp;&amp;nbsp;&amp;nbsp; porta.4&lt;br /&gt;#define&amp;nbsp;P_SH_ROW&amp;nbsp;&amp;nbsp;&amp;nbsp; porta.5&lt;br /&gt;#define&amp;nbsp;P_DT_COL&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;portc.0&lt;br /&gt;#define&amp;nbsp;P_SH_COL&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;portc.1&lt;br /&gt;#define&amp;nbsp;P_BUTTON3 portc.5&lt;br /&gt;#define&amp;nbsp;P_SPEAKER portc.3&lt;br /&gt;#define&amp;nbsp;P_BUTTON1 portc.4&lt;br /&gt;#define&amp;nbsp;P_BUTTON2 portc.2&lt;br /&gt;&lt;br /&gt;//&amp;nbsp;define&amp;nbsp;IO&amp;nbsp;port&amp;nbsp;direction&lt;br /&gt;#define&amp;nbsp;P_TRISA&amp;nbsp;0b00000000&lt;br /&gt;#define&amp;nbsp;P_TRISC&amp;nbsp;0b00110100&lt;br /&gt;&lt;br /&gt;//&amp;nbsp;macro&amp;nbsp;defs&lt;br /&gt;#define&amp;nbsp;SET_RED(x,y)&amp;nbsp;disp[y]|=1&amp;lt;&amp;lt;(7-(x))&lt;br /&gt;#define&amp;nbsp;SET_GREEN(x,y)&amp;nbsp;disp[8+(y)]|=1&amp;lt;&amp;lt;(7-(x))&lt;br /&gt;#define&amp;nbsp;SET_ORANGE(x,y)&amp;nbsp;SET_RED(x,y);&amp;nbsp;SET_GREEN(x,y)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;#define&amp;nbsp;BUTTON_DEBOUNCE&amp;nbsp;2&lt;br /&gt;&lt;br /&gt;//&amp;nbsp;info&amp;nbsp;used&amp;nbsp;by&amp;nbsp;the&amp;nbsp;interrupt&amp;nbsp;handler&lt;br /&gt;byte&amp;nbsp;soundPhase&amp;nbsp;=&amp;nbsp;0;&lt;br /&gt;byte&amp;nbsp;soundPeriod&amp;nbsp;=&amp;nbsp;&amp;nbsp;100;&lt;br /&gt;byte&amp;nbsp;soundDur&amp;nbsp;=&amp;nbsp;0;&lt;br /&gt;&lt;br /&gt;//&amp;nbsp;display&amp;nbsp;buffer&amp;nbsp;(rows&amp;nbsp;0-7&amp;nbsp;for&amp;nbsp;red,&amp;nbsp;8-15&amp;nbsp;for&amp;nbsp;green)&lt;br /&gt;byte&amp;nbsp;disp[16];&lt;br /&gt;&lt;br /&gt;//////////////////////////////////////////////////////&lt;br /&gt;//&lt;br /&gt;//&amp;nbsp;interrupt&amp;nbsp;handler&amp;nbsp;&lt;br /&gt;//&lt;br /&gt;//&amp;nbsp;timer0&amp;nbsp;interrupt&amp;nbsp;is&amp;nbsp;used&amp;nbsp;to&amp;nbsp;drive&amp;nbsp;the&amp;nbsp;piezo&amp;nbsp;speaker&lt;br /&gt;//&lt;br /&gt;void&amp;nbsp;interrupt(&amp;nbsp;void&amp;nbsp;)&lt;br /&gt;{&lt;br /&gt; //&amp;nbsp;check&amp;nbsp;if&amp;nbsp;this&amp;nbsp;is&amp;nbsp;timer0&amp;nbsp;overflow&amp;nbsp;event&lt;br /&gt; if(&amp;nbsp;intcon.2&amp;nbsp;)&lt;br /&gt; {&lt;br /&gt;  //&amp;nbsp;drive&amp;nbsp;the&amp;nbsp;piezo&amp;nbsp;sounder&lt;br /&gt;  soundPhase=!soundPhase;&lt;br /&gt;  P_SPEAKER&amp;nbsp;=&amp;nbsp;soundPhase?1:0;  &lt;br /&gt;  &lt;br /&gt;  //&amp;nbsp;still&amp;nbsp;sounding?  &lt;br /&gt;  if(!soundDur)&lt;br /&gt;  {&lt;br /&gt;   //&amp;nbsp;stop&amp;nbsp;the&amp;nbsp;interrupt..&amp;nbsp;killing&amp;nbsp;sound&lt;br /&gt;   intcon.5&amp;nbsp;=&amp;nbsp;0; &lt;br /&gt;  }&lt;br /&gt;  else&lt;br /&gt;  {&lt;br /&gt;   //&amp;nbsp;still&amp;nbsp;sounding&lt;br /&gt;   --soundDur;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  //&amp;nbsp;setup&amp;nbsp;the&amp;nbsp;next&amp;nbsp;timer&amp;nbsp;interrupt&lt;br /&gt;  tmr0=soundPeriod;&lt;br /&gt;  &lt;br /&gt;  //&amp;nbsp;clear&amp;nbsp;interrupt&amp;nbsp;flag&lt;br /&gt;  intcon.2&amp;nbsp;=&amp;nbsp;0;&lt;br /&gt;   &lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//////////////////////////////////////////////////////&lt;br /&gt;//&lt;br /&gt;//&amp;nbsp;beep&lt;br /&gt;//&amp;nbsp;&lt;br /&gt;//&amp;nbsp;start&amp;nbsp;a&amp;nbsp;sound&amp;nbsp;playing&lt;br /&gt;//&lt;br /&gt;void&amp;nbsp;beep(byte&amp;nbsp;pitch,&amp;nbsp;byte&amp;nbsp;dur)&lt;br /&gt;{&lt;br /&gt; soundPeriod&amp;nbsp;=&amp;nbsp;255-pitch;&lt;br /&gt; soundDur&amp;nbsp;=&amp;nbsp;dur;&lt;br /&gt; intcon.5&amp;nbsp;=&amp;nbsp;1; &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//////////////////////////////////////////////////////&lt;br /&gt;//&lt;br /&gt;//&amp;nbsp;refresh&lt;br /&gt;//&amp;nbsp;&lt;br /&gt;//&amp;nbsp;update&amp;nbsp;the&amp;nbsp;LED&amp;nbsp;matrix&amp;nbsp;based&amp;nbsp;on&amp;nbsp;content&amp;nbsp;of&amp;nbsp;the&amp;nbsp;&lt;br /&gt;//&amp;nbsp;disp[]&amp;nbsp;array&lt;br /&gt;//&lt;br /&gt;void&amp;nbsp;refresh()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;int&amp;nbsp;i;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;//&amp;nbsp;clear&amp;nbsp;vertical&amp;nbsp;shift&amp;nbsp;register&amp;nbsp;and&amp;nbsp;load&amp;nbsp;a&amp;nbsp;logic&amp;nbsp;1&amp;nbsp;at&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;//&amp;nbsp;bit&amp;nbsp;position&amp;nbsp;0.&amp;nbsp;This&amp;nbsp;bit&amp;nbsp;will&amp;nbsp;be&amp;nbsp;shifted&amp;nbsp;along&amp;nbsp;to&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;//&amp;nbsp;drive&amp;nbsp;each&amp;nbsp;row&amp;nbsp;of&amp;nbsp;the&amp;nbsp;LED&amp;nbsp;matrix&amp;nbsp;in&amp;nbsp;turn&lt;br /&gt;&amp;nbsp;&amp;nbsp;for(i=0;i&amp;lt;16;++i)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;P_SH_ROW&amp;nbsp;=&amp;nbsp;0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;P_DT_ROW&amp;nbsp;=&amp;nbsp;(i==15)?1:0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;P_SH_ROW&amp;nbsp;=&amp;nbsp;1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;P_DT_ROW&amp;nbsp;=&amp;nbsp;0;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;//&amp;nbsp;for&amp;nbsp;each&amp;nbsp;row&amp;nbsp;of&amp;nbsp;data&amp;nbsp;(8&amp;nbsp;x&amp;nbsp;red,&amp;nbsp;8&amp;nbsp;x&amp;nbsp;green)&lt;br /&gt;&amp;nbsp;&amp;nbsp;for(i=0;i&amp;lt;16;++i)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt; //&amp;nbsp;this&amp;nbsp;cross&amp;nbsp;reference&amp;nbsp;of&amp;nbsp;vertical&amp;nbsp;bit&amp;nbsp;position&amp;nbsp;to&amp;nbsp;row&amp;nbsp;of&amp;nbsp;the&amp;nbsp;&lt;br /&gt; //&amp;nbsp;disp[]&amp;nbsp;array&amp;nbsp;is&amp;nbsp;used&amp;nbsp;since&amp;nbsp;the&amp;nbsp;matrix&amp;nbsp;is&amp;nbsp;connected&amp;nbsp;for&amp;nbsp;wiring&lt;br /&gt; //&amp;nbsp;convenience&amp;nbsp;and&amp;nbsp;the&amp;nbsp;order&amp;nbsp;of&amp;nbsp;rows&amp;nbsp;is&amp;nbsp;different&lt;br /&gt; byte&amp;nbsp;ix[16]&amp;nbsp;=&amp;nbsp;{ 15, 7,&amp;nbsp;14,&amp;nbsp;6,&amp;nbsp;13,&amp;nbsp;5,&amp;nbsp;12,&amp;nbsp;4,&amp;nbsp;0,&amp;nbsp;8,&amp;nbsp;1,&amp;nbsp;9,&amp;nbsp;2,&amp;nbsp;10,&amp;nbsp;3,&amp;nbsp;11&amp;nbsp;};  &lt;br /&gt; &lt;br /&gt; //&amp;nbsp;look&amp;nbsp;up&amp;nbsp;the&amp;nbsp;row&amp;nbsp;data&amp;nbsp;byte&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;byte&amp;nbsp;d=disp[ix[i]];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;store&amp;nbsp;clock&amp;nbsp;low&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;P_STORE&amp;nbsp;=&amp;nbsp;0;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;load&amp;nbsp;the&amp;nbsp;8&amp;nbsp;bits&amp;nbsp;of&amp;nbsp;data&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for(int&amp;nbsp;j=0;j&amp;lt;8;++j)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;shift&amp;nbsp;a&amp;nbsp;column&amp;nbsp;bit&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;P_SH_COL&amp;nbsp;=&amp;nbsp;0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;P_DT_COL&amp;nbsp;=&amp;nbsp;d&amp;1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;P_SH_COL&amp;nbsp;=&amp;nbsp;1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;d&amp;gt;&amp;gt;=1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;store&amp;nbsp;clock&amp;nbsp;high..&amp;nbsp;row&amp;nbsp;data&amp;nbsp;is&amp;nbsp;clocked&amp;nbsp;to&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;the&amp;nbsp;output&amp;nbsp;of&amp;nbsp;shift&amp;nbsp;registers,&amp;nbsp;simultaneously&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;with&amp;nbsp;the&amp;nbsp;clocking&amp;nbsp;in&amp;nbsp;of&amp;nbsp;a&amp;nbsp;new&amp;nbsp;scan&amp;nbsp;row&amp;nbsp;in&amp;nbsp;the&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;vertical&amp;nbsp;shift&amp;nbsp;registers&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;P_STORE&amp;nbsp;=&amp;nbsp;1;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;set&amp;nbsp;pins&amp;nbsp;low&amp;nbsp;again&amp;nbsp;and&amp;nbsp;add&amp;nbsp;a&amp;nbsp;&amp;quot;display&amp;nbsp;delay&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;while&amp;nbsp;the&amp;nbsp;row&amp;nbsp;data&amp;nbsp;is&amp;nbsp;shown,&amp;nbsp;before&amp;nbsp;it&amp;nbsp;is&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;hidden&amp;nbsp;again&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;P_SH_ROW&amp;nbsp;=&amp;nbsp;0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;P_DT_COL&amp;nbsp;=&amp;nbsp;0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;delay_ms(1);&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;P_SH_ROW&amp;nbsp;=&amp;nbsp;1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;P_STORE&amp;nbsp;=&amp;nbsp;0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;P_SH_COL&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;P_SH_ROW&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;&amp;nbsp;&lt;br /&gt;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;void&amp;nbsp;breakout()&lt;br /&gt;{&lt;br /&gt; int&amp;nbsp;i;&lt;br /&gt; byte&amp;nbsp;bricks[8];&lt;br /&gt; byte&amp;nbsp;rowsOfBricks=3;&lt;br /&gt; byte&amp;nbsp;speed&amp;nbsp;=&amp;nbsp;250;&lt;br /&gt; byte&amp;nbsp;lives=3;&lt;br /&gt; &lt;br /&gt; //&amp;nbsp;loop&amp;nbsp;for&amp;nbsp;each&amp;nbsp;level&lt;br /&gt; for(;;)&lt;br /&gt; {&lt;br /&gt;  //&amp;nbsp;setup&amp;nbsp;the&amp;nbsp;wall&lt;br /&gt;  memset(bricks,0,sizeof(bricks));&lt;br /&gt;  memset(bricks,255,rowsOfBricks);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;  //&amp;nbsp;init&amp;nbsp;variables&lt;br /&gt;  char&amp;nbsp;x=3; //&amp;nbsp;position&amp;nbsp;of&amp;nbsp;bat&lt;br /&gt;  char&amp;nbsp;bx=4; //&amp;nbsp;position&amp;nbsp;of&amp;nbsp;ball&lt;br /&gt;  char&amp;nbsp;by=6;&lt;br /&gt;  char&amp;nbsp;dx=0; //&amp;nbsp;direction&amp;nbsp;of&amp;nbsp;ball&lt;br /&gt;  char&amp;nbsp;dy=-1;&lt;br /&gt;   &lt;br /&gt;  //&amp;nbsp;ball&amp;nbsp;movement&amp;nbsp;counter.&amp;nbsp;Set&amp;nbsp;to&amp;nbsp;a&amp;nbsp;value&amp;nbsp;to&lt;br /&gt;  //&amp;nbsp;give&amp;nbsp;a&amp;nbsp;short&amp;nbsp;delay&amp;nbsp;at&amp;nbsp;the&amp;nbsp;start&amp;nbsp;of&amp;nbsp;a&amp;nbsp;level&lt;br /&gt;  byte&amp;nbsp;bc&amp;nbsp;=&amp;nbsp;100;&amp;nbsp;&amp;nbsp;&lt;br /&gt;  &lt;br /&gt;  //&amp;nbsp;counter&amp;nbsp;used&amp;nbsp;to&amp;nbsp;debounce&amp;nbsp;the&amp;nbsp;movement&amp;nbsp;buttons&lt;br /&gt;  byte&amp;nbsp;buttonDebounce&amp;nbsp;=&amp;nbsp;0;&lt;br /&gt;&lt;br /&gt;  //&amp;nbsp;loop&amp;nbsp;until&amp;nbsp;level&amp;nbsp;is&amp;nbsp;complete&lt;br /&gt;  for(;;)&lt;br /&gt;  {   &lt;br /&gt;   //&amp;nbsp;do&amp;nbsp;we&amp;nbsp;need&amp;nbsp;to&amp;nbsp;move&amp;nbsp;the&amp;nbsp;ball?&lt;br /&gt;   if(++bc&amp;nbsp;==&amp;nbsp;0)&lt;br /&gt;   {&lt;br /&gt;    //&amp;nbsp;reset&amp;nbsp;the&amp;nbsp;counter&lt;br /&gt;    bc&amp;nbsp;=&amp;nbsp;speed;&lt;br /&gt;    &lt;br /&gt;    //&amp;nbsp;calc&amp;nbsp;next&amp;nbsp;ball&amp;nbsp;position&lt;br /&gt;    char&amp;nbsp;nx&amp;nbsp;=&amp;nbsp;bx&amp;nbsp;+&amp;nbsp;dx;&lt;br /&gt;    char&amp;nbsp;ny&amp;nbsp;=&amp;nbsp;by&amp;nbsp;+&amp;nbsp;dy;&lt;br /&gt;    if(nx&amp;lt;0||nx&amp;gt;7) //&amp;nbsp;off&amp;nbsp;screen&amp;nbsp;left&amp;nbsp;or&amp;nbsp;right&lt;br /&gt;    {&lt;br /&gt;     dx=-dx;&lt;br /&gt;     nx=bx;&lt;br /&gt;    }&lt;br /&gt;    if(ny&amp;lt;0||ny&amp;gt;7) //&amp;nbsp;off&amp;nbsp;screen&amp;nbsp;top&amp;nbsp;or&amp;nbsp;bottom&lt;br /&gt;    {&lt;br /&gt;     dy=-dy;&lt;br /&gt;     ny=by;&lt;br /&gt;    }&lt;br /&gt;    if(ny==7) //&amp;nbsp;on&amp;nbsp;the&amp;nbsp;bottom&amp;nbsp;row?&lt;br /&gt;    {&lt;br /&gt;     if(bx==x) //&amp;nbsp;flat&amp;nbsp;hit&amp;nbsp;left&amp;nbsp;side&lt;br /&gt;     {&lt;br /&gt;      if(dx&amp;gt;0)&amp;nbsp;dx=0;&amp;nbsp;else&amp;nbsp;dx=-1;&lt;br /&gt;      beep(200,50);   &lt;br /&gt;     }&lt;br /&gt;     else&amp;nbsp;if(bx==x+1) //&amp;nbsp;hit&amp;nbsp;right&amp;nbsp;side&lt;br /&gt;     {&lt;br /&gt;      if(dx&amp;lt;0)&amp;nbsp;dx=0;&amp;nbsp;else&amp;nbsp;dx=1;&lt;br /&gt;      beep(200,50);   &lt;br /&gt;     }&lt;br /&gt;     else&amp;nbsp;if(nx==x) //&amp;nbsp;hit&amp;nbsp;left&amp;nbsp;end&lt;br /&gt;     {&lt;br /&gt;      dx=-1;&lt;br /&gt;      beep(100,50);   &lt;br /&gt;     }&lt;br /&gt;     else&amp;nbsp;if(nx==x+1) //&amp;nbsp;hit&amp;nbsp;right&amp;nbsp;end&lt;br /&gt;     {&lt;br /&gt;      dx=1;&lt;br /&gt;      beep(100,50);   &lt;br /&gt;     }&lt;br /&gt;     else&lt;br /&gt;     {&lt;br /&gt;      //&amp;nbsp;ball&amp;nbsp;has&amp;nbsp;dropped&amp;nbsp;off&amp;nbsp;bottom&amp;nbsp;of&amp;nbsp;screen&lt;br /&gt;      for(i=0;i&amp;lt;3;++i)&lt;br /&gt;      {&lt;br /&gt;       //&amp;nbsp;death&amp;nbsp;routine&lt;br /&gt;       refresh();&lt;br /&gt;       beep(50,100);&lt;br /&gt;       delay_ms(100);&lt;br /&gt;       refresh();&lt;br /&gt;       beep(150,100);&lt;br /&gt;       delay_ms(100);&lt;br /&gt;      }&lt;br /&gt;      &lt;br /&gt;      //&amp;nbsp;lose&amp;nbsp;a&amp;nbsp;life&lt;br /&gt;      if(lives--&amp;nbsp;&amp;lt;=&amp;nbsp;0)&lt;br /&gt;      {&lt;br /&gt;       //&amp;nbsp;all&amp;nbsp;lives&amp;nbsp;gone&lt;br /&gt;       for(;;)&lt;br /&gt;       {&lt;br /&gt;        for(i=0;i&amp;lt;50;++i)&lt;br /&gt;         refresh();&lt;br /&gt;        delay_ms(500);&lt;br /&gt;       }&lt;br /&gt;      }&lt;br /&gt;      else&lt;br /&gt;      {&lt;br /&gt;       //&amp;nbsp;start&amp;nbsp;of&amp;nbsp;next&amp;nbsp;round&lt;br /&gt;       x=3;&lt;br /&gt;       bx=4;&lt;br /&gt;       by=6;&lt;br /&gt;       dx=0;&amp;nbsp;&amp;nbsp;    &lt;br /&gt;       bc=100;&lt;br /&gt;      }&lt;br /&gt;     }&lt;br /&gt;      &lt;br /&gt;     //&amp;nbsp;common&amp;nbsp;stuff&lt;br /&gt;     nx=bx;&lt;br /&gt;     ny=by;&lt;br /&gt;     dy=-1;&lt;br /&gt;    }&lt;br /&gt;  &lt;br /&gt;    //&amp;nbsp;move&amp;nbsp;the&amp;nbsp;ball&lt;br /&gt;    bx&amp;nbsp;=&amp;nbsp;nx;&lt;br /&gt;    by&amp;nbsp;=&amp;nbsp;ny;&lt;br /&gt;  &lt;br /&gt;    //&amp;nbsp;hit&amp;nbsp;a&amp;nbsp;brick?&lt;br /&gt;    if(bricks[by]&amp;(1&amp;lt;&amp;lt;(7-bx)))&lt;br /&gt;    {&lt;br /&gt;     //&amp;nbsp;remove&amp;nbsp;the&amp;nbsp;brick&amp;nbsp;and&amp;nbsp;bounce&lt;br /&gt;     bricks[by]&amp;=~(1&amp;lt;&amp;lt;(7-bx));&lt;br /&gt;     dy=-dy; &lt;br /&gt;     beep(100,200);   &lt;br /&gt;      &lt;br /&gt;     //&amp;nbsp;any&amp;nbsp;bricks&amp;nbsp;left?&lt;br /&gt;     byte&amp;nbsp;allGone&amp;nbsp;=&amp;nbsp;1;&lt;br /&gt;     for(i=0;i&amp;lt;sizeof(bricks);++i)&lt;br /&gt;     {&lt;br /&gt;      if(bricks[i])&lt;br /&gt;      {&lt;br /&gt;       allGone=0;&lt;br /&gt;       break;&lt;br /&gt;      }&lt;br /&gt;     }&lt;br /&gt;      &lt;br /&gt;     //&amp;nbsp;end&amp;nbsp;of&amp;nbsp;level&lt;br /&gt;     if(allGone)&lt;br /&gt;     {&lt;br /&gt;      //&amp;nbsp;beep&lt;br /&gt;      for(i=0;i&amp;lt;10;++i)&lt;br /&gt;      {&lt;br /&gt;       beep(50,50);   &lt;br /&gt;       delay_ms(100);&lt;br /&gt;      }&lt;br /&gt;      &lt;br /&gt;      //&amp;nbsp;add&amp;nbsp;more&amp;nbsp;bricks&lt;br /&gt;      if(rowsOfBricks&amp;lt;5)&lt;br /&gt;      {&lt;br /&gt;       rowsOfBricks++;&lt;br /&gt;      }&lt;br /&gt;      else&lt;br /&gt;      {&lt;br /&gt;       //&amp;nbsp;or&amp;nbsp;make&amp;nbsp;it&amp;nbsp;faster&lt;br /&gt;       if(speed&amp;nbsp;&amp;lt;&amp;nbsp;254)&lt;br /&gt;        ++speed;&lt;br /&gt;      }       &lt;br /&gt;      break;&lt;br /&gt;     }    &lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;  &lt;br /&gt;   //&amp;nbsp;prepare&amp;nbsp;screen&amp;nbsp;buffer&lt;br /&gt;   memcpy(&amp;disp[0],&amp;nbsp;bricks,&amp;nbsp;sizeof(bricks));&lt;br /&gt;   memcpy(&amp;disp[8],&amp;nbsp;bricks,&amp;nbsp;sizeof(bricks));&lt;br /&gt;&lt;br /&gt;   //&amp;nbsp;show&amp;nbsp;ball&lt;br /&gt;   SET_RED(bx,by);&lt;br /&gt;    &lt;br /&gt;   //&amp;nbsp;show&amp;nbsp;bat&lt;br /&gt;   SET_GREEN(x,7);&lt;br /&gt;   SET_GREEN(x+1,7);&lt;br /&gt; &lt;br /&gt;   //&amp;nbsp;still&amp;nbsp;in&amp;nbsp;debounce&amp;nbsp;period?&lt;br /&gt;   if(buttonDebounce)&lt;br /&gt;   {&lt;br /&gt;    //&amp;nbsp;wait&amp;nbsp;for&amp;nbsp;button&amp;nbsp;release&lt;br /&gt;    if(P_BUTTON1&amp;nbsp;&amp;&amp;&amp;nbsp;P_BUTTON2&amp;nbsp;&amp;&amp;&amp;nbsp;P_BUTTON3)&lt;br /&gt;     buttonDebounce--;  &lt;br /&gt;   }&lt;br /&gt;   else&amp;nbsp;    &lt;br /&gt;   {&lt;br /&gt;    //&amp;nbsp;left?&lt;br /&gt;    if(!P_BUTTON1)&lt;br /&gt;    {&lt;br /&gt;     if(x&amp;gt;0)&amp;nbsp;x--;&lt;br /&gt;     buttonDebounce&amp;nbsp;=&amp;nbsp;BUTTON_DEBOUNCE;&lt;br /&gt;    }&lt;br /&gt;    //&amp;nbsp;right?&lt;br /&gt;    else&amp;nbsp;if(!P_BUTTON2)&lt;br /&gt;    {&lt;br /&gt;     if(x&amp;lt;6)&amp;nbsp;x++;&lt;br /&gt;     buttonDebounce&amp;nbsp;=&amp;nbsp;BUTTON_DEBOUNCE;&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   //&amp;nbsp;and&amp;nbsp;refresh&amp;nbsp;the&amp;nbsp;display&lt;br /&gt;   refresh();&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void&amp;nbsp;main()&lt;br /&gt;{&amp;nbsp;&lt;br /&gt; &lt;br /&gt; osccon&amp;nbsp;=&amp;nbsp;0b01110001; //&amp;nbsp;osc&amp;nbsp;control&amp;nbsp;/&amp;nbsp;8MHz&amp;nbsp;/&amp;nbsp;internal&lt;br /&gt; cmcon0&amp;nbsp;=&amp;nbsp;7;    //&amp;nbsp;comparator&amp;nbsp;off&lt;br /&gt; ansel=0;    //&amp;nbsp;digital&amp;nbsp;IO&lt;br /&gt;  &lt;br /&gt; trisa&amp;nbsp;=&amp;nbsp;P_TRISA;  //&amp;nbsp;port&amp;nbsp;A&amp;nbsp;I/O&amp;nbsp;direction&lt;br /&gt; trisc&amp;nbsp;=&amp;nbsp;P_TRISC;  //&amp;nbsp;port&amp;nbsp;C&amp;nbsp;I/O&amp;nbsp;direction&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt; porta&amp;nbsp;=&amp;nbsp;0;    //&amp;nbsp;clear&amp;nbsp;port&amp;nbsp;A&lt;br /&gt; portc&amp;nbsp;=&amp;nbsp;0;    //&amp;nbsp;clear&amp;nbsp;port&amp;nbsp;C&lt;br /&gt; &lt;br /&gt; option_reg&amp;nbsp;=&amp;nbsp;0b10000011; //&amp;nbsp;timer0...&amp;nbsp;configure&amp;nbsp;source&amp;nbsp;and&amp;nbsp;prescaler&lt;br /&gt; intcon.7&amp;nbsp;=&amp;nbsp;1;    //&amp;nbsp;GIE&amp;nbsp;-&amp;nbsp;enable&amp;nbsp;interrupts&lt;br /&gt; intcon.6&amp;nbsp;=&amp;nbsp;1;    //&amp;nbsp;PEIE&amp;nbsp;-&amp;nbsp;enable&amp;nbsp;interrupts&lt;br /&gt; intcon.5&amp;nbsp;=&amp;nbsp;0;    //&amp;nbsp;T0IE&amp;nbsp;-&amp;nbsp;timer&amp;nbsp;0&amp;nbsp;interrupts&amp;nbsp;diabled&amp;nbsp;for&amp;nbsp;now&lt;br /&gt; intcon.2&amp;nbsp;=&amp;nbsp;0;    //&amp;nbsp;T0IF&amp;nbsp;-&amp;nbsp;clear&amp;nbsp;timer&amp;nbsp;0&amp;nbsp;interrupt&amp;nbsp;flag&lt;br /&gt; &lt;br /&gt; breakout();&lt;br /&gt;}&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-7962873746348145781?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/7962873746348145781/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2010/02/diy-games-console.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/7962873746348145781'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/7962873746348145781'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2010/02/diy-games-console.html' title='DIY Games Console'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-6426841449164004503</id><published>2010-01-10T13:35:00.000-08:00</published><updated>2010-01-10T14:09:08.108-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lego'/><category scheme='http://www.blogger.com/atom/ns#' term='electronics'/><title type='text'>DIY radio controller for Lego</title><content type='html'>This was an experiment with a couple of Holtek remote control encoder and decoder chips (HT12E and HT12D) together with a cheap RF transmitter and receiver pair I picked up off ebay. OK, so the chips are not really designed for controlling models (more for opening your garage doors and so on) and lego's own IR controller would probably work better but its all good fun!&lt;br /&gt;&lt;br /&gt;The receiver connects up to the Lego Power Functions 9V battery box and drives 2 power functions motors independently with forward/stop/reverse control. I bought a couple of power functions extension cables to get the connectors.&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_rn0sSfRNtpI/S0pN97cqA7I/AAAAAAAABGo/adSeVotdtTs/s1600-h/P1108611.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 262px;" src="http://2.bp.blogspot.com/_rn0sSfRNtpI/S0pN97cqA7I/AAAAAAAABGo/adSeVotdtTs/s320/P1108611.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5425234427446428594" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_rn0sSfRNtpI/S0pOfIowiJI/AAAAAAAABHA/58Qq_3GRyC4/s1600-h/P1108612.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 211px;" src="http://1.bp.blogspot.com/_rn0sSfRNtpI/S0pOfIowiJI/AAAAAAAABHA/58Qq_3GRyC4/s320/P1108612.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5425234997922531474" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The receiver uses a cheap RF receiver module from ebay (I got receiver + transmitter for about £9) which is connected to the Holtek H12D. The address bits are all tied to ground and the data bits feed the 4 inputs of an L293D motor driver. A 7805 +5V regulator supplies the IC's and the RF receiver circuit (since the Lego 9V supply is too high for them)&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_rn0sSfRNtpI/S0pOPUOnDFI/AAAAAAAABGw/4V3viIsgqJQ/s1600-h/P1108613.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 302px; height: 320px;" src="http://1.bp.blogspot.com/_rn0sSfRNtpI/S0pOPUOnDFI/AAAAAAAABGw/4V3viIsgqJQ/s320/P1108613.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5425234726156176466" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The timing resistors on the H12D receiver are 100K + 12K in series. These pair with the transmitter's 1M + 470K (I'm not sure how good these selections are but it seems to work...)&lt;br /&gt;&lt;br /&gt;The transmitter simply drives the 4 data bits of the H12E with tactile switches (closed to ground, pull ups on open). The H12E is powered and transmit enabled all the time the transmitter is on (to make sure the "all buttons off" state is transmitted to stop the motors)&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_rn0sSfRNtpI/S0pOYtkpUCI/AAAAAAAABG4/bA-Rh9HaTHI/s1600-h/P1108610.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 314px; height: 320px;" src="http://4.bp.blogspot.com/_rn0sSfRNtpI/S0pOYtkpUCI/AAAAAAAABG4/bA-Rh9HaTHI/s320/P1108610.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5425234887578308642" /&gt;&lt;/a&gt;&lt;br /&gt;Since there is no proportional control its all a bit stop-start and sometimes I found the receiver got "stuck" while the car was spinning on the spot and I had to place the transmitter really close (I think the electrical noise from the motors might be to blame.. but I also suspect my timing resistors not be quite right)&lt;br /&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/FzfiUV41oHc&amp;hl=en_US&amp;fs=1&amp;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/FzfiUV41oHc&amp;hl=en_US&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-6426841449164004503?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/6426841449164004503/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2010/01/diy-radio-controller-for-lego.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/6426841449164004503'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/6426841449164004503'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2010/01/diy-radio-controller-for-lego.html' title='DIY radio controller for Lego'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_rn0sSfRNtpI/S0pN97cqA7I/AAAAAAAABGo/adSeVotdtTs/s72-c/P1108611.JPG' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-5810936961510248930</id><published>2010-01-06T02:30:00.000-08:00</published><updated>2010-01-06T02:36:38.383-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='launchpad'/><category scheme='http://www.blogger.com/atom/ns#' term='midi'/><title type='text'>PLAYPAD program for Launchpad fun</title><content type='html'>I've been promising it for a while but I finally got round to making a download for other people to try out my Launchpad MIDI experiments. &lt;br /&gt;&lt;br /&gt;Downloads and description are here...&lt;br /&gt;&lt;a href="http://sites.google.com/site/skriyl/Home/launchpad-playpad-download"&gt;http://sites.google.com/site/skriyl/Home/launchpad-playpad-download&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Check out the mindblowing visuals...&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_rn0sSfRNtpI/S0Rm3lykyEI/AAAAAAAABGg/eIFI8Sosh8k/s1600-h/playpad.gif"&gt;&lt;img id="BLOGGER_PHOTO_ID_5423572956483995714" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 320px; CURSOR: hand; HEIGHT: 162px; TEXT-ALIGN: center" alt="" src="http://1.bp.blogspot.com/_rn0sSfRNtpI/S0Rm3lykyEI/AAAAAAAABGg/eIFI8Sosh8k/s320/playpad.gif" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-5810936961510248930?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/5810936961510248930/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2010/01/playpad-program-for-launchpad-fun.html#comment-form' title='17 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/5810936961510248930'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/5810936961510248930'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2010/01/playpad-program-for-launchpad-fun.html' title='PLAYPAD program for Launchpad fun'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_rn0sSfRNtpI/S0Rm3lykyEI/AAAAAAAABGg/eIFI8Sosh8k/s72-c/playpad.gif' height='72' width='72'/><thr:total>17</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-5695616645791242591</id><published>2010-01-03T14:24:00.000-08:00</published><updated>2010-01-05T01:20:48.425-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='electronics'/><category scheme='http://www.blogger.com/atom/ns#' term='pic'/><title type='text'>Make your own annoying musical greetings card!</title><content type='html'>I love the tiny 8 pin PICs from Microchip.. an entire computer in a package the size of a fingernail that costs pennies and can be programmed from your PC using just C and run on a watch battery. They're great.. but its taken me a while to find a use for one.&lt;br /&gt;&lt;br /&gt;This was a quick and silly project to play a tune on a piezo sounder. Hopefully the comments in the source code included below are enough to work out whats going on.. this was actually a great project to work out how to use timers and interrupts on PICs, which I'd not done before. There were a few little hoops to jump through to fit the melody data into the tiny EEPROM space (128 bytes) of the 12F629.&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/QmeGl0uSvHI&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/QmeGl0uSvHI&amp;hl=en_US&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;I used SourceBoost C and PICkit 2 USB programmer.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#include &amp;lt;system.h&amp;gt;&lt;br /&gt;&lt;br /&gt;// config word; internal oscillator, watchdog and master clear are off&lt;br /&gt;#pragma DATA _CONFIG, _INTRC_OSC_NOCLKOUT &amp; _WDT_OFF &amp; _MCLRE_OFF&lt;br /&gt;&lt;br /&gt;//Set clock frequency&lt;br /&gt;#pragma CLOCK_FREQ 4000000&lt;br /&gt;&lt;br /&gt;// This is the tune data... high nybble of each byte is the relative duration (1-16) and the&lt;br /&gt;// low nybble is the note (1-16) or a break (0). Note numbers are mapped to frequencies in &lt;br /&gt;// code. A melody can use only 15 different notes in total and the total number of bytes that&lt;br /&gt;// can be stored in EEPROM on a PIC12F629 is 128. There is a null terminator at the end of the&lt;br /&gt;// melody data&lt;br /&gt;#pragma DATA _EEPROM, &lt;br /&gt;0x44, 0x20, 0x44, 0x10, 0x18, 0x16, 0x10, 0x14, 0x16, 0x10, 0x18, 0x1b, 0x10, 0x18, 0x16, 0x10, &lt;br /&gt;0x14, 0x41, 0x20, 0x41, 0x10, 0x15, 0x13, 0x10, 0x11, 0x13, 0x10, 0x15, 0x17, 0x10, 0x15, 0x13, &lt;br /&gt;0x10, 0x11, 0x44, 0x20, 0x44, 0x10, 0x18, 0x16, 0x10, 0x14, 0x16, 0x10, 0x18, 0x1b, 0x10, 0x18, &lt;br /&gt;0x16, 0x10, 0x24, 0x10, 0x1b, 0x1a, 0x10, 0x19, 0x18, 0x10, 0x17, 0x16, 0x10, 0x15, 0x14, 0x20, &lt;br /&gt;0x16, 0x20, 0x14, 0x10, 0x14, 0x16, 0x10, 0x17, 0x48, 0x20, 0x48, 0x10, 0x18, 0x19, 0x10, 0x1a, &lt;br /&gt;0x1b, 0x10, 0x1a, 0x19, 0x10, 0x18, 0x17, 0x10, 0x16, 0x15, 0x10, 0x16, 0x17, 0x10, 0x16, 0x15, &lt;br /&gt;0x10, 0x11, 0x12, 0x10, 0x13, 0x44, 0x20, 0x44, 0x20, 0x44, 0x20, 0x44, 0x20, 0x24, 0x1b, 0x1a, &lt;br /&gt;0x10, 0x19, 0x18, 0x10, 0x17, 0x16, 0x10, 0x15, 0x34, 0x36, 0x44, 0x40, 0x00&lt;br /&gt;&lt;br /&gt;typedef unsigned char byte;&lt;br /&gt;&lt;br /&gt;// info used by the interrupt handler&lt;br /&gt;byte next_tmr1h = 0;&lt;br /&gt;byte next_tmr1l = 0;&lt;br /&gt;byte wave = 0;&lt;br /&gt;&lt;br /&gt;// interrupt handler called when the timer1 overflows&lt;br /&gt;void interrupt( void )&lt;br /&gt;{&lt;br /&gt; // check if this is timer1 overflow event&lt;br /&gt; if( pir1 &amp; (1 &lt;&lt; TMR1IF) )&lt;br /&gt; {&lt;br /&gt;  // set up the timer 1 counters so they will overflow &lt;br /&gt;  // again after the appropriate time delay&lt;br /&gt;  tmr1h = next_tmr1h;&lt;br /&gt;  tmr1l = next_tmr1l;&lt;br /&gt; &lt;br /&gt;  // toggle pin state GPIO5, which drives the piezo sounder&lt;br /&gt;  wave=!wave;&lt;br /&gt;  gpio = wave? 0b100000 : 0b000000;  &lt;br /&gt;  &lt;br /&gt;  //clear timer 1 interrupt bit&lt;br /&gt;  clear_bit( pir1, TMR1IF ); &lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void main( void )&lt;br /&gt;{&lt;br /&gt; // configure timer1 for interrupts / no prescaler&lt;br /&gt; t1con=0; &lt;br /&gt; intcon.6=1;&lt;br /&gt; intcon.7=1;&lt;br /&gt; pie1.0=1;&lt;br /&gt; clear_bit( pir1, TMR1IF ); //clear timer 1 interrupt bit&lt;br /&gt; &lt;br /&gt; // set up IO pins&lt;br /&gt; trisio = 0;&lt;br /&gt; gpio=0;&lt;br /&gt;&lt;br /&gt; // loop forever&lt;br /&gt; for(;;)&lt;br /&gt; {&lt;br /&gt;  byte addr = 0;&lt;br /&gt;  byte data = 0;&lt;br /&gt;  &lt;br /&gt;  // loop through the tune&lt;br /&gt;  for(;;)&lt;br /&gt;  {&lt;br /&gt;   // read byte from EEPROM&lt;br /&gt;   eeadr = addr;&lt;br /&gt;   eecon1.0 = 1;&lt;br /&gt;   data = eedata;&lt;br /&gt;   ++addr;&lt;br /&gt;&lt;br /&gt;   // a zero byte indicates end of the tune&lt;br /&gt;   if(!data || addr &gt; 0x7f)&lt;br /&gt;    break;&lt;br /&gt;    &lt;br /&gt;   // extract the note number from the low nybble&lt;br /&gt;   byte note = data &amp; 0x0f;&lt;br /&gt;   &lt;br /&gt;   // play a note?&lt;br /&gt;   if(note)&lt;br /&gt;   {&lt;br /&gt;    // lookup corresponding frequency&lt;br /&gt;    long freq = 0;&lt;br /&gt;    switch(note)&lt;br /&gt;    {&lt;br /&gt;    case 1: freq=196; break; // G&lt;br /&gt;    case 2: freq=220; break; // A&lt;br /&gt;    case 3: freq=247; break; // B&lt;br /&gt;    case 4: freq=262; break; // C&lt;br /&gt;    case 5: freq=294; break; // D&lt;br /&gt;    case 6: freq=330; break; // E&lt;br /&gt;    case 7: freq=349; break; // F&lt;br /&gt;    case 8: freq=392; break; // G&lt;br /&gt;    case 9: freq=440; break; // A&lt;br /&gt;    case 10: freq=494; break; // B&lt;br /&gt;    case 11: freq=524; break; // C&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    // convert this into the correct timer count values&lt;br /&gt;    // Internal clock is 4MHz and Timer1 counts at 1/4 &lt;br /&gt;    // of this frequency (1MHz). We need to call the &lt;br /&gt;    // interrupt handler at double the pitch frequency so&lt;br /&gt;    // that we can generate the 2 phases of the square wave&lt;br /&gt;    // pulse. What we calculate here is the initial 16 bit &lt;br /&gt;    // Timer1 value that will overflow (at 0xffff) after the &lt;br /&gt;    // appropriate period of time.&lt;br /&gt;    long l = (0xffff - (500000L/freq));&lt;br /&gt;    next_tmr1h = l &gt;&gt; 8;&lt;br /&gt;    next_tmr1l = l&amp;0xff;&lt;br /&gt;    tmr1h = next_tmr1h;&lt;br /&gt;    tmr1l = next_tmr1l;&lt;br /&gt;    wave = 0; &lt;br /&gt;    &lt;br /&gt;    // enable the timer (start sound)  &lt;br /&gt;    t1con.0=1; &lt;br /&gt;   }&lt;br /&gt;   else&lt;br /&gt;   {&lt;br /&gt;    // disable the timer (stop sound)&lt;br /&gt;    t1con.0=0; &lt;br /&gt;   }&lt;br /&gt;     &lt;br /&gt;   // duration is in top 4 bits. We'll just &lt;br /&gt;   // us an empty "for" loop to provide a delay&lt;br /&gt;   int dur = 70*(data &gt;&gt; 4);&lt;br /&gt;   for(int p=0;p&amp;lt;dur;++p)&lt;br /&gt;   {&lt;br /&gt;    // empty for loop for delay&lt;br /&gt;    for(byte q=1;q;++q);&lt;br /&gt;   }&lt;br /&gt;  &lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-5695616645791242591?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/5695616645791242591/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2010/01/diy-annoying-greetings-card.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/5695616645791242591'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/5695616645791242591'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2010/01/diy-annoying-greetings-card.html' title='Make your own annoying musical greetings card!'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-4974483541797650985</id><published>2010-01-03T13:31:00.000-08:00</published><updated>2010-01-11T03:53:21.624-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='launchpad'/><category scheme='http://www.blogger.com/atom/ns#' term='midi'/><title type='text'>The poor mans Harmonic Keyboard</title><content type='html'>I have always been curious about the &lt;a href="http://www.c-thru-music.com/"&gt;Axis Controllers&lt;/a&gt; and their unusual key layout, particularly as this 'harmonic table' layout is intended to make chord structures simpler and easier to understand. I wondered what it would be like to play one and thought, hey, maybe I could do it on my Novation Launchpad..!&lt;br /&gt;&lt;br /&gt;The first problem is that the Axis has a staggered honeycomb of a hexagonal keys where the Launchpad is a square 8x8 grid. I thought the notes might translate better if the Launchpad was held at 45 degress, but eventually decided to keep it simple.&lt;br /&gt;&lt;br /&gt;Here is the key layout I ended up with...&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_rn0sSfRNtpI/S0Jda20qaqI/AAAAAAAABGY/HYnX-tBTtYA/s1600-h/harmonic+table.gif"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 241px;" src="http://2.bp.blogspot.com/_rn0sSfRNtpI/S0Jda20qaqI/AAAAAAAABGY/HYnX-tBTtYA/s320/harmonic+table.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5422999617281878690" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The code is based on some earlier Launchpad MIDI projects. It is Visual C++ / Windows API code which simply receives input from the pad, sends MIDI to light up the buttons and outputs a MIDI stream to Reason (which actually makes the sounds). I used the wonderful Midi Yoke utility from &lt;a href="http://www.midiox.com/"&gt;Midi-OX&lt;/a&gt; which lets you transmit MIDI from one Windows application and use that stream as input to another (without that I would need to implement a Windows Midi Input device)&lt;br /&gt;&lt;br /&gt;I am gathering all my recent Launchpad experiments into a single app which I will post for download together with source code some time soon. Watch this space.&lt;br /&gt;&lt;br /&gt;edit: get it here &lt;a href="http://sites.google.com/site/skriyl/Home/launchpad-playpad-download"&gt;http://sites.google.com/site/skriyl/Home/launchpad-playpad-download&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/LxcR4O-GRZg&amp;hl=en_US&amp;fs=1&amp;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/LxcR4O-GRZg&amp;hl=en_US&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-4974483541797650985?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/4974483541797650985/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2010/01/poor-mans-harmonic-keyboard.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/4974483541797650985'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/4974483541797650985'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2010/01/poor-mans-harmonic-keyboard.html' title='The poor mans Harmonic Keyboard'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_rn0sSfRNtpI/S0Jda20qaqI/AAAAAAAABGY/HYnX-tBTtYA/s72-c/harmonic+table.gif' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8909459762367220480.post-8647740921410411318</id><published>2010-01-03T09:02:00.000-08:00</published><updated>2010-01-03T09:05:24.113-08:00</updated><title type='text'>what the blog?</title><content type='html'>Well, here I am in the blogosphere... lets see how long this lasts... At the very least I hope to post up info about my various spare-time projects; music, electronics and so on. Maybe the occasional rant if you are lucky. Catch you later&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8909459762367220480-8647740921410411318?l=hotchk155.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hotchk155.blogspot.com/feeds/8647740921410411318/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://hotchk155.blogspot.com/2010/01/what-blog.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/8647740921410411318'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8909459762367220480/posts/default/8647740921410411318'/><link rel='alternate' type='text/html' href='http://hotchk155.blogspot.com/2010/01/what-blog.html' title='what the blog?'/><author><name>Jason Hotchkiss</name><uri>https://profiles.google.com/105009608886388132613</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh4.googleusercontent.com/-zKAo4pS2ypQ/AAAAAAAAAAI/AAAAAAAACIo/rtN4kMd6rCk/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry></feed>
