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

MIDI.h

Committer:
okini3939
Date:
2013-01-08
Revision:
1:0eeca7deec08
Parent:
0:713ef38fead1

File content as of revision 1:0eeca7deec08:

/*!
 *  @file       MIDI.h
 *  Project     MIDI Library
 *  @brief      MIDI Library for the Arduino
 *  Version     3.2
 *  @author     Francois Best 
 *  @date       24/02/11
 *  License     GPL Forty Seven Effects - 2011
 */
/*
 * Ported for mbed by Hiroshi Suga
 *   Orignal: http://www.arduino.cc/playground/Main/MIDILibrary
 */

#ifndef LIB_MIDI_H_
#define LIB_MIDI_H_

#include "mbed.h"


/*  
    ###############################################################
    #                                                             #
    #    CONFIGURATION AREA                                       #
    #                                                             #
    #    Here are a few settings you can change to customize      #
    #    the library for your own project. You can for example    #
    #    choose to compile only parts of it so you gain flash     #
    #    space and optimise the speed of your sketch.             #
    #                                                             #
    ###############################################################
 */


#define COMPILE_MIDI_IN         1           // Set this setting to 1 to use the MIDI input.
#define COMPILE_MIDI_OUT        1           // Set this setting to 1 to use the MIDI output. 
#define COMPILE_MIDI_THRU       0           // Set this setting to 1 to use the MIDI Soft Thru feature
                                            // Please note that the Thru will work only when both COMPILE_MIDI_IN and COMPILE_MIDI_OUT set to 1.


#define USE_SERIAL_PORT         _midi      // Change the number (to Serial1 for example) if you want
                                            // to use a different serial port for MIDI I/O.


#define USE_RUNNING_STATUS      1           // Running status enables short messages when sending multiple values
                                            // of the same type and channel.
                                            // Set to 0 if you have troubles with controlling you hardware.


#define USE_CALLBACKS           1           // Set this to 1 if you want to use callback handlers (to bind your functions to the library).
                                            // To use the callbacks, you need to have COMPILE_MIDI_IN set to 1

#define USE_1BYTE_PARSING       1           // Each call to MIDI.read will only parse one byte (might be faster).


// END OF CONFIGURATION AREA 
// (do not modify anything under this line unless you know what you are doing)


#define MIDI_BAUDRATE           31250

#define MIDI_CHANNEL_OMNI       0
#define MIDI_CHANNEL_OFF        17          // and over

#define MIDI_SYSEX_ARRAY_SIZE   255         // Maximum size is 65535 bytes.

/*! Type definition for practical use (because "unsigned char" is a bit long to write.. )*/
typedef uint8_t byte;
typedef uint16_t word;

/*! Enumeration of MIDI types */
enum kMIDIType {
    NoteOff               = 0x80,   ///< Note Off
    NoteOn                = 0x90,   ///< Note On
    AfterTouchPoly        = 0xA0,   ///< Polyphonic AfterTouch
    ControlChange         = 0xB0,   ///< Control Change / Channel Mode
    ProgramChange         = 0xC0,   ///< Program Change
    AfterTouchChannel     = 0xD0,   ///< Channel (monophonic) AfterTouch
    PitchBend             = 0xE0,   ///< Pitch Bend
    SystemExclusive       = 0xF0,   ///< System Exclusive
    TimeCodeQuarterFrame  = 0xF1,   ///< System Common - MIDI Time Code Quarter Frame
    SongPosition          = 0xF2,   ///< System Common - Song Position Pointer
    SongSelect            = 0xF3,   ///< System Common - Song Select
    TuneRequest           = 0xF6,   ///< System Common - Tune Request
    Clock                 = 0xF8,   ///< System Real Time - Timing Clock
    Start                 = 0xFA,   ///< System Real Time - Start
    Continue              = 0xFB,   ///< System Real Time - Continue
    Stop                  = 0xFC,   ///< System Real Time - Stop
    ActiveSensing         = 0xFE,   ///< System Real Time - Active Sensing
    SystemReset           = 0xFF,   ///< System Real Time - System Reset
    InvalidType           = 0x00    ///< For notifying errors
};

/*! Enumeration of Thru filter modes */
enum kThruFilterMode {
    Off                   = 0,  ///< Thru disabled (nothing passes through).
    Full                  = 1,  ///< Fully enabled Thru (every incoming message is sent back).
    SameChannel           = 2,  ///< Only the messages on the Input Channel will be sent back.
    DifferentChannel      = 3   ///< All the messages but the ones on the Input Channel will be sent back.
};


/*! The midimsg structure contains decoded data of a MIDI message read from the serial port with read() or thru(). \n */
struct midimsg {
    /*! The MIDI channel on which the message was recieved. \n Value goes from 1 to 16. */
    byte channel; 
    /*! The type of the message (see the define section for types reference) */
    kMIDIType type;
    /*! The first data byte.\n Value goes from 0 to 127.\n */
    byte data1;
    /*! The second data byte. If the message is only 2 bytes long, this one is null.\n Value goes from 0 to 127. */
    byte data2;
    /*! System Exclusive dedicated byte array. \n Array length is stocked on 16 bits, in data1 (LSB) and data2 (MSB) */
    byte sysex_array[MIDI_SYSEX_ARRAY_SIZE];
    /*! This boolean indicates if the message is valid or not. There is no channel consideration here, validity means the message respects the MIDI norm. */
    bool valid;
};




/*! \brief The main class for MIDI handling.\n
    See member descriptions to know how to use it,
    or check out the examples supplied with the library.
 */
class MIDI {
    
    
public:
    // Constructor and Destructor
    MIDI(PinName p_tx, PinName p_rx);
    ~MIDI();
    
    
    void begin(const byte inChannel = 1);
    
    
    
    
/* ####### OUTPUT COMPILATION BLOCK ####### */  
#if COMPILE_MIDI_OUT

public: 
    
    void sendNoteOn(byte NoteNumber,byte Velocity,byte Channel);
    void sendNoteOff(byte NoteNumber,byte Velocity,byte Channel);
    void sendProgramChange(byte ProgramNumber,byte Channel);
    void sendControlChange(byte ControlNumber, byte ControlValue,byte Channel);
    void sendPitchBend(int PitchValue,byte Channel);
    void sendPitchBend(unsigned int PitchValue,byte Channel);
    void sendPitchBend(double PitchValue,byte Channel);
    void sendPolyPressure(byte NoteNumber,byte Pressure,byte Channel);
    void sendAfterTouch(byte Pressure,byte Channel);
    void sendSysEx(int length, const byte *const array,bool ArrayContainsBoundaries = false);   
    void sendTimeCodeQuarterFrame(byte TypeNibble, byte ValuesNibble);
    void sendTimeCodeQuarterFrame(byte data);
    void sendSongPosition(unsigned int Beats);
    void sendSongSelect(byte SongNumber);
    void sendTuneRequest();
    void sendRealTime(kMIDIType Type);
    
    void send(kMIDIType type, byte param1, byte param2, byte channel);
    
private:
    
    Serial _midi;
    byte genstatus(const kMIDIType inType,const byte inChannel) const;
    
    
    // Attributes
#if USE_RUNNING_STATUS
    byte            mRunningStatus_TX;
#endif // USE_RUNNING_STATUS

#endif  // COMPILE_MIDI_OUT
    

    
/* ####### INPUT COMPILATION BLOCK ####### */
#if COMPILE_MIDI_IN 
    
public:
    
    bool read();
    bool read(const byte Channel);
    
    // Getters
    kMIDIType getType() const;
    byte getChannel() const;
    byte getData1() const;
    byte getData2() const;
    const byte * getSysExArray() const;
    unsigned int getSysExArrayLength() const;
    bool check() const;
    
    byte getInputChannel() const 
    {
        return mInputChannel;
    }
    
    // Setters
    void setInputChannel(const byte Channel);
    
    /*! \brief Extract an enumerated MIDI type from a status byte.
     
     This is a utility static method, used internally, made public so you can handle kMIDITypes more easily.
     */
    static inline kMIDIType getTypeFromStatusByte(const byte inStatus) 
    {
        if ((inStatus < 0x80) 
            || (inStatus == 0xF4) 
            || (inStatus == 0xF5) 
            || (inStatus == 0xF9) 
            || (inStatus == 0xFD)) return InvalidType; // data bytes and undefined.
        if (inStatus < 0xF0) return (kMIDIType)(inStatus & 0xF0);   // Channel message, remove channel nibble.
        else return (kMIDIType)inStatus;
    }
    
    
#if USE_CALLBACKS
    
    void setHandleNoteOff(void (*fptr)(byte channel, byte note, byte velocity));
    void setHandleNoteOn(void (*fptr)(byte channel, byte note, byte velocity));
    void setHandleAfterTouchPoly(void (*fptr)(byte channel, byte note, byte pressure));
    void setHandleControlChange(void (*fptr)(byte channel, byte number, byte value));
    void setHandleProgramChange(void (*fptr)(byte channel, byte number));
    void setHandleAfterTouchChannel(void (*fptr)(byte channel, byte pressure));
    void setHandlePitchBend(void (*fptr)(byte channel, int bend));
    void setHandleSystemExclusive(void (*fptr)(byte * array, byte size));
    void setHandleTimeCodeQuarterFrame(void (*fptr)(byte data));
    void setHandleSongPosition(void (*fptr)(unsigned int beats));
    void setHandleSongSelect(void (*fptr)(byte songnumber));
    void setHandleTuneRequest(void (*fptr)(void));
    void setHandleClock(void (*fptr)(void));
    void setHandleStart(void (*fptr)(void));
    void setHandleContinue(void (*fptr)(void));
    void setHandleStop(void (*fptr)(void));
    void setHandleActiveSensing(void (*fptr)(void));
    void setHandleSystemReset(void (*fptr)(void));
    
    void disconnectCallbackFromType(kMIDIType Type);
    
#endif // USE_CALLBACKS
    
    
private:
    
    bool input_filter(byte inChannel);
    bool parse(byte inChannel);
    void reset_input_attributes();
    
    // Attributes
    byte            mRunningStatus_RX;
    byte            mInputChannel;
    
    byte            mPendingMessage[MIDI_SYSEX_ARRAY_SIZE];
    unsigned int    mPendingMessageExpectedLenght;
    unsigned int    mPendingMessageIndex;                   // Extended to unsigned int for larger sysex payloads.
    
    midimsg         mMessage;
    
#if USE_CALLBACKS
    
    void launchCallback();
    
    void (*mNoteOffCallback)(byte channel, byte note, byte velocity);
    void (*mNoteOnCallback)(byte channel, byte note, byte velocity);
    void (*mAfterTouchPolyCallback)(byte channel, byte note, byte velocity);
    void (*mControlChangeCallback)(byte channel, byte, byte);
    void (*mProgramChangeCallback)(byte channel, byte);
    void (*mAfterTouchChannelCallback)(byte channel, byte);
    void (*mPitchBendCallback)(byte channel, int);
    void (*mSystemExclusiveCallback)(byte * array, byte size);
    void (*mTimeCodeQuarterFrameCallback)(byte data);
    void (*mSongPositionCallback)(unsigned int beats);
    void (*mSongSelectCallback)(byte songnumber);
    void (*mTuneRequestCallback)(void);
    void (*mClockCallback)(void);
    void (*mStartCallback)(void);
    void (*mContinueCallback)(void);
    void (*mStopCallback)(void);
    void (*mActiveSensingCallback)(void);
    void (*mSystemResetCallback)(void);
    
#endif // USE_CALLBACKS
    
    
#endif // COMPILE_MIDI_IN
    

/* ####### THRU COMPILATION BLOCK ####### */
#if (COMPILE_MIDI_IN && COMPILE_MIDI_OUT && COMPILE_MIDI_THRU) // Thru
    
public:
    
    // Getters
    kThruFilterMode getFilterMode() const { return mThruFilterMode; }
    bool getThruState() const { return mThruActivated; }
    
    
    // Setters
    void turnThruOn(kThruFilterMode inThruFilterMode = Full);
    void turnThruOff();
    
    void setThruFilterMode(const kThruFilterMode inThruFilterMode);
    
    
private:
    
    void thru_filter(byte inChannel);
    
    bool                mThruActivated;
    kThruFilterMode     mThruFilterMode;
    
#endif // Thru
    
};

#endif // LIB_MIDI_H_