Cosmetics.

This commit is contained in:
Francois Best 2012-05-22 22:34:15 +02:00
parent 21b1e76e95
commit 698889dd6e
2 changed files with 204 additions and 123 deletions

View File

@ -10,7 +10,8 @@
#include "MIDI.h"
#include <stdlib.h>
#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
@ -137,10 +141,13 @@ 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 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 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).
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,
@ -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).
See the detailed controllers numbers & description here:
http://www.somascape.org/midi/tech/spec.html#ctrlnums
*/
void MIDI_Class::sendControlChange(byte ControlNumber,
byte ControlValue,
@ -281,7 +298,9 @@ 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 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,
@ -295,7 +314,9 @@ 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 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,
@ -308,7 +329,9 @@ 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 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,
@ -325,8 +348,11 @@ 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 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<length;++i) {
USE_SERIAL_PORT.write(array[i]);
MIDI_SERIAL_PORT.write(array[i]);
}
USE_SERIAL_PORT.write(0xF7);
MIDI_SERIAL_PORT.write(0xF7);
}
else {
for (int i=0;i<length;++i) {
USE_SERIAL_PORT.write(array[i]);
MIDI_SERIAL_PORT.write(array[i]);
}
@ -365,7 +391,8 @@ void MIDI_Class::sendSysEx(int length,
/*! \brief Send a Tune Request message.
When a MIDI unit receives this message, it should tune its oscillators (if equipped with any)
When a MIDI unit receives this message,
it should tune its oscillators (if equipped with any).
*/
void MIDI_Class::sendTuneRequest()
{
@ -377,9 +404,9 @@ void MIDI_Class::sendTuneRequest()
/*! \brief Send a MIDI Time Code Quarter Frame.
See MIDI Specification for more information.
\param TypeNibble MTC type
\param ValuesNibble MTC data
See MIDI Specification for more information.
*/
void MIDI_Class::sendTimeCodeQuarterFrame(byte TypeNibble, byte ValuesNibble)
{
@ -392,14 +419,15 @@ void MIDI_Class::sendTimeCodeQuarterFrame(byte TypeNibble, byte ValuesNibble)
/*! \brief Send a MIDI Time Code Quarter Frame.
\param data if you want to encode directly the nibbles in your program,
you can send the byte here.
See MIDI Specification for more information.
\param data if you want to encode directly the nibbles in your program, you can send the byte here.
*/
void MIDI_Class::sendTimeCodeQuarterFrame(byte data)
{
USE_SERIAL_PORT.write((byte)TimeCodeQuarterFrame);
USE_SERIAL_PORT.write(data);
MIDI_SERIAL_PORT.write((byte)TimeCodeQuarterFrame);
MIDI_SERIAL_PORT.write(data);
#if USE_RUNNING_STATUS
mRunningStatus_TX = InvalidType;
@ -414,9 +442,9 @@ void MIDI_Class::sendTimeCodeQuarterFrame(byte data)
void MIDI_Class::sendSongPosition(unsigned int Beats)
{
USE_SERIAL_PORT.write((byte)SongPosition);
USE_SERIAL_PORT.write(Beats & 0x7F);
USE_SERIAL_PORT.write((Beats >> 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)
{

View File

@ -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.. )*/
/*! 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
@ -90,6 +94,7 @@ enum kMIDIType {
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:
@ -174,8 +207,10 @@ private:
/* ####### 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);
@ -282,12 +320,13 @@ private:
#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: