Advertisement
Guest User

DJSpooky's MIDI Controller

a guest
Oct 23rd, 2017
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.62 KB | None | 0 0
  1.  /*
  2.   *  David Welch and Joe Weber (DJ Spooky)
  3.   *  Professor Holcomb
  4.   *  ECE 353: Computer Systems Lab I
  5.   *  Project 2
  6.   *  MIDI Controller
  7.   *
  8.   */
  9.  
  10. #include <io.h>
  11. #include <avr/interrupt.h>
  12. #include <avr/delay.h>
  13. #include <avr/eeprom.h>
  14.  
  15. void initializeTimer()
  16. {
  17.     OCR1A = 0x07A1;         // COMPA Interrupt value (Should be 0x07A1, but is off by factor of 4)
  18.     TCCR1B |= (1 << CS10);  // Prescaler = 1024
  19.     TCCR1B |= (1 << CS12);
  20.     TIMSK |= (1 << OCIE1A); // Enable interrupt when Timer1 = OCR1A
  21.     sei();                  // Enable global interrupts
  22. }
  23.  
  24. // Sets up different things as different stuff
  25. void setRegisters()
  26. {
  27.     // I/O enables
  28.     DDRA = 0x00;                // Set PINA as input
  29.     DDRB = 0xFF;                // Set PORTB as output
  30.     DDRD = 0x40;                // Set the one pin on PORTD to output
  31.    
  32.     // Timer sets & enables
  33.     UBRRH = 0x00; UBRRL = 0x07; // Set Universal Baud Rate Register to 7
  34.     UCSRB |= (1 << RXEN);       // Enable Receiver
  35.     UCSRB |= (1 << TXEN);       // Enable Transmitter
  36.  
  37.     // Analong to Digital Converter enables
  38.     ADMUX |= (1 << MUX2);       // Analog Channel & Gain Selection||Single Ended Input ADC7
  39.     ADMUX |= (1 << MUX1);       //                                ||
  40.     ADMUX |= (1 << MUX0);       //                                ||
  41.     ADCSRA |= (1 << ADEN);      // ADC Enable
  42. }
  43.  
  44. // Called when TCNT1 = OCR1A
  45. ISR(TIMER1_COMPA_vect)
  46. {
  47.     PORTB = 0x00; // Turn off the LED... Its been 500ms
  48. }
  49.  
  50. int main(void)
  51. {
  52.     initializeTimer();            // Initialize the timer
  53.     setRegisters();               // Sets up different things as different stuff
  54.  
  55.     uint16_t light;               // The digital light value (0 - 1024)
  56.     uint16_t t;                   // TCNT1
  57.     uint16_t gahbage;             // Enables TCNT1H and TCNT1L to be read
  58.     uint8_t* eepromAddress;       // EEPROM Address (Byte addressable)
  59.     uint8_t* eA;                  // EEPROM Address (Byte addressable)
  60.     uint8_t status, data1, data2; // Define our 3 bytes of data
  61.     uint8_t t1, t2;               // First and 2nd timer bytes
  62.     uint8_t nothing;              // Filters out junk in the write UDR
  63.     uint8_t flag = 0;             // Determines if we were in record mode or not the previous loop
  64.     uint8_t mod = 1;              // Modulates the signal based on the light sensor data
  65.    
  66.     // Loop continuously
  67.     while(1){
  68.         // Mode 1: Recording
  69.         // Mode 2: Playback
  70.         // Mode 3: Playback & Modify (Mode 2 modifier)
  71.  
  72.         // RECORDING - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  73.         if(PINA & (1 << 0)){
  74.            
  75.             // If we're coming into record from another function
  76.             if(!flag){
  77.                 flag = 1;          // Set flag
  78.                 eepromAddress = 1; // Reset stored MIDI data
  79.                 TCNT1 = 0;         // Reset clock
  80.             }
  81.  
  82.             if(UCSRA & (1 << RXC)){ // When there's data
  83.  
  84.                 // We've got the first byte of data!
  85.                 status = UDR;  // UDR = USART Data Register (RXB)
  86.  
  87.                 // Wait for the 2nd byte
  88.                 while(!(UCSRA & (1 << RXC)));
  89.                 data1 = UDR;   // Read the note
  90.                 // If the note is being played (as opposed to stopped)
  91.                 if (status != 0x80)
  92.                     PORTB = data1; // Make the LED bar correspond to the note
  93.                
  94.                 // Wait for the 3rd byte
  95.                 while(!(UCSRA & (1 << RXC)));
  96.                 data2 = UDR;   // Velocity data
  97.                
  98.                 gahbage = TCNT1;
  99.                 t1 = TCNT1H;   // Record the clock!
  100.                 t2 = TCNT1L;
  101.  
  102.                 TCNT1 = 0;     // Start the clock!
  103.  
  104.                 // Write our data to EEPROM
  105.                 eeprom_write_byte(eepromAddress, status); // Write data
  106.                 eepromAddress++; // Increment address
  107.                 eeprom_write_byte(eepromAddress, data1);
  108.                 eepromAddress++;
  109.                 eeprom_write_byte(eepromAddress, data2);
  110.                 eepromAddress++;
  111.                 eeprom_write_byte(eepromAddress, t1);
  112.                 eepromAddress++;
  113.                 eeprom_write_byte(eepromAddress, t2);
  114.                 eepromAddress++;
  115.                 eeprom_write_byte(0, eepromAddress);
  116.             }
  117.         }
  118.  
  119.         // PLAYBACK - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  120.         else if(PINA & (1 << 1)){
  121.  
  122.             mod = 1; // Assume regular light
  123.             eA = 1;  // Start from the first data address (eepromAddress is in slot1)
  124.            
  125.             // Loop through the stored data when the switch is on & there's more data
  126.             while((eepromAddress - eA >= 4) && (PINA & (1 << 1))){
  127.                 // Read from MIDI;
  128.                 status = eeprom_read_byte(eA); // Read data
  129.                 eA++; // Incrament address
  130.                 data1 = eeprom_read_byte(eA);
  131.                 eA++;
  132.                 data2 = eeprom_read_byte(eA);
  133.                 eA++;
  134.                 t1 = eeprom_read_byte(eA);
  135.                 eA++;
  136.                 t2 = eeprom_read_byte(eA);
  137.                 eA++;
  138.                 eepromAddress = eeprom_read_byte(0); // Read the max address
  139.                
  140.                 // Deduce time from 2 bytes to 1
  141.                 t = ((uint16_t)t1);
  142.                 t = (t << 8);
  143.                 t = t | ((uint16_t)t2);
  144.  
  145.                 // If its our first time in the playback, don't wait for the first note
  146.                 if (eA == 6)
  147.                     t = 0;
  148.  
  149.                 // PLAYBACK & MODIFY - - - - - - - - - - - - - - - - - - - - - - - - - -
  150.                 if(PINA & (1 << 2)){
  151.                     ADCSRA |= (1 << ADSC); // Ready to read from the ADC
  152.                     light = ADC; // Read from the ADC
  153.                     if(light <= (1 << 6)) // Bright light
  154.                         mod = 2;
  155.                     else if((light > (1 << 6)) && (light < (1 << 9))) // Medium light
  156.                         mod = 1;
  157.                     else // if(light >= (1 << 9)) // Dim light
  158.                         mod = 0;
  159.                 }
  160.                
  161.                 // If there's bright light, half the time intervals
  162.                 if(mod == 2){
  163.                     t = (t >> 1);
  164.                 }
  165.  
  166.                 // Wait for the time between notes or note duration
  167.                 TCNT1 = 0;
  168.                 while((TCNT1 != t) && (PINA & (1 << 1)));
  169.  
  170.                 // If there's dim light, double the time intervals
  171.                 if(mod == 0){
  172.                     TCNT1 = 0x07A1; // Trigger the interrupt
  173.                     TCNT1 = 0;
  174.                     while((TCNT1 != t) && (PINA & (1 << 1)));
  175.                 }
  176.                
  177.                 //Write to MIDI
  178.                 while(((UCSRA & (1 << UDRE)) == 0) && (PINA & (1 << 1))); // Wait for the computer to be ready to be written to
  179.                 UDR = status; // Send the status
  180.                 while(((UCSRA & (1 << UDRE)) == 0) && (PINA & (1 << 1)));
  181.                 UDR = data1;
  182.                 while(((UCSRA & (1 << UDRE)) == 0) && (PINA & (1 << 1)));
  183.                 UDR = data2;
  184.  
  185.                 // If the note is being played (as opposed to stopped)
  186.                 if (status != 0x80)
  187.                     PORTB = data1; // Make the LED bar correspond to the note
  188.             }
  189.  
  190.             // Wait before looping again immediately (500ms - 2s depending on mod)
  191.             TCNT1 = 0;
  192.             while((TCNT1 != 0x07A2) && (PINA & (1 << 1)));
  193.             if(mod != 2){
  194.                 TCNT1 = 0;
  195.                 while((TCNT1 != 0x07A2) && (PINA & (1 << 1)));
  196.             }
  197.             if(mod == 0){
  198.                 TCNT1 = 0;
  199.                 while((TCNT1 != 0x07A2) && (PINA & (1 << 1)));
  200.                 TCNT1 = 0;
  201.                 while((TCNT1 != 0x07A2) && (PINA & (1 << 1)));
  202.             }
  203.            
  204.             nothing = UDR; // Prevents accidentally writing into record
  205.             flag = 0;      // We're not in record
  206.         }
  207.  
  208.         // NOTHING - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  209.         else{
  210.             nothing = UDR; // Prevents accidentally writing into record
  211.             flag = 0;      // We're not in record
  212.         }
  213.     }
  214. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement