diff options
| author | Peter Teichman <peter@teichman.org> | 2011-12-04 13:24:26 -0500 |
|---|---|---|
| committer | Peter Teichman <peter@teichman.org> | 2011-12-04 13:24:26 -0500 |
| commit | 31efb3527937e6a2402a4b0f49f09f27b1f1deed (patch) | |
| tree | 5835fb7be7767363378a7420751067e1252c14ed /examples | |
Initial add of Timothy Twillman's Arduino Midi library 1.2.2
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/MidiPneumaticsExample/MidiPneumaticsExample.pde | 134 | ||||
| -rw-r--r-- | examples/MidiReceiveExample/MidiReceiveExample.pde | 98 | ||||
| -rw-r--r-- | examples/MidiSendExample/MidiSendExample.pde | 108 |
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(); +} |
