Advertisement
Guest User

Untitled

a guest
Sep 26th, 2017
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 13.24 KB | None | 0 0
  1. /*
  2.  * Keyboard Piano
  3.  * Mark Mouritsen
  4.  * u0606723
  5.  * Last revised 05/06/2015
  6.  *
  7.  * Current version uses keys 1234567890-=ASDFGHJKL;'(BLACK KEYS) QWERTYUIOP[]|ZXCVBNM<>/(WHITE KEYS) for the piano and the UP, DOWN, LEFT and RIGHT arrow keys to change the notes.
  8.  *
  9.  *
  10.  * This program has 4 functions (and one helper function):
  11.  * - setup: intialize everything
  12.  * - loop: constantly read data and parse complete data
  13.  * - blink: interrupt that begins moving data from the data line into the data variable
  14.  *          on the negative edge of the input clock from the keyboard
  15.  * - getNote: converts data from keyboard into a note number which note can be retrieved from an array
  16.  *
  17.  * The program ultimately reads data from the keyboard, triggering the read via interrupt on the negative edge of the clock.
  18.  * The data is then parsed and the program sends a clock frequency to the output pin based on keys pressed. The frequency is
  19.  * no longer driven once all recognized note keys have been released.
  20.  *
  21.  * The program is compiled in Energia and run with the MSP-EXP430G2 Evaluation board on a MSP430G2553 MCU.
  22.  */
  23.  
  24. // Constants
  25. const int dataPin = 6;        // P1.4
  26. const int clkPin = 7;         // P1.5
  27. const int soundPin = 11;      // P1.6 (on MSP430G2553, it would be GND on 14 pin models)
  28. int soundOut = 0;             // Which pin to output the next note onto, this is a rolling value
  29. int soundMax = 2;             // Max output pins (+1), hardware forces a max of 3 different clock outputs
  30. int last[3];                  // Keeps track of which notes are playing
  31.  
  32. // Variables used by interrupts:
  33. volatile int done = LOW;      // Signals main program that reading is done
  34. volatile int bit_count = -1;  // Keeps track of which bit is being read
  35. volatile int data = 0;        // The data coming from dataPin (the keyboard)
  36. volatile int kbd_data = 0;    // Complete data stored as captured from the dataPin
  37.  
  38. // Variables
  39. int release = LOW;  // Signals when a button release has occured
  40. int kbd_data_ = 0;  // Stores kbd_data so corruption doesn't occur from a following interrupt
  41. int modi = 3;       // Which octave we are on (+1, i.e: modi 3 is 4th octave)
  42. int lo_m = 0;       // Modifier for the lower keys
  43. int hi_m = 0;       // Modifier for the upper keys
  44. int shift = 0;      // 0 = Shift key up, 1 = Shift key down
  45. int note = -1;      // The note being played, -1 = Not recognized
  46.  
  47. // Data queue
  48. const int data_max = 9;     // Queue size (needs to be something that our program can keep up with so we don't overwrite values in the queue, 0-3 should be more than enough though since the keyboard's clock is 16khz and the MSP430G2553 is 16Mhz)
  49. int data_in[data_max + 1];  // Queue array
  50. int data_read = 0;          // Read pointer
  51. int data_write = 0;         // Write pointer
  52.  
  53. // Notes array
  54. const int white[53] = {-1,31,33,37,41,44,49,55,62,65,73,82,87,98,110,123,131,147,165,175,196,220,247,262,294,330,349,392,440,494,523,587,659,698,784,880,988,1047,1175,1319,1397,1568,1760,1976,2093,2349,2637,2794,3136,3520,3951,4186,4699};
  55. const int black[53] = {-1,-1,35,39,-1,46,52,58,-1,69,78,-1,93,104,117,-1,139,156,-1,185,208,233,-1,277,311,-1,370,415,466,-1,554,622,-1,740,831,932,-1,1109,1245,-1,1480,1661,1865,-1,2217,2489,-1,2960,3322,3729,-1,4435,4978};
  56. //const int notes[89] = {31,33,35,37,39,41,44,46,49,52,55,58,62,65,69,73,78,82,87,93,98,104,110,117,123,131,139,147,156,165,175,185,196,208,220,233,247,262,277,294,311,330,349,370,392,415,440,466,494,523,554,587,622,659,698,740,784,831,880,932,988,1047,1109,1175,1245,1319,1397,1480,1568,1661,1760,1865,1976,2093,2217,2349,2489,2637,2794,2960,3136,3322,3520,3729,3951,4186,4435,4699,4978};
  57.  
  58. /*
  59.  * Init
  60.  */
  61. void setup()
  62. {
  63.   //Initialize serial and wait for port to open:
  64.   //Serial.begin(9600);
  65.  
  66.   // Enable the red LED and turn it off until setup is done
  67.   pinMode(2, OUTPUT);
  68.   digitalWrite(2, LOW);
  69.  
  70.   // Enable internal pullup for CLK and DATA lines
  71.   pinMode(clkPin, INPUT_PULLUP);
  72.   pinMode(dataPin, INPUT_PULLUP);
  73.  
  74.   // Enable the output pins and turn them off
  75.   for (int i = 0; i <= soundMax; i++) {
  76.     pinMode(soundPin + i, OUTPUT);
  77.     analogWrite(soundPin + i, 0);
  78.     last[i] = -1;
  79.   }
  80.  
  81.   // Disable interrupts during setup (so keyboard does not trigger anything)
  82.   noInterrupts();
  83.  
  84.   // Interrupt is fired whenever CLK falls
  85.   attachInterrupt(clkPin, blink, FALLING);
  86.  
  87.   // Re-enable interrupts
  88.   interrupts();
  89.  
  90.   // Setup complete, turn red light on
  91.   digitalWrite(2, HIGH);
  92. }
  93.  
  94. /*
  95.  * Main Loop
  96.  */
  97. void loop()
  98. {
  99.   // Store the current DATA state into our data variable
  100.   data = digitalRead(dataPin);
  101.  
  102.   /* If the interrupt has finished reading (after 11 bits)
  103.    * print out the code that was read */
  104.   if (done == HIGH) {
  105.     // Set done to LOW so we can read more incoming data
  106.     done = LOW;
  107.    
  108.     // Store kbd_data into a new variable so it isn't corrupted while we use it
  109.     kbd_data_ = data_in[data_read];
  110.     data_read++;
  111.    
  112.     // DEBUG - Print data
  113.     //Serial.println(kbd_data_);
  114.    
  115.     if (data_read > data_max)
  116.       data_read = 0;
  117.  
  118.     // Next input will be a release
  119.     if (kbd_data_ == 240) {
  120.       release = HIGH;
  121.      
  122.     // Release arrived
  123.     } else if (release == HIGH) {
  124.       release = LOW; // Reset the relase
  125.      
  126.       switch (kbd_data_) {
  127.         // Modifiers UP & DOWN modify the upper keys, LEFT & RIGHT modify the lower keys
  128.         case 117: //UP
  129.           hi_m++;
  130.           break;
  131.         case 114: //DOWN
  132.           hi_m--;
  133.           break;
  134.         case 107: //LEFT
  135.           lo_m--;
  136.           break;
  137.         case 116: //RIGHT
  138.           lo_m++;
  139.           break;
  140.       }
  141.       // Get the note
  142.       note = getNote(kbd_data_);
  143.      
  144.       // If the note is recognized
  145.       if (note != 0)
  146.       {
  147.         // Get which of the notes was playing and turn it off
  148.         // If none of the last 3 notes were what was released, do nothing
  149.         int store = soundOut; // In case we need to restore it later
  150.         for (int i = 0; i <= soundMax; i++) {
  151.           // If this was the note released, set soundOut to this
  152.           if (note == last[i]) {
  153.             soundOut = i;
  154.             break;
  155.           }
  156.          
  157.           // Otherwise, the note released wasn't in the array
  158.           if (i == soundMax)
  159.             soundOut = -1;
  160.         }
  161.        
  162.         // Remove the tone being played from the specific pin
  163.         if (soundOut >= 0) {
  164.           last[soundOut] = -1;
  165.           noTone(soundPin + soundOut);
  166.         }
  167.        
  168.         // If we released a note that is not in our array, reset the soundOut position
  169.         else
  170.           soundOut = store;
  171.       }
  172.     } else {
  173.       // Get the note based on which key was pressed
  174.       note = getNote(kbd_data_);
  175.      
  176.       // If a recognized note was played...
  177.       if (note != 0) {
  178.         // Play the note
  179.        
  180.         // ...If it's not already being played
  181.         if (soundOut <= soundMax && !contains(note, last, soundMax + 1)) {
  182.           // Store the note so we can check it for release later
  183.           last[soundOut] = note;
  184.          
  185.           // Check if it was a black key
  186.           if (note < 0) {
  187.             if (black[note * -1] > 0)
  188.               tone(soundPin + soundOut++, black[note * -1]);
  189.           }
  190.           // Or white key
  191.           else
  192.             tone(soundPin + soundOut++, white[note]);
  193.            
  194.           // Roll our array counter over if we get greater than our max # of pins
  195.           if (soundOut > soundMax)
  196.             soundOut = 0;
  197.         }
  198.       }
  199.     }
  200.   }
  201.   // Finish input parse
  202. }
  203.  
  204. /*
  205.  * contains - Returns a true or false based on
  206.  * whether or not the given array arr contains
  207.  * the given value val
  208.  */
  209. boolean contains(int val, int *arr, int size){
  210.     int i;
  211.     for (i=0; i < size; i++) {
  212.         if (arr[i] == val)
  213.             return true;
  214.     }
  215.     return false;
  216. }
  217.  
  218. /*
  219.  * blink - Captures any bits sent along the data
  220.  * line while the clock is active and stores them
  221.  * into kbd_data
  222.  */
  223. void blink()
  224. {
  225.   // bit_count will be '-1' if we're beginning the read
  226.   if (bit_count < 0) {
  227.     bit_count = 0;
  228.     kbd_data = 0;
  229.    
  230.   // bit_count will be between 0 and 7 during the read
  231.   } else if (bit_count < 8) {
  232.     // If the data line is high, store a 1 at the current bit position
  233.     if (data == HIGH) {
  234.       kbd_data |= (1<<bit_count);
  235.     }
  236.    
  237.     // Increment bit_count
  238.     bit_count++;
  239.  
  240.   // The last bit will be a parity bit (we will ignore these for now)
  241.   } else if (bit_count == 8) {
  242.     // Increment bit_count
  243.     bit_count++;
  244.    
  245.   // After the parity bit we will have our stop bit
  246.   } else {
  247.     // Reset the bit_count
  248.     bit_count = -1;
  249.    
  250.     // Set done high to let the main loop know we're ready to print the value
  251.     done = HIGH;
  252.    
  253.     data_in[data_write] = kbd_data;
  254.     data_write++;
  255.     if (data_write > data_max)
  256.       data_write = 0;
  257.   }
  258.  
  259.   // Return from the interrupt
  260.   return;
  261. }
  262.  
  263. /*
  264.  * Returns a note value (that can be used in the
  265.  * note array to get a specific clock frequency)
  266.  * based on the key pressed and modifiers used
  267.  */
  268. int getNote(int in)
  269. {
  270.   int ret = 0; // The return value
  271.   int bar = 0;  // Used to increase or decrease by an additional octave
  272.   int color = 1;
  273.   boolean low = false;
  274.  
  275.   switch (in) {
  276.     // Notes QWERTYUIOP[]|
  277.     case 21: //Q
  278.       ret = 5;
  279.       bar = -1;
  280.       break;
  281.     case 29: //W
  282.       ret = 6;
  283.       bar = -1;
  284.       break;
  285.     case 36: //E
  286.       ret = 7;
  287.       bar = -1;
  288.       break;
  289.     case 45: //R
  290.       ret = 1;
  291.       break;
  292.     case 44: //T
  293.       ret = 2;
  294.       break;
  295.     case 53: //Y
  296.       ret = 3;
  297.       break;
  298.     case 60: //U
  299.       ret = 4;
  300.       break;
  301.     case 67: //I
  302.       ret = 5;
  303.       break;
  304.     case 68: //O
  305.       ret = 6;
  306.       break;
  307.     case 77: //P
  308.       ret = 7;
  309.       break;
  310.     case 84: //[
  311.       ret = 1;
  312.       bar = 1;
  313.       break;
  314.     case 91: //]
  315.       ret = 2;
  316.       bar = 1;
  317.       break;
  318.     case 93:
  319.       ret = 3;
  320.       bar = 1;
  321.       break;
  322.    
  323.     // Notes 1234567890-=
  324.     case 22: //1
  325.       ret = 4;
  326.       bar = -1;
  327.       color = -1;
  328.       break;
  329.     case 30: //2
  330.       ret = 5;
  331.       bar = -1;
  332.       color = -1;
  333.       break;
  334.     case 38: //3
  335.       ret = 6;
  336.       bar = -1;
  337.       color = -1;
  338.       break;
  339.     case 37: //4
  340.       ret = 7;
  341.       bar = -1;
  342.       color = -1;
  343.       break;
  344.     case 46: //5
  345.       ret = 1;
  346.       bar = 0;
  347.       color = -1;
  348.       break;
  349.     case 54: //6
  350.       ret = 2;
  351.       bar = 0;
  352.       color = -1;
  353.       break;
  354.     case 61: //7
  355.       ret = 3;
  356.       bar = 0;
  357.       color = -1;
  358.       break;
  359.     case 62: //8
  360.       ret = 4;
  361.       bar = 0;
  362.       color = -1;
  363.       break;
  364.     case 70: //9
  365.       ret = 5;
  366.       bar = 0;
  367.       color = -1;
  368.       break;
  369.     case 69: //0
  370.       ret = 6;
  371.       bar = 0;
  372.       color = -1;
  373.       break;
  374.     case 78: //-
  375.       ret = 7 ;
  376.       bar = 0;
  377.       color = -1;
  378.       break;
  379.     case 85: //=
  380.       ret = 1;
  381.       bar = 1;
  382.       color = -1;
  383.       break;
  384.    
  385.     // Keys ASDFGHJKL;'
  386.     case 28: //a
  387.       ret = 1;
  388.       bar = -2;
  389.       low = true;
  390.       color = -1;
  391.       break;
  392.     case 27: //s
  393.       ret = 2;
  394.       bar = -2;
  395.       low = true;
  396.       color = -1;
  397.       break;
  398.     case 35: //d
  399.       ret = 3;
  400.       bar = -2;
  401.       low = true;
  402.       color = -1;
  403.       break;
  404.     case 43: //f
  405.       ret = 4;
  406.       bar = -2;
  407.       low = true;
  408.       color = -1;
  409.       break;
  410.     case 52: //g
  411.       ret = 5;
  412.       bar = -2;
  413.       low = true;
  414.       color = -1;
  415.       break;
  416.     case 51: //h
  417.       ret = 6;
  418.       bar = -2;
  419.       low = true;
  420.       color = -1;
  421.       break;
  422.     case 59: //j
  423.       ret = 7;
  424.       bar = -2;
  425.       low = true;
  426.       color = -1;
  427.       break;
  428.     case 66: //k
  429.       ret = 1;
  430.       bar = -1;
  431.       low = true;
  432.       color = -1;
  433.       break;
  434.     case 75: //l
  435.       ret = 2;
  436.       bar = -1;
  437.       low = true;
  438.       color = -1;
  439.       break;
  440.     case 76: //;
  441.       ret = 3;
  442.       bar = -1;
  443.       low = true;
  444.       color = -1;
  445.       break;
  446.     case 82: //'
  447.       ret = 4;
  448.       bar = -1;
  449.       low = true;
  450.       color = -1;
  451.       break;
  452.      
  453.     // Keys ZXCVBNM,./
  454.     case 26: //z
  455.       ret = 2;
  456.       bar = -2;
  457.       low = true;
  458.       break;
  459.     case 34: //x
  460.       ret = 3;
  461.       bar = -2;
  462.       low = true;
  463.       break;
  464.     case 33: //c
  465.       ret = 4;
  466.       bar = -2;
  467.       low = true;
  468.       break;
  469.     case 42: //v
  470.       ret = 5;
  471.       bar = -2;
  472.       low = true;
  473.       break;
  474.     case 50: //b
  475.       ret = 6;
  476.       bar = -2;
  477.       low = true;
  478.       break;
  479.     case 49: //n
  480.       ret = 7;
  481.       bar = -2;
  482.       low = true;
  483.       break;
  484.     case 58: //m
  485.       ret = 1;
  486.       bar = -1;
  487.       low = true;
  488.       break;
  489.     case 65: //,
  490.       ret = 2;
  491.       bar = -1;
  492.       low = true;
  493.       break;
  494.     case 73: //.
  495.       ret = 3;
  496.       bar = -1;
  497.       low = true;
  498.       break;
  499.     case 74: ///
  500.       ret = 4;
  501.       bar = -1;
  502.       low = true;
  503.       break;
  504.     default:
  505.       return 0;
  506.       break;
  507.   }
  508.  
  509.   if (modi + bar > 6 || modi + bar < 0)
  510.     return 0;
  511.   if (low)
  512.     return ((ret + (7 * (modi + bar)) + 1 - lo_m) * color);
  513.   return ((ret + (7 * (modi + bar)) + 1 - hi_m) * color);
  514. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement