Skip to content

Commit a4c68b3

Browse files
author
falkTX
committed
Initial commit
0 parents  commit a4c68b3

File tree

14 files changed

+6343
-0
lines changed

14 files changed

+6343
-0
lines changed

Makefile

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
all:
2+
gcc src/ttymidi.c -o ttymidi -lasound
3+
clean:
4+
rm ttymidi
5+
install:
6+
install -m 0755 ttymidi /usr/local/bin
7+
uninstall:
8+
rm /usr/local/bin/ttymidi

README

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
ttyMIDI is a GPL-licensed program that allows external serial devices to
2+
interface with the ALSA sequencer.
3+
4+
5+
COMPILATION
6+
7+
The ttyMIDI source code is comprised of a single C file. To compile it, just
8+
run the following command:
9+
10+
make
11+
12+
This program depends on libasound2, so you should have the development headers
13+
for that installed. In Debian or Ubuntu, you can install it by running:
14+
15+
apt-get install libasound2-dev
16+
17+
After you compile ttyMIDI, you may wish to copy it to /usr/bin for easy
18+
access. This can be done simply by following command:
19+
20+
sudo make install
21+
22+
USAGE
23+
24+
First, you need an external device that can send MIDI commands through the
25+
serial port. To find out more about programming an external device, read the
26+
TTYMIDI SPECIFICATION section. If you are using an Arduino board
27+
(http://www.arduino.cc), read the instructions under the arduino folder. Once
28+
your device is programmed and connected to your PC's serial port, follow the
29+
instructions below.
30+
31+
To connect to ttyS0 at 2400bps:
32+
33+
ttymidi -s /dev/ttyS0 -b 2400
34+
35+
To connect to ttyUSB port at default speed (115200bps) and display information
36+
about incoming MIDI events:
37+
38+
ttymidi -s /dev/ttyUSB0 -v
39+
40+
ttyMIDI creates an ALSA MIDI output port that can be interfaced to any
41+
compatible program. This is done in the following manner:
42+
43+
ttymidi -s /dev/ttyUSB0 & # start ttyMIDI
44+
timidity -iA & # start some ALSA compatible MIDI program
45+
aconnect -i # list available MIDI input clients
46+
aconnect -o # list available MIDI output clients
47+
aconnect 128:0 129:0 # where 128 and 129 are the client numbers for
48+
# ttyMIDI and timidity
49+
50+
Further, ttyMIDI creates an ALSA MIDI input port that feeds incoming MIDI events
51+
back to the serial port. Before better documentation exists, check the header file of
52+
the ardumidi library to figure out how to read this data at the Arduino end.
53+
54+
If you would like to use a GUI to connect your MIDI clients, there are many
55+
available. One of my favorites is qjackctl.
56+
57+
58+
TTYMIDI SPECIFICATION
59+
60+
The message format expected by ttyMIDI is based on what I could gather about the
61+
MIDI specification online. I tried to make it as similar as possible to the
62+
specification, but some differences exist. The good news is that as long as you
63+
follow the specification described below, everything should work.
64+
65+
Every MIDI command is sent through the serial port as 3 bytes. The first byte
66+
contains the command type and channel. After that, 2 parameter bytes are
67+
transmitted. To simplify the decoding process, ttyMIDI does not support
68+
"running status", and it also forces every command into 3 bytes. So even
69+
commands which only have 1 parameter must transmit byte #3 (transmitting a 0 in
70+
this case). This is described in more details in the table below:
71+
72+
byte1 byte2 byte3 Command name
73+
74+
0x80-0x8F Key # (0-127) Off Velocity (0-127) Note OFF
75+
0x90-0x90 Key # (0-127) On Velocity (0-127) Note ON
76+
0xA0-0xA0 Key # (0-127) Pressure (0-127) Poly Key Pressure
77+
0xB0-0xB0 Control # (0-127) Control Value (0-127) Control Change
78+
0xC0-0xC0 Program # (0-127) Not Used (send 0) Program Change
79+
0xD0-0xD0 Pressure Value (0-127) Not Used (send 0) Mono Key Pressure (Channel Pressure)
80+
0xE0-0xE0 Range LSB (0-127) Range MSB (0-127) Pitch Bend
81+
82+
Not implemented:
83+
0xF0-0xF0 Manufacturer's ID Model ID System
84+
85+
Byte #1 is given as COMMAND + CHANNEL. So, for example, 0xE3 is the Pitch Bend
86+
command (0xE0) for channel 4 (0x03).
87+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#include <MIDI.h>
2+
/*
3+
This example is a modified version of Basic I/O MIDI tutorial
4+
by Franky. It tries to demonstrate how to use Arduino MIDI
5+
library together with ttyMIDI. You will need to install
6+
Arduino MIDI library for this to work:
7+
8+
http://www.arduino.cc/playground/Main/MIDILibrary
9+
10+
All example patches shipped with the Arduino MIDI library
11+
will work with ttyMIDI with same change (if they wont, please
12+
report a bug).
13+
14+
*/
15+
16+
#define LED 13 // LED pin on Arduino board
17+
18+
void setup() {
19+
pinMode(LED, OUTPUT);
20+
MIDI.begin(4); // Launch MIDI with default options
21+
// input channel is set to 4
22+
23+
/* Now the problem is that serial port at the computer is only
24+
able to read serial data at 'standard' baud rates. MIDI baud rate
25+
that Arduino MIDI library is using, is not one of these.
26+
One way of fixing this is to edit line 54 of file MIDI.h and set
27+
Arduino MIDI library to use some other baud rate.
28+
29+
However, one can just simply change the baud rate
30+
of serial line to some standard baud rate by calling Serial.begin(int)
31+
immediately after calling MIDI.begin(int). Here we set the speed
32+
to default baud rate of ttymidi, 115200! This is all you need to
33+
remember to do if you want to read the data with ttymidi running
34+
on your computer.
35+
*/
36+
Serial.begin(115200);
37+
}
38+
39+
void loop() {
40+
if (MIDI.read()) {
41+
digitalWrite(LED,HIGH); // Blink the LED
42+
MIDI.sendNoteOn(42,127,1); // Send a Note (pitch 42, velo 127 on channel 1)
43+
delay(1000); // Wait for a second
44+
MIDI.sendNoteOff(42,0,1); // Stop the note
45+
digitalWrite(LED,LOW);
46+
}
47+
}

arduino/README

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
NOTE that ardumidi library is becoming obsolete, but will still be present
2+
in our distribution package as an example how to communicate with ttymidi at
3+
computer end. For those of you who are not interested in such an excursion,
4+
we advice downloading Arduino MIDI library, which is now (almost (read further))
5+
compatible with ttymidi:
6+
7+
http://www.arduino.cc/playground/Main/MIDILibrary
8+
9+
When using MIDI library, please check our example patch as there is one small
10+
detail that you have to remember when using MIDI library together with
11+
ttymidi (you have to call Serial.begin(115200) after MIDI.begin(int) command.
12+
You can copy the example patch demonstrating this like so:
13+
14+
cp -r MIDI /path/to/arduino/sketchbook/libraries/
15+
16+
You should install MIDILibrary before doing this. Example patch will appear
17+
to examples dialog of Arduino IDE.
18+
19+
If you still want to install the Arduino ttymidi library (which I so aptly
20+
named "ardumidi"), just copy the ttymidi folder into the Arduino libraries folder:
21+
22+
cp -r ardumidi /path/to/arduino/sketchbook/libraries/
23+
24+
This library comes with example sketches. Please take
25+
a look at them, as they contains information on how to use the library.

arduino/ardumidi/ardumidi.cpp

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
This file is part of ttymidi.
3+
4+
ttymidi is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation, either version 3 of the License, or
7+
(at your option) any later version.
8+
9+
ttymidi is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU General Public License for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with ttymidi. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
// file version 0.60
18+
19+
#include "WProgram.h"
20+
#include "HardwareSerial.h"
21+
#include "ardumidi.h"
22+
23+
void midi_note_off(byte channel, byte key, byte velocity)
24+
{
25+
midi_command(0x80, channel, key, velocity);
26+
}
27+
28+
void midi_note_on(byte channel, byte key, byte velocity)
29+
{
30+
midi_command(0x90, channel, key, velocity);
31+
}
32+
33+
void midi_key_pressure(byte channel, byte key, byte value)
34+
{
35+
midi_command(0xA0, channel, key, value);
36+
}
37+
38+
void midi_controller_change(byte channel, byte control, byte value)
39+
{
40+
midi_command(0xB0, channel, control, value);
41+
}
42+
43+
void midi_program_change(byte channel, byte program)
44+
{
45+
midi_command_short(0xC0, channel, program);
46+
}
47+
48+
void midi_channel_pressure(byte channel, byte value)
49+
{
50+
midi_command_short(0xD0, channel, value);
51+
}
52+
53+
void midi_pitch_bend(byte channel, int value)
54+
{
55+
midi_command(0xE0, channel, value & 0x7F, value >> 7);
56+
}
57+
58+
void midi_command(byte command, byte channel, byte param1, byte param2)
59+
{
60+
Serial.print(command | (channel & 0x0F), BYTE);
61+
Serial.print(param1 & 0x7F, BYTE);
62+
Serial.print(param2 & 0x7F, BYTE);
63+
}
64+
65+
void midi_command_short(byte command, byte channel, byte param1)
66+
{
67+
Serial.print(command | (channel & 0x0F), BYTE);
68+
Serial.print(param1 & 0x7F, BYTE);
69+
}
70+
71+
void midi_print(char* msg, int len)
72+
{
73+
Serial.print(0xFF, BYTE);
74+
Serial.print(0x00, BYTE);
75+
Serial.print(0x00, BYTE);
76+
Serial.print(len , BYTE);
77+
Serial.print(msg);
78+
}
79+
80+
void midi_comment(char* msg)
81+
{
82+
int len = 0;
83+
char* ptr = msg;
84+
while (*ptr++) len++;
85+
midi_print(msg, len);
86+
}
87+
88+
int midi_message_available() {
89+
/*
90+
This bit will check that next bytes to be read would actually
91+
have the midi status bit. If not it will remove uncorrect bytes
92+
from internal buffer
93+
*/
94+
while ((Serial.available() > 0) && ((Serial.peek() & B10000000) != 0x80)) {
95+
Serial.read();
96+
}
97+
98+
/* Well we don't exactly know how many commands there might be in the Serial buffer
99+
so we'll just guess it according the type of message that happens to be waiting
100+
in the buffer. At least we get first one right! */
101+
byte command = Serial.peek() & 11110000;
102+
if (command != MIDI_PROGRAM_CHANGE && command != MIDI_CHANNEL_PRESSURE) {
103+
return (Serial.available()/2);
104+
}
105+
return (Serial.available()/3);
106+
}
107+
108+
MidiMessage read_midi_message() {
109+
MidiMessage message;
110+
byte midi_status = Serial.read();
111+
message.command = (midi_status & B11110000);
112+
message.channel = (midi_status & B00001111);
113+
message.param1 = Serial.read();
114+
if (message.command != MIDI_PROGRAM_CHANGE && message.command != MIDI_CHANNEL_PRESSURE) {
115+
message.param2 = Serial.read();
116+
}
117+
return message;
118+
}
119+
120+
int get_pitch_bend(MidiMessage m) {
121+
return (m.param1 & 0x7F) + ((m.param2 & 0x7F) << 7);
122+
}
123+

arduino/ardumidi/ardumidi.h

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
This file is part of ttymidi.
3+
4+
ttymidi is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation, either version 3 of the License, or
7+
(at your option) any later version.
8+
9+
ttymidi is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU General Public License for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with ttymidi. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
// file version 0.60
18+
19+
#ifndef ardumidi_h
20+
#define ardumidi_h
21+
22+
#include "WProgram.h"
23+
24+
// MIDI notes
25+
#define MIDI_C0 0
26+
#define MIDI_D0 2
27+
#define MIDI_E0 4
28+
#define MIDI_F0 5
29+
#define MIDI_G0 7
30+
#define MIDI_A0 9
31+
#define MIDI_B0 11
32+
#define MIDI_C 60
33+
#define MIDI_D 62
34+
#define MIDI_E 64
35+
#define MIDI_F 65
36+
#define MIDI_G 67
37+
#define MIDI_A 69
38+
#define MIDI_B 71
39+
#define MIDI_SHARP 1
40+
#define MIDI_FLAT -1
41+
#define MIDI_OCTAVE 12
42+
43+
// MIDI out
44+
#define MIDI_NOTE_OFF 0x80
45+
#define MIDI_NOTE_ON 0x90
46+
#define MIDI_PRESSURE 0xA0
47+
#define MIDI_CONTROLLER_CHANGE 0xB0
48+
#define MIDI_PROGRAM_CHANGE 0xC0
49+
#define MIDI_CHANNEL_PRESSURE 0xD0
50+
#define MIDI_PITCH_BEND 0xE0
51+
52+
struct MidiMessage {
53+
byte command;
54+
byte channel;
55+
byte param1;
56+
byte param2;
57+
};
58+
59+
// MIDI in
60+
void midi_note_off(byte channel, byte key, byte velocity);
61+
void midi_note_on(byte channel, byte key, byte velocity);
62+
void midi_key_pressure(byte channel, byte key, byte value);
63+
void midi_controller_change(byte channel, byte control, byte value);
64+
void midi_program_change(byte channel, byte program);
65+
void midi_channel_pressure(byte channel, byte value);
66+
void midi_pitch_bend(byte channel, int value);
67+
void midi_command(byte command, byte channel, byte param1, byte param2);
68+
void midi_command_short(byte command, byte channel, byte param1);
69+
70+
// MIDI out
71+
int midi_message_available();
72+
MidiMessage read_midi_message();
73+
int get_pitch_bend(MidiMessage msg);
74+
75+
// Other
76+
void midi_print(char* msg, int len);
77+
void midi_comment(char* msg);
78+
79+
#endif

0 commit comments

Comments
 (0)