PDA

View Full Version : Teensy 3.1 Midi - USB Interface: 1 in+2 Out/Thru (split) + Midi Controller



sandysound
01-07-2016, 12:09 PM
Hello All,
I am a Sound Engineer and often I am required to run two Mac based sequencers in sync with each other.
I would like to make a controller to give me basic functions like "Go/Play", "Next", "Back", "Pause" and "stop" (Like a glorified old school tape machine AND maybe a pot for Master Volume control. These can be generic on/off Midi commands or MMC commands).
So thats 5 buttons and a Slider/Pot. There are many tutorials on how to do this with the Teensy, but I would also like to incorporate some other functions which would be very useful to me.
A MIDI in (So I can use the device as a stand alone Midi - USB converter when I need it)
2 x MIDI Out (Again so I can use it as a USB-MIDI device PLUS send the Controller side of it out PLUS act as a MIDI Thru port from the MIDI in AND an output from the USB MIDI.
I plan on adding a 5V power in (so would cut the tracer from USB + Pads on the Teensy so that all devices get their needs met in the chain: the Teensy and 2 x MIDI devices).
Phew.
Do you think that is possible with just the Teensy? I have found MIDI controller tutorials and Midi to USB tutorials using the Teensy, and MIDI splitter tutorials (without the teensy) but am unsure of how to combine them all.
And how many Buttons/sliders would I be able to have on my controller after allowing for the other ins/outs? I would probably just max it out for future uses.
It would be fantastic for me to have one box that does it all and is flexible in its uses rather than doing everything independently - It creates so much clutter having a controller and then a cable to a splitter and then a USB interface... I would rather have it all in one compact box!

Regards,

Sandy

sandysound
01-07-2016, 10:41 PM
Ok, This has taken me all day to draw! Well, not to draw, but to find a program to use and figure out how to use it!
I have used the analogue ins for the buttons but I believe these could be bumped to the digital side? Its just the Pots and Faders that need to be on the Analogue side?
And as for the rest of the circuit - will it work?!
I am not circuit savvy but have looked at the midi specification to see how to do a MIDI-Out/Thru circuit and a MIDI In circuit... Mine differs a little because I want the Teensy to absorb all the data from the In, merge any potential data from the USB or buttons/knobs/faders and Output that to the Outputs...
Am I doing this right? Is this making sense? Or am I totally lost!
6028

I have used a sharp PC900V for an Optocoupler - as recommended by the MIDI specifications, and put a power regulator on the input for safety.
The MIDI guidelines also recommend adding some ferrite chokes on the pins to the MIDI socket- I just didnt draw them in.
And I don't know for sure if I got the Diode or the Capacitor around the right way. I also started to get confused which pin the midi should be coming out of to go to the PC900... Brain melting. Time for bed!

adrian
01-08-2016, 12:59 AM
Yes you can do this. you are totally on the right track

I didn't know that midi called for a ferrite choke!! I have successfully used this circuit (https://www.pjrc.com/teensy/td_libs_MIDI.html) (no choke). Midi thru is pretty easy and midi out hardware is really easy ... I'm not sure about running 2 midi out ports off one serial line, but seems OK (I've never done it myself) ...software merge is easy ...

As to sliders and buttons, I use 13 buttons and one motorised fader myself, outputing usb midi .... adding in your software merge is not going to be a problem ... I can give you the code.

One thing I would query is sync ... while you may be sending midi messages "at the same time", don't you need a MTC / MMC- type master to stop drift? Just starting them together is not really good enough is it??? I've not investigated that in the teensy context (cause I've never synced two sequencers ...) .... what do you need to send to keep sync / update transport speed, midi protocol wise? That could be 'tricky'???

Here is a link (https://forum.pjrc.com/threads/31708-Passing-regular-MIDI-from-host-to-host) for USB midi to serial midi .... adding in merge from buttons etc is nt going to be much of a step ...

sandysound
01-08-2016, 01:19 AM
Cool, I designed the circuit using the Teensy MIDI reference page and some diagrams (below) I found in a Document here: http://www.midi.org/techspecs/ca33.pdf
You can include ferrite beads to "improve EMI/EMC performance".
6030
6031
I think the buttons need to be on the digital pins instead of the analogue pins but thats no biggie.
Maybe I have the MIDI lines round the wrong way on the connectors - I plan on using a different TX for each MIDI output - just cause I can really. As for Sync... I don't know anything about MIDI Sync! I assume if I tell a MIDI command to leave the Teensy on TX1,2 and 3 it will happen simultaneously on each output... Am I wrong?
When it comes to Sync my main concern is usually the device receiving the MIDI and outputting the Audio (Soundcard) are slaved to a master clock using Timeclock...
Keeps the computers audio outputs sample accurate but never thought the MIDI might be transmitted at different times! Would adding a clock to the Teensy help to control that?
Your offer of code is greatly accepted!

adrian
01-08-2016, 01:51 AM
Yes buttons are on digital pins (there are lots) ... faders and pots are on analog pins ...

You are right that if you send on TX 1 2 and 3 'at the same time' the midi messages will be spat out at pretty much the same time .... I was thinking you just use tx 1 but with two midi interfaces hooked up to in parallel, so midi would be 'simultaneous'

I would have thought that the transports would drift apart even if started at exactly the same time?? BUT If you already have a clock then you should be OK ...

Might be a good thing to research though, but if you say that you already have sample accurate sync, then you should be good to go, and not need clock from the teensy (how you would do MMC / MTC from the teensy, I'm not sure ... must be doable though).

you are welcome to my code ... but you must suffer .... .... picture (s) of MY CONTROLLER!!!!

60326033

It uses the faderport protocol (which is just a bunch of specific midi messages) and includes a motorised fader ... it takes the feedback from the DAW and moves the fader to the right position .... the joystick changes track, the big buttons are transport control, and the little buttons select automation write / read modes. The wheel is track pan (just finishing the code for that right now!! It uses a 24 click encoder, and some neat lookup table tricks). Happy to share the code ....

Of course, the controller can be changed, at the press of a teensy button ...TO A MAME DEFENDER CONTROLLER!! YAY

Hijacked.

EDIT: you only need an optocoupler for midi in connected to RX... TX for serial midi out is just a couple of resistors (hence, I think its going to be pretty easy to use tx 1 only but with 2 midi output DINS ...

sandysound
01-08-2016, 02:30 AM
Heh heh cool man - thanks for the pics! Looks sweet as bro!
Ok -would I need to put a resistor on each output or just one and then split?
Here is a recent setup I created - slightly less complicated than usual! In this setup I used the Zen Studio as a master clock over ADAT as well as analog input preamp and splitter to the Motu's. It also had two Midi controllers (or keyboards generally).
Ive never thought about latency between the signals when running systems like this - Its just not been an issue. I usually check the syncing of the systems by recording the outputs of both machines and then zooming in on the wav files. It's bang on every time. I hope to achieve the same level of accuracy using the Teensy...
6034
Looking at code - I don't get how to enable the midi to be transmit over all the outputs - usb and serial 1, 2 and 3...
I'm not good at code! Lol
Here's what I have, its been collected and butchered to fit - kind of, I think!
I can see where you assign Midi Notes to the Digital pins but I don't see anything similar for the Analogue section...


/* some code designed for using the Teensy 3 as a USB MIDI controller
v1.0, December 17 2013
by Yann Seznec www.yannseznec.com

no copyright or anything, use however you want

remember to select MIDI as your USB Type in the Tools menu

this should also work with other Teensy boards, apart from the "touch" pins

things that are kind of dumb in this code:
- the touch threshold is hard coded (int touchThreshold)
- touch pins only send midi note on/off with no velocity change
- no system for sending touch pin as CC
- the CC assignments are sort of random, probably should have another array for them

*/


int const numPins = 10; // number of analog inputs
int currentVal[numPins];
int newVal[numPins];
int analogPins[] = {
14,15,16,17,18,19,20,21,22,23 // which analog pins to use
};


int const numDigPins = 7; // number of digital pins to send note values
int currentDig[numDigPins];
int digitalpin[] = {
2,3,4,5,6,11,12 // which digital pins to use for sending note values
};
int digitalpitch[] = {
48,50,51,53,55,57,58}; // which midi notes to send from the digital pins selected above
int digInput[numDigPins];


int const numDigPinsCC = 0; // number of digital pins to send CC
int currentDigcc[numDigPinsCC];
int digitalpincc[] = {
2,3,4,5,6,7,8,9,10 // which digital pins to use for sending CC
};
int digInputcc[numDigPinsCC];


int const numTouchPins = 0; // number of pins to use as touchpins, sending note values
int touch[numTouchPins];
int touchon[numTouchPins];
int touchpin[] = {
0,1,15,16,17}; // which digital pins to use as touch pins
int touchpitch[] = {
60,63,65,67,70}; // which midi notes to send from the touch pins
int touchThreshold = 2000;
int touchMax = 5000;


// the MIDI channel number to send messages
const int channel = 1;



void setup() {
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
pinMode(6, INPUT_PULLUP);
pinMode(11, INPUT_PULLUP);
pinMode(12, INPUT_PULLUP);

Serial.begin(31250);

}


// digital pins sending notes
for (int i = 0; i < numDigPins; i++) {
if (digitalRead(digitalpin[i]) == 1 && currentDig[i] == 0) {
usbMIDI.sendNoteOff(digitalpitch[i], 100, channel);
currentDig[i] = 1;
}
if (digitalRead(digitalpin[i]) == 0 && currentDig[i] == 1) {
usbMIDI.sendNoteOn(digitalpitch[i], 100, channel);
currentDig[i] = 0;
}
}

// digital pins sending CC

for (int i = 0; i < numDigPinsCC; i++) {
if (digitalRead(digitalpincc[i]) == 1 && currentDigcc[i] == 0) {
usbMIDI.sendControlChange(i+50, 0, channel);
currentDigcc[i] = 1;
}
if (digitalRead(digitalpincc[i]) == 0 && currentDigcc[i] == 1) {
usbMIDI.sendControlChange(i+50, 127, channel);
currentDigcc[i] = 0;
}
}

// analog pins

for (int i = 0; i < numPins; i++) {

newVal[i] = analogRead(analogPins[i]);

if (abs(newVal[i] - currentVal[i])>3) {
usbMIDI.sendControlChange(i+1, newVal[i]>>3, channel);
currentVal[i] = newVal[i];
}
}

// i think if you remove these last two lines everything breaks and things are sad and people cry
while (usbMIDI.read()); // read and discard any incoming MIDI messages
delay(25);
}






And thanks to yourself I have this in another tab:


#include <MIDI.h>;
int chnl,d1,d2,dd;
kMIDIType type;
void setup() {

Serial.begin(31250);

}

void loop() {
if (MIDI.read() && MIDI.getType() < SystemExclusive) {
type = MIDI.getType();
d1 = MIDI.getData1();
d2 = MIDI.getData2();
dd = d1 + (d2 << 8);
chnl = MIDI.getChannel();
// and then send...
switch(type){
case NoteOn:
usbMIDI.sendNoteOn(d1,d2,chnl);
break;
case NoteOff:
usbMIDI.sendNoteOff(d1,d2,chnl);
break;
case AfterTouchPoly:
usbMIDI.sendPolyPressure(d1,d2,chnl);
break;
case ControlChange:
usbMIDI.sendControlChange(d1,d2,chnl);
break;
case ProgramChange:
usbMIDI.sendProgramChange(dd,chnl);
break;
case AfterTouchChannel:
usbMIDI.sendAfterTouch(dd,chnl);
break;
case PitchBend:

usbMIDI.sendPitchBend(dd,chnl);
break;
case SystemExclusive:
// handle sysex
break;
default:
// F8 et seq.
break;
}
}
if (usbMIDI.read() && usbMIDI.getType() < SystemExclusive) {
type = (kMIDIType) usbMIDI.getType();
d1 = usbMIDI.getData1();
d2 = usbMIDI.getData2();

chnl = usbMIDI.getChannel();
// and then send...
MIDI.send(type,d1,d2,chnl);
}
}

sandysound
01-08-2016, 02:49 AM
In this example, the tx is split, then individually amplified? and then the 220 resister before each output...
6035
Other circuits I have seen use an IC to make the split... I think the Teensy should be able to handle doing individual serial outputs in sync for each "thru" - I will try it first, I think it is the simplest way forward?!

adrian
01-08-2016, 03:19 AM
.....BUT Oh shit, you gonna make me think about ohms law??? I think just whack another DIN on off the back of the other one ...would make current draw an issue I suppose, but voltage and resistance should be in spec ... must be a diagram for that somewhere ...

Anyway .... happy to help with the code ...just give us a bit of a thinking time ... Note that there are code wrappers under 'advanced' for posting code .. makes it easier to read

EDIT ... I see you are looking at schematics ... because its a software split fundamentally usig a teensy I'm not sure about the diagram .... putting the same signal out of two separate ports vs analog splitting of one port is probably neither here nor there ...interesting though (someone will know the answer ...)

Back to clocking ... I get your clocking for your audio interfaces ...I used to run sync using adat (when I had an adat interface, obviously) ... What I was thinking about was then sequencer transports ... presumably on two different macs .... I guess that clocking the audio interfaces connected to the sequencers will work ok, but I am not an expert by any means when it comes to syncing sequencers ... What I am wondering is that while you have the audio packets synced up distribution wise (i.e. all the converters convert on the clock), what keeps the sequencers producing samples at the same time after initially setting them off together ... on old school tape machines, smpte was used to speed up slow down play rates .... i guess the adat master will sync the sequencers if the sequencers are set as slave ... I would have thought that mtc was the usual way to do that ( but I just don't know) ...


Here is an interesting link (http://www.kerrygalloway.com/WikiPARIS/wikka.php?wakka=ADATRMESync) about syncing reaper (a sequencer / daw) to adat

adrian
01-08-2016, 05:36 AM
What are the sequencers you are trying to sync? Can their transports be slaved to yr adat master? Or maybe one can send mtc or something to the other ??

Do you require output over usb midi and serial 'sequentially', merging with 'button data', ?? To explain .... if there is usbmidi data, it is merged with 'button data' (if any) and output to the serial ...and if there is serial data it is merged with 'button data' (if any) and output to usbmidi?

Code to come

sandysound
01-08-2016, 09:21 AM
Further to your question for clarity: forcing the output of the machines to "listen" to a WC sample rate such as 48kHz means neither machine gets ahead or behind the other as they will only release each individual audio sample as it is "told" to. The audio then comes out simultaneously. As long as the midi commands depart the controller /split they will arrive at the same time and all is well. For this purpose it is best to use the same kind of MIDI device on each machine - in my example I am using identical Motu's to handle the MIDI and Audio data so that both machines will react and behave in unison.

sandysound
01-08-2016, 10:00 AM
Here is a new circuit diagram - its getting very messy - I will have to do another one.
6037
You can now see three discreet inputs to the serial inputs of the teensy.
I have also added a 16 position rotary encoder for Midi Channel Select for the "Local" inputs (Buttons/pots/faders) - so you can choose which channel you want them to be on (Midi Ch 1-16). This is only to affect the "local" buttons/faders/pots on the box.
Plus a switch to turn only the buttons (not pots or faders - they remain CC data) from CC note on/off to MIDI Machine Control messages. Circuit open = MIDI CC data, circuit closed = MMC data.
Is that possible?
Or am I asking too much now...
The more time you give me the more I get to think about it lol.
Thanks Adrian - super appreciate your help.

sandysound
01-08-2016, 10:21 AM
Hmmm, my initial reply to your post #9 has gone missing - I must have done something by accident - I was using the phone!
But here is what it said:
Thanks again Adrain, food for thought about the split. And sorry about the code wrapping or lack of - I thought there must be a better way! I'll try to fix it.
I got thinking about maxing out the Teensy specs: if it has 3 serial ports, why not make this device a 3x3 in and out stand alone Midi Port + USB with Thru functionalty AND controller! You can thank my nap for coming up with that bright spark - would that change your code much?!
Basically I would like all incoming data to output everywhere, including Midi, serial ports and local buttons (regardless of origin so it doesn't matter which port I plug things into or out of - they all get the same signal). How that is handled exactly I don't really know - preferably as fast as possible! :-D

In regards to clocking a sequencer, it is very common to use a Master Wordclock device to slave the computers too via their Audio Interface. This is what keeps the software and hardware insync. I use Ableton Live, Liveprofessor and Q Lab primarily and within the software settings you can select which clock to use - internal or external (WC). Just like in your Reaper example.
Digital Recording studios will clock absolutely everything Digital to one Master clock such as an Apogee Big Ben.
I use them to run a main and back up playback rig for redundancy. Computers are great but can be a show stopper when they fail so clocking everything to one clock means I can switch between the two if one crashes / fails without losing my "place" in the show and we can carry on while I try to reboot the failed machine and get that back to where we are in the show.

sandysound
01-08-2016, 06:40 PM
I saw PJRC mention in another thread that only Serial 1 and 2 has FIFO - is that important? Do I need it for serial 3 or should we just focus on a 2 in 2 out instead of 3 x 3?

adrian
01-08-2016, 07:37 PM
I think FIFO is pretty necessary for what you are doing, at least without delving deep, and I think only serial1 has a big FIFO ...I think that an analog solution for splitting a single serial out line is the best way to go for your application where all of the midi outs are just the same, but I might be wrong. Or is it that you now keen on a 3x3 routing matrix?

EDIT: Actually Im not sure that you can use more than 1 serial port for serial midi at a time .... that could be a real spanner in the works ... you might need multiple teensys for multiple midi ports.

Never tried it obviously ... but someone would have thought about it.

EDIT : found this (http://little-scale.blogspot.co.nz/2009/09/multiplexing-midi-output-streams-with.html)

sandysound
01-08-2016, 08:32 PM
Copy - good read.
I'm hoping the software can do two - it just looks easier lol but I can go the analog way if need be no problem.

EDIT: I found this posted by PJRC:


Actually, both Serial1 and Serial2 on Teensy 3.1 and 3.2 have the FIFO.

On Teensy 3.0, only Serial1 had a FIFO.

None of the ports on Teensy LC have FIFOs.

EDIT: You probably saw that also seeing as you then ask about it lol sorry bro!

PaulStoffregen
01-08-2016, 11:52 PM
... only Serial 1 and 2 has FIFO - is that important?

As with so many technical features, the answer is "it depends".

MIDI's 31250 baud rate is pretty slow compared to the speed of Teensy 3.2. Without the FIFO, that's an interrupt every 320 microseconds. You can tolerate almost double that much interrupt latency before the incoming bits overwrite the buffer.

So really, the question is whether you'll be blocking serial port interrupts for that long. If you're just using the 3 serial ports, the answer is you'll almost certainly be safe. Those interrupts last only several microseconds.... nowhere near 320. The serial interrupts are at a higher priority level than USB and most others, so even if some other interrupts last a long time, the question is whether they block the serial ones.

But if you use a library like Adafruit_Neopixel which hogs the CPU with interrupts turned off, you can run into trouble. It disables interrupts for approx 30 us per LED. So around 10 LEDs and certainly by 20, it could start to cause serial data loss at MIDI baud rates.

The FIFO will let you tolerate 8X longer interrupt latency, so it makes a huge improvement, but it's not magic.

The other things FIFOs do, which probably won't matter for this project, is lower the CPU usage of the interrupts. Managing the FIFO takes a little extra work, but the 4X or more reduction in the number of interrupts greatly offsets its minor overhead. If you're doing a lot of computationally intensive stuff which has to keep real-time pace with the data, the FIFO might help a little on the CPU side. But for relatively simple MIDI protocol, the fast CPU in Teensy 3.2 will probably be more than enough even with extra overhead in the interrupts.

adrian
01-09-2016, 02:50 AM
Thankyou Paul.. How would I go about using two instances of the Midi Serial Library "per uart". In the documentation for 4.2 of the arduino midi library there is a macro defined for creating a separate instance of the library ... Here is an example (pardon me for not using code markers and not posting the whole of the code ...)

MIDI_CREATE_INSTANCE (HardwareSerial, Serial2, midi2);


When I try it I get "Serial2 is not a type" on compile ... Serial2 is an object? what is its type? (I am a C++ noob) ....or is the macro not working cause teensy is not on 4.2??

I suppose I will have to look at the source code to see how to properly institute 2 separate per uart instances of the library?>>?..

adrian
01-09-2016, 03:20 AM
OK ... stocktake ... you have your sequencers synced up using word clock magic (Hmm pretty sure wordclock is for audio distribution between digital pieces, and not transport sync ....I used to use an RME pci-e piece for adat sync, but never for transport sync ... anyway) .... So all you need is MMC to kick them off at the same time.

Here Is where I have got to ...

Two serial midi outs, using separate uarts, is on the cards. At this stage though only one serial out is programmed.

One serial in at this stage, too ... scaling the serial MIDI hardware and software is the 'trick'... its a matter of instantiating two or more library objects for each serial port .... there is this very cool example (http://arduinomidilib.fortyseveneffects.com/a00008.html), which will help with the midi thru no-end ....

An interesting thing is that supposedly thru mirroring is turned on by default in the serial midi library (v4.2).... there is a mode for it in v 3.x, but I think that it is not on by default ... will have to look at this further.

how it plays out for usb, Im not so sure ...

The 1 x 1 serial interface is mirrored with USB midi i/o, and sent with with Midi button data (selectable as either MMC or CC/random Midi) plus a fader (one only).

The selection as to MMC mode or random Midi mode is a one only choice, requiring a reset to change ... if no choice is made as to mode then nothing works .... Thats the way its programmed.

The fader is not motorized (I have taken the motor code out ... i.e.no parameter feedback, so soft takeover needed). The one I have is a capacitive touch enabled one, so when you touch it, a MIDI message is sent once, and then 10 bit CC data is send CC 0, 3 bits MSB and CC 32 7 bits LSB.

There is a rotary encoder that selects channel .... the problem with this is that there is no feedback as to what channel you have selected (maybe LEDs??? an oled?? or maybe a 16 position switch!!!)

I'm going to test this over the next couple of days (I have all the hardware!! and most of the code has already been tested, so it should just work ... it compiles atm!!!)

and get into sorting out the thru function better ...aiming for 2 x 2...






#define SWITCHES 7
#define TOUCHTHRESH 2000
#define HYST 2 //HYSTERESIS AMOUNT
#include <usb_midi.h>
#include <MIDI.h>
#include "midicontrolHACK3.h"

int myMode = 0;
const int MMC = 1;
const int MIDINOTES = 2;

static int myChannel = 1;

const byte MMCSTOP [] {240, 127, 127, 6, 1, 247};
const byte MMCPLAY [] {240, 127, 127, 6, 2, 247};
const byte MMCFFWD [] {240, 127, 127, 6, 4, 247};
const byte MMCRWD [] {240, 127, 127, 6, 5, 247};
const byte MMCPUNCHIN [] {240, 127, 127, 6, 6, 247};
const byte MMCPUNCHOUT[] {240, 127, 127, 6, 7, 247};
const byte MMCPAUSE [] {240, 127, 127, 6, 9, 247};

const byte* MMCTransport [] {MMCSTOP, MMCPLAY, MMCFFWD, MMCRWD, MMCPUNCHIN, MMCPUNCHOUT, MMCPAUSE};

const uint8_t wiperPin = A4; //read fader value analog pin
const uint8_t touchPin = 1; /// capacitive touch fader

int sendSwitchesMIDINOTES [] {19, 21, 6, 1, 5, 99, 67}; // 7 random MIDI note numbers ??? could be CC ...

const uint8_t switchesPinTable [] {15, 22, 23, 9, 10, 11, 12, 16, 17};
/*
15, 22, 23 etc ... first 7 bits of C pin register
16 and 17 are first two pins of B register for encoder
*/

static int8_t enc_states[] = {0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0};
static uint8_t old_AB = 0;

void Fader::RW() // set up for capacitive touch
{
PositionPinRead();
touchPinRead = touchRead (touchPin);
if (touchPinRead > TOUCHTHRESH)
{
if (TOUCHSENT == false) {
usbMIDI.sendPolyPressure (127, 1, 1);
TOUCHSENT = true;
}
PINWRITE();
}
else
{
if (TOUCHSENT == true) {
usbMIDI.sendPolyPressure (127, 0, 1);
TOUCHSENT = false;
}
}
}

void Fader::PositionPinRead()
{
hystPinRead = analogRead (wiperPin);
if (currentPinRead > (hystPinRead + HYST) || hystPinRead > (currentPinRead + HYST))
{
currentPinRead = hystPinRead;
}
}

void Fader::PINWRITE ()
{
sendMSB = currentPinRead >> 3;
sendLSB = currentPinRead & 0x00F;
usbMIDI.sendControlChange (0, sendMSB, 1);
//delay(1); // 500 micros is probably better here??? is it even needed??
usbMIDI.sendControlChange (32, sendLSB, 1);
}

void Switches::RW (int choice, int channel) // could be done using bounce library, and if no noteoff's required, could be structured a bit more simply maybe
{
readMSB = GPIOC_PDIR & 0x07F;
//readLSB = GPIOD_PDIR & 0x00F;
//delay(1); is this needed..?
switch (choice)
{ case MIDINOTES:
for (int i = 0; i < SWITCHES; i++)
{
if (!(readMSB & (1 << i)))
{
if (!(mask & (1 << i) ))
{
MIDI.sendSysEx (6, MMCTransport[i], false);
usbMIDI.sendSysEx (6, MMCTransport[i]);
mask |= (1 << i);
}
}
else {
if ((mask & (1 << i)))
{
mask &= ~(1 << i);
}
}
}
break;
case MMC:
for (int i = 0; i < SWITCHES; i++)
{
if (!(readMSB & (1 << i)))
{
if (!(mask & (1 << i) ))
{
usbMIDI.sendNoteOn (sendSwitchesMIDINOTES [i], 127, channel);
MIDI.sendNoteOn (sendSwitchesMIDINOTES [i], 127, channel);
mask |= (1 << i);
}
}
else {
if ((mask & (1 << i)))
{
usbMIDI.sendNoteOff (sendSwitchesMIDINOTES [i], 0, channel);
MIDI.sendNoteOff (sendSwitchesMIDINOTES [i], 0, channel);
mask &= ~(1 << i);
}
}
}
break;
}
}

void Rotary::SET_CH (int& channel)
{
old_AB <<= 2; //remember previous state
old_AB |= (GPIOB_PDIR & 0x03 ); //add current state
RotaryRead = ( enc_states[( old_AB & 0x0F )]);
if (RotaryRead > 0)
{
channel++; if (channel > 16) {
channel = 16;
}
}
else if (RotaryRead < 0)
{
channel--; if (channel < 1) {
channel = 1;
}
}

}

void setup()
{
//MIDI.begin();
//Serial.begin (31250);
for (int i = 0; i < SWITCHES + 2; i++) // + 2 for encoder pin setup
{
pinMode(switchesPinTable [i], OUTPUT);
digitalWrite (switchesPinTable [i], LOW);
delay (1);
pinMode(switchesPinTable [i], INPUT_PULLUP );
}

}

void loop()
{
do
{
if (digitalRead (11) == LOW) {
myMode = MMC;
}
else if (digitalRead (12) == LOW) {
myMode = MIDINOTES;
}
}
while ((myMode != MMC) && (myMode != MIDINOTES));
Serial.println(String(myMode));
delay(1000);
{
Switches mySwitches;
Fader myFader;
Rotary myRotary;
while (true)
{
myRotary.SET_CH (myChannel);
myFader.RW();
mySwitches.RW (myMode, myChannel);
midithru();
}
}
}

void midithru()
{
int chnl, d1, d2, dd;
kMIDIType type;
if (MIDI.read() && MIDI.getType() < SystemExclusive) {
type = MIDI.getType();
d1 = MIDI.getData1();
d2 = MIDI.getData2();
dd = d1 + (d2 << 8);
chnl = MIDI.getChannel();
// and then send...
switch (type) {
case NoteOn:
usbMIDI.sendNoteOn(d1, d2, chnl);
break;
case NoteOff:
usbMIDI.sendNoteOff(d1, d2, chnl);
break;
case AfterTouchPoly:
usbMIDI.sendPolyPressure(d1, d2, chnl);
break;
case ControlChange:
usbMIDI.sendControlChange(d1, d2, chnl);
break;
case ProgramChange:
usbMIDI.sendProgramChange(dd, chnl);
break;
case AfterTouchChannel:
usbMIDI.sendAfterTouch(dd, chnl);
break;
case PitchBend:

usbMIDI.sendPitchBend(dd, chnl);
break;
case SystemExclusive:
// handle sysex
break;
default:
// F8 et seq.
break;
}
}
if (usbMIDI.read() && usbMIDI.getType() < SystemExclusive) {
type = (kMIDIType) usbMIDI.getType();
d1 = usbMIDI.getData1();
d2 = usbMIDI.getData2();

chnl = usbMIDI.getChannel();
// and then send...
MIDI.send(type, d1, d2, chnl);
}
}




class Fader
{
public:
void PositionUSBRead ();
void PositionPinRead ();
void RW ();
void MOTOR ();
void STOP();
void PINWRITE ();

private:
uint16_t hystPinRead;
uint16_t touchPinRead;
uint16_t currentPinRead;
uint8_t sendMSB;
uint8_t sendLSB;
bool TOUCHSENT = false;
bool PINUPDATED = true;
};


class Switches
{
public:
void RW (int, int);
private:
uint16_t readMSB;
//uint8_t readLSB;
uint16_t mask = 0;
uint16_t eleven;
};

class Rotary
{
public:
void SET_CH (int&);
private:
int8_t RotaryRead;
};

sandysound
01-09-2016, 01:05 PM
Dude!
Nice!
Yes you are correct the Wordclock does not sync transport controls - but I don't think it to be an issue (until I try it and find otherwise).
I have not needed to sync transport control in the past - as long as it leaves all outputs at the same time, it should "arrive" within a reasonable tolerance.
I have ordered parts so am awaiting you test results!
And yeah I think a 16 Position switch pot was the go - am trying to keep it simple. Leds would be a nice touch but maybe in a later revision?! I can easily add those hardware styles rather than use software.
Restart for button "mode" select is fine - can it be done via a switch? The reset is a good idea - it stops one from accidentally changing it during a show...?
I am excited to see how you get on - chances of a youtube vid?!

adrian
01-09-2016, 09:17 PM
Im excited to see how you get on too. The fader bit works fine as does the encoder, and so does the MMC stuff (although I have yet to use it on my own sequencer setup (tonight maybe) ... the midi through code looks fine ... the issue is using two uarts in and out simultaneously ... willhave to do some coding ...

I've never used a 16 position switch! And when I think about it, having the ability to change channel in the middle of a session might not be that great, so maybe it needs to be an initial global setting ....

By the way, the reset I am talking about is unplugging the thing from power !!! .... If you go down a separate power supply route then you can add a switch!!

One thing, on the hardware side, I reckon it would be good to think about a pcb ... good for midi connectors, for sure, and from experience, solering lots of wires to the teensy pins and running them to buttons is a pain ...a pcb with organised headers etc seems a better idea .... there is a schematic for midi ins and outs (I have breadboarded it easy enough incl. optocoupler) ... and that brings me back to the merge split thing .... I think I have a midi in circuit breadboarded from an old product, so I will test that code too...

Don't forget a spare teensy if you are ordering parts .... I'll take some photos ....

Back to sync ... lets say you start the two transports at the same time (on different machines). You cut from one to the other after 5 minutes, I'm pretty sure that you are only lucky if they are on the same beat .....unless they are synced.

adrian
01-10-2016, 07:20 AM
So I tested the MMC code properly.. found a bug and fixed it ... now it works good ....

I updated the code post above

Mode select between MMC sysex and Midi notes (or CC evenutally) works fine, and channel select using a rotary works fine, but the lack of feedback makes it difficult to know 'what channel you are on' ... and it is easily bumped .... the rotary I have cost 4 dollars and the detents are not 'accurate' .... I could serial monitor the channel variable, but other than that I would have had no idea what channel. The slider works, spitting out 10 bit midi ... I remembered why capacitive touch is so good on faders.... when you are not touching it you don't need to read values!! great.

All this works over usb ...the next thing is to do the midi serial interfaces ... Like I said I have the hardware somewhere from another project ...but I have to work out coding for multiple serial ports (could just dispense with the midi library and 'do raw'!! whatever that may mean) ...and the mirroring thru needs to be sorted too ... there is a mirror thru function in the Midi library, just a matter of getting into it.

So ...all the easy bits are done ... on to a 2 x 2 interface with which to merge etc split etc.

I was thinking usb in from host, controller stuff, and 2 teensy serial in, all merged to the 2 teensy serial outs...

For usb out to host, I guess there is no point in mirroring back the usb in from host, so ..... controller stuff and two teensy serial ins, all merged to the usb out to host.

I found a weird hardware fault with my controller ... BOOO (I'm using pin 13 with the led on it as in input, plus register reads ... might not have got that quite right yet) .... so when I am fixing that (might be sh+t soldering??) I'll fakey up the serialMidi ins and outs,

I have a couple of spare optocouplers from an old project), and I'll get onto the midi interface code, now that the controller stuff is sorted.

I actually controlled my DAW using the MMC sysex messages.... the ffwd and rewind functions are weird, but they worked (just a strange implementation) ...punchin, play, pause stop etc ...neat.

Pictures (or it didn't happen):
60566057

sandysound
01-10-2016, 10:54 PM
Qudos man - You are on to it!
Yeah a 16 position switch is the go I reckon - and I agree, might not be particularly useful in the middle of a set but you never know!
I plan to cut the tracer from usb on the teensy and run an independent power supply - Makes things more stable - I don't like to rely on a computer powering my hardware if I can help it!
MMC can be very useful for simple operations like punch in - or stop ha ha it will be a great feature!
Have you seen MIDI Show Control? It may be more useful than MMC and also does Clock... Perhaps that will solve the sync issue you are thinking of?
Really impressed Dude - I'll be in Wellington in Feb - we should Beer.

Pensive
01-10-2016, 11:29 PM
... and it is easily bumped .... the rotary I have cost 4 dollars and the detents are not 'accurate' ....

I feel your pain. What good are detents which are not accurate? They are pointless..

I bought some adafruit ones, i need to test if they are accurate, but i'm assuming they are on top of this. Will test very soon.....

adrian
01-11-2016, 03:08 AM
Pensive.... you will never guess where I got the encoder from .....:rolleyes: i'm using a fast register read, so maybe some of that is read instability .... but the one I got is not super clicky like a good old school detented nob.

adrian
01-11-2016, 03:16 AM
Sandysound ... deuwde ... When you said "Bro" i thought you might be a kiwi!! coolio. Drop us a line fosho if you are in Wellington.

I've done some more work on the merge thing ...whew,

The answer is in v 4.2 of the Midi library .... If that runs on the teensy ok, then no worries about a 2 x 2 midi routing matrix.... if not, I'll have to hack the the current library a bit (looks like v3.2??) ... 3.2 uses a macro to select the serial port, and I don't have any idea how to vary that upon instantiating a new MIDI object ... macros are like pre processor, and I'm out of my depth .... But i reckon I can hack the library.

v4.2 uses templates which is like oh no for me, but i can paint by numbers so, if 4.2 works on teensy, NO WORRIES..... very simple, and an example even exists already of 2 x 2 merge!!

rock on.

I'll have a look at MIDI Show Control ... is that like DMX or something ....I'll look it up ...

EDIT: Show control is a bit like DMX ...

but I reckon its a bit mickey mouse ... from wikipaedia:

The first show to fully utilize the MSC specification was the Magic Kingdom Parade at Walt Disney World's Magic Kingdom in September, 1991.

snigger

sandysound
01-11-2016, 10:29 AM
Ha ha ha!
Yeah - I live in Oslo now but coming back home for some Sunshine in Feb/March!
MSC could be very useful if syncing transport controls is required?
Good Work man, I included a Teensy 3.2 in my order ;-)

adrian
01-11-2016, 06:41 PM
I'm not sure about MSC for ongoing sync. I think MTC is more usual, or maybe extracting position data from asio audio driver, even???

Anyway, good news ...I think I've cracked the 2 x 2 interface part, software wise atm, here (https://forum.pjrc.com/threads/32432-Arduino-MIDI-Library-4-2-2-x-2-Midi-Interface-thru-merge). Have do do real hardware testing.

The weather over here has been fantastic ... hope it holds for you.

sandysound
01-13-2016, 12:11 PM
Thanks man,
Thats great news!
I'm still waiting for parts sigh... How did your hardware tests go?

adrian
01-13-2016, 09:31 PM
i've tested everything apart from the 2 x 2 midi interface bit ...I'll get to it this weekend. The code looks good, and I found my breadboard with a midi in circuit on it still! incl optocoupler ... I 'll just check it over and do an output circuit ... then fire it up maybe even tomorrow.

sandysound
01-14-2016, 11:49 AM
Just realised I left off the 280 Ohm resister from my parts order. Dammit. I'll have to use something else while I order them.

adrian
01-30-2016, 03:57 AM
Hello!!

I finally got round to testing out the midithru hardware functionality ... I made a 1 x 1 midi hardware interface, and attached in and out to different serial ports ... so I sent midi in one serial port and out the other ! Plus ... up the teensy USB...

Also, it worked really well as a thru ..in the serial port and out ..etc. It worked with the interrupt-driven main controller program (I've re-written the whole thing as a library, too!!) ...

All that remains is a proper test of 'everything together' ...I need to build another hardware interface, so its 2 x 2 + USB, and stress test it, along with the rest of the controller program ... I noticed a slight bit of latencyusing 1 x 1, but really minimal!! surprised me how good in fact.... better than 50% of the data out had the same timestamp on the way back in!! Totally awesome! That's fast.

Anyway, here is the documentation, in an example.... note it uses MIDI 4.2, and if you want MAME functionality (i.e. USB keyboard), you need a custom USB type.

Happy to share the actual library (cpp and h) ... I'll finish up assembling the hardware, do a stress test, and tidy up soon ...

Promise.


//1 Rotary encoder, 1 Motorised fader (using native FaderPort protocol "FPP"), 1 Joystick (4 switches) and 9 other switches / buttons, and a 2 x 2 USB Midi interface, merger and splitter!
//3 different modes choosable on startup by button press. MODE1.MidiController MODE2.Faderport clone MODE3.MAME controller. Because MAME uses keystrokes, a cutom usb type of keyboard/midi is needed
//Obviously if you want to ditch MAME, you won't need a custom usb type
//Also MIDI 4.2 library is required.

#include <usb_midi.h>
#include <MIDI.h>
#include "myController13.h"

#define NUM_INPUT_SWITCHES 13// Number of digital switches you are using, 13 or less ...
// The digital pins used are, in order, 2, 14, 7, 8, 15, 22, 23, 18, 3, 4, 5, 11, 6.
// SO ... if you want 4 digital pins, use 2, 14, 7, and 8 (the first 4).
// The rotary encoder is on digital 16 and 17 ...
// The fader wiper in is pin A14, and the touch line is pin 19. See below for more on the fader MOTOR
/*

Switches 2 14 7 8 15 22 23 18 3 4 5 11 6

mode 1 USB MMC MMC MMC MMC MMC MMC MMC Note70 71 72 73 74 Note75
STOP PLAY FFWD RWD PCHIN PCHOUT PAUSE
midi1 "" "" "" Note70 """" Note75
midi2 "" "" "" Note70 """" Note75


mode 2 USB AfterT AfterT AfterT AfterT
FPP FPP FPP FPP ........... ............ FPP
bankL bankR ChL ChR PLAY PCH STOP RW FF REC TCH WRTE SHIFT
midi1 N/A ... N/A
midi2 N/A ... N/A


mode 3 USB DOWN UP LEFT RIGHT A B C D E
midi1 N/A ... N/A
midi2 N/A ... N/A


Encoder L R

mode 1 CH 16-1 CH 1-16 (for swiches send)
mode 2 FPP FPP
PANL PANR
mode 3 LEFT RIGHT


Fader

mode 1 10 bit messages MSB CC 00 (3bits) LSB CC 32 (7bits)
mode 2 10 bit messages MSB CC 00 (3bits) LSB CC 32 (7bits)
mode 3 N/A


MIDI RX1 TX1 RX2 TX2
Midimerger / split / thru incl USB (but USB in /out has no thru...)

RX1 to TX1, TX2, and USB
RX2 to TX1, TX2, and USB
USB to TX1 and TX2
*/

#define MOTOR
//Comment out '#define MOTOR' above if you DO NOT want to use the fader MOTOR on mode 1 and 2.
//If using the MOTOR, the pwm / speed pin is 20, and the direction pin is 21.
//The fader wiper in is pin A14, and the capacative touch line is pin 19.

#define TOUCHTHRESH 2000 // Threshold for fader capacitive touch ... the fader is assumed to have capacative touch even if the MOTOR is not used.
#define HYST 2 // Amount of hysteresis jitter suppresion for the fader. A capacitor across wiper and ground is otherwise needed.

/*In your setup, call ...
myController13.Mode (mode1 pin, mode2 pin, mode3 pin)
substituting your own pin numbers for the relevant mode
3 modes ...1.MidiController 2.Faderport clone 3.MAME controller
So ...
myController13.Mode (4,5,11)
makes pin 4 the switch for mode 1, pin 5 for mode 2, pin 11 for mode 3
Once a selection is made via the switches, there is no way to change it unless you power cycle... after selection the pins have their 'usual functions' (above)
*/

//Finally, in your loop, call myController13.Loop();

void setup()
{
myController13.Mode(4, 5, 11);
}

void loop()
{
myController13.Loop();
}

The only outstanding thing is feedback for the channel selection rotary .... I'm thinking an oled and a teensy lc (controlled by sysex of course).

sandysound
03-25-2016, 09:51 AM
Hey Bro,
Just finished the Festival - life has been on hold the last 6 weeks!
I have all the bits with me but no time to build, will have to drag it back to Norway with me to complete. Still haven't found any 280 ohm resistors - where did you get yours from? I've tried Jaycar and Surplustronics in Auckland but no joy :-(
I will try and get to Wellington sometime next week - I am in Masterton at the mo. If I get near I'll buzz you for a coffee/beer!

adrian
03-26-2016, 12:12 AM
Dude! If you make it over the hill to Wellington, it would be fun to say hi!

I was hoping to finish off my 2 x 2 / usb midi interface over easter ...I've got to mount it / connect it, and test the software yet .. here is a picture of the perf board etc. Of course I also want to get into the studio to finish a song idea I started last week ... and work is just so busy at the moment... sheesh. AND there is a cool new teensy library 'Talkie' I want to play with... hmm

6846

I have exactly 2 x 270 ohm resistors!! You can have them if you like..... but they are like 2 cents or something from farnell / element 14 online... jay car can be a bit variable as to parts, but the wellington one is surprisingly good. Anyway, rock on, bro.

sandysound
03-27-2016, 10:56 AM
Cool man, I'll keep you posted, I may be able to catch up wednesday night... We'll see how it plays out.
I have 270 Ohm resistors, but the spec asks for 280... Am I being pedantic? Maybe a 270 is best used in parallel with a 10 ohm resistor also?

adrian
03-27-2016, 10:03 PM
Keep in touch, dude.

The schematic I use (https://www.pjrc.com/teensy/td_libs_MIDI.html) says 270Ohm. And 270 vs 280 just doesn't matter, in my view ... think about using 5% tolerance parts, and well,.... for a MIDI circuit I'm sure it makes no difference....

DanieleFromItaly
05-10-2017, 07:50 PM
HI guys, for a simple midithru (serial<->usb), do I need the whole midithru() function posted in this thread or can be semplified ? A very simple "pass everything as is".

Thanks,
Daniele.

adrian
05-12-2017, 01:42 AM
Hi

midi serial to midi usb requires repackaging, transcoding if you like. here is a thread (https://forum.pjrc.com/threads/34697-Midi-usb-raw-input-question-and-possible-bug-in-usb_midi-h)with working code etc etc. for a 2 x 2 interface post 14 / 16

DanieleFromItaly
05-12-2017, 04:37 PM
Hi

midi serial to midi usb requires repackaging, transcoding if you like. here is a thread (https://forum.pjrc.com/threads/34697-Midi-usb-raw-input-question-and-possible-bug-in-usb_midi-h)with working code etc etc. for a 2 x 2 interface post 14 / 16

Ah ok, thanks !

Daniele.