From 698889dd6ea011fca59424b161f9eae1a09071a8 Mon Sep 17 00:00:00 2001 From: Francois Best Date: Tue, 22 May 2012 22:34:15 +0200 Subject: [PATCH] Cosmetics. --- src/MIDI.cpp | 178 +++++++++++++++++++++++++++++++-------------------- src/MIDI.h | 149 ++++++++++++++++++++++++++---------------- 2 files changed, 204 insertions(+), 123 deletions(-) diff --git a/src/MIDI.cpp b/src/MIDI.cpp index 335748f..9517f99 100644 --- a/src/MIDI.cpp +++ b/src/MIDI.cpp @@ -10,7 +10,8 @@ #include "MIDI.h" #include -#include "Arduino.h" // If using an old (pre-1.0) version of Arduino, use WConstants.h instead of Arduino.h +#include "Arduino.h" // If using an old (pre-1.0) version of Arduino, + // use WConstants.h instead of Arduino.h #include "HardwareSerial.h" @@ -20,13 +21,12 @@ #include "../SoftwareSerial/SoftwareSerial.h" SoftwareSerial softSerialClass(SOFTSERIAL_RX_PIN,SOFTSERIAL_TX_PIN); -#undef USE_SERIAL_PORT -#define USE_SERIAL_PORT softSerialClass +#undef MIDI_SERIAL_PORT +#define MIDI_SERIAL_PORT softSerialClass #endif // USE_SOFTWARE_SERIAL - /*! \brief Main instance (the class comes pre-instantiated). */ MIDI_Class MIDI; @@ -82,7 +82,7 @@ void MIDI_Class::begin(const byte inChannel) { // Initialise the Serial port - USE_SERIAL_PORT.begin(MIDI_BAUDRATE); + MIDI_SERIAL_PORT.begin(MIDI_BAUDRATE); #if COMPILE_MIDI_OUT @@ -122,6 +122,10 @@ void MIDI_Class::begin(const byte inChannel) } +// ============================================================================= +// MIDI Output +// ============================================================================= + #if COMPILE_MIDI_OUT // Private method for generating a status byte from channel and type @@ -136,11 +140,14 @@ const byte MIDI_Class::genstatus(const kMIDIType inType, /*! \brief Generate and send a MIDI message from the values given. \param type The message type (see type defines for reference) - \param data1 The first data byte. - \param data2 The second data byte (if the message contains only 1 data byte, set this one to 0). - \param channel The output channel on which the message will be sent (values from 1 to 16). Note: you cannot send to OMNI. + \param data1 The first data byte. + \param data2 The second data byte (if the message contains only 1 data byte, + set this one to 0). + \param channel The output channel on which the message will be sent + (values from 1 to 16). Note: you cannot send to OMNI. - This is an internal method, use it only if you need to send raw data from your code, at your own risks. + This is an internal method, use it only if you need to send raw data + from your code, at your own risks. */ void MIDI_Class::send(kMIDIType type, byte data1, @@ -172,17 +179,17 @@ void MIDI_Class::send(kMIDIType type, if (mRunningStatus_TX != statusbyte) { // New message, memorise and send header mRunningStatus_TX = statusbyte; - USE_SERIAL_PORT.write(mRunningStatus_TX); + MIDI_SERIAL_PORT.write(mRunningStatus_TX); } #else // Don't care about running status, send the Control byte. - USE_SERIAL_PORT.write(statusbyte); + MIDI_SERIAL_PORT.write(statusbyte); #endif // Then send data - USE_SERIAL_PORT.write(data1); + MIDI_SERIAL_PORT.write(data1); if (type != ProgramChange && type != AfterTouchChannel) { - USE_SERIAL_PORT.write(data2); + MIDI_SERIAL_PORT.write(data2); } return; } @@ -195,9 +202,13 @@ void MIDI_Class::send(kMIDIType type, /*! \brief Send a Note On message - \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 - \param Velocity Note attack velocity (0 to 127). A NoteOn with 0 velocity is considered as a NoteOff. - \param Channel The channel on which the message will be sent (1 to 16). + \param NoteNumber Pitch value in the MIDI format (0 to 127). + \param Velocity Note attack velocity (0 to 127). A + NoteOn with 0 velocity is considered as a NoteOff. + \param Channel The channel on which the message will be sent (1 to 16). + + Take a look at the values, names and frequencies of notes here: + http://www.phys.unsw.edu.au/jw/notes.html */ void MIDI_Class::sendNoteOn(byte NoteNumber, byte Velocity, @@ -210,9 +221,12 @@ void MIDI_Class::sendNoteOn(byte NoteNumber, /*! \brief Send a Note Off message (a real Note Off, not a Note On with null velocity) - \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 + \param NoteNumber Pitch value in the MIDI format (0 to 127). \param Velocity Release velocity (0 to 127). - \param Channel The channel on which the message will be sent (1 to 16). + \param Channel The channel on which the message will be sent (1 to 16). + + Take a look at the values, names and frequencies of notes here: + http://www.phys.unsw.edu.au/jw/notes.html */ void MIDI_Class::sendNoteOff(byte NoteNumber, byte Velocity, @@ -225,8 +239,8 @@ void MIDI_Class::sendNoteOff(byte NoteNumber, /*! \brief Send a Program Change message - \param ProgramNumber The Program to select (0 to 127). - \param Channel The channel on which the message will be sent (1 to 16). + \param ProgramNumber The Program to select (0 to 127). + \param Channel The channel on which the message will be sent (1 to 16). */ void MIDI_Class::sendProgramChange(byte ProgramNumber, byte Channel) @@ -238,9 +252,12 @@ void MIDI_Class::sendProgramChange(byte ProgramNumber, /*! \brief Send a Control Change message - \param ControlNumber The controller number (0 to 127). See the detailed description here: http://www.somascape.org/midi/tech/spec.html#ctrlnums + \param ControlNumber The controller number (0 to 127). \param ControlValue The value for the specified controller (0 to 127). - \param Channel The channel on which the message will be sent (1 to 16). + \param Channel The channel on which the message will be sent (1 to 16). + + See the detailed controllers numbers & description here: + http://www.somascape.org/midi/tech/spec.html#ctrlnums */ void MIDI_Class::sendControlChange(byte ControlNumber, byte ControlValue, @@ -253,9 +270,9 @@ void MIDI_Class::sendControlChange(byte ControlNumber, /*! \brief Send a Polyphonic AfterTouch message (applies to only one specified note) - \param NoteNumber The note to apply AfterTouch to (0 to 127). - \param Pressure The amount of AfterTouch to apply (0 to 127). - \param Channel The channel on which the message will be sent (1 to 16). + \param NoteNumber The note to apply AfterTouch to (0 to 127). + \param Pressure The amount of AfterTouch to apply (0 to 127). + \param Channel The channel on which the message will be sent (1 to 16). */ void MIDI_Class::sendPolyPressure(byte NoteNumber, byte Pressure, @@ -268,8 +285,8 @@ void MIDI_Class::sendPolyPressure(byte NoteNumber, /*! \brief Send a MonoPhonic AfterTouch message (applies to all notes) - \param Pressure The amount of AfterTouch to apply to all notes. - \param Channel The channel on which the message will be sent (1 to 16). + \param Pressure The amount of AfterTouch to apply to all notes. + \param Channel The channel on which the message will be sent (1 to 16). */ void MIDI_Class::sendAfterTouch(byte Pressure, byte Channel) @@ -281,8 +298,10 @@ void MIDI_Class::sendAfterTouch(byte Pressure, /*! \brief Send a Pitch Bend message using a signed integer value. - \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. - \param Channel The channel on which the message will be sent (1 to 16). + \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. + \param Channel The channel on which the message will be sent (1 to 16). */ void MIDI_Class::sendPitchBend(int PitchValue, byte Channel) @@ -295,8 +314,10 @@ void MIDI_Class::sendPitchBend(int PitchValue, /*! \brief Send a Pitch Bend message using an unsigned integer value. - \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. - \param Channel The channel on which the message will be sent (1 to 16). + \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. + \param Channel The channel on which the message will be sent (1 to 16). */ void MIDI_Class::sendPitchBend(unsigned int PitchValue, byte Channel) @@ -308,8 +329,10 @@ void MIDI_Class::sendPitchBend(unsigned int PitchValue, /*! \brief Send a Pitch Bend message using a floating point value. - \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. - \param Channel The channel on which the message will be sent (1 to 16). + \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. + \param Channel The channel on which the message will be sent (1 to 16). */ void MIDI_Class::sendPitchBend(double PitchValue, byte Channel) @@ -323,10 +346,13 @@ void MIDI_Class::sendPitchBend(double PitchValue, /*! \brief Generate and send a System Exclusive frame. - \param length The size of the array to send - \param array The byte array containing the data to send - \param ArrayContainsBoundaries When set to 'true', 0xF0 & 0xF7 bytes (start & stop SysEx) will NOT be sent (and therefore must be included in the array). - default value is set to 'false' for compatibility with previous versions of the library. + \param length The size of the array to send + \param array The byte array containing the data to send + \param ArrayContainsBoundaries When set to 'true', 0xF0 & 0xF7 bytes + (start & stop SysEx) will NOT be sent + (and therefore must be included in the array). + default value for ArrayContainsBoundaries is set to 'false' for compatibility + with previous versions of the library. */ void MIDI_Class::sendSysEx(int length, const byte *const array, @@ -335,22 +361,22 @@ void MIDI_Class::sendSysEx(int length, if (ArrayContainsBoundaries == false) { - USE_SERIAL_PORT.write(0xF0); + MIDI_SERIAL_PORT.write(0xF0); for (int i=0;i> 7) & 0x7F); + MIDI_SERIAL_PORT.write((byte)SongPosition); + MIDI_SERIAL_PORT.write(Beats & 0x7F); + MIDI_SERIAL_PORT.write((Beats >> 7) & 0x7F); #if USE_RUNNING_STATUS mRunningStatus_TX = InvalidType; @@ -429,8 +457,8 @@ void MIDI_Class::sendSongPosition(unsigned int Beats) void MIDI_Class::sendSongSelect(byte SongNumber) { - USE_SERIAL_PORT.write((byte)SongSelect); - USE_SERIAL_PORT.write(SongNumber & 0x7F); + MIDI_SERIAL_PORT.write((byte)SongSelect); + MIDI_SERIAL_PORT.write(SongNumber & 0x7F); #if USE_RUNNING_STATUS mRunningStatus_TX = InvalidType; @@ -441,7 +469,8 @@ void MIDI_Class::sendSongSelect(byte SongNumber) /*! \brief Send a Real Time (one byte) message. - \param Type The available Real Time types are: Start, Stop, Continue, Clock, ActiveSensing and SystemReset. + \param Type The available Real Time types are: + Start, Stop, Continue, Clock, ActiveSensing and SystemReset. You can also send a Tune Request with this method. @see kMIDIType */ @@ -455,7 +484,7 @@ void MIDI_Class::sendRealTime(kMIDIType Type) case Continue: case ActiveSensing: case SystemReset: - USE_SERIAL_PORT.write((byte)Type); + MIDI_SERIAL_PORT.write((byte)Type); break; default: // Invalid Real Time marker @@ -473,14 +502,19 @@ void MIDI_Class::sendRealTime(kMIDIType Type) #endif // COMPILE_MIDI_OUT +// ============================================================================= +// MIDI Input +// ============================================================================= #if COMPILE_MIDI_IN -/*! \brief Read a MIDI message from the serial port using the main input channel (see setInputChannel() for reference). +/*! \brief Read a MIDI message from the serial port + using the main input channel (see setInputChannel() for reference). - Returned value: true if any valid message has been stored in the structure, false if not. + \return True if a valid message has been stored in the structure, false if not. A valid message is a message that matches the input channel. \n\n - If the Thru is enabled and the messages matches the filter, it is sent back on the MIDI output. + If the Thru is enabled and the messages matches the filter, + it is sent back on the MIDI output. */ bool MIDI_Class::read() { @@ -490,7 +524,9 @@ bool MIDI_Class::read() } -/*! \brief Reading/thru-ing method, the same as read() with a given input channel to read on. */ +/*! \brief Reading/thru-ing method, the same as read() + with a given input channel to read on. + */ bool MIDI_Class::read(const byte inChannel) { @@ -522,7 +558,7 @@ bool MIDI_Class::read(const byte inChannel) bool MIDI_Class::parse(byte inChannel) { - const int bytes_available = USE_SERIAL_PORT.available(); + const int bytes_available = MIDI_SERIAL_PORT.available(); if (bytes_available <= 0) { // No data available. @@ -531,7 +567,7 @@ bool MIDI_Class::parse(byte inChannel) // If the buffer is full -> Don't Panic! Call the Vogons to destroy it. if (bytes_available == 128) { - USE_SERIAL_PORT.flush(); + MIDI_SERIAL_PORT.flush(); } else { @@ -544,7 +580,7 @@ bool MIDI_Class::parse(byte inChannel) */ - const byte extracted = USE_SERIAL_PORT.read(); + const byte extracted = MIDI_SERIAL_PORT.read(); if (mPendingMessageIndex == 0) { // Start a new pending message mPendingMessage[0] = extracted; @@ -856,7 +892,8 @@ kMIDIType MIDI_Class::getType() const /*! \brief Get the channel of the message stored in the structure. - Channel range is 1 to 16. For non-channel messages, this will return 0. + \return Channel range is 1 to 16. + For non-channel messages, this will return 0. */ byte MIDI_Class::getChannel() const { @@ -922,7 +959,8 @@ bool MIDI_Class::check() const // Setters /*! \brief Set the value for the input MIDI channel \param Channel the channel value. Valid values are 1 to 16, - MIDI_CHANNEL_OMNI if you want to listen to all channels, and MIDI_CHANNEL_OFF to disable MIDI input. + MIDI_CHANNEL_OMNI if you want to listen to all channels, + and MIDI_CHANNEL_OFF to disable MIDI input. */ void MIDI_Class::setInputChannel(const byte Channel) { @@ -957,7 +995,8 @@ void MIDI_Class::setHandleSystemReset(void (*fptr)(void)) /*! \brief Detach an external function from the given type. Use this method to cancel the effects of setHandle********. - \param Type The type of message to unbind. When a message of this type is received, no function will be called. + \param Type The type of message to unbind. + When a message of this type is received, no function will be called. */ void MIDI_Class::disconnectCallbackFromType(kMIDIType Type) { @@ -1036,9 +1075,11 @@ void MIDI_Class::launchCallback() #endif // COMPILE_MIDI_IN +// ============================================================================= +// MIDI Soft Thru +// ============================================================================= - -#if (COMPILE_MIDI_IN && COMPILE_MIDI_OUT && COMPILE_MIDI_THRU) // Thru +#if (COMPILE_MIDI_IN && COMPILE_MIDI_OUT && COMPILE_MIDI_THRU) /*! \brief Set the filter for thru mirroring \param inThruFilterMode a filter mode @@ -1075,7 +1116,8 @@ void MIDI_Class::turnThruOff() } -// This method is called upon reception of a message and takes care of Thru filtering and sending. +// This method is called upon reception of a message +// and takes care of Thru filtering and sending. void MIDI_Class::thru_filter(byte inChannel) { diff --git a/src/MIDI.h b/src/MIDI.h index 993c1d6..58ea2f2 100644 --- a/src/MIDI.h +++ b/src/MIDI.h @@ -31,24 +31,24 @@ #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 1 // 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. + // Please note that the Thru will work only when both COMPILE_MIDI_IN and COMPILE_MIDI_OUT set to 1. -#define USE_SERIAL_PORT Serial // Change the number (to Serial1 for example) if you want -// to use a different serial port for MIDI I/O. +#define MIDI_SERIAL_PORT Serial // Change the number (to Serial1 for example) if you want + // to use a different serial port for MIDI I/O. -#define USE_SOFTWARE_SERIAL 1 // Set to 1 to use SoftwareSerial instead of native serial ports. +#define USE_SOFTWARE_SERIAL 0 // Set to 1 to use SoftwareSerial instead of native serial ports. #define SOFTSERIAL_RX_PIN 1 // This pin number will be used for MIDI Input #define SOFTSERIAL_TX_PIN 2 // This pin number will be used for MIDI Output. #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. + // of the same type and channel. + // Set to 0 if you have troubles controlling your 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 + // 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). @@ -63,10 +63,14 @@ #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; + +/*! 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 @@ -87,9 +91,10 @@ enum kMIDIType { 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 + InvalidType = 0x00 ///< For notifying errors }; + /*! Enumeration of Thru filter modes */ enum kThruFilterMode { Off = 0, ///< Thru disabled (nothing passes through). @@ -99,20 +104,46 @@ enum kThruFilterMode { }; -/*! 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. */ +/*! The midimsg structure contains decoded data + of a MIDI message read from the serial port + with read() or thru(). + */ +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) */ + + /*! 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 */ + + /*! The first data byte. + \n Value goes from 0 to 127. + */ 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. */ + + /*! 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) */ + + /*! 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. */ + + /*! 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; + }; @@ -122,22 +153,24 @@ struct midimsg { See member descriptions to know how to use it, or check out the examples supplied with the library. */ -class MIDI_Class { - +class MIDI_Class +{ public: + + // ========================================================================= // Constructor and Destructor + MIDI_Class(); ~MIDI_Class(); - void begin(const byte inChannel = 1); + // ========================================================================= + // MIDI Output - - /* ####### OUTPUT COMPILATION BLOCK ####### */ -#if COMPILE_MIDI_OUT +#if COMPILE_MIDI_OUT // Start compilation block public: @@ -170,12 +203,14 @@ private: byte mRunningStatus_TX; #endif // USE_RUNNING_STATUS -#endif // COMPILE_MIDI_OUT +#endif // COMPILE_MIDI_OUT - /* ####### INPUT COMPILATION BLOCK ####### */ -#if COMPILE_MIDI_IN + // ========================================================================= + // MIDI Input + +#if COMPILE_MIDI_IN // Start compilation block public: @@ -205,18 +240,40 @@ public: */ static inline const kMIDIType getTypeFromStatusByte(const byte inStatus) { - if ((inStatus < 0x80) - || (inStatus == 0xF4) - || (inStatus == 0xF5) - || (inStatus == 0xF9) - || (inStatus == 0xFD)) return InvalidType; // data bytes and undefined. + 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; } +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; + + + // ========================================================================= + // Input Callbacks + #if USE_CALLBACKS +public: + 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)); @@ -238,27 +295,8 @@ public: 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); @@ -280,14 +318,15 @@ private: void (*mActiveSensingCallback)(void); void (*mSystemResetCallback)(void); -#endif // USE_CALLBACKS - +#endif // USE_CALLBACKS #endif // COMPILE_MIDI_IN - /* ####### THRU COMPILATION BLOCK ####### */ -#if (COMPILE_MIDI_IN && COMPILE_MIDI_OUT && COMPILE_MIDI_THRU) // Thru + // ========================================================================= + // MIDI Soft Thru + +#if (COMPILE_MIDI_IN && COMPILE_MIDI_OUT && COMPILE_MIDI_THRU) public: