Introduction

High Level Design

Program/Hardware Design

Results

Conclusions

Appendix A: Code

Appendix B: Schematics

Appendix C: Parts Listing 

Appendix D: Specific Tasks

References

Pictures

 

Xuemin Hang: xh24@cornell.edu

Marcel Xu: mx23@cornell.edu

 

 

Appendix A       
       
Audio Code

 

/**************AUDIO CODE FOR MUSIC SYNTHESIZER *****************/          
#include <Mega32.h>   //the chip
#include <stdio.h>       //for debugging using printf, etc
#include <Math.h>      // for sine function
 
// definitions
#define begin {
#define end   }
 
void initialize(void);              //to set up ports  
void chordsPlay(void);
 
//the following must not be registers
#pragma regalloc-  
unsigned long increment,increment2 ;
unsigned char r_char;            //received char    
unsigned int i, j;                     //index to sineTable and counter for number of iterations in the assembly loop
unsigned char notes;             //counter for number of notes played simultaneously
//flags for modulating the wave envelope
unsigned char modulate, brass, count, instrumentcount, instrumentshift;    
unsigned char sineTable[256] @0x300;  //Table of values; need location to avoid glitch   
#pragma regalloc+  
 
//**************************************************      
void main(void)
begin 
  initialize();   
 
  //main loop never exits
  while(1)
  begin
   chordsPlay();  //executes the pushbutton detection and music synthesis
  end       
end 
//**********************************************************
void chordsPlay(void) //function that detects pushbuttons and activates the digital music synthesis
begin
     if(brass==1){  //if the instrument requires waveform modulation
                if(count<instrumentcount) count++; //increment counter when not yet time for modulation
                else{ 
                     if(modulate>instrumentshift) modulate=modulate>>1;          //shift in zeroes from the left
                     count=0;           //reset counter
                }
     }
     else modulate=0xff;  //if the instrument does not require waveform modulation
    
     notes=0;   //reset counter for notes
    
     if(PINC.7==0){       // 493.883 Hz
                if(notes==0){        //if no notes played yet
                                notes=1; //one note played
                                increment = 20715;//frequency*41.94304
                }
     }
     if(PINC.6==0){               // 466.164 Hz---467           
                if(notes==0){ //if no notes played yet
                                notes=1; //one note played
                                increment = 19552;//frequency*41.94304
                     }
                     else if(notes==1){//if one note played
                                notes=2; //two notes played
                                increment2 = 19552;//frequency*41.94304
                     }
}    
if(PINC.5==0){  // 440 Hz --441   
if(notes==0){ //if no notes played yet
                                notes=1; //one note played
                                increment = 18455;//frequency*41.94304
                } 
                else if(notes==1){ //if one note played
                                notes=2;    //two notes played
                                increment2 = 18455;//frequency*41.94304
                }             
}
if(PINC.4==0){      // 415.305 Hz---416
                if(notes==0){ //if no notes played yet
                                notes=1; //one note played
                                increment = 17419;//frequency*41.94304
                     }
                else if(notes==1){ //if one note played
                                notes=2; //two notes played
                                increment2 = 17419;//frequency*41.94304
     }
}  
f(PINC.3==0){      // 391.995 Hz  ---390
                if(notes==0){ //if no notes played yet
                                notes=1; //one note played
                                increment = 16441;//frequency*41.94304
                }           
                else if(notes==1){ //if one note played
                                notes=2;  //two notes played
                                increment2 = 16441;//frequency*41.94304
     }
}
if(PINC.2==0){     // 369.994 Hz ---370
                if(notes==0){ //if no notes played yet
                                notes=1; //one note played
                                increment = 15519;//frequency*41.94304
                }           
                else if(notes==1){ //if one note played
                                notes=2; //two notes played
                                increment2 = 15519;//frequency*41.94304
                }
}   
if(PINC.1==0){    //349.228 Hz     ---350
                if(notes==0){ //if no notes played yet
                                notes=1; //one note played
                                increment = 14648;//frequency*41.94304
                }           
                else if(notes==1){ //if one note played
                                notes=2;    //two notes played
                increment2 = 14648;//frequency*41.94304
     }
 }            
if(PINC.0==0){    // 329.628 Hz     ---328
                if(notes==0){ //if no notes played yet
                                notes=1; //one note played
                                increment =13826;//frequency*41.94304
                }           
                else if(notes==1){ //if one note played
                                notes=2; //two notes played
                                increment2 = 13826;//frequency*41.94304
                }
}
if(PINB.7==0){ // 311.127 Hz --- 310
                if(notes==0){ //if no notes played yet
                                notes=1; //one note played
                                increment = 13050;//frequency*41.94304
                }           
                else if(notes==1){ //if one note played
                                notes=2; //two notes played
                                increment2 = 13050;//frequency*41.94304
                }
}
if(PINB.6==0){    //293.665 Hz --- 294
                if(notes==0){ //if no notes played yet
                                notes=1; //one note played
                                increment = 12317;//frequency*41.94304
                }           
                else if(notes==1){ //if one note played
                                notes=2; //two notes played
                                increment2 = 12317;//frequency*41.94304
                }
}
if(PINB.5==0){ //277.183 Hz --- 277
                if(notes==0){ //if no notes played yet
                                notes=1; //one note played
                                increment = 11626;//frequency*41.94304
                }           
                else if(notes==1){ //if one note played
                                notes=2; //two notes played
                                increment2 = 11626;//frequency*41.94304
                }
}
if(PINB.4==0){    //261.626 Hz --- 262
                if(notes==0){ //if no notes played yet
                                notes=1; //one note played
                                increment = 10973;//frequency*41.94304
                }            
                else if(notes==1){ //if one note played
                                notes=2; //two notes played
                                increment2 = 10973;//frequency*41.94304
                }
}
if(PINB.3==0){    //246.942 Hz --- 247
                if(notes==0){ //if no notes played yet
                                notes=1; //one note played
                                increment = 10357;//frequency*41.94304
                }           
                else if(notes==1){ //if one note played
                                notes=2; //two notes played
                                increment2 = 10357;//frequency*41.94304
                }
}
if(PINB.2==0){    //233.082 Hz --- 233
                if(notes==0){ //if no notes played yet
                                notes=1; //one note played
                                increment = 9776;//frequency*41.94304 
                }           
                else if(notes==1){ //if one note played
                                notes=2; //two notes played
                                increment2 = 9776;//frequency*41.94304
                }
}
if(PINB.1==0){    //220 Hz --- 220
                if(notes==0){ //if no notes played yet
                                notes=1; //one note played
                                increment = 9227;//frequency*41.94304
                }           
                else if(notes==1){ //if one note played
                                notes=2; //two notes played
                                increment2 = 9227;//frequency*41.94304
                }
}
if(PINB.0==0){    //207.652 Hz --- 208
                if(notes==0){ //if no notes played yet
                                notes=1; //one note played
                                increment = 8710;//frequency*41.94304
                }           
                else if(notes==1){ //if one note played
                notes=2; //two notes played
                                increment2 = 8710;//frequency*41.94304
                }
}
if(PIND.7==0){   //195.998 Hz --- 196
                if(notes==0){ //if no notes played yet
                                notes=1; //one note played
                                increment = 8221;//frequency*41.94304
                }           
                else if(notes==1){ //if one note played
                                notes=2; //two notes played
                                increment2 = 8221;//frequency*41.94304
                }
}
if(PIND.6==0){   //184.997 Hz --- 185
                if(notes==0){ //if no notes played yet
                                notes=1; //one note played
                                increment = 7759;//frequency*41.94304                
                }           
                else if(notes==1){ //if one note played
                                notes=2; //two notes played
                                increment2 = 7759;//frequency*41.94304
                }
}
if(PIND.5==0){   // 174.614 Hz --- 175
                if(notes==0){ //if no notes played yet
                                notes=1; //one note played
                                increment = 7324;//frequency*41.94304
                }           
                else if(notes==1){ //if one note played
                                notes=2; //two notes played
                                increment2 = 7324;//frequency*41.94304
                }
}
if(PIND.4==0){   // 164.814 Hz --- 165
                if(notes==0){ //if no notes played yet
                                notes=1; //one note played
                                increment = 6913;//frequency*41.94304
                }           
                else if(notes==1){ //if one note played
                                notes=2; //two notes played
                                increment2 = 6913;//frequency*41.94304
                }
}
if(PIND.3==0){   // 146.832Hz   --- 147  
                if(notes==0){ //if no notes played yet
                                notes=1; //one note played
                                increment = 6159;//frequency*41.94304
                }           
                else if(notes==1){ //if one note played
                                notes=2; //two notes played
                                increment2 = 6159;//frequency*41.94304
                }
}
if(PIND.2==0){   // 130.813 Hz  --- 131
                if(notes==0){ //if no notes played yet
                                notes=1; //one note played
                                increment = 5487;//frequency*41.94304
                }           
                else if(notes==1){ //if one note played
                                notes=2; //two notes played
                                increment2 = 5487;//frequency*41.94304
                }
}
               
if(notes==1) increment2=0;
if(notes==0) modulate=0xff;
 
if(notes>0) //one or more notes played
      begin    
                #asm
                                ;load the increment bytes into registers
                                lds r9, _increment                 
                                lds r10,_increment+1
                                lds r11, _increment+2    
                 
      
                                ;load the increment bytes into registers
                                lds r3, _increment2                               
                                lds r4,_increment2+1
                                lds r5, _increment2+2    
                               
                                ;code with *** are responsible for modulating the waveform
lds r29, _modulate                                ;load the modulation flag into register ***
         
                                ldi  R31, 0x3                           ;high byte of Z is always pointing to start of the sineTable    
                                lds  r26,_j                               ;load int j into registers
                                lds  r27,_j+1  
                                   
                                Loop:
                                ;40-cycle loop
                                                add r12, r9                              ;accumulator = accumulator + increment;  
                                                adc r13, r10                             ;24-bit accumulator: r14 is highbyte1 (r14, r13, r12)
                                                adc r14, r11                             ;increment: r11 is highbyte1 (r11,r10,r9)      
                                                mov r30, r14                       ;put highbyte1 into address Z
                                                ld  r2, Z                  ;2 cycles (load sineTable[highbyte1] at address Z to register 2)
                                               
                                                add r6, r3                                ;accumulator = accumulator + increment;  
                                                adc r7, r4                 ;24-bit accumulator: r8 is highbyte (r8, r7, r6)
                                                adc r8, r5                                 ;increment: r5 is highbyte2 (r5,r4,r3) 
                                                mov r30, r8           ;put highbyte2 into address Z
                                                ld  r15, Z                ;2 cycles (load sineTable[highbyte2] at address Z to register 15)
                                               
                                                add r15, r2                              ;add the 2 contents together
                                               
                                                sbrs r29, 0                               ;skip if bit 0 is 0 ***
                                                lsr r15                                      ;shift right (/2)  ***
                                                                    
                                                sbrs r29, 1                               ;skip if bit 1 is 0 ***
                                                lsr r15                                      ;shift right (/2)  ***
                                               
                                                sbrs r29, 2                               ;skip if bit 2 is 0 ***
                                                lsr r15                                      ;shift right (/2)  ***
                                   
                                                sbrs r29, 3                               ;skip if bit 3=0  ***
                                                lsr r15                                      ;shift right (/2)  ***
                                               
                                                sbrs r29, 4                               ;skip if bit 4 =0 ***
                                                lsr r15                                      ;shift right (/2)  ***
                                                                    
                                                sbrs r29, 5                               ;skip if bit5=0    ***
                                                lsr r15                                      ;shift right (/2)  ***
                                               
                                                sbrs r29, 6                               ;skip if bit6=0   ***
                                                lsr r15                                      ;shift right (/2) ***
                                   
                                              sbrs r29, 7                 ;skip if bit7=0  ***
                                                lsr r15                                      ;shift right (/2)***
 
                                                ;PORTA = sineTable[highbyte1] + sineTable[highbyte2]
                                                out  0x1B,r15                                        
 
               ldi r28, 0                                  ;put constants into registers
                                                ldi r25, 1                                 ;put constants into registers
                                                add r26, r25                            ;j++;   
                                                adc r27, r28
               
               
                                                cpi  r26, low(0x07d0)              ;1 cycle
                                                ldi  r28, high(0x07d0)             ;1 cycle
                                                cpc  r27, r28                            ;1 cycle
                                                brsh EndLoop                      ;while(j<2000) ( 1 cycle if false)
                                                rjmp Loop                             ;2 cycles      else, repeat the loop 
                                                                  
                                                EndLoop:
 
                                #endasm                     
                  
      end
   
               
end  
//*************************************************************************
interrupt [USART_RXC] void usart_rec(void) //implements the menu commands from the PC
begin
   r_char=UDR;                      // get a char
  
   switch(r_char){   //command depends on the representative char                               
                case 'd':   //default
                                brass=0;
                                for(i=0;i<256;i++) sineTable[i]=64+(char)(63.5*sin(6.283*((float)i)/256.0));
                                break;                                     
                                                                  
                                                                                                                                               
                //WOODWINDS
                                                                               
                case 'c':     //clarinet sound ....very good (clarinet and bass clarinet) ----------- DEMO  
                                brass=0;
                                for(i=0;i<256;i++) sineTable[i]=64+(char)((19.01 *sin(6.283*((float)i)/256.0)) + (0.76 *sin(2*6.283*((float)i)/256.0))+ (18.82*sin(3*6.283*((float)i)/256.0)) + (2.28*sin(4*6.283*((float)i)/256.0)) + (10.08*sin(5*6.283*((float)i)/256.0)) + (2.09 *sin(6*6.283*((float)i)/256.0))+ (4.94*sin(7*6.283*((float)i)/256.0)) + (0.95 *sin(8*6.283*((float)i)/256.0))+(4.56*sin(9*6.283*((float)i)/256.0)));
                                break;                                                                                     
                                                                                  
                case 'f':     //flute sound 
                                brass=0;
                                for(i=0;i<256;i++) sineTable[i]=64+(char)((29.81 *sin(6.283*((float)i)/256.0)) + (23.95*sin(2*6.283*((float)i)/256.0)) + (5.37*sin(3*6.283*((float)i)/256.0)) + (3.28*sin(4*6.283*((float)i)/256.0)) + (1.49*sin(5*6.283*((float)i)/256.0)) + (0.596*sin(6*6.283*((float)i)/256.0)));
                                break;  
                               
                case 'p':   //piccolo
                                brass=0;
                                for(i=0;i<256;i++) sineTable[i]=64+(char)((29.81 *sin(2*6.283*((float)i)/256.0)) + (23.95*sin(4*6.283*((float)i)/256.0)) + (5.37*sin(6*6.283*((float)i)/256.0)) + (3.28*sin(8*6.283*((float)i)/256.0)) + (1.49*sin(10*6.283*((float)i)/256.0)) + (0.596*sin(12*6.283*((float)i)/256.0)));
                                break;                                                                                                                                     
                                          
                case 'o':    //oboe sound
                                for(i=0;i<256;i++) sineTable[i]=64+(char)((3.01*sin(6.283*((float)i)/256.0)) + (11.14*sin(2*6.283*((float)i)/256.0))+ (10.08*sin(3*6.283*((float)i)/256.0)) + (17.33*sin(4*6.283*((float)i)/256.0)) + (9.905*sin(5*6.283*((float)i)/256.0)) + (6.72*sin(6*6.283*((float)i)/256.0))+ (3.36*sin(7*6.283*((float)i)/256.0))+ (0.0884*sin(8*6.283*((float)i)/256.0)) + (0.531*sin(9*6.283*((float)i)/256.0)));
                                brass=1;
                                instrumentcount=40;
                                instrumentshift=0x7f;
                                break;     
                                                                               
                                                                                                                                         
                //BRASS
                                                                               
                case 'h':    //horn long sound (good for lower octave)            
                                for(i=0;i<256;i++) sineTable[i]=64+(char)((24.8 *sin(6.283*((float)i)/256.0)) + (22.076*sin(2*6.283*((float)i)/256.0))+ (12.4*sin(3*6.283*((float)i)/256.0)) + (3.72*sin(4*6.283*((float)i)/256.0)) + (0.248*sin(5*6.283*((float)i)/256.0)) + (0.248*sin(8*6.283*((float)i)/256.0)));
                                brass=1;
                                instrumentcount=50;
                                instrumentshift=0x7f;
                                break;       
                                                                               
                case 'i':     //horn bounce sound (good for lower octave)
                                for(i=0;i<256;i++) sineTable[i]=64+(char)((24.8 *sin(6.283*((float)i)/256.0)) + (22.076*sin(2*6.283*((float)i)/256.0))+ (12.4*sin(3*6.283*((float)i)/256.0)) + (3.72*sin(4*6.283*((float)i)/256.0)) + (0.248*sin(5*6.283*((float)i)/256.0)) + (0.248*sin(8*6.283*((float)i)/256.0)));
                                brass=1;
                                instrumentcount=30;
                                instrumentshift=0;
                                break;                                     
                                                                                                  
                case 't':     //trombone long sound (good for lower octave) ----------- DEMO    
                                for(i=0;i<256;i++) sineTable[i]=64+(char)((4.12*sin(6.283*((float)i)/256.0)) + (19.42*sin(2*6.283*((float)i)/256.0))+ (37.35*sin(3*6.283*((float)i)/256.0)) + (0.374*sin(4*6.283*((float)i)/256.0)) + (1.494*sin(5*6.283*((float)i)/256.0)) + (0.747*sin(6*6.283*((float)i)/256.0)));
                                brass=1;
                                instrumentcount=45;
                                instrumentshift=0x7f;
                                break;   
                                                                                                                                                               
                 case 'u':   //trombone bounce sound (good for lower octave) ----------- DEMO  
                                for(i=0;i<256;i++) sineTable[i]=64+(char)((4.12*sin(6.283*((float)i)/256.0)) + (19.42*sin(2*6.283*((float)i)/256.0))+ (37.35*sin(3*6.283*((float)i)/256.0)) + (0.374*sin(4*6.283*((float)i)/256.0)) + (1.494*sin(5*6.283*((float)i)/256.0)) + (0.747*sin(6*6.283*((float)i)/256.0)));
                                brass=1;
                                instrumentcount=30;
                                instrumentshift=0x0;
                                break;              
                                 
                case 'r': //trumpet long sound
                                for(i=0;i<256;i++) sineTable[i]=(char)(0.5*i);
                                brass=1;                                
                                instrumentcount=20;
                                instrumentshift=0x7f;
                                break;                        
                                                          
                case 's': //trumpet bouncesound
                                for(i=0;i<256;i++) sineTable[i]=(char)(0.5*i);
                                brass=1;                                
                                instrumentcount=20;
                                instrumentshift=0;
                                break;                
                                                                               
                                                                               
                                //STRINGS  
                               
                case 'z':    //guitar (plucked string) ----------- DEMO
                                for(i=0;i<256;i++) sineTable[i]=64+(char)((4.12*sin(2*6.283*((float)i)/256.0)) + (20.1*sin(4*6.283*((float)i)/256.0))+ (37.35*sin(6*6.283*((float)i)/256.0)) + (0.374*sin(8*6.283*((float)i)/256.0)) + (1.494*sin(10*6.283*((float)i)/256.0)) );
                                    brass=1;
                                    instrumentcount=15;
                                instrumentshift=0;
                                break;                                                  
                                                                                                               
        //PERCUSSION
 
case 'y':     //steel drum
                                for(i=0;i<256;i++) sineTable[i]=64+(char)((sin(6.283*((float)i)/256.0)) + (19.42*sin(2*6.283*((float)i)/256.0))+ (37.35*sin(3*6.283*((float)i)/256.0))); 
                                brass=1;
                                instrumentcount=8;
                                instrumentshift=0x0;
                                break; 
                                                                               
 
   }
end 
//**********************************************************
//Set it all up
void initialize(void)
begin
  UCSRB = 0x98 ;//enable RxC,Rx,Tx
  UBRRL = 103 ;   //using a 16 MHz crystal (9600)
 
  //set up the ports  
  DDRD=0x00;     // PORT D is an input with pullup
  PORTD=0xff;
  DDRB=0x00;      // PORT B is an input with pullup
  PORTB=0xff; 
  DDRC=0x00;      // PORT C is an input with pullup
  PORTC=0xff;            
 
  DDRA=0xff;    // PORT A is an output 
  PORTA=0;
 
  //make sine table
  for(i=0;i<256;i++) sineTable[i]=64+(char)(63.5*sin(6.283*((float)i)/256.0)); 
 
  //init the flags
  increment = 0;  
  increment2=0;
 
  notes=0;
  j=1; 
  modulate=0xff;     
  brass=1;
  count=0;
  instrumentcount=0;
  instrumentshift=0xff;
 
  //crank up the ISRs
  #asm
                sei
                clr r14
                clr r13  
                clr r12 
                clr r6
                clr r7