Merge branch 'master' into feature/usb
This commit is contained in:
commit
dd5b39a686
|
|
@ -1,2 +1,4 @@
|
||||||
*.sublime-workspace
|
*.sublime-workspace
|
||||||
*.pyc
|
*.pyc
|
||||||
|
logs/
|
||||||
|
build/
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
#Arduino MIDI Library v4.0
|
#Arduino MIDI Library v4.1
|
||||||
|
|
||||||
This library enables MIDI I/O communications on the Arduino serial ports.
|
This library enables MIDI I/O communications on the Arduino serial ports.
|
||||||
The purpose of this library is not to make a big synthetizer out of an Arduino board, the application remains yours. However, it will help you interfacing it with other MIDI devices.
|
The purpose of this library is not to make a big synthetizer out of an Arduino board, the application remains yours. However, it will help you interfacing it with other MIDI devices.
|
||||||
|
|
||||||
Download the latest version [here](https://github.com/FortySevenEffects/arduino_midi_library/releases/download/4.0/Arduino_MIDI_Library_v4.0.zip).
|
Download the latest version [here](https://github.com/FortySevenEffects/arduino_midi_library/releases/download/4.1/Arduino_MIDI_Library_v4.1.zip).
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
* Compatible with all Arduino boards (and clones with an AVR processor)
|
* Compatible with all Arduino boards (and clones with an AVR processor)
|
||||||
|
|
@ -18,6 +18,7 @@ Download the latest version [here](https://github.com/FortySevenEffects/arduino_
|
||||||
|
|
||||||
|
|
||||||
#### Changelog
|
#### Changelog
|
||||||
|
* 16/04/2014 : Version 4.1 released. Bug fixes regarding running status.
|
||||||
* 13/02/2014 : Version 4.0 released. Moved to GitHub, added multiple instances & software serial support, and a few bug fixes.
|
* 13/02/2014 : Version 4.0 released. Moved to GitHub, added multiple instances & software serial support, and a few bug fixes.
|
||||||
* 29/01/2012 : Version 3.2 released. Release notes are [here](http://sourceforge.net/news/?group_id=265194)
|
* 29/01/2012 : Version 3.2 released. Release notes are [here](http://sourceforge.net/news/?group_id=265194)
|
||||||
* 06/05/2011 : Version 3.1 released. Added [callback](http://playground.arduino.cc/Main/MIDILibraryCallbacks) support.
|
* 06/05/2011 : Version 3.1 released. Added [callback](http://playground.arduino.cc/Main/MIDILibraryCallbacks) support.
|
||||||
|
|
@ -34,7 +35,7 @@ Download the latest version [here](https://github.com/FortySevenEffects/arduino_
|
||||||
|
|
||||||
### What do I need to do?
|
### What do I need to do?
|
||||||
|
|
||||||
* Download the library ([link](https://github.com/FortySevenEffects/arduino_midi_library/releases/download/4.0/Arduino_MIDI_Library_v4.0.zip))
|
* Download the library ([link](https://github.com/FortySevenEffects/arduino_midi_library/releases/download/4.1/Arduino_MIDI_Library_v4.1.zip))
|
||||||
* Follow the installation instructions there: http://arduino.cc/en/Guide/Libraries
|
* Follow the installation instructions there: http://arduino.cc/en/Guide/Libraries
|
||||||
* Include the library in your sketch using the menu in the IDE, or type `#include <MIDI.h>`
|
* Include the library in your sketch using the menu in the IDE, or type `#include <MIDI.h>`
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
!!MIDI Library v4.0
|
!!MIDI Library v4.1
|
||||||
|
|
||||||
This library enables MIDI I/O communications on the Arduino serial ports. You can send and receive messages of all kinds (including System Exclusive, RealTime etc..). The purpose of this library is not to make a big synthetizer out of an Arduino board, the application remains yours. However, it will help you interfacing it with other MIDI devices.
|
This library enables MIDI I/O communications on the Arduino serial ports. You can send and receive messages of all kinds (including System Exclusive, RealTime etc..). The purpose of this library is not to make a big synthetizer out of an Arduino board, the application remains yours. However, it will help you interfacing it with other MIDI devices.
|
||||||
|
|
||||||
Download the latest version [[ https://github.com/FortySevenEffects/arduino_midi_library/releases/download/4.0/Arduino_MIDI_Library_v4.0.zip | here ]].
|
Download the latest version [[ https://github.com/FortySevenEffects/arduino_midi_library/releases/download/4.1/Arduino_MIDI_Library_v4.1.zip | here ]].
|
||||||
|
|
||||||
You can now follow the developments on [[ http://github.com/FortySevenEffects/arduino_midi_library/ | GitHub]].
|
You can now follow the developments on [[ http://github.com/FortySevenEffects/arduino_midi_library/ | GitHub]].
|
||||||
|
|
||||||
|
|
@ -20,6 +20,7 @@ You can now follow the developments on [[ http://github.com/FortySevenEffects/ar
|
||||||
|
|
||||||
|
|
||||||
!!!!Changelog:
|
!!!!Changelog:
|
||||||
|
* 16/04/2014 : Version 4.1 released. Bug fixes regarding running status.
|
||||||
* 13/02/2014 : Version 4.0 released. Moved to GitHub, added multiple instances & software serial support, and a few bug fixes.
|
* 13/02/2014 : Version 4.0 released. Moved to GitHub, added multiple instances & software serial support, and a few bug fixes.
|
||||||
* 29/01/2012 : Version 3.2 released. Release notes are [[ http://sourceforge.net/news/?group_id=265194 | here ]]
|
* 29/01/2012 : Version 3.2 released. Release notes are [[ http://sourceforge.net/news/?group_id=265194 | here ]]
|
||||||
* 06/05/2011 : Version 3.1 released. Added [[ http://playground.arduino.cc/Main/MIDILibraryCallbacks | callback]] support.
|
* 06/05/2011 : Version 3.1 released. Added [[ http://playground.arduino.cc/Main/MIDILibraryCallbacks | callback]] support.
|
||||||
|
|
@ -34,7 +35,7 @@ You can now follow the developments on [[ http://github.com/FortySevenEffects/ar
|
||||||
|
|
||||||
!!!What do I need to do?
|
!!!What do I need to do?
|
||||||
|
|
||||||
* Download the library ([[ https://github.com/FortySevenEffects/arduino_midi_library/releases/download/4.0/Arduino_MIDI_Library_v4.0.zip | link ]])
|
* Download the library ([[ https://github.com/FortySevenEffects/arduino_midi_library/releases/download/4.1/Arduino_MIDI_Library_v4.1.zip | link ]])
|
||||||
* Follow the installation instructions there: http://arduino.cc/en/Guide/Libraries
|
* Follow the installation instructions there: http://arduino.cc/en/Guide/Libraries
|
||||||
* Include the library in your sketch using the menu in the IDE, or type [@#include <MIDI.h>@]
|
* Include the library in your sketch using the menu in the IDE, or type [@#include <MIDI.h>@]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,17 @@
|
||||||
"folders":
|
"folders":
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"path": "."
|
"path": ".",
|
||||||
|
"folder_exclude_patterns": [".*", "__pycache__"],
|
||||||
|
"file_exclude_patterns": [".*"]
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"build_systems":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "Arduino MIDI Library Validator",
|
||||||
|
"cmd": ["python3", "${project_path}/res/validate.py"],
|
||||||
|
"path": "/usr/local/bin:/usr/bin:/bin"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,23 @@
|
||||||
#include <SoftwareSerial.h>
|
|
||||||
#define MIDI_AUTO_INSTANCIATE 0
|
|
||||||
#include <MIDI.h>
|
#include <MIDI.h>
|
||||||
|
|
||||||
// This program demonstrates how to use two serial ports at a time,
|
// This program will measure the time needed to receive, parse and process a
|
||||||
// the hardware serial being used for sending messages to the computer,
|
// NoteOn message.
|
||||||
// while MIDI is handled on a software serial port.
|
// For it to work, please connect RX and TX on the MIDI port:
|
||||||
// This program measures the time spent to receive and parse a message.
|
// Due, Leonardo and other USB-native Arduinos: Serial1
|
||||||
|
// All other Arduinos: Connect pins 2 and 3.
|
||||||
|
// The program will then wait for 100 loops and print the results.
|
||||||
|
|
||||||
|
#if defined(ARDUINO_SAM_DUE) || defined(USBCON)
|
||||||
|
// Print through USB and bench with Hardware serial
|
||||||
|
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, midiBench);
|
||||||
|
#else
|
||||||
|
#include <SoftwareSerial.h>
|
||||||
|
SoftwareSerial midiSerial(2,3);
|
||||||
|
MIDI_CREATE_INSTANCE(SoftwareSerial, midiSerial, midiBench);
|
||||||
|
#endif
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
SoftwareSerial midiSerial(2,3);
|
|
||||||
MIDI_CREATE_INSTANCE(SoftwareSerial, midiSerial, softMidi);
|
|
||||||
|
|
||||||
unsigned long gTime_start = 0;
|
unsigned long gTime_start = 0;
|
||||||
unsigned long gTime_stop = 0;
|
unsigned long gTime_stop = 0;
|
||||||
unsigned gCounter = 0;
|
unsigned gCounter = 0;
|
||||||
|
|
@ -24,39 +30,37 @@ unsigned long gTime_max = 0;
|
||||||
void handleNoteOn(byte inChannel, byte inNote, byte inVelocity)
|
void handleNoteOn(byte inChannel, byte inNote, byte inVelocity)
|
||||||
{
|
{
|
||||||
gTime_stop = micros();
|
gTime_stop = micros();
|
||||||
|
|
||||||
const unsigned long diff = gTime_stop - gTime_start;
|
const unsigned long diff = gTime_stop - gTime_start;
|
||||||
gTime_sum += diff;
|
gTime_sum += diff;
|
||||||
|
|
||||||
if (diff > gTime_max) gTime_max = diff;
|
if (diff > gTime_max) gTime_max = diff;
|
||||||
if (diff < gTime_min) gTime_min = diff;
|
if (diff < gTime_min) gTime_min = diff;
|
||||||
|
|
||||||
gCounter++;
|
if (gCounter++ >= 1000)
|
||||||
|
|
||||||
if (gCounter >= 100)
|
|
||||||
{
|
{
|
||||||
const unsigned long average = gTime_sum / (float)gCounter;
|
const unsigned long average = gTime_sum / (float)gCounter;
|
||||||
|
|
||||||
Serial.println("Time to receive NoteOn: ");
|
Serial.println("Time to receive NoteOn: ");
|
||||||
|
|
||||||
Serial.print("Average: ");
|
Serial.print("Average: ");
|
||||||
Serial.print(average);
|
Serial.print(average);
|
||||||
Serial.println(" microsecs");
|
Serial.println(" microsecs");
|
||||||
|
|
||||||
Serial.print("Min: ");
|
Serial.print("Min: ");
|
||||||
Serial.print(gTime_min);
|
Serial.print(gTime_min);
|
||||||
Serial.println(" microsecs");
|
Serial.println(" microsecs");
|
||||||
|
|
||||||
Serial.print("Max: ");
|
Serial.print("Max: ");
|
||||||
Serial.print(gTime_max);
|
Serial.print(gTime_max);
|
||||||
Serial.println(" microsecs");
|
Serial.println(" microsecs");
|
||||||
|
|
||||||
gCounter = 0;
|
gCounter = 0;
|
||||||
gTime_sum = 0;
|
gTime_sum = 0;
|
||||||
gTime_max = 0;
|
gTime_max = 0;
|
||||||
gTime_min = -1;
|
gTime_min = -1;
|
||||||
|
|
||||||
softMidi.turnThruOff();
|
midiBench.turnThruOff();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -64,18 +68,18 @@ void handleNoteOn(byte inChannel, byte inNote, byte inVelocity)
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
softMidi.begin();
|
midiBench.setHandleNoteOn(handleNoteOn);
|
||||||
|
midiBench.begin();
|
||||||
Serial.begin(38400);
|
|
||||||
Serial.print("Arduino Ready");
|
|
||||||
|
|
||||||
softMidi.sendNoteOn(69,127,1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
while(!Serial);
|
||||||
|
Serial.begin(115200);
|
||||||
|
Serial.println("Arduino Ready");
|
||||||
|
|
||||||
|
midiBench.sendNoteOn(69,127,1);
|
||||||
|
}
|
||||||
|
|
||||||
void loop()
|
void loop()
|
||||||
{
|
{
|
||||||
gTime_start = micros();
|
gTime_start = micros();
|
||||||
softMidi.read();
|
midiBench.read();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,20 +2,22 @@
|
||||||
|
|
||||||
// This function will be automatically called when a NoteOn is received.
|
// This function will be automatically called when a NoteOn is received.
|
||||||
// It must be a void-returning function with the correct parameters,
|
// It must be a void-returning function with the correct parameters,
|
||||||
// see documentation here:
|
// see documentation here:
|
||||||
// http://arduinomidilib.sourceforge.net/class_m_i_d_i___class.html
|
// http://arduinomidilib.fortyseveneffects.com/a00022.html
|
||||||
|
|
||||||
void HandleNoteOn(byte channel, byte pitch, byte velocity)
|
void HandleNoteOn(byte channel, byte pitch, byte velocity)
|
||||||
{
|
{
|
||||||
// Do whatever you want when you receive a Note On.
|
// Do whatever you want when you receive a Note On.
|
||||||
|
|
||||||
if (velocity == 0)
|
if (velocity == 0)
|
||||||
{
|
{
|
||||||
// This acts like a NoteOff.
|
// This acts like a NoteOff. You can ask the library to call the NoteOff
|
||||||
|
// callback when receiving null-velocity NoteOn messages.
|
||||||
|
// See MIDI_HANDLE_NULL_VELOCITY_NOTE_ON_AS_NOTE_OFF in midi_Settings.h
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to keep your callbacks short (no delays ect)
|
// Try to keep your callbacks short (no delays ect)
|
||||||
// otherwise it would slow down the loop() and have a bad impact
|
// otherwise it would slow down the loop() and have a bad impact
|
||||||
// on real-time performance.
|
// on real-time performance.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -23,22 +25,21 @@ void HandleNoteOn(byte channel, byte pitch, byte velocity)
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
// Initiate MIDI communications, listen to all channels
|
// Connect the HandleNoteOn function to the library,
|
||||||
MIDI.begin(MIDI_CHANNEL_OMNI);
|
|
||||||
|
|
||||||
// Connect the HandleNoteOn function to the library,
|
|
||||||
// so it is called upon reception of a NoteOn.
|
// so it is called upon reception of a NoteOn.
|
||||||
MIDI.setHandleNoteOn(HandleNoteOn); // Put only the name of the function
|
MIDI.setHandleNoteOn(HandleNoteOn); // Put only the name of the function
|
||||||
}
|
|
||||||
|
|
||||||
|
// Initiate MIDI communications, listen to all channels
|
||||||
|
MIDI.begin(MIDI_CHANNEL_OMNI);
|
||||||
|
}
|
||||||
|
|
||||||
void loop()
|
void loop()
|
||||||
{
|
{
|
||||||
// Call MIDI.read the fastest you can for real-time performance.
|
// Call MIDI.read the fastest you can for real-time performance.
|
||||||
MIDI.read();
|
MIDI.read();
|
||||||
|
|
||||||
// There is no need to check if there are messages incoming
|
// There is no need to check if there are messages incoming
|
||||||
// if they are bound to a Callback function.
|
// if they are bound to a Callback function.
|
||||||
// The attached method will be called automatically
|
// The attached method will be called automatically
|
||||||
// when the corresponding message has been received.
|
// when the corresponding message has been received.
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
#include <SoftwareSerial.h>
|
|
||||||
#include <MIDI.h>
|
#include <MIDI.h>
|
||||||
|
|
||||||
// This example shows how to create two instances of the library to create a merger.
|
// This example shows how to create two instances of the library to create a merger.
|
||||||
|
|
@ -7,10 +6,15 @@
|
||||||
// A out = A in + B in
|
// A out = A in + B in
|
||||||
// B out = B in + A in
|
// B out = B in + A in
|
||||||
|
|
||||||
SoftwareSerial softSerial(2,3);
|
#ifdef ARDUINO_SAM_DUE
|
||||||
|
MIDI_CREATE_INSTANCE(HardwareSerial, Serial, midiA);
|
||||||
MIDI_CREATE_INSTANCE(HardwareSerial, Serial, midiA);
|
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, midiB);
|
||||||
MIDI_CREATE_INSTANCE(SoftwareSerial, softSerial, midiB);
|
#else
|
||||||
|
#include <SoftwareSerial.h>
|
||||||
|
SoftwareSerial softSerial(2,3);
|
||||||
|
MIDI_CREATE_INSTANCE(HardwareSerial, Serial, midiA);
|
||||||
|
MIDI_CREATE_INSTANCE(SoftwareSerial, softSerial, midiB);
|
||||||
|
#endif
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
|
|
@ -30,7 +34,7 @@ void loop()
|
||||||
midiA.getData2(),
|
midiA.getData2(),
|
||||||
midiA.getChannel());
|
midiA.getChannel());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (midiB.read())
|
if (midiB.read())
|
||||||
{
|
{
|
||||||
// Thru on B has already pushed the input message to out B.
|
// Thru on B has already pushed the input message to out B.
|
||||||
|
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
|
|
||||||
#include <SoftwareSerial.h>
|
|
||||||
#include <MIDI.h>
|
|
||||||
#include <LiquidCrystal.h>
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include "midi_ValidatorSerialDebug.h"
|
|
||||||
#include "midi_ValidatorLCD.h"
|
|
||||||
#include "midi_ValidatorLEDs.h"
|
|
||||||
#include "midi_ValidatorInstances.h"
|
|
||||||
#include "midi_ValidatorTester.h"
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
setupSerialDebug();
|
|
||||||
setupLCD();
|
|
||||||
setupLEDs();
|
|
||||||
setupTesters();
|
|
||||||
Serial.println("Tester ready");
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void loop()
|
|
||||||
{
|
|
||||||
if (launchTests() == true)
|
|
||||||
{
|
|
||||||
setLedsFinal(true);
|
|
||||||
Serial.println("All tests passed.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
setLedsFinal(false);
|
|
||||||
Serial.println("Some tests failed!");
|
|
||||||
}
|
|
||||||
while (true);
|
|
||||||
}
|
|
||||||
Binary file not shown.
|
|
@ -1,10 +0,0 @@
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <SoftwareSerial.h>
|
|
||||||
#include <MIDI.h>
|
|
||||||
|
|
||||||
extern midi::MidiInterface<HardwareSerial> midiHW;
|
|
||||||
extern midi::MidiInterface<SoftwareSerial> midiSW;
|
|
||||||
|
|
||||||
void setupMidi();
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
#include <Arduino.h>
|
|
||||||
#include "midi_ValidatorInstances.h"
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
SoftwareSerial softSerial(10, 11);
|
|
||||||
|
|
||||||
#if defined(__AVR_ATmega32U4__) // Leonardo uses Serial1 as hardware serial.
|
|
||||||
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, midiHW);
|
|
||||||
MIDI_CREATE_INSTANCE(SoftwareSerial, softSerial, midiSW);
|
|
||||||
#else
|
|
||||||
MIDI_CREATE_INSTANCE(HardwareSerial, Serial, midiHW);
|
|
||||||
MIDI_CREATE_INSTANCE(SoftwareSerial, softSerial, midiSW);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void setupMidi()
|
|
||||||
{
|
|
||||||
while (!softSerial.isListening())
|
|
||||||
softSerial.listen();
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <LiquidCrystal.h>
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
extern LiquidCrystal lcd;
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void setupLCD();
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void setProgressBar(unsigned inProgress, unsigned inTotal);
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
#include <Arduino.h>
|
|
||||||
#include "midi_ValidatorLCD.h"
|
|
||||||
|
|
||||||
#define LCD_D4 8
|
|
||||||
#define LCD_D5 9
|
|
||||||
#define LCD_D6 10
|
|
||||||
#define LCD_D7 11
|
|
||||||
#define LCD_RS 12
|
|
||||||
#define LCD_EN 13
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
byte progressChar[6][8] =
|
|
||||||
{
|
|
||||||
{ B00000, B00000, B00000, B00000, B00000, B00000, B00000, B00000 },
|
|
||||||
{ B10000, B10000, B10000, B10000, B10000, B10000, B10000, B10000 },
|
|
||||||
{ B11000, B11000, B11000, B11000, B11000, B11000, B11000, B11000 },
|
|
||||||
{ B11100, B11100, B11100, B11100, B11100, B11100, B11100, B11100 },
|
|
||||||
{ B11110, B11110, B11110, B11110, B11110, B11110, B11110, B11110 },
|
|
||||||
{ B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111 },
|
|
||||||
};
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
LiquidCrystal lcd(LCD_RS, LCD_EN, LCD_D4, LCD_D5, LCD_D6, LCD_D7);
|
|
||||||
|
|
||||||
void setupLCD()
|
|
||||||
{
|
|
||||||
for (byte i = 0; i < 6; ++i)
|
|
||||||
lcd.createChar(i, progressChar[i]);
|
|
||||||
|
|
||||||
lcd.begin(16,2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void setProgressBar(unsigned inProgress, unsigned inTotal)
|
|
||||||
{
|
|
||||||
const byte numCols = 16;
|
|
||||||
const byte numPix = 5;
|
|
||||||
const unsigned progress = (inProgress * numCols* numPix) / inTotal;
|
|
||||||
const byte cursorX = progress / numPix;
|
|
||||||
const byte charIndex = progress % numPix;
|
|
||||||
|
|
||||||
lcd.setCursor(cursorX, 1);
|
|
||||||
lcd.write(charIndex);
|
|
||||||
}
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#define LED_PASS 4
|
|
||||||
#define LED_FAIL 5
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void setupLEDs();
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
inline void blinkLed(byte inLedNum)
|
|
||||||
{
|
|
||||||
digitalWrite(inLedNum, HIGH);
|
|
||||||
delay(100);
|
|
||||||
digitalWrite(inLedNum, LOW);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void blinkPass()
|
|
||||||
{
|
|
||||||
blinkLed(LED_PASS);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void blinkFail()
|
|
||||||
{
|
|
||||||
blinkLed(LED_FAIL);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void setLedsFinal(bool inSuccess)
|
|
||||||
{
|
|
||||||
if (inSuccess)
|
|
||||||
{
|
|
||||||
digitalWrite(LED_PASS, HIGH);
|
|
||||||
digitalWrite(LED_FAIL, LOW);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
digitalWrite(LED_FAIL, HIGH);
|
|
||||||
digitalWrite(LED_PASS, LOW);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
#include <Arduino.h>
|
|
||||||
#include "midi_ValidatorLEDs.h"
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void setupLEDs()
|
|
||||||
{
|
|
||||||
pinMode(LED_PASS, OUTPUT);
|
|
||||||
pinMode(LED_FAIL, OUTPUT);
|
|
||||||
}
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
void setupSerialDebug();
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
#include <Arduino.h>
|
|
||||||
#include "midi_ValidatorSerialDebug.h"
|
|
||||||
|
|
||||||
void setupSerialDebug()
|
|
||||||
{
|
|
||||||
Serial.begin(9600);
|
|
||||||
while (!Serial)
|
|
||||||
{
|
|
||||||
; // wait for serial port to connect. Needed for Leonardo only
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
void setupTesters();
|
|
||||||
bool launchTests();
|
|
||||||
|
|
@ -1,109 +0,0 @@
|
||||||
#include <Arduino.h>
|
|
||||||
#include "midi_ValidatorTester.h"
|
|
||||||
#include "midi_ValidatorInstances.h"
|
|
||||||
#include "midi_ValidatorTests.h"
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<class SerialClass>
|
|
||||||
class Tester
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef bool (*Functor) (MIDI_CLASS(SerialClass)&);
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit Tester(MIDI_CLASS(SerialClass)& inInstance)
|
|
||||||
: mMidiInstance(inInstance)
|
|
||||||
, mProgress(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
mProgress = 0;
|
|
||||||
mMidiInstance.begin(MIDI_CHANNEL_OMNI);
|
|
||||||
mMidiInstance.turnThruOff();
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
inline bool performTest(Functor inTestMethod)
|
|
||||||
{
|
|
||||||
if (inTestMethod != 0)
|
|
||||||
{
|
|
||||||
const bool result = expect((*inTestMethod)(mMidiInstance));
|
|
||||||
setProgressBar(++mProgress, NUM_TESTS);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool expect(bool inCondition) const
|
|
||||||
{
|
|
||||||
Serial.print(testNames[mProgress]);
|
|
||||||
Serial.print(": ");
|
|
||||||
if (inCondition == false)
|
|
||||||
{
|
|
||||||
Serial.println("Failed /!\\");
|
|
||||||
blinkFail();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Serial.println("Passed");
|
|
||||||
blinkPass();
|
|
||||||
}
|
|
||||||
return inCondition;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool run()
|
|
||||||
{
|
|
||||||
bool result = true;
|
|
||||||
result &= performTest(testNoteOn);
|
|
||||||
result &= performTest(testNoteOff);
|
|
||||||
result &= performTest(testControlChange);
|
|
||||||
result &= performTest(testProgramChange);
|
|
||||||
result &= performTest(testAftertouchMono);
|
|
||||||
result &= performTest(testAftertouchPoly);
|
|
||||||
result &= performTest(testPitchBend);
|
|
||||||
result &= performTest(testSysEx);
|
|
||||||
result &= performTest(testClock);
|
|
||||||
result &= performTest(testStart);
|
|
||||||
result &= performTest(testStop);
|
|
||||||
result &= performTest(testContinue);
|
|
||||||
result &= performTest(testActiveSensing);
|
|
||||||
result &= performTest(testTimeCode);
|
|
||||||
result &= performTest(testSongSelect);
|
|
||||||
result &= performTest(testSongPosition);
|
|
||||||
result &= performTest(testTuneRequest);
|
|
||||||
result &= performTest(testSystemReset);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
MIDI_CLASS(SerialClass)& mMidiInstance;
|
|
||||||
unsigned mProgress;
|
|
||||||
};
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Tester<HardwareSerial> testerHW(midiHW);
|
|
||||||
Tester<SoftwareSerial> testerSW(midiSW);
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void setupTesters()
|
|
||||||
{
|
|
||||||
testerHW.setup();
|
|
||||||
testerSW.setup();
|
|
||||||
setupMidi();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool launchTests()
|
|
||||||
{
|
|
||||||
Serial.println("Testing HW:");
|
|
||||||
if (testerHW.run() == false)
|
|
||||||
return false;
|
|
||||||
Serial.println("Testing SW:");
|
|
||||||
if (testerSW.run() == false)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#define NUM_TESTS 18
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#define DECLARE_MIDI_TEST(Name) \
|
|
||||||
template<class SerialClass> \
|
|
||||||
bool Name(MIDI_CLASS(SerialClass)& inMidi)
|
|
||||||
|
|
||||||
#define IMPLEMENT_MIDI_TEST(Name, Instance) \
|
|
||||||
template<class SerialClass> \
|
|
||||||
bool Name(MIDI_CLASS(SerialClass)& Instance)
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
static const char * testNames[] =
|
|
||||||
{
|
|
||||||
// 0123456789ABCDEF
|
|
||||||
"NoteOn ",
|
|
||||||
"NoteOff ",
|
|
||||||
"ControlChange ",
|
|
||||||
"ProgramChange ",
|
|
||||||
"AftertouchMono ",
|
|
||||||
"AftertouchPoly ",
|
|
||||||
"PitchBend ",
|
|
||||||
"SysEx ",
|
|
||||||
"Clock ",
|
|
||||||
"Start ",
|
|
||||||
"Stop ",
|
|
||||||
"Continue ",
|
|
||||||
"ActiveSensing ",
|
|
||||||
"TimeCode ",
|
|
||||||
"SongSelect ",
|
|
||||||
"SongPosition ",
|
|
||||||
"TuneRequest ",
|
|
||||||
"SystemReset ",
|
|
||||||
};
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
DECLARE_MIDI_TEST(testNoteOn);
|
|
||||||
DECLARE_MIDI_TEST(testNoteOff);
|
|
||||||
DECLARE_MIDI_TEST(testControlChange);
|
|
||||||
DECLARE_MIDI_TEST(testProgramChange);
|
|
||||||
DECLARE_MIDI_TEST(testAftertouchMono);
|
|
||||||
DECLARE_MIDI_TEST(testAftertouchPoly);
|
|
||||||
DECLARE_MIDI_TEST(testPitchBend);
|
|
||||||
DECLARE_MIDI_TEST(testSysEx);
|
|
||||||
DECLARE_MIDI_TEST(testClock);
|
|
||||||
DECLARE_MIDI_TEST(testStart);
|
|
||||||
DECLARE_MIDI_TEST(testStop);
|
|
||||||
DECLARE_MIDI_TEST(testContinue);
|
|
||||||
DECLARE_MIDI_TEST(testActiveSensing);
|
|
||||||
DECLARE_MIDI_TEST(testTimeCode);
|
|
||||||
DECLARE_MIDI_TEST(testSongSelect);
|
|
||||||
DECLARE_MIDI_TEST(testSongPosition);
|
|
||||||
DECLARE_MIDI_TEST(testTuneRequest);
|
|
||||||
DECLARE_MIDI_TEST(testSystemReset);
|
|
||||||
|
|
||||||
|
|
@ -1,229 +0,0 @@
|
||||||
#include <Arduino.h>
|
|
||||||
#include "midi_ValidatorTests.h"
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
IMPLEMENT_MIDI_TEST(testNoteOn, inMidi)
|
|
||||||
{
|
|
||||||
inMidi.sendNoteOn(12, 42, 3);
|
|
||||||
while (inMidi.read() == false) { }
|
|
||||||
|
|
||||||
bool result = inMidi.getType() == midi::NoteOn &&
|
|
||||||
inMidi.getData1() == 12 &&
|
|
||||||
inMidi.getData2() == 42 &&
|
|
||||||
inMidi.getChannel() == 3;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLEMENT_MIDI_TEST(testNoteOff, inMidi)
|
|
||||||
{
|
|
||||||
inMidi.sendNoteOff(12, 42, 3);
|
|
||||||
while (inMidi.read() == false) { }
|
|
||||||
|
|
||||||
bool result = inMidi.getType() == midi::NoteOff &&
|
|
||||||
inMidi.getData1() == 12 &&
|
|
||||||
inMidi.getData2() == 42 &&
|
|
||||||
inMidi.getChannel() == 3;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLEMENT_MIDI_TEST(testControlChange, inMidi)
|
|
||||||
{
|
|
||||||
inMidi.sendControlChange(12, 42, 3);
|
|
||||||
while (inMidi.read() == false) { }
|
|
||||||
|
|
||||||
bool result = inMidi.getType() == midi::ControlChange &&
|
|
||||||
inMidi.getData1() == 12 &&
|
|
||||||
inMidi.getData2() == 42 &&
|
|
||||||
inMidi.getChannel() == 3;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLEMENT_MIDI_TEST(testProgramChange, inMidi)
|
|
||||||
{
|
|
||||||
inMidi.sendProgramChange(12, 3);
|
|
||||||
while (inMidi.read() == false) { }
|
|
||||||
|
|
||||||
bool result = inMidi.getType() == midi::ProgramChange &&
|
|
||||||
inMidi.getData1() == 12 &&
|
|
||||||
inMidi.getData2() == 0 &&
|
|
||||||
inMidi.getChannel() == 3;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLEMENT_MIDI_TEST(testAftertouchMono, inMidi)
|
|
||||||
{
|
|
||||||
inMidi.sendAfterTouch(12, 3);
|
|
||||||
while (inMidi.read() == false) { }
|
|
||||||
|
|
||||||
bool result = inMidi.getType() == midi::AfterTouchChannel &&
|
|
||||||
inMidi.getData1() == 12 &&
|
|
||||||
inMidi.getData2() == 0 &&
|
|
||||||
inMidi.getChannel() == 3;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLEMENT_MIDI_TEST(testAftertouchPoly, inMidi)
|
|
||||||
{
|
|
||||||
inMidi.sendPolyPressure(12, 42, 3);
|
|
||||||
while (inMidi.read() == false) { }
|
|
||||||
|
|
||||||
bool result = inMidi.getType() == midi::AfterTouchPoly &&
|
|
||||||
inMidi.getData1() == 12 &&
|
|
||||||
inMidi.getData2() == 42 &&
|
|
||||||
inMidi.getChannel() == 3;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
volatile int pitchBendMemory = 0;
|
|
||||||
|
|
||||||
void pitchBendCallback(byte inChannel, int inValue)
|
|
||||||
{
|
|
||||||
pitchBendMemory = inValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLEMENT_MIDI_TEST(testPitchBend, inMidi)
|
|
||||||
{
|
|
||||||
inMidi.setHandlePitchBend(pitchBendCallback);
|
|
||||||
pitchBendMemory = 0;
|
|
||||||
inMidi.sendPitchBend((int)1234, 3);
|
|
||||||
while (inMidi.read() == false) { }
|
|
||||||
|
|
||||||
bool result = inMidi.getType() == midi::PitchBend &&
|
|
||||||
pitchBendMemory == 1234 &&
|
|
||||||
inMidi.getChannel() == 3;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
IMPLEMENT_MIDI_TEST(testSysEx, inMidi)
|
|
||||||
{
|
|
||||||
static const byte testData[13] =
|
|
||||||
{
|
|
||||||
'H', 'e', 'l', 'l', 'o', ',', ' ',
|
|
||||||
'w', 'o', 'r', 'l', 'd', 0
|
|
||||||
};
|
|
||||||
|
|
||||||
inMidi.sendSysEx(13, testData);
|
|
||||||
|
|
||||||
while (inMidi.read() == false) { }
|
|
||||||
|
|
||||||
bool result = inMidi.getSysExArrayLength() == 15 && // 13 + F0 + F7
|
|
||||||
memcmp((const char*)inMidi.getSysExArray()+1,
|
|
||||||
(const char*)testData,
|
|
||||||
13) == 0;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLEMENT_MIDI_TEST(testClock, inMidi)
|
|
||||||
{
|
|
||||||
inMidi.sendRealTime(midi::Clock);
|
|
||||||
while (inMidi.read() == false) { }
|
|
||||||
return inMidi.getType() == midi::Clock;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLEMENT_MIDI_TEST(testStart, inMidi)
|
|
||||||
{
|
|
||||||
inMidi.sendRealTime(midi::Start);
|
|
||||||
while (inMidi.read() == false) { }
|
|
||||||
return inMidi.getType() == midi::Start;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLEMENT_MIDI_TEST(testStop, inMidi)
|
|
||||||
{
|
|
||||||
inMidi.sendRealTime(midi::Stop);
|
|
||||||
while (inMidi.read() == false) { }
|
|
||||||
return inMidi.getType() == midi::Stop;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLEMENT_MIDI_TEST(testContinue, inMidi)
|
|
||||||
{
|
|
||||||
inMidi.sendRealTime(midi::Continue);
|
|
||||||
while (inMidi.read() == false) { }
|
|
||||||
return inMidi.getType() == midi::Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLEMENT_MIDI_TEST(testActiveSensing, inMidi)
|
|
||||||
{
|
|
||||||
inMidi.sendRealTime(midi::ActiveSensing);
|
|
||||||
while (inMidi.read() == false) { }
|
|
||||||
return inMidi.getType() == midi::ActiveSensing;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// \todo Add callback to process parsed value
|
|
||||||
|
|
||||||
volatile byte timeCodeMemory = 0;
|
|
||||||
|
|
||||||
void timeCodeCallback(byte inData)
|
|
||||||
{
|
|
||||||
timeCodeMemory = inData;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLEMENT_MIDI_TEST(testTimeCode, inMidi)
|
|
||||||
{
|
|
||||||
timeCodeMemory = 0;
|
|
||||||
inMidi.setHandleTimeCodeQuarterFrame(timeCodeCallback);
|
|
||||||
inMidi.sendTimeCodeQuarterFrame(0x07, 0x0F);
|
|
||||||
while (inMidi.read() == false) { }
|
|
||||||
bool result = inMidi.getType() == midi::TimeCodeQuarterFrame &&
|
|
||||||
timeCodeMemory == 0x7F &&
|
|
||||||
inMidi.getChannel() == 0;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
IMPLEMENT_MIDI_TEST(testSongSelect, inMidi)
|
|
||||||
{
|
|
||||||
inMidi.sendSongSelect(12);
|
|
||||||
while (inMidi.read() == false) { }
|
|
||||||
|
|
||||||
bool result = inMidi.getType() == midi::SongSelect &&
|
|
||||||
inMidi.getData1() == 12 &&
|
|
||||||
inMidi.getData2() == 0 &&
|
|
||||||
inMidi.getChannel() == 0;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
volatile int songPositionMemory = 0;
|
|
||||||
|
|
||||||
void songPositionCallback(unsigned int inPosition)
|
|
||||||
{
|
|
||||||
songPositionMemory = inPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLEMENT_MIDI_TEST(testSongPosition, inMidi)
|
|
||||||
{
|
|
||||||
songPositionMemory = 0;
|
|
||||||
inMidi.setHandleSongPosition(songPositionCallback);
|
|
||||||
inMidi.sendSongPosition(12345);
|
|
||||||
while (inMidi.read() == false) { }
|
|
||||||
|
|
||||||
bool result = inMidi.getType() == midi::SongPosition &&
|
|
||||||
songPositionMemory == 12345 &&
|
|
||||||
inMidi.getChannel() == 0;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
IMPLEMENT_MIDI_TEST(testTuneRequest, inMidi)
|
|
||||||
{
|
|
||||||
inMidi.sendTuneRequest();
|
|
||||||
while (inMidi.read() == false) { }
|
|
||||||
return inMidi.getType() == midi::TuneRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLEMENT_MIDI_TEST(testSystemReset, inMidi)
|
|
||||||
{
|
|
||||||
inMidi.sendRealTime(midi::SystemReset);
|
|
||||||
while (inMidi.read() == false) { }
|
|
||||||
return inMidi.getType() == midi::SystemReset;
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
# Use this script to install the library directy from the git clone.
|
|
||||||
|
|
||||||
|
|
||||||
if [[ -d /Applications/Arduino.app ]]
|
|
||||||
then
|
|
||||||
|
|
||||||
# Define locations
|
|
||||||
|
|
||||||
lib_path=/Applications/Arduino.app/Contents/Resources/Java/libraries/MIDI
|
|
||||||
|
|
||||||
if [[ -d $lib_path ]]
|
|
||||||
then
|
|
||||||
# Remove old lib
|
|
||||||
rm -rf $lib_path
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create folder
|
|
||||||
mkdir $lib_path
|
|
||||||
|
|
||||||
# Copy sources
|
|
||||||
cp ../src/MIDI.cpp $lib_path
|
|
||||||
cp ../src/MIDI.h $lib_path
|
|
||||||
cp ../src/midi_* $lib_path
|
|
||||||
|
|
||||||
# Copy resources
|
|
||||||
cp ../res/keywords.txt $lib_path
|
|
||||||
|
|
||||||
# Copy examples
|
|
||||||
mkdir $lib_path/examples
|
|
||||||
|
|
||||||
cp -r examples/* $lib_path/examples
|
|
||||||
|
|
||||||
# Copy doc
|
|
||||||
mkdir $lib_path/doc
|
|
||||||
|
|
||||||
cp -r ../doc/* $lib_path/doc
|
|
||||||
|
|
||||||
else
|
|
||||||
echo "Arduino application not found."
|
|
||||||
fi
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
# This script installs the Arduino MIDI Library into the Arduino application,
|
|
||||||
# so that every sketch can include it directly, without having to copy anything.
|
|
||||||
#
|
|
||||||
# To install the library, run this script by double-clicking it,
|
|
||||||
# it should be directly executable and seen as such by Mac OS X.
|
|
||||||
# If not, open a terminal, cd to the script location, and run ./install_mac
|
|
||||||
#
|
|
||||||
# Open the Arduino IDE, and you're ready to go!
|
|
||||||
|
|
||||||
# The script assumes the Arduino application
|
|
||||||
# is installed in the default location.
|
|
||||||
|
|
||||||
if [[ -d /Applications/Arduino.app ]]
|
|
||||||
then
|
|
||||||
|
|
||||||
# Define locations
|
|
||||||
lib_path=/Applications/Arduino.app/Contents/Resources/Java/libraries/MIDI
|
|
||||||
|
|
||||||
if [[ -d $lib_path ]]
|
|
||||||
then
|
|
||||||
# Remove old lib
|
|
||||||
rm -rf $lib_path
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create folder
|
|
||||||
mkdir $lib_path
|
|
||||||
|
|
||||||
# Install contents
|
|
||||||
cp -r * $lib_path
|
|
||||||
|
|
||||||
# Cleanup
|
|
||||||
rm $lib_path/install_mac
|
|
||||||
|
|
||||||
else
|
|
||||||
echo "Arduino application not found."
|
|
||||||
fi
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
#
|
|
||||||
# Generate an archive with packaged content for easier delivery.
|
|
||||||
# The generated archive contains:
|
|
||||||
# - Source files (MIDI.cpp / MIDI.h)
|
|
||||||
# - Resources (keywords.txt)
|
|
||||||
# - Documentation (Doxygen)
|
|
||||||
# - Examples for Arduino IDE
|
|
||||||
# - Installation scripts
|
|
||||||
|
|
||||||
|
|
||||||
# Create a temporary destination folder
|
|
||||||
mkdir -p temp/doc
|
|
||||||
mkdir -p temp/examples
|
|
||||||
|
|
||||||
# Copy sources
|
|
||||||
cp ../src/* temp
|
|
||||||
|
|
||||||
# Copy resources
|
|
||||||
cp keywords.txt temp
|
|
||||||
cp install_* temp
|
|
||||||
rm temp/install_local_*
|
|
||||||
|
|
||||||
# Copy examples
|
|
||||||
cp -r examples/* temp/examples
|
|
||||||
|
|
||||||
# Generate & copy doc
|
|
||||||
cd ../doc
|
|
||||||
/Applications/Doxygen.app/Contents/Resources/doxygen Doxyfile
|
|
||||||
rm -rf latex
|
|
||||||
cd ../res
|
|
||||||
|
|
||||||
cp -r ../doc/* temp/doc
|
|
||||||
|
|
||||||
# Generate package
|
|
||||||
mv temp MIDI
|
|
||||||
zip -r MIDI.zip MIDI
|
|
||||||
|
|
||||||
|
|
||||||
# Remove temp folder
|
|
||||||
rm -rf MIDI
|
|
||||||
|
|
||||||
# Archive generated packaged
|
|
||||||
|
|
||||||
if [[ !( -d ../bin ) ]]
|
|
||||||
then
|
|
||||||
mkdir ../bin # Create archives location
|
|
||||||
fi
|
|
||||||
|
|
||||||
mv MIDI.zip ../bin/Arduino_MIDI_Library.zip
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Generate an archive with packaged content for easier delivery.
|
||||||
|
# The generated archive contains:
|
||||||
|
# - Source files (MIDI.cpp / MIDI.h)
|
||||||
|
# - Resources (keywords.txt)
|
||||||
|
# - Examples for Arduino IDE
|
||||||
|
# - Installation scripts
|
||||||
|
|
||||||
|
cd "`dirname "${0}"`"
|
||||||
|
|
||||||
|
root="${PWD}/.."
|
||||||
|
build="$root/build/MIDI"
|
||||||
|
|
||||||
|
echo root $root
|
||||||
|
echo build $build
|
||||||
|
|
||||||
|
# Create a temporary destination folder
|
||||||
|
mkdir -p "$build"
|
||||||
|
mkdir -p "$build/examples"
|
||||||
|
|
||||||
|
# Copy sources
|
||||||
|
cd "$root/src/"
|
||||||
|
cp * "$build/"
|
||||||
|
|
||||||
|
# Copy resources
|
||||||
|
cd "$root/res/"
|
||||||
|
cp keywords.txt "$build/"
|
||||||
|
|
||||||
|
# Copy examples
|
||||||
|
cd "$root/res/examples/"
|
||||||
|
cp -r * "$build/examples"
|
||||||
|
|
||||||
|
# Generate package
|
||||||
|
cd "$build/.."
|
||||||
|
zip -r Arduino_MIDI_Library.zip MIDI
|
||||||
|
|
@ -0,0 +1,114 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import rtmidi
|
||||||
|
import random
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class Midi:
|
||||||
|
InvalidType = 0x00 # For notifying errors
|
||||||
|
NoteOff = 0x80 # Note Off
|
||||||
|
NoteOn = 0x90 # Note On
|
||||||
|
AfterTouchPoly = 0xA0 # Polyphonic AfterTouch
|
||||||
|
ControlChange = 0xB0 # Control Change / Channel Mode
|
||||||
|
ProgramChange = 0xC0 # Program Change
|
||||||
|
AfterTouchChannel = 0xD0 # Channel (monophonic) AfterTouch
|
||||||
|
PitchBend = 0xE0 # Pitch Bend
|
||||||
|
SystemExclusive = 0xF0 # System Exclusive
|
||||||
|
TimeCodeQuarterFrame = 0xF1 # System Common - MIDI Time Code Quarter Frame
|
||||||
|
SongPosition = 0xF2 # System Common - Song Position Pointer
|
||||||
|
SongSelect = 0xF3 # System Common - Song Select
|
||||||
|
TuneRequest = 0xF6 # System Common - Tune Request
|
||||||
|
Clock = 0xF8 # System Real Time - Timing Clock
|
||||||
|
Start = 0xFA # System Real Time - Start
|
||||||
|
Continue = 0xFB # System Real Time - Continue
|
||||||
|
Stop = 0xFC # System Real Time - Stop
|
||||||
|
ActiveSensing = 0xFE # System Real Time - Active Sensing
|
||||||
|
SystemReset = 0xFF # System Real Time - System Reset
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def getChannel(statusByte):
|
||||||
|
return statusByte & 0x0f;
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def getType(statusByte):
|
||||||
|
if statusByte >= 0xf0:
|
||||||
|
# System messages
|
||||||
|
return statusByte
|
||||||
|
else:
|
||||||
|
# Channel messages
|
||||||
|
return statusByte & 0xf0;
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class MidiInterface:
|
||||||
|
def __init__(self, listenerCallback = None):
|
||||||
|
self.input = rtmidi.MidiIn()
|
||||||
|
self.output = rtmidi.MidiOut()
|
||||||
|
self.listenerCallback = listenerCallback
|
||||||
|
self.ports = self.getAvailablePorts()
|
||||||
|
self.port = self.connect(self.choosePorts())
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def handleMidiInput(self, message, timestamp):
|
||||||
|
midiData = message[0]
|
||||||
|
if self.listenerCallback:
|
||||||
|
self.listenerCallback(midiData)
|
||||||
|
|
||||||
|
def send(self, message):
|
||||||
|
print('Sending', message)
|
||||||
|
self.output.send_message(message)
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def getAvailablePorts(self):
|
||||||
|
return {
|
||||||
|
'input' : self.input.get_ports(),
|
||||||
|
'output': self.output.get_ports(),
|
||||||
|
}
|
||||||
|
|
||||||
|
def choosePorts(self):
|
||||||
|
return {
|
||||||
|
'input' : self.choosePort(self.ports['input'], 'input'),
|
||||||
|
'output': self.choosePort(self.ports['output'], 'output')
|
||||||
|
}
|
||||||
|
|
||||||
|
def choosePort(self, ports, direction):
|
||||||
|
if not ports:
|
||||||
|
print('No MIDI ports available, bailing out.')
|
||||||
|
return None
|
||||||
|
|
||||||
|
if len(ports) == 1:
|
||||||
|
return {
|
||||||
|
'id': 0,
|
||||||
|
'name': ports[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Give a choice
|
||||||
|
print('Multiple %s ports available, please make a choice:' % direction)
|
||||||
|
choices = dict()
|
||||||
|
for port, i in zip(ports, range(0, len(ports))):
|
||||||
|
choices[i] = port
|
||||||
|
print(' [%d]' % i, port)
|
||||||
|
choiceIndex = int(input('-> '))
|
||||||
|
return {
|
||||||
|
'id': choiceIndex,
|
||||||
|
'name': choices[choiceIndex]
|
||||||
|
}
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def connect(self, ports):
|
||||||
|
if not ports:
|
||||||
|
return None
|
||||||
|
|
||||||
|
print('Connecting input to %s' % ports['input']['name'])
|
||||||
|
print('Connecting output to %s' % ports['output']['name'])
|
||||||
|
|
||||||
|
self.input.set_callback(self.handleMidiInput)
|
||||||
|
self.input.open_port(ports['input']['id'])
|
||||||
|
self.output.open_port(ports['output']['id'])
|
||||||
|
return ports
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class Tester:
|
||||||
|
def __init__(self, interface):
|
||||||
|
self.interface = interface
|
||||||
|
self.sent = None
|
||||||
|
self.expected = None
|
||||||
|
self.received = None
|
||||||
|
|
||||||
|
def handleMidiInput(self, data):
|
||||||
|
print('Recived data:', data)
|
||||||
|
self.received = data
|
||||||
|
|
||||||
|
def checkThru(self, message):
|
||||||
|
self.interface.send(message)
|
||||||
|
self.sent = message
|
||||||
|
self.expected = message
|
||||||
|
self.received = None
|
||||||
|
while not self.received:
|
||||||
|
pass
|
||||||
|
return self.expected == self.received
|
||||||
|
|
@ -0,0 +1,167 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
from pprint import pprint
|
||||||
|
from midi import *
|
||||||
|
from tester import *
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
rootDir = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '../..'))
|
||||||
|
logsDir = os.path.join(rootDir, 'logs')
|
||||||
|
resDir = os.path.join(rootDir, 'res')
|
||||||
|
srcDir = os.path.join(rootDir, 'src')
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class Dict(dict):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.__dict__ = self
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class Arduino:
|
||||||
|
if sys.platform == 'darwin':
|
||||||
|
binary = '/Applications/Arduino.app/Contents/MacOS/JavaApplicationStub'
|
||||||
|
home = os.path.expanduser('~/Documents/Arduino')
|
||||||
|
elif sys.platform == 'win32':
|
||||||
|
binary = 'arduino.exe'
|
||||||
|
home = os.path.expanduser('~/My Documents/Arduino')
|
||||||
|
elif sys.platform == 'linux':
|
||||||
|
binary = 'arduino'
|
||||||
|
home = os.path.expanduser('~/Arduino')
|
||||||
|
else:
|
||||||
|
print('Unsupported platform %s' % str(sys.platform))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
libraryDir = os.path.join(home, 'libraries')
|
||||||
|
|
||||||
|
boards = [
|
||||||
|
Dict({
|
||||||
|
'name': 'Uno',
|
||||||
|
'id': 'arduino:avr:uno',
|
||||||
|
'port': None,
|
||||||
|
}),
|
||||||
|
Dict({
|
||||||
|
'name': 'Leonardo',
|
||||||
|
'id': 'arduino:avr:leonardo',
|
||||||
|
'port': None,
|
||||||
|
}),
|
||||||
|
Dict({
|
||||||
|
'name': 'Mega',
|
||||||
|
'id': 'arduino:avr:mega',
|
||||||
|
'port': None,
|
||||||
|
}),
|
||||||
|
Dict({
|
||||||
|
'name': 'Due',
|
||||||
|
'id': 'arduino:sam:due',
|
||||||
|
'port': None,
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
|
||||||
|
def checkReturnCode(code):
|
||||||
|
if code == 0:
|
||||||
|
return True
|
||||||
|
if code == 1:
|
||||||
|
print('Operation failed.')
|
||||||
|
if code == 2:
|
||||||
|
print('File not found')
|
||||||
|
if code == 3:
|
||||||
|
print('Invalid argument')
|
||||||
|
return False
|
||||||
|
|
||||||
|
def verify(sketch, boardId):
|
||||||
|
return Arduino.checkReturnCode(subprocess.call([
|
||||||
|
Arduino.binary,
|
||||||
|
'--verify', sketch,
|
||||||
|
'--board', boardId,
|
||||||
|
'--verbose-build',
|
||||||
|
]))
|
||||||
|
#], stdout = open(os.devnull, 'wb')))
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class ArduinoMidiLibrary:
|
||||||
|
def __init__(self):
|
||||||
|
self.path = os.path.join(Arduino.libraryDir, 'MIDI')
|
||||||
|
self.sources = self.getSources()
|
||||||
|
self.resources = self.getResources()
|
||||||
|
|
||||||
|
def getSources(self):
|
||||||
|
sources = dict()
|
||||||
|
for root, dirs, files in os.walk(srcDir):
|
||||||
|
for name, ext in [os.path.splitext(f) for f in files]:
|
||||||
|
if ext in ('.cpp', '.hpp', '.h'):
|
||||||
|
source = os.path.join(root, name + ext)
|
||||||
|
dest = os.path.join(self.path, os.path.relpath(source, srcDir))
|
||||||
|
sources[source] = dest
|
||||||
|
return sources
|
||||||
|
|
||||||
|
def getResources(self):
|
||||||
|
return {
|
||||||
|
os.path.join(resDir, 'keywords.txt'): os.path.join(self.path, 'keywords.txt'),
|
||||||
|
os.path.join(resDir, 'examples/'): os.path.join(self.path, 'examples/'),
|
||||||
|
}
|
||||||
|
|
||||||
|
def install(self):
|
||||||
|
payloads = dict(list(self.sources.items()) + list(self.resources.items()))
|
||||||
|
for s,d in payloads.items():
|
||||||
|
if not os.path.exists(os.path.dirname(d)):
|
||||||
|
os.makedirs(os.path.dirname(d))
|
||||||
|
if os.path.isfile(s):
|
||||||
|
shutil.copy2(s, d)
|
||||||
|
elif os.path.isdir(s):
|
||||||
|
if os.path.exists(d):
|
||||||
|
shutil.rmtree(d)
|
||||||
|
shutil.copytree(s, d)
|
||||||
|
|
||||||
|
def getInstalledExamples(self):
|
||||||
|
exDir = os.path.join(self.path, 'examples')
|
||||||
|
return [os.path.join(exDir, x, x + '.ino') for x in next(os.walk(exDir))[1]]
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
for board in Arduino.boards:
|
||||||
|
# Validate examples
|
||||||
|
print('Validation for Arduino %s' % board.name)
|
||||||
|
for example in self.getInstalledExamples():
|
||||||
|
if not Arduino.verify(example, board.id):
|
||||||
|
print('{0:40} {1}'.format(os.path.basename(example), 'FAILED'))
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
print('{0:40} {1}'.format(os.path.basename(example), 'PASSED'))
|
||||||
|
return True
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def main():
|
||||||
|
midiInterface = MidiInterface()
|
||||||
|
tester = Tester(midiInterface)
|
||||||
|
midiInterface.listenerCallback = tester.handleMidiInput
|
||||||
|
|
||||||
|
tester.checkThru([Midi.NoteOn, 64, 80])
|
||||||
|
tester.checkThru([Midi.AfterTouchChannel, 1])
|
||||||
|
tester.checkThru([2])
|
||||||
|
tester.checkThru([3])
|
||||||
|
tester.checkThru([Midi.NoteOn, 64, 0])
|
||||||
|
tester.checkThru([65, 127])
|
||||||
|
tester.checkThru([65, 0])
|
||||||
|
tester.checkThru([66, 127])
|
||||||
|
tester.checkThru([66, 0])
|
||||||
|
|
||||||
|
#lib = ArduinoMidiLibrary()
|
||||||
|
#lib.install()
|
||||||
|
#if lib.validate():
|
||||||
|
# print('Validation passed')
|
||||||
|
#else:
|
||||||
|
# print('Validation failed')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
19
src/MIDI.cpp
19
src/MIDI.cpp
|
|
@ -2,10 +2,23 @@
|
||||||
* @file MIDI.cpp
|
* @file MIDI.cpp
|
||||||
* Project Arduino MIDI Library
|
* Project Arduino MIDI Library
|
||||||
* @brief MIDI Library for the Arduino
|
* @brief MIDI Library for the Arduino
|
||||||
* @version 4.0
|
* @version 4.1
|
||||||
* @author Francois Best
|
* @author Francois Best
|
||||||
* @date 24/02/11
|
* @date 24/02/11
|
||||||
* license GPL Forty Seven Effects - 2011
|
* @license GPL v3.0 - Copyright Forty Seven Effects 2014
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "MIDI.h"
|
#include "MIDI.h"
|
||||||
|
|
@ -44,6 +57,7 @@ BEGIN_MIDI_NAMESPACE
|
||||||
\param inLength The lenght of the input buffer.
|
\param inLength The lenght of the input buffer.
|
||||||
\return The lenght of the encoded output buffer.
|
\return The lenght of the encoded output buffer.
|
||||||
@see decodeSysEx
|
@see decodeSysEx
|
||||||
|
Code inspired from Ruin & Wesen's SysEx encoder/decoder - http://ruinwesen.com
|
||||||
*/
|
*/
|
||||||
unsigned encodeSysEx(const byte* inData, byte* outSysEx, unsigned inLength)
|
unsigned encodeSysEx(const byte* inData, byte* outSysEx, unsigned inLength)
|
||||||
{
|
{
|
||||||
|
|
@ -80,6 +94,7 @@ unsigned encodeSysEx(const byte* inData, byte* outSysEx, unsigned inLength)
|
||||||
\param inLength The lenght of the input buffer.
|
\param inLength The lenght of the input buffer.
|
||||||
\return The lenght of the output buffer.
|
\return The lenght of the output buffer.
|
||||||
@see encodeSysEx @see getSysExArrayLength
|
@see encodeSysEx @see getSysExArrayLength
|
||||||
|
Code inspired from Ruin & Wesen's SysEx encoder/decoder - http://ruinwesen.com
|
||||||
*/
|
*/
|
||||||
unsigned decodeSysEx(const byte* inSysEx, byte* outData, unsigned inLength)
|
unsigned decodeSysEx(const byte* inSysEx, byte* outData, unsigned inLength)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
18
src/MIDI.h
18
src/MIDI.h
|
|
@ -2,10 +2,23 @@
|
||||||
* @file MIDI.h
|
* @file MIDI.h
|
||||||
* Project Arduino MIDI Library
|
* Project Arduino MIDI Library
|
||||||
* @brief MIDI Library for the Arduino
|
* @brief MIDI Library for the Arduino
|
||||||
* @version 4.0
|
* @version 4.1
|
||||||
* @author Francois Best
|
* @author Francois Best
|
||||||
* @date 24/02/11
|
* @date 24/02/11
|
||||||
* license GPL Forty Seven Effects - 2011
|
* @license GPL v3.0 - Copyright Forty Seven Effects 2014
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
@ -117,6 +130,7 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static inline MidiType getTypeFromStatusByte(byte inStatus);
|
static inline MidiType getTypeFromStatusByte(byte inStatus);
|
||||||
|
static inline Channel getChannelFromStatusByte(byte inStatus);
|
||||||
static inline bool isChannelMessage(MidiType inType);
|
static inline bool isChannelMessage(MidiType inType);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
87
src/MIDI.hpp
87
src/MIDI.hpp
|
|
@ -2,10 +2,23 @@
|
||||||
* @file midi_Inline.hpp
|
* @file midi_Inline.hpp
|
||||||
* Project Arduino MIDI Library
|
* Project Arduino MIDI Library
|
||||||
* @brief MIDI Library for the Arduino - Inline implementations
|
* @brief MIDI Library for the Arduino - Inline implementations
|
||||||
* @version 4.0
|
* @version 4.1
|
||||||
* @author Francois Best
|
* @author Francois Best
|
||||||
* @date 24/02/11
|
* @date 24/02/11
|
||||||
* license GPL Forty Seven Effects - 2011
|
* @license GPL v3.0 - Copyright Forty Seven Effects 2014
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
@ -496,9 +509,7 @@ inline bool MidiInterface<SerialPort>::read(Channel inChannel)
|
||||||
template<class SerialPort>
|
template<class SerialPort>
|
||||||
bool MidiInterface<SerialPort>::parse()
|
bool MidiInterface<SerialPort>::parse()
|
||||||
{
|
{
|
||||||
const byte bytes_available = mSerial.available();
|
if (mSerial.available() == 0)
|
||||||
|
|
||||||
if (bytes_available == 0)
|
|
||||||
// No data available.
|
// No data available.
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
@ -534,29 +545,11 @@ bool MidiInterface<SerialPort>::parse()
|
||||||
// Else: well, we received another status byte,
|
// Else: well, we received another status byte,
|
||||||
// so the running status does not apply here.
|
// so the running status does not apply here.
|
||||||
// It will be updated upon completion of this message.
|
// It will be updated upon completion of this message.
|
||||||
|
|
||||||
if (mPendingMessageIndex >= (mPendingMessageExpectedLenght - 1))
|
|
||||||
{
|
|
||||||
mMessage.type = getTypeFromStatusByte(mPendingMessage[0]);
|
|
||||||
mMessage.channel = (mPendingMessage[0] & 0x0f) + 1;
|
|
||||||
mMessage.data1 = mPendingMessage[1];
|
|
||||||
|
|
||||||
// Save data2 only if applicable
|
|
||||||
if (mPendingMessageExpectedLenght == 3)
|
|
||||||
mMessage.data2 = mPendingMessage[2];
|
|
||||||
else
|
|
||||||
mMessage.data2 = 0;
|
|
||||||
|
|
||||||
mPendingMessageIndex = 0;
|
|
||||||
mPendingMessageExpectedLenght = 0;
|
|
||||||
mMessage.valid = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (getTypeFromStatusByte(mPendingMessage[0]))
|
switch (getTypeFromStatusByte(mPendingMessage[0]))
|
||||||
{
|
{
|
||||||
// 1 byte messages
|
// 1 byte messages
|
||||||
case Start:
|
case Start:
|
||||||
case Continue:
|
case Continue:
|
||||||
case Stop:
|
case Stop:
|
||||||
|
|
@ -616,17 +609,38 @@ bool MidiInterface<SerialPort>::parse()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then update the index of the pending message.
|
if (mPendingMessageIndex >= (mPendingMessageExpectedLenght - 1))
|
||||||
mPendingMessageIndex++;
|
{
|
||||||
|
// Reception complete
|
||||||
|
mMessage.type = getTypeFromStatusByte(mPendingMessage[0]);
|
||||||
|
mMessage.channel = getChannelFromStatusByte(mPendingMessage[0]);
|
||||||
|
mMessage.data1 = mPendingMessage[1];
|
||||||
|
|
||||||
#if USE_1BYTE_PARSING
|
// Save data2 only if applicable
|
||||||
|
if (mPendingMessageExpectedLenght == 3)
|
||||||
|
mMessage.data2 = mPendingMessage[2];
|
||||||
|
else
|
||||||
|
mMessage.data2 = 0;
|
||||||
|
|
||||||
|
mPendingMessageIndex = 0;
|
||||||
|
mPendingMessageExpectedLenght = 0;
|
||||||
|
mMessage.valid = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Waiting for more data
|
||||||
|
mPendingMessageIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if USE_1BYTE_PARSING
|
||||||
// Message is not complete.
|
// Message is not complete.
|
||||||
return false;
|
return false;
|
||||||
#else
|
#else
|
||||||
// Call the parser recursively
|
// Call the parser recursively
|
||||||
// to parse the rest of the message.
|
// to parse the rest of the message.
|
||||||
return parse();
|
return parse();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -698,7 +712,7 @@ bool MidiInterface<SerialPort>::parse()
|
||||||
mPendingMessage[mPendingMessageIndex] = extracted;
|
mPendingMessage[mPendingMessageIndex] = extracted;
|
||||||
|
|
||||||
// Now we are going to check if we have reached the end of the message
|
// Now we are going to check if we have reached the end of the message
|
||||||
if (mPendingMessageIndex >= (mPendingMessageExpectedLenght-1))
|
if (mPendingMessageIndex >= (mPendingMessageExpectedLenght - 1))
|
||||||
{
|
{
|
||||||
// "FML" case: fall down here with an overflown SysEx..
|
// "FML" case: fall down here with an overflown SysEx..
|
||||||
// This means we received the last possible data byte that can fit
|
// This means we received the last possible data byte that can fit
|
||||||
|
|
@ -712,7 +726,7 @@ bool MidiInterface<SerialPort>::parse()
|
||||||
mMessage.type = getTypeFromStatusByte(mPendingMessage[0]);
|
mMessage.type = getTypeFromStatusByte(mPendingMessage[0]);
|
||||||
|
|
||||||
if (isChannelMessage(mMessage.type))
|
if (isChannelMessage(mMessage.type))
|
||||||
mMessage.channel = (mPendingMessage[0] & 0x0f) + 1;
|
mMessage.channel = getChannelFromStatusByte(mPendingMessage[0]);
|
||||||
else
|
else
|
||||||
mMessage.channel = 0;
|
mMessage.channel = 0;
|
||||||
|
|
||||||
|
|
@ -766,9 +780,6 @@ bool MidiInterface<SerialPort>::parse()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// What are our chances to fall here?
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private method, see midi_Settings.h for documentation
|
// Private method, see midi_Settings.h for documentation
|
||||||
|
|
@ -936,6 +947,14 @@ MidiType MidiInterface<SerialPort>::getTypeFromStatusByte(byte inStatus)
|
||||||
return (MidiType)inStatus;
|
return (MidiType)inStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief Returns channel in the range 1-16
|
||||||
|
*/
|
||||||
|
template<class SerialPort>
|
||||||
|
inline Channel MidiInterface<SerialPort>::getChannelFromStatusByte(byte inStatus)
|
||||||
|
{
|
||||||
|
return (inStatus & 0x0f) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
template<class SerialPort>
|
template<class SerialPort>
|
||||||
bool MidiInterface<SerialPort>::isChannelMessage(MidiType inType)
|
bool MidiInterface<SerialPort>::isChannelMessage(MidiType inType)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,23 @@
|
||||||
* @file midi_Defs.h
|
* @file midi_Defs.h
|
||||||
* Project Arduino MIDI Library
|
* Project Arduino MIDI Library
|
||||||
* @brief MIDI Library for the Arduino - Definitions
|
* @brief MIDI Library for the Arduino - Definitions
|
||||||
* @version 4.0
|
* @version 4.1
|
||||||
* @author Francois Best
|
* @author Francois Best
|
||||||
* @date 24/02/11
|
* @date 24/02/11
|
||||||
* license GPL Forty Seven Effects - 2011
|
* @license GPL v3.0 - Copyright Forty Seven Effects 2014
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,23 @@
|
||||||
* @file midi_Namespace.h
|
* @file midi_Namespace.h
|
||||||
* Project Arduino MIDI Library
|
* Project Arduino MIDI Library
|
||||||
* @brief MIDI Library for the Arduino - Namespace declaration
|
* @brief MIDI Library for the Arduino - Namespace declaration
|
||||||
* @version 4.0
|
* @version 4.1
|
||||||
* @author Francois Best
|
* @author Francois Best
|
||||||
* @date 24/02/11
|
* @date 24/02/11
|
||||||
* license GPL Forty Seven Effects - 2011
|
* @license GPL v3.0 - Copyright Forty Seven Effects 2014
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,23 @@
|
||||||
* @file midi_Settings.h
|
* @file midi_Settings.h
|
||||||
* Project Arduino MIDI Library
|
* Project Arduino MIDI Library
|
||||||
* @brief MIDI Library for the Arduino - Settings
|
* @brief MIDI Library for the Arduino - Settings
|
||||||
* @version 4.0
|
* @version 4.1
|
||||||
* @author Francois Best
|
* @author Francois Best
|
||||||
* @date 24/02/11
|
* @date 24/02/11
|
||||||
* license GPL Forty Seven Effects - 2011
|
* @license GPL v3.0 - Copyright Forty Seven Effects 2014
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
@ -48,13 +61,13 @@
|
||||||
// Set the default port to use for MIDI.
|
// Set the default port to use for MIDI.
|
||||||
#if MIDI_AUTO_INSTANCIATE
|
#if MIDI_AUTO_INSTANCIATE
|
||||||
# ifdef ARDUINO
|
# ifdef ARDUINO
|
||||||
|
# include "Arduino.h"
|
||||||
# ifdef USBCON
|
# ifdef USBCON
|
||||||
# define MIDI_DEFAULT_SERIAL_PORT Serial1 // For Leonardo
|
# define MIDI_DEFAULT_SERIAL_PORT Serial1 // For Leonardo
|
||||||
# else
|
# else
|
||||||
# define MIDI_DEFAULT_SERIAL_PORT Serial // For other Arduinos
|
# define MIDI_DEFAULT_SERIAL_PORT Serial // For other Arduinos
|
||||||
# endif
|
# endif
|
||||||
# define MIDI_DEFAULT_SERIAL_CLASS HardwareSerial
|
# define MIDI_DEFAULT_SERIAL_CLASS HardwareSerial
|
||||||
# include "Arduino.h"
|
|
||||||
# include "HardwareSerial.h"
|
# include "HardwareSerial.h"
|
||||||
# else
|
# else
|
||||||
# error Auto-instanciation disabled. Use MIDI_CREATE_INSTANCE macro.
|
# error Auto-instanciation disabled. Use MIDI_CREATE_INSTANCE macro.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue