/
Mode_LSDJ_SlaveSync.ino
225 lines (211 loc) · 9.04 KB
/
Mode_LSDJ_SlaveSync.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/**************************************************************************
* 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
}