summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorPeter Teichman <peter@teichman.org>2011-12-04 13:24:26 -0500
committerPeter Teichman <peter@teichman.org>2011-12-04 13:24:26 -0500
commit31efb3527937e6a2402a4b0f49f09f27b1f1deed (patch)
tree5835fb7be7767363378a7420751067e1252c14ed /examples
Initial add of Timothy Twillman's Arduino Midi library 1.2.2
Diffstat (limited to 'examples')
-rw-r--r--examples/MidiPneumaticsExample/MidiPneumaticsExample.pde134
-rw-r--r--examples/MidiReceiveExample/MidiReceiveExample.pde98
-rw-r--r--examples/MidiSendExample/MidiSendExample.pde108
3 files changed, 340 insertions, 0 deletions
diff --git a/examples/MidiPneumaticsExample/MidiPneumaticsExample.pde b/examples/MidiPneumaticsExample/MidiPneumaticsExample.pde
new file mode 100644
index 0000000..33ff588
--- /dev/null
+++ b/examples/MidiPneumaticsExample/MidiPneumaticsExample.pde
@@ -0,0 +1,134 @@
+/*
+ * This sketch was for a project controlling pneumatics via Midi -- I used 4
+ * daisychained TPIC6B595 shift registers to control 32 pneumatic solenoids
+ * requiring 24v control signals. In my setup I used Garage Band as the
+ * sequencer (since it was already on my machine), with midiO plugin,
+ * sending Midi to Max/MSP, where I connected a Midi In object to a serial
+ * object that sent the data to my Arduino.
+ *
+ * A little complicated, but it worked reasonably well.
+ */
+
+#include "Midi.h"
+
+
+// Pins used to communicate with the TPIC6B595 shiftg registers
+#define D_PIN 2
+#define RCK_PIN 3
+#define SRCK_PIN 4
+#define SRCLR_PIN 5
+#define EN_PIN 6
+
+// Number of shift registers in the chain
+#define NUM_TPIC6B595 4
+
+
+// Subclassing Midi class to override the note handling functions
+class MyMidi : public Midi {
+ public:
+
+ MyMidi(HardwareSerial &s) : Midi(s) {}
+
+ void handleNoteOn(unsigned int channel, unsigned int note, unsigned int velocity)
+ {
+ // indicator bit to show note on received
+ digitalWrite(13, HIGH);
+
+ // set the pin corresponding to the note high (open the valve); the
+ // note & 31 bit is to limit the pin # from 0-31 since otherwise
+ // with a high note we could end up writing memory that's outside
+ // the array
+ tpic6b595_set((note & 31), HIGH);
+ tpic6b595_load();
+ }
+
+ void handleNoteOff(unsigned int channel, unsigned int note, unsigned int velocity)
+ {
+ // This is pretty much the same as handleNoteOn, except it turns things off
+ // instead of on.
+
+ digitalWrite(13, LOW);
+ tpic6b595_set((note & 31), LOW);
+ tpic6b595_load();
+ }
+};
+
+
+// Since the shift registers are read-only, need to keep a copy of the current
+// state of each output locally
+unsigned char tpic6b595_vals[NUM_TPIC6B595];
+
+// Create the actual instance of our Midi class; attach it to the standard
+// serial port.
+MyMidi midi(Serial);
+
+
+// Function for initializing the pins for communicating with the TPIC6B595's
+void tpic6b595_init()
+{
+
+ pinMode(D_PIN, OUTPUT);
+ pinMode(RCK_PIN, OUTPUT);
+ pinMode(SRCK_PIN, OUTPUT);
+ pinMode(SRCLR_PIN, OUTPUT);
+ pinMode(EN_PIN, OUTPUT);
+
+ digitalWrite(RCK_PIN, LOW);
+ digitalWrite(SRCK_PIN, LOW);
+ digitalWrite(SRCLR_PIN, LOW);
+ digitalWrite(SRCLR_PIN, HIGH);
+ digitalWrite(EN_PIN, LOW);
+}
+
+
+// Load the current state of the TPIC6B595 values into the shift registers &
+// latch the new values
+void tpic6b595_load()
+{
+ for (int i = 0; i < NUM_TPIC6B595; i++) {
+ shiftOut(D_PIN, SRCK_PIN, MSBFIRST, tpic6b595_vals[(NUM_TPIC6B595 - 1) - i]);
+ }
+
+ digitalWrite(RCK_PIN, HIGH);
+ delayMicroseconds(10);
+ digitalWrite(RCK_PIN, LOW);
+}
+
+
+// Get the state of any of the TPIC6B595 pins (first chip is considered to
+// be pins 0-7, chip 2 pins 8-15, etc.
+unsigned char tpic6b595_get(unsigned char pin)
+{
+ return (tpic6b595_vals[pin / 8] & _BV(pin & 7));
+}
+
+
+// Set the state of any of the TPIC6B595 pins (again, first chip is pins 0-7,
+// chip 2 pins 8-15, etc.
+void tpic6b595_set(unsigned char pin, unsigned char val)
+{
+ if (val) {
+ tpic6b595_vals[pin / 8] |= _BV(pin & 7);
+ } else {
+ tpic6b595_vals[pin / 8] &= ~_BV(pin & 7);
+ }
+}
+
+
+// Set pin 13 to output for some indication of data being received, initialize the
+// shift registers, start the Midi instance and turn off all shift register outputs
+void setup()
+{
+ pinMode(13, OUTPUT);
+ tpic6b595_init();
+ midi.begin(0, 115200);
+
+ tpic6b595_load();
+}
+
+
+// All we gotta do is process Midi data...
+void loop()
+{
+ midi.poll();
+}
diff --git a/examples/MidiReceiveExample/MidiReceiveExample.pde b/examples/MidiReceiveExample/MidiReceiveExample.pde
new file mode 100644
index 0000000..36a8c30
--- /dev/null
+++ b/examples/MidiReceiveExample/MidiReceiveExample.pde
@@ -0,0 +1,98 @@
+// This sketch turns on the LED at D13 when any "NOTE ON" message is received.
+// It turns the LED off when any "NOTE OFF" message is received.
+//
+// (note that NOTE ON's with velocity = 0 are actually NOTE OFF's, and are
+// treated as such)
+//
+// It's necessary to subclass Midi in order to handle receiving messages. If
+// you're only sending data, see MidiSendExample, which is a bit simpler.
+//
+// If you're both sending AND receiving you'll need to subclass like this,
+// but only for receive functions.
+//
+
+#include "Midi.h"
+
+// To use the Midi class for receiving Midi messages, you need to subclass it.
+// If you're a C++ person this makes sense; if not, just follow the example
+// functions below.
+//
+// Basically, MyMidi here can do anything Midi can do -- it just has the ability
+// to easily change what the functions do when different message types are received.
+//
+class MyMidi : public Midi {
+ 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)
+ {
+ digitalWrite(13, HIGH);
+ }
+
+ void handleNoteOff(unsigned int channel, unsigned int note, unsigned int velocity)
+ {
+ digitalWrite(13, LOW);
+ }
+
+ /* You can define any of these functions and they will be called when the
+ matching message type is received. Otherwise those types of Midi messages
+ are just ignored.
+
+ For C++ folks: these are all declared virtual in the base class
+
+ void handleNoteOff(unsigned int channel, unsigned int note, unsigned int velocity);
+ void handleNoteOn(unsigned int channel, unsigned int note, unsigned int velocity);
+ void handleVelocityChange(unsigned int channel, unsigned int note, unsigned int velocity);
+ void handleControlChange(unsigned int channel, unsigned int controller, unsigned int value);
+ void handleProgramChange(unsigned int channel, unsigned int program);
+ void handleAfterTouch(unsigned int channel, unsigned int velocity);
+ void handlePitchChange(unsigned int pitch);
+ void handleSongPosition(unsigned int position);
+ void handleSongSelect(unsigned int song);
+ void handleRuneRequest(void);
+ void handleSync(void);
+ void handleStart(void);
+ void handleContinue(void);
+ void handleStop(void);
+ void handleActiveSense(void);
+ void handleReset(void);
+*/
+};
+
+// Create an instance of the MyMidi class.
+MyMidi midi(Serial);
+
+
+void setup()
+{
+ pinMode(13, OUTPUT);
+
+ // This causes the midi object to listen to ALL Midi channels. If a number
+ // from 1-16 is passed, messages will be filtered so that any messages to
+ // channels other than the given one will be ignored.
+ //
+ // Note that you can pass a second parameter as a baud rate, if you're doing
+ // Midi protocol but using some other communication method (e.g. sending
+ // Midi data from Max/MSP using the standard Arduino USB connection, you
+ // can set the baud rate to something more standard and use the regular
+ // Max serial object)
+ midi.begin(0);
+}
+
+
+void loop()
+{
+ // Must be called every time through loop() IF dealing with incoming MIDI --
+ // if you're just sending MIDI out, you don't need to use poll().
+ //
+ // Make sure other code doesn't take too long to process or serial data
+ // can get backed up (and you can end up with obnoxious latency that ears
+ // don't like).
+ //
+ // The poll function will cause the midi code to suck data from the serial
+ // port and process it, and call any functions that are defined for handling
+ // midi messages.
+ midi.poll();
+}
diff --git a/examples/MidiSendExample/MidiSendExample.pde b/examples/MidiSendExample/MidiSendExample.pde
new file mode 100644
index 0000000..cc1eff9
--- /dev/null
+++ b/examples/MidiSendExample/MidiSendExample.pde
@@ -0,0 +1,108 @@
+// This sketch is for building a simple MIDI controller with 2 buttons for
+// sending note values & 2 knobs for control values
+//
+// To get this working, you should have set up the following hardware:
+// - a switch from Digital Pin 2 to +5v, and a 1 to 10K resistor from
+// pin 2 to ground
+// - a switch from Digital Pin 3 to +5v, and a 1 to 10K resistor from
+// pin 3 to ground
+// - a potentiometer with one side at +5v, one side at ground, and the
+// wiper (center pin) connected to Analog Pin 0
+// - a potentiometer with one side at +5v, one side at ground, and the
+// wiper (center pin) connected to Analog Pin 1
+//
+
+#include "Midi.h"
+
+// Create an instance of the Midi class.
+//
+// If we were had to receive messages, you'd have to make a subclass of the
+// Midi class. See the MidiReceiveExample for an example of how to do that.
+//
+// Sending is a lot easier :)
+Midi midi(Serial);
+
+
+void setup()
+{
+ // Configure digital pins for input.
+ pinMode(2, INPUT);
+ pinMode(3, INPUT);
+
+ // This causes the midi object to listen to ALL Midi channels. If a number
+ // from 1-16 is passed, messages will be filtered so that any messages to
+ // channels other than the given one will be ignored.
+ midi.begin(0);
+}
+
+int lastDigital2 = LOW;
+int lastDigital3 = LOW;
+
+int lastAnalog0 = 0;
+int lastAnalog1 = 0;
+
+// MIDI channel to send messages to
+int channelOut = 1;
+
+
+void doControls()
+{
+ int a;
+
+
+ // Changes on analog lines cause control change events
+ // to be sent; these are parameters from 0-127
+
+ a = analogRead(0) / 8 ;
+ if (a != lastAnalog0) {
+ midi.sendControlChange(channelOut, 15, a);
+ lastAnalog0 = a;
+ }
+
+ a = analogRead(1) / 8;
+ if (a != lastAnalog1) {
+ midi.sendControlChange(channelOut, 16, a);
+ lastAnalog1 = a;
+ }
+}
+
+
+void doKeys()
+{
+ int d;
+
+
+ // Basic code to check pins 2-5; if there's a change on the pin, send
+ // a NOTE ON or NOTE OFF, depending on whether the button was pressed
+ // or released, with a different note value for each button. The velocity
+ // for all of the NOTE ON messages is the max (127)
+
+ d = digitalRead(2);
+ if (d != lastDigital2) {
+ if (d == HIGH) {
+ midi.sendNoteOn(channelOut, 40, 127);
+ } else {
+ midi.sendNoteOff(channelOut, 40, 0);
+ }
+ lastDigital2 = d;
+ }
+
+ d = digitalRead(3);
+ if (d != lastDigital3) {
+ if (d == HIGH) {
+ midi.sendNoteOn(channelOut, 41, 127);
+ } else {
+ midi.sendNoteOff(channelOut, 41, 0);
+ }
+ lastDigital3 = d;
+ }
+}
+
+
+void loop()
+{
+ // DON'T need to call midi.poll(), because this sketch doesn't need to
+ // receive any Midi data.
+ doKeys();
+ doControls();
+}