aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDonald Delmar Davis <don@suspectdevices.com>2013-04-24 22:15:21 -0700
committerDonald Delmar Davis <don@suspectdevices.com>2013-04-24 22:15:21 -0700
commitaa917d1d8fd5dde9934264bdaa0891e08a08fd1d (patch)
tree665fcd4d8fdcee9501ff52f17734ac0af0f6546c
parent3db89a7ef64570933fa152cd616c93424c8a5d50 (diff)
I am told that I need to commit at least once a day so people know I am alive...
-rw-r--r--libmaple/include/libmaple/MidiSpecs.h (renamed from libmaple/MidiSpecs.h)0
-rw-r--r--libmaple/include/libmaple/MinSysex.h (renamed from libmaple/MinSysex.h)0
-rw-r--r--libmaple/include/libmaple/usb_midi_device.h2
-rw-r--r--wirish/include/wirish/usb_midi.h186
-rw-r--r--wirish/usb_midi.cpp440
5 files changed, 599 insertions, 29 deletions
diff --git a/libmaple/MidiSpecs.h b/libmaple/include/libmaple/MidiSpecs.h
index 293060d..293060d 100644
--- a/libmaple/MidiSpecs.h
+++ b/libmaple/include/libmaple/MidiSpecs.h
diff --git a/libmaple/MinSysex.h b/libmaple/include/libmaple/MinSysex.h
index 57e371d..57e371d 100644
--- a/libmaple/MinSysex.h
+++ b/libmaple/include/libmaple/MinSysex.h
diff --git a/libmaple/include/libmaple/usb_midi_device.h b/libmaple/include/libmaple/usb_midi_device.h
index 1cac225..63e886d 100644
--- a/libmaple/include/libmaple/usb_midi_device.h
+++ b/libmaple/include/libmaple/usb_midi_device.h
@@ -36,6 +36,8 @@
#define _LIBMAPLE_USB_MIDI_H_
#include <libmaple/libmaple_types.h>
+#include <MidiSpecs.h>
+#include <MinSysex.h>
#include <libmaple/gpio.h>
#include <libmaple/usb.h>
diff --git a/wirish/include/wirish/usb_midi.h b/wirish/include/wirish/usb_midi.h
index 3ee1989..99f2ad8 100644
--- a/wirish/include/wirish/usb_midi.h
+++ b/wirish/include/wirish/usb_midi.h
@@ -35,29 +35,183 @@
#include <wirish/Print.h>
#include <wirish/boards.h>
-/**
- * @brief Virtual serial terminal.
+/*
+ * This is the Midi class. If you are just sending Midi data, you only need to make an
+ * instance of the class, passing it your serial port -- in most cases it looks like
+ *
+ * USBMidi midi(channel);
+ *
+ * then you don't need to do anything else; you can start using it to send Midi messages,
+ * e.g.
+ *
+ * midi.sendNoteOn(1, note, velocity);
+ *
+ * If you are using it to receive Midi data, it's a little more complex & you will need
+ * to subclass the Midi class.
+ *
+ * For people not used to C++ this may look confusing, but it's actually pretty easy.
+ * Note that you only need to write the functions for event types you want to handle.
+ * They should match the names & prototypes of the functions in the class; look at
+ * the functions in the Midi class below that have the keyword "virtual" to see which
+ * ones you can use.
+ *
+ * Here's an example of one that takes NOTE ON, NOTE OFF, and CONTROL CHANGE:
+ *
+ * class MyMidi : public USBMidi {
+ * public:
+ *
+ * // Need this to compile; it just hands things off to the Midi class.
+ * MyMidi(HardwareSerial &s) : Midi(s) {}
+ *
+ * void handleNoteOn(unsigned int channel, unsigned int note, unsigned int velocity)
+ * {
+ * if (note == 40) {digitalWrite(13, HIGH); }
+ * }
+ *
+ * void handleNoteOff(unsigned int channel, unsigned int note, unsigned int velocity)
+ * {
+ * if (note == 40) { digitalWrite(13, LOW); }
+ * }
+ *
+ * void handleControlChange(unsigned int channel, unsigned int controller,
+ * unsigned int value)
+ * {
+ * analogWrite(6, value * 2);
+ * }
+ *
+ * Then you need to make an instance of this class:
+ *
+ * MyMidi midi();
+ *
+ * If receiving Midi data, you also need to call the poll function every time through
+ * loop(); e.g.
+ *
+ * void loop() {
+ * midi.poll();
+ * }
+ *
+ * This causes the Midi class to read data from the serial port and process it.
*/
-class USBMidi : public Print {
-public:
- USBMidi(void);
-
- void begin(void);
- void end(void);
+class USBMidi {
+private:
+ // The serial port used by this Midi instance (it takes complete control over the port)
+
+ /* Private Receive Parameters */
+
+ // The channel this Midi instance receives data for (0 means all channels)
+ int channelIn_;
+
+ // These are for keeping track of partial Midi messages as bytes come in
+ int recvMode_;
+ int recvByteCount_;
+ int recvEvent_;
+ int recvArg0_;
+ int recvBytesNeeded_;
+ int lastStatusSent_;
+
+ /* Private Send Parameters */
+
+ // This controls whether every Midi message gets a command byte sent with it
+ // (Midi can just send a single command byte and then stream events without
+ // sending the command each time)
+ bool sendFullCommands_;
+
+ /* Internal functions */
+
+ // Called whenever data is read from the serial port
+ void dispatchPacket(uint32 packet);
+
+ // This doesn't work -- by making it private, we ensure nobody ever calls it
+ //Midi();
+
+public:
+ // Set this parameter to anything other than 0 to cause every MIDI update to
+ // include a copy of the current event (e.g. for every note off to include
+ // the NOTE OFF event) -- by default, if an event is the same type of event as
+ // the last one sent, the event byte isn't sent; just the new note/velocity
+ static const unsigned int PARAM_SEND_FULL_COMMANDS = 0x1000;
+
+ // Use this parameter to update the channel the MIDI code is looking for messages
+ // to. 0 means "all channels".
+ static const unsigned int PARAM_CHANNEL_IN = 0x1001;
+
+
+ // Constructor -- generally just use e.g. "Midi midi(Serial);"
+ USBMidi();
+
+ // Call to start the serial port, at given baud. For many applications
+ // the default parameters are just fine (which will cause messages for all
+ // MIDI channels to be delivered)
+ void begin(unsigned int channel = 0);
+ //void begin();
+ void end();
+
uint32 available(void);
-
- uint32 read(void *buf, uint32 len);
- uint8 read(void);
-
- void write(uint8);
- void write(const char *str);
- void write(const void*, uint32);
-
+
+ uint32 readPackets(void *buf, uint32 len);
+ uint32 readPacket(void);
+
+ void writePacket(uint32);
+// void write(const char *str);
+ void writePackets(const void*, uint32);
+
uint8 isConnected();
uint8 pending();
+
+
+ // Changes the updateable parameters (params are Midi::PARAM_SEND_FULL_COMMANDS or
+ // Midi::PARAM_CHANNEL_IN -- see above for what they mean)
+ void setParam(unsigned int param, unsigned int val);
+
+ // Get current values for the user updateable parameters (params, etc same as above)
+ unsigned int getParam(unsigned int param);
+
+
+ // poll() should be called every time through loop() IF dealing with incoming MIDI
+ // (if you're only SENDING MIDI events from the Arduino, you don't need to call
+ // poll); it causes data to be read from the serial port and processed.
+ void poll();
+
+ // Call these to send MIDI messages of the given types
+ void sendNoteOff(unsigned int channel, unsigned int note, unsigned int velocity);
+ void sendNoteOn(unsigned int channel, unsigned int note, unsigned int velocity);
+ void sendVelocityChange(unsigned int channel, unsigned int note, unsigned int velocity);
+ void sendControlChange(unsigned int channel, unsigned int controller, unsigned int value);
+ void sendProgramChange(unsigned int channel, unsigned int program);
+ void sendAfterTouch(unsigned int channel, unsigned int velocity);
+ void sendPitchChange(unsigned int pitch);
+ void sendSongPosition(unsigned int position);
+ void sendSongSelect(unsigned int song);
+ void sendTuneRequest(void);
+ void sendSync(void);
+ void sendStart(void);
+ void sendContinue(void);
+ void sendStop(void);
+ void sendActiveSense(void);
+ void sendReset(void);
+
+ // Overload these in a subclass to get MIDI messages when they come in
+ virtual void handleNoteOff(unsigned int channel, unsigned int note, unsigned int velocity);
+ virtual void handleNoteOn(unsigned int channel, unsigned int note, unsigned int velocity);
+ virtual void handleVelocityChange(unsigned int channel, unsigned int note, unsigned int velocity);
+ virtual void handleControlChange(unsigned int channel, unsigned int controller, unsigned int value);
+ virtual void handleProgramChange(unsigned int channel, unsigned int program);
+ virtual void handleAfterTouch(unsigned int channel, unsigned int velocity);
+ virtual void handlePitchChange(unsigned int pitch);
+ virtual void handleSongPosition(unsigned int position);
+ virtual void handleSongSelect(unsigned int song);
+ virtual void handleTuneRequest(void);
+ virtual void handleSync(void);
+ virtual void handleStart(void);
+ virtual void handleContinue(void);
+ virtual void handleStop(void);
+ virtual void handleActiveSense(void);
+ virtual void handleReset(void);
};
+
+
#if BOARD_HAVE_MIDIUSB
extern USBMidi MidiUSB;
#endif
diff --git a/wirish/usb_midi.cpp b/wirish/usb_midi.cpp
index 54ce7a9..6926639 100644
--- a/wirish/usb_midi.cpp
+++ b/wirish/usb_midi.cpp
@@ -3,6 +3,7 @@
*
* Copyright (c) 2010 Perry Hung.
* Copyright (c) 2013 Magnus Lundin.
+ * Copyright (c) 2013 Donald Delmar Davis, Suspect Devices.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
@@ -23,6 +24,28 @@
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
+ *
+ * Midi.cpp: Code for MIDI processing library, Arduino version
+ *
+ * (c) 2003-2008 Tymm Twillman <tymm@booyaka.com>
+ *
+ * This file is part of Tymm's Arduino Midi Library.
+ *
+ * Tymm's Arduino Midi Library is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * Tymm's Arduino Midi Library is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Tymm's Arduino Midi Library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *
*****************************************************************************/
/**
@@ -33,7 +56,6 @@
#include <string.h>
#include <stdint.h>
-
#include <libmaple/nvic.h>
#include <libmaple/usb_midi_device.h>
#include <libmaple/usb.h>
@@ -52,9 +74,27 @@ USBMidi::USBMidi(void) {
#endif
}
-void USBMidi::begin(void) {
+// Constructor -- set up defaults for variables, get ready for use (but don't
+// take over serial port yet)
+
+void USBMidi::begin(unsigned int channel) {
#if BOARD_HAVE_MIDIUSB
usb_midi_enable(BOARD_USB_DISC_DEV, BOARD_USB_DISC_BIT);
+ /* Not in proprietary stream */
+ recvMode_ = 0;
+ /* No bytes recevied */
+ recvByteCount_ = 0;
+ /* Not processing an event */
+ recvEvent_ = 0;
+ /* No arguments to the event we haven't received */
+ recvArg0_ = 0;
+ /* Not waiting for bytes to complete a message */
+ recvBytesNeeded_ = 0;
+ // There was no last event.
+ lastStatusSent_ = false;
+ // Don't send the extra bytes; just send deltas
+ sendFullCommands_ = false;
+
#endif
}
@@ -64,15 +104,15 @@ void USBMidi::end(void) {
#endif
}
-void USBMidi::write(uint8 ch) {
- this->write(&ch, 1);
+void USBMidi::writePacket(uint32 p) {
+ this->writePackets(&p, 1);
}
-void USBMidi::write(const char *str) {
- this->write(str, strlen(str));
-}
+//void USBMidi::write(const char *str) {
+// this->write(str, strlen(str));
+//}
-void USBMidi::write(const void *buf, uint32 len) {
+void USBMidi::writePackets(const void *buf, uint32 len) {
if (!this->isConnected() || !buf) {
return;
}
@@ -105,7 +145,7 @@ uint32 USBMidi::available(void) {
return usb_midi_data_available();
}
-uint32 USBMidi::read(void *buf, uint32 len) {
+uint32 USBMidi::readPackets(void *buf, uint32 len) {
if (!buf) {
return 0;
}
@@ -119,10 +159,10 @@ uint32 USBMidi::read(void *buf, uint32 len) {
}
/* Blocks forever until 1 byte is received */
-uint8 USBMidi::read(void) {
- uint8 b;
- this->read(&b, 1);
- return b;
+uint32 USBMidi::readPacket(void) {
+ uint32 p;
+ this->readPackets(&p, 1);
+ return p;
}
uint8 USBMidi::pending(void) {
@@ -136,3 +176,377 @@ uint8 USBMidi::isConnected(void) {
#if BOARD_HAVE_MIDIUSB
USBMidi MidiUSB;
#endif
+
+
+// This is used for tracking when we're processing a proprietary stream of data
+// The assigned value is arbitrary; just for internal use.
+static const int MODE_PROPRIETARY = 0xff;
+
+
+// These are midi status message types as sent on the wire
+static const int STATUS_EVENT_NOTE_OFF = 0x80;
+static const int STATUS_EVENT_NOTE_ON = 0x90;
+static const int STATUS_EVENT_VELOCITY_CHANGE = 0xA0;
+static const int STATUS_EVENT_CONTROL_CHANGE = 0xB0;
+static const int STATUS_EVENT_PROGRAM_CHANGE = 0xC0;
+static const int STATUS_AFTER_TOUCH = 0xD0;
+static const int STATUS_PITCH_CHANGE = 0xE0;
+static const int STATUS_START_PROPRIETARY = 0xF0;
+static const int STATUS_SONG_POSITION = 0xF2;
+static const int STATUS_SONG_SELECT = 0xF3;
+static const int STATUS_TUNE_REQUEST = 0xF6;
+static const int STATUS_END_PROPRIETARY = 0xF7;
+static const int STATUS_SYNC = 0xF8;
+static const int STATUS_START = 0xFA;
+static const int STATUS_CONTINUE = 0xFB;
+static const int STATUS_STOP = 0xFC;
+static const int STATUS_ACTIVE_SENSE = 0xFE;
+static const int STATUS_RESET = 0xFF;
+
+union EVENT_t {
+ uint32 i;
+ uint8 b[4];
+ MIDI_EVENT_PACKET_t p;
+};
+
+// Handle decoding incoming MIDI traffic a byte at a time -- remembers
+// what it needs to from one call to the next.
+//
+// This is a private function & not meant to be called from outside this class.
+// It's used whenever data is available from the serial port.
+//
+void USBMidi::dispatchPacket(uint32 p)
+{
+ union EVENT_t e;
+
+ e.i=p;
+ // !!!!!!!!!!!!!!!! FIX THIS VERY VERY SHORTLY !!!!!!!!!!!!!!
+ if (recvMode_ & MODE_PROPRIETARY
+ && CIN_IS_SYSEX(e.p.cin))
+ {
+ /* If proprietary handling compiled in, just pass all data received
+ * after a START_PROPRIETARY event to proprietary_decode
+ * until get an END_PROPRIETARY event
+ */
+
+#ifdef CONFIG_MIDI_PROPRIETARY
+ proprietaryDecode(byte);
+#endif
+
+ return;
+ }
+
+ switch (e.p.cin) {
+ case CIN_3BYTE_SYS_COMMON:
+ if (e.p.midi0 == MIDIv1_SONG_POSITION_PTR) {
+ handleSongPosition(((uint16)e.p.midi2)<<7|((uint16)e.p.midi1));
+ }
+ break;
+
+ case CIN_2BYTE_SYS_COMMON:
+ switch (e.p.midi0) {
+ case MIDIv1_SONG_SELECT:
+ handleSongSelect(e.p.midi1);
+ break;
+ case MIDIv1_MTC_QUARTER_FRAME:
+ break;
+ }
+ break;
+ case CIN_NOTE_OFF:
+ handleNoteOff(MIDIv1_VOICE_CHANNEL(e.p.midi0), e.p.midi1, e.p.midi2);
+ break;
+ case CIN_NOTE_ON:
+ handleNoteOn(MIDIv1_VOICE_CHANNEL(e.p.midi0), e.p.midi1, e.p.midi2);
+ break;
+ case CIN_AFTER_TOUCH:
+ handleVelocityChange(MIDIv1_VOICE_CHANNEL(e.p.midi0), e.p.midi1, e.p.midi2);
+ break;
+ case CIN_CONTROL_CHANGE:
+ handleControlChange(MIDIv1_VOICE_CHANNEL(e.p.midi0), e.p.midi1, e.p.midi2);
+ break;
+ case CIN_PROGRAM_CHANGE:
+ handleProgramChange(MIDIv1_VOICE_CHANNEL(e.p.midi0), e.p.midi1);
+ break;
+ case CIN_CHANNEL_PRESSURE:
+ handleAfterTouch(MIDIv1_VOICE_CHANNEL(e.p.midi0), e.p.midi1);
+ break;
+
+ case CIN_PITCH_WHEEL:
+ handlePitchChange(((uint16)e.p.midi2)<<7|((uint16)e.p.midi1));
+ break;
+ case CIN_1BYTE:
+ switch (e.p.midi0) {
+ case MIDIv1_CLOCK:
+ handleSync();
+ break;
+ case MIDIv1_TICK:
+ break;
+ case MIDIv1_START:
+ handleStart();
+ break;
+ case MIDIv1_CONTINUE:
+ handleContinue();
+ break;
+ case MIDIv1_STOP:
+ handleStop();
+ break;
+ case MIDIv1_ACTIVE_SENSE:
+ handleActiveSense();
+ break;
+ case MIDIv1_RESET:
+ handleReset();
+ break;
+ case STATUS_TUNE_REQUEST:
+ handleTuneRequest();
+ break;
+
+ default:
+ break;
+ }
+ break;
+ }
+}
+
+
+// Try to read data at serial port & pass anything read to processing function
+void USBMidi::poll(void)
+{ while(available()) {
+ dispatchPacket(readPacket());
+ }
+}
+
+static union EVENT_t outPacket;
+
+// Send Midi NOTE OFF message to a given channel, with note 0-127 and velocity 0-127
+void USBMidi::sendNoteOff(unsigned int channel, unsigned int note, unsigned int velocity)
+{
+ outPacket.p.cable=DEFAULT_MIDI_CABLE;
+ outPacket.p.cin=CIN_NOTE_OFF;
+ outPacket.p.midi0=MIDIv1_NOTE_OFF|(channel & 0x0f);
+ outPacket.p.midi1=note;
+ outPacket.p.midi2=velocity;
+ writePacket(outPacket.i);
+
+}
+
+
+// Send Midi NOTE ON message to a given channel, with note 0-127 and velocity 0-127
+void USBMidi::sendNoteOn(unsigned int channel, unsigned int note, unsigned int velocity)
+{
+ outPacket.p.cable=DEFAULT_MIDI_CABLE;
+ outPacket.p.cin=CIN_NOTE_ON;
+ outPacket.p.midi0=MIDIv1_NOTE_ON|(channel & 0x0f);
+ outPacket.p.midi1=note;
+ outPacket.p.midi2=velocity;
+ writePacket(outPacket.i);
+
+}
+
+// Send a Midi VELOCITY CHANGE message to a given channel, with given note 0-127,
+// and new velocity 0-127
+// Note velocity change == polyphonic aftertouch.
+// Note aftertouch == channel pressure.
+void USBMidi::sendVelocityChange(unsigned int channel, unsigned int note, unsigned int velocity)
+{
+ outPacket.p.cable=DEFAULT_MIDI_CABLE;
+ outPacket.p.cin=CIN_AFTER_TOUCH;
+ outPacket.p.midi0=MIDIv1_AFTER_TOUCH |(channel & 0x0f);
+ outPacket.p.midi1=note;
+ outPacket.p.midi2=velocity;
+ writePacket(outPacket.i);
+
+}
+
+
+// Send a Midi CC message to a given channel, as a given controller 0-127, with given
+// value 0-127
+void USBMidi::sendControlChange(unsigned int channel, unsigned int controller, unsigned int value)
+{
+ outPacket.p.cable=DEFAULT_MIDI_CABLE;
+ outPacket.p.cin=CIN_CONTROL_CHANGE;
+ outPacket.p.midi0=MIDIv1_CONTROL_CHANGE |(channel & 0x0f);
+ outPacket.p.midi1=controller;
+ outPacket.p.midi2=value;
+ writePacket(outPacket.i);
+
+}
+
+// Send a Midi PROGRAM CHANGE message to given channel, with program ID 0-127
+void USBMidi::sendProgramChange(unsigned int channel, unsigned int program)
+{
+ outPacket.p.cable=DEFAULT_MIDI_CABLE;
+ outPacket.p.cin=CIN_PROGRAM_CHANGE;
+ outPacket.p.midi0=MIDIv1_PROGRAM_CHANGE |(channel & 0x0f);
+ outPacket.p.midi1=program;
+ writePacket(outPacket.i);
+
+}
+
+// Send a Midi AFTER TOUCH message to given channel, with velocity 0-127
+void USBMidi::sendAfterTouch(unsigned int channel, unsigned int velocity)
+{
+ outPacket.p.cable=DEFAULT_MIDI_CABLE;
+ outPacket.p.cin=CIN_CHANNEL_PRESSURE;
+ outPacket.p.midi0=MIDIv1_CHANNEL_PRESSURE |(channel & 0x0f);
+ outPacket.p.midi1=velocity;
+ writePacket(outPacket.i);
+
+}
+
+// Send a Midi PITCH CHANGE message, with a 14-bit pitch (always for all channels)
+void USBMidi::sendPitchChange(unsigned int pitch)
+{
+ outPacket.p.cable=DEFAULT_MIDI_CABLE;
+ outPacket.p.cin=CIN_PITCH_WHEEL;
+ outPacket.p.midi0=MIDIv1_PITCH_WHEEL;
+ outPacket.p.midi1= (uint8) pitch & 0x07F;
+ outPacket.p.midi2= (uint8) (pitch<<7) & 0x7f;
+ writePacket(outPacket.i);
+
+}
+
+// Send a Midi SONG POSITION message, with a 14-bit position (always for all channels)
+void USBMidi::sendSongPosition(unsigned int position)
+{
+ outPacket.p.cable=DEFAULT_MIDI_CABLE;
+ outPacket.p.cin=CIN_3BYTE_SYS_COMMON;
+ outPacket.p.midi0=MIDIv1_SONG_POSITION_PTR;
+ outPacket.p.midi1= (uint8) position & 0x07F;
+ outPacket.p.midi2= (uint8) (position<<7) & 0x7f;
+ writePacket(outPacket.i);
+
+}
+
+// Send a Midi SONG SELECT message, with a song ID of 0-127 (always for all channels)
+void USBMidi::sendSongSelect(unsigned int song)
+{
+ outPacket.p.cable=DEFAULT_MIDI_CABLE;
+ outPacket.p.cin=CIN_2BYTE_SYS_COMMON;
+ outPacket.p.midi0=MIDIv1_SONG_SELECT;
+ outPacket.p.midi1= (uint8) song & 0x07F;
+ writePacket(outPacket.i);
+
+}
+
+// Send a Midi TUNE REQUEST message (TUNE REQUEST is always for all channels)
+void USBMidi::sendTuneRequest(void)
+{
+ outPacket.p.cable=DEFAULT_MIDI_CABLE;
+ outPacket.p.cin=CIN_1BYTE;
+ outPacket.p.midi0=MIDIv1_TUNE_REQUEST;
+ writePacket(outPacket.i);
+}
+
+
+// Send a Midi SYNC message (SYNC is always for all channels)
+void USBMidi::sendSync(void)
+{
+ outPacket.p.cable=DEFAULT_MIDI_CABLE;
+ outPacket.p.cin=CIN_1BYTE;
+ outPacket.p.midi0=MIDIv1_CLOCK;
+ writePacket(outPacket.i);
+}
+
+// Send a Midi START message (START is always for all channels)
+void USBMidi::sendStart(void)
+{
+ outPacket.p.cable=DEFAULT_MIDI_CABLE;
+ outPacket.p.cin=CIN_1BYTE;
+ outPacket.p.midi0=MIDIv1_START ;
+ writePacket(outPacket.i);
+}
+
+
+// Send a Midi CONTINUE message (CONTINUE is always for all channels)
+void USBMidi::sendContinue(void)
+{
+ outPacket.p.cable=DEFAULT_MIDI_CABLE;
+ outPacket.p.cin=CIN_1BYTE;
+ outPacket.p.midi0=MIDIv1_CONTINUE ;
+ writePacket(outPacket.i);
+}
+
+
+// Send a Midi STOP message (STOP is always for all channels)
+void USBMidi::sendStop(void)
+{
+ outPacket.p.cable=DEFAULT_MIDI_CABLE;
+ outPacket.p.cin=CIN_1BYTE;
+ outPacket.p.midi0=MIDIv1_STOP ;
+ writePacket(outPacket.i);
+}
+
+// Send a Midi ACTIVE SENSE message (ACTIVE SENSE is always for all channels)
+void USBMidi::sendActiveSense(void)
+{
+ outPacket.p.cable=DEFAULT_MIDI_CABLE;
+ outPacket.p.cin=CIN_1BYTE;
+ outPacket.p.midi0=MIDIv1_ACTIVE_SENSE ;
+ writePacket(outPacket.i);
+}
+
+// Send a Midi RESET message (RESET is always for all channels)
+void USBMidi::sendReset(void)
+{
+ outPacket.p.cable=DEFAULT_MIDI_CABLE;
+ outPacket.p.cin=CIN_1BYTE;
+ outPacket.p.midi0=MIDIv1_RESET ;
+ writePacket(outPacket.i);
+}
+
+
+// Open the serial port and begin processing.
+//void Midi::begin(unsigned int channel, unsigned long baud)
+//{
+// channelIn_ = channel;
+// serial_.begin(baud);
+//}
+
+
+// Set (package-specific) parameters for the Midi instance
+void USBMidi::setParam(unsigned int param, unsigned int val)
+{
+ if (param == PARAM_SEND_FULL_COMMANDS) {
+ if (val) {
+ sendFullCommands_ = true;
+ } else {
+ sendFullCommands_ = false;
+ }
+ } else if (param == PARAM_CHANNEL_IN) {
+ channelIn_ = val;
+ }
+}
+
+
+// Get (package-specific) parameters for the Midi instance
+unsigned int USBMidi::getParam(unsigned int param)
+{
+ if (param == PARAM_SEND_FULL_COMMANDS) {
+ return sendFullCommands_;
+ } else if (param == PARAM_CHANNEL_IN) {
+ return channelIn_;
+ }
+
+ return 0;
+}
+
+
+// Placeholders. You should subclass the Midi base class and define these to have your
+// version called.
+void USBMidi::handleNoteOff(unsigned int channel, unsigned int note, unsigned int velocity) {}
+void USBMidi::handleNoteOn(unsigned int channel, unsigned int note, unsigned int velocity) {}
+void USBMidi::handleVelocityChange(unsigned int channel, unsigned int note, unsigned int velocity) {}
+void USBMidi::handleControlChange(unsigned int channel, unsigned int controller, unsigned int value) {}
+void USBMidi::handleProgramChange(unsigned int channel, unsigned int program) {}
+void USBMidi::handleAfterTouch(unsigned int channel, unsigned int velocity) {}
+void USBMidi::handlePitchChange(unsigned int pitch) {}
+void USBMidi::handleSongPosition(unsigned int position) {}
+void USBMidi::handleSongSelect(unsigned int song) {}
+void USBMidi::handleTuneRequest(void) {}
+void USBMidi::handleSync(void) {}
+void USBMidi::handleStart(void) {}
+void USBMidi::handleContinue(void) {}
+void USBMidi::handleStop(void) {}
+void USBMidi::handleActiveSense(void) {}
+void USBMidi::handleReset(void) {}
+