Showing preview only (302K chars total). Download the full file or copy to clipboard to get everything.
Repository: trash80/Arduinoboy
Branch: master
Commit: 5bb05a905f70
Files: 18
Total size: 291.8 KB
Directory structure:
gitextract_yht0xf5z/
├── Arduinoboy/
│ ├── Arduinoboy.ino
│ ├── Led_Functions.ino
│ ├── Memory_Functions.ino
│ ├── Mode.ino
│ ├── Mode_LSDJ_Keyboard.ino
│ ├── Mode_LSDJ_Map.ino
│ ├── Mode_LSDJ_MasterSync.ino
│ ├── Mode_LSDJ_Midiout.ino
│ ├── Mode_LSDJ_SlaveSync.ino
│ ├── Mode_MidiGb.ino
│ ├── Mode_Nanoloop.ino
│ ├── Mode_Programmer.ino
│ └── UsbMidi.ino
├── Changelog.md
├── Editor/
│ └── ArduinoBoyEditor-Midi.maxpat
├── LICENSE
├── README.md
└── platformio.ini
================================================
FILE CONTENTS
================================================
================================================
FILE: Arduinoboy/Arduinoboy.ino
================================================
/***************************************************************************
***************************************************************************
* __ _ __ *
* ____ __________/ /_ __(_)___ ____ / /_ ____ __ __ *
* / __ `/ ___/ __ / / / / / __ \/ __ \/ __ \/ __ \/ / / / *
* / /_/ / / / /_/ / /_/ / / / / / /_/ / /_/ / /_/ / /_/ / *
* \__,_/_/ \__,_/\__,_/_/_/ /_/\____/_.___/\____/\__, / *
* /____/ *
* *
***************************************************************************
***************************************************************************
* *
* Version: 1.3.4 *
* Date: May 19 2020 *
* Name: Timothy Lamb *
* Email: trash80@gmail.com *
* *
***************************************************************************
***************************************************************************
* *
* NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE *
* *
* https://github.com/trash80/Arduinoboy *
* *
* Arduino pin settings: (Layout is final) *
* - 6 LEDS on pins 8 to 13 *
* - Push button on pin 3 (for selecting mode) *
* - MIDI Opto-isolator power on pin 4 *
* - Gameboy Clock line on analog in pin 0 *
* - Gameboy Serial Data input on analog in pin 1 *
* - Serial Data from gameboy on analog in pin 2 *
* *
* Teensy pin settings: *
* - 6 LEDS on pins 23,22,21,20,4,13 *
* - Push button on pin 2 (for selecting mode) *
* - MIDI Opto-isolator power connected to +3v *
* - Gameboy Clock line on pin 16 *
* - Gameboy Serial Data input on analog in pin 17 *
* - Serial Data from gameboy on analog in pin 18 *
* *
* Teensy USB MIDI is supported *
* Teensy LC should work but untested *
* *
* Program Information: *
* LSDJ Slave Mode Midi Note Effects: *
* 48 - C-2 Sends a Sequencer Start Command *
* 49 - C#2 Sends a Sequencer Stop Command *
* 50 - D-2 Toggles Normal Tempo *
* 51 - D#2 Toggles 1/2 Tempo *
* 52 - E-2 Toggles 1/4 Tempo *
* 53 - F-2 Toggles 1/8 Tempo *
* *
* LSDJ Keyboard Mode: *
* 48 - C-2 Mute Pu1 Off/On *
* 49 - C#2 Mute Pu2 Off/On *
* 50 - D-2 Mute Wav Off/On *
* 51 - D#2 Mute Noi Off/On *
* 52 - E-2 Livemode Cue Sequence *
* 53 - F-2 Livemode Cursor Up *
* 54 - F#2 Livemode Cursor Down *
* 55 - G-2 Livemode Cursor Left *
* 56 - G#2 Livemode Cursor Right *
* 57 - A-2 Table Up *
* 58 - A#2 Table Down *
* 59 - B-2 Cue Table *
* 60 - C-3 to C-8 Notes! *
* Prgram Change to select from instrument table *
* *
***************************************************************************/
/***************************************************************************
* *
* 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 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#define MEM_MAX 65
#define NUMBER_OF_MODES 7 //Right now there are 7 modes, Might be more in the future
//!!! do not edit these, they are the position in EEPROM memory that contain the value of each stored setting
#define MEM_CHECK 0
#define MEM_VERSION_FIRST 1
#define MEM_VERSION_SECOND 2
#define MEM_MODE 5
#define MEM_FORCE_MODE 4
#define MEM_LSDJSLAVE_MIDI_CH 6
#define MEM_LSDJMASTER_MIDI_CH 7
#define MEM_KEYBD_CH 8
#define MEM_KEYBD_COMPAT_MODE 9
#define MEM_KEYBD_CH_TO_INST 10
#define MEM_MIDIOUT_NOTE_CH 11
#define MEM_MIDIOUT_CC_CH 15
#define MEM_MIDIOUT_CC_MODE 19
#define MEM_MIDIOUT_CC_SCALING 23
#define MEM_MIDIOUT_CC_NUMBERS 27
#define MEM_MGB_CH 55
#define MEM_LIVEMAP_CH 60
#define MEM_MIDIOUT_BIT_DELAY 61
#define MEM_MIDIOUT_BYTE_DELAY 63
/***************************************************************************
* User Settings
***************************************************************************/
boolean usbMode = false; //to use usb for serial communication as oppose to MIDI - sets baud rate to 38400
byte defaultMemoryMap[MEM_MAX] = {
0x7F,0x01,0x03,0x7F, //memory init check
0x00, //force mode (forces lsdj to be sl)
0x00, //mode
15, //sync effects midi channel (0-15 = 1-16)
15, //masterNotePositionMidiChannel - LSDJ in master mode will send its song position on the start button via midi note. (0-15 = 1-16)
15, //keyboardInstrumentMidiChannel - midi channel for keyboard instruments in lsdj. (0-15 = 1-16)
1, //Keyboard Compatability Mode
1, //Set to true if you want to have midi channel set the instrument number / doesnt do anything anymore
0,1,2,3, //midiOutNoteMessageChannels - midi channels for lsdj midi out note messages Default: channels 1,2,3,4
0,1,2,3, //midiOutCCMessageChannels - midi channels for lsdj midi out CC messages Default: channels 1,2,3,4
1,1,1,1, //midiOutCCMode - CC Mode, 0=use 1 midi CC, with the range of 00-6F, 1=uses 7 midi CCs with the
//range of 0-F (the command's first digit would be the CC#), either way the value is scaled to 0-127 on output
1,1,1,1, //midiOutCCScaling - CC Scaling- Setting to 1 scales the CC value range to 0-127 as oppose to lsdj's incomming 00-6F (0-112) or 0-F (0-15)
1,2,3,7,10,11,12, //pu1: midiOutCCMessageNumbers - CC numbers for lsdj midi out, if CCMode is 1, all 7 ccs are used per channel at the cost of a limited resolution of 0-F
1,2,3,7,10,11,12, //pu2
1,2,3,7,10,11,12, //wav
1,2,3,7,10,11,12, //noi
0, 1, 2, 3, 4, //mGB midi channels (0-15 = 1-16)
0, //sync map midi channel start (0-15 = 1-16) (for song rows 0x80 to 0xFF it's this channel plus 1)
80,1, //midiout bit check delay & bit check delay multiplier
0,0//midiout byte received delay & byte received delay multiplier
};
byte memory[MEM_MAX];
/***************************************************************************
* Lets Assign our Arduino Pins .....
***************************************************************************/
/***************************************************************************
* Teensy 3.2, Teensy LC
*
* Notes on Teensy: Pins are not the same as in the schematic, the mapping is below.
* Feel free to change, all related config in is this block.
* Be sure to compile
***************************************************************************/
#if defined (__MK20DX256__) || defined (__MK20DX128__) || defined (__MKL26Z64__)
#define USE_TEENSY 1
#define USE_USB 1
#include <MIDI.h>
#if defined (__MKL26Z64__)
#define GB_SET(bit_cl,bit_out,bit_in) GPIOB_PDOR = ((bit_in<<3) | (bit_out<<1) | bit_cl)
#else
#define GB_SET(bit_cl,bit_out,bit_in) GPIOB_PDOR = (GPIOB_PDIR & 0xfffffff4) | ((bit_in<<3) | (bit_out<<1) | bit_cl)
#endif
int pinGBClock = 16; // Analog In 0 - clock out to gameboy
int pinGBSerialOut = 17; // Analog In 1 - serial data to gameboy
int pinGBSerialIn = 18; // Analog In 2 - serial data from gameboy
int pinMidiInputPower = 0; // Not used!
int pinStatusLed = 13; // Status LED
int pinLeds[] = {23,22,21,20,4,13}; // LED Pins
int pinButtonMode = 2; //toggle button for selecting the mode
HardwareSerial *serial = &Serial1;
/***************************************************************************
* Arduino Leonardo/Yún/Micro (ATmega32U4)
***************************************************************************/
#elif defined (__AVR_ATmega32U4__)
#define USE_LEONARDO
#include <MIDIUSB.h>
#define GB_SET(bit_cl, bit_out, bit_in) PORTF = (PINF & B00011111) | ((bit_cl<<7) | ((bit_out)<<6) | ((bit_in)<<5))
// ^ The reason for not using digitalWrite is to allign clock and data pins for the GB shift reg.
// Pin distribution comes from official Arduino Leonardo documentation
int pinGBClock = A0; // Analog In 0 - clock out to gameboy
int pinGBSerialOut = A1; // Analog In 1 - serial data to gameboy
int pinGBSerialIn = A2; // Analog In 2 - serial data from gameboy
int pinMidiInputPower = 4; // power pin for midi input opto-isolator
int pinStatusLed = 13; // Status LED
int pinLeds[] = {12,11,10,9,8,13}; // LED Pins
int pinButtonMode = 3; //toggle button for selecting the mode
HardwareSerial *serial = &Serial1;
/***************************************************************************
* Arduino Due (ATmSAM3X8E)
***************************************************************************/
#elif defined (__SAM3X8E__)
#define USE_DUE
#define USE_LEONARDO
#include <MIDIUSB.h>
#include <digitalWriteFast.h>
#define GB_SET(bit_cl, bit_out, bit_in) digitalWriteFast(A0, bit_cl); digitalWriteFast(A1, bit_out); digitalWriteFast(A2, bit_in);
// ^ The reason for not using digitalWrite is to allign clock and data pins for the GB shift reg.
int pinGBClock = A0; // Analog In 0 - clock out to gameboy
int pinGBSerialOut = A1; // Analog In 1 - serial data to gameboy
int pinGBSerialIn = A2; // Analog In 2 - serial data from gameboy
int pinMidiInputPower = 4; // power pin for midi input opto-isolator
int pinStatusLed = 13; // Status LED
int pinLeds[] = {12,11,10,9,8,13}; // LED Pins
int pinButtonMode = 3; //toggle button for selecting the mode
HardwareSerial *serial = &Serial;
/***************************************************************************
* Arduino UNO/Ethernet/Nano (ATmega328), Arduino UNO Wifi (ATmega4809) or Mega 2560 (ATmega2560/ATmega1280) (assumed)
***************************************************************************/
#else
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define GB_SET(bit_cl,bit_out,bit_in) PORTF = (PINF & B11111000) | ((bit_in<<2) | ((bit_out)<<1) | bit_cl)
#elif defined(__AVR_ATmega4809__)
#define GB_SET(bit_cl,bit_out,bit_in) PORTD = (PIND & B11111000) | ((bit_in<<2) | ((bit_out)<<1) | bit_cl)
#else
#define GB_SET(bit_cl,bit_out,bit_in) PORTC = (PINC & B11111000) | ((bit_in<<2) | ((bit_out)<<1) | bit_cl)
#endif
// ^ The reason for not using digitalWrite is to allign clock and data pins for the GB shift reg.
int pinGBClock = A0; // Analog In 0 - clock out to gameboy
int pinGBSerialOut = A1; // Analog In 1 - serial data to gameboy
int pinGBSerialIn = A2; // Analog In 2 - serial data from gameboy
int pinMidiInputPower = 4; // power pin for midi input opto-isolator
int pinStatusLed = 13; // Status LED
int pinLeds[] = {12,11,10,9,8,13}; // LED Pins
int pinButtonMode = 3; //toggle button for selecting the mode
HardwareSerial *serial = &Serial;
#endif
/***************************************************************************
* Memory
***************************************************************************/
#ifndef USE_DUE
#include <EEPROM.h>
boolean alwaysUseDefaultSettings = false; //set to true to always use the settings below, else they are pulled from memory for the software editor
#else
boolean alwaysUseDefaultSettings = true; //set to true to always use the default settings, in Due board is necessary as it doesn't have EEPROM
#endif
int eepromMemoryByte = 0; //Location of where to store settings from mem
/***************************************************************************
* Sysex Settings & vars
***************************************************************************/
boolean sysexReceiveMode = 0;
boolean sysexProgrammingMode = 0;
boolean sysexProgrammingWaiting = 0;
boolean sysexProgrammingConnected = 0;
unsigned long sysexProgrammerWaitTime = 2000; //2 seconds
unsigned long sysexProgrammerCallTime = 1000; //1 second
unsigned long sysexProgrammerLastResponse = 0;
unsigned long sysexProgrammerLastSent = 0;
byte sysexManufacturerId = 0x69; //har har harrrrr :)
int sysexPosition;
byte sysexData[128];
byte longestSysexMessage = 128;
int midioutBitDelay = 0;
int midioutByteDelay = 0;
/***************************************************************************
* Switches and states
***************************************************************************/
boolean sequencerStarted = false; //Sequencer has Started
boolean midiSyncEffectsTime = false;
boolean midiNoteOnMode =false;
boolean midiNoteOffMode =false;
boolean midiProgramChange=false;
boolean midiAddressMode =false;
boolean midiValueMode =false;
int midiOutLastNote[4] = {-1,-1,-1,-1};
boolean statusLedIsOn =false;
boolean statusLedBlink =false;
boolean nanoState =false;
boolean nanoSkipSync =false;
int buttonDepressed;
int buttonState;
unsigned long int buttonProgrammerWaitTime = 2000; //2 whole seconds
unsigned long int buttonTime;
boolean blinkSwitch[6];
unsigned long int blinkSwitchTime[6];
uint8_t switchLight = 0;
uint16_t blinkMaxCount = 1000;
unsigned long midioutNoteTimer[4];
byte midioutNoteHold[4][4];
byte midioutNoteHoldCounter[4];
int midioutNoteTimerThreshold = 10;
/***************************************************************************
* Counter vars
***************************************************************************/
int countLSDJTicks = 0; //for loop int (we need to cycle 8 pulses)
int countSyncTime = 0;
int countSyncLightTime=0;
int countSyncSteps = 0;
int countSyncPulse = 0;
int countGbClockTicks =0;
int countClockPause =0;
int countIncommingMidiByte =0;
int countStatusLedOn =0;
unsigned int waitClock =0;
int miscLastLed;
unsigned long int miscLedTime;
unsigned long int miscLedMaxTime;
/***************************************************************************
* Inbound Data Placeholders
***************************************************************************/
byte incomingMidiByte; //incomming midi message
byte readgbClockLine;
byte readGbSerialIn;
byte bit;
byte midiData[] = {0, 0, 0};
byte lastMidiData[] = {0, 0, 0};
int incomingMidiNote = 0;
int incomingMidiVel = 0;
byte readToggleMode;
byte serialWriteBuffer[256];
byte midiDefaultStartOffset;
int writePosition=0;
int readPosition=0;
int lastMode=0; //Stores the last selected mode for leds.
byte midiSyncByte;
byte midiSyncByteLast;
byte midiStatusType;
byte midiStatusChannel;
/***************************************************************************
* LSDJ Keyboard mode settings
***************************************************************************/
byte keyboardNotes[] = {0x1A,0x1B,0x22,0x23,0x21,0x2A,0x34,0x32,0x33,0x31,0x3B,0x3A,
0x15,0x1E,0x1D,0x26,0x24,0x2D,0x2E,0x2C,0x36,0x35,0x3D,0x3C};
byte keyboardOctDn = 0x05;
byte keyboardOctUp = 0x06;
byte keyboardInsDn = 0x04;
byte keyboardInsUp = 0x0C;
byte keyboardTblDn = 0x03;
byte keyboardTblUp = 0x0B;
byte keyboardTblCue= 0x29;
byte keyboardMut1 = 0x01;
byte keyboardMut2 = 0x09;
byte keyboardMut3 = 0x78;
byte keyboardMut4 = 0x07;
byte keyboardCurL = 0x6B;
byte keyboardCurR = 0x74;
byte keyboardCurU = 0x75;
byte keyboardCurD = 0x72;
byte keyboardPgUp = 0x7D;
byte keyboardPgDn = 0x7A;
byte keyboardEntr = 0x5A;
int keyboardCurrentOct = 0;
int keyboardCurrentIns = 0;
int keyboardCurrentTbl = 0;
int keyboardLastOct = 0;
int keyboardLastIns = 0;
int keyboardLastTbl = 0;
int keyboardDiff = 0;
int keyboardCount = 0;
byte keyboardStartOctave = 0x24;
byte keyboardNoteStart = 0;
byte keyboardNoteOffset = 0;
byte keyboardCommands[12];
/***************************************************************************
* LSDJ Midi Map mode vars
***************************************************************************/
int mapCurrentRow = -1;
int mapQueueMessage = -1;
unsigned long mapQueueTime;
// mapQueueWait is used for delaying a sync byte
// if it is called right before a note on message on sequencer start
// (Note value is also a clock tick)
uint8_t mapQueueWaitSerial = 2; //2ms
uint8_t mapQueueWaitUsb = 5; //5ms - Needs to be longer because message packet is processed all at once
/***************************************************************************
* mGB Settings
***************************************************************************/
#define GB_MIDI_DELAY 500 //Microseconds to delay the sending of a byte to gb
void setup() {
/*
Init Memory
*/
initMemory(0);
/*
Init Pins
*/
for(int led=0;led<=5;led++) pinMode(pinLeds[led],OUTPUT);
pinMode(pinStatusLed,OUTPUT);
pinMode(pinButtonMode,INPUT);
pinMode(pinGBClock,OUTPUT);
pinMode(pinGBSerialIn,INPUT);
pinMode(pinGBSerialOut,OUTPUT);
/*
Set MIDI Serial Rate
*/
#ifdef USE_USB
serial->begin(31250); //31250
#else
if(usbMode == true) {
serial->begin(38400);
} else {
pinMode(pinMidiInputPower,OUTPUT);
digitalWrite(pinMidiInputPower,HIGH); // turn on the optoisolator
#ifdef USE_LEONARDO
Serial1.begin(31250); //31250
#else
Serial.begin(31250); //31250
#endif
}
#endif
/*
Set Pin States
*/
digitalWrite(pinGBClock,HIGH); // gameboy wants a HIGH line
digitalWrite(pinGBSerialOut,LOW); // no data to send
/*
Misc Startup
*/
keyboardNoteStart = keyboardStartOctave + 12; // Set the octave where the actual notes start (the octave below is for the mutes, cursor, etc)
/*
Assign the keyboard mode command array for the first octave
*/
keyboardCommands[0] = keyboardMut1;
keyboardCommands[1] = keyboardMut2;
keyboardCommands[2] = keyboardMut3;
keyboardCommands[3] = keyboardMut4;
keyboardCommands[4] = keyboardCurL;
keyboardCommands[5] = keyboardCurR;
keyboardCommands[6] = keyboardCurU;
keyboardCommands[7] = keyboardCurD;
keyboardCommands[8] = keyboardEntr;
keyboardCommands[9] = keyboardTblDn;
keyboardCommands[10] = keyboardTblUp;
keyboardCommands[11] = keyboardTblCue;
/*
Load Settings from EEPROM
*/
#ifndef USE_DUE
if(!memory[MEM_FORCE_MODE]) memory[MEM_MODE] = EEPROM.read(MEM_MODE);
#endif
lastMode = memory[MEM_MODE];
/*
usbMidi sysex support
*/
usbMidiInit();
startupSequence();
showSelectedMode(); //Light up the LED that shows which mode we are in.
}
/*
Main Loop, which we don't use to be able to isolate each mode into its own setup and loop functions
*/
void loop () {
setMode();
switchMode();
}
================================================
FILE: Arduinoboy/Led_Functions.ino
================================================
/*
showSelectedMode1 turns off the last mode led, turns on the new mode led
and delays for a period of time to reduce jitter behavior from the mode
changing too fast.
*/
void showSelectedMode()
{
digitalWrite(pinStatusLed,LOW);
for(int m=0;m<3;m++) {
switch(memory[MEM_MODE]) {
case 0:
case 1:
case 2:
case 3:
case 4:
digitalWrite(pinLeds[memory[MEM_MODE]],HIGH);
break;
case 5:
digitalWrite(pinStatusLed,HIGH);
digitalWrite(pinLeds[0],HIGH);
digitalWrite(pinLeds[1],HIGH);
break;
case 6:
digitalWrite(pinLeds[0],HIGH);
digitalWrite(pinLeds[1],HIGH);
digitalWrite(pinLeds[2],HIGH);
digitalWrite(pinLeds[3],HIGH);
digitalWrite(pinLeds[4],HIGH);
digitalWrite(pinLeds[5],HIGH);
break;
}
delay(100);
digitalWrite(pinLeds[0],LOW);
digitalWrite(pinLeds[1],LOW);
digitalWrite(pinLeds[2],LOW);
digitalWrite(pinLeds[3],LOW);
digitalWrite(pinLeds[4],LOW);
digitalWrite(pinLeds[5],LOW);
delay(100);
}
lastMode = memory[MEM_MODE];
delay(300);
}
void updateVisualSync()
{
if(!countSyncTime) {
if(!blinkSwitch[5]) digitalWrite(pinStatusLed,HIGH);
digitalWrite(pinLeds[0],LOW);
digitalWrite(pinLeds[1],LOW);
digitalWrite(pinLeds[2],LOW);
digitalWrite(pinLeds[3],LOW);
digitalWrite(pinLeds[switchLight],HIGH);
blinkSwitch[5]=1;
blinkSwitchTime[5]=0;
countSyncLightTime = 0;
switchLight++;
if(switchLight==4) switchLight=0;
}
countSyncTime++;
if(countSyncTime == 24) countSyncTime=0;
}
void updateBlinkLights()
{
updateBlinkLight(0);
updateBlinkLight(1);
updateBlinkLight(2);
updateBlinkLight(3);
updateBlinkLight(4);
updateBlinkLight(5);
}
void updateBlinkLight(uint8_t light)
{
if(blinkSwitch[light]) {
blinkSwitchTime[light]++;
if(blinkSwitchTime[light] == blinkMaxCount) {
blinkSwitch[light]=0;
blinkSwitchTime[light]=0;
digitalWrite(pinLeds[light],LOW);
}
}
}
void updateStatusLight()
{
if(blinkSwitch[5]) {
blinkSwitchTime[5]++;
if(blinkSwitchTime[5] == blinkMaxCount) {
blinkSwitch[5]=0;
blinkSwitchTime[5]=0;
digitalWrite(pinStatusLed,LOW);
}
}
}
void blinkLight(byte midiMessage, byte midiValue)
{
if(midiValue) {
switch(midiMessage) {
case 0x90:
if(!blinkSwitch[0]) digitalWrite(pinLeds[0],HIGH);
blinkSwitch[0]=1;
blinkSwitchTime[0]=0;
break;
case 0x95:
if(!blinkSwitch[0]) digitalWrite(pinLeds[0],HIGH);
blinkSwitch[0]=1;
blinkSwitchTime[0]=0;
break;
case 0x9A:
if(!blinkSwitch[0]) digitalWrite(pinLeds[0],HIGH);
blinkSwitch[0]=1;
blinkSwitchTime[0]=0;
break;
case 0x91:
if(!blinkSwitch[1]) digitalWrite(pinLeds[1],HIGH);
blinkSwitch[1]=1;
blinkSwitchTime[1]=0;
break;
case 0x96:
if(!blinkSwitch[1]) digitalWrite(pinLeds[1],HIGH);
blinkSwitch[1]=1;
blinkSwitchTime[1]=0;
break;
case 0x9B:
if(!blinkSwitch[1]) digitalWrite(pinLeds[1],HIGH);
blinkSwitch[1]=1;
blinkSwitchTime[1]=0;
break;
case 0x92:
if(!blinkSwitch[2]) digitalWrite(pinLeds[2],HIGH);
blinkSwitch[2]=1;
blinkSwitchTime[2]=0;
break;
case 0x97:
if(!blinkSwitch[2]) digitalWrite(pinLeds[2],HIGH);
blinkSwitch[2]=1;
blinkSwitchTime[2]=0;
break;
case 0x9C:
if(!blinkSwitch[2]) digitalWrite(pinLeds[2],HIGH);
blinkSwitch[2]=1;
blinkSwitchTime[2]=0;
break;
case 0x93:
if(!blinkSwitch[3]) digitalWrite(pinLeds[3],HIGH);
blinkSwitch[3]=1;
blinkSwitchTime[3]=0;
break;
case 0x98:
if(!blinkSwitch[3]) digitalWrite(pinLeds[3],HIGH);
blinkSwitch[3]=1;
blinkSwitchTime[3]=0;
break;
case 0x9D:
if(!blinkSwitch[3]) digitalWrite(pinLeds[3],HIGH);
blinkSwitch[3]=1;
blinkSwitchTime[3]=0;
break;
case 0x94:
if(!blinkSwitch[0]) digitalWrite(pinLeds[0],HIGH);
blinkSwitch[0]=1;
blinkSwitchTime[0]=0;
if(!blinkSwitch[1]) digitalWrite(pinLeds[1],HIGH);
blinkSwitch[1]=1;
blinkSwitchTime[1]=0;
if(!blinkSwitch[2]) digitalWrite(pinLeds[2],HIGH);
blinkSwitch[2]=1;
blinkSwitchTime[2]=0;
break;
case 0x99:
if(!blinkSwitch[0]) digitalWrite(pinLeds[0],HIGH);
blinkSwitch[0]=1;
blinkSwitchTime[0]=0;
if(!blinkSwitch[1]) digitalWrite(pinLeds[1],HIGH);
blinkSwitch[1]=1;
blinkSwitchTime[1]=0;
if(!blinkSwitch[2]) digitalWrite(pinLeds[2],HIGH);
blinkSwitch[2]=1;
blinkSwitchTime[2]=0;
break;
case 0x9E:
if(!blinkSwitch[0]) digitalWrite(pinLeds[0],HIGH);
blinkSwitch[0]=1;
blinkSwitchTime[0]=0;
if(!blinkSwitch[1]) digitalWrite(pinLeds[1],HIGH);
blinkSwitch[1]=1;
blinkSwitchTime[1]=0;
if(!blinkSwitch[2]) digitalWrite(pinLeds[2],HIGH);
blinkSwitch[2]=1;
blinkSwitchTime[2]=0;
break;
}
}
switch(midiMessage) {
case 0xE0:
case 0xE1:
case 0xE2:
case 0xE3:
case 0xE4:
case 0xB0:
case 0xB1:
case 0xB2:
case 0xB3:
case 0xB4:
if(!blinkSwitch[5]) digitalWrite(pinStatusLed,HIGH);
blinkSwitch[5]=1;
blinkSwitchTime[5]=0;
break;
default:
break;
}
}
void updateProgrammerLeds()
{
if(miscLedTime == miscLedMaxTime) {
if(sysexProgrammingConnected) {
miscLedMaxTime = 400;
blinkSelectedLight(miscLastLed);
miscLastLed++;
if(miscLastLed == 5) miscLastLed = 0;
} else {
blinkSelectedLight(5);
miscLedMaxTime = 3000;
}
miscLedTime=0;
}
miscLedTime++;
updateBlinkLights();
}
/*
updateStatusLed should be placed inside of the main loop cycle of a mode function. It counts to a
certain number to delay the action of turning off the status led, so the blink is visible to the human eye. ;)>
I guess this could be called the blinking routine.
*/
void updateStatusLed()
{
if(statusLedIsOn) { //is the led on?
countStatusLedOn++; //then increment the counter by 1
if(countStatusLedOn > 3000) { //if the counter is pretty high
countStatusLedOn = 0; //then reset it to zero.
digitalWrite(pinStatusLed,LOW); //and turn off the status led
statusLedIsOn = false; //and set our "is it on?" to false, cause its off now. ;p
} else if (statusLedBlink && countStatusLedOn == 1) { //someone told me to blink, because i was already on
digitalWrite(pinStatusLed,LOW); //so I'll turn off and turn back on later..
} else if (statusLedBlink && countStatusLedOn > 1000) {//Now that I've waited long enough I'll finish my blink.
statusLedBlink = false; //Turn off the issued blink
digitalWrite(pinStatusLed,HIGH); //... and finally turn back on.
}
}
}
/*
statusLedOn is the function to call when we want the status led to blink for us.
all it does is check if its been already asked to turn on, if it has it will set a flag
to make it blink. Either way it will reset the blink timer and turn on the LED
*/
void statusLedOn()
{
if(statusLedIsOn) {
statusLedBlink = true; //Make it blink even though its already on
}
statusLedIsOn = true; //This is the flag the updator function looks for to know if its ok to increment the timer and wait to turn off the led
countStatusLedOn = 0; //Reset the timer
digitalWrite(pinStatusLed,HIGH); //Turn on the led
}
/* cute startup sequence */
void startupSequence()
{
int ledFxA;
int ledFxB;
for(ledFxB=0;ledFxB<2;ledFxB++) {
for(ledFxA=0;ledFxA<6;ledFxA++) {
digitalWrite(pinLeds[ledFxA], HIGH);
delay(25);
digitalWrite(pinLeds[ledFxA], LOW);
}
for(ledFxA=4;ledFxA>=0;ledFxA--) {
digitalWrite(pinLeds[ledFxA], HIGH);
delay(25);
digitalWrite(pinLeds[ledFxA], LOW);
}
}
delay(50);
for(ledFxA=0;ledFxA<6;ledFxA++) digitalWrite(pinLeds[ledFxA], HIGH); // sets the LED on
delay(100);
for(ledFxA=0;ledFxA<6;ledFxA++) digitalWrite(pinLeds[ledFxA], LOW); // sets the digital pin as output
delay(100);
for(ledFxA=0;ledFxA<6;ledFxA++) digitalWrite(pinLeds[ledFxA], HIGH); // sets the LED on
delay(100);
for(ledFxA=0;ledFxA<6;ledFxA++) digitalWrite(pinLeds[ledFxA], LOW); // sets the digital pin as output
delay(500);
}
================================================
FILE: Arduinoboy/Memory_Functions.ino
================================================
boolean checkMemory()
{
byte chk;
#ifndef USE_DUE
for(int m=0;m<4;m++){
chk = EEPROM.read(MEM_CHECK+m);
if(chk != defaultMemoryMap[MEM_CHECK+m]) {
return false;
}
}
#endif
return true;
}
void initMemory(boolean reinit)
{
if(!alwaysUseDefaultSettings) {
#ifndef USE_DUE
if(reinit || !checkMemory()) {
for(int m=(MEM_MAX);m>=0;m--){
EEPROM.write(m,defaultMemoryMap[m]);
}
}
#endif
loadMemory();
} else {
for(int m=0;m<=MEM_MAX;m++){
memory[m] = defaultMemoryMap[m];
}
}
changeTasks();
}
void loadMemory()
{
#ifndef USE_DUE
for(int m=(MEM_MAX);m>=0;m--){
memory[m] = EEPROM.read(m);
}
#endif
changeTasks();
}
void printMemory()
{
for(int m=0;m<=MEM_MAX;m++){
serial->println(memory[m],HEX);
}
}
void saveMemory()
{
#ifndef USE_DUE
for(int m=(MEM_MAX-1);m>=0;m--){
EEPROM.write(m,memory[m]);
}
changeTasks();
#endif
}
void changeTasks()
{
midioutByteDelay = memory[MEM_MIDIOUT_BYTE_DELAY] * memory[MEM_MIDIOUT_BYTE_DELAY+1];
midioutBitDelay = memory[MEM_MIDIOUT_BIT_DELAY] * memory[MEM_MIDIOUT_BIT_DELAY+1];
}
================================================
FILE: Arduinoboy/Mode.ino
================================================
/**************************************************************************
* Name: Timothy Lamb *
* Email: trash80@gmail.com *
***************************************************************************/
/***************************************************************************
* *
* 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 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
/* ***************************************************************************/
/* "Mode" Functions. Deals with changing the setup of arduino. */
/* ***************************************************************************/
/*
setMode will check if the push button is depressed, If it is it will
increment the mode number and make sure its in the
range 0 to 4 by mod (%). It will then write the mode to memory,
set the leds to display the mode, and switch the code over to the
right function.
*/
void setMode()
{
buttonDepressed = digitalRead(pinButtonMode);
if(!memory[MEM_FORCE_MODE] && buttonDepressed) { //if the button is pressed
memory[MEM_MODE]++; //increment the mode number
if(memory[MEM_MODE] > (NUMBER_OF_MODES - 1)) memory[MEM_MODE]=0; //if the mode is greater then 4 it will wrap back to 0
#ifndef USE_DUE
if(!memory[MEM_FORCE_MODE]) EEPROM.write(MEM_MODE, memory[MEM_MODE]); //write mode to eeprom if we arnt forcing a mode in the config
#endif
showSelectedMode(); //set the LEDS
switchMode();
}
}
/*
switchMode is only called from setMode. its responsible for
linking the mode number to its corrisponding function,
and then calling that function. function. function.
*/
void switchMode()
{
switch(memory[MEM_MODE])
{
case 0:
modeLSDJSlaveSyncSetup();
break;
case 1:
modeLSDJMasterSyncSetup();
break;
case 2:
modeLSDJKeyboardSetup();
break;
case 3:
modeNanoloopSetup();
break;
case 4:
modeMidiGbSetup();
break;
case 5:
modeLSDJMapSetup();
break;
case 6:
modeLSDJMidioutSetup();
break;
}
}
/* ***************************************************************************/
/* General Global Functions Used in more then one of the modes */
/* ***************************************************************************/
/*
sequencerStart is called when either LSDJ has started to play in master mode,
or when a MIDI Start or continue command is received in lsdj slave mode.
Basically it just resets some counters we use and sets a "start" flag.
*/
void sequencerStart()
{
sequencerStarted = true; //Sequencer has started?
countSyncPulse = 0; //Used for status LED, counts 24 ticks (quarter notes)
countSyncTime = 0; //Used to count a custom amount of clock ticks (2/4/8) for sync effects
countSyncLightTime=0;
switchLight=0;
}
/*
sequencerStop is called when either LSDJ has stopped sending sync commands for
some time in LSDJ Master mode, or when a MIDI Stop command is received in
lsdj slave mode.
Basically it just resets some counters we use and sets the "start" flag to false.
*/
void sequencerStop()
{
midiSyncEffectsTime = false;//Turn off MIDI sync effects in LSDJ slave mode
sequencerStarted = false; //Sequencer has started?
countSyncPulse = 0; //Used for status LED, counts 24 ticks (quarter notes)
countSyncTime = 0; //Used to count a custom amount of clock ticks (2/4/8) for sync effects
countSyncLightTime=0;
switchLight=0;
digitalWrite(pinLeds[0],LOW);
digitalWrite(pinLeds[1],LOW);
digitalWrite(pinLeds[2],LOW);
digitalWrite(pinLeds[3],LOW);
digitalWrite(pinLeds[memory[MEM_MODE]],HIGH);
}
================================================
FILE: Arduinoboy/Mode_LSDJ_Keyboard.ino
================================================
/**************************************************************************
* Name: Timothy Lamb *
* Email: trash80@gmail.com *
***************************************************************************/
/***************************************************************************
* *
* 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 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
void modeLSDJKeyboardSetup()
{
digitalWrite(pinStatusLed,LOW);
pinMode(pinGBClock,OUTPUT);
digitalWrite(pinGBClock,HIGH);
#ifdef USE_TEENSY
usbMIDI.setHandleRealTimeSystem(NULL);
#endif
blinkMaxCount=1000;
/* The stuff below makes sure the code is in the same state as LSDJ on reset / restart, mode switched, etc. */
for(int rst=0;rst<5;rst++) sendKeyboardByteToGameboy(keyboardOctDn); //Return lsdj to the first octave
for(int rst=0;rst<41;rst++) sendKeyboardByteToGameboy(keyboardInsDn); //Return lsdj to the first instrument
keyboardCurrentOct = 0; //Set our current octave to 0.
keyboardLastOct = 0; //Set our last octave to 0.
keyboardCurrentIns = 0; //Set out current instrument to 0.
keyboardLastIns = 0; //Set out last used instrument to 0.
modeLSDJKeyboard(); //.... And start the fun
}
void modeLSDJKeyboard()
{
while(1){ //Loop foreverrrr
modeLSDJKeyboardMidiReceive();
if (serial->available()) { //If MIDI is sending
incomingMidiByte = serial->read(); //Get the byte sent from MIDI
if(!checkForProgrammerSysex(incomingMidiByte) && !usbMode) serial->write(incomingMidiByte);//Echo the Byte to MIDI Output
/***************************************************************************
* Midi to LSDJ Keyboard Handling *
***************************************************************************/
//If the byte is a Status Message
if(incomingMidiByte & 0x80) {
/* Status message Information (# = midi channel 0 to F [1-16] )
0x8# = Note Off
0x9# = Note On
0xA# = AfterTouch (ie, key pressure)
0xB# = Control Change
0xC# = Program (patch) change
0xD# = Channel Pressure
0xE# = Pitch Wheel
0xF0 - 0xF7 = System Common Messages
0xF8 - 0xFF = System Realtime Messages
*/
//Weee hello world bitwise and. ... make the second hex digit zero so we can have a simple case statement
// - the second digit is usually the midi channel 0 to F (1-16) unless its a 0xF0 message...
switch (incomingMidiByte & 0xF0) {
case 0x90:
//Note-On Status Message (Note: we have to treat this carefully because note status isnt sent on every note-on, damn it)
//There are 3 bytes total we need: Channel, Note, and velocity, these wil be assigned to a array until we have the velocity,
//at that point we can then call our note out function to LSDJ
midiNoteOnMode = true; //Set our stupid "Note on mode" on
midiData[0] = incomingMidiByte; //Assign the byte to the first position of a data array. (this is the midi channel)
midiData[1] = false; //Force the second position to false (this will hold the note number)
break;
case 0xC0:
//Program change message
midiProgramChange = true; //Set our silly "Program Change mode" ... we need to get the next byte later
midiNoteOnMode = false; //Turn Note-on mode off
midiData[0] = incomingMidiByte - 48;//Set the number to a "note on" message so we can use the same "channel" variable as note on messages
break;
case 0xF0:
//Do nothing, these dont interfear with our note-on mode
break;
default:
//Turn Note-On mode off
midiNoteOnMode = false;
break;
}
} else if(midiNoteOnMode) {
//It wasnt a status bit, so lets assume it was a note message if the last status message was note-on.
if(!midiData[1]) {
//If we dont have a note number, we assume this byte is the note number, get it...
midiData[1] = incomingMidiByte;
} else {
//We have our note and channel, so call our note function...
playLSDJNote(midiData[0], midiData[1], incomingMidiByte);
midiData[1] = false; //Set the note to false, forcing to capture the next note
}
} else if (midiProgramChange) {
changeLSDJInstrument(midiData[0], incomingMidiByte);
midiProgramChange = false;
midiData[0] = false;
}
}
updateStatusLed(); // Update our status blinker
setMode(); // Check if mode button was depressed
}
}
/*
changeLSDJInstrument does what it does via magic (rtfm, realize the fucking magic)
*/
void changeLSDJInstrument(byte channel,byte message)
{
keyboardCurrentIns = message; //set the current instrument number
if(channel == (0x90+memory[MEM_KEYBD_CH]) && keyboardCurrentIns != keyboardLastIns) {
//if its on our midi channel and the instrument isnt the same as our currrent
if(!memory[MEM_KEYBD_COMPAT_MODE]) {
sendKeyboardByteToGameboy(0x80 | message); // <- this is suppose to work but doesn't :/
} else {
//We will find out which is greater, the current instrument or the last instrument. then
//cycle up or down to that instrument
if(keyboardCurrentIns > keyboardLastIns) {
keyboardDiff = keyboardCurrentIns - keyboardLastIns;
for(keyboardCount=0;keyboardCount<keyboardDiff;keyboardCount++) {
sendKeyboardByteToGameboy(keyboardInsUp); //send the instrument up command to go up to the requested instrument
}
} else {
keyboardDiff = keyboardLastIns - keyboardCurrentIns;
for(keyboardCount=0;keyboardCount<keyboardDiff;keyboardCount++) {
sendKeyboardByteToGameboy(keyboardInsDn); //send the instrument down command to down to the requested instrument
}
}
}
keyboardLastIns = keyboardCurrentIns; //assign our instrument for future reference to this function
}
}
/*
w00t...
*/
void playLSDJNote(byte channel,byte note, byte velocity)
{
if(channel == (0x90+memory[MEM_KEYBD_CH])
&& velocity > 0x00) { //If midi channel = ours and the velocity is greater then 0
if(note >= keyboardNoteStart) {
keyboardNoteOffset = 0;
note = note - keyboardNoteStart; //subtract the octave offset to get a value ranging from 0 to 48 for comparison
keyboardCurrentOct = note / 0x0C; //get a octave value from 0 to 4 by deviding the current note by 12
changeLSDJOctave();
if(note >= 0x3C) keyboardNoteOffset = 0x0C; //if the note really high we need to use the second row of keyboard keys
note = (note % 12) + keyboardNoteOffset; //get a 0 to 11 range of notes and add the offset
sendKeyboardByteToGameboy(keyboardNotes[note]); // and finally send the note
} else if (note >= keyboardStartOctave) { //If we are at the octave below notes
keyboardDiff = note - keyboardStartOctave; //Get a value between 0 and 11
if(keyboardDiff < 8 && keyboardDiff > 3) sendKeyboardByteToGameboy(0xE0); //if we are sending cursor values we have to send a 0xE0 byte for "extended" pc keyboard mode
sendKeyboardByteToGameboy(keyboardCommands[note - keyboardStartOctave]); //send the byte corrisponding to the note number in the keyboard command array
}
}
}
/*
changeLSDJOctave compares the last octave with the current one and then sends a byte
to shift the octave to match if need be. its pretty much the same as the changeLSDJInstrument function.
*/
void changeLSDJOctave()
{
if(keyboardCurrentOct != keyboardLastOct) {
if(!memory[MEM_KEYBD_COMPAT_MODE]) { // This new mode doesnt work yet. :/
keyboardCurrentOct = 0xB3 + keyboardCurrentOct;
sendKeyboardByteToGameboy(keyboardCurrentOct);
} else {
///We will find out which is greater, the current octave or the last. then
//cycle up or down to that octave
if(keyboardCurrentOct > keyboardLastOct) {
keyboardDiff = keyboardCurrentOct - keyboardLastOct;
for(keyboardCount=0;keyboardCount<keyboardDiff;keyboardCount++)
{
sendKeyboardByteToGameboy(keyboardOctUp);
}
} else {
keyboardDiff = keyboardLastOct - keyboardCurrentOct;
for(keyboardCount=0;keyboardCount<keyboardDiff;keyboardCount++)
{
sendKeyboardByteToGameboy(keyboardOctDn);
}
}
}
keyboardLastOct = keyboardCurrentOct;
}
}
/*
sendKeyboardByteToGameboy
*/
void sendKeyboardByteToGameboy(byte send_byte)
{
GB_SET(0,0,0);
delayMicroseconds(50); //Delays are added to simulate PC keyboard rate
GB_SET(1,0,0);
delayMicroseconds(50);
for(countLSDJTicks=0;countLSDJTicks<8;countLSDJTicks++) { //we are going to send 8 bits, so do a loop 8 times
if(send_byte & 0x01) { //if the first bit is equal to 1
GB_SET(0,1,0);
delayMicroseconds(50);
GB_SET(1,1,0);
delayMicroseconds(50);
} else {
GB_SET(0,0,0);
delayMicroseconds(50);
GB_SET(1,0,0);
delayMicroseconds(50);
}
send_byte >>= 1; //bitshift right once for the next bit we are going to send
}
GB_SET(0,0,0);
delayMicroseconds(50);
GB_SET(1,0,0);
delayMicroseconds(50);
GB_SET(0,1,0);
delayMicroseconds(50);
GB_SET(1,1,0);
delayMicroseconds(4000);
}
void modeLSDJKeyboardMidiReceive()
{
#ifdef USE_TEENSY
while(usbMIDI.read(memory[MEM_KEYBD_CH]+1)) {
switch(usbMIDI.getType()) {
case 0x80: // note off
playLSDJNote(0x90+memory[MEM_KEYBD_CH], usbMIDI.getData1(), 0);
break;
case 0x90: // note on
playLSDJNote(0x90+memory[MEM_KEYBD_CH], usbMIDI.getData1(), usbMIDI.getData2());
break;
case 0xC0: // PG
changeLSDJInstrument(0xC0+memory[MEM_KEYBD_CH], usbMIDI.getData1());
break;
/*
case 3: // CC
break;
case 5: // AT
break;
case 6: // PB
break;
*/
}
}
#endif
#ifdef USE_LEONARDO
midiEventPacket_t rx;
do {
rx = MidiUSB.read();
switch (rx.header)
{
case 0x08: // note off
playLSDJNote(0x90+memory[MEM_KEYBD_CH], rx.byte2, 0);
statusLedOn();
break;
case 0x09: // note on
playLSDJNote(0x90+memory[MEM_KEYBD_CH], rx.byte2, rx.byte3);
statusLedOn();
break;
case 0x0C: // PG
changeLSDJInstrument(0xC0+memory[MEM_KEYBD_CH], rx.byte2);
statusLedOn();
break;
}
} while (rx.header != 0);
#endif
}
================================================
FILE: Arduinoboy/Mode_LSDJ_Map.ino
================================================
/**************************************************************************
* Name: Timothy Lamb *
* Email: trash80@gmail.com *
***************************************************************************/
/***************************************************************************
* *
* 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 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
void modeLSDJMapSetup()
{
digitalWrite(pinStatusLed,LOW);
pinMode(pinGBClock,OUTPUT);
digitalWrite(pinGBClock, HIGH);
#ifdef USE_TEENSY
usbMIDI.setHandleRealTimeSystem(usbMidiLSDJMapRealtimeMessage);
#endif
blinkMaxCount=1000;
modeLSDJMap();
}
void modeLSDJMap()
{
while(1){ //Loop forever
modeLSDJMapUsbMidiReceive();
checkMapQueue();
if (serial->available()) { //If MIDI Byte Availaibleleleiel
incomingMidiByte = serial->read(); //Read it
checkForProgrammerSysex(incomingMidiByte);
if(incomingMidiByte & 0x80) { //If we have received a MIDI Status Byte
switch (incomingMidiByte) {
case 0xF8:
setMapByte(0xFF, false);
usbMidiSendRTMessage(incomingMidiByte);
break;
case 0xFA: // Case: Transport Start Message
case 0xFB: // and Case: Transport Continue Message
sequencerStart(); // Start the sequencer
usbMidiSendRTMessage(incomingMidiByte);
break;
case 0xFC: // Case: Transport Stop Message
sequencerStop();
setMapByte(0xFE, false);
usbMidiSendRTMessage(incomingMidiByte);
break;
default:
midiData[0] = incomingMidiByte;
midiNoteOnMode = true;
if(midiData[0] == (0x90+memory[MEM_LIVEMAP_CH])
|| midiData[0] == (0x90+(memory[MEM_LIVEMAP_CH]+1))) resetMapCue();
}
} else if(midiNoteOnMode) { //if we've received a message thats not a status and our note capture mode is true
midiNoteOnMode = false;
midiData[1] = incomingMidiByte;
usbMidiSendTwoByteMessage(midiData[0],midiData[1]);
if(midiData[0] == (0x90+memory[MEM_LIVEMAP_CH])
|| midiData[0] == (0x90+(memory[MEM_LIVEMAP_CH]+1))) resetMapCue();
} else {
midiNoteOnMode = true;
if(midiData[0] == (0x90+memory[MEM_LIVEMAP_CH])
|| midiData[0] == (0x90+(memory[MEM_LIVEMAP_CH]+1))) {
if(incomingMidiByte) {
if(midiData[0] == (0x90+(memory[MEM_LIVEMAP_CH]+1))) {
setMapByte(128+midiData[1], false);
} else {
setMapByte(midiData[1], false);
}
} else {
setMapByte(0xFE, false);
}
} else if (midiData[0] == (0x80+memory[MEM_LIVEMAP_CH])
|| midiData[0] == (0x80+(memory[MEM_LIVEMAP_CH]+1))) {
setMapByte(0xFE, false);
}
usbMidiSendThreeByteMessage(midiData[0], midiData[1], incomingMidiByte);
checkMapQueue();
}
} else {
setMode(); //Check if the mode button was depressed
updateStatusLight();
checkMapQueue();
updateBlinkLights();
}
}
}
void setMapByte(uint8_t b, boolean usb)
{
uint8_t wait = mapQueueWaitSerial;
if(usb) {
wait = mapQueueWaitUsb;
}
switch(b) {
case 0xFF:
setMapQueueMessage(0xFF, wait);
break;
case 0xFE:
if(!sequencerStarted) {
sendByteToGameboy(0xFE);
} else if (mapCurrentRow >= 0) {
setMapQueueMessage(mapCurrentRow, wait);
}
break;
default:
mapCurrentRow = b;
sendByteToGameboy(b);
resetMapCue();
}
}
void setMapQueueMessage(uint8_t m, uint8_t wait)
{
if(mapQueueMessage == -1 || mapQueueMessage == 0xFF) {
mapQueueTime=millis()+wait;
mapQueueMessage=m;
}
}
void resetMapCue()
{
mapQueueMessage=-1;
}
void checkMapQueue()
{
if(mapQueueMessage >= 0 && millis()>mapQueueTime) {
if(mapQueueMessage == 0xFF) {
sendByteToGameboy(mapQueueMessage);
} else {
if(mapQueueMessage == 0xFE || mapCurrentRow == mapQueueMessage) {
// Only kill playback if the row is the last one that's been played.
mapCurrentRow = -1;
sendByteToGameboy(0xFE);
}
}
mapQueueMessage=-1;
updateVisualSync();
}
}
void usbMidiLSDJMapRealtimeMessage(uint8_t message)
{
switch(message) {
case 0xF8:
setMapByte(0xFF, true);
break;
case 0xFA: // Case: Transport Start Message
case 0xFB: // and Case: Transport Continue Message
resetMapCue();
sequencerStart(); // Start the sequencer
break;
case 0xFC: // Case: Transport Stop Message
sequencerStop(); // Stop the sequencer
setMapByte(0xFE, true);
break;
}
}
void modeLSDJMapUsbMidiReceive()
{
#ifdef USE_TEENSY
while(usbMIDI.read()) {
uint8_t ch = usbMIDI.getChannel() - 1;
if(ch != memory[MEM_LIVEMAP_CH] && ch != (memory[MEM_LIVEMAP_CH] + 1)){
continue;
}
switch(usbMIDI.getType()) {
case 0x80: // note off
setMapByte(0xFE, true);
break;
case 0x90: // note on
if(ch == (memory[MEM_LIVEMAP_CH] + 1)) {
setMapByte(128+usbMIDI.getData1(), true);
} else {
setMapByte(usbMIDI.getData1(), true);
}
break;
/*
case 3: // CC
break;
case 4: // PG
break;
case 5: // AT
break;
case 6: // PB
break;
*/
}
}
#endif
#ifdef USE_LEONARDO
midiEventPacket_t rx;
do
{
rx = MidiUSB.read();
usbMidiLSDJMapRealtimeMessage(rx.byte1);
uint8_t ch = rx.byte1 & 0x0F;
if (ch != memory[MEM_LIVEMAP_CH] && ch != (memory[MEM_LIVEMAP_CH] + 1))
{
continue;
}
switch (rx.header)
{
case 0x08: // note off
setMapByte(0xFE, true);
break;
case 0x09: // note on
if (ch == (memory[MEM_LIVEMAP_CH] + 1))
{
setMapByte(128 + rx.byte2, true);
}
else
{
setMapByte(rx.byte2, true);
}
break;
}
} while (rx.header != 0);
#endif
}
================================================
FILE: Arduinoboy/Mode_LSDJ_MasterSync.ino
================================================
/**************************************************************************
* Name: Timothy Lamb *
* Email: trash80@gmail.com *
***************************************************************************/
/***************************************************************************
* *
* 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 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
void modeLSDJMasterSyncSetup()
{
digitalWrite(pinStatusLed,LOW);
pinMode(pinGBClock,INPUT);
#ifdef USE_TEENSY
usbMIDI.setHandleRealTimeSystem(NULL);
#endif
countSyncTime=0;
blinkMaxCount=1000;
modeLSDJMasterSync();
}
void modeLSDJMasterSync()
{
while(1){
#ifdef USE_TEENSY
while(usbMIDI.read()) ;
#endif
if (serial->available()) { //If serial data was send to midi input
incomingMidiByte = serial->read(); //Read it
if(!checkForProgrammerSysex(incomingMidiByte) && !usbMode) serial->write(incomingMidiByte); //Send it to the midi output
}
readgbClockLine = digitalRead(pinGBClock); //Read gameboy's clock line
if(readgbClockLine) { //If Gb's Clock is On
while(readgbClockLine) { //Loop untill its off
readgbClockLine = digitalRead(pinGBClock);//Read the clock again
bit = digitalRead(pinGBSerialIn); //Read the serial input for song position
checkActions();
}
countClockPause= 0; //Reset our wait timer for detecting a sequencer stop
readGbSerialIn = readGbSerialIn << 1; //left shift the serial byte by one to append new bit from last loop
readGbSerialIn = readGbSerialIn + bit; //and then add the bit that was read
sendMidiClockSlaveFromLSDJ(); //send the clock & start offset data to midi
}
setMode();
}
}
void checkActions()
{
checkLSDJStopped(); //Check if LSDJ hit Stop
setMode();
updateStatusLight();
}
/*
checkLSDJStopped counts how long the clock was on, if its been on too long we assume
LSDJ has stopped- Send a MIDI transport stop message and return true.
*/
boolean checkLSDJStopped()
{
countClockPause++; //Increment the counter
if(countClockPause > 16000) { //if we've reached our waiting period
if(sequencerStarted) {
readgbClockLine=false;
countClockPause = 0; //reset our clock
serial->write(0xFC); //send the transport stop message
#ifdef USE_TEENSY
usbMIDI.sendRealTime(0xFC);
#endif
#ifdef USE_LEONARDO
midiEventPacket_t event = {0x0F, 0xFC};
MidiUSB.sendMIDI(event);
MidiUSB.flush();
#endif
sequencerStop(); //call the global sequencer stop function
}
return true;
}
return false;
}
/*
sendMidiClockSlaveFromLSDJ waits for 8 clock bits from LSDJ,
sends the transport start command if sequencer hasnt started yet,
sends the midi clock tick, and sends a note value that corrisponds to
LSDJ's row number on start (LSDJ only sends this once when it starts)
*/
void sendMidiClockSlaveFromLSDJ()
{
if(!countGbClockTicks) { //If we hit 8 bits
if(!sequencerStarted) { //If the sequencer hasnt started
serial->write((0x90+memory[MEM_LSDJMASTER_MIDI_CH])); //Send the midi channel byte
serial->write(readGbSerialIn); //Send the row value as a note
serial->write(0x7F); //Send a velocity 127
serial->write(0xFA); //send MIDI transport start message
#ifdef USE_TEENSY
usbMIDI.sendNoteOn(memory[MEM_LSDJMASTER_MIDI_CH]+1,readGbSerialIn,0x7F);
usbMIDI.sendRealTime(0xFA);
#endif
#ifdef USE_LEONARDO
midiEventPacket_t event = {0x09, 0x90 | memory[MEM_LSDJMASTER_MIDI_CH] + 1, readGbSerialIn, 0x7F};
MidiUSB.sendMIDI(event);
MidiUSB.flush();
event = {0x0F, 0xFA};
MidiUSB.sendMIDI(event);
MidiUSB.flush();
#endif
sequencerStart(); //call the global sequencer start function
}
serial->write(0xF8); //Send the MIDI Clock Tick
#ifdef USE_TEENSY
usbMIDI.sendRealTime(0xF8);
#endif
#ifdef USE_LEONARDO
midiEventPacket_t event = {0x0F, 0xF8};
MidiUSB.sendMIDI(event);
MidiUSB.flush();
#endif
countGbClockTicks=0; //Reset the bit counter
readGbSerialIn = 0x00; //Reset our serial read value
updateVisualSync();
}
countGbClockTicks++; //Increment the bit counter
if(countGbClockTicks==8) countGbClockTicks=0;
}
================================================
FILE: Arduinoboy/Mode_LSDJ_Midiout.ino
================================================
/**************************************************************************
* Name: Timothy Lamb *
* Email: trash80@gmail.com *
***************************************************************************/
/***************************************************************************
* *
* 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 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
void modeLSDJMidioutSetup()
{
digitalWrite(pinStatusLed,LOW);
pinMode(pinGBClock,OUTPUT);
digitalWrite(pinGBClock,HIGH);
#ifdef USE_TEENSY
usbMIDI.setHandleRealTimeSystem(NULL);
#endif
countGbClockTicks=0;
lastMidiData[0] = -1;
lastMidiData[1] = -1;
midiValueMode = false;
blinkMaxCount=60;
modeLSDJMidiout();
}
void modeLSDJMidiout()
{
#ifdef USE_LEONARDO
midiEventPacket_t packet;
#endif
while(1){
if(getIncommingSlaveByte()) {
if(incomingMidiByte > 0x6f) {
switch(incomingMidiByte)
{
case 0x7F: //clock tick
serial->write(0xF8);
#ifdef USE_TEENSY
usbMIDI.sendRealTime((int)0xF8);
#endif
#ifdef USE_LEONARDO
packet = {0x0F, 0xF8};
MidiUSB.sendMIDI(packet);
MidiUSB.flush();
#endif
break;
case 0x7E: //seq stop
serial->write(0xFC);
#ifdef USE_TEENSY
usbMIDI.sendRealTime((int)0xFC);
#endif
#ifdef USE_LEONARDO
packet = {0x0F, 0xFC};
MidiUSB.sendMIDI(packet);
MidiUSB.flush();
#endif
stopAllNotes();
break;
case 0x7D: //seq start
serial->write(0xFA);
#ifdef USE_TEENSY
usbMIDI.sendRealTime((int)0xFA);
#endif
#ifdef USE_LEONARDO
packet = {0x0F, 0xFA};
MidiUSB.sendMIDI(packet);
MidiUSB.flush();
#endif
break;
default:
midiData[0] = (incomingMidiByte - 0x70);
midiValueMode = true;
break;
}
} else if (midiValueMode == true) {
midiValueMode = false;
midioutDoAction(midiData[0],incomingMidiByte);
}
} else {
setMode(); // Check if mode button was depressed
updateBlinkLights();
#ifdef USE_TEENSY
while(usbMIDI.read()) ;
#endif
#ifdef USE_LEONARDO
// while (MidiUSB.read()) ;
#endif
if (serial->available()) { //If serial data was send to midi inp
checkForProgrammerSysex(serial->read());
}
}
}
}
void midioutDoAction(byte m, byte v)
{
if(m < 4) {
//note message
if(v) {
checkStopNote(m);
playNote(m,v);
} else if (midiOutLastNote[m]>=0) {
stopNote(m);
}
} else if (m < 8) {
m-=4;
//cc message
playCC(m,v);
} else if(m < 0x0C) {
m-=8;
playPC(m,v);
}
blinkLight(0x90+m,v);
}
void checkStopNote(byte m)
{
if((midioutNoteTimer[m]+midioutNoteTimerThreshold) < millis()) {
stopNote(m);
}
}
void stopNote(byte m)
{
for(int x=0;x<midioutNoteHoldCounter[m];x++) {
midiData[0] = (0x80 + (memory[MEM_MIDIOUT_NOTE_CH+m]));
midiData[1] = midioutNoteHold[m][x];
midiData[2] = 0x00;
serial->write(midiData,3);
#ifdef USE_TEENSY
usbMIDI.sendNoteOff(midioutNoteHold[m][x], 0, memory[MEM_MIDIOUT_NOTE_CH+m]+1);
#endif
#ifdef USE_LEONARDO
midiEventPacket_t packet = { 0x08, 0x80 | memory[MEM_MIDIOUT_NOTE_CH + m], midioutNoteHold[m][x], 0 };
MidiUSB.sendMIDI(packet);
MidiUSB.flush();
#endif
}
midiOutLastNote[m] = -1;
midioutNoteHoldCounter[m] = 0;
}
void playNote(byte m, byte n)
{
midiData[0] = (0x90 + (memory[MEM_MIDIOUT_NOTE_CH+m]));
midiData[1] = n;
midiData[2] = 0x7F;
serial->write(midiData,3);
#ifdef USE_TEENSY
usbMIDI.sendNoteOn(n, 127, memory[MEM_MIDIOUT_NOTE_CH+m]+1);
#endif
#ifdef USE_LEONARDO
midiEventPacket_t packet = { 0x09, 0x90 | memory[MEM_MIDIOUT_NOTE_CH + m], n, 127 };
MidiUSB.sendMIDI(packet);
MidiUSB.flush();
#endif
midioutNoteHold[m][midioutNoteHoldCounter[m]] =n;
midioutNoteHoldCounter[m]++;
midioutNoteTimer[m] = millis();
midiOutLastNote[m] =n;
}
void playCC(byte m, byte n)
{
byte v = n;
if(memory[MEM_MIDIOUT_CC_MODE+m]) {
if(memory[MEM_MIDIOUT_CC_SCALING+m]) {
v = (v & 0x0F)*8;
//if(v) v --;
}
n=(m*7)+((n>>4) & 0x07);
midiData[0] = (0xB0 + (memory[MEM_MIDIOUT_CC_CH+m]));
midiData[1] = (memory[MEM_MIDIOUT_CC_NUMBERS+n]);
midiData[2] = v;
serial->write(midiData,3);
#ifdef USE_TEENSY
usbMIDI.sendControlChange((memory[MEM_MIDIOUT_CC_NUMBERS+n]), v, memory[MEM_MIDIOUT_NOTE_CH+m]+1);
#endif
#ifdef USE_LEONARDO
midiEventPacket_t packet = {0x0B, 0xB0 | (memory[MEM_MIDIOUT_NOTE_CH + m]+1), (memory[MEM_MIDIOUT_CC_NUMBERS + n]), v};
MidiUSB.sendMIDI(packet);
MidiUSB.flush();
#endif
} else {
if(memory[MEM_MIDIOUT_CC_SCALING+m]) {
float s;
s = n;
v = ((s / 0x6f) * 0x7f);
}
n=(m*7);
midiData[0] = (0xB0 + (memory[MEM_MIDIOUT_CC_CH+m]));
midiData[1] = (memory[MEM_MIDIOUT_CC_NUMBERS+n]);
midiData[2] = v;
serial->write(midiData,3);
#ifdef USE_TEENSY
usbMIDI.sendControlChange((memory[MEM_MIDIOUT_CC_NUMBERS+n]), v, memory[MEM_MIDIOUT_NOTE_CH+m]+1);
#endif
#ifdef USE_LEONARDO
midiEventPacket_t packet = {0x0B, 0xB0 | (memory[MEM_MIDIOUT_NOTE_CH + m]+1), (memory[MEM_MIDIOUT_CC_NUMBERS + n]), v};
MidiUSB.sendMIDI(packet);
MidiUSB.flush();
#endif
}
}
void playPC(byte m, byte n)
{
midiData[0] = (0xC0 + (memory[MEM_MIDIOUT_NOTE_CH+m]));
midiData[1] = n;
serial->write(midiData,2);
#ifdef USE_TEENSY
usbMIDI.sendProgramChange(n, memory[MEM_MIDIOUT_NOTE_CH+m]+1);
#endif
#ifdef USE_LEONARDO
midiEventPacket_t packet = {0x0C, 0xC0 | (memory[MEM_MIDIOUT_NOTE_CH + m]+1), n};
MidiUSB.sendMIDI(packet);
MidiUSB.flush();
#endif
}
void stopAllNotes()
{
for(int m=0;m<4;m++) {
if(midiOutLastNote[m]>=0) {
stopNote(m);
}
midiData[0] = (0xB0 + (memory[MEM_MIDIOUT_NOTE_CH+m]));
midiData[1] = 123;
midiData[2] = 0x7F;
serial->write(midiData,3); //Send midi
#ifdef USE_TEENSY
usbMIDI.sendControlChange(123, 127, memory[MEM_MIDIOUT_NOTE_CH+m]+1);
#endif
#ifdef USE_LEONARDO
midiEventPacket_t packet = {0x0B, 0xB0 | memory[MEM_MIDIOUT_NOTE_CH + m], 123, 127};
MidiUSB.sendMIDI(packet);
MidiUSB.flush();
#endif
}
}
boolean getIncommingSlaveByte()
{
delayMicroseconds(midioutBitDelay);
GB_SET(0,0,0);
delayMicroseconds(midioutBitDelay);
GB_SET(1,0,0);
delayMicroseconds(2);
if(digitalRead(pinGBSerialIn)) {
incomingMidiByte = 0;
for(countClockPause=0;countClockPause!=7;countClockPause++) {
GB_SET(0,0,0);
delayMicroseconds(2);
GB_SET(1,0,0);
incomingMidiByte = (incomingMidiByte << 1) + digitalRead(pinGBSerialIn);
}
return true;
}
return false;
}
================================================
FILE: Arduinoboy/Mode_LSDJ_SlaveSync.ino
================================================
/**************************************************************************
* Name: Timothy Lamb *
* Email: trash80@gmail.com *
***************************************************************************/
/***************************************************************************
* *
* 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 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
void modeLSDJSlaveSyncSetup()
{
digitalWrite(pinStatusLed,LOW);
pinMode(pinGBClock,OUTPUT);
digitalWrite(pinGBClock,HIGH);
#ifdef USE_TEENSY
usbMIDI.setHandleRealTimeSystem(usbMidiLSDJSlaveRealtimeMessage);
#endif
blinkMaxCount=1000;
modeLSDJSlaveSync();
}
void modeLSDJSlaveSync()
{
while(1){ //Loop forever
modeLSDJSlaveSyncUsbMidiReceive();
if (serial->available()) { //If MIDI Byte Availaibleleleiel
incomingMidiByte = serial->read(); //Read it
if(!checkForProgrammerSysex(incomingMidiByte) && !usbMode) serial->write(incomingMidiByte); //Send it back to the Midi out
if(incomingMidiByte & 0x80) { //If we have received a MIDI Status Byte
switch (incomingMidiByte) {
case 0xF8: //Case: Clock Message Recieved
if((sequencerStarted && midiSyncEffectsTime && !countSyncTime) //If the seq has started and our sync effect is on and at zero
|| (sequencerStarted && !midiSyncEffectsTime)) { //or seq is started and there is no sync effects
if(!countSyncPulse && midiDefaultStartOffset) { //if we received a note for start offset
//sendByteToGameboy(midiDefaultStartOffset); //send the offset
}
sendClockTickToLSDJ(); //send the clock tick
updateVisualSync();
}
if(midiSyncEffectsTime) { //If sync effects are turned on
countSyncTime++; //increment our tick counter
countSyncTime = countSyncTime % countSyncSteps; //and mod it by the number of steps we want for the effect
}
break;
case 0xFA: // Case: Transport Start Message
case 0xFB: // and Case: Transport Continue Message
sequencerStart(); // Start the sequencer
break;
case 0xFC: // Case: Transport Stop Message
sequencerStop(); // Stop the sequencer
break;
default:
if(incomingMidiByte == (0x90+memory[MEM_LSDJSLAVE_MIDI_CH])) { //if a midi note was received and its on the channel of the sync effects channel
midiNoteOnMode = true; //turn on note capture
midiData[0] = false; //and reset the captured note
} else {
midiNoteOnMode = false; //turn off note capture
}
}
} else if(midiNoteOnMode) { //if we've received a message thats not a status and our note capture mode is true
if(!midiData[0]) { //if there is no note number yet
midiData[0] = incomingMidiByte; //then assume the byte is a note and assign it to a place holder
} else { //else assumed velocity
if(incomingMidiByte > 0x00) {
getSlaveSyncEffect(midiData[0]); //then call our sync effects function
}
midiData[0] = false; //and reset the captured note
}
}
}
setMode(); //Check if the mode button was depressed
updateStatusLight();
}
}
/*
sendClockTickToLSDJ is a lovely loving simple function I wish they where all this short
Technicallyly we are sending nothing but a 8bit clock pulse
*/
void sendClockTickToLSDJ()
{
for(countLSDJTicks=0;countLSDJTicks<8;countLSDJTicks++) {
GB_SET(0,0,0);
GB_SET(1,0,0);
}
}
/*
getSlaveSyncEffect receives a note, and assigns the propper effect of that note
*/
void getSlaveSyncEffect(byte note)
{
switch(note) {
case 48: //C-3ish, Transport Start
sequencerStart();
break;
case 49: //C#3 Transport Stop
sequencerStop();
break;
case 50: //D-3 Turn off sync effects
midiSyncEffectsTime = false;
break;
case 51: //D#3 Sync effect, 1/2 time
midiSyncEffectsTime = true;
countSyncTime = 0;
countSyncSteps = 2;
break;
case 52: //E-3 Sync Effect, 1/4 time
midiSyncEffectsTime = true;
countSyncTime = 0;
countSyncSteps = 4;
break;
case 53: //F-3 Sync Effect, 1/8 time
midiSyncEffectsTime = true;
countSyncTime = 0;
countSyncSteps = 8;
break;
default: //All other notes will make LSDJ Start at the row number thats the same as the note number.
midiDefaultStartOffset = midiData[0];
break;
}
}
void usbMidiLSDJSlaveRealtimeMessage(uint8_t message)
{
switch(message) {
case 0xF8:
if((sequencerStarted && midiSyncEffectsTime && !countSyncTime) //If the seq has started and our sync effect is on and at zero
|| (sequencerStarted && !midiSyncEffectsTime)) { //or seq is started and there is no sync effects
if(!countSyncPulse && midiDefaultStartOffset) { //if we received a note for start offset
//sendByteToGameboy(midiDefaultStartOffset); //send the offset
}
sendClockTickToLSDJ(); //send the clock tick
updateVisualSync();
}
if(midiSyncEffectsTime) { //If sync effects are turned on
countSyncTime++; //increment our tick counter
countSyncTime = countSyncTime % countSyncSteps; //and mod it by the number of steps we want for the effect
}
break;
case 0xFA: // Case: Transport Start Message
case 0xFB: // and Case: Transport Continue Message
sequencerStart(); // Start the sequencer
break;
case 0xFC: // Case: Transport Stop Message
sequencerStop();
break;
}
}
void modeLSDJSlaveSyncUsbMidiReceive()
{
#ifdef USE_TEENSY
while(usbMIDI.read(memory[MEM_LSDJSLAVE_MIDI_CH]+1)) {
switch(usbMIDI.getType()) {
case 0x90: // note on
getSlaveSyncEffect(usbMIDI.getData1());
break;
/*
case 0: // note on
break;
case 3: // CC
break;
case 4: // PG
break;
case 5: // AT
break;
case 6: // PB
break;
*/
}
}
#endif
#ifdef USE_LEONARDO
midiEventPacket_t rx;
do
{
rx = MidiUSB.read();
uint8_t ch = rx.byte1 & 0x0F;
if (ch == memory[MEM_LSDJSLAVE_MIDI_CH] && rx.header == 0x09)
{
getSlaveSyncEffect(rx.byte2);
}
switch (rx.byte1)
{
case 0xF8:
if ((sequencerStarted && midiSyncEffectsTime && !countSyncTime) //If the seq has started and our sync effect is on and at zero
|| (sequencerStarted && !midiSyncEffectsTime))
{ //or seq is started and there is no sync effects
if (!countSyncPulse && midiDefaultStartOffset)
{ //if we received a note for start offset
//sendByteToGameboy(midiDefaultStartOffset); //send the offset
}
sendClockTickToLSDJ(); //send the clock tick
updateVisualSync();
}
if (midiSyncEffectsTime)
{ //If sync effects are turned on
countSyncTime++; //increment our tick counter
countSyncTime = countSyncTime % countSyncSteps; //and mod it by the number of steps we want for the effect
}
break;
case 0xFA: // Case: Transport Start Message
case 0xFB: // and Case: Transport Continue Message
sequencerStart(); // Start the sequencer
break;
case 0xFC: // Case: Transport Stop Message
sequencerStop();
break;
}
} while (rx.header != 0);
#endif
}
================================================
FILE: Arduinoboy/Mode_MidiGb.ino
================================================
/**************************************************************************
* Name: Timothy Lamb *
* Email: trash80@gmail.com *
***************************************************************************/
/***************************************************************************
* *
* 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 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
void modeMidiGbSetup()
{
digitalWrite(pinStatusLed,LOW);
pinMode(pinGBClock,OUTPUT);
digitalWrite(pinGBClock,HIGH);
#ifdef USE_TEENSY
usbMIDI.setHandleRealTimeSystem(NULL);
#endif
blinkMaxCount=1000;
modeMidiGb();
}
void modeMidiGb()
{
boolean sendByte = false;
while(1){ //Loop foreverrrr
modeMidiGbUsbMidiReceive();
if (serial->available()) { //If MIDI is sending
incomingMidiByte = serial->read(); //Get the byte sent from MIDI
if(!checkForProgrammerSysex(incomingMidiByte) && !usbMode) serial->write(incomingMidiByte); //Echo the Byte to MIDI Output
if(incomingMidiByte & 0x80) {
switch (incomingMidiByte & 0xF0) {
case 0xF0:
midiValueMode = false;
break;
default:
sendByte = false;
midiStatusChannel = incomingMidiByte&0x0F;
midiStatusType = incomingMidiByte&0xF0;
if(midiStatusChannel == memory[MEM_MGB_CH]) {
midiData[0] = midiStatusType;
sendByte = true;
} else if (midiStatusChannel == memory[MEM_MGB_CH+1]) {
midiData[0] = midiStatusType+1;
sendByte = true;
} else if (midiStatusChannel == memory[MEM_MGB_CH+2]) {
midiData[0] = midiStatusType+2;
sendByte = true;
} else if (midiStatusChannel == memory[MEM_MGB_CH+3]) {
midiData[0] = midiStatusType+3;
sendByte = true;
} else if (midiStatusChannel == memory[MEM_MGB_CH+4]) {
midiData[0] = midiStatusType+4;
sendByte = true;
} else {
midiValueMode =false;
midiAddressMode=false;
}
if(sendByte) {
statusLedOn();
sendByteToGameboy(midiData[0]);
delayMicroseconds(GB_MIDI_DELAY);
midiValueMode =false;
midiAddressMode=true;
}
break;
}
} else if (midiAddressMode){
midiAddressMode = false;
midiValueMode = true;
midiData[1] = incomingMidiByte;
sendByteToGameboy(midiData[1]);
delayMicroseconds(GB_MIDI_DELAY);
} else if (midiValueMode) {
midiData[2] = incomingMidiByte;
midiAddressMode = true;
midiValueMode = false;
sendByteToGameboy(midiData[2]);
delayMicroseconds(GB_MIDI_DELAY);
statusLedOn();
blinkLight(midiData[0],midiData[2]);
}
} else {
setMode(); // Check if mode button was depressed
updateBlinkLights();
updateStatusLed();
}
}
}
/*
sendByteToGameboy does what it says. yay magic
*/
void sendByteToGameboy(byte send_byte)
{
for(countLSDJTicks=0;countLSDJTicks!=8;countLSDJTicks++) { //we are going to send 8 bits, so do a loop 8 times
if(send_byte & 0x80) {
GB_SET(0,1,0);
GB_SET(1,1,0);
} else {
GB_SET(0,0,0);
GB_SET(1,0,0);
}
#if defined (F_CPU) && (F_CPU > 24000000)
// Delays for Teensy etc where CPU speed might be clocked too fast for cable & shift register on gameboy.
delayMicroseconds(1);
#endif
send_byte <<= 1;
}
}
void modeMidiGbUsbMidiReceive()
{
#ifdef USE_TEENSY
while(usbMIDI.read()) {
uint8_t ch = usbMIDI.getChannel() - 1;
boolean send = false;
if(ch == memory[MEM_MGB_CH]) {
ch = 0;
send = true;
} else if (ch == memory[MEM_MGB_CH+1]) {
ch = 1;
send = true;
} else if (ch == memory[MEM_MGB_CH+2]) {
ch = 2;
send = true;
} else if (ch == memory[MEM_MGB_CH+3]) {
ch = 3;
send = true;
} else if (ch == memory[MEM_MGB_CH+4]) {
ch = 4;
send = true;
}
if(!send) return;
uint8_t s;
switch(usbMIDI.getType()) {
case 0x80: // note off
case 0x90: // note on
s = 0x90 + ch;
if(usbMIDI.getType() == 0x80) {
s = 0x80 + ch;
}
sendByteToGameboy(s);
delayMicroseconds(GB_MIDI_DELAY);
sendByteToGameboy(usbMIDI.getData1());
delayMicroseconds(GB_MIDI_DELAY);
sendByteToGameboy(usbMIDI.getData2());
delayMicroseconds(GB_MIDI_DELAY);
blinkLight(s, usbMIDI.getData2());
break;
case 0xB0: // CC
sendByteToGameboy(0xB0+ch);
delayMicroseconds(GB_MIDI_DELAY);
sendByteToGameboy(usbMIDI.getData1());
delayMicroseconds(GB_MIDI_DELAY);
sendByteToGameboy(usbMIDI.getData2());
delayMicroseconds(GB_MIDI_DELAY);
blinkLight(0xB0+ch, usbMIDI.getData2());
break;
case 0xC0: // PG
sendByteToGameboy(0xC0+ch);
delayMicroseconds(GB_MIDI_DELAY);
sendByteToGameboy(usbMIDI.getData1());
delayMicroseconds(GB_MIDI_DELAY);
blinkLight(0xC0+ch, usbMIDI.getData2());
break;
case 0xE0: // PB
sendByteToGameboy(0xE0+ch);
delayMicroseconds(GB_MIDI_DELAY);
sendByteToGameboy(usbMIDI.getData1());
delayMicroseconds(GB_MIDI_DELAY);
sendByteToGameboy(usbMIDI.getData2());
delayMicroseconds(GB_MIDI_DELAY);
break;
}
statusLedOn();
}
#endif
#ifdef USE_LEONARDO
midiEventPacket_t rx;
do
{
rx = MidiUSB.read();
uint8_t ch = rx.byte1 & 0x0F;
boolean send = false;
if(ch == memory[MEM_MGB_CH]) {
ch = 0;
send = true;
} else if (ch == memory[MEM_MGB_CH+1]) {
ch = 1;
send = true;
} else if (ch == memory[MEM_MGB_CH+2]) {
ch = 2;
send = true;
} else if (ch == memory[MEM_MGB_CH+3]) {
ch = 3;
send = true;
} else if (ch == memory[MEM_MGB_CH+4]) {
ch = 4;
send = true;
}
if (!send) return;
uint8_t s;
switch (rx.header)
{
case 0x08: // note off
case 0x09: // note on
s = 0x90 + ch;
if (rx.header == 0x08)
{
s = 0x80 + ch;
}
sendByteToGameboy(s);
delayMicroseconds(GB_MIDI_DELAY);
sendByteToGameboy(rx.byte2);
delayMicroseconds(GB_MIDI_DELAY);
sendByteToGameboy(rx.byte3);
delayMicroseconds(GB_MIDI_DELAY);
blinkLight(s, rx.byte2);
break;
case 0x0B: // CC
sendByteToGameboy(0xB0 + ch);
delayMicroseconds(GB_MIDI_DELAY);
sendByteToGameboy(rx.byte2);
delayMicroseconds(GB_MIDI_DELAY);
sendByteToGameboy(rx.byte3);
delayMicroseconds(GB_MIDI_DELAY);
blinkLight(0xB0 + ch, rx.byte2);
break;
case 0x0C: // PG
sendByteToGameboy(0xC0 + ch);
delayMicroseconds(GB_MIDI_DELAY);
sendByteToGameboy(rx.byte2);
delayMicroseconds(GB_MIDI_DELAY);
blinkLight(0xC0 + ch, rx.byte2);
break;
case 0x0E: // PB
sendByteToGameboy(0xE0 + ch);
delayMicroseconds(GB_MIDI_DELAY);
sendByteToGameboy(rx.byte2);
delayMicroseconds(GB_MIDI_DELAY);
sendByteToGameboy(rx.byte3);
delayMicroseconds(GB_MIDI_DELAY);
break;
default:
return;
}
statusLedOn();
} while (rx.header != 0);
#endif
}
================================================
FILE: Arduinoboy/Mode_Nanoloop.ino
================================================
/**************************************************************************
* Name: Timothy Lamb *
* Email: trash80@gmail.com *
***************************************************************************/
/***************************************************************************
* *
* 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 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
void modeNanoloopSetup()
{
digitalWrite(pinStatusLed,LOW);
pinMode(pinGBClock,OUTPUT);
digitalWrite(pinGBClock,HIGH);
#ifdef USE_TEENSY
usbMIDI.setHandleRealTimeSystem(usbMidiNanoloopRealtimeMessage);
#endif
blinkMaxCount=1000;
modeNanoloopSync();
}
void modeNanoloopSync()
{
while(1){ //Loop forever
modeNanoloopUsbMidiReceive();
if (serial->available()) { //If MIDI Byte Availaibleleleiel
incomingMidiByte = serial->read(); //Read it
if(!checkForProgrammerSysex(incomingMidiByte) && !usbMode) serial->write(incomingMidiByte); //Send it back to the Midi out
if(incomingMidiByte & 0x80) {
switch (incomingMidiByte) {
case 0xF8: // Clock Message Recieved
// Send a clock tick out if the sequencer is running
if(sequencerStarted) {
nanoSkipSync = !nanoSkipSync;
if(countSyncTime) {
nanoState = sendTickToNanoloop(nanoState, false);
} else {
nanoState = sendTickToNanoloop(true, true);
}
nanoState = sendTickToNanoloop(nanoState, nanoSkipSync);
updateVisualSync();
break;
}
break;
case 0xFA: // Transport Start Message
case 0xFB: // Transport Continue Message
sequencerStart();
break;
case 0xFC: // Transport Stop Message
sequencerStop();
break;
default:
break;
}
}
}
setMode(); //Check if the mode button was depressed
updateStatusLight();
}
}
boolean sendTickToNanoloop(boolean state, boolean last_state)
{
if(!state) {
if(last_state) {
GB_SET(0,1,0);
GB_SET(1,1,0);
} else {
GB_SET(0,0,0);
GB_SET(1,0,0);
}
return true;
} else {
GB_SET(0,1,0);
GB_SET(1,1,0);
return false;
}
}
void usbMidiNanoloopRealtimeMessage(uint8_t message)
{
switch(message) {
case 0xF8:
if(sequencerStarted) {
nanoSkipSync = !nanoSkipSync;
if(countSyncTime) {
nanoState = sendTickToNanoloop(nanoState, false);
} else {
nanoState = sendTickToNanoloop(true, true);
}
nanoState = sendTickToNanoloop(nanoState, nanoSkipSync);
updateVisualSync();
}
break;
case 0xFA: // Case: Transport Start Message
case 0xFB: // and Case: Transport Continue Message
sequencerStart(); // Start the sequencer
break;
case 0xFC: // Case: Transport Stop Message
sequencerStop();
break;
}
}
void modeNanoloopUsbMidiReceive()
{
#ifdef USE_TEENSY
while(usbMIDI.read(memory[MEM_LSDJSLAVE_MIDI_CH]+1)) {
switch(usbMIDI.getType()) {
case 0x90: // note on
getSlaveSyncEffect(usbMIDI.getData1());
break;
/*
case 0: // note on
break;
case 3: // CC
break;
case 4: // PG
break;
case 5: // AT
break;
case 6: // PB
break;
*/
}
}
#endif
#ifdef USE_LEONARDO
midiEventPacket_t rx;
do
{
rx = MidiUSB.read();
usbMidiNanoloopRealtimeMessage(rx.byte1);
} while (rx.header != 0);
#endif
}
================================================
FILE: Arduinoboy/Mode_Programmer.ino
================================================
void modeProgrammer()
{
while(sysexProgrammingConnected || sysexProgrammingMode) {
checkProgrammerConnected();
if (serial->available()) checkForProgrammerSysex(serial->read());
updateProgrammerLeds();
setMode();
usbMidiUpdate();
}
showSelectedMode();
switchMode();
}
void setProgrammerConnected()
{
sysexProgrammerLastResponse = millis();
if(!sysexProgrammingConnected) {
programmerSendSettings();
}
sysexProgrammingConnected = 1;
}
void checkProgrammerConnected()
{
programmerSendConnectRequest();
programmerCheckTimeout();
}
void programmerSendSettings()
{
sysexData[0] = 0xF0;
sysexData[1] = sysexManufacturerId;
sysexData[2] = 0x40;
memcpy(&sysexData[3], memory, MEM_MAX+1);
sysexData[MEM_MAX+3] = 0xF7;
serial->write(sysexData, MEM_MAX+4);
#ifdef USE_TEENSY
usbMIDI.sendSysEx(MEM_MAX+4, sysexData);
#endif
}
void setProgrammerRequestConnect()
{
uint8_t data[4] = {0xF0,sysexManufacturerId,65,0xF7};
serial->write(data, 4);
#ifdef USE_TEENSY
usbMIDI.sendSysEx(4, data);
#endif
}
void setProgrammerMemorySave()
{
byte offset = 2;
for(byte m=4;m<=MEM_MAX;m++) {
memory[m] = sysexData[offset];
offset++;
}
saveMemory();
loadMemory();
programmerSendSettings();
}
void setProgrammerRestoreMemory()
{
initMemory(1);
programmerSendSettings();
}
void programmerCheckTimeout()
{
if(sysexProgrammingConnected && millis() > (sysexProgrammerLastResponse+sysexProgrammerWaitTime)) {
//programmer timeout!
sysexProgrammingConnected = 0;
sysexProgrammingMode = 0;
}
if(sysexProgrammingMode && millis() > (sysexProgrammerLastResponse+sysexProgrammerWaitTime)) {
//programmer timeout!
sysexProgrammingConnected = 0;
sysexProgrammingMode = 0;
}
}
void programmerSendConnectRequest()
{
if(millis() > (sysexProgrammerLastSent+sysexProgrammerCallTime)) {
uint8_t data[6] = {0xF0, sysexManufacturerId, 0x7F, defaultMemoryMap[MEM_VERSION_FIRST], defaultMemoryMap[MEM_VERSION_SECOND], 0xF7};
serial->write(data, 6);
#ifdef USE_TEENSY
usbMIDI.sendSysEx(6, data);
#endif
sysexProgrammerLastSent = millis();
}
}
boolean checkSysexChecksum()
{
byte checksum = sysexData[(sysexPosition - 1)];
byte checkdata= 0;
if(checksum) {
for(int x=2;x!=(sysexPosition - 2);x++) {
checkdata += sysexData[x];
}
if(checkdata & 0x80) checkdata -= 0x7F;
if(checkdata == checksum) {
return true;
}
}
return true;
}
void clearSysexBuffer()
{
for(int x=0;x!=sysexPosition;x++) {
sysexData[x]= 0;
}
sysexPosition = 0;
}
void setMode(byte mode)
{
memory[MEM_MODE] = mode;
#ifndef USE_DUE
EEPROM.write(MEM_MODE, memory[MEM_MODE]);
#endif
showSelectedMode();
switchMode();
}
void sendMode()
{
uint8_t data[4] = {0xF0, sysexManufacturerId, memory[MEM_MODE], 0xF7};
serial->write(data, 4);
#ifdef USE_TEENSY
usbMIDI.sendSysEx(4, data);
#endif
}
void setMidioutDelay(byte a,byte b,byte c,byte d)
{
memory[MEM_MIDIOUT_BIT_DELAY] = a;
memory[MEM_MIDIOUT_BIT_DELAY+1] = b;
memory[MEM_MIDIOUT_BYTE_DELAY] = c;
memory[MEM_MIDIOUT_BYTE_DELAY+1] = d;
saveMemory();
changeTasks();
}
void getSysexData()
{
if(sysexData[0] == 0x69 && checkSysexChecksum()) {
//sysex good, do stuff
sysexPosition = 0;
if(sysexProgrammingMode) {
if(sysexData[1] == 64
&& sysexData[2] == defaultMemoryMap[MEM_VERSION_FIRST]
&& sysexData[3] == defaultMemoryMap[MEM_VERSION_SECOND]) {
//serial connected to programmer
setProgrammerRequestConnect();
}
if(sysexData[1] == 66
&& sysexData[2] == defaultMemoryMap[MEM_VERSION_FIRST]
&& sysexData[3] == defaultMemoryMap[MEM_VERSION_SECOND]) {
//serial connected to programmer
setProgrammerConnected();
}
if(sysexData[1] == 70) {
//save states
setProgrammerMemorySave();
}
if(sysexData[1] == 71) {
//save states
setProgrammerRestoreMemory();
}
}
if(sysexData[1] == 72) {
sysexProgrammingMode = true;
sysexProgrammerLastResponse = millis();
modeProgrammer();
}
if(sysexData[1] == 73) {
sendMode();
}
if(sysexData[1] == 74) {
setMode(sysexData[2]);
}
if(sysexData[1] == 75) {
setMidioutDelay(sysexData[2],sysexData[3],sysexData[4],sysexData[5]);
}
}
clearSysexBuffer();
}
boolean checkForProgrammerSysex(byte sin)
{
if(sin == 0xF0) {
sysexReceiveMode = true;
sysexPosition= 0;
return true;
} else if (sin == 0xF7 && sysexReceiveMode) {
sysexReceiveMode = false;
getSysexData();
sysexPosition= 0;
return true;
} else if (sysexReceiveMode == true) {
sysexData[sysexPosition] = sin;
sysexPosition++;
if(sysexPosition > longestSysexMessage) {
clearSysexBuffer();
sysexReceiveMode = false;
}
return true;
}
return false;
}
void blinkSelectedLight(int led)
{
if(!blinkSwitch[led]) digitalWrite(pinLeds[led],HIGH);
blinkSwitch[led]=1;
blinkSwitchTime[led]=0;
}
================================================
FILE: Arduinoboy/UsbMidi.ino
================================================
#ifndef USE_TEENSY
void usbMidiSendTwoByteMessage(uint8_t b1, uint8_t b2) {};
void usbMidiSendThreeByteMessage(uint8_t b1, uint8_t b2, uint8_t b3) {};
void usbMidiSendRTMessage(uint8_t b) {};
void usbMidiHandleSysEx(const uint8_t *data, uint16_t length, bool complete) {};
void usbMidiInit() {};
void usbMidiUpdate() {};
#else
void usbMidiSendTwoByteMessage(uint8_t b1, uint8_t b2)
{
uint8_t stat = b1 & 0xf0;
uint8_t chan = (b1 & 0x0f)+1;
if(stat == 0xC0) {
usbMIDI.sendProgramChange(b2, chan);
} else if (stat == 0xD0) {
usbMIDI.sendAfterTouch(b2, chan);
}
}
void usbMidiSendThreeByteMessage(uint8_t b1, uint8_t b2, uint8_t b3)
{
uint8_t channel = (b1&0x0F)+1;
switch(midiData[0] & 0xF0) {
case 0x80:
usbMIDI.sendNoteOff(b2, b3, channel);
usbMIDI.send_now();
break;
case 0x90:
usbMIDI.sendNoteOn(b2, b3, channel);
usbMIDI.send_now();
break;
case 0xA0:
usbMIDI.sendPolyPressure(b2, b3, channel);
break;
case 0xB0:
usbMIDI.sendControlChange(b2, b3, channel);
usbMIDI.send_now();
break;
case 0xE0:
unsigned short v = (unsigned short)b3;
v<<=7;
v|=(unsigned short)b2;
usbMIDI.sendPitchBend(v, channel);
break;
}
}
void usbMidiSendRTMessage(uint8_t b)
{
usbMIDI.sendRealTime(b);
}
void usbMidiUpdate()
{
usbMIDI.read();
}
void usbMidiHandleSysEx(const uint8_t *data, uint16_t length, bool complete)
{
if(sysexPosition + length >= longestSysexMessage || (length < 3 && complete)) {
//wrapped!
sysexPosition = 0;
return ;
}
if(sysexPosition == 0 && complete) {
memcpy(&sysexData[0], &data[1], length-2);
sysexPosition += length-2;
} else if (sysexPosition == 0 && !complete) {
memcpy(&sysexData[0], &data[1], length-1);
sysexPosition += length-1;
} else if (!complete) {
memcpy(&sysexData[sysexPosition], &data[0], length);
sysexPosition += length;
} else {
memcpy(&sysexData[sysexPosition], &data[0], length-1);
sysexPosition += length-1;
}
if(complete) {
getSysexData();
}
}
void usbMidiInit()
{
usbMIDI.setHandleSysEx(usbMidiHandleSysEx);
}
#endif
================================================
FILE: Changelog.md
================================================
## Changelog
### 05/19/20
* Arduinoboy to version 1.3.4
* Added support for Arduino Mega 2560 and Arduino UNO Wifi
### 05/17/20
* Arduinoboy to version 1.3.3
* Added support for Arduino Due
### 05/03/20
* Arduinoboy to version 1.3.2
* Added support for Arduino Leonardo/Yún/Micro (ATmega32U4) (only Leonardo tested)
### 04/19/20
* Arduinoboy to version 1.3.1
* Fixed Nanoloop sync through USB (teensy and Leonardo tested)
### 07/10/16
* New Version 1.3.0a, please download from the [Releases] (https://github.com/trash80/Arduinoboy/releases) if you want the most recent stable version.
* Added Teensy 3.x & LC support. Check the main file for the pin configuration.
* Added USB MIDI support for Teensy
* Updated LSDJ LIVEMAP / SYNCMAP mode. This only works with LSDJ Arduinoboy version 4.8.7 and above. Licensed users can [download it here](http://littlesounddj.com/lsd/latest/full_version/lsdj4_8_7-arduinoboy.zip) Livemap has been removed in favor of stable sync slave mode.
### 06/26/15
* Project has been moved to GitHub. mGB has been moved to it's own project [Available here](https://github.com/trash80/mGB)
### 12/23/11
* Arduinoboy to version 1.2.3
* Fixed code to work in Arduino 1.0 Software.
### 09/14/11
* Arduinoboy to version 1.2.2
* Fixed bug in mGB mode causing the Arduinoboy to respond to other MIDI channels besides the ones assigned to mGB.
### 04/03/11
* Arduinoboy to version 1.2.0
* Added EEPROM based settings to all modes which include reassigning MIDI channels in mGB
* Created software editor for Arduinoboy settings. The file is in the zip and requires the free Max Runtime: http://cycling74.com/downloads/
* Added 2 new Modes that require a new version of LSDJ. There is a unofficial release of LSDJ which supports these new modes, available here: http://littlesounddj.com/lsd/latest/full_version
* LIVEMAP / SYNCMAP
* LIVEMAP - Lsdj will use its own clock, but a incoming midi note will cue midi note # to song row # in live mode.
* SYNCMAP - Lsdj will sync to incoming MIDI sync, and notes immediately change the song row #.
* MIDIOUT - LSDJ to MIDIOUT. Each of the 4 gameboy channels send MIDI data on 4 midi channels by the use of effects commands:
* N - Sends a MIDI Note - Absolute to the value placed in the effect. N00 sends note off, N01-N6F send notes 1 to 112.
* Q - Sends a MIDI Note relative to the current channel's pitch. The effect value is a offset. so Q0C in PU1 would send a note 1 octave higher than what Pu1 is currently playing. This is useful as a table command to track midi notes as normal notes in the sequencer.
* X - Sends a MIDI CC - By default in Arduinoboy the high nibble selects a CC#, and the low nibble sends a value [0-F] to [0-127]. This can be changed to allow just 1 midi CC with a range of 00-6F, or 7 CCs with scaled or unscaled values.
* Y - Sends a program/patch/preset change.
### 02/07/09
* Arduinoboy to version 1.1.0
* Changed Gameboy Pins to the Arduino's "Analog In" pins. From the old version's 5,6,7 to A0,A1,A2. This allows better more stable behavior. View the source file for changes. And the new "schematic" at the bottom of the page.
### 02/02/09
* mGB to version 1.3.0
* Rewrote 90% of code into assembly for much faster performance- especially noticeable on DMG.
* Changed note behavior. Removed Monophonic note memory to increase performance.
* Envelope does not retrigger if the notes overlap and have the same velocity- Good for arpeggios / broken chords.
* Note off has a slight delay so immediate retrigged notes don't cause "clicking" effect due to turning off the synth.
* Added screen off mode for great signal-to-noise ratio, longer battery life, and better performance on DMG. (To toggle the screen mode hold Select and press A.)
* Created back-end routine that prioritizes processes for better performance.
* Added 8 "noise" shapes to the Wav synth for more interesting effects.
* Made Wav pitch sweep stable and changed it so it glitches out at values above 8. :D
### 11/05/08
* New Google group created for Arduinoboy and mGB. http://groups.google.com/group/arduinoboy
* New Flickr Group. Share your Arduinoboy pics. :) http://flickr.com/groups/arduinoboy
* mGB to version 1.2.4
* Fixed small bug with the indicator arrow, it was offset vertically a bit.
* Fixed bug with unexpected behavior with large PB Ranges
* PB Range Max is now 48 notes. (hehe)
* Octave Shift max is now -2/+3
* Added some Octave shift logic. If the current note is greater than what the GB can play due to octave shifting, it will select the lower octave note, so no off key notes will play.
* Added Gameboy Color fast-cpu mode- better performance with newer Gameboys.
### 10/28/08
* mGB to version 1.2.3
* Added Note markers above synth number, so you can tell if the synth is on. ;)
* Added PB wheel reset to MIDI panic (Start button)
* Code more efficient (I'm sure there is still more to do here)
* nitro2k01 @ http://gameboygenius.8bitcollective.com rewrote my gamejack serial function to make it as fast as possible. THANKS!!
* Arduinoboy 1.0.5 yet again its just a release to work with mGB 1.2.3 - Everytime the code is sped up on mGB, I remove some delay in Arduinoboy to make the communication faster. This is why you always see a update of Arduinoboy with mGB
### 10/25/08
* Added Program Change messages to mGB
* Rewrote MIDI data input for mGB. (Rewrote the function in ASM to make it faster)
* Added Controller Priority. While changing parameters on the gameboy itself, MIDI messages will not overwrite your changes while your editing them. This is a good live mode feature
* Arduinoboy code updated yet again for mGB behavior. Arduinoboy release will now always be included in a zip file inside the mGB zip so you know that the version of Arduinoboy thats included with the mGB archive is the one to use.
### 10/23/08
* Found & Fixed various bugs in 1.2.0
* Changed help text. Made it more clear.
### 10/23/08
* Added preset load/save memory to mGB. 16 Storage slots for each synth. Recalled via interface or by Midi CC 5 for now, I want to add program change message but would require further rewrites. Check the information below for mGB usage.
* mGB is now rock solid stable *(It needs Arduinoboy 1.0.3 to work properly)*
* Changed mGB interface to use less sprites, as a result the look has changed.
* Arduinoboy 1.0.3 has better behavior for mGB 1.2.0 but should also work better for old mGB versions as well.
### 10/20/08
* Added interface to mGB.
* Changed WAV CC Parameters
* Arduinoboy 1.0.2 has better behavior for mGB 1.1.0
================================================
FILE: Editor/ArduinoBoyEditor-Midi.maxpat
================================================
{
"patcher" : {
"fileversion" : 1,
"appversion" : {
"major" : 7,
"minor" : 2,
"revision" : 1,
"architecture" : "x86",
"modernui" : 1
}
,
"rect" : [ 34.0, 79.0, 708.0, 615.0 ],
"bglocked" : 0,
"openinpresentation" : 1,
"default_fontsize" : 12.0,
"default_fontface" : 0,
"default_fontname" : "Arial",
"gridonopen" : 1,
"gridsize" : [ 15.0, 15.0 ],
"gridsnaponopen" : 1,
"objectsnaponopen" : 1,
"statusbarvisible" : 2,
"toolbarvisible" : 1,
"lefttoolbarpinned" : 0,
"toptoolbarpinned" : 0,
"righttoolbarpinned" : 0,
"bottomtoolbarpinned" : 0,
"toolbars_unpinned_last_save" : 0,
"tallnewobj" : 0,
"boxanimatetime" : 200,
"enablehscroll" : 1,
"enablevscroll" : 1,
"devicewidth" : 0.0,
"description" : "",
"digest" : "",
"tags" : "",
"style" : "",
"subpatcher_template" : "",
"boxes" : [ {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-4",
"linecount" : 3,
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 877.0, 1231.0, 422.0, 47.0 ],
"presentation" : 1,
"presentation_linecount" : 2,
"presentation_rect" : [ 15.0, 10.0, 448.0, 33.0 ],
"style" : "",
"text" : "Select MIDI IN & OUT Port below and plug Arduinoboy 1.2 into the corresponding ports. Wait a few seconds, if the status doesnt change, check your cables."
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-216",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 613.0, 256.0, 168.0, 20.0 ],
"presentation" : 1,
"presentation_rect" : [ 192.0, 58.0, 132.0, 20.0 ],
"style" : "",
"text" : "Arduinoboy Midi Out"
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-215",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 598.0, 241.0, 168.0, 20.0 ],
"presentation" : 1,
"presentation_rect" : [ 30.0, 59.0, 168.0, 20.0 ],
"style" : "",
"text" : "Arduinoboy Midi In"
}
}
, {
"box" : {
"id" : "obj-108",
"maxclass" : "button",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 67.0, 97.0, 20.0, 20.0 ],
"style" : ""
}
}
, {
"box" : {
"allowdrag" : 0,
"fontsize" : 11.595187,
"id" : "obj-111",
"items" : [ "AU DLS Synth 1", ",", "Loopback Bus 1", ",", "Loopback IAC Bus 2", ",", "MIDISPORT 2x2 Port A", ",", "MIDISPORT 2x2 Port B", ",", "Teensy MIDI", ",", "from Max 1", ",", "from Max 2" ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 184.0, 144.0, 115.0, 21.0 ],
"presentation" : 1,
"presentation_rect" : [ 192.0, 78.0, 142.0, 21.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 11.595187,
"id" : "obj-116",
"maxclass" : "newobj",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 184.0, 121.0, 50.0, 21.0 ],
"style" : "",
"text" : "midiinfo"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 11.595187,
"id" : "obj-134",
"maxclass" : "newobj",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 68.0, 121.0, 50.0, 21.0 ],
"style" : "",
"text" : "midiinfo"
}
}
, {
"box" : {
"allowdrag" : 0,
"fontsize" : 11.595187,
"id" : "obj-135",
"items" : [ "Loopback Bus 1", ",", "Loopback IAC Bus 2", ",", "MIDISPORT 2x2 Port A", ",", "MIDISPORT 2x2 Port B", ",", "Teensy MIDI", ",", "to Max 1", ",", "to Max 2" ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 70.0, 145.0, 115.0, 21.0 ],
"presentation" : 1,
"presentation_rect" : [ 30.0, 78.0, 141.0, 21.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 11.595187,
"id" : "obj-136",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 68.0, 73.0, 58.0, 21.0 ],
"style" : "",
"text" : "loadbang"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-8",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 231.0, 196.0, 49.0, 22.0 ],
"style" : "",
"text" : "midiout"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-6",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "int" ],
"patching_rect" : [ 118.0, 187.0, 42.0, 22.0 ],
"style" : "",
"text" : "midiin"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 16.0,
"id" : "obj-180",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 284.0, 777.0, 251.0, 24.0 ],
"presentation" : 1,
"presentation_rect" : [ 376.0, 68.0, 53.0, 24.0 ],
"style" : "",
"text" : "Mode"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-115",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 206.0, 1052.0, 81.0, 22.0 ],
"style" : "",
"text" : "prepend 70 0"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-107",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 1134.0, 1008.0, 48.0, 22.0 ],
"style" : "",
"text" : "r mode"
}
}
, {
"box" : {
"allowdrag" : 0,
"id" : "obj-78",
"items" : [ "1:", "LSDJ", "Slave", "Mode", ",", "2:", "LSDJ", "Master", "Mode", ",", "3:", "LSDJ", "Keyboard", "Mode", ",", "4:", "Nanoloop", "Sync", ",", "5:", "mGB", "Mode", ",", "6:", "LSDJ", "Live/Sync", "Map", ",", "7:", "LSDJ", "MIDI", "Out" ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 1134.0, 1033.0, 145.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 435.0, 70.0, 195.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-10",
"linecount" : 3,
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 573.0, 1216.0, 374.0, 40.0 ],
"presentation" : 1,
"presentation_linecount" : 3,
"presentation_rect" : [ 17.0, 556.0, 374.0, 40.0 ],
"style" : "",
"text" : "Delay between each time aBoy checks the Gameboy for\nnew incomming messages. Lower numbers tend to freeze\nLSDJ. Default is 40us with a multiplier of 1",
"textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-106",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 730.0, 1196.0, 81.0, 18.0 ],
"presentation" : 1,
"presentation_rect" : [ 174.0, 536.0, 81.0, 18.0 ],
"style" : "",
"text" : "MULTIPLIER"
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-105",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 574.0, 1196.0, 128.0, 18.0 ],
"presentation" : 1,
"presentation_rect" : [ 16.0, 536.0, 99.0, 18.0 ],
"style" : "",
"text" : "BIT CHECK DELAY"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 16.0,
"id" : "obj-77",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 574.0, 1165.0, 317.0, 24.0 ],
"presentation" : 1,
"presentation_rect" : [ 18.0, 505.0, 317.0, 24.0 ],
"style" : "",
"text" : "LSDJ MIDI OUT Mode Advanced Settings",
"textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-46",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 798.0, 1195.0, 50.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 242.0, 535.0, 50.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-45",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 674.0, 1195.0, 50.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 118.0, 535.0, 50.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-51",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 1115.0, 1124.0, 140.0, 22.0 ],
"style" : "",
"text" : "r midiout_bytedelaymulti"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-12",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 990.0, 1126.0, 115.0, 22.0 ],
"style" : "",
"text" : "r midiout_bytedelay"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-14",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 798.0, 1125.0, 130.0, 22.0 ],
"style" : "",
"text" : "r midiout_bitdelaymulti"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-44",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 674.0, 1126.0, 105.0, 22.0 ],
"style" : "",
"text" : "r midiout_bitdelay"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-2",
"maxclass" : "message",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 372.0, 1124.0, 117.0, 22.0 ],
"style" : "",
"text" : "240 105 71 127 247"
}
}
, {
"box" : {
"bgcolor" : [ 0.72549, 0.72549, 0.72549, 1.0 ],
"bgcolor2" : [ 0.34902, 0.34902, 0.34902, 1.0 ],
"bgfillcolor_angle" : 270.0,
"bgfillcolor_autogradient" : 0.0,
"bgfillcolor_color" : [ 0.290196, 0.309804, 0.301961, 1.0 ],
"bgfillcolor_color1" : [ 0.72549, 0.72549, 0.72549, 1.0 ],
"bgfillcolor_color2" : [ 0.34902, 0.34902, 0.34902, 1.0 ],
"bgfillcolor_proportion" : 0.39,
"bgfillcolor_type" : "gradient",
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 16.0,
"gradient" : 1,
"id" : "obj-3",
"maxclass" : "message",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 376.0, 1084.0, 138.0, 26.0 ],
"presentation" : 1,
"presentation_rect" : [ 377.0, 466.0, 138.0, 26.0 ],
"style" : "",
"text" : "Restore Defaults",
"textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-43",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 86.0, 1178.0, 43.0, 22.0 ],
"style" : "",
"text" : "s sout"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-18",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 93.0, 1115.0, 101.0, 22.0 ],
"style" : "",
"text" : "prepend 240 105"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-17",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 87.0, 1070.0, 97.0, 22.0 ],
"style" : "",
"text" : "append 127 247"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-7",
"maxclass" : "message",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 925.0, 1119.0, 64.0, 22.0 ],
"style" : "",
"text" : "5"
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-237",
"linecount" : 2,
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 628.0, 271.0, 221.0, 33.0 ],
"presentation" : 1,
"presentation_rect" : [ 11.0, 469.0, 355.0, 20.0 ],
"style" : "",
"text" : "trash80.loves.you.only.sometimes.love. 2010",
"textcolor" : [ 0.682353, 0.682353, 0.682353, 1.0 ]
}
}
, {
"box" : {
"bgcolor" : [ 0.529412, 0.690196, 0.545098, 1.0 ],
"bgcolor2" : [ 0.188235, 0.431373, 0.211765, 1.0 ],
"bgfillcolor_angle" : 270.0,
"bgfillcolor_autogradient" : 0.0,
"bgfillcolor_color" : [ 0.290196, 0.309804, 0.301961, 1.0 ],
"bgfillcolor_color1" : [ 0.529412, 0.690196, 0.545098, 1.0 ],
"bgfillcolor_color2" : [ 0.188235, 0.431373, 0.211765, 1.0 ],
"bgfillcolor_proportion" : 0.39,
"bgfillcolor_type" : "gradient",
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 16.0,
"gradient" : 1,
"id" : "obj-235",
"linecount" : 2,
"maxclass" : "message",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 928.0, 1042.0, 161.0, 44.0 ],
"presentation" : 1,
"presentation_rect" : [ 518.0, 466.0, 180.0, 26.0 ],
"style" : "",
"text" : "Send & Save Changes",
"textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
}
}
, {
"box" : {
"id" : "obj-234",
"maxclass" : "button",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 360.0, 269.0, 20.0, 20.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-233",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 360.0, 313.0, 47.0, 22.0 ],
"style" : "",
"text" : "s reset"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 11.595187,
"id" : "obj-214",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 834.0, 92.0, 133.0, 21.0 ],
"style" : "",
"text" : "prepend bgcolor 0.5 0 0"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-211",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 833.0, 54.0, 63.0, 22.0 ],
"style" : "",
"text" : "r statusint"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 11.595187,
"id" : "obj-209",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patcher" : {
"fileversion" : 1,
"appversion" : {
"major" : 7,
"minor" : 2,
"revision" : 1,
"architecture" : "x86",
"modernui" : 1
}
,
"rect" : [ 25.0, 47.0, 152.0, 172.0 ],
"bglocked" : 0,
"openinpresentation" : 0,
"default_fontsize" : 10.0,
"default_fontface" : 0,
"default_fontname" : "Arial",
"gridonopen" : 1,
"gridsize" : [ 15.0, 15.0 ],
"gridsnaponopen" : 1,
"objectsnaponopen" : 1,
"statusbarvisible" : 2,
"toolbarvisible" : 1,
"lefttoolbarpinned" : 0,
"toptoolbarpinned" : 0,
"righttoolbarpinned" : 0,
"bottomtoolbarpinned" : 0,
"toolbars_unpinned_last_save" : 0,
"tallnewobj" : 0,
"boxanimatetime" : 200,
"enablehscroll" : 1,
"enablevscroll" : 1,
"devicewidth" : 0.0,
"description" : "",
"digest" : "",
"tags" : "",
"style" : "",
"subpatcher_template" : "",
"boxes" : [ {
"box" : {
"fontname" : "Arial",
"fontsize" : 11.595187,
"id" : "obj-47",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 32.0, 31.0, 68.0, 20.0 ],
"style" : "",
"text" : "loadmess 1"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 11.595187,
"id" : "obj-45",
"maxclass" : "newobj",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 32.0, 55.75, 54.0, 20.0 ],
"style" : "",
"text" : "metro 20"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 11.595187,
"id" : "obj-44",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 32.0, 103.75, 83.0, 20.0 ],
"style" : "",
"text" : "prepend angle"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 11.595187,
"id" : "obj-43",
"maxclass" : "newobj",
"numinlets" : 5,
"numoutlets" : 4,
"outlettype" : [ "int", "", "", "int" ],
"patching_rect" : [ 32.0, 79.75, 79.0, 20.0 ],
"style" : "",
"text" : "counter 0 359"
}
}
, {
"box" : {
"comment" : "",
"id" : "obj-51",
"maxclass" : "outlet",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 32.0, 127.75, 25.0, 25.0 ],
"style" : ""
}
}
],
"lines" : [ {
"patchline" : {
"destination" : [ "obj-44", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-43", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-51", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-44", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-43", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-45", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-45", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-47", 0 ]
}
}
]
}
,
"patching_rect" : [ 1048.0, 117.0, 71.0, 21.0 ],
"saved_object_attributes" : {
"description" : "",
"digest" : "",
"fontsize" : 10.0,
"globalpatchername" : "",
"style" : "",
"tags" : ""
}
,
"style" : "",
"text" : "p automove"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-207",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 823.0, 199.0, 74.0, 22.0 ],
"style" : "",
"text" : "prepend set"
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 16.0,
"id" : "obj-206",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1072.0, 243.0, 216.0, 24.0 ],
"presentation" : 1,
"presentation_rect" : [ 548.0, 14.0, 137.0, 24.0 ],
"style" : "",
"text" : "Connected",
"textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-205",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 823.0, 165.0, 50.0, 22.0 ],
"style" : "",
"text" : "r status"
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 16.0,
"id" : "obj-203",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 583.0, 226.0, 216.0, 24.0 ],
"presentation" : 1,
"presentation_rect" : [ 475.0, 14.0, 216.0, 24.0 ],
"style" : "",
"text" : "Status"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-202",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 1188.0, 805.0, 79.0, 22.0 ],
"style" : "",
"text" : "r livemap_ch"
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-198",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1146.0, 915.0, 139.0, 18.0 ],
"presentation" : 1,
"presentation_rect" : [ 422.0, 251.0, 139.0, 18.0 ],
"style" : "",
"text" : "Midi Channel"
}
}
, {
"box" : {
"allowdrag" : 0,
"id" : "obj-199",
"items" : [ 1, ",", 2, ",", 3, ",", 4, ",", 5, ",", 6, ",", 7, ",", 8, ",", 9, ",", 10, ",", 11, ",", 12, ",", 13, ",", 14, ",", 15, ",", 16 ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 1146.0, 932.0, 72.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 422.0, 268.0, 72.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 16.0,
"id" : "obj-200",
"linecount" : 2,
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1144.0, 881.0, 225.0, 42.0 ],
"presentation" : 1,
"presentation_rect" : [ 419.0, 220.0, 281.0, 24.0 ],
"style" : "",
"text" : "LSDJ LIVEMAP/SYNCMAP Settings",
"textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
}
}
, {
"box" : {
"angle" : 74.590027,
"grad1" : [ 0.047059, 0.611765, 0.913725, 1.0 ],
"grad2" : [ 0.047059, 0.698039, 0.913725, 1.0 ],
"id" : "obj-201",
"maxclass" : "panel",
"mode" : 1,
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1132.0, 870.0, 279.0, 95.0 ],
"presentation" : 1,
"presentation_rect" : [ 412.0, 210.0, 285.0, 94.0 ],
"proportion" : 0.39,
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-72",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 1298.0, 499.0, 67.0, 22.0 ],
"style" : "",
"text" : "r mgb_ch5"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-194",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 1284.0, 478.0, 67.0, 22.0 ],
"style" : "",
"text" : "r mgb_ch4"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-195",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 1271.0, 457.0, 67.0, 22.0 ],
"style" : "",
"text" : "r mgb_ch3"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-196",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 1257.0, 436.0, 67.0, 22.0 ],
"style" : "",
"text" : "r mgb_ch2"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-197",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 1244.0, 415.0, 67.0, 22.0 ],
"style" : "",
"text" : "r mgb_ch1"
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-192",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1324.0, 674.0, 79.0, 18.0 ],
"presentation" : 1,
"presentation_rect" : [ 321.0, 251.0, 79.0, 18.0 ],
"style" : "",
"text" : "POLY Channel"
}
}
, {
"box" : {
"allowdrag" : 0,
"id" : "obj-193",
"items" : [ 1, ",", 2, ",", 3, ",", 4, ",", 5, ",", 6, ",", 7, ",", 8, ",", 9, ",", 10, ",", 11, ",", 12, ",", 13, ",", 14, ",", 15, ",", 16 ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 1324.0, 691.0, 72.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 321.0, 268.0, 72.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-190",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1247.0, 674.0, 79.0, 18.0 ],
"presentation" : 1,
"presentation_rect" : [ 244.0, 251.0, 79.0, 18.0 ],
"style" : "",
"text" : "NOI Channel"
}
}
, {
"box" : {
"allowdrag" : 0,
"id" : "obj-191",
"items" : [ 1, ",", 2, ",", 3, ",", 4, ",", 5, ",", 6, ",", 7, ",", 8, ",", 9, ",", 10, ",", 11, ",", 12, ",", 13, ",", 14, ",", 15, ",", 16 ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 1247.0, 691.0, 72.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 244.0, 268.0, 72.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-188",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1172.0, 674.0, 79.0, 18.0 ],
"presentation" : 1,
"presentation_rect" : [ 169.0, 251.0, 79.0, 18.0 ],
"style" : "",
"text" : "WAV Channel"
}
}
, {
"box" : {
"allowdrag" : 0,
"id" : "obj-189",
"items" : [ 1, ",", 2, ",", 3, ",", 4, ",", 5, ",", 6, ",", 7, ",", 8, ",", 9, ",", 10, ",", 11, ",", 12, ",", 13, ",", 14, ",", 15, ",", 16 ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 1172.0, 691.0, 72.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 169.0, 268.0, 72.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-186",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1098.0, 675.0, 79.0, 18.0 ],
"presentation" : 1,
"presentation_rect" : [ 95.0, 252.0, 79.0, 18.0 ],
"style" : "",
"text" : "PU2 Channel"
}
}
, {
"box" : {
"allowdrag" : 0,
"id" : "obj-187",
"items" : [ 1, ",", 2, ",", 3, ",", 4, ",", 5, ",", 6, ",", 7, ",", 8, ",", 9, ",", 10, ",", 11, ",", 12, ",", 13, ",", 14, ",", 15, ",", 16 ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 1098.0, 692.0, 72.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 95.0, 269.0, 72.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-182",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1024.0, 675.0, 79.0, 18.0 ],
"presentation" : 1,
"presentation_rect" : [ 21.0, 252.0, 79.0, 18.0 ],
"style" : "",
"text" : "PU1 Channel"
}
}
, {
"box" : {
"allowdrag" : 0,
"id" : "obj-183",
"items" : [ 1, ",", 2, ",", 3, ",", 4, ",", 5, ",", 6, ",", 7, ",", 8, ",", 9, ",", 10, ",", 11, ",", 12, ",", 13, ",", 14, ",", 15, ",", 16 ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 1024.0, 692.0, 72.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 21.0, 269.0, 72.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 16.0,
"id" : "obj-184",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1022.0, 641.0, 225.0, 24.0 ],
"presentation" : 1,
"presentation_rect" : [ 19.0, 221.0, 225.0, 24.0 ],
"style" : "",
"text" : "mGB Midi Settings",
"textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
}
}
, {
"box" : {
"angle" : 74.590027,
"grad1" : [ 0.047059, 0.611765, 0.913725, 1.0 ],
"grad2" : [ 0.047059, 0.698039, 0.913725, 1.0 ],
"id" : "obj-185",
"maxclass" : "panel",
"mode" : 1,
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1010.0, 630.0, 402.0, 94.0 ],
"presentation" : 1,
"presentation_rect" : [ 7.0, 210.0, 402.0, 94.0 ],
"proportion" : 0.39,
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-172",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 1035.0, 493.0, 95.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn47"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-173",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 1021.0, 471.0, 95.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn46"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-174",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 1007.0, 450.0, 95.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn45"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-175",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 992.0, 429.0, 95.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn44"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-176",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 980.0, 408.0, 95.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn43"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-177",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 966.0, 387.0, 95.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn42"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-178",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 953.0, 366.0, 95.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn41"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-165",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 884.0, 493.0, 95.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn37"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-166",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 869.0, 471.0, 95.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn36"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-167",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 856.0, 450.0, 95.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn35"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-168",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 842.0, 429.0, 95.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn34"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-169",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 829.0, 408.0, 95.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn33"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-170",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 815.0, 387.0, 95.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn32"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-171",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 802.0, 366.0, 95.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn31"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-158",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 740.0, 493.0, 95.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn27"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-159",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 725.0, 471.0, 95.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn26"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-160",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 712.0, 450.0, 95.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn25"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-161",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 698.0, 429.0, 95.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn24"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-162",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 685.0, 408.0, 95.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn23"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-163",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 671.0, 387.0, 95.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn22"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-164",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 658.0, 366.0, 95.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn21"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-157",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 616.0, 494.0, 95.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn17"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-141",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 601.0, 472.0, 95.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn16"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-142",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 588.0, 451.0, 95.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn15"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-143",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 574.0, 430.0, 95.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn14"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-144",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 561.0, 409.0, 95.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn13"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-145",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 547.0, 388.0, 95.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn12"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-42",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 534.0, 367.0, 94.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccn11"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-146",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 1002.0, 852.0, 88.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccs4"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-147",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 989.0, 831.0, 88.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccs3"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-148",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 975.0, 810.0, 88.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccs2"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-149",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 962.0, 789.0, 88.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccs1"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-150",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 549.0, 704.0, 92.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccm4"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-30",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 536.0, 683.0, 92.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccm3"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-31",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 522.0, 662.0, 92.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccm2"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-151",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 509.0, 641.0, 92.0, 22.0 ],
"style" : "",
"text" : "r midiout_ccm1"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-152",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 117.0, 817.0, 89.0, 22.0 ],
"style" : "",
"text" : "r midiout_cch4"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-153",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 105.0, 796.0, 89.0, 22.0 ],
"style" : "",
"text" : "r midiout_cch3"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-27",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 90.0, 775.0, 89.0, 22.0 ],
"style" : "",
"text" : "r midiout_cch2"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-28",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 77.0, 754.0, 89.0, 22.0 ],
"style" : "",
"text" : "r midiout_cch1"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-24",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 76.0, 732.0, 89.0, 22.0 ],
"style" : "",
"text" : "r midiout_nch4"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-154",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 63.0, 710.0, 89.0, 22.0 ],
"style" : "",
"text" : "r midiout_nch3"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-155",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 49.0, 688.0, 89.0, 22.0 ],
"style" : "",
"text" : "r midiout_nch2"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-156",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 36.0, 666.0, 89.0, 22.0 ],
"style" : "",
"text" : "r midiout_nch1"
}
}
, {
"box" : {
"allowdrag" : 0,
"id" : "obj-117",
"items" : [ 1, "CC", "with", "range", "0-6F", ",", 7, "CCs", "with", "range", "0-F" ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 495.0, 871.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 237.0, 427.0, 69.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-118",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 761.0, 871.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 519.0, 427.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-119",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 719.0, 871.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 477.0, 427.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-120",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 677.0, 871.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 435.0, 427.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-121",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 635.0, 871.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 393.0, 427.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-122",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 593.0, 871.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 351.0, 427.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-123",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 551.0, 871.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 309.0, 427.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-124",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 449.0, 871.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 194.0, 427.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"allowdrag" : 0,
"id" : "obj-125",
"items" : [ "Use", "Exact", "Value", ",", "Spread", "value", "from", 0, "to", 127 ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 814.0, 871.0, 119.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 563.0, 427.0, 119.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"allowdrag" : 0,
"id" : "obj-126",
"items" : [ 1, ",", 2, ",", 3, ",", 4, ",", 5, ",", 6, ",", 7, ",", 8, ",", 9, ",", 10, ",", 11, ",", 12, ",", 13, ",", 14, ",", 15, ",", 16 ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 374.0, 871.0, 72.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 121.0, 427.0, 72.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-127",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 268.0, 872.0, 31.0, 18.0 ],
"presentation" : 1,
"presentation_rect" : [ 15.0, 428.0, 31.0, 18.0 ],
"style" : "",
"text" : "NOI"
}
}
, {
"box" : {
"allowdrag" : 0,
"id" : "obj-128",
"items" : [ 1, ",", 2, ",", 3, ",", 4, ",", 5, ",", 6, ",", 7, ",", 8, ",", 9, ",", 10, ",", 11, ",", 12, ",", 13, ",", 14, ",", 15, ",", 16 ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 300.0, 871.0, 72.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 48.0, 427.0, 72.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"allowdrag" : 0,
"id" : "obj-92",
"items" : [ 1, "CC", "with", "range", "0-6F", ",", 7, "CCs", "with", "range", "0-F" ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 496.0, 850.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 237.0, 406.0, 69.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-93",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 762.0, 850.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 519.0, 406.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-94",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 720.0, 850.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 477.0, 406.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-95",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 678.0, 850.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 435.0, 406.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-96",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 636.0, 850.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 393.0, 406.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-97",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 594.0, 850.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 351.0, 406.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-98",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 552.0, 850.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 309.0, 406.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-99",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 450.0, 850.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 194.0, 406.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"allowdrag" : 0,
"id" : "obj-100",
"items" : [ "Use", "Exact", "Value", ",", "Spread", "value", "from", 0, "to", 127 ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 815.0, 850.0, 119.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 563.0, 406.0, 119.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"allowdrag" : 0,
"id" : "obj-101",
"items" : [ 1, ",", 2, ",", 3, ",", 4, ",", 5, ",", 6, ",", 7, ",", 8, ",", 9, ",", 10, ",", 11, ",", 12, ",", 13, ",", 14, ",", 15, ",", 16 ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 375.0, 850.0, 72.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 121.0, 406.0, 72.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-102",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 269.0, 851.0, 31.0, 18.0 ],
"presentation" : 1,
"presentation_rect" : [ 16.0, 407.0, 31.0, 18.0 ],
"style" : "",
"text" : "WAV"
}
}
, {
"box" : {
"allowdrag" : 0,
"id" : "obj-103",
"items" : [ 1, ",", 2, ",", 3, ",", 4, ",", 5, ",", 6, ",", 7, ",", 8, ",", 9, ",", 10, ",", 11, ",", 12, ",", 13, ",", 14, ",", 15, ",", 16 ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 301.0, 850.0, 72.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 48.0, 406.0, 72.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"allowdrag" : 0,
"id" : "obj-79",
"items" : [ 1, "CC", "with", "range", "0-6F", ",", 7, "CCs", "with", "range", "0-F" ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 496.0, 829.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 237.0, 385.0, 69.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-80",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 762.0, 829.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 519.0, 385.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-81",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 720.0, 829.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 477.0, 385.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-82",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 678.0, 829.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 435.0, 385.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-84",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 636.0, 829.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 393.0, 385.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-85",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 594.0, 829.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 351.0, 385.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-86",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 552.0, 829.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 309.0, 385.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-87",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 450.0, 829.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 194.0, 385.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"allowdrag" : 0,
"id" : "obj-88",
"items" : [ "Use", "Exact", "Value", ",", "Spread", "value", "from", 0, "to", 127 ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 815.0, 829.0, 119.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 563.0, 385.0, 119.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"allowdrag" : 0,
"id" : "obj-89",
"items" : [ 1, ",", 2, ",", 3, ",", 4, ",", 5, ",", 6, ",", 7, ",", 8, ",", 9, ",", 10, ",", 11, ",", 12, ",", 13, ",", 14, ",", 15, ",", 16 ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 375.0, 829.0, 72.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 121.0, 385.0, 72.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-90",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 269.0, 830.0, 31.0, 18.0 ],
"presentation" : 1,
"presentation_rect" : [ 16.0, 386.0, 31.0, 18.0 ],
"style" : "",
"text" : "PU2"
}
}
, {
"box" : {
"allowdrag" : 0,
"id" : "obj-91",
"items" : [ 1, ",", 2, ",", 3, ",", 4, ",", 5, ",", 6, ",", 7, ",", 8, ",", 9, ",", 10, ",", 11, ",", 12, ",", 13, ",", 14, ",", 15, ",", 16 ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 301.0, 829.0, 72.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 48.0, 385.0, 72.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"allowdrag" : 0,
"id" : "obj-76",
"items" : [ 1, "CC", "with", "range", "0-6F", ",", 7, "CCs", "with", "range", "0-F" ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 491.0, 776.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 237.0, 364.0, 69.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-75",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 495.0, 789.0, 53.0, 18.0 ],
"presentation" : 1,
"presentation_rect" : [ 242.0, 345.0, 53.0, 18.0 ],
"style" : "",
"text" : "CC Mode"
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-74",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 817.0, 789.0, 73.0, 18.0 ],
"presentation" : 1,
"presentation_rect" : [ 565.0, 345.0, 73.0, 18.0 ],
"style" : "",
"text" : "CC SCALING"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-70",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 762.0, 808.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 519.0, 364.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-71",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 763.0, 789.0, 36.0, 18.0 ],
"presentation" : 1,
"presentation_rect" : [ 520.0, 345.0, 36.0, 18.0 ],
"style" : "",
"text" : "CC#6"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-68",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 720.0, 808.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 477.0, 364.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-69",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 721.0, 789.0, 36.0, 18.0 ],
"presentation" : 1,
"presentation_rect" : [ 478.0, 345.0, 36.0, 18.0 ],
"style" : "",
"text" : "CC#5"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-64",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 678.0, 808.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 435.0, 364.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-65",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 679.0, 789.0, 36.0, 18.0 ],
"presentation" : 1,
"presentation_rect" : [ 436.0, 345.0, 36.0, 18.0 ],
"style" : "",
"text" : "CC#4"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-66",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 636.0, 808.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 393.0, 364.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-67",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 637.0, 789.0, 36.0, 18.0 ],
"presentation" : 1,
"presentation_rect" : [ 394.0, 345.0, 36.0, 18.0 ],
"style" : "",
"text" : "CC#3"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-62",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 594.0, 808.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 351.0, 364.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-63",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 595.0, 789.0, 36.0, 18.0 ],
"presentation" : 1,
"presentation_rect" : [ 352.0, 345.0, 36.0, 18.0 ],
"style" : "",
"text" : "CC#2"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-60",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 458.0, 725.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 309.0, 364.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-61",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 553.0, 789.0, 36.0, 18.0 ],
"presentation" : 1,
"presentation_rect" : [ 310.0, 345.0, 36.0, 18.0 ],
"style" : "",
"text" : "CC#1"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-59",
"maxclass" : "number",
"maximum" : 127,
"minimum" : 1,
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 417.0, 725.0, 41.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 194.0, 364.0, 41.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-55",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 451.0, 789.0, 36.0, 18.0 ],
"presentation" : 1,
"presentation_rect" : [ 198.0, 345.0, 36.0, 18.0 ],
"style" : "",
"text" : "CC#0"
}
}
, {
"box" : {
"allowdrag" : 0,
"id" : "obj-56",
"items" : [ "Use", "Exact", "Value", ",", "Spread", "value", "from", 0, "to", 127 ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 815.0, 808.0, 119.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 563.0, 364.0, 119.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-54",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 373.0, 789.0, 71.0, 18.0 ],
"presentation" : 1,
"presentation_rect" : [ 120.0, 345.0, 71.0, 18.0 ],
"style" : "",
"text" : "CC MIDI CH"
}
}
, {
"box" : {
"allowdrag" : 0,
"id" : "obj-53",
"items" : [ 1, ",", 2, ",", 3, ",", 4, ",", 5, ",", 6, ",", 7, ",", 8, ",", 9, ",", 10, ",", 11, ",", 12, ",", 13, ",", 14, ",", 15, ",", 16 ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 375.0, 808.0, 72.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 121.0, 364.0, 72.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-52",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 298.0, 789.0, 74.0, 18.0 ],
"presentation" : 1,
"presentation_rect" : [ 45.0, 345.0, 74.0, 18.0 ],
"style" : "",
"text" : "Note MIDI CH"
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-49",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 269.0, 809.0, 31.0, 18.0 ],
"presentation" : 1,
"presentation_rect" : [ 16.0, 365.0, 31.0, 18.0 ],
"style" : "",
"text" : "PU1"
}
}
, {
"box" : {
"allowdrag" : 0,
"id" : "obj-50",
"items" : [ 1, ",", 2, ",", 3, ",", 4, ",", 5, ",", 6, ",", 7, ",", 8, ",", 9, ",", 10, ",", 11, ",", 12, ",", 13, ",", 14, ",", 15, ",", 16 ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 301.0, 808.0, 72.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 48.0, 364.0, 72.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 16.0,
"id" : "obj-47",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 269.0, 762.0, 251.0, 24.0 ],
"presentation" : 1,
"presentation_rect" : [ 19.0, 318.0, 251.0, 24.0 ],
"style" : "",
"text" : "LSDJ MIDI OUT Mode Settings",
"textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
}
}
, {
"box" : {
"angle" : 74.590027,
"grad1" : [ 0.047059, 0.611765, 0.913725, 1.0 ],
"grad2" : [ 0.047059, 0.698039, 0.913725, 1.0 ],
"id" : "obj-48",
"maxclass" : "panel",
"mode" : 1,
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 257.0, 751.0, 692.0, 153.0 ],
"presentation" : 1,
"presentation_rect" : [ 8.0, 307.0, 690.0, 156.0 ],
"proportion" : 0.39,
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-41",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 239.0, 562.0, 84.0, 22.0 ],
"style" : "",
"text" : "r sync_midich"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-40",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 146.0, 439.0, 96.0, 22.0 ],
"style" : "",
"text" : "r master_midich"
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-36",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 239.0, 653.0, 139.0, 18.0 ],
"presentation" : 1,
"presentation_rect" : [ 23.0, 155.0, 139.0, 18.0 ],
"style" : "",
"text" : "Midi Channel"
}
}
, {
"box" : {
"allowdrag" : 0,
"id" : "obj-37",
"items" : [ 1, ",", 2, ",", 3, ",", 4, ",", 5, ",", 6, ",", 7, ",", 8, ",", 9, ",", 10, ",", 11, ",", 12, ",", 13, ",", 14, ",", 15, ",", 16 ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 239.0, 670.0, 72.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 97.0, 155.0, 72.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 16.0,
"id" : "obj-38",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 237.0, 619.0, 225.0, 24.0 ],
"presentation" : 1,
"presentation_rect" : [ 19.0, 123.0, 206.0, 24.0 ],
"style" : "",
"text" : "LSDJ Slave Mode Settings",
"textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
}
}
, {
"box" : {
"angle" : 74.590027,
"grad1" : [ 0.047059, 0.611765, 0.913725, 1.0 ],
"grad2" : [ 0.047059, 0.698039, 0.913725, 1.0 ],
"id" : "obj-39",
"maxclass" : "panel",
"mode" : 1,
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 225.0, 608.0, 279.0, 95.0 ],
"presentation" : 1,
"presentation_rect" : [ 7.0, 111.0, 228.0, 96.0 ],
"proportion" : 0.39,
"style" : ""
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-32",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 147.0, 502.0, 139.0, 18.0 ],
"presentation" : 1,
"presentation_rect" : [ 254.0, 155.0, 139.0, 18.0 ],
"style" : "",
"text" : "Midi Channel"
}
}
, {
"box" : {
"allowdrag" : 0,
"id" : "obj-33",
"items" : [ 1, ",", 2, ",", 3, ",", 4, ",", 5, ",", 6, ",", 7, ",", 8, ",", 9, ",", 10, ",", 11, ",", 12, ",", 13, ",", 14, ",", 15, ",", 16 ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 147.0, 519.0, 72.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 328.0, 155.0, 72.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 16.0,
"id" : "obj-34",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 145.0, 468.0, 225.0, 24.0 ],
"presentation" : 1,
"presentation_rect" : [ 250.0, 123.0, 212.0, 24.0 ],
"style" : "",
"text" : "LSDJ Master Mode Settings",
"textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
}
}
, {
"box" : {
"angle" : 74.590027,
"grad1" : [ 0.047059, 0.611765, 0.913725, 1.0 ],
"grad2" : [ 0.047059, 0.698039, 0.913725, 1.0 ],
"id" : "obj-35",
"maxclass" : "panel",
"mode" : 1,
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 133.0, 457.0, 279.0, 95.0 ],
"presentation" : 1,
"presentation_rect" : [ 238.0, 111.0, 228.0, 96.0 ],
"proportion" : 0.39,
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-29",
"maxclass" : "newobj",
"numinlets" : 60,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 82.0, 1003.0, 815.5, 22.0 ],
"style" : "",
"text" : "pack 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-26",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 100.0, 312.0, 107.0, 22.0 ],
"style" : "",
"text" : "r kb_compatmode"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-20",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 86.0, 291.0, 72.0, 22.0 ],
"style" : "",
"text" : "r kb_midich"
}
}
, {
"box" : {
"id" : "obj-25",
"maxclass" : "toggle",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "int" ],
"parameter_enable" : 0,
"patching_rect" : [ 188.0, 404.0, 20.0, 20.0 ],
"presentation" : 1,
"presentation_rect" : [ 610.0, 176.0, 20.0, 20.0 ],
"style" : ""
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-23",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 208.0, 405.0, 139.0, 18.0 ],
"presentation" : 1,
"presentation_rect" : [ 485.0, 178.0, 139.0, 18.0 ],
"style" : "",
"text" : "Compatability Mode"
}
}
, {
"box" : {
"fontface" : 1,
"fontname" : "Arial",
"fontsize" : 10.0,
"id" : "obj-22",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 97.0, 387.0, 139.0, 18.0 ],
"presentation" : 1,
"presentation_rect" : [ 485.0, 154.0, 139.0, 18.0 ],
"style" : "",
"text" : "Midi Channel"
}
}
, {
"box" : {
"allowdrag" : 0,
"id" : "obj-21",
"items" : [ 1, ",", 2, ",", 3, ",", 4, ",", 5, ",", 6, ",", 7, ",", 8, ",", 9, ",", 10, ",", 11, ",", 12, ",", 13, ",", 14, ",", 15, ",", 16 ],
"maxclass" : "umenu",
"numinlets" : 1,
"numoutlets" : 3,
"outlettype" : [ "int", "", "" ],
"parameter_enable" : 0,
"patching_rect" : [ 97.0, 404.0, 72.0, 22.0 ],
"presentation" : 1,
"presentation_rect" : [ 559.0, 154.0, 72.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 16.0,
"id" : "obj-19",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 95.0, 353.0, 198.0, 24.0 ],
"presentation" : 1,
"presentation_rect" : [ 481.0, 122.0, 198.0, 24.0 ],
"style" : "",
"text" : "Keyboard Mode Settings",
"textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-15",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 0,
"patcher" : {
"fileversion" : 1,
"appversion" : {
"major" : 7,
"minor" : 2,
"revision" : 1,
"architecture" : "x86",
"modernui" : 1
}
,
"rect" : [ 169.0, 153.0, 1400.0, 794.0 ],
"bglocked" : 0,
"openinpresentation" : 0,
"default_fontsize" : 12.0,
"default_fontface" : 0,
"default_fontname" : "Arial",
"gridonopen" : 1,
"gridsize" : [ 15.0, 15.0 ],
"gridsnaponopen" : 1,
"objectsnaponopen" : 1,
"statusbarvisible" : 2,
"toolbarvisible" : 1,
"lefttoolbarpinned" : 0,
"toptoolbarpinned" : 0,
"righttoolbarpinned" : 0,
"bottomtoolbarpinned" : 0,
"toolbars_unpinned_last_save" : 0,
"tallnewobj" : 0,
"boxanimatetime" : 200,
"enablehscroll" : 1,
"enablevscroll" : 1,
"devicewidth" : 0.0,
"description" : "",
"digest" : "",
"tags" : "",
"style" : "",
"subpatcher_template" : "",
"boxes" : [ {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-50",
"maxclass" : "message",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 985.0, 531.0, 117.0, 22.0 ],
"style" : "",
"text" : "240 105 72 127 247"
}
}
, {
"box" : {
"id" : "obj-43",
"maxclass" : "button",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 985.0, 497.0, 20.0, 20.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-8",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 1011.0, 368.0, 63.0, 22.0 ],
"style" : "",
"text" : "r statusint"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-2",
"maxclass" : "newobj",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 1011.0, 411.0, 44.0, 22.0 ],
"style" : "",
"text" : "gate 1"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-51",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1465.0, 803.0, 142.0, 22.0 ],
"style" : "",
"text" : "s midiout_bytedelaymulti"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-52",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1452.0, 782.0, 117.0, 22.0 ],
"style" : "",
"text" : "s midiout_bytedelay"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-53",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1438.0, 761.0, 132.0, 22.0 ],
"style" : "",
"text" : "s midiout_bitdelaymulti"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-54",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1425.0, 740.0, 107.0, 22.0 ],
"style" : "",
"text" : "s midiout_bitdelay"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-49",
"maxclass" : "number",
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 675.0, 908.0, 50.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-45",
"maxclass" : "number",
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 635.0, 936.0, 50.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-46",
"maxclass" : "number",
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 621.0, 854.0, 50.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-47",
"maxclass" : "number",
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 607.0, 879.0, 50.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-233",
"maxclass" : "newobj",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 227.0, 486.0, 45.0, 22.0 ],
"style" : "",
"text" : "r reset"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-126",
"maxclass" : "message",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 760.0, 515.0, 131.0, 22.0 ],
"style" : "",
"text" : "240 105 66 1 3 69 247"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-121",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 760.0, 569.0, 43.0, 22.0 ],
"style" : "",
"text" : "s sout"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-123",
"maxclass" : "newobj",
"numinlets" : 4,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 761.0, 483.0, 199.0, 22.0 ],
"style" : "",
"text" : "if $i3 == 105 && $i4==65 then bang"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-120",
"maxclass" : "message",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 270.0, 717.0, 32.5, 22.0 ],
"style" : "",
"text" : "1"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-119",
"maxclass" : "message",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 347.0, 717.0, 32.5, 22.0 ],
"style" : "",
"text" : "0"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-118",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 400.0, 754.0, 65.0, 22.0 ],
"style" : "",
"text" : "s statusint"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-117",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 296.0, 759.0, 52.0, 22.0 ],
"style" : "",
"text" : "s status"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-116",
"maxclass" : "message",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 238.0, 696.0, 83.0, 22.0 ],
"style" : "",
"text" : "Disconnected"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-115",
"maxclass" : "message",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 335.0, 695.0, 69.0, 22.0 ],
"style" : "",
"text" : "Connected"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-114",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 335.0, 655.0, 106.0, 22.0 ],
"style" : "",
"text" : "if $i1>5 then bang"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-113",
"maxclass" : "number",
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "bang" ],
"parameter_enable" : 0,
"patching_rect" : [ 335.0, 620.0, 50.0, 22.0 ],
"style" : ""
}
}
, {
"box" : {
"id" : "obj-112",
"maxclass" : "button",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 334.0, 549.0, 20.0, 20.0 ],
"style" : ""
}
}
, {
"box" : {
"id" : "obj-111",
"maxclass" : "toggle",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "int" ],
"parameter_enable" : 0,
"patching_rect" : [ 305.0, 482.0, 20.0, 20.0 ],
"style" : ""
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-110",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 305.0, 456.0, 60.0, 22.0 ],
"style" : "",
"text" : "loadbang"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-109",
"maxclass" : "newobj",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 334.0, 521.0, 71.0, 22.0 ],
"style" : "",
"text" : "metro 1000"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-108",
"maxclass" : "newobj",
"numinlets" : 5,
"numoutlets" : 4,
"outlettype" : [ "int", "", "", "int" ],
"patching_rect" : [ 334.0, 577.0, 114.0, 22.0 ],
"style" : "",
"text" : "counter 0 1 100000"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-202",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1404.0, 858.0, 81.0, 22.0 ],
"style" : "",
"text" : "s livemap_ch"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-93",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1329.0, 983.0, 97.0, 22.0 ],
"style" : "",
"text" : "s midiout_ccn47"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-94",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1313.0, 961.0, 97.0, 22.0 ],
"style" : "",
"text" : "s midiout_ccn46"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-95",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1300.0, 940.0, 97.0, 22.0 ],
"style" : "",
"text" : "s midiout_ccn45"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-96",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1286.0, 919.0, 97.0, 22.0 ],
"style" : "",
"text" : "s midiout_ccn44"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-97",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1273.0, 898.0, 97.0, 22.0 ],
"style" : "",
"text" : "s midiout_ccn43"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-98",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1259.0, 877.0, 97.0, 22.0 ],
"style" : "",
"text" : "s midiout_ccn42"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-99",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1246.0, 856.0, 97.0, 22.0 ],
"style" : "",
"text" : "s midiout_ccn41"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-100",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1229.0, 834.0, 97.0, 22.0 ],
"style" : "",
"text" : "s midiout_ccn37"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-101",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1215.0, 812.0, 97.0, 22.0 ],
"style" : "",
"text" : "s midiout_ccn36"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-102",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1202.0, 791.0, 97.0, 22.0 ],
"style" : "",
"text" : "s midiout_ccn35"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-103",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1188.0, 770.0, 97.0, 22.0 ],
"style" : "",
"text" : "s midiout_ccn34"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-104",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 1175.0, 749.0, 97.0, 22.0 ],
"style" : "",
"text" : "s midiout_ccn33"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-105",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect
gitextract_yht0xf5z/ ├── Arduinoboy/ │ ├── Arduinoboy.ino │ ├── Led_Functions.ino │ ├── Memory_Functions.ino │ ├── Mode.ino │ ├── Mode_LSDJ_Keyboard.ino │ ├── Mode_LSDJ_Map.ino │ ├── Mode_LSDJ_MasterSync.ino │ ├── Mode_LSDJ_Midiout.ino │ ├── Mode_LSDJ_SlaveSync.ino │ ├── Mode_MidiGb.ino │ ├── Mode_Nanoloop.ino │ ├── Mode_Programmer.ino │ └── UsbMidi.ino ├── Changelog.md ├── Editor/ │ └── ArduinoBoyEditor-Midi.maxpat ├── LICENSE ├── README.md └── platformio.ini
Condensed preview — 18 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (371K chars).
[
{
"path": "Arduinoboy/Arduinoboy.ino",
"chars": 20855,
"preview": "/***************************************************************************\n ******************************************"
},
{
"path": "Arduinoboy/Led_Functions.ino",
"chars": 8587,
"preview": "\n /*\n showSelectedMode1 turns off the last mode led, turns on the new mode led\n and delays for a period of time to r"
},
{
"path": "Arduinoboy/Memory_Functions.ino",
"chars": 1147,
"preview": "\nboolean checkMemory()\n{\n byte chk;\n #ifndef USE_DUE\n for(int m=0;m<4;m++){\n chk = EEPROM.read(MEM_CHECK+m);\n "
},
{
"path": "Arduinoboy/Mode.ino",
"chars": 4290,
"preview": "/**************************************************************************\n * Name: Timothy Lamb "
},
{
"path": "Arduinoboy/Mode_LSDJ_Keyboard.ino",
"chars": 11427,
"preview": "/**************************************************************************\n * Name: Timothy Lamb "
},
{
"path": "Arduinoboy/Mode_LSDJ_Map.ino",
"chars": 7177,
"preview": "/**************************************************************************\n * Name: Timothy Lamb "
},
{
"path": "Arduinoboy/Mode_LSDJ_MasterSync.ino",
"chars": 5173,
"preview": "/**************************************************************************\n * Name: Timothy Lamb "
},
{
"path": "Arduinoboy/Mode_LSDJ_Midiout.ino",
"chars": 7432,
"preview": "/**************************************************************************\n * Name: Timothy Lamb "
},
{
"path": "Arduinoboy/Mode_LSDJ_SlaveSync.ino",
"chars": 9254,
"preview": "/**************************************************************************\n * Name: Timothy Lamb "
},
{
"path": "Arduinoboy/Mode_MidiGb.ino",
"chars": 8746,
"preview": "/**************************************************************************\n * Name: Timothy Lamb "
},
{
"path": "Arduinoboy/Mode_Nanoloop.ino",
"chars": 4501,
"preview": "/**************************************************************************\n * Name: Timothy Lamb "
},
{
"path": "Arduinoboy/Mode_Programmer.ino",
"chars": 5148,
"preview": "void modeProgrammer()\n{\n while(sysexProgrammingConnected || sysexProgrammingMode) {\n checkProgrammerConnected();\n "
},
{
"path": "Arduinoboy/UsbMidi.ino",
"chars": 2371,
"preview": "\n#ifndef USE_TEENSY\nvoid usbMidiSendTwoByteMessage(uint8_t b1, uint8_t b2) {};\nvoid usbMidiSendThreeByteMessage(uint8_t "
},
{
"path": "Changelog.md",
"chars": 6758,
"preview": "## Changelog\n\n### 05/19/20\n* Arduinoboy to version 1.3.4\n* Added support for Arduino Mega 2560 and Arduino UNO Wifi\n\n###"
},
{
"path": "Editor/ArduinoBoyEditor-Midi.maxpat",
"chars": 168076,
"preview": "{\n\t\"patcher\" : \t{\n\t\t\"fileversion\" : 1,\n\t\t\"appversion\" : \t\t{\n\t\t\t\"major\" : 7,\n\t\t\t\"minor\" : 2,\n\t\t\t\"revision\" : 1,\n\t\t\t\"archi"
},
{
"path": "LICENSE",
"chars": 18047,
"preview": " GNU GENERAL PUBLIC LICENSE\n Version 2, June 1991\n\n Copyright (C) 1989, 1991 Fr"
},
{
"path": "README.md",
"chars": 9174,
"preview": "# Arduinoboy\nOfficial ArduinoBoy Repository for serial MIDI communication to the Nintendo Gameboy.\n\n. The extraction includes 18 files (291.8 KB), approximately 105.2k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.