<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://hades.mech.northwestern.edu//api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jenny+Yong</id>
	<title>Mech - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://hades.mech.northwestern.edu//api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jenny+Yong"/>
	<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php/Special:Contributions/Jenny_Yong"/>
	<updated>2026-05-13T08:04:48Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.8</generator>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=12988</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=12988"/>
		<updated>2009-03-20T14:30:10Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Team Members */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Image:AutomatedXylophoneLCD.jpg|thumb|250x250 px|left|Automated Xylophone: LCD Screen during Edit Mode]] &lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoids.jpg|thumb|400x400 px|right|Automated Xylophone: Housing for Solenoids]]&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoidInterface.jpg|thumb|300x300 px|right|Automated Xylophone: Solenoid Support and Xylophone Interface]]&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
[[Image:AutomatedXylophonePICCircuitry.jpg|thumb|400x400 px|center|Automated Xylophone: PIC and LCD Circuitry]]&lt;br /&gt;
[[Image:AutomatedXylophoneRelays.jpg|thumb|400x400 px|center|Automated Xylophone: Relay Circuitry]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[Image:AutomatedXylophoneCircuitDiagram.jpg|thumb|400x400 px|center|Automated Xylophone: Circuit Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
[[Image:AutomatedXylophonePic2.jpg|thumb|300x300 px|right|Automated Xylophone]]&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found [http://www.youtube.com/watch?v=_ubpAEyq9kg here].  A video of our Automated Xylophone playing in playback mode can be found [http://www.youtube.com/watch?v=QUSQOINeglQ here] with vies of the LCD screen during playback mode [http://www.youtube.com/watch?v=bwAo6oKskMs here].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=ME_333_final_projects&amp;diff=11853</id>
		<title>ME 333 final projects</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=ME_333_final_projects&amp;diff=11853"/>
		<updated>2009-03-19T16:26:16Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Automated Xylophone */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See the &#039;&#039;&#039;[[ME 333 end of course schedule]]&#039;&#039;&#039;.  &lt;br /&gt;
&lt;br /&gt;
Final projects for ME 333 in years 2000-2007 can be found&lt;br /&gt;
&#039;&#039;&#039;[http://lims.mech.northwestern.edu/~design/mechatronics/ here]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ME 333 Final Projects 2009 ==&lt;br /&gt;
&lt;br /&gt;
=== [[Mozart&#039;s Right Hand]] ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== [[Persistence-of-Vision Display]] ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== [[Rock-Paper-Scissors]] ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== [[Three-speaker Chladni Patterns]] ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== [[Basketball]] ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== [[Robot Drummer]] ===&lt;br /&gt;
The Robot Drummer is a device that demonstrates high-speed motor control by being able to drum when given commands.  Through an RS232 cable, Matlab sends commands to a &amp;quot;master&amp;quot; PIC.  The master then sends the commands to two &amp;quot;slave&amp;quot; PICs through I2C communication.  The slaves take the commands and implement PID control of the motors.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Automated Fish Refuge]] ===&lt;br /&gt;
[[Image:Entire Fish Refuge|right|thumb|200px]]&lt;br /&gt;
The automated fish refuge allows for the controlled movement of a fish refuge with the goal of recording specific behavior.  The mechanical design is completely adjustable and allows adjustable degrees of oscillating movement and orientation of the refuge.  The program is primarily in MATLAB for ease of use and the velocity profile can be a sine, square, triangle, or any function that the user inputs. [http://www.youtube.com/watch?v=wGOKujMhN88 Check out the video!]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Marionette]] ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== [[Monkeybot]] ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== [[PPOD-mini:  6-DOF Shaker]] ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== [[Automated Xylophone]] ===&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|200x200 px|right|Automated Xylophone]]&lt;br /&gt;
The Automated Xylophone controls several solenoids which hit various pitches on an actual xylophone based on the note selected.  The device has two main modes: using the keypad, a user can choose to either play notes in real time or store songs to be played back later.  A video of the Automated Xylophone playing in real time mode can be found [http://www.youtube.com/watch?v=_ubpAEyq9kg here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Vision-based Cannon]] ===&lt;br /&gt;
[[Image:SM_Gun_Camera_PIC_Setup.JPG|thumb|200x200 px|right|Vision-based Cannon]]&lt;br /&gt;
This project uses a webcam and Matlab to analyze an image and direct a modified USB Missile Launcher to fire at targets found in the image.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ME 333 Final Projects 2008 ==&lt;br /&gt;
&lt;br /&gt;
=== [[IR Tracker]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:IR_Tracker_Main.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
The IR Tracker (aka &amp;quot;Spot&amp;quot;) is a device that follows a moving infrared light. It continuously detects the position of an infrared emitter in two axes, and then tracks the emitter with a laser. [[Media:MT_MS_AZ_TrackerVideo.mp4|See Spot Run.]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Chosen the OUTSTANDING PROJECT by the students of ME 333.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Robot Snake]] ===&lt;br /&gt;
[[Image:HLSSnakeMain.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This remote control robotic snake uses servo motors with a traveling sine wave motion profile to mimic serpentine motion.  The robotic snake is capable of moving forward, left, right and in reverse.   &lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Programmable Stiffness Joint]] === &lt;br /&gt;
&lt;br /&gt;
[[Image:SteelToePic2.jpg|thumb|200px|The &#039;Steel Toe&#039; programmable stiffness joint|right]]&lt;br /&gt;
&lt;br /&gt;
The Programmable Stiffness Joint varies rotational stiffness as desired by the user.  It is the first step in modeling the mechanical impedance of the human ankle joint (both stiffness and damping) for the purpose of determining the respective breakdown of the two properties over the gait cycle.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== [[Magnetic based sample purification]] ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== [[Continuously Variable Transmission]] ===&lt;br /&gt;
&lt;br /&gt;
[[image:CVT_system.JPG|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This prototype is a proof of concept model of a variable ratio transmission to be implemented in the 2008-2009 Formula SAE competition vehicle.  The gear ratio is determined by the distances between the pulley halves which are controllable electronically.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Granular Flow Rotating Sphere]] ===&lt;br /&gt;
[[Image:Team-21-main-picture.JPG|right|thumb|200px]]&lt;br /&gt;
This device will be used to study the granular flow of particles within a rotating sphere. The sphere is filled with grains of varying size and then rotated about two different axes according to a series of position and angular velocity inputs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Vibratory Clock]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Vibratory_Clock.jpg|right|thumb|Vibratory Clock|200px]]&lt;br /&gt;
&lt;br /&gt;
The Vibratory Clock allows a small object to act as an hour &amp;quot;hand&amp;quot; on a horizontal circular platform that is actuated from underneath by three speakers.  The object slides around the circular platform, impelled by friction forces due to the vibration.  [http://www.youtube.com/watch?v=KhgTNCfdwZw Check it out!]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[WiiMouse]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:HPIM1027.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
The WiiMouse is a handheld remote that can be used to move a cursor on a windows-based PC, via accelerometer input captured through device movement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Intelligent Oscillation Controller]] ===&lt;br /&gt;
&lt;br /&gt;
[[image:ME333_learning_oscillator.jpg|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This device &amp;quot;learns&amp;quot; a forcing function that is applied to a spring and mass system to match an arbitrary, periodic acceleration profile.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Baseball]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Baseball_Playfield.jpg|Sweet Baseball Game|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
An interactive baseball game inspired by pinball, featuring pitching, batting, light up bases and a scoreboard to keep track of the game.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Ball Balancing Challenge]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Ballbalancechallenge.JPG|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
An interactive game involving ball balancing on a touchscreen with touchscreen feedback and joystick action. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11852</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11852"/>
		<updated>2009-03-19T16:25:12Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Results */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Image:AutomatedXylophoneLCD.jpg|thumb|250x250 px|left|Automated Xylophone: LCD Screen during Edit Mode]] &lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoids.jpg|thumb|400x400 px|right|Automated Xylophone: Housing for Solenoids]]&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoidInterface.jpg|thumb|300x300 px|right|Automated Xylophone: Solenoid Support and Xylophone Interface]]&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
[[Image:AutomatedXylophonePICCircuitry.jpg|thumb|400x400 px|center|Automated Xylophone: PIC and LCD Circuitry]]&lt;br /&gt;
[[Image:AutomatedXylophoneRelays.jpg|thumb|400x400 px|center|Automated Xylophone: Relay Circuitry]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[Image:AutomatedXylophoneCircuitDiagram.jpg|thumb|400x400 px|center|Automated Xylophone: Circuit Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
[[Image:AutomatedXylophonePic2.jpg|thumb|300x300 px|right|Automated Xylophone]]&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found [http://www.youtube.com/watch?v=_ubpAEyq9kg here].  A video of our Automated Xylophone playing in playback mode can be found [http://www.youtube.com/watch?v=QUSQOINeglQ here] with vies of the LCD screen during playback mode [http://www.youtube.com/watch?v=bwAo6oKskMs here].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=ME_333_final_projects&amp;diff=11685</id>
		<title>ME 333 final projects</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=ME_333_final_projects&amp;diff=11685"/>
		<updated>2009-03-19T01:40:28Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Automated Xylophone */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See the &#039;&#039;&#039;[[ME 333 end of course schedule]]&#039;&#039;&#039;.  &lt;br /&gt;
&lt;br /&gt;
Final projects for ME 333 in years 2000-2007 can be found&lt;br /&gt;
&#039;&#039;&#039;[http://lims.mech.northwestern.edu/~design/mechatronics/ here]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ME 333 Final Projects 2009 ==&lt;br /&gt;
&lt;br /&gt;
=== [[Mozart&#039;s Right Hand]] ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== [[Persistence-of-Vision Display]] ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== [[Rock-Paper-Scissors]] ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== [[Three-speaker Chladni Patterns]] ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== [[Basketball]] ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== [[Robot Drummer]] ===&lt;br /&gt;
The Robot Drummer is a device that demonstrates high-speed motor control by being able to drum when given commands.  Through an RS232 cable, Matlab sends commands to a &amp;quot;master&amp;quot; PIC.  The master then sends the commands to two &amp;quot;slave&amp;quot; PICs through I2C communication.  The slaves take the commands and implement PID control of the motors.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Automated Fish Refuge]] ===&lt;br /&gt;
[[Image:Entire Fish Refuge|right|thumb|200px]]&lt;br /&gt;
The automated fish refuge allows for the controlled movement of a fish refuge with the goal of recording specific behavior.  The mechanical design is completely adjustable and allows adjustable degrees of oscillating movement and orientation of the refuge.  The program is primarily in MATLAB for ease of use and the velocity profile can be a sine, square, triangle, or any function that the user inputs. [http://www.youtube.com/watch?v=wGOKujMhN88 Check out the video!]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Marionette]] ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== [[Monkeybot]] ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== [[PPOD-mini:  6-DOF Shaker]] ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== [[Automated Xylophone]] ===&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|200x200 px|right|Automated Xylophone]]&lt;br /&gt;
The automated xylophone controls several solenoids which hit various pitches on an actual xylophone based on the note selected.  The device has two main modes: using the keypad, a user can choose to either play notes in real time or store songs to be played back later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Vision-based Cannon]] ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ME 333 Final Projects 2008 ==&lt;br /&gt;
&lt;br /&gt;
=== [[IR Tracker]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:IR_Tracker_Main.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
The IR Tracker (aka &amp;quot;Spot&amp;quot;) is a device that follows a moving infrared light. It continuously detects the position of an infrared emitter in two axes, and then tracks the emitter with a laser. [[Media:MT_MS_AZ_TrackerVideo.mp4|See Spot Run.]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Chosen the OUTSTANDING PROJECT by the students of ME 333.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Robot Snake]] ===&lt;br /&gt;
[[Image:HLSSnakeMain.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This remote control robotic snake uses servo motors with a traveling sine wave motion profile to mimic serpentine motion.  The robotic snake is capable of moving forward, left, right and in reverse.   &lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Programmable Stiffness Joint]] === &lt;br /&gt;
&lt;br /&gt;
[[Image:SteelToePic2.jpg|thumb|200px|The &#039;Steel Toe&#039; programmable stiffness joint|right]]&lt;br /&gt;
&lt;br /&gt;
The Programmable Stiffness Joint varies rotational stiffness as desired by the user.  It is the first step in modeling the mechanical impedance of the human ankle joint (both stiffness and damping) for the purpose of determining the respective breakdown of the two properties over the gait cycle.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== [[Magnetic based sample purification]] ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== [[Continuously Variable Transmission]] ===&lt;br /&gt;
&lt;br /&gt;
[[image:CVT_system.JPG|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This prototype is a proof of concept model of a variable ratio transmission to be implemented in the 2008-2009 Formula SAE competition vehicle.  The gear ratio is determined by the distances between the pulley halves which are controllable electronically.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Granular Flow Rotating Sphere]] ===&lt;br /&gt;
[[Image:Team-21-main-picture.JPG|right|thumb|200px]]&lt;br /&gt;
This device will be used to study the granular flow of particles within a rotating sphere. The sphere is filled with grains of varying size and then rotated about two different axes according to a series of position and angular velocity inputs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Vibratory Clock]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Vibratory_Clock.jpg|right|thumb|Vibratory Clock|200px]]&lt;br /&gt;
&lt;br /&gt;
The Vibratory Clock allows a small object to act as an hour &amp;quot;hand&amp;quot; on a horizontal circular platform that is actuated from underneath by three speakers.  The object slides around the circular platform, impelled by friction forces due to the vibration.  [http://www.youtube.com/watch?v=KhgTNCfdwZw Check it out!]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[WiiMouse]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:HPIM1027.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
The WiiMouse is a handheld remote that can be used to move a cursor on a windows-based PC, via accelerometer input captured through device movement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Intelligent Oscillation Controller]] ===&lt;br /&gt;
&lt;br /&gt;
[[image:ME333_learning_oscillator.jpg|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This device &amp;quot;learns&amp;quot; a forcing function that is applied to a spring and mass system to match an arbitrary, periodic acceleration profile.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Baseball]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Baseball_Playfield.jpg|Sweet Baseball Game|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
An interactive baseball game inspired by pinball, featuring pitching, batting, light up bases and a scoreboard to keep track of the game.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Ball Balancing Challenge]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Ballbalancechallenge.JPG|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
An interactive game involving ball balancing on a touchscreen with touchscreen feedback and joystick action. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=ME_333_final_projects&amp;diff=11684</id>
		<title>ME 333 final projects</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=ME_333_final_projects&amp;diff=11684"/>
		<updated>2009-03-19T01:40:16Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* ME 333 Final Projects 2009 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See the &#039;&#039;&#039;[[ME 333 end of course schedule]]&#039;&#039;&#039;.  &lt;br /&gt;
&lt;br /&gt;
Final projects for ME 333 in years 2000-2007 can be found&lt;br /&gt;
&#039;&#039;&#039;[http://lims.mech.northwestern.edu/~design/mechatronics/ here]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ME 333 Final Projects 2009 ==&lt;br /&gt;
&lt;br /&gt;
=== [[Mozart&#039;s Right Hand]] ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== [[Persistence-of-Vision Display]] ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== [[Rock-Paper-Scissors]] ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== [[Three-speaker Chladni Patterns]] ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== [[Basketball]] ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== [[Robot Drummer]] ===&lt;br /&gt;
The Robot Drummer is a device that demonstrates high-speed motor control by being able to drum when given commands.  Through an RS232 cable, Matlab sends commands to a &amp;quot;master&amp;quot; PIC.  The master then sends the commands to two &amp;quot;slave&amp;quot; PICs through I2C communication.  The slaves take the commands and implement PID control of the motors.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Automated Fish Refuge]] ===&lt;br /&gt;
[[Image:Entire Fish Refuge|right|thumb|200px]]&lt;br /&gt;
The automated fish refuge allows for the controlled movement of a fish refuge with the goal of recording specific behavior.  The mechanical design is completely adjustable and allows adjustable degrees of oscillating movement and orientation of the refuge.  The program is primarily in MATLAB for ease of use and the velocity profile can be a sine, square, triangle, or any function that the user inputs. [http://www.youtube.com/watch?v=wGOKujMhN88 Check out the video!]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Marionette]] ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== [[Monkeybot]] ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== [[PPOD-mini:  6-DOF Shaker]] ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== [[Automated Xylophone]] ===&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|200x200 px|left|Automated Xylophone]]&lt;br /&gt;
The automated xylophone controls several solenoids which hit various pitches on an actual xylophone based on the note selected.  The device has two main modes: using the keypad, a user can choose to either play notes in real time or store songs to be played back later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== [[Vision-based Cannon]] ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ME 333 Final Projects 2008 ==&lt;br /&gt;
&lt;br /&gt;
=== [[IR Tracker]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:IR_Tracker_Main.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
The IR Tracker (aka &amp;quot;Spot&amp;quot;) is a device that follows a moving infrared light. It continuously detects the position of an infrared emitter in two axes, and then tracks the emitter with a laser. [[Media:MT_MS_AZ_TrackerVideo.mp4|See Spot Run.]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Chosen the OUTSTANDING PROJECT by the students of ME 333.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Robot Snake]] ===&lt;br /&gt;
[[Image:HLSSnakeMain.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This remote control robotic snake uses servo motors with a traveling sine wave motion profile to mimic serpentine motion.  The robotic snake is capable of moving forward, left, right and in reverse.   &lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Programmable Stiffness Joint]] === &lt;br /&gt;
&lt;br /&gt;
[[Image:SteelToePic2.jpg|thumb|200px|The &#039;Steel Toe&#039; programmable stiffness joint|right]]&lt;br /&gt;
&lt;br /&gt;
The Programmable Stiffness Joint varies rotational stiffness as desired by the user.  It is the first step in modeling the mechanical impedance of the human ankle joint (both stiffness and damping) for the purpose of determining the respective breakdown of the two properties over the gait cycle.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== [[Magnetic based sample purification]] ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== [[Continuously Variable Transmission]] ===&lt;br /&gt;
&lt;br /&gt;
[[image:CVT_system.JPG|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This prototype is a proof of concept model of a variable ratio transmission to be implemented in the 2008-2009 Formula SAE competition vehicle.  The gear ratio is determined by the distances between the pulley halves which are controllable electronically.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Granular Flow Rotating Sphere]] ===&lt;br /&gt;
[[Image:Team-21-main-picture.JPG|right|thumb|200px]]&lt;br /&gt;
This device will be used to study the granular flow of particles within a rotating sphere. The sphere is filled with grains of varying size and then rotated about two different axes according to a series of position and angular velocity inputs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Vibratory Clock]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Vibratory_Clock.jpg|right|thumb|Vibratory Clock|200px]]&lt;br /&gt;
&lt;br /&gt;
The Vibratory Clock allows a small object to act as an hour &amp;quot;hand&amp;quot; on a horizontal circular platform that is actuated from underneath by three speakers.  The object slides around the circular platform, impelled by friction forces due to the vibration.  [http://www.youtube.com/watch?v=KhgTNCfdwZw Check it out!]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[WiiMouse]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:HPIM1027.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
The WiiMouse is a handheld remote that can be used to move a cursor on a windows-based PC, via accelerometer input captured through device movement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Intelligent Oscillation Controller]] ===&lt;br /&gt;
&lt;br /&gt;
[[image:ME333_learning_oscillator.jpg|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This device &amp;quot;learns&amp;quot; a forcing function that is applied to a spring and mass system to match an arbitrary, periodic acceleration profile.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Baseball]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Baseball_Playfield.jpg|Sweet Baseball Game|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
An interactive baseball game inspired by pinball, featuring pitching, batting, light up bases and a scoreboard to keep track of the game.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Ball Balancing Challenge]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Ballbalancechallenge.JPG|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
An interactive game involving ball balancing on a touchscreen with touchscreen feedback and joystick action. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11683</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11683"/>
		<updated>2009-03-19T01:38:05Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Image:AutomatedXylophoneLCD.jpg|thumb|250x250 px|left|Automated Xylophone: LCD Screen during Edit Mode]] &lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoids.jpg|thumb|400x400 px|right|Automated Xylophone: Housing for Solenoids]]&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoidInterface.jpg|thumb|300x300 px|right|Automated Xylophone: Solenoid Support and Xylophone Interface]]&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
[[Image:AutomatedXylophonePICCircuitry.jpg|thumb|400x400 px|center|Automated Xylophone: PIC and LCD Circuitry]]&lt;br /&gt;
[[Image:AutomatedXylophoneRelays.jpg|thumb|400x400 px|center|Automated Xylophone: Relay Circuitry]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[Image:AutomatedXylophoneCircuitDiagram.jpg|thumb|400x400 px|center|Automated Xylophone: Circuit Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
[[Image:AutomatedXylophonePic2.jpg|thumb|300x300 px|right|Automated Xylophone]]&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11682</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11682"/>
		<updated>2009-03-19T01:36:07Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Image:AutomatedXylophoneLCD.jpg|thumb|250x250 px|left|Automated Xylophone: LCD Screen during Edit Mode]] &lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoids.jpg|thumb|400x400 px|right|Automated Xylophone: Housing for Solenoids]]&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoidInterface.jpg|thumb|300x300 px|right|Automated Xylophone: Solenoid Support and Xylophone Interface]]&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
[[Image:AutomatedXylophonePICCircuitry.jpg|thumb|400x400 px|left|Automated Xylophone: PIC and LCD Circuitry]]&lt;br /&gt;
[[Image:AutomatedXylophoneRelays.jpg|thumb|400x400 px|right|Automated Xylophone: Relay Circuitry]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[Image:AutomatedXylophoneCircuitDiagram.jpg|thumb|400x400 px|center|Automated Xylophone: Circuit Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
[[Image:AutomatedXylophonePic2.jpg|thumb|300x300 px|right|Automated Xylophone]]&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11681</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11681"/>
		<updated>2009-03-19T01:35:10Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Team Members */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Image:AutomatedXylophoneLCD.jpg|thumb|250x250 px|left|Automated Xylophone: LCD Screen during Edit Mode]] &lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoids.jpg|thumb|400x400 px|right|Automated Xylophone: Housing for Solenoids]]&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoidInterface.jpg|thumb|300x300 px|right|Automated Xylophone: Solenoid Support and Xylophone Interface]]&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
[[Image:AutomatedXylophonePICCircuitry.jpg|thumb|400x400 px|center|Automated Xylophone: PIC and LCD Circuitry]]&lt;br /&gt;
[[Image:AutomatedXylophoneRelays.jpg|thumb|400x400 px|center|Automated Xylophone: Relay Circuitry]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[Image:AutomatedXylophoneCircuitDiagram.jpg|thumb|400x400 px|center|Automated Xylophone: Circuit Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
[[Image:AutomatedXylophonePic2.jpg|thumb|300x300 px|right|Automated Xylophone]]&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11680</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11680"/>
		<updated>2009-03-19T01:35:01Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Image:AutomatedXylophoneLCD.jpg|thumb|250x250 px|left|Automated Xylophone: LCD Screen during Edit Mode]] &lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoids.jpg|thumb|400x400 px|right|Automated Xylophone: Housing for Solenoids]]&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoidInterface.jpg|thumb|300x300 px|right|Automated Xylophone: Solenoid Support and Xylophone Interface]]&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
[[Image:AutomatedXylophonePICCircuitry.jpg|thumb|400x400 px|center|Automated Xylophone: PIC and LCD Circuitry]]&lt;br /&gt;
[[Image:AutomatedXylophoneRelays.jpg|thumb|400x400 px|center|Automated Xylophone: Relay Circuitry]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[Image:AutomatedXylophoneCircuitDiagram.jpg|thumb|400x400 px|center|Automated Xylophone: Circuit Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
[[Image:AutomatedXylophonePic2.jpg|thumb|300x300 px|right|Automated Xylophone]]&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11679</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11679"/>
		<updated>2009-03-19T01:34:47Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Edit Mode */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Image:AutomatedXylophoneLCD.jpg|thumb|250x250 px|left|Automated Xylophone: LCD Screen during Edit Mode]] &lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoids.jpg|thumb|400x400 px|right|Automated Xylophone: Housing for Solenoids]]&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoidInterface.jpg|thumb|300x300 px|right|Automated Xylophone: Solenoid Support and Xylophone Interface]]&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
[[Image:AutomatedXylophonePICCircuitry.jpg|thumb|400x400 px|center|Automated Xylophone: PIC and LCD Circuitry]]&lt;br /&gt;
[[Image:AutomatedXylophoneRelays.jpg|thumb|400x400 px|center|Automated Xylophone: Relay Circuitry]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[Image:AutomatedXylophoneCircuitDiagram.jpg|thumb|400x400 px|center|Automated Xylophone: Circuit Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
[[Image:AutomatedXylophonePic2.jpg|thumb|300x300 px|right|Automated Xylophone]]&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11678</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11678"/>
		<updated>2009-03-19T01:34:12Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Edit Mode */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
[[Image:AutomatedXylophoneLCD.jpg|thumb|250x250 px|left|Automated Xylophone: LCD Screen during Edit Mode]] &lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoids.jpg|thumb|400x400 px|right|Automated Xylophone: Housing for Solenoids]]&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoidInterface.jpg|thumb|300x300 px|right|Automated Xylophone: Solenoid Support and Xylophone Interface]]&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
[[Image:AutomatedXylophonePICCircuitry.jpg|thumb|400x400 px|center|Automated Xylophone: PIC and LCD Circuitry]]&lt;br /&gt;
[[Image:AutomatedXylophoneRelays.jpg|thumb|400x400 px|center|Automated Xylophone: Relay Circuitry]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[Image:AutomatedXylophoneCircuitDiagram.jpg|thumb|400x400 px|center|Automated Xylophone: Circuit Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
[[Image:AutomatedXylophonePic2.jpg|thumb|300x300 px|right|Automated Xylophone]]&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11676</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11676"/>
		<updated>2009-03-19T01:33:56Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Operating the Automated Xylophone */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
[[Image:AutomatedXylophoneLCD.jpg|thumb|200x200 px|left|Automated Xylophone: LCD Screen during Edit Mode]] &lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoids.jpg|thumb|400x400 px|right|Automated Xylophone: Housing for Solenoids]]&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoidInterface.jpg|thumb|300x300 px|right|Automated Xylophone: Solenoid Support and Xylophone Interface]]&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
[[Image:AutomatedXylophonePICCircuitry.jpg|thumb|400x400 px|center|Automated Xylophone: PIC and LCD Circuitry]]&lt;br /&gt;
[[Image:AutomatedXylophoneRelays.jpg|thumb|400x400 px|center|Automated Xylophone: Relay Circuitry]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[Image:AutomatedXylophoneCircuitDiagram.jpg|thumb|400x400 px|center|Automated Xylophone: Circuit Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
[[Image:AutomatedXylophonePic2.jpg|thumb|300x300 px|right|Automated Xylophone]]&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11675</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11675"/>
		<updated>2009-03-19T01:33:36Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Operating the Automated Xylophone */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
[[Image:AutomatedXylophoneLCD.jpg|thumb|200x200 px|right|Automated Xylophone: LCD Screen during Edit Mode]] &lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoids.jpg|thumb|400x400 px|right|Automated Xylophone: Housing for Solenoids]]&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoidInterface.jpg|thumb|300x300 px|right|Automated Xylophone: Solenoid Support and Xylophone Interface]]&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
[[Image:AutomatedXylophonePICCircuitry.jpg|thumb|400x400 px|center|Automated Xylophone: PIC and LCD Circuitry]]&lt;br /&gt;
[[Image:AutomatedXylophoneRelays.jpg|thumb|400x400 px|center|Automated Xylophone: Relay Circuitry]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[Image:AutomatedXylophoneCircuitDiagram.jpg|thumb|400x400 px|center|Automated Xylophone: Circuit Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
[[Image:AutomatedXylophonePic2.jpg|thumb|300x300 px|right|Automated Xylophone]]&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11674</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11674"/>
		<updated>2009-03-19T01:33:23Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Operating the Automated Xylophone */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
[[Image:AutomatedXylophoneLCD.jpg|thumb|500x500 px|right|Automated Xylophone: LCD Screen during Edit Mode]] &lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoids.jpg|thumb|400x400 px|right|Automated Xylophone: Housing for Solenoids]]&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoidInterface.jpg|thumb|300x300 px|right|Automated Xylophone: Solenoid Support and Xylophone Interface]]&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
[[Image:AutomatedXylophonePICCircuitry.jpg|thumb|400x400 px|center|Automated Xylophone: PIC and LCD Circuitry]]&lt;br /&gt;
[[Image:AutomatedXylophoneRelays.jpg|thumb|400x400 px|center|Automated Xylophone: Relay Circuitry]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[Image:AutomatedXylophoneCircuitDiagram.jpg|thumb|400x400 px|center|Automated Xylophone: Circuit Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
[[Image:AutomatedXylophonePic2.jpg|thumb|300x300 px|right|Automated Xylophone]]&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:AutomatedXylophoneLCD.jpg&amp;diff=11673</id>
		<title>File:AutomatedXylophoneLCD.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:AutomatedXylophoneLCD.jpg&amp;diff=11673"/>
		<updated>2009-03-19T01:32:53Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11672</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11672"/>
		<updated>2009-03-19T01:31:03Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Commented Keypad Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoids.jpg|thumb|400x400 px|right|Automated Xylophone: Housing for Solenoids]]&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoidInterface.jpg|thumb|300x300 px|right|Automated Xylophone: Solenoid Support and Xylophone Interface]]&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
[[Image:AutomatedXylophonePICCircuitry.jpg|thumb|400x400 px|center|Automated Xylophone: PIC and LCD Circuitry]]&lt;br /&gt;
[[Image:AutomatedXylophoneRelays.jpg|thumb|400x400 px|center|Automated Xylophone: Relay Circuitry]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[Image:AutomatedXylophoneCircuitDiagram.jpg|thumb|400x400 px|center|Automated Xylophone: Circuit Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
[[Image:AutomatedXylophonePic2.jpg|thumb|300x300 px|right|Automated Xylophone]]&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11671</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11671"/>
		<updated>2009-03-19T01:30:45Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Results and Next Steps */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoids.jpg|thumb|400x400 px|right|Automated Xylophone: Housing for Solenoids]]&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoidInterface.jpg|thumb|300x300 px|right|Automated Xylophone: Solenoid Support and Xylophone Interface]]&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
[[Image:AutomatedXylophonePICCircuitry.jpg|thumb|400x400 px|center|Automated Xylophone: PIC and LCD Circuitry]]&lt;br /&gt;
[[Image:AutomatedXylophoneRelays.jpg|thumb|400x400 px|center|Automated Xylophone: Relay Circuitry]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[Image:AutomatedXylophoneCircuitDiagram.jpg|thumb|400x400 px|center|Automated Xylophone: Circuit Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
[[Image:AutomatedXylophonePic2.jpg|thumb|300x300 px|right|Automated Xylophone]]&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11670</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11670"/>
		<updated>2009-03-19T01:30:31Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Results and Next Steps */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoids.jpg|thumb|400x400 px|right|Automated Xylophone: Housing for Solenoids]]&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoidInterface.jpg|thumb|300x300 px|right|Automated Xylophone: Solenoid Support and Xylophone Interface]]&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
[[Image:AutomatedXylophonePICCircuitry.jpg|thumb|400x400 px|center|Automated Xylophone: PIC and LCD Circuitry]]&lt;br /&gt;
[[Image:AutomatedXylophoneRelays.jpg|thumb|400x400 px|center|Automated Xylophone: Relay Circuitry]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[Image:AutomatedXylophoneCircuitDiagram.jpg|thumb|400x400 px|center|Automated Xylophone: Circuit Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
[[Image:AutomatedXylophonePic2.jpg|thumb|300x300 px|right|Automated Xylophone]]&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11669</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11669"/>
		<updated>2009-03-19T01:30:05Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoids.jpg|thumb|400x400 px|right|Automated Xylophone: Housing for Solenoids]]&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoidInterface.jpg|thumb|300x300 px|right|Automated Xylophone: Solenoid Support and Xylophone Interface]]&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
[[Image:AutomatedXylophonePICCircuitry.jpg|thumb|400x400 px|center|Automated Xylophone: PIC and LCD Circuitry]]&lt;br /&gt;
[[Image:AutomatedXylophoneRelays.jpg|thumb|400x400 px|center|Automated Xylophone: Relay Circuitry]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[Image:AutomatedXylophoneCircuitDiagram.jpg|thumb|400x400 px|center|Automated Xylophone: Circuit Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
[[Image:AutomatedXylophonePic2.jpg|thumb|400x400 px|right|Automated Xylophone]]&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:AutomatedXylophonePic2.jpg&amp;diff=11667</id>
		<title>File:AutomatedXylophonePic2.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:AutomatedXylophonePic2.jpg&amp;diff=11667"/>
		<updated>2009-03-19T01:29:23Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11664</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11664"/>
		<updated>2009-03-19T01:27:20Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Connecting the LCD */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoids.jpg|thumb|400x400 px|right|Automated Xylophone: Housing for Solenoids]]&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoidInterface.jpg|thumb|300x300 px|right|Automated Xylophone: Solenoid Support and Xylophone Interface]]&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
[[Image:AutomatedXylophonePICCircuitry.jpg|thumb|400x400 px|center|Automated Xylophone: PIC and LCD Circuitry]]&lt;br /&gt;
[[Image:AutomatedXylophoneRelays.jpg|thumb|400x400 px|center|Automated Xylophone: Relay Circuitry]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[Image:AutomatedXylophoneCircuitDiagram.jpg|thumb|400x400 px|center|Automated Xylophone: Circuit Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11663</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11663"/>
		<updated>2009-03-19T01:27:09Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Powering the Solenoids */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoids.jpg|thumb|400x400 px|right|Automated Xylophone: Housing for Solenoids]]&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoidInterface.jpg|thumb|300x300 px|right|Automated Xylophone: Solenoid Support and Xylophone Interface]]&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
[[Image:AutomatedXylophonePICCircuitry.jpg|thumb|400x400 px|center|Automated Xylophone: PIC and LCD Circuitry]]&lt;br /&gt;
[[Image:AutomatedXylophoneRelays.jpg|thumb|400x400 px|center|Automated Xylophone: Relay Circuitry]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[Image:AutomatedXylophoneCircuitDiagram.jpg|thumb|400x400 px|center|Automated Xylophone: Circuit Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
[More information or a link necessary] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11662</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11662"/>
		<updated>2009-03-19T01:26:42Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoids.jpg|thumb|400x400 px|right|Automated Xylophone: Housing for Solenoids]]&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoidInterface.jpg|thumb|300x300 px|right|Automated Xylophone: Solenoid Support and Xylophone Interface]]&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
[[Image:AutomatedXylophonePICCircuitry.jpg|thumb|400x400 px|center|Automated Xylophone: PIC and LCD Circuitry]]&lt;br /&gt;
[[Image:AutomatedXylophoneRelays.jpg|thumb|400x400 px|center|Automated Xylophone: Relay Circuitry]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[Image:AutomatedXylophoneCircuitDiagram.jpg|thumb|400x400 px|center|Automated Xylophone: Circuit Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
[More description needed]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
[More information or a link necessary] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11661</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11661"/>
		<updated>2009-03-19T01:26:25Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoids.jpg|thumb|400x400 px|right|Automated Xylophone: Housing for Solenoids]]&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoidInterface.jpg|thumb|300x300 px|right|Automated Xylophone: Solenoid Support and Xylophone Interface]]&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
[[Image:AutomatedXylophoneRelays.jpg|thumb|400x400 px|center|Automated Xylophone: Relay Circuitry]]&lt;br /&gt;
[[Image:AutomatedXylophonePICCircuitry.jpg|thumb|400x400 px|center|Automated Xylophone: PIC and LCD Circuitry]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[Image:AutomatedXylophoneCircuitDiagram.jpg|thumb|400x400 px|center|Automated Xylophone: Circuit Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
[More description needed]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
[More information or a link necessary] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11660</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11660"/>
		<updated>2009-03-19T01:26:08Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoids.jpg|thumb|400x400 px|right|Automated Xylophone: Housing for Solenoids]]&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoidInterface.jpg|thumb|300x300 px|right|Automated Xylophone: Solenoid Support and Xylophone Interface]]&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
[[Image:AutomatedXylophoneRelays.jpg|thumb|400x400 px|right|Automated Xylophone: Relay Circuitry]]&lt;br /&gt;
[[Image:AutomatedXylophonePICCircuitry.jpg|thumb|400x400 px|right|Automated Xylophone: PIC and LCD Circuitry]]&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[Image:AutomatedXylophoneCircuitDiagram.jpg|thumb|400x400 px|center|Automated Xylophone: Circuit Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
[More description needed]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
[More information or a link necessary] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11659</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11659"/>
		<updated>2009-03-19T01:25:54Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoids.jpg|thumb|400x400 px|right|Automated Xylophone: Housing for Solenoids]]&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoidInterface.jpg|thumb|300x300 px|right|Automated Xylophone: Solenoid Support and Xylophone Interface]]&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
[[Image:AutomatedXylophoneRelays.jpg|thumb|400x400 px|center|Automated Xylophone: Relay Circuitry]]&lt;br /&gt;
[[Image:AutomatedXylophonePICCircuitry.jpg|thumb|400x400 px|center|Automated Xylophone: PIC and LCD Circuitry]]&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[Image:AutomatedXylophoneCircuitDiagram.jpg|thumb|400x400 px|center|Automated Xylophone: Circuit Diagram]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
[More description needed]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
[More information or a link necessary] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11658</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11658"/>
		<updated>2009-03-19T01:25:25Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoids.jpg|thumb|400x400 px|right|Automated Xylophone: Housing for Solenoids]]&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoidInterface.jpg|thumb|300x300 px|right|Automated Xylophone: Solenoid Support and Xylophone Interface]]&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[[Image:AutomatedXylophoneCircuitDiagram.jpg|thumb|400x400 px|center|Automated Xylophone: Circuit Diagram]]&lt;br /&gt;
[[Image:AutomatedXylophoneRelays.jpg|thumb|400x400 px|center|Automated Xylophone: Relay Circuitry]]&lt;br /&gt;
[[Image:AutomatedXylophonePICCircuitry.jpg|thumb|400x400 px|center|Automated Xylophone: PIC and LCD Circuitry]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
[More description needed]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
[More information or a link necessary] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:AutomatedXylophonePICCircuitry.jpg&amp;diff=11657</id>
		<title>File:AutomatedXylophonePICCircuitry.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:AutomatedXylophonePICCircuitry.jpg&amp;diff=11657"/>
		<updated>2009-03-19T01:25:11Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:AutomatedXylophoneRelays.jpg&amp;diff=11656</id>
		<title>File:AutomatedXylophoneRelays.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:AutomatedXylophoneRelays.jpg&amp;diff=11656"/>
		<updated>2009-03-19T01:24:12Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:AutomatedXylophoneCircuitDiagram.jpg&amp;diff=11655</id>
		<title>File:AutomatedXylophoneCircuitDiagram.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:AutomatedXylophoneCircuitDiagram.jpg&amp;diff=11655"/>
		<updated>2009-03-19T01:20:45Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11654</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11654"/>
		<updated>2009-03-19T01:18:32Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Mechanical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoids.jpg|thumb|400x400 px|right|Automated Xylophone: Housing for Solenoids]]&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoidInterface.jpg|thumb|300x300 px|right|Automated Xylophone: Solenoid Support and Xylophone Interface]]&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[Insert picture of circuit and circuit diagram] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
[More description needed]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
[More information or a link necessary] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:AutomatedXylophoneSolenoidInterface.jpg&amp;diff=11653</id>
		<title>File:AutomatedXylophoneSolenoidInterface.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:AutomatedXylophoneSolenoidInterface.jpg&amp;diff=11653"/>
		<updated>2009-03-19T01:14:42Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11652</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11652"/>
		<updated>2009-03-19T01:12:22Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Mechanical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoids.jpg|thumb|400x400 px|right|Automated Xylophone: Housing for Solenoids]]&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[Insert picture of circuit and circuit diagram] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
[More description needed]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
[More information or a link necessary] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11651</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11651"/>
		<updated>2009-03-19T01:11:59Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[Image:AutomatedXylophoneSolenoids.jpg|thumb|400x400 px|right|Automated Xylophone: Housing for Solenoids]]&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[Insert picture of circuit and circuit diagram] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
[More description needed]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
[More information or a link necessary] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:AutomatedXylophoneSolenoids.jpg&amp;diff=11650</id>
		<title>File:AutomatedXylophoneSolenoids.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:AutomatedXylophoneSolenoids.jpg&amp;diff=11650"/>
		<updated>2009-03-19T01:09:30Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11648</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11648"/>
		<updated>2009-03-19T00:52:52Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Team Members */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[Include pictures of interior of wooden casing] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[Insert picture of circuit and circuit diagram] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
[More description needed]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
[More information or a link necessary] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11647</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11647"/>
		<updated>2009-03-19T00:52:39Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[Include pictures of interior of wooden casing] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[Insert picture of circuit and circuit diagram] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
[More description needed]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
[More information or a link necessary] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11646</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11646"/>
		<updated>2009-03-19T00:51:56Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Xylophone and Keypad]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[Include pictures of interior of wooden casing] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[Insert picture of circuit and circuit diagram] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
[More description needed]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
[More information or a link necessary] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11645</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11645"/>
		<updated>2009-03-19T00:51:33Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[Image:AutomatedXylophonePicture1.jpg|thumb|300x300 px|left|Circuit Diagram]]&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[Include pictures of interior of wooden casing] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[Insert picture of circuit and circuit diagram] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
[More description needed]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
[More information or a link necessary] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:AutomatedXylophonePicture1.jpg&amp;diff=11644</id>
		<title>File:AutomatedXylophonePicture1.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:AutomatedXylophonePicture1.jpg&amp;diff=11644"/>
		<updated>2009-03-19T00:50:06Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11643</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11643"/>
		<updated>2009-03-19T00:44:01Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Team Members */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[Include pictures of interior of wooden casing] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[Insert picture of circuit and circuit diagram] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
[More description needed]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
[More information or a link necessary] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11642</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11642"/>
		<updated>2009-03-19T00:43:48Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Team Members */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|400x400 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[Include pictures of interior of wooden casing] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[Insert picture of circuit and circuit diagram] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
[More description needed]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
[More information or a link necessary] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11641</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11641"/>
		<updated>2009-03-19T00:43:24Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Team Members */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|350x350 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[Include pictures of interior of wooden casing] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[Insert picture of circuit and circuit diagram] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
[More description needed]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
[More information or a link necessary] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11640</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11640"/>
		<updated>2009-03-19T00:43:06Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Team Members */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|200x200 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[Include pictures of interior of wooden casing] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[Insert picture of circuit and circuit diagram] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
[More description needed]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
[More information or a link necessary] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11639</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11639"/>
		<updated>2009-03-19T00:42:51Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Team Members */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[[Image:AutomatedXylophoneGroup.jpg|thumb|500x500 px|right|From L to R: Jenny, Neil and Brandon]]&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[Include pictures of interior of wooden casing] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[Insert picture of circuit and circuit diagram] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
[More description needed]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
[More information or a link necessary] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:AutomatedXylophoneGroup.jpg&amp;diff=11638</id>
		<title>File:AutomatedXylophoneGroup.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:AutomatedXylophoneGroup.jpg&amp;diff=11638"/>
		<updated>2009-03-19T00:41:20Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11637</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11637"/>
		<updated>2009-03-19T00:26:16Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* Next Steps */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[Include team picture] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[Include pictures of interior of wooden casing] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[Insert picture of circuit and circuit diagram] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
[More description needed]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
[More information or a link necessary] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the user to play multiple notes at the same time or chords&lt;br /&gt;
*Allowing the user to hear what notes they are programming while in edit mode&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11635</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11635"/>
		<updated>2009-03-19T00:23:14Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[Include team picture] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[Include pictures of interior of wooden casing] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[Insert picture of circuit and circuit diagram] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
[More description needed]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  To learn more about incorporating an LCD screen, check [[C Example: Parallel Interfacing with LCDs|here]]  &amp;lt;br&amp;gt;&lt;br /&gt;
[More information or a link necessary] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, we used multiplexing to interface the PIC with the keypad.  To learn more about our technique for doing so, check out our code below.  You can also learn more about multiplexing [http://en.wikipedia.org/wiki/Multiplexing here]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwari, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11634</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11634"/>
		<updated>2009-03-19T00:19:57Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[Include team picture] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our Automated Xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in real time mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* 1 PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 1 LCD Screen&lt;br /&gt;
* 1 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[Include pictures of interior of wooden casing] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[Insert picture of circuit and circuit diagram] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in edit mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.  Check out our circuit diagram to get a better idea of how we incorporated the relays into our circuit.&amp;lt;br&amp;gt;&lt;br /&gt;
[More description needed]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for edit mode.  &amp;lt;br&amp;gt;&lt;br /&gt;
[More information or a link necessary] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during edit and playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, &lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwar, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both real time mode, edit mode and playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in real time mode can be found here.  A video of our Automated Xylophone playing in playback mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11632</id>
		<title>Automated Xylophone</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Automated_Xylophone&amp;diff=11632"/>
		<updated>2009-03-19T00:13:50Z</updated>

		<summary type="html">&lt;p&gt;Jenny Yong: /* References */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
[Include team picture] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
*Brandon Robins (Senior in Mechanical Engineering and Music Performance, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Neil Tiwari (Masters Student in Biomedical Engineering and Kind of a Big Deal, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
*Jenny Yong (Senior in Mechanical Engineering, Northwestern University) &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The goal of this project was to have a user input a sequence of notes and have a PIC controlled solenoid system hit a xylophone to generate tones.  Our automated xylophone operates in two settings -- real time mode and playback mode.  In real time mode, the user inputs notes using the keypad and they get played back on the xylophone instantaneously.  In edit mode, a user can use the keypad and LCD screen to verify and store over 250 notes in sequence including rests to be played back on the xylophone while in playback mode.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Click [[ME 333 final projects|here]] to check out other Mechatronics projects!&lt;br /&gt;
&lt;br /&gt;
== Operating the Automated Xylophone ==&lt;br /&gt;
[[Image:Jameco16buttonkeypad.jpg|thumb|500x500 px|right|Keypad Arrangement]] &lt;br /&gt;
The user interface includes a keypad containing 16 buttons, arranged as shown on the right.  &lt;br /&gt;
=== Real Time Mode ===&lt;br /&gt;
Our Automated Xylophone defaults to real time mode.  In real time mode, the first two rows of buttons (1-3, A, 4-6 and B) are used to determine xylophone note.  As soon as a button is depressed, it will immediately trigger a solenoid to play the chosen note. Tp return to real time mode after entering edit mode or playback mode, you reset the PIC.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Edit Mode ===&lt;br /&gt;
To enter edit mode, you hit button *.  Edit mode allows you to store about 250 notes, including rests, per block.  Once you first enter edit mode, you must select which block you would like to store your collection of notes.  To increase the block number, use button C.  Button 9 will decrease the block number.  Once you have selected your block, you hit the enter button, button D.  Now, you are ready to begin programming notes. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As in Real Time Mode, the first two rows of buttons still determine which note to program.  Buttons 7 and 8 will adjust the note duration to longer and shorter respectively.  Buttons 9 and C will adjust the which sequential number is being programmed.  As with determining block number, button C increases the note number and button 9 will decrease the note number.  Rests can be programmed using button #.  To enter and store a note, you use the enter button, button #.  Once you have finished entering the string of notes you would like to store, you hit button 0.  Hitting this button will bring you to playback mode. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Playback Mode ===&lt;br /&gt;
The user enters playback mode after going through edit mode.  You can enter playback mode without having actually programmed anything in edit mode by simply pressing the 0 button after having entered edit mode.  Once you are in playback mode, you select which block you would like to play similar to how you programmed which box you would like to edit.  Button C will increase the block number, button 9 will decrease the block number.  To select the block and play the stored notes, you hit the # button. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parts List ==&lt;br /&gt;
=== Mechanical Components ===&lt;br /&gt;
* 8 Jameco 262262 (Pull-type) 12V Solenoids for more information look [[Actuators Available in the Mechatronics Lab|here]]&amp;lt;br&amp;gt;&lt;br /&gt;
* Wood used for housing &amp;lt;br&amp;gt;&lt;br /&gt;
* Aluminum and foam core were used to position the solenoids at the appropriate height &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Electronic Components ===&lt;br /&gt;
* PIC Microcontroller &amp;lt;br&amp;gt;&lt;br /&gt;
* Button Pad 4x4 Breakout PCB found [http://www.sparkfun.com/commerce/product_info.php?products_id=8033 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* Button Pad 4x4 Covering found [http://www.sparkfun.com/commerce/product_info.php?products_id=7835 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* LCD Screen&lt;br /&gt;
* 24FC1025 EEPROM whose data sheet can be found [http://ww1.microchip.com/downloads/en/DeviceDoc/21941B.pdf here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Jameco Shinmei 2A 5V DPDT Relay RSB-5-S &amp;lt;br&amp;gt;&lt;br /&gt;
* 8 Small Signal Diodes found [http://www.sparkfun.com/commerce/product_info.php?products_id=8588 here] &amp;lt;br&amp;gt;&lt;br /&gt;
* 6 1k resistors&lt;br /&gt;
* 4 NPN transistors&lt;br /&gt;
* 1k potentiometer&lt;br /&gt;
&lt;br /&gt;
=== The Xylophone ===&lt;br /&gt;
The xylophone that we selected can be found and purchased [http://www.amazon.com/Little-Tikes-Jungle-Jamboree-Xylophone/dp/B00005M9JB/ref=sr_1_9/191-4560003-3684936?ie=UTF8&amp;amp;s=toys-and-games&amp;amp;qid=1237343534&amp;amp;sr=1-9 here].&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
We decided to incorporate solenoids into our design as a method to strike the xylophone keys.  Solenoids are on-off actuators consisting of a plunger moving in an electromagnetic field.  Since we decided to use pull-type solenoids, when the solenoids are powered, the plunger is &amp;quot;pulled&amp;quot; or attracted to the powered coils.  For more information on solenoids, check out [[Actuators Available in the Mechatronics Lab]].&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[Include pictures of interior of wooden casing] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Mechanical Interface === &lt;br /&gt;
Our mechanical design was fairly simple and straightforward.  We needed to determine the optimal way for the solenoids to hit the xylophone keys, and a way to support them in that position.  Initially, we found it to be most intuitive for the solenoids to strike downward onto the keys.  However, that design would require us to keep the solenoids powered during rest.  Therefore, we choose to have our solenoids strike from below the xylophone which allows us to keep them powered off while inactive. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One feature of our mechanical design is that with the xylophone chosen as the bars are hit, the piano keys depress.  This design creates the appearance of a phantom piano player. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Solenoid Positioning ===&lt;br /&gt;
To improve aesthetics and support the xylophone at the proper height, we created a wooden housing for the solenoids.  Within the housing, our solenoids rest on an aluminum beam which hold them at the appropriate height.  On our aluminum beam, we have a ladder-like structure made of foam core to hold the solenoids in place.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Foam core was also placed underneath each bar of the xylophone, as is shown.  The purpose of this addition was to allow a greater acceptable surface for the solenoid to interact with the xylophone.  Tape was also placed around the piston of the solenoids, as can be seen in the photos.  This technique was a temporary solution to prevent the solenoids from banging on the aluminum beam and keep them at an operable height once powered at 12 V. The xylophone is placed on top of the wooden housing with the bars properly aligned with the solenoids. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electrical Design ==&lt;br /&gt;
=== Circuit Diagram ===&lt;br /&gt;
[Insert picture of circuit and circuit diagram] &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Creating the Automated Xylophone did require some intricate circuitry, as can be seen in the picture of our circuit and our circuit diagram.  The most complicated aspects included powering our solenoids using an external power supply and relays, connecting the LCD screen to our PIC and using an EEPROM to store our song information in playback mode.  More detailed descriptions of these steps can be found below.  &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Powering the Solenoids ===&lt;br /&gt;
Since the solenoids need to operate at full voltage and required a lot of current, we were unable to power them using the PIC.  Instead, we worked with an external power supply and relays.&amp;lt;br&amp;gt;&lt;br /&gt;
[More description needed]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connecting the LCD ===&lt;br /&gt;
The LCD screen allows the user to monitor his progress in programming for Playback Mode.  &amp;lt;br&amp;gt;&lt;br /&gt;
[More information or a link necessary] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using an EEPROM ===&lt;br /&gt;
For our Automated Xylophone, an EEPROM is used to store all of the note information during playback mode.  More information on connecting an EEPROM to a PIC can be found [[Data logging with an EEPROM|here]] and [[Interfacing to External EEPROM|here]]. &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
Within our code, &lt;br /&gt;
=== Commented Main Code File ===&lt;br /&gt;
&amp;lt;pre&amp;gt;  &lt;br /&gt;
//Brandon Robins, Neil Tiwar, Jennifer Yong&lt;br /&gt;
//Team 24: Automated Xylophone Final Code&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT       &lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)    // use hardware i2c controller&lt;br /&gt;
#define EEPROM_WR 0xA0                // Define initial EEPROM write address block (See EEPROM data sheet)&lt;br /&gt;
#define EEPROM_RD 0xA1                // Define initial EEPROM read address block (See EEPROM data sheet)&lt;br /&gt;
#define LED_GND1  PIN_C7              // Define LED GND pins&lt;br /&gt;
#define LED_GND2  PIN_E1              &lt;br /&gt;
#define LED_GND3  PIN_E2&lt;br /&gt;
#define LED_GND4  PIN_C6&lt;br /&gt;
/*#define SWT_GND1  PIN_C0       // Already defined in key.c as col0-3&lt;br /&gt;
#define SWT_GND2  PIN_C1&lt;br /&gt;
#define SWT_GND3  PIN_C2&lt;br /&gt;
#define SWT_GND4  PIN_C5&lt;br /&gt;
#define SWITCH1  PIN_B1          // Already defined in key.c as row0-3&lt;br /&gt;
#define SWITCH2  PIN_B2&lt;br /&gt;
#define SWITCH3  PIN_B3&lt;br /&gt;
#define SWITCH4  PIN_B4 */&lt;br /&gt;
#define SOL8  PIN_D0            // Define Solenoid Output Pins&lt;br /&gt;
#define SOL7  PIN_D1&lt;br /&gt;
#define SOL6  PIN_D2&lt;br /&gt;
#define SOL5  PIN_D3&lt;br /&gt;
#define SOL4  PIN_D4&lt;br /&gt;
#define SOL3  PIN_D5&lt;br /&gt;
#define SOL2  PIN_D6&lt;br /&gt;
#define SOL1  PIN_D7&lt;br /&gt;
&lt;br /&gt;
//Include LCD and keypad multiplexing code files&lt;br /&gt;
#include &amp;quot;flex_lcd.c&amp;quot;&lt;br /&gt;
#include &amp;quot;key.c&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Define Variables&lt;br /&gt;
int block = 1, sel_note, i, j = 1, note_lengths[4] = {1 2 4 8};&lt;br /&gt;
int16 address, dis_address = 1, duration, temp_duration, temp_note, value;&lt;br /&gt;
//char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char notes[] = {&amp;quot;R&amp;quot; &amp;quot;C&amp;quot; &amp;quot;D&amp;quot; &amp;quot;E&amp;quot; &amp;quot;F&amp;quot; &amp;quot;G&amp;quot; &amp;quot;A&amp;quot; &amp;quot;B&amp;quot; &amp;quot;C&amp;quot;};&lt;br /&gt;
//char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot; &amp;quot;#&amp;quot; &amp;quot; &amp;quot;}; // for use with 12 keys and 12 solenoids&lt;br /&gt;
char note_quality[] = {&amp;quot;E&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;8&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;};&lt;br /&gt;
&lt;br /&gt;
void write_eeprom(int16 address, int16 data) //Writing to the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_write(data);&lt;br /&gt;
   i2c_stop();&lt;br /&gt;
   delay_ms(5);   //Delay time needed in order to allow EEPROM to write data from buffer to memory sector&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int16 read_eeprom(int16 address) // Reading from the EEPROM function&lt;br /&gt;
{&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_WR);&lt;br /&gt;
   i2c_write(address&amp;gt;&amp;gt;8);&lt;br /&gt;
   i2c_write(address);&lt;br /&gt;
   i2c_start();&lt;br /&gt;
   i2c_write(EEPROM_RD);  &lt;br /&gt;
   value = i2c_read(0);&lt;br /&gt;
   i2c_stop(); &lt;br /&gt;
   return(value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Edit Address Block allows you to change which address block is being written too&lt;br /&gt;
int edit_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
while(1){&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fEdit Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;D&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//This part of the code lets the user select keys for use in edit mode&lt;br /&gt;
void key_select()&lt;br /&gt;
{&lt;br /&gt;
dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
sel_note = read_eeprom(address);&lt;br /&gt;
duration = read_eeprom(address+1);&lt;br /&gt;
if (sel_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
//if (duration &amp;gt; 8) duration = 2;&lt;br /&gt;
duration = note_lengths[1];&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
   while (1) {&lt;br /&gt;
 &lt;br /&gt;
   keypress = kbd_getc(); //Get keypad input from key.c&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;1&#039;) {&lt;br /&gt;
         sel_note = 1;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;2&#039;) {&lt;br /&gt;
         sel_note = 2;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;3&#039;) {&lt;br /&gt;
         sel_note = 3;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;A&#039;) {&lt;br /&gt;
         sel_note = 4;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;4&#039;) {&lt;br /&gt;
         sel_note = 5;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;5&#039;) {&lt;br /&gt;
         sel_note = 6;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;6&#039;) {&lt;br /&gt;
         sel_note = 7;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;B&#039;) {&lt;br /&gt;
         sel_note = 8;      &lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;7&#039;) &amp;amp;&amp;amp; (j &amp;lt; 3)) {&lt;br /&gt;
         //sel_note = 9;&lt;br /&gt;
         j++;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;8&#039;) &amp;amp;&amp;amp; (j &amp;gt; 0)) {&lt;br /&gt;
         //sel_note = 10;&lt;br /&gt;
         j--;&lt;br /&gt;
         duration = note_lengths[j];&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (dis_address &amp;lt; 250)) {&lt;br /&gt;
         address+=2;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (dis_address &amp;gt; 1)) {&lt;br /&gt;
         address-=2;&lt;br /&gt;
         dis_address--;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;) {&lt;br /&gt;
         //real_time_mode();&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;0&#039;) {&lt;br /&gt;
         break;&lt;br /&gt;
      }     &lt;br /&gt;
      if (keypress == &#039;#&#039;) {&lt;br /&gt;
         sel_note = 0;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // The D key acts like the Enter key. In this case this allows for writing to the EEPROM.&lt;br /&gt;
      if (keypress == &#039;D&#039;) {    &lt;br /&gt;
         write_eeprom(address,sel_note);&lt;br /&gt;
         address++;&lt;br /&gt;
         write_eeprom(address,duration);&lt;br /&gt;
         address++;&lt;br /&gt;
         dis_address++;&lt;br /&gt;
         temp_note = read_eeprom(address);&lt;br /&gt;
         temp_duration = read_eeprom(address+1);&lt;br /&gt;
            if (temp_note &amp;gt; 12) sel_note = 1;&lt;br /&gt;
            else sel_note = temp_note;&lt;br /&gt;
           &lt;br /&gt;
            if (temp_duration &amp;gt; 8) duration = 2;&lt;br /&gt;
            else duration = temp_duration;&lt;br /&gt;
         printf(lcd_putc,&amp;quot;\f%02d/%03lu-Note: %c%c \nDuration: %1lu beat&amp;quot;,block,dis_address,notes[sel_note],note_quality[sel_note],duration);&lt;br /&gt;
      }    &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In Playback mode user can select which address block to play. The xylophone then plays this address block back.&lt;br /&gt;
int playback_block_select()&lt;br /&gt;
{&lt;br /&gt;
char keypress;&lt;br /&gt;
kbd_init();&lt;br /&gt;
printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
   while(1){&lt;br /&gt;
      keypress = kbd_getc();&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;C&#039;) &amp;amp;&amp;amp; (block &amp;lt; 10)){&lt;br /&gt;
      block++;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      if ((keypress == &#039;9&#039;) &amp;amp;&amp;amp; (block &amp;gt; 1)){&lt;br /&gt;
      block--;&lt;br /&gt;
      printf(lcd_putc,&amp;quot;\fPlay Address\n  Block # %02d&amp;quot;,block);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if (keypress == &#039;#&#039;){&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
      if (keypress == &#039;*&#039;){&lt;br /&gt;
      return block;&lt;br /&gt;
      break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void playback_mode()&lt;br /&gt;
{&lt;br /&gt;
   playback_block_select();&lt;br /&gt;
   dis_address = 1;&lt;br /&gt;
   if (block == 1) address = 0;&lt;br /&gt;
   if (block == 2) address = 500;&lt;br /&gt;
   if (block == 3) address = 1000;&lt;br /&gt;
   if (block == 4) address = 1500;&lt;br /&gt;
   if (block == 5) address = 2000;&lt;br /&gt;
   if (block == 6) address = 2500;&lt;br /&gt;
   if (block == 7) address = 3000;&lt;br /&gt;
   if (block == 8) address = 3500;&lt;br /&gt;
   if (block == 9) address = 4000;&lt;br /&gt;
   if (block == 10) address = 4500;&lt;br /&gt;
&lt;br /&gt;
      for (i=0; i&amp;lt;250; i++){&lt;br /&gt;
           value = read_eeprom(address); // Send data from analog input to write function  &lt;br /&gt;
           printf(lcd_putc,&amp;quot;\fAddress: %03lu\nNote: %c%c&amp;quot;,dis_address,notes[value],note_quality[value]);&lt;br /&gt;
           delay_ms(250);&lt;br /&gt;
           if (value == 1){&lt;br /&gt;
              output_high(SOL1);            //This section outputs the lows and highs to the solenoids in order to hit the keys&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 2){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 3){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 4){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 5){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 6){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 7){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (value == 8){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           address+=2;&lt;br /&gt;
           dis_address++;&lt;br /&gt;
      }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//In real time mode the user presses a key and the solenoids are activated to hit the keys&lt;br /&gt;
void real_time_mode()&lt;br /&gt;
{&lt;br /&gt;
kbd_init();&lt;br /&gt;
lcd_putc(&amp;quot;\fReal Time Mode\n&amp;quot;);&lt;br /&gt;
   while (1) {&lt;br /&gt;
   keypress = kbd_getc();&lt;br /&gt;
           if (keypress == &#039;1&#039;){&lt;br /&gt;
              output_high(SOL1);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL1);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;2&#039;){&lt;br /&gt;
              output_high(SOL2);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL2);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;3&#039;){&lt;br /&gt;
              output_high(SOL3);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL3);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;A&#039;){&lt;br /&gt;
              output_high(SOL4);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL4);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;4&#039;){&lt;br /&gt;
              output_high(SOL5);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL5);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;5&#039;){&lt;br /&gt;
              output_high(SOL6);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL6);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;6&#039;){&lt;br /&gt;
              output_high(SOL7);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL7);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;B&#039;){&lt;br /&gt;
              output_high(SOL8);&lt;br /&gt;
              delay_ms(100);&lt;br /&gt;
              output_low(SOL8);&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;*&#039;){&lt;br /&gt;
               edit_block_select();&lt;br /&gt;
               key_select();&lt;br /&gt;
           }&lt;br /&gt;
           if (keypress == &#039;0&#039;){&lt;br /&gt;
               playback_mode();&lt;br /&gt;
           }&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Where the code starts&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   lcd_init();  // Always call this first.&lt;br /&gt;
   lcd_putc(&amp;quot;\fHello There...\n&amp;quot;);&lt;br /&gt;
   kbd_init();&lt;br /&gt;
   real_time_mode();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Commented LED Code ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// flex_lcd.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LCD_DB4   PIN_A3&lt;br /&gt;
#define LCD_DB5   PIN_A2&lt;br /&gt;
#define LCD_DB6   PIN_A1&lt;br /&gt;
#define LCD_DB7   PIN_A0&lt;br /&gt;
&lt;br /&gt;
#define LCD_RS    PIN_E0&lt;br /&gt;
#define LCD_RW    PIN_A5&lt;br /&gt;
#define LCD_E     PIN_A4 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define USE_LCD_RW   1     &lt;br /&gt;
&lt;br /&gt;
//========================================&lt;br /&gt;
&lt;br /&gt;
#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines&lt;br /&gt;
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int8 const LCD_INIT_STRING[4] =&lt;br /&gt;
{&lt;br /&gt;
 0x20 | (lcd_type &amp;lt;&amp;lt; 2), // Func set: 4-bit, 2 lines, 5x8 dots&lt;br /&gt;
 0xc,                    // Display on&lt;br /&gt;
 1,                      // Clear display&lt;br /&gt;
 6                       // Increment cursor&lt;br /&gt;
 };&lt;br /&gt;
                             &lt;br /&gt;
&lt;br /&gt;
//-------------------------------------&lt;br /&gt;
void lcd_send_nibble(int8 nibble)&lt;br /&gt;
{&lt;br /&gt;
// Note:  !! converts an integer expression&lt;br /&gt;
// to a boolean (1 or 0).&lt;br /&gt;
 output_bit(LCD_DB4, !!(nibble &amp;amp; 1));&lt;br /&gt;
 output_bit(LCD_DB5, !!(nibble &amp;amp; 2)); &lt;br /&gt;
 output_bit(LCD_DB6, !!(nibble &amp;amp; 4));   &lt;br /&gt;
 output_bit(LCD_DB7, !!(nibble &amp;amp; 8));   &lt;br /&gt;
&lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
 output_high(LCD_E);&lt;br /&gt;
 delay_us(2);&lt;br /&gt;
 output_low(LCD_E);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------&lt;br /&gt;
// This sub-routine is only called by lcd_read_byte().&lt;br /&gt;
// It&#039;s not a stand-alone routine.  For example, the&lt;br /&gt;
// R/W signal is set high by lcd_read_byte() before&lt;br /&gt;
// this routine is called.     &lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_nibble(void)&lt;br /&gt;
{&lt;br /&gt;
int8 retval;&lt;br /&gt;
// Create bit variables so that we can easily set&lt;br /&gt;
// individual bits in the retval variable.&lt;br /&gt;
#bit retval_0 = retval.0&lt;br /&gt;
#bit retval_1 = retval.1&lt;br /&gt;
#bit retval_2 = retval.2&lt;br /&gt;
#bit retval_3 = retval.3&lt;br /&gt;
&lt;br /&gt;
retval = 0;&lt;br /&gt;
   &lt;br /&gt;
output_high(LCD_E);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
retval_0 = input(LCD_DB4);&lt;br /&gt;
retval_1 = input(LCD_DB5);&lt;br /&gt;
retval_2 = input(LCD_DB6);&lt;br /&gt;
retval_3 = input(LCD_DB7);&lt;br /&gt;
 &lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
   &lt;br /&gt;
return(retval);   &lt;br /&gt;
}   &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//---------------------------------------&lt;br /&gt;
// Read a byte from the LCD and return it.&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
int8 lcd_read_byte(void)&lt;br /&gt;
{&lt;br /&gt;
int8 low;&lt;br /&gt;
int8 high;&lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
high = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
low = lcd_read_nibble();&lt;br /&gt;
&lt;br /&gt;
return( (high&amp;lt;&amp;lt;4) | low);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//----------------------------------------&lt;br /&gt;
// Send a byte to the LCD.&lt;br /&gt;
void lcd_send_byte(int8 address, int8 n)&lt;br /&gt;
{&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)) ;&lt;br /&gt;
#else&lt;br /&gt;
delay_us(60); &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
if(address)&lt;br /&gt;
   output_high(LCD_RS);&lt;br /&gt;
else&lt;br /&gt;
   output_low(LCD_RS);&lt;br /&gt;
     &lt;br /&gt;
 delay_cycles(1);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
delay_cycles(1);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(n &amp;gt;&amp;gt; 4);&lt;br /&gt;
lcd_send_nibble(n &amp;amp; 0xf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
void lcd_init(void)&lt;br /&gt;
{&lt;br /&gt;
int8 i;&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_RS);&lt;br /&gt;
&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
output_low(LCD_RW);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
output_low(LCD_E);&lt;br /&gt;
&lt;br /&gt;
delay_ms(15);&lt;br /&gt;
&lt;br /&gt;
for(i=0 ;i &amp;lt; 3; i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_nibble(0x03);&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
lcd_send_nibble(0x02);&lt;br /&gt;
&lt;br /&gt;
for(i=0; i &amp;lt; sizeof(LCD_INIT_STRING); i++)&lt;br /&gt;
   {&lt;br /&gt;
    lcd_send_byte(0, LCD_INIT_STRING[i]);&lt;br /&gt;
   &lt;br /&gt;
    // If the R/W signal is not used, then&lt;br /&gt;
    // the busy bit can&#039;t be polled.  One of&lt;br /&gt;
    // the init commands takes longer than&lt;br /&gt;
    // the hard-coded delay of 60 us, so in&lt;br /&gt;
    // that case, lets just do a 5 ms delay&lt;br /&gt;
    // after all four of them.&lt;br /&gt;
    #ifndef USE_LCD_RW&lt;br /&gt;
    delay_ms(5);&lt;br /&gt;
    #endif&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//----------------------------&lt;br /&gt;
&lt;br /&gt;
void lcd_gotoxy(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
int8 address;&lt;br /&gt;
&lt;br /&gt;
if(y != 1)&lt;br /&gt;
   address = lcd_line_two;&lt;br /&gt;
else&lt;br /&gt;
   address=0;&lt;br /&gt;
&lt;br /&gt;
address += x-1;&lt;br /&gt;
lcd_send_byte(0, 0x80 | address);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//-----------------------------&lt;br /&gt;
void lcd_putc(char c)&lt;br /&gt;
{&lt;br /&gt;
 switch(c)&lt;br /&gt;
   {&lt;br /&gt;
    case &#039;\f&#039;:&lt;br /&gt;
      lcd_send_byte(0,1);&lt;br /&gt;
      delay_ms(2);&lt;br /&gt;
      break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\n&#039;:&lt;br /&gt;
       lcd_gotoxy(1,2);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    case &#039;\b&#039;:&lt;br /&gt;
       lcd_send_byte(0,0x10);&lt;br /&gt;
       break;&lt;br /&gt;
   &lt;br /&gt;
    default:&lt;br /&gt;
       lcd_send_byte(1,c);&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//------------------------------&lt;br /&gt;
#ifdef USE_LCD_RW&lt;br /&gt;
char lcd_getc(int8 x, int8 y)&lt;br /&gt;
{&lt;br /&gt;
char value;&lt;br /&gt;
&lt;br /&gt;
lcd_gotoxy(x,y);&lt;br /&gt;
&lt;br /&gt;
// Wait until busy flag is low.&lt;br /&gt;
while(bit_test(lcd_read_byte(),7)); &lt;br /&gt;
&lt;br /&gt;
output_high(LCD_RS);&lt;br /&gt;
value = lcd_read_byte();&lt;br /&gt;
output_low(lcd_RS);&lt;br /&gt;
&lt;br /&gt;
return(value);&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Commented Keypad Code===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//=============================&lt;br /&gt;
&lt;br /&gt;
//Keypad connection:&lt;br /&gt;
#define row0 PIN_B1&lt;br /&gt;
#define row1 PIN_B2&lt;br /&gt;
#define row2 PIN_B3&lt;br /&gt;
#define row3 PIN_B4&lt;br /&gt;
#define col0 PIN_C0&lt;br /&gt;
#define col1 PIN_C1&lt;br /&gt;
#define col2 PIN_C2&lt;br /&gt;
#define col3 PIN_C5&lt;br /&gt;
&lt;br /&gt;
// Keypad layout:&lt;br /&gt;
char const KEYS[4][4] =&lt;br /&gt;
{{&#039;A&#039;,&#039;3&#039;,&#039;2&#039;,&#039;1&#039;},&lt;br /&gt;
 {&#039;B&#039;,&#039;6&#039;,&#039;5&#039;,&#039;4&#039;},&lt;br /&gt;
 {&#039;C&#039;,&#039;9&#039;,&#039;8&#039;,&#039;7&#039;},&lt;br /&gt;
 {&#039;D&#039;,&#039;#&#039;,&#039;0&#039;,&#039;*&#039;}};&lt;br /&gt;
&lt;br /&gt;
char keypress;&lt;br /&gt;
&lt;br /&gt;
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where&lt;br /&gt;
// n is the number of times you expect&lt;br /&gt;
// to call kbd_getc each second&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//initialize keypad&lt;br /&gt;
void kbd_init()&lt;br /&gt;
{&lt;br /&gt;
//set_tris_b(0xF0);&lt;br /&gt;
//output_b(0xF0);&lt;br /&gt;
port_b_pullups(true); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//set all rows to high&lt;br /&gt;
short int ALL_ROWS (void)&lt;br /&gt;
{&lt;br /&gt;
if(input (row0) &amp;amp; input (row1) &amp;amp; input (row2) &amp;amp; input (row3))&lt;br /&gt;
   return (0);&lt;br /&gt;
else&lt;br /&gt;
   return (1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
char kbd_getc()&lt;br /&gt;
{&lt;br /&gt;
static byte kbd_call_count;&lt;br /&gt;
static short int kbd_down;&lt;br /&gt;
static char last_key;&lt;br /&gt;
static byte col;&lt;br /&gt;
&lt;br /&gt;
byte kchar;&lt;br /&gt;
byte row;&lt;br /&gt;
&lt;br /&gt;
kchar=&#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
//pulse various columns with high&lt;br /&gt;
if(++kbd_call_count&amp;gt;KBD_DEBOUNCE_FACTOR)&lt;br /&gt;
  {&lt;br /&gt;
   switch (col)&lt;br /&gt;
     {&lt;br /&gt;
      case 0:&lt;br /&gt;
        output_low(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
   &lt;br /&gt;
      case 1:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_low(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 2:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_low(col2);&lt;br /&gt;
        output_high(col3);&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case 3:&lt;br /&gt;
        output_high(col0);&lt;br /&gt;
        output_high(col1);&lt;br /&gt;
        output_high(col2);&lt;br /&gt;
        output_low(col3);&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
   if(kbd_down)&lt;br /&gt;
     {&lt;br /&gt;
      if(!ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         kbd_down=false;&lt;br /&gt;
         kchar=last_key;&lt;br /&gt;
         last_key=&#039;\0&#039;;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   else&lt;br /&gt;
     {&lt;br /&gt;
      if(ALL_ROWS())&lt;br /&gt;
        {&lt;br /&gt;
         if(!input (row0))&lt;br /&gt;
            row=0;&lt;br /&gt;
         else if(!input (row1))&lt;br /&gt;
            row=1;&lt;br /&gt;
         else if(!input (row2))&lt;br /&gt;
            row=2;&lt;br /&gt;
         else if(!input (row3))&lt;br /&gt;
            row=3;&lt;br /&gt;
&lt;br /&gt;
         last_key =KEYS[row][col];&lt;br /&gt;
         kbd_down = true;&lt;br /&gt;
        }&lt;br /&gt;
      else&lt;br /&gt;
        {&lt;br /&gt;
         ++col;&lt;br /&gt;
         if(col==4)&lt;br /&gt;
            col=0;&lt;br /&gt;
        }&lt;br /&gt;
     }&lt;br /&gt;
   kbd_call_count=0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
//return the detected key&lt;br /&gt;
return(kchar);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results and Next Steps ==&lt;br /&gt;
=== Results ===&lt;br /&gt;
Our Automated Xylophone operated as expected, with full capability in both Real Time Mode and Playback Mode.  We were also able to get excellent sound on our xylophone.  A video of our Automated Xylophone playing in Real Time Mode can be found here.  A video of our Automated Xylophone playing in Playback Mode can be found here.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Next Steps ===&lt;br /&gt;
Given more time, potential next steps include:&amp;lt;br&amp;gt;&lt;br /&gt;
*Allowing the keypad to use wireless connectivity to send information to the xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating an enclosure for the circuitry &amp;lt;br&amp;gt;&lt;br /&gt;
*Creating a more permanent housing for the solenoids and xylophone &amp;lt;br&amp;gt;&lt;br /&gt;
*Incorporating the RGB LEDs on the Keypad &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
[[Actuators Available in the Mechatronics Lab]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Data logging with an EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Interfacing to External EEPROM]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[C Example: Parallel Interfacing with LCDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://en.wikipedia.org/wiki/Multiplexing Multiplexing]&lt;/div&gt;</summary>
		<author><name>Jenny Yong</name></author>
	</entry>
</feed>