Ported from Arduino MIDI library Orignal: http://www.arduino.cc/playground/Main/MIDILibrary use Serial (UART)

Dependents:   MIDI_sample MIDI_usb_bridge MIDI_Interpreter midi-timer ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MIDI.cpp Source File

MIDI.cpp

Go to the documentation of this file.
00001 /*!
00002  *  @file       MIDI.cpp
00003  *  Project     MIDI Library
00004  *  @brief      MIDI Library for the Arduino
00005  *  @version    3.2
00006  *  @author     Francois Best 
00007  *  @date       24/02/11
00008  *  license     GPL Forty Seven Effects - 2011
00009  */
00010 /*
00011  * Ported for mbed by Hiroshi Suga
00012  *   Orignal: http://www.arduino.cc/playground/Main/MIDILibrary
00013  */
00014 
00015 #include "MIDI.h"
00016 #include "mbed.h"
00017 
00018 
00019 
00020 /*! \brief Default constructor for MIDI. */
00021 MIDI::MIDI(PinName p_tx, PinName p_rx) : _midi(p_tx, p_rx)
00022 { 
00023     
00024 #if USE_CALLBACKS
00025     
00026     // Initialise callbacks to NULL pointer
00027     mNoteOffCallback                = NULL;
00028     mNoteOnCallback                 = NULL;
00029     mAfterTouchPolyCallback         = NULL;
00030     mControlChangeCallback          = NULL;
00031     mProgramChangeCallback          = NULL;
00032     mAfterTouchChannelCallback      = NULL;
00033     mPitchBendCallback              = NULL;
00034     mSystemExclusiveCallback        = NULL;
00035     mTimeCodeQuarterFrameCallback   = NULL;
00036     mSongPositionCallback           = NULL;
00037     mSongSelectCallback             = NULL;
00038     mTuneRequestCallback            = NULL;
00039     mClockCallback                  = NULL;
00040     mStartCallback                  = NULL;
00041     mContinueCallback               = NULL;
00042     mStopCallback                   = NULL;
00043     mActiveSensingCallback          = NULL;
00044     mSystemResetCallback            = NULL;
00045     
00046 #endif
00047     
00048 }
00049 
00050 
00051 /*! \brief Default destructor for MIDI.
00052  
00053  This is not really useful for the Arduino, as it is never called...
00054  */
00055 MIDI::~MIDI()
00056 {
00057 
00058 }
00059 
00060 
00061 /*! \brief Call the begin method in the setup() function of the Arduino.
00062  
00063  All parameters are set to their default values:
00064  - Input channel set to 1 if no value is specified
00065  - Full thru mirroring
00066  */
00067 void MIDI::begin(const byte  inChannel)
00068 {
00069     
00070     // Initialise the Serial port
00071     USE_SERIAL_PORT.baud(MIDI_BAUDRATE);
00072     
00073     
00074 #if COMPILE_MIDI_OUT
00075     
00076 #if USE_RUNNING_STATUS
00077     
00078     mRunningStatus_TX = InvalidType;
00079     
00080 #endif // USE_RUNNING_STATUS
00081     
00082 #endif // COMPILE_MIDI_OUT
00083     
00084     
00085 #if COMPILE_MIDI_IN
00086     
00087     mInputChannel = inChannel;
00088     mRunningStatus_RX = InvalidType;
00089     mPendingMessageIndex = 0;
00090     mPendingMessageExpectedLenght = 0;
00091     
00092     mMessage.valid  = false;
00093     mMessage.type  = InvalidType;
00094     mMessage.channel  = 0;
00095     mMessage.data1  = 0;
00096     mMessage.data2  = 0;
00097     
00098 #endif // COMPILE_MIDI_IN
00099     
00100     
00101 #if (COMPILE_MIDI_IN && COMPILE_MIDI_OUT && COMPILE_MIDI_THRU) // Thru
00102     
00103     mThruFilterMode = Full;
00104     mThruActivated = true;
00105     
00106 #endif // Thru
00107     
00108 }
00109 
00110 
00111 #if COMPILE_MIDI_OUT
00112 
00113 // Private method for generating a status byte from channel and type
00114 byte  MIDI::genstatus(const kMIDIType  inType,
00115                                  const byte  inChannel) const
00116 {
00117     
00118     return ((byte )inType | ((inChannel-1) & 0x0F));
00119     
00120 }
00121 
00122 
00123 /*! \brief Generate and send a MIDI message from the values given.
00124  \param type    The message type (see type defines for reference)
00125  \param data1   The first data byte.
00126  \param data2   The second data byte (if the message contains only 1 data byte, set this one to 0).
00127  \param channel The output channel on which the message will be sent (values from 1 to 16). Note: you cannot send to OMNI.
00128  
00129  This is an internal method, use it only if you need to send raw data from your code, at your own risks.
00130  */
00131 void MIDI::send(kMIDIType  type,
00132                       byte  data1,
00133                       byte  data2,
00134                       byte  channel)
00135 {
00136     
00137     // Then test if channel is valid
00138     if (channel >= MIDI_CHANNEL_OFF || channel == MIDI_CHANNEL_OMNI || type < NoteOff) {
00139         
00140 #if USE_RUNNING_STATUS  
00141         mRunningStatus_TX = InvalidType;
00142 #endif 
00143         
00144         return; // Don't send anything
00145     }
00146     
00147     if (type <= PitchBend) {
00148         // Channel messages
00149         
00150         // Protection: remove MSBs on data
00151         data1 &= 0x7F;
00152         data2 &= 0x7F;
00153         
00154         byte  statusbyte = genstatus(type,channel);
00155         
00156 #if USE_RUNNING_STATUS
00157         // Check Running Status
00158         if (mRunningStatus_TX != statusbyte) {
00159             // New message, memorise and send header
00160             mRunningStatus_TX = statusbyte;
00161             USE_SERIAL_PORT.putc(mRunningStatus_TX);
00162         }
00163 #else
00164         // Don't care about running status, send the Control byte.
00165         USE_SERIAL_PORT.putc(statusbyte);
00166 #endif
00167         
00168         // Then send data
00169         USE_SERIAL_PORT.putc(data1);
00170         if (type != ProgramChange && type != AfterTouchChannel) {
00171             USE_SERIAL_PORT.putc(data2);
00172         }
00173         return;
00174     }
00175     if (type >= TuneRequest && type <= SystemReset) {
00176         // System Real-time and 1 byte.
00177         sendRealTime(type);
00178     }
00179     
00180 }
00181 
00182 
00183 /*! \brief Send a Note On message 
00184  \param NoteNumber  Pitch value in the MIDI format (0 to 127). Take a look at the values, names and frequencies of notes here: http://www.phys.unsw.edu.au/jw/notes.html\n
00185  \param Velocity    Note attack velocity (0 to 127). A NoteOn with 0 velocity is considered as a NoteOff.
00186  \param Channel     The channel on which the message will be sent (1 to 16). 
00187  */
00188 void MIDI::sendNoteOn(byte  NoteNumber,
00189                             byte  Velocity,
00190                             byte  Channel)
00191 { 
00192     
00193     send(NoteOn,NoteNumber,Velocity,Channel);
00194 
00195 }
00196 
00197 
00198 /*! \brief Send a Note Off message (a real Note Off, not a Note On with null velocity)
00199  \param NoteNumber  Pitch value in the MIDI format (0 to 127). Take a look at the values, names and frequencies of notes here: http://www.phys.unsw.edu.au/jw/notes.html\n
00200  \param Velocity    Release velocity (0 to 127).
00201  \param Channel     The channel on which the message will be sent (1 to 16).
00202  */
00203 void MIDI::sendNoteOff(byte  NoteNumber,
00204                              byte  Velocity,
00205                              byte  Channel)
00206 {
00207     
00208     send(NoteOff,NoteNumber,Velocity,Channel);
00209 
00210 }
00211 
00212 
00213 /*! \brief Send a Program Change message 
00214  \param ProgramNumber   The Program to select (0 to 127).
00215  \param Channel         The channel on which the message will be sent (1 to 16).
00216  */
00217 void MIDI::sendProgramChange(byte  ProgramNumber,
00218                                    byte  Channel)
00219 {
00220     
00221     send(ProgramChange,ProgramNumber,0,Channel);
00222 
00223 }
00224 
00225 
00226 /*! \brief Send a Control Change message 
00227  \param ControlNumber   The controller number (0 to 127). See the detailed description here: http://www.somascape.org/midi/tech/spec.html#ctrlnums
00228  \param ControlValue    The value for the specified controller (0 to 127).
00229  \param Channel         The channel on which the message will be sent (1 to 16). 
00230  */
00231 void MIDI::sendControlChange(byte  ControlNumber,
00232                                    byte  ControlValue,
00233                                    byte  Channel)
00234 {
00235     
00236     send(ControlChange,ControlNumber,ControlValue,Channel);
00237 
00238 }
00239 
00240 
00241 /*! \brief Send a Polyphonic AfterTouch message (applies to only one specified note)
00242  \param NoteNumber      The note to apply AfterTouch to (0 to 127).
00243  \param Pressure        The amount of AfterTouch to apply (0 to 127).
00244  \param Channel         The channel on which the message will be sent (1 to 16). 
00245  */
00246 void MIDI::sendPolyPressure(byte  NoteNumber,
00247                                   byte  Pressure,
00248                                   byte  Channel)
00249 {
00250     
00251     send(AfterTouchPoly,NoteNumber,Pressure,Channel);
00252 
00253 }
00254 
00255 
00256 /*! \brief Send a MonoPhonic AfterTouch message (applies to all notes)
00257  \param Pressure        The amount of AfterTouch to apply to all notes.
00258  \param Channel         The channel on which the message will be sent (1 to 16). 
00259  */
00260 void MIDI::sendAfterTouch(byte  Pressure,
00261                                 byte  Channel)
00262 {
00263     
00264     send(AfterTouchChannel,Pressure,0,Channel);
00265 
00266 }
00267 
00268 
00269 /*! \brief Send a Pitch Bend message using a signed integer value.
00270  \param PitchValue  The amount of bend to send (in a signed integer format), between -8192 (maximum downwards bend) and 8191 (max upwards bend), center value is 0.
00271  \param Channel     The channel on which the message will be sent (1 to 16).
00272  */
00273 void MIDI::sendPitchBend(int PitchValue,
00274                                byte  Channel)
00275 {
00276     
00277     unsigned int bend = PitchValue + 8192;
00278     sendPitchBend(bend,Channel);
00279     
00280 }
00281 
00282 
00283 /*! \brief Send a Pitch Bend message using an unsigned integer value.
00284  \param PitchValue  The amount of bend to send (in a signed integer format), between 0 (maximum downwards bend) and 16383 (max upwards bend), center value is 8192.
00285  \param Channel     The channel on which the message will be sent (1 to 16).
00286  */
00287 void MIDI::sendPitchBend(unsigned int PitchValue,
00288                                byte  Channel)
00289 {
00290     
00291     send(PitchBend,(PitchValue & 0x7F),(PitchValue >> 7) & 0x7F,Channel);
00292     
00293 }
00294 
00295 
00296 /*! \brief Send a Pitch Bend message using a floating point value.
00297  \param PitchValue  The amount of bend to send (in a floating point format), between -1.0f (maximum downwards bend) and +1.0f (max upwards bend), center value is 0.0f.
00298  \param Channel     The channel on which the message will be sent (1 to 16).
00299  */
00300 void MIDI::sendPitchBend(double PitchValue,
00301                                byte  Channel)
00302 {
00303     
00304     unsigned int pitchval = (PitchValue+1.f)*8192;
00305     if (pitchval > 16383) pitchval = 16383;     // overflow protection
00306     sendPitchBend(pitchval,Channel);
00307     
00308 }
00309 
00310 
00311 /*! \brief Generate and send a System Exclusive frame.
00312  \param length  The size of the array to send
00313  \param array   The byte array containing the data to send
00314  \param ArrayContainsBoundaries  When set to 'true', 0xF0 & 0xF7 bytes (start & stop SysEx) will NOT be sent (and therefore must be included in the array).
00315  default value is set to 'false' for compatibility with previous versions of the library.
00316  */
00317 void MIDI::sendSysEx(int length,
00318                            const byte  *const array,
00319                            bool ArrayContainsBoundaries)
00320 {
00321     
00322     if (ArrayContainsBoundaries == false) {
00323         
00324         USE_SERIAL_PORT.putc(0xF0);
00325         
00326         for (int i=0;i<length;++i) {
00327             
00328             USE_SERIAL_PORT.putc(array[i]);
00329             
00330         }
00331         
00332         USE_SERIAL_PORT.putc(0xF7);
00333         
00334     }
00335     else {
00336         
00337         for (int i=0;i<length;++i) {
00338             
00339             USE_SERIAL_PORT.putc(array[i]);
00340             
00341         }
00342         
00343     }
00344     
00345 #if USE_RUNNING_STATUS
00346     mRunningStatus_TX = InvalidType;
00347 #endif
00348     
00349 }
00350 
00351 
00352 /*! \brief Send a Tune Request message. 
00353  
00354  When a MIDI unit receives this message, it should tune its oscillators (if equipped with any) 
00355  */
00356 void MIDI::sendTuneRequest()
00357 {
00358     
00359     sendRealTime(TuneRequest);
00360 
00361 }
00362 
00363 
00364 /*! \brief Send a MIDI Time Code Quarter Frame. 
00365  
00366  See MIDI Specification for more information.
00367  \param TypeNibble  MTC type
00368  \param ValuesNibble    MTC data
00369  */
00370 void MIDI::sendTimeCodeQuarterFrame(byte  TypeNibble, byte  ValuesNibble)
00371 {
00372     
00373     byte  data = ( ((TypeNibble & 0x07) << 4) | (ValuesNibble & 0x0F) );
00374     sendTimeCodeQuarterFrame(data);
00375     
00376 }
00377 
00378 
00379 /*! \brief Send a MIDI Time Code Quarter Frame. 
00380  
00381  See MIDI Specification for more information.
00382  \param data     if you want to encode directly the nibbles in your program, you can send the byte here.
00383  */
00384 void MIDI::sendTimeCodeQuarterFrame(byte  data)
00385 {
00386     
00387     USE_SERIAL_PORT.putc((byte )TimeCodeQuarterFrame);
00388     USE_SERIAL_PORT.putc(data);
00389 
00390 #if USE_RUNNING_STATUS
00391     mRunningStatus_TX = InvalidType;
00392 #endif
00393     
00394 }
00395 
00396 
00397 /*! \brief Send a Song Position Pointer message.
00398  \param Beats   The number of beats since the start of the song.
00399  */
00400 void MIDI::sendSongPosition(unsigned int Beats)
00401 {
00402     
00403     USE_SERIAL_PORT.putc((byte )SongPosition);
00404     USE_SERIAL_PORT.putc(Beats & 0x7F);
00405     USE_SERIAL_PORT.putc((Beats >> 7) & 0x7F);
00406 
00407 #if USE_RUNNING_STATUS
00408     mRunningStatus_TX = InvalidType;
00409 #endif
00410     
00411 }
00412 
00413 
00414 /*! \brief Send a Song Select message */
00415 void MIDI::sendSongSelect(byte  SongNumber)
00416 {
00417     
00418     USE_SERIAL_PORT.putc((byte )SongSelect);
00419     USE_SERIAL_PORT.putc(SongNumber & 0x7F);
00420 
00421 #if USE_RUNNING_STATUS
00422     mRunningStatus_TX = InvalidType;
00423 #endif
00424     
00425 }
00426 
00427 
00428 /*! \brief Send a Real Time (one byte) message. 
00429  
00430  \param Type The available Real Time types are: Start, Stop, Continue, Clock, ActiveSensing and SystemReset.
00431  You can also send a Tune Request with this method.
00432  @see kMIDIType
00433  */
00434 void MIDI::sendRealTime(kMIDIType  Type)
00435 {
00436     switch (Type) {
00437         case TuneRequest: // Not really real-time, but one byte anyway.
00438         case Clock:
00439         case Start:
00440         case Stop:  
00441         case Continue:
00442         case ActiveSensing:
00443         case SystemReset:
00444             USE_SERIAL_PORT.putc((byte )Type);
00445             break;
00446         default:
00447             // Invalid Real Time marker
00448             break;
00449     }
00450     
00451     // Do not cancel Running Status for real-time messages as they can be interleaved within any message.
00452     // Though, TuneRequest can be sent here, and as it is a System Common message, it must reset Running Status.
00453 #if USE_RUNNING_STATUS
00454     if (Type == TuneRequest) mRunningStatus_TX = InvalidType;
00455 #endif
00456     
00457 }
00458 
00459 #endif // COMPILE_MIDI_OUT
00460 
00461 
00462 
00463 #if COMPILE_MIDI_IN
00464 
00465 /*! \brief Read a MIDI message from the serial port using the main input channel (see setInputChannel() for reference).
00466  
00467  Returned value: true if any valid message has been stored in the structure, false if not.
00468  A valid message is a message that matches the input channel. \n\n
00469  If the Thru is enabled and the messages matches the filter, it is sent back on the MIDI output.
00470  */
00471 bool MIDI::read()
00472 {
00473     
00474     return read(mInputChannel);
00475     
00476 }
00477 
00478 
00479 /*! \brief Reading/thru-ing method, the same as read() with a given input channel to read on. */
00480 bool MIDI::read(const byte  inChannel)
00481 {
00482     
00483     if (inChannel >= MIDI_CHANNEL_OFF) return false; // MIDI Input disabled.
00484     
00485     if (parse(inChannel)) {
00486         
00487         if (input_filter(inChannel)) {
00488             
00489 #if (COMPILE_MIDI_OUT && COMPILE_MIDI_THRU)
00490             thru_filter(inChannel);
00491 #endif
00492             
00493 #if USE_CALLBACKS
00494             launchCallback();
00495 #endif
00496             
00497             return true;
00498         }
00499         
00500     }
00501     
00502     return false;
00503     
00504 }
00505 
00506 
00507 // Private method: MIDI parser
00508 bool MIDI::parse(byte  inChannel)
00509 { 
00510     
00511     const int bytes_available = USE_SERIAL_PORT.readable();
00512     
00513     if (bytes_available <= 0) {
00514         // No data available.
00515         return false;
00516     }
00517     
00518     // If the buffer is full -> Don't Panic! Call the Vogons to destroy it.
00519     if (bytes_available == 128) {
00520 //        USE_SERIAL_PORT.flush();
00521     }   
00522     else {
00523         
00524         /* Parsing algorithm:
00525          Get a byte from the serial buffer.
00526          * If there is no pending message to be recomposed, start a new one.
00527          - Find type and channel (if pertinent)
00528          - Look for other bytes in buffer, call parser recursively, until the message is assembled or the buffer is empty.
00529          * Else, add the extracted byte to the pending message, and check validity. When the message is done, store it.
00530          */
00531         
00532         
00533         const byte  extracted = USE_SERIAL_PORT.getc();
00534         
00535         if (mPendingMessageIndex == 0) { // Start a new pending message
00536             mPendingMessage[0] = extracted;
00537             
00538             // Check for running status first
00539             switch (getTypeFromStatusByte(mRunningStatus_RX)) {
00540                     // Only these types allow Running Status:
00541                 case NoteOff:
00542                 case NoteOn:
00543                 case AfterTouchPoly:
00544                 case ControlChange:
00545                 case ProgramChange:
00546                 case AfterTouchChannel:
00547                 case PitchBend: 
00548                     
00549                     // If the status byte is not received, prepend it to the pending message
00550                     if (extracted < 0x80) {
00551                         mPendingMessage[0] = mRunningStatus_RX;
00552                         mPendingMessage[1] = extracted;
00553                         mPendingMessageIndex = 1;
00554                     }
00555                     // Else: well, we received another status byte, so the running status does not apply here.
00556                     // It will be updated upon completion of this message.
00557                     
00558                     break;
00559                     
00560                 default:
00561                     // No running status
00562                     break;
00563             }
00564             
00565             
00566             switch (getTypeFromStatusByte(mPendingMessage[0])) {
00567                     
00568                     // 1 byte messages
00569                 case Start:
00570                 case Continue:
00571                 case Stop:
00572                 case Clock:
00573                 case ActiveSensing:
00574                 case SystemReset:
00575                 case TuneRequest:
00576                     // Handle the message type directly here.
00577                     mMessage.type  = getTypeFromStatusByte(mPendingMessage[0]);
00578                     mMessage.channel  = 0;
00579                     mMessage.data1  = 0;
00580                     mMessage.data2  = 0;
00581                     mMessage.valid  = true;
00582                     
00583                     // \fix Running Status broken when receiving Clock messages.
00584                     // Do not reset all input attributes, Running Status must remain unchanged.
00585                     //reset_input_attributes(); 
00586                     
00587                     // We still need to reset these
00588                     mPendingMessageIndex = 0;
00589                     mPendingMessageExpectedLenght = 0;
00590                     
00591                     return true;
00592                     
00593                     // 2 bytes messages
00594                 case ProgramChange:
00595                 case AfterTouchChannel:
00596                 case TimeCodeQuarterFrame:
00597                 case SongSelect:
00598                     mPendingMessageExpectedLenght = 2;
00599                     break;
00600                     
00601                     // 3 bytes messages
00602                 case NoteOn:
00603                 case NoteOff:
00604                 case ControlChange:
00605                 case PitchBend:
00606                 case AfterTouchPoly:
00607                 case SongPosition:
00608                     mPendingMessageExpectedLenght = 3;
00609                     break;
00610                     
00611                 case SystemExclusive:
00612                     mPendingMessageExpectedLenght = MIDI_SYSEX_ARRAY_SIZE; // As the message can be any lenght between 3 and MIDI_SYSEX_ARRAY_SIZE bytes
00613                     mRunningStatus_RX = InvalidType;
00614                     break;
00615                     
00616                 case InvalidType:
00617                 default:
00618                     // This is obviously wrong. Let's get the hell out'a here.
00619                     reset_input_attributes();
00620                     return false;
00621             }
00622             
00623             // Then update the index of the pending message.
00624             mPendingMessageIndex++;
00625             
00626 #if USE_1BYTE_PARSING
00627             // Message is not complete.
00628             return false;
00629 #else
00630             // Call the parser recursively
00631             // to parse the rest of the message.
00632             return parse(inChannel);
00633 #endif
00634             
00635         }
00636         else { 
00637             
00638             // First, test if this is a status byte
00639             if (extracted >= 0x80) {
00640                 
00641                 // Reception of status bytes in the middle of an uncompleted message
00642                 // are allowed only for interleaved Real Time message or EOX
00643                 switch (extracted) {
00644                     case Clock:
00645                     case Start:
00646                     case Continue:
00647                     case Stop:
00648                     case ActiveSensing:
00649                     case SystemReset:
00650                         
00651                         /*
00652                          This is tricky. Here we will have to extract the one-byte message,
00653                          pass it to the structure for being read outside the MIDI class,
00654                          and recompose the message it was interleaved into.
00655                          
00656                          Oh, and without killing the running status.. 
00657                          
00658                          This is done by leaving the pending message as is, it will be completed on next calls.
00659                          */
00660                         
00661                         mMessage.type  = (kMIDIType )extracted;
00662                         mMessage.data1  = 0;
00663                         mMessage.data2  = 0;
00664                         mMessage.channel  = 0;
00665                         mMessage.valid  = true;
00666                         return true;
00667                         
00668                         // End of Exclusive
00669                     case 0xF7:
00670                         if (getTypeFromStatusByte(mPendingMessage[0]) == SystemExclusive) {
00671                             
00672                             // Store System Exclusive array in midimsg structure
00673                             for (byte  i=0;i<MIDI_SYSEX_ARRAY_SIZE;i++) {
00674                                 mMessage.sysex_array [i] = mPendingMessage[i];
00675                             }
00676                             
00677                             mMessage.type  = SystemExclusive;
00678 
00679                             // Get length
00680                             mMessage.data1  = (mPendingMessageIndex+1) & 0xFF;   
00681                             mMessage.data2  = (mPendingMessageIndex+1) >> 8;
00682                             
00683                             mMessage.channel  = 0;
00684                             mMessage.valid  = true;
00685                             
00686                             reset_input_attributes();
00687                             
00688                             return true;
00689                         }
00690                         else {
00691                             // Well well well.. error.
00692                             reset_input_attributes();
00693                             return false;
00694                         }
00695                         
00696                     default:
00697                         break;
00698                 }
00699                 
00700                 
00701                 
00702             }
00703             
00704             
00705             // Add extracted data byte to pending message
00706             mPendingMessage[mPendingMessageIndex] = extracted;
00707             
00708             
00709             // Now we are going to check if we have reached the end of the message
00710             if (mPendingMessageIndex >= (mPendingMessageExpectedLenght-1)) {
00711                 
00712                 // "FML" case: fall down here with an overflown SysEx..
00713                 // This means we received the last possible data byte that can fit the buffer.
00714                 // If this happens, try increasing MIDI_SYSEX_ARRAY_SIZE.
00715                 if (getTypeFromStatusByte(mPendingMessage[0]) == SystemExclusive) {
00716                     reset_input_attributes();
00717                     return false;
00718                 }
00719                 
00720                 
00721                 mMessage.type  = getTypeFromStatusByte(mPendingMessage[0]);
00722                 mMessage.channel  = (mPendingMessage[0] & 0x0F)+1; // Don't check if it is a Channel Message
00723                 
00724                 mMessage.data1  = mPendingMessage[1];
00725                 
00726                 // Save data2 only if applicable
00727                 if (mPendingMessageExpectedLenght == 3) mMessage.data2  = mPendingMessage[2];
00728                 else mMessage.data2  = 0;
00729                 
00730                 // Reset local variables
00731                 mPendingMessageIndex = 0;
00732                 mPendingMessageExpectedLenght = 0;
00733                 
00734                 mMessage.valid  = true;
00735                 
00736                 // Activate running status (if enabled for the received type)
00737                 switch (mMessage.type ) {
00738                     case NoteOff:
00739                     case NoteOn:
00740                     case AfterTouchPoly:
00741                     case ControlChange:
00742                     case ProgramChange:
00743                     case AfterTouchChannel:
00744                     case PitchBend: 
00745                         // Running status enabled: store it from received message
00746                         mRunningStatus_RX = mPendingMessage[0];
00747                         break;
00748                         
00749                     default:
00750                         // No running status
00751                         mRunningStatus_RX = InvalidType;
00752                         break;
00753                 }
00754                 return true;
00755             }
00756             else {
00757                 // Then update the index of the pending message.
00758                 mPendingMessageIndex++;
00759                 
00760 #if USE_1BYTE_PARSING
00761                 // Message is not complete.
00762                 return false;
00763 #else
00764                 // Call the parser recursively
00765                 // to parse the rest of the message.
00766                 return parse(inChannel);
00767 #endif
00768                 
00769             }
00770             
00771         }
00772         
00773     }
00774     
00775     // What are our chances to fall here?
00776     return false;
00777 }
00778 
00779 
00780 // Private method: check if the received message is on the listened channel
00781 bool MIDI::input_filter(byte  inChannel)
00782 {
00783     
00784     
00785     // This method handles recognition of channel (to know if the message is destinated to the Arduino)
00786     
00787     
00788     if (mMessage.type  == InvalidType) return false;
00789     
00790     
00791     // First, check if the received message is Channel
00792     if (mMessage.type  >= NoteOff && mMessage.type  <= PitchBend) {
00793         
00794         // Then we need to know if we listen to it
00795         if ((mMessage.channel  == mInputChannel) || (mInputChannel == MIDI_CHANNEL_OMNI)) {
00796             return true;
00797             
00798         }
00799         else {
00800             // We don't listen to this channel
00801             return false;
00802         }
00803         
00804     }
00805     else {
00806         
00807         // System messages are always received
00808         return true;
00809     }
00810     
00811 }
00812 
00813 
00814 // Private method: reset input attributes
00815 void MIDI::reset_input_attributes()
00816 {
00817     
00818     mPendingMessageIndex = 0;
00819     mPendingMessageExpectedLenght = 0;
00820     mRunningStatus_RX = InvalidType;
00821     
00822 }
00823 
00824 
00825 // Getters
00826 /*! \brief Get the last received message's type
00827  
00828  Returns an enumerated type. @see kMIDIType
00829  */
00830 kMIDIType  MIDI::getType() const
00831 {
00832     
00833     return mMessage.type ;
00834 
00835 }
00836 
00837 
00838 /*! \brief Get the channel of the message stored in the structure.
00839  
00840  Channel range is 1 to 16. For non-channel messages, this will return 0.
00841  */
00842 byte  MIDI::getChannel() const
00843 {
00844     
00845     return mMessage.channel ;
00846 
00847 }
00848 
00849 
00850 /*! \brief Get the first data byte of the last received message. */
00851 byte  MIDI::getData1() const
00852 {
00853     
00854     return mMessage.data1 ;
00855 
00856 }
00857 
00858 
00859 /*! \brief Get the second data byte of the last received message. */
00860 byte  MIDI::getData2() const
00861 { 
00862     
00863     return mMessage.data2 ;
00864 
00865 }
00866 
00867 
00868 /*! \brief Get the System Exclusive byte array. 
00869  
00870  @see getSysExArrayLength to get the array's length in bytes.
00871  */
00872 const byte  * MIDI::getSysExArray() const
00873 { 
00874     
00875     return mMessage.sysex_array ;
00876 
00877 }
00878 
00879 /*! \brief Get the lenght of the System Exclusive array.
00880  
00881  It is coded using data1 as LSB and data2 as MSB.
00882  \return The array's length, in bytes.
00883  */
00884 unsigned int MIDI::getSysExArrayLength() const
00885 {
00886     
00887     unsigned int coded_size = ((unsigned int)(mMessage.data2 ) << 8) | mMessage.data1 ;
00888     
00889     return (coded_size > MIDI_SYSEX_ARRAY_SIZE) ? MIDI_SYSEX_ARRAY_SIZE : coded_size;
00890     
00891 }
00892 
00893 
00894 /*! \brief Check if a valid message is stored in the structure. */
00895 bool MIDI::check() const
00896 { 
00897     
00898     return mMessage.valid ;
00899 
00900 }
00901 
00902 
00903 // Setters
00904 /*! \brief Set the value for the input MIDI channel 
00905  \param Channel the channel value. Valid values are 1 to 16, 
00906  MIDI_CHANNEL_OMNI if you want to listen to all channels, and MIDI_CHANNEL_OFF to disable MIDI input.
00907  */
00908 void MIDI::setInputChannel(const byte  Channel)
00909 { 
00910     
00911     mInputChannel = Channel;
00912     
00913 }
00914 
00915 
00916 #if USE_CALLBACKS
00917 
00918 void MIDI::setHandleNoteOff(void (*fptr)(byte  channel, byte  note, byte  velocity))         { mNoteOffCallback = fptr; }
00919 void MIDI::setHandleNoteOn(void (*fptr)(byte  channel, byte  note, byte  velocity))          { mNoteOnCallback = fptr; }
00920 void MIDI::setHandleAfterTouchPoly(void (*fptr)(byte  channel, byte  note, byte  pressure))  { mAfterTouchPolyCallback = fptr; }
00921 void MIDI::setHandleControlChange(void (*fptr)(byte  channel, byte  number, byte  value))    { mControlChangeCallback = fptr; }
00922 void MIDI::setHandleProgramChange(void (*fptr)(byte  channel, byte  number))                { mProgramChangeCallback = fptr; }
00923 void MIDI::setHandleAfterTouchChannel(void (*fptr)(byte  channel, byte  pressure))          { mAfterTouchChannelCallback = fptr; }
00924 void MIDI::setHandlePitchBend(void (*fptr)(byte  channel, int bend))                       { mPitchBendCallback = fptr; }
00925 void MIDI::setHandleSystemExclusive(void (*fptr)(byte  * array, byte  size))                { mSystemExclusiveCallback = fptr; }
00926 void MIDI::setHandleTimeCodeQuarterFrame(void (*fptr)(byte  data))                         { mTimeCodeQuarterFrameCallback = fptr; }
00927 void MIDI::setHandleSongPosition(void (*fptr)(unsigned int beats))                        { mSongPositionCallback = fptr; }
00928 void MIDI::setHandleSongSelect(void (*fptr)(byte  songnumber))                             { mSongSelectCallback = fptr; }
00929 void MIDI::setHandleTuneRequest(void (*fptr)(void))                                       { mTuneRequestCallback = fptr; }
00930 void MIDI::setHandleClock(void (*fptr)(void))                                             { mClockCallback = fptr; }
00931 void MIDI::setHandleStart(void (*fptr)(void))                                             { mStartCallback = fptr; }
00932 void MIDI::setHandleContinue(void (*fptr)(void))                                          { mContinueCallback = fptr; }
00933 void MIDI::setHandleStop(void (*fptr)(void))                                              { mStopCallback = fptr; }
00934 void MIDI::setHandleActiveSensing(void (*fptr)(void))                                     { mActiveSensingCallback = fptr; }
00935 void MIDI::setHandleSystemReset(void (*fptr)(void))                                       { mSystemResetCallback = fptr; }
00936 
00937 
00938 /*! \brief Detach an external function from the given type.
00939  
00940  Use this method to cancel the effects of setHandle********.
00941  \param Type        The type of message to unbind. When a message of this type is received, no function will be called.
00942  */
00943 void MIDI::disconnectCallbackFromType(kMIDIType  Type)
00944 {
00945     
00946     switch (Type) {
00947         case NoteOff:               mNoteOffCallback = NULL;                break;
00948         case NoteOn:                mNoteOnCallback = NULL;                 break;
00949         case AfterTouchPoly:        mAfterTouchPolyCallback = NULL;         break;
00950         case ControlChange:         mControlChangeCallback = NULL;          break;
00951         case ProgramChange:         mProgramChangeCallback = NULL;          break;
00952         case AfterTouchChannel:     mAfterTouchChannelCallback = NULL;      break;
00953         case PitchBend:             mPitchBendCallback = NULL;              break;
00954         case SystemExclusive:       mSystemExclusiveCallback = NULL;        break;
00955         case TimeCodeQuarterFrame:  mTimeCodeQuarterFrameCallback = NULL;   break;
00956         case SongPosition:          mSongPositionCallback = NULL;           break;
00957         case SongSelect:            mSongSelectCallback = NULL;             break;
00958         case TuneRequest:           mTuneRequestCallback = NULL;            break;
00959         case Clock:                 mClockCallback = NULL;                  break;
00960         case Start:                 mStartCallback = NULL;                  break;
00961         case Continue:              mContinueCallback = NULL;               break;
00962         case Stop:                  mStopCallback = NULL;                   break;
00963         case ActiveSensing:         mActiveSensingCallback = NULL;          break;
00964         case SystemReset:           mSystemResetCallback = NULL;            break;
00965         default:
00966             break;
00967     }
00968     
00969 }
00970 
00971 
00972 // Private - launch callback function based on received type.
00973 void MIDI::launchCallback()
00974 {
00975     
00976     // The order is mixed to allow frequent messages to trigger their callback faster.
00977     
00978     switch (mMessage.type ) {
00979             // Notes
00980         case NoteOff:               if (mNoteOffCallback != NULL)               mNoteOffCallback(mMessage.channel ,mMessage.data1 ,mMessage.data2 );   break;
00981         case NoteOn:                if (mNoteOnCallback != NULL)                mNoteOnCallback(mMessage.channel ,mMessage.data1 ,mMessage.data2 );    break;
00982             
00983             // Real-time messages
00984         case Clock:                 if (mClockCallback != NULL)                 mClockCallback();           break;          
00985         case Start:                 if (mStartCallback != NULL)                 mStartCallback();           break;
00986         case Continue:              if (mContinueCallback != NULL)              mContinueCallback();        break;
00987         case Stop:                  if (mStopCallback != NULL)                  mStopCallback();            break;
00988         case ActiveSensing:         if (mActiveSensingCallback != NULL)         mActiveSensingCallback();   break;
00989             
00990             // Continuous controllers
00991         case ControlChange:         if (mControlChangeCallback != NULL)         mControlChangeCallback(mMessage.channel ,mMessage.data1 ,mMessage.data2 ); break;
00992         case PitchBend:             if (mPitchBendCallback != NULL)             mPitchBendCallback(mMessage.channel ,(int)((mMessage.data1  & 0x7F) | ((mMessage.data2  & 0x7F)<< 7)) - 8192); break; // TODO: check this
00993         case AfterTouchPoly:        if (mAfterTouchPolyCallback != NULL)        mAfterTouchPolyCallback(mMessage.channel ,mMessage.data1 ,mMessage.data2 );    break;
00994         case AfterTouchChannel:     if (mAfterTouchChannelCallback != NULL)     mAfterTouchChannelCallback(mMessage.channel ,mMessage.data1 );    break;
00995             
00996         case ProgramChange:         if (mProgramChangeCallback != NULL)         mProgramChangeCallback(mMessage.channel ,mMessage.data1 );    break;
00997         case SystemExclusive:       if (mSystemExclusiveCallback != NULL)       mSystemExclusiveCallback(mMessage.sysex_array ,mMessage.data1 );  break;
00998             
00999             // Occasional messages
01000         case TimeCodeQuarterFrame:  if (mTimeCodeQuarterFrameCallback != NULL)  mTimeCodeQuarterFrameCallback(mMessage.data1 );  break;
01001         case SongPosition:          if (mSongPositionCallback != NULL)          mSongPositionCallback((mMessage.data1  & 0x7F) | ((mMessage.data2  & 0x7F)<< 7)); break;
01002         case SongSelect:            if (mSongSelectCallback != NULL)            mSongSelectCallback(mMessage.data1 );    break;
01003         case TuneRequest:           if (mTuneRequestCallback != NULL)           mTuneRequestCallback(); break;
01004             
01005         case SystemReset:           if (mSystemResetCallback != NULL)           mSystemResetCallback(); break;
01006         case InvalidType:
01007         default:
01008             break;
01009     }
01010     
01011 }
01012 
01013 
01014 #endif // USE_CALLBACKS
01015 
01016 
01017 #endif // COMPILE_MIDI_IN
01018 
01019 
01020 
01021 
01022 #if (COMPILE_MIDI_IN && COMPILE_MIDI_OUT && COMPILE_MIDI_THRU) // Thru
01023 
01024 /*! \brief Set the filter for thru mirroring
01025  \param inThruFilterMode a filter mode
01026  
01027  @see kThruFilterMode
01028  */
01029 void MIDI::setThruFilterMode(kThruFilterMode  inThruFilterMode)
01030 { 
01031     
01032     mThruFilterMode = inThruFilterMode;
01033     if (mThruFilterMode != Off) mThruActivated = true;
01034     else mThruActivated = false;
01035     
01036 }
01037 
01038 
01039 /*! \brief Setter method: turn message mirroring on. */
01040 void MIDI::turnThruOn(kThruFilterMode  inThruFilterMode)
01041 { 
01042     
01043     mThruActivated = true;
01044     mThruFilterMode = inThruFilterMode;
01045     
01046 }
01047 
01048 
01049 /*! \brief Setter method: turn message mirroring off. */
01050 void MIDI::turnThruOff()
01051 {
01052     
01053     mThruActivated = false; 
01054     mThruFilterMode = Off;
01055     
01056 }
01057 
01058 
01059 // This method is called upon reception of a message and takes care of Thru filtering and sending.
01060 void MIDI::thru_filter(byte  inChannel)
01061 {
01062     
01063     /*
01064      This method handles Soft-Thru filtering.
01065      
01066      Soft-Thru filtering:
01067      - All system messages (System Exclusive, Common and Real Time) are passed to output unless filter is set to Off
01068      - Channel messages are passed to the output whether their channel is matching the input channel and the filter setting
01069      
01070      */
01071     
01072     // If the feature is disabled, don't do anything.
01073     if (!mThruActivated || (mThruFilterMode == Off)) return;
01074     
01075     
01076     // First, check if the received message is Channel
01077     if (mMessage.type  >= NoteOff && mMessage.type  <= PitchBend) {
01078         
01079         const bool filter_condition = ((mMessage.channel  == mInputChannel) || (mInputChannel == MIDI_CHANNEL_OMNI));
01080         
01081         // Now let's pass it to the output
01082         switch (mThruFilterMode) {
01083             case Full:
01084                 send(mMessage.type ,mMessage.data1 ,mMessage.data2 ,mMessage.channel );
01085                 return;
01086             case SameChannel:
01087                 if (filter_condition) {
01088                     send(mMessage.type ,mMessage.data1 ,mMessage.data2 ,mMessage.channel );
01089                     return;
01090                 }
01091                 break;
01092             case DifferentChannel:
01093                 if (!filter_condition) {
01094                     send(mMessage.type ,mMessage.data1 ,mMessage.data2 ,mMessage.channel );
01095                     return;
01096                 }
01097                 break;
01098             case Off:
01099                 // Do nothing. 
01100                 // Technically it's impossible to get there because the case was already tested earlier.
01101                 break;
01102             default:
01103                 break;
01104         }
01105         
01106     }
01107     else {
01108         
01109         // Send the message to the output
01110         switch (mMessage.type ) {
01111                 // Real Time and 1 byte
01112             case Clock:
01113             case Start:
01114             case Stop:
01115             case Continue:
01116             case ActiveSensing:
01117             case SystemReset:
01118             case TuneRequest:   
01119                 sendRealTime(mMessage.type );
01120                 return;
01121                 
01122             case SystemExclusive:
01123                 // Send SysEx (0xF0 and 0xF7 are included in the buffer)
01124                 sendSysEx(mMessage.data1 ,mMessage.sysex_array ,true); 
01125                 return;
01126                 
01127             case SongSelect:
01128                 sendSongSelect(mMessage.data1 );
01129                 return;
01130                 
01131             case SongPosition:
01132                 sendSongPosition(mMessage.data1  | ((unsigned)mMessage.data2 <<7));
01133                 return;
01134                 
01135             case TimeCodeQuarterFrame:
01136                 sendTimeCodeQuarterFrame(mMessage.data1 ,mMessage.data2 );
01137                 return;
01138 
01139             default:
01140                 break;
01141                 
01142         }
01143         
01144     }
01145     
01146 }
01147 
01148 
01149 #endif // Thru