Skip to content

Commit

Permalink
add I2M.MUTE/SOLO; flag for multiple usb out
Browse files Browse the repository at this point in the history
  • Loading branch information
attowatt committed May 7, 2023
1 parent 985b377 commit 00ccd5a
Show file tree
Hide file tree
Showing 8 changed files with 242 additions and 92 deletions.
58 changes: 42 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ Caution: Do not connect power from the modular and the default USB port of the T
| | [I2M.REP repetitions](#i2mrep) | | [I2M.REP# channel repetitions](#i2mrep-1) | Set note repetition |
| get | [I2M.RAT](#i2mrat) | | [I2M.RAT# channel](#i2mrat-1) | Get note ratcheting |
| | [I2M.RAT ratchets](#i2mrat) | | [I2M.RAT# channel ratchets](#i2mrat-1) | Set note ratcheting |
| | [I2M.MUTE on/off](#i2mmute) | | [I2M.MUTE# channel on/off](i2mmute-1) | Set channel mute state |
| | [I2M.SOLO on/off](#i2msolo) | | [I2M.SOLO# channel on/off](i2msolo-2) | Set channel solo state |
| | [I2M.NOTE note velocity](#i2mnote) | I2M.N | [I2M.N# channel note velocity](#i2mn) | Send Note On |
| | [I2M.NOTE.O note](#i2mnoteo) | I2M.NO | [I2M.NO# channel note](#i2mno) | Send Note Off |
| | [I2M.NT note velocity duration](#i2mnt) | | [I2M.NT# channel note velocity dur](#i2mnt-1) | Send Note On with duration |
Expand Down Expand Up @@ -285,6 +287,27 @@ Get current ratcheting / Set ratcheting of MIDI notes to `x` ratchets (1..127) f

Get current ratcheting / Set ratcheting of MIDI notes to `x` ratchets (1..127) for channel `ch` (0..32). Set `x = 1` for no ratcheting. Default is `x = 1`. Use `ch = 0` to set for all channels.

#### I2M.MUTE
`I2M.MUTE x`

Set mute state of current MIDI channel to `x`. If `x = 1` all outoing MIDI messages on that channel are muted. Default is `x = 0`.

#### I2M.MUTE#
`I2M.MUTE# ch x`

Set mute state of MIDI channel `ch` to `x`. If `x = 1` all outoing MIDI messages on that channel are muted. Default is `x = 0`. Use `ch = 0` to set for all channels.

#### I2M.SOLO
`I2M.SOLO x`

Set solo state of current MIDI channel to `x`. If `x = 1` all outoing MIDI messages on that channel are solod. Default is `x = 0`.

#### I2M.SOLO#
`I2M.SOLO x`

Set solo state of MIDI channel `ch` to `x`. If `x = 1` all outoing MIDI messages on that channel are solod. Default is `x = 0`. Use `ch = 0` to set for all channels.


---

### MIDI out: Notes
Expand Down Expand Up @@ -1070,17 +1093,17 @@ Ground | → Sleeve | → MIDI Pin 2
- Unzip the files and open `firmware/i2c2midi_firmware/i2c2midi_firmware.ino` with [Teensyduino](https://www.pjrc.com/teensy/td_download.html).
- Depending on your hardware, change the following settings:
- For MKI / Teensy 3.2:
- Set line 36 to `//#define MK2`
- Set line 52 to `#define TEENSY3X`
- Set line 53 to `//#define TEENSY41 `
- Set line 37 to `//#define MK2`
- Set line 40 to `#define TEENSY3X`
- Set line 41 to `//#define TEENSY41 `
- For MKII / Teensy 3.6:
- Set line 36 to `#define MK2`
- Set line 52 to `#define TEENSY3X`
- Set line 53 to `//#define TEENSY41 `
- Set line 37 to `#define MK2`
- Set line 40 to `#define TEENSY3X`
- Set line 41 to `//#define TEENSY41 `
- For MKII / Teensy 4.1:
- Set line 36 to `#define MK2`
- Set line 52 to `//#define TEENSY3X`
- Set line 53 to `#define TEENSY41 `
- Set line 37 to `#define MK2`
- Set line 40 to `//#define TEENSY3X`
- Set line 41 to `#define TEENSY41 `
- Make sure to install all necessary libraries (see list of libraries below). [More info on how to install libraries](https://docs.arduino.cc/software/ide-v1/tutorials/installing-libraries).
- Connect the Teensy to your computer with a USB cable. Caution: Don't connect the module to Euro power and USB at the same time!
- Under `Tools`:
Expand All @@ -1093,15 +1116,18 @@ Ground | → Sleeve | → MIDI Pin 2

### Changelog

- Version 5.0.0 (works with Teletype Firmware `5.0.0 BETA 1` [Link](https://llllllll.co/t/teletype-5-0-0-beta-testing/62210))
- New OP `I2M.MUTE` / `I2M.MUTE#`: Get/Set mute state of MIDI channel
- New OP `I2M.SOLO` / `I2M.SOLO#`: Get/Set solo state of MIDI channel
- Version 4.4.1 (+ Teletype Firmware `I2M BETA 3.1`)
- Bugfix: Chord 1 could not be set as a scale
- Version 4.4 (+ Teletype Firmware `I2M BETA 3.1`)
- Version 4.4.0 (+ Teletype Firmware `I2M BETA 3.1`)
- New OP `I2M.C.QN`: Get the transformed chord note at index
- New OP `I2M.C.QV`: Get the transformed chord note velocity at index
- Version 4.3 (+ Teletype Firmware `I2M BETA 3`)
- Version 4.3.0 (+ Teletype Firmware `I2M BETA 3`)
- New looping MIDI buffer / MIDI recorder feature, with new OPs: `I2M.B.R`, `I2M.B.L`, `I2M.B.START`, `I2M.B.END`, `I2M.B.DIR`, `I2M.B.SPE`, `I2M.B.FB`, `I2M.B.NSHIFT`, `I2M.B.VSHIFT`, `I2M.B.TSHIFT`, `I2M.B.NOFF`, `I2M.B.VOFF`, `I2M.B.TOFF`, `I2M.B.CLR`, `I2M.B.MODE`
- New OP `I2M.C.DIR`: Set a play direction for a chord
- Version 4.2 (+ Teletype Firmware `I2M BETA 2`)
- Version 4.2.0 (+ Teletype Firmware `I2M BETA 2`)
- New channel-specific OP variants for most of the existing OPs
- New OP `I2M.NT`: Send a note with specific duration
- New OP `I2M.C.B`: Define chord using reverse binary notation (`R...`)
Expand All @@ -1117,15 +1143,15 @@ Ground | → Sleeve | → MIDI Pin 2
- _BREAKING_: New modes for `I2M.MIN` and `I2M.MAX`: Ignore notes, clamp notes, fold back notes by one octave, fold back notes by multiple octaves
- _BREAKING_: Removed getter OPs for `I2M.MIN`, `I2M.MAX`, `I2M.C.ROT`, `I2M.C.INV`, `I2M.C.STR` because OPs have multiple parameters
- _BREAKING_: Removed `I2M.NC`, `I2M.NOC`, `I2M.CCC`, `I2M.CCVC`; replaced by channel-specific OP variants
- Version 4.1
- Version 4.1.0
- Experimental support for Teensy 4.1
- Version 4.0 (+ Teletype Firmware `I2M BETA 1`) ([more info](https://llllllll.co/t/i2c2midi-a-diy-module-that-translates-i2c-to-midi/40950/229))
- Version 4.0.0 (+ Teletype Firmware `I2M BETA 1`) ([more info](https://llllllll.co/t/i2c2midi-a-diy-module-that-translates-i2c-to-midi/40950/229))
- Completely rewritten firmware with support for i2c2midi's dedicated Teletype OPs (`I2M`).
- Updated README.
- Version 3.1
- Version 3.1.0
- Added feature flag to use i2c2midi as USB device, using the Teensy Micro USB jack.
- Fixed a bug where unknown I2C request messages would freeze the I2C bus.
- Version 3.0 (MKII)
- Version 3.0.0 (MKII)
- Firmware for i2c2midi hardware MKII, adding USB Host functionality.


Expand Down
75 changes: 46 additions & 29 deletions firmware/i2c2midi_firmware/i2c2midi_firmware.ino
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
I2C2MIDI MK2
– Firmware v4_4_1
– Firmware v5_0_0
https://github.com/attowatt/i2c2midi
-------------------------------------------------------------------------------------------
Copyright (c) 2022 attowatt (http://www.attowatt.com)
Copyright (c) 2023 attowatt (http://www.attowatt.com)
MIT License
Expand All @@ -32,25 +32,30 @@
-------------------------------------------------------------------------------------------
*/


// Turn on MK2 features
#define MK2
#define MK2

// Set Teensy model (Teensy 3.x vs. Teensy 4.1)
#define TEENSY3X
//#define TEENSY41

// USB Device
// i2c2midi can also act as a USB device and send MIDI data over the Teensy Micro USB jack to a host (e.g. a computer).
// Please note: Do not connect Teensy USB and Euro Power at the same time! Please cut the 5V pads on the Teensy!
// Select Tools -> USB Type "MIDI" in Teensyduino, and uncomment the next line to turn the MIDI device feature on:
//#define USB_DEVICE
// i2c2midi can also act as a USB device and send MIDI data over the Teensy Micro USB jack to a host (e.g. a computer).
// Please note: Do not connect Teensy USB and Euro Power at the same time! Please cut the 5V pads on the Teensy!
// Select Tools -> USB Type "MIDI" in Teensyduino, and uncomment the next line to turn the MIDI device feature on:
// #define USB_DEVICE

// Turn on debugging mode
//#define DEBUG
// Debug Mode
// Turn on debug mode to plot some debug message to the Serial Monitor
//#define DEBUG

// Turn on testing mode
// Sending Channel 1, note 60, velocity 127
//#define TEST
// Sending: channel 1, random note between 50 and 70, velocity 127
//#define TEST

// Set Teensy model (Teensy 3.x vs. Teensy 4.1)
#define TEENSY3X
//#define TEENSY41
// Experimental feature enabling multiple devices for USB MIDI out
//#define MULTIPLEUSBOUT


// -------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -92,13 +97,18 @@


// USB Host
// The front panel USB jack ...
// ... receives data from MIDI controllers (MIDI in)
// ... sends out MIDI data to devices (MIDI out)
// The front panel USB jack ...
// ... receives data from MIDI controllers (MIDI in)
// ... sends out MIDI data to devices (MIDI out)
#ifdef MK2
USBHost myusb;
USBHub hub1(myusb); // USB host: MIDI in
MIDIDevice_BigBuffer midiDevice(myusb); // USB host: MIDI out
#ifdef MULTIPLEUSBOUT
USBHub hub2(myusb);
MIDIDevice_BigBuffer midiDevice2(myusb);
MIDIDevice_BigBuffer* midiDeviceList[2] = { 0 };
#endif
#endif

// I2C
Expand All @@ -109,27 +119,29 @@ void i2cReceiveEvent(size_t count); // function for receiving I2C messages, coun
void i2cRequestEvent(void); // function for receiving I2C messages, count = number of bites

// I2C Address
// i2c2midi acts as a I2C follower and listens to messages on address 0x3F (63).
// To use Teletype's distingEX OPs, change the address back to 0x42.
// i2c2midi acts as a I2C follower and listens to messages on address 0x3F (63).
const uint8_t i2cAddress = 0x3F; // official I2C address for Teletype I2M OPs

// MIDI TRS
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);




// -------------------------------------------------------------------------------------------


// channels
#ifdef MK2
const byte channelsOut = 32; // number of MIDI channels OUT (1-16 for TRS out, 17-32 for USB out)
const byte channelsIn = 16; // number of MIDI channels IN (16 for USB in)
#else
const byte channelsOut = 16; // number of MIDI channels OUT
const byte channelsIn = 0; // number of MIDI channels IN
const byte channelsIn = 0; // number of MIDI channels IN
#endif

// channels
int channelMute[channelsOut]; // mute state for each MIDI out channel
int channelSolo[channelsOut]; // solo state for each MIDI out channel

// notes
const byte maxNotes = 8;
unsigned long notes[channelsOut][maxNotes][7];
Expand Down Expand Up @@ -273,7 +285,6 @@ unsigned long lastLEDMillis2 = 0; // last time LED 2 turned on
const byte animationSpeed = 100; // start up animation speed



// -------------------------------------------------------------------------------------------
// SETUP
// -------------------------------------------------------------------------------------------
Expand All @@ -287,7 +298,8 @@ void setup() {

// I2C
#ifdef TEENSY3X
Wire.begin(I2C_SLAVE, i2cAddress, I2C_PINS_18_19, I2C_PULLUP_EXT, 400000); // setup for slave mode, address, pins 18/19, external pullups, 400kHz
// setup for slave mode, address, pins 18/19, external pullups, 400kHz
Wire.begin(I2C_SLAVE, i2cAddress, I2C_PINS_18_19, I2C_PULLUP_EXT, 400000);
#endif
#ifdef TEENSY41
Wire.begin(i2cAddress);
Expand All @@ -297,12 +309,16 @@ void setup() {
Wire.onReceive(i2cReceiveEvent); // register i2c events
Wire.onRequest(i2cRequestEvent);

// serial
// Serial
Serial.begin(115200);

// MIDI & USB MIDI
MIDI.begin();
#ifdef MK2
#ifdef MULTIPLEUSBOUT
midiDeviceList[0] = &midiDevice;
midiDeviceList[1] = &midiDevice2;
#endif
myusb.begin();
#endif

Expand All @@ -319,6 +335,7 @@ void setup() {
currentScale[i][j] = j;
}
}

// setup default note duration & note shift
for (int i = 0; i < channelsOut; i++) {
currentNoteDuration[i] = 100;
Expand All @@ -329,10 +346,11 @@ void setup() {
noteLowerLimit[i] = 0;
noteLowerLimit[i] = 0;
noteLimitMode[i] = 0;
channelMute[i] = 0;
channelSolo[i] = 0;
}


//start up animation
// start up animation
for (int i = 0; i < 4; i++) {
digitalWrite(led2,HIGH); delay(animationSpeed);
digitalWrite(led1,HIGH); delay(animationSpeed);
Expand All @@ -344,7 +362,6 @@ void setup() {
Serial.println("started");
#endif


}


Expand Down Expand Up @@ -447,4 +464,4 @@ void loop() {
TESTFunction(); // function for testing
#endif

}
}
11 changes: 0 additions & 11 deletions firmware/i2c2midi_firmware/midiBuffer.ino
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,6 @@ void checkBuffer() {
fixedOffset2 = bufferSpeed / 100.;
}
}

#ifdef DEBUG
int lastPosition = bufferFrame;
#endif

if (bufferElapsedMicros >= bufferSpeed * 10) { // default bufferSpeed of 100 * 10 = 1000, so 1 bufferframe per millisecond

Expand Down Expand Up @@ -71,13 +67,6 @@ void checkBuffer() {
bufferElapsedMicros = bufferElapsedMicros - bufferSpeed * 10; // reset the timer
}

#ifdef DEBUG
if (bufferFrame != lastPosition) {
Serial.print(bufferRoundCount); Serial.print(" : ");
Serial.println(bufferFrame);
}
#endif

for (int i = 0; i < maxBuffer; i++) { // go through the MIDI buffer
if (buffer[i][2]) { // check if there is a note to be played
if (bufferRoundCount != buffer[i][5]) { // check if note has been played already in this round
Expand Down
25 changes: 23 additions & 2 deletions firmware/i2c2midi_firmware/midiCCs.ino
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ void handleRamp(int channel, int controller, int value, int slewTime, bool type)

// function for updating ramps
void updateRamps() {
for (int i = 0; i < maxRamps; i++) { // go through all ramps
for (int i = 0; i < maxRamps; i++) { // go through all ramps
if (myRamps[i].isRunning()) { // check if the ramp is running
int currentValue = myRamps[i].update(); // update the ramp
//int currentValueScaled = scaleDown(currentValue); // scale the value down from 14 bit to 0..127
Expand Down Expand Up @@ -125,14 +125,35 @@ int scaleDown (int value) {

// function for sending MIDI CC
void sendMidiCC(int channel, int controller, int value) {

// check channel mute
if (channelMute[channel] == 1 && channelSolo[channel] != 1) return;

// check channel solo
int solo = 0;
for(int i = 0; i < channelsOut; i++)
{
solo = solo + channelSolo[i];
}
if (solo > 0 && channelSolo[channel] != 1) return;


if (isTRS(channel)) {
MIDI.sendControlChange(controller, value, channel+1);
#ifdef USB_DEVICE
usbMIDI.sendControlChange(controller, value, channel+1);
#endif
} else {
#ifdef MK2
midiDevice.sendControlChange(controller, value, channel+1-16);
#ifdef MULTIPLEUSBOUT
for (int i = 0; i < 2; i++) {
if (* midiDeviceList[i] && channel == i+16) {
midiDeviceList[i]->sendControlChange(controller, value, i+1);
}
}
#else
midiDevice.sendControlChange(controller, value, channel+1-16);
#endif
#endif
}
blinkLED(1);
Expand Down
Loading

0 comments on commit 00ccd5a

Please sign in to comment.