Show Posts
Pages: [1]
1  Forum 2005-2010 (read only) / Development / New: Extended MIDI Library on: April 08, 2009, 07:45:02 am
Hi All,

I've been working on a project involving MIDI and discovered that the existing library doesn't have any support for system real-time messages.
So I wrote a new extended library with support for real-time messages.

Real-time messages are messages like:
- Timing Clock. (24ppqn)
- Start.
- Stop.
- Continue.
- Active Sensing.
- Reset.

I plan on supporting System Exclusive in the future.
Further more I managed to reduce the size of the library.

Of course I haven't been able to test everything to it's full extend, so please let me know if you happen to encounter any bugs while using this lib.

After including the library you need to declare an object of type MIDI before you are able to use it.

Putting the following line outside of your setup() and loop() will suffice:
Code:
MIDI midi;

 Also make sure you include WProgram.h in your sketch before this library.
Code:
#include <WProgram.h>
#include <MIDI.h>

I think all the names of variables, parameters, functions are logical descriptions of their purpose, but in short:

You first have to call MIDI.begin(). After this you can either use MIDI.read() or MIDI.read(int channel, bool sys) to check if there is an incoming message. It will return true if a message was read, otherwise it will return false.
Ones a message is read it is available until you either call read(), read(channel, sys).
The sys parameter allows you to read for messages on the given channel and still receive System real-time messages (which are not channel bound) if true or ignore them if false.
A MIDI message can be three different sizes: 1, 2 or 3 bytes. So it is advised to check the message size with getSize() before retrieving the data1 en data2 parts of the message.
The default value for data1 and data2 is 0 which can also be a value received from a MIDI device.
getType() Allows you to check what kind of MIDI message is received very much like in the old library.
Retrieving the data from the message is possible with: getStatus(), getData1(), getData2().

I also added a method to retrieve the channel from the status byte, which can come in handy.

Sending MIDI messages is possible by using one of the three send() methods.
send(status), send(status, data1), send(status, data1, data2).

I will add a send method that allows you to specify message type, channel and (optionally) data soon.

http://webserv.nhl.nl/~weste608/Arduino_MIDI/MIDI(extended).zip
2  Forum 2005-2010 (read only) / Development / Re: undefined reference to function from my library on: April 01, 2009, 08:02:41 pm
Quote
I suspect that deleting MIDI.o and then recompile will solve your problem?

Thank you very much!!!
Copied the directory around one to many incorrect times  smiley-grin
3  Forum 2005-2010 (read only) / Development / undefined reference to function from my library on: April 01, 2009, 07:24:13 pm
Hi all,

I'm trying to write my own MIDI library for the Arduino.
Now I seem to have com across a strange problem. Apparently I'm able to call the begin() method of my object, but when I try to call read() I get an error telling me there is no reference to that method...

o: In function `loop':
E:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\build52696.tmp/Temporary_8968_8700.cpp:17: undefined reference to `MIDI::read()'


Basically I can call methods that don't return anything, but I can't call methods with a return value.

code:
MIDI.h:
Code:
#ifndef MIDI_h
#define MIDI_h

#include "WConstants.h"

struct Midimsg {
      byte status;
      byte data1;
      byte data2;
};

class MIDI {
      public:
            MIDI();
            void begin();
            bool read();
            void send(byte status, byte data1, byte data2);
            void send(byte status, byte data1);
            void send(byte status);
            byte getStatus();
            byte getData1();
            byte getData2();
            byte getChannelFromStatus(byte status);
            int getMessageSize(byte status);
      private:
            Midimsg msg;
            byte getNextByte();
            void clearMessage();
};

#endif

MIDI.cpp:
Code:
#include "WProgram.h"

#include "MIDI.h"
#include "HardwareSerial.h"

MIDI::MIDI() { }

void MIDI::begin() {
      Serial.begin(31250);
}

bool MIDI::read() {
      clearMessage();
      if (Serial.available() > 0) {
            byte sts = Serial.read();
            int size = getMessageSize(sts);
            switch (format) {
                  case 1: {
                        msg.status = sts;
                        msg.data1 = 0;
                        msg.data2 = 0;
                  }
                  return true;
                  
                  case 2: {
                        byte dat1 = getNextByte();
                        if (dat1 != -1) {
                              msg.status = sts;
                              msg.data1 = dat1;
                              msg.data2 = 0;
                        }
                  }
                  return true;
                  
                  case 3: {
                        byte dat1 = getNextByte();
                        if (dat1 != -1) {
                              byte dat2 = getNextByte();
                              if (dat2 != -1) {
                                    msg.status = sts;
                                    msg.data1 = dat1;
                                    msg.data2 = dat2;
                              }
                        }
                  }
                  return true;
                  
                  case -1:
                  return false; // invalid status byte
            }
      }
      else {
            return false;
      }
      return false;
}

void MIDI::send(byte status, byte data1, byte data2) {
      Serial.print(status, BYTE);
      Serial.print(data1, BYTE);
      Serial.print(data2, BYTE);
}

void MIDI::send(byte status, byte data1) {
      Serial.print(status, BYTE);
      Serial.print(data1, BYTE);
}

void MIDI::send(byte status) {
      Serial.print(status, BYTE);
}

byte MIDI::getStatus() {
      return msg.status;
}

byte MIDI::getData1() {
      return msg.data1;
}

byte MIDI::getData2() {
      return msg.data2;
}

byte MIDI::getChannelFromStatus(byte status) {
      return (status & 0x0F);
}

int MIDI::getMessageSize(byte status) {
      if (status > 0xF5) { // 1 byte msg
            return 1;
      }
      else if ((status > 0xC0 && status < 0xE0) || (status == 0xF3)) { // 2 byte msg
            return 2;
      }
      else if ((status > 0x7F && status < 0xC0) || (status > 0xDF && status < 0xF0)) { // 3 byte msg
            return 3;
      }
      else {
            return -1; // invalid/unsupported message
      }
}

byte MIDI::getNextByte() {
      int i = 3;
      while ((Serial.available() < 1) && (i > 0)) { // wait for the 2nd byte if it isn't already available
            delayMicroseconds(10);
            i--;
      }
      return Serial.read();
}

void MIDI::clearMessage() {
      msg.status = 0;
      msg.data1 = 0;
      msg.data2 = 0;
}

I'm using version 0015 and experienced the same problem with v0013.

Great thanks in advance.
4  Forum 2005-2010 (read only) / Interfacing / Re: works: MIDI-IN: code + schematics on: April 04, 2009, 11:59:33 am
Giorgio,

You might want to try adapting the code to your needs. If you find it hard to understand you might want to do some more research on programming.
Basically all you need to do is add some vars in the top part for the additional leds.

Code:
if (dat1 > 19 && dat1 < 23) {
        digitalWrite(ledPC, HIGH);
        delay(50);
        digitalWrite(ledPC, LOW); // forgot this last time
      }

This part finds out what the PC value is, you might want to change this to more if statements so that you can turn on or turn off the led of your choice.
5  Forum 2005-2010 (read only) / Interfacing / Re: works: MIDI-IN: code + schematics on: April 01, 2009, 07:51:39 pm
Quote
Can anyone help me with the code for simply reading 3 (20,21,22) program change and 1 control change (36) and simply activate 1 led for each program change and 1 led for the control change?

The following might work for you.

Code:
#include <MIDI.h>

byte ledPC = 11;
byte ledCC = 12;
byte channel = 1;

void setup() {
  pinMode(ledPC, OUTPUT);
  pinMode(ledCC, OUTPUT);
  MIDI.begin();
  MIDI.useExternalPowerPin();
}

void loop() {
  if (MIDI.read(channel)) {
    if (MIDI.getType() == PC) {
      byte dat1 = MIDI.getData1();
      if (dat1 > 19 && dat1 < 23) {
        digitalWrite(ledPC, HIGH);
        delay(50);
      }
    }
    else if (MIDI.getType() == CC) {
      if (MIDI.getData1() == 36) {
        digitalWrite(ledCC, HIGH);
        delay(50);
      }
    }
  }
}

Edit: You might want to download the MIDI library from the playground first smiley-wink
6  Forum 2005-2010 (read only) / Interfacing / Re: works: MIDI-IN: code + schematics on: March 26, 2009, 05:55:33 pm
this will also work without the 100k resistor btw
7  Forum 2005-2010 (read only) / Interfacing / Re: works: MIDI-IN: code + schematics on: March 26, 2009, 01:56:50 pm
8  Forum 2005-2010 (read only) / Interfacing / Re: works: MIDI-IN: code + schematics on: March 26, 2009, 01:56:42 pm
I just got MIDI-IN working with the CNY17-2 optocoupler. I used the MIDI library from the arduino playground to make the led on pin 13 flash on receiving a MIDI message. You can find the modified scheme below.
Pages: [1]