This is a part of the Kinetiszer project.
midi.c@1:8ae4ab73ca6a, 2014-10-28 (annotated)
- Committer:
- Clemo
- Date:
- Tue Oct 28 20:09:12 2014 +0000
- Revision:
- 1:8ae4ab73ca6a
- Parent:
- 0:cb80470434eb
First publication (untested)
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Clemo | 0:cb80470434eb | 1 | /* |
Clemo | 0:cb80470434eb | 2 | Copyright 2013 Paul Soulsby www.soulsbysynths.com |
Clemo | 0:cb80470434eb | 3 | This file is part of Atmegatron. |
Clemo | 0:cb80470434eb | 4 | |
Clemo | 0:cb80470434eb | 5 | Atmegatron is free software: you can redistribute it and/or modify |
Clemo | 0:cb80470434eb | 6 | it under the terms of the GNU General Public License as published by |
Clemo | 0:cb80470434eb | 7 | the Free Software Foundation, either version 3 of the License, or |
Clemo | 0:cb80470434eb | 8 | (at your option) any later version. |
Clemo | 0:cb80470434eb | 9 | |
Clemo | 0:cb80470434eb | 10 | Atmegatron is distributed in the hope that it will be useful, |
Clemo | 0:cb80470434eb | 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
Clemo | 0:cb80470434eb | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
Clemo | 0:cb80470434eb | 13 | GNU General Public License for more details. |
Clemo | 0:cb80470434eb | 14 | |
Clemo | 0:cb80470434eb | 15 | You should have received a copy of the GNU General Public License |
Clemo | 0:cb80470434eb | 16 | along with Atmegatron. If not, see <http://www.gnu.org/licenses/>. |
Clemo | 0:cb80470434eb | 17 | */ |
Clemo | 0:cb80470434eb | 18 | |
Clemo | 0:cb80470434eb | 19 | #include "atmegatron.h" |
Clemo | 0:cb80470434eb | 20 | |
Clemo | 0:cb80470434eb | 21 | |
Clemo | 0:cb80470434eb | 22 | //frequency of all midi notes (rounded to nearest integer) |
Clemo | 0:cb80470434eb | 23 | const uint16_t MIDI_freqs[128] = |
Clemo | 0:cb80470434eb | 24 | { |
Clemo | 0:cb80470434eb | 25 | 8, 9, 9,10,10,11,12,12,13,14,15,15,16,17,18,19, |
Clemo | 0:cb80470434eb | 26 | 21,22,23,24,26,28,29,31,33,35,37,39,41,44,46,49, |
Clemo | 0:cb80470434eb | 27 | 52,55,58,62,65,69,73,78,82,87,92,98,104,110,117,123, |
Clemo | 0:cb80470434eb | 28 | 131,139,147,156,165,175,185,196,208,220,233,247,262,277,294,311, |
Clemo | 0:cb80470434eb | 29 | 330,349,370,392,415,440,466,494,523,554,587,622,659,698,740,784, |
Clemo | 0:cb80470434eb | 30 | 831,880,932,988,1047,1109,1175,1245,1319,1397,1480,1568,1661,1760,1865,1976, |
Clemo | 0:cb80470434eb | 31 | 2093,2217,2349,2489,2637,2794,2960,3136,3322,3520,3729,3951,4186,4435,4699,4978, |
Clemo | 0:cb80470434eb | 32 | 5274,5588,5920,6272,6645,7040,7459,7902,8372,8870,9397,9956,10548,11175,11840,12544 |
Clemo | 0:cb80470434eb | 33 | }; |
Clemo | 0:cb80470434eb | 34 | |
Clemo | 0:cb80470434eb | 35 | |
Clemo | 0:cb80470434eb | 36 | //local vars |
Clemo | 0:cb80470434eb | 37 | |
Clemo | 0:cb80470434eb | 38 | boolean arp_triggernext=false; //trigger arpeggiator note on next midi clock |
Clemo | 0:cb80470434eb | 39 | boolean gettingSYSEX=false; //in the middle of getting sysex message |
Clemo | 0:cb80470434eb | 40 | boolean memDumping=false; //in the middle of dumping memory to librarian software |
Clemo | 0:cb80470434eb | 41 | byte curMemDump=0; //current stage of memory dump |
Clemo | 0:cb80470434eb | 42 | byte SYSEXbytenum=0; //byte number of sysex message |
Clemo | 0:cb80470434eb | 43 | byte SYSEXmesstype=0; //type of sysex message |
Clemo | 0:cb80470434eb | 44 | |
Clemo | 0:cb80470434eb | 45 | //lets and gets |
Clemo | 0:cb80470434eb | 46 | byte MIDI_curnote = 57; //current note pressed |
Clemo | 0:cb80470434eb | 47 | byte MIDI_curbutnote = 60; //current note of test button |
Clemo | 0:cb80470434eb | 48 | boolean MIDI_keydown[128]; //store which keys are down for arpeggiator |
Clemo | 0:cb80470434eb | 49 | signed char MIDI_totnoteson =0; //total notes held down |
Clemo | 0:cb80470434eb | 50 | char MIDI_lasttotnoteson = 0; //last total notes held down |
Clemo | 0:cb80470434eb | 51 | boolean MIDI_clockpresent=false; //is midi clock present? |
Clemo | 0:cb80470434eb | 52 | boolean MIDI_SYSEXread=false; //is sysex read enabled? |
Clemo | 0:cb80470434eb | 53 | unsigned long MIDI_clocktick=0; |
Clemo | 0:cb80470434eb | 54 | unsigned long MIDI_clockticksperarpstep=12; |
Clemo | 0:cb80470434eb | 55 | unsigned long MIDI_clocknextarp=0; |
Clemo | 0:cb80470434eb | 56 | char MIDI_pbend_level=0; |
Clemo | 0:cb80470434eb | 57 | byte MIDI_channel=0; |
Clemo | 0:cb80470434eb | 58 | |
Clemo | 0:cb80470434eb | 59 | //Lets and Gets |
Clemo | 0:cb80470434eb | 60 | byte MIDI_Get_curNote(void) |
Clemo | 0:cb80470434eb | 61 | { //get current midi note |
Clemo | 0:cb80470434eb | 62 | return MIDI_curnote; |
Clemo | 0:cb80470434eb | 63 | } |
Clemo | 0:cb80470434eb | 64 | |
Clemo | 0:cb80470434eb | 65 | |
Clemo | 0:cb80470434eb | 66 | unsigned int MIDI_Get_Freq(byte notenum) |
Clemo | 0:cb80470434eb | 67 | { //get current midi frequency (potentially different to actual current frequency in pitch tab) |
Clemo | 0:cb80470434eb | 68 | return MIDI_freqs[notenum]; |
Clemo | 0:cb80470434eb | 69 | } |
Clemo | 0:cb80470434eb | 70 | |
Clemo | 0:cb80470434eb | 71 | |
Clemo | 0:cb80470434eb | 72 | boolean MIDI_Get_KeyDown(byte notenum) |
Clemo | 0:cb80470434eb | 73 | { //find out if note is down |
Clemo | 0:cb80470434eb | 74 | return MIDI_keydown[notenum]; |
Clemo | 0:cb80470434eb | 75 | } |
Clemo | 0:cb80470434eb | 76 | |
Clemo | 0:cb80470434eb | 77 | |
Clemo | 0:cb80470434eb | 78 | void MIDI_Let_ClockArpSpeed(unsigned int newspeed) |
Clemo | 0:cb80470434eb | 79 | { //set clock arp speed. not actual speed. see Arp_Let_Speed for how this works |
Clemo | 0:cb80470434eb | 80 | MIDI_clockticksperarpstep = ((unsigned long)newspeed+1) * 24 >> 13; |
Clemo | 0:cb80470434eb | 81 | } |
Clemo | 0:cb80470434eb | 82 | |
Clemo | 0:cb80470434eb | 83 | |
Clemo | 0:cb80470434eb | 84 | void MIDI_Let_SYSEXRead(boolean newval) |
Clemo | 0:cb80470434eb | 85 | { //set sysex read mode |
Clemo | 0:cb80470434eb | 86 | MIDI_SYSEXread = newval; |
Clemo | 0:cb80470434eb | 87 | } |
Clemo | 0:cb80470434eb | 88 | |
Clemo | 0:cb80470434eb | 89 | |
Clemo | 0:cb80470434eb | 90 | //boolean MIDI_Get_SYSEXRead(void) |
Clemo | 0:cb80470434eb | 91 | //{ |
Clemo | 0:cb80470434eb | 92 | // return MIDI_SYSEXread; |
Clemo | 0:cb80470434eb | 93 | //} |
Clemo | 0:cb80470434eb | 94 | |
Clemo | 0:cb80470434eb | 95 | |
Clemo | 0:cb80470434eb | 96 | boolean MIDI_Get_ClockPresent(void) |
Clemo | 0:cb80470434eb | 97 | { //return if midi clock is preset |
Clemo | 0:cb80470434eb | 98 | return MIDI_clockpresent; |
Clemo | 0:cb80470434eb | 99 | } |
Clemo | 0:cb80470434eb | 100 | |
Clemo | 0:cb80470434eb | 101 | |
Clemo | 0:cb80470434eb | 102 | void MIDI_Set_Channel(byte newchannel) |
Clemo | 0:cb80470434eb | 103 | { |
Clemo | 0:cb80470434eb | 104 | if(newchannel!=MIDI_channel){ |
Clemo | 0:cb80470434eb | 105 | MIDI_channel = newchannel; |
Clemo | 0:cb80470434eb | 106 | Memory_Channel_Write(newchannel); |
Clemo | 0:cb80470434eb | 107 | } |
Clemo | 0:cb80470434eb | 108 | } |
Clemo | 0:cb80470434eb | 109 | |
Clemo | 0:cb80470434eb | 110 | //MIDI meat |
Clemo | 0:cb80470434eb | 111 | //initialise serial port |
Clemo | 0:cb80470434eb | 112 | void MIDI_Init(void) |
Clemo | 0:cb80470434eb | 113 | { //enable midi. just uses standard arduino serial ports. |
Clemo | 0:cb80470434eb | 114 | MIDI_channel = Memory_Channel_Read(); |
Clemo | 0:cb80470434eb | 115 | Serial.begin(31250); |
Clemo | 0:cb80470434eb | 116 | } |
Clemo | 0:cb80470434eb | 117 | |
Clemo | 0:cb80470434eb | 118 | |
Clemo | 0:cb80470434eb | 119 | //********MIDI note stuff*********** |
Clemo | 0:cb80470434eb | 120 | //press key |
Clemo | 0:cb80470434eb | 121 | void MIDI_NoteOn(byte notenum) |
Clemo | 0:cb80470434eb | 122 | { |
Clemo | 0:cb80470434eb | 123 | MIDI_curnote = notenum; //set current note = new note |
Clemo | 0:cb80470434eb | 124 | MIDI_lasttotnoteson = MIDI_totnoteson; //set last total notes on |
Clemo | 0:cb80470434eb | 125 | MIDI_totnoteson++; //increment total notes on |
Clemo | 0:cb80470434eb | 126 | MIDI_keydown[notenum] = true; //set midi key down = true |
Clemo | 0:cb80470434eb | 127 | #ifdef __HAS_ARPEGGIATOR__ |
Clemo | 0:cb80470434eb | 128 | if (Arp_Get_Type()==0) |
Clemo | 0:cb80470434eb | 129 | #endif // __HAS_ARPEGGIATOR__ |
Clemo | 0:cb80470434eb | 130 | { //if arpeggiator off then |
Clemo | 0:cb80470434eb | 131 | MIDI_TriggerNote(notenum); //trigger note |
Clemo | 0:cb80470434eb | 132 | } |
Clemo | 0:cb80470434eb | 133 | #ifdef __HAS_ARPEGGIATOR__ |
Clemo | 0:cb80470434eb | 134 | else if (MIDI_lasttotnoteson==0 && MIDI_totnoteson==1) { //if arpeggiator on and this is the first note pressed down |
Clemo | 0:cb80470434eb | 135 | Arp_Reset(); //reset arpeggiator and lfo, so they sync together |
Clemo | 0:cb80470434eb | 136 | LFO_Reset(); |
Clemo | 0:cb80470434eb | 137 | } |
Clemo | 0:cb80470434eb | 138 | #endif // __HAS_ARPEGGIATOR__ |
Clemo | 0:cb80470434eb | 139 | } |
Clemo | 0:cb80470434eb | 140 | |
Clemo | 0:cb80470434eb | 141 | |
Clemo | 0:cb80470434eb | 142 | //release key |
Clemo | 0:cb80470434eb | 143 | void MIDI_NoteOff(byte notenum) |
Clemo | 0:cb80470434eb | 144 | { |
Clemo | 0:cb80470434eb | 145 | MIDI_keydown[notenum] = false; //set midi key down = false |
Clemo | 0:cb80470434eb | 146 | MIDI_lasttotnoteson = MIDI_totnoteson; //set last total notes on |
Clemo | 0:cb80470434eb | 147 | MIDI_totnoteson--; //decrement total notes on |
Clemo | 0:cb80470434eb | 148 | if (MIDI_totnoteson<=0){ //if total notes on = 0 (ie all keys released) (use <= for safety) |
Clemo | 0:cb80470434eb | 149 | AEnv_Release(); //release amplitude envelope |
Clemo | 0:cb80470434eb | 150 | FEnv_Release(); //release filter envelope |
Clemo | 0:cb80470434eb | 151 | if (MIDI_totnoteson<0){ //safety - if tot notes on < 0 |
Clemo | 0:cb80470434eb | 152 | MIDI_totnoteson = 0; //reset to 0 (<0 not possible) |
Clemo | 0:cb80470434eb | 153 | } |
Clemo | 0:cb80470434eb | 154 | } |
Clemo | 0:cb80470434eb | 155 | } |
Clemo | 0:cb80470434eb | 156 | |
Clemo | 0:cb80470434eb | 157 | |
Clemo | 0:cb80470434eb | 158 | //*********TRIGGER A NOTE**************** (used by arpeggiator too) |
Clemo | 0:cb80470434eb | 159 | void MIDI_TriggerNote(byte notenum) |
Clemo | 0:cb80470434eb | 160 | { |
Clemo | 0:cb80470434eb | 161 | Pitch_Let_NextFreq(MIDI_freqs[notenum]); //set next frequency (pitch) |
Clemo | 0:cb80470434eb | 162 | Pitch_ResetPorta(); //set portamento start tick |
Clemo | 0:cb80470434eb | 163 | AEnv_Trigger(); //trigger amplitude envelope |
Clemo | 0:cb80470434eb | 164 | FEnv_Trigger(); //trigger filter envelope |
Clemo | 0:cb80470434eb | 165 | } |
Clemo | 0:cb80470434eb | 166 | |
Clemo | 0:cb80470434eb | 167 | |
Clemo | 0:cb80470434eb | 168 | //reset all notes |
Clemo | 0:cb80470434eb | 169 | void MIDI_Reset(void) |
Clemo | 0:cb80470434eb | 170 | { |
Clemo | 0:cb80470434eb | 171 | uint8_t i; |
Clemo | 0:cb80470434eb | 172 | for (i=0; i<=127; i++) |
Clemo | 0:cb80470434eb | 173 | { |
Clemo | 0:cb80470434eb | 174 | MIDI_NoteOff(i); |
Clemo | 0:cb80470434eb | 175 | } |
Clemo | 0:cb80470434eb | 176 | } |
Clemo | 0:cb80470434eb | 177 | |
Clemo | 0:cb80470434eb | 178 | |
Clemo | 0:cb80470434eb | 179 | //press the test button (value knob) |
Clemo | 0:cb80470434eb | 180 | void MIDI_TestButtonDown(void) |
Clemo | 0:cb80470434eb | 181 | { |
Clemo | 0:cb80470434eb | 182 | Pitch_Let_NextFreq(MIDI_freqs[MIDI_curbutnote]); //set next frequency |
Clemo | 0:cb80470434eb | 183 | Pitch_ResetPorta(); //set portamento start tick |
Clemo | 0:cb80470434eb | 184 | AEnv_Trigger(); //trigger amplitude envelope |
Clemo | 0:cb80470434eb | 185 | FEnv_Trigger(); //trigger filter envelope |
Clemo | 0:cb80470434eb | 186 | } |
Clemo | 0:cb80470434eb | 187 | |
Clemo | 0:cb80470434eb | 188 | |
Clemo | 0:cb80470434eb | 189 | //release the test button (value knob) |
Clemo | 0:cb80470434eb | 190 | void MIDI_TestButtonUp(void) |
Clemo | 0:cb80470434eb | 191 | { |
Clemo | 0:cb80470434eb | 192 | if (MIDI_totnoteson<=0){ //prevent stuck notes |
Clemo | 0:cb80470434eb | 193 | AEnv_Release(); //release amplitude envelope |
Clemo | 0:cb80470434eb | 194 | FEnv_Release(); //release filter envelope |
Clemo | 0:cb80470434eb | 195 | } |
Clemo | 0:cb80470434eb | 196 | } |
Clemo | 0:cb80470434eb | 197 | |
Clemo | 0:cb80470434eb | 198 | |
Clemo | 0:cb80470434eb | 199 | //increment test button note (clockwise turn) |
Clemo | 0:cb80470434eb | 200 | void MIDI_TestButtonInc(void) |
Clemo | 0:cb80470434eb | 201 | { |
Clemo | 0:cb80470434eb | 202 | if (MIDI_curbutnote<126){ //if cur test button note < max midi note |
Clemo | 0:cb80470434eb | 203 | MIDI_curbutnote++; //increment |
Clemo | 0:cb80470434eb | 204 | Pitch_Let_NextFreq(MIDI_freqs[MIDI_curbutnote]); //set next frequency (pitch) |
Clemo | 0:cb80470434eb | 205 | } |
Clemo | 0:cb80470434eb | 206 | } |
Clemo | 0:cb80470434eb | 207 | |
Clemo | 0:cb80470434eb | 208 | |
Clemo | 0:cb80470434eb | 209 | //decrement test button note (anti clockwise turn) |
Clemo | 0:cb80470434eb | 210 | void MIDI_TestButtonDec(void) |
Clemo | 0:cb80470434eb | 211 | { |
Clemo | 0:cb80470434eb | 212 | if (MIDI_curbutnote>1){ //if cur test button note > min midi note |
Clemo | 0:cb80470434eb | 213 | MIDI_curbutnote--; //decrement |
Clemo | 0:cb80470434eb | 214 | Pitch_Let_NextFreq(MIDI_freqs[MIDI_curbutnote]); //set next frequency (pitch) |
Clemo | 0:cb80470434eb | 215 | } |
Clemo | 0:cb80470434eb | 216 | } |
Clemo | 0:cb80470434eb | 217 | |
Clemo | 0:cb80470434eb | 218 | |
Clemo | 0:cb80470434eb | 219 | //*******MIDI clock stuff******** |
Clemo | 0:cb80470434eb | 220 | //MIDI clock start received |
Clemo | 0:cb80470434eb | 221 | void MIDI_ClockStart(void) |
Clemo | 0:cb80470434eb | 222 | { |
Clemo | 0:cb80470434eb | 223 | MIDI_clockpresent = true; //set clock present |
Clemo | 0:cb80470434eb | 224 | MIDI_clocktick = 0; //reset clock tick counter |
Clemo | 0:cb80470434eb | 225 | MIDI_clocknextarp = 0; //reset next arpeggiator note tick |
Clemo | 0:cb80470434eb | 226 | #ifdef __HAS_ARPEGGIATOR__ |
Clemo | 0:cb80470434eb | 227 | if (Arp_Get_Type()!=0) { //if arpeggiator on |
Clemo | 0:cb80470434eb | 228 | Arp_Reset(); //reset it (so synced with clock) |
Clemo | 0:cb80470434eb | 229 | } |
Clemo | 0:cb80470434eb | 230 | #endif // __HAS_ARPEGGIATOR__ |
Clemo | 0:cb80470434eb | 231 | LFO_Reset(); //reset lfo (so synced with clock) |
Clemo | 0:cb80470434eb | 232 | } |
Clemo | 0:cb80470434eb | 233 | |
Clemo | 0:cb80470434eb | 234 | |
Clemo | 0:cb80470434eb | 235 | //No implementation of clock continue at present. just does clock start |
Clemo | 0:cb80470434eb | 236 | void MIDI_ClockContinue(void) |
Clemo | 0:cb80470434eb | 237 | { |
Clemo | 0:cb80470434eb | 238 | MIDI_ClockStart(); |
Clemo | 0:cb80470434eb | 239 | } |
Clemo | 0:cb80470434eb | 240 | |
Clemo | 0:cb80470434eb | 241 | |
Clemo | 0:cb80470434eb | 242 | //MIDI clock stop received |
Clemo | 0:cb80470434eb | 243 | void MIDI_ClockStop(void) |
Clemo | 0:cb80470434eb | 244 | { |
Clemo | 0:cb80470434eb | 245 | MIDI_clockpresent = false; //set clock not present |
Clemo | 0:cb80470434eb | 246 | } |
Clemo | 0:cb80470434eb | 247 | |
Clemo | 0:cb80470434eb | 248 | |
Clemo | 0:cb80470434eb | 249 | //MIDI clock tick received |
Clemo | 0:cb80470434eb | 250 | void MIDI_ClockTick(void) |
Clemo | 0:cb80470434eb | 251 | { |
Clemo | 0:cb80470434eb | 252 | if (MIDI_clockpresent==true) { //check clock has acutally been started (not rogue data) |
Clemo | 0:cb80470434eb | 253 | #ifdef __HAS_ARPEGGIATOR__ |
Clemo | 0:cb80470434eb | 254 | if (MIDI_clocktick>=MIDI_clocknextarp && Arp_Get_Type()!=0){ //if midi clock counter > midi clock value for next arppeggiator trigger (and arpeggitor on) : |
Clemo | 0:cb80470434eb | 255 | arp_triggernext = true; //trigger arpeggiator at end of current midi receive (bottom of MIDI_poll) |
Clemo | 0:cb80470434eb | 256 | } |
Clemo | 0:cb80470434eb | 257 | #endif // __HAS_ARPEGGIATOR__ |
Clemo | 0:cb80470434eb | 258 | if (MIDI_clocktick%24 == 0){ //every 24 clock ticks (every beat): |
Clemo | 0:cb80470434eb | 259 | Hardware_LED_StartFlash(4,1); //flash the midi led |
Clemo | 0:cb80470434eb | 260 | } |
Clemo | 0:cb80470434eb | 261 | MIDI_clocktick++; //increment midi clock counter |
Clemo | 0:cb80470434eb | 262 | } |
Clemo | 0:cb80470434eb | 263 | |
Clemo | 0:cb80470434eb | 264 | } |
Clemo | 0:cb80470434eb | 265 | |
Clemo | 0:cb80470434eb | 266 | |
Clemo | 0:cb80470434eb | 267 | //get midi clock counter |
Clemo | 0:cb80470434eb | 268 | unsigned long MIDI_Get_ClockTick(void) |
Clemo | 0:cb80470434eb | 269 | { |
Clemo | 0:cb80470434eb | 270 | return MIDI_clocktick; |
Clemo | 0:cb80470434eb | 271 | } |
Clemo | 0:cb80470434eb | 272 | |
Clemo | 0:cb80470434eb | 273 | |
Clemo | 0:cb80470434eb | 274 | //get pitch bend (only using msb of pitch bend data) |
Clemo | 0:cb80470434eb | 275 | char MIDI_Get_PitchBend_Level(void) |
Clemo | 0:cb80470434eb | 276 | { |
Clemo | 0:cb80470434eb | 277 | return MIDI_pbend_level; |
Clemo | 0:cb80470434eb | 278 | } |
Clemo | 0:cb80470434eb | 279 | |
Clemo | 0:cb80470434eb | 280 | |
Clemo | 0:cb80470434eb | 281 | //***********SYSEX stuff*********** |
Clemo | 0:cb80470434eb | 282 | //byte of sysex data received |
Clemo | 0:cb80470434eb | 283 | void MIDI_SYSEX_read(byte databyte) |
Clemo | 0:cb80470434eb | 284 | { |
Clemo | 0:cb80470434eb | 285 | //int addr; |
Clemo | 0:cb80470434eb | 286 | int samp; |
Clemo | 0:cb80470434eb | 287 | |
Clemo | 0:cb80470434eb | 288 | switch (SYSEXbytenum){ //SYSEXbytenum - counter used to log position in sysex message |
Clemo | 0:cb80470434eb | 289 | case 1: //Manufactuer ID 125 (one day I'll get my own!) |
Clemo | 0:cb80470434eb | 290 | if (databyte!=125){ |
Clemo | 0:cb80470434eb | 291 | gettingSYSEX = false; |
Clemo | 0:cb80470434eb | 292 | Hardware_LED_SetState(4,LOW); |
Clemo | 0:cb80470434eb | 293 | } |
Clemo | 0:cb80470434eb | 294 | break; |
Clemo | 0:cb80470434eb | 295 | case 2: //Product ID (0 for Atmegatron) |
Clemo | 0:cb80470434eb | 296 | if (databyte!=0){ |
Clemo | 0:cb80470434eb | 297 | gettingSYSEX = false; |
Clemo | 0:cb80470434eb | 298 | Hardware_LED_SetState(4,LOW); |
Clemo | 0:cb80470434eb | 299 | } |
Clemo | 0:cb80470434eb | 300 | break; |
Clemo | 0:cb80470434eb | 301 | case 3: //Message type ID (0 = patch, 1 = waveform, 2 = mem dump) |
Clemo | 0:cb80470434eb | 302 | SYSEXmesstype = databyte; |
Clemo | 0:cb80470434eb | 303 | break; |
Clemo | 0:cb80470434eb | 304 | default: |
Clemo | 0:cb80470434eb | 305 | if (SYSEXmesstype==SYSEX_PATCH && MIDI_SYSEXread==true){ //********Patch******** |
Clemo | 0:cb80470434eb | 306 | if (SYSEXbytenum>=4 && SYSEXbytenum<=19){ //set relevent value (decided by SYSEXbytenum (position in message)) |
Clemo | 0:cb80470434eb | 307 | Hardware_Let_Value(SYSEXbytenum-4,databyte); |
Clemo | 0:cb80470434eb | 308 | } |
Clemo | 0:cb80470434eb | 309 | if (SYSEXbytenum>=20 && SYSEXbytenum<=25){ |
Clemo | 0:cb80470434eb | 310 | Hardware_Let_Ctrl(0,SYSEXbytenum-20,databyte<<1); //values that are byte (0-255) are *2, because sysex max value is 127 |
Clemo | 0:cb80470434eb | 311 | } |
Clemo | 0:cb80470434eb | 312 | if (SYSEXbytenum>=26 && SYSEXbytenum<=29){ |
Clemo | 0:cb80470434eb | 313 | Hardware_Let_Ctrl(1,SYSEXbytenum-24,databyte<<1); |
Clemo | 0:cb80470434eb | 314 | } |
Clemo | 0:cb80470434eb | 315 | if (SYSEXbytenum==30){ |
Clemo | 0:cb80470434eb | 316 | Hard_Let_Shift(FUNC_WAVE,databyte); |
Clemo | 0:cb80470434eb | 317 | } |
Clemo | 0:cb80470434eb | 318 | if (SYSEXbytenum==31){ |
Clemo | 0:cb80470434eb | 319 | Hard_Let_Shift(FUNC_FILT,databyte); |
Clemo | 0:cb80470434eb | 320 | } |
Clemo | 0:cb80470434eb | 321 | if (SYSEXbytenum==32){ |
Clemo | 0:cb80470434eb | 322 | Hard_Let_Shift(FUNC_FENVA,databyte); |
Clemo | 0:cb80470434eb | 323 | } |
Clemo | 0:cb80470434eb | 324 | if (SYSEXbytenum==33){ |
Clemo | 0:cb80470434eb | 325 | Hard_Let_Shift(FUNC_LFOTYPE,databyte); |
Clemo | 0:cb80470434eb | 326 | } |
Clemo | 0:cb80470434eb | 327 | if (SYSEXbytenum==34){ |
Clemo | 0:cb80470434eb | 328 | #ifdef __HAS_ARPEGGIATOR__ |
Clemo | 0:cb80470434eb | 329 | Hard_Let_Shift(FUNC_ARPTYPE,databyte); |
Clemo | 0:cb80470434eb | 330 | #endif // __HAS_ARPEGGIATOR__ |
Clemo | 0:cb80470434eb | 331 | } |
Clemo | 0:cb80470434eb | 332 | if (SYSEXbytenum==35){ |
Clemo | 0:cb80470434eb | 333 | Hard_Let_Shift(FUNC_PORTA,databyte); |
Clemo | 0:cb80470434eb | 334 | } |
Clemo | 0:cb80470434eb | 335 | if (SYSEXbytenum==36){ //this is the last byte |
Clemo | 0:cb80470434eb | 336 | Hard_Let_Shift(FUNC_BITCRUSH, databyte); |
Clemo | 0:cb80470434eb | 337 | Hardware_LED_StartFlash(0,5); //Flash function knob led. this means all bytes received (different to end of sysex message (F7)) |
Clemo | 0:cb80470434eb | 338 | if(memDumping==true){ //****if this is part of a mem dump receive:**** |
Clemo | 0:cb80470434eb | 339 | Serial.flush(); //flush serial buffer - need all the mem clear for next message |
Clemo | 0:cb80470434eb | 340 | Memory_Save(curMemDump); //save current received patch to flash mem |
Clemo | 0:cb80470434eb | 341 | curMemDump++; //increment mem dump counter (patch num to request) |
Clemo | 0:cb80470434eb | 342 | Serial.write(SYSEXBEGIN); //0 begin sysex message |
Clemo | 0:cb80470434eb | 343 | Serial.write(125); //1 manufacturer ID |
Clemo | 0:cb80470434eb | 344 | Serial.write(0); //2 product ID |
Clemo | 0:cb80470434eb | 345 | if (curMemDump<16){ //first 16 dumps are patches, if more patches to recieve: request next patch |
Clemo | 0:cb80470434eb | 346 | Serial.write(SYSEX_CALLPATCH); //3 message type |
Clemo | 0:cb80470434eb | 347 | } |
Clemo | 0:cb80470434eb | 348 | else{ //or request first user wave |
Clemo | 0:cb80470434eb | 349 | Serial.write(SYSEX_CALLWAVE); //3 message type |
Clemo | 0:cb80470434eb | 350 | curMemDump = 0; //reset counter for user waves |
Clemo | 0:cb80470434eb | 351 | } |
Clemo | 0:cb80470434eb | 352 | Serial.write(curMemDump); //4 mem dump number (so librarian knows which patch/wave) |
Clemo | 0:cb80470434eb | 353 | Serial.write(SYSEXEND); //end message |
Clemo | 0:cb80470434eb | 354 | } |
Clemo | 0:cb80470434eb | 355 | } |
Clemo | 0:cb80470434eb | 356 | } |
Clemo | 0:cb80470434eb | 357 | |
Clemo | 0:cb80470434eb | 358 | if (SYSEXmesstype==SYSEX_WAVE && MIDI_SYSEXread==true){ //***********User Wave************** |
Clemo | 0:cb80470434eb | 359 | if (SYSEXbytenum>=4 && SYSEXbytenum<=35){ //bytes of sample data |
Clemo | 0:cb80470434eb | 360 | samp = (int)databyte; //convert to integer |
Clemo | 0:cb80470434eb | 361 | samp *= 2; //*2 (librarian outputs (-63 - 63), we need (-127 - 128, actually use -126 - 126) |
Clemo | 0:cb80470434eb | 362 | samp -= 126; //apply offset (byte transmitted as positive integers) |
Clemo | 0:cb80470434eb | 363 | Wave_Let_UserWave(SYSEXbytenum-4,(signed char)samp); //convert to char and set current user wave |
Clemo | 0:cb80470434eb | 364 | } |
Clemo | 0:cb80470434eb | 365 | if (SYSEXbytenum==35){ //last byte of data |
Clemo | 0:cb80470434eb | 366 | Hardware_LED_StartFlash(0,5); //Flash function knob led. this means all bytes received (different to end of sysex message (F7)) |
Clemo | 0:cb80470434eb | 367 | if(memDumping==true){ //****if this is part of a mem dump receive:**** |
Clemo | 0:cb80470434eb | 368 | Serial.flush(); //flush serial buffer - need all the mem clear for next message |
Clemo | 0:cb80470434eb | 369 | Memory_UserWave_Write(curMemDump); //save current received user wave to flash mem |
Clemo | 0:cb80470434eb | 370 | curMemDump++; //increment mem dump counter (user wave to request) |
Clemo | 0:cb80470434eb | 371 | if (curMemDump<6){ //if more user waves still to receive: request next user wave |
Clemo | 0:cb80470434eb | 372 | Serial.write(SYSEXBEGIN); //0 begin message |
Clemo | 0:cb80470434eb | 373 | Serial.write(125); //1 manufacturer ID |
Clemo | 0:cb80470434eb | 374 | Serial.write(0); //2 product ID |
Clemo | 0:cb80470434eb | 375 | Serial.write(SYSEX_CALLWAVE); //3 message type |
Clemo | 0:cb80470434eb | 376 | Serial.write(curMemDump); //4 mem dump number (so librarian knows which patch/wave) |
Clemo | 0:cb80470434eb | 377 | Serial.write(SYSEXEND); //end message |
Clemo | 0:cb80470434eb | 378 | } |
Clemo | 0:cb80470434eb | 379 | else{ //finished final user wave |
Clemo | 0:cb80470434eb | 380 | memDumping = false; //stop dumping |
Clemo | 0:cb80470434eb | 381 | } |
Clemo | 0:cb80470434eb | 382 | } |
Clemo | 0:cb80470434eb | 383 | } |
Clemo | 0:cb80470434eb | 384 | } |
Clemo | 0:cb80470434eb | 385 | |
Clemo | 0:cb80470434eb | 386 | if (SYSEXmesstype==SYSEX_MEM && MIDI_SYSEXread==true){ //*************Memory Dump************** |
Clemo | 0:cb80470434eb | 387 | curMemDump = 0; //counter used to track which patch/wave is being dumped |
Clemo | 0:cb80470434eb | 388 | memDumping = true; //memory dump started |
Clemo | 0:cb80470434eb | 389 | Serial.write(SYSEXBEGIN); //request first patch from librarian |
Clemo | 0:cb80470434eb | 390 | Serial.write(125); //1 manufacturer ID |
Clemo | 0:cb80470434eb | 391 | Serial.write(0); //2 product ID |
Clemo | 0:cb80470434eb | 392 | Serial.write(SYSEX_CALLPATCH); //3 message type |
Clemo | 0:cb80470434eb | 393 | Serial.write(curMemDump); //4 mem dump number (patch 0) |
Clemo | 0:cb80470434eb | 394 | Serial.write(SYSEXEND); //end message |
Clemo | 0:cb80470434eb | 395 | } |
Clemo | 0:cb80470434eb | 396 | } |
Clemo | 0:cb80470434eb | 397 | } |
Clemo | 0:cb80470434eb | 398 | |
Clemo | 0:cb80470434eb | 399 | |
Clemo | 0:cb80470434eb | 400 | //Write patch to librarian |
Clemo | 0:cb80470434eb | 401 | void MIDI_SYSEX_write_patch(void) |
Clemo | 0:cb80470434eb | 402 | { |
Clemo | 0:cb80470434eb | 403 | byte data; |
Clemo | 0:cb80470434eb | 404 | byte i; |
Clemo | 0:cb80470434eb | 405 | //boolean b; |
Clemo | 0:cb80470434eb | 406 | |
Clemo | 0:cb80470434eb | 407 | Serial.write(SYSEXBEGIN); |
Clemo | 0:cb80470434eb | 408 | Serial.write(125); // 1 manufacturer ID |
Clemo | 0:cb80470434eb | 409 | Serial.write(0); // 2 product ID |
Clemo | 0:cb80470434eb | 410 | Serial.write(SYSEX_PATCH); // 3 message type |
Clemo | 0:cb80470434eb | 411 | for (i=0;i<16;i++){ // 4-19 function vals |
Clemo | 0:cb80470434eb | 412 | Serial.write(Hardware_Get_Value(i)); |
Clemo | 0:cb80470434eb | 413 | } |
Clemo | 0:cb80470434eb | 414 | for (i=0;i<6;i++){ // 20-25 ctrl vals bank=0 |
Clemo | 0:cb80470434eb | 415 | data = Hardware_Get_Ctrl(0, i) >> 1; |
Clemo | 0:cb80470434eb | 416 | Serial.write(data); |
Clemo | 0:cb80470434eb | 417 | } |
Clemo | 0:cb80470434eb | 418 | for (i=2;i<6;i++){ // 26-29 ctrl vals bank=1 |
Clemo | 0:cb80470434eb | 419 | data = Hardware_Get_Ctrl(1, i) >> 1; |
Clemo | 0:cb80470434eb | 420 | Serial.write(data); |
Clemo | 0:cb80470434eb | 421 | } |
Clemo | 0:cb80470434eb | 422 | Serial.write(Hard_Get_Shift(FUNC_WAVE)); //30-36 shift mode for functions |
Clemo | 0:cb80470434eb | 423 | Serial.write(Hard_Get_Shift(FUNC_FILT)); |
Clemo | 0:cb80470434eb | 424 | Serial.write(Hard_Get_Shift(FUNC_FENVA)); |
Clemo | 0:cb80470434eb | 425 | Serial.write(Hard_Get_Shift(FUNC_LFOTYPE)); |
Clemo | 0:cb80470434eb | 426 | #ifdef __HAS_ARPEGGIATOR__ |
Clemo | 0:cb80470434eb | 427 | Serial.write(Hard_Get_Shift(FUNC_ARPTYPE)); |
Clemo | 0:cb80470434eb | 428 | #else |
Clemo | 0:cb80470434eb | 429 | Serial.write(0); |
Clemo | 0:cb80470434eb | 430 | #endif // __HAS_ARPEGGIATOR__ |
Clemo | 0:cb80470434eb | 431 | Serial.write(Hard_Get_Shift(FUNC_PORTA)); |
Clemo | 0:cb80470434eb | 432 | Serial.write(Hard_Get_Shift(FUNC_BITCRUSH)); |
Clemo | 0:cb80470434eb | 433 | Serial.write(SYSEXEND); //37 end message |
Clemo | 0:cb80470434eb | 434 | |
Clemo | 0:cb80470434eb | 435 | } |
Clemo | 0:cb80470434eb | 436 | |
Clemo | 0:cb80470434eb | 437 | |
Clemo | 0:cb80470434eb | 438 | //**************MIDI POLL ********************* |
Clemo | 0:cb80470434eb | 439 | void MIDI_Poll(void) |
Clemo | 0:cb80470434eb | 440 | { |
Clemo | 0:cb80470434eb | 441 | byte incomingByte=0; |
Clemo | 0:cb80470434eb | 442 | static byte notebyte=0; //these are all static because there's a small chance that the subroutine is exited before the 2 bytes of MIDI needed for note_on are received. |
Clemo | 0:cb80470434eb | 443 | static byte velocitybyte=0; |
Clemo | 0:cb80470434eb | 444 | static byte statusbuffer=0; |
Clemo | 0:cb80470434eb | 445 | static boolean firstbyte; |
Clemo | 0:cb80470434eb | 446 | if (Serial.available() > 0) { //if there is something in the serial input buffer |
Clemo | 0:cb80470434eb | 447 | do { |
Clemo | 0:cb80470434eb | 448 | incomingByte = Serial.read(); // read the incoming byte: |
Clemo | 0:cb80470434eb | 449 | if (incomingByte>247) { // ****this is where MIDI clock stuff is done*** |
Clemo | 0:cb80470434eb | 450 | switch (incomingByte){ |
Clemo | 0:cb80470434eb | 451 | case 248: //MIDI clock tick |
Clemo | 0:cb80470434eb | 452 | MIDI_ClockTick(); |
Clemo | 0:cb80470434eb | 453 | break; |
Clemo | 0:cb80470434eb | 454 | case 250: //MIDI clock start |
Clemo | 0:cb80470434eb | 455 | MIDI_ClockStart(); |
Clemo | 0:cb80470434eb | 456 | break; |
Clemo | 0:cb80470434eb | 457 | case 251: //MIDI clock continue (not implemented) |
Clemo | 0:cb80470434eb | 458 | MIDI_ClockContinue(); |
Clemo | 0:cb80470434eb | 459 | break; |
Clemo | 0:cb80470434eb | 460 | case 252: //MIDI clock stop |
Clemo | 0:cb80470434eb | 461 | MIDI_ClockStop(); |
Clemo | 0:cb80470434eb | 462 | break; |
Clemo | 0:cb80470434eb | 463 | } |
Clemo | 0:cb80470434eb | 464 | } |
Clemo | 0:cb80470434eb | 465 | else if (incomingByte>239) { //*****this is where SYSEX stuff is done***** |
Clemo | 0:cb80470434eb | 466 | statusbuffer = 0; |
Clemo | 0:cb80470434eb | 467 | if (incomingByte==SYSEXBEGIN){ //start of sysex message |
Clemo | 0:cb80470434eb | 468 | gettingSYSEX = true; |
Clemo | 0:cb80470434eb | 469 | SYSEXbytenum = 0; //reset message byte counter |
Clemo | 0:cb80470434eb | 470 | Hardware_LED_SetState(4,HIGH); //turn midi light on while receiving |
Clemo | 0:cb80470434eb | 471 | } |
Clemo | 0:cb80470434eb | 472 | if (incomingByte==SYSEXEND){ //end of sysex message |
Clemo | 0:cb80470434eb | 473 | gettingSYSEX = false; |
Clemo | 0:cb80470434eb | 474 | Hardware_LED_SetState(4,LOW); //turn midi light off (this doesn't guarantee that message was successfully read though! Func knob flashes for that) |
Clemo | 0:cb80470434eb | 475 | } |
Clemo | 0:cb80470434eb | 476 | } |
Clemo | 0:cb80470434eb | 477 | else if (incomingByte>127) { //*****this is where all other message types are done ****** |
Clemo | 0:cb80470434eb | 478 | statusbuffer = incomingByte; //status buffer stores what kind of buffer it is |
Clemo | 0:cb80470434eb | 479 | firstbyte = true; //it must be the first byte of pair |
Clemo | 0:cb80470434eb | 480 | notebyte = 0; //so reset the note byte |
Clemo | 0:cb80470434eb | 481 | velocitybyte = 0; //and velocity byte, ready incase it's a note |
Clemo | 0:cb80470434eb | 482 | gettingSYSEX = false; //safety - note a sysex message |
Clemo | 0:cb80470434eb | 483 | } |
Clemo | 0:cb80470434eb | 484 | else if (gettingSYSEX==true){ //****SYSEX data******* if getting sysex, it HAS to be sysex data if < 128 |
Clemo | 0:cb80470434eb | 485 | SYSEXbytenum++; //inc message byte counter |
Clemo | 0:cb80470434eb | 486 | MIDI_SYSEX_read(incomingByte); //process the incoming byte |
Clemo | 0:cb80470434eb | 487 | } |
Clemo | 0:cb80470434eb | 488 | else if (statusbuffer!=0) { //******all other message data******* |
Clemo | 0:cb80470434eb | 489 | if (firstbyte == true) { //if it's first byte of pair |
Clemo | 0:cb80470434eb | 490 | notebyte = incomingByte; //set note = incoming byte |
Clemo | 0:cb80470434eb | 491 | firstbyte = false; //and set = false, so ready for second byte |
Clemo | 0:cb80470434eb | 492 | } |
Clemo | 0:cb80470434eb | 493 | else { // so must be second byte of pair then |
Clemo | 0:cb80470434eb | 494 | velocitybyte = incomingByte; //set velocitybyte as incoming byte (even if not note data) |
Clemo | 0:cb80470434eb | 495 | if (statusbuffer == (NOTE_ON | MIDI_channel) && velocitybyte != 0) { //is it a note on? |
Clemo | 0:cb80470434eb | 496 | Hardware_LED_StartFlash(4,1); //flash midi led |
Clemo | 0:cb80470434eb | 497 | MIDI_NoteOn(notebyte); //trigger note |
Clemo | 0:cb80470434eb | 498 | } |
Clemo | 0:cb80470434eb | 499 | else if (statusbuffer == (NOTE_OFF | MIDI_channel) || (statusbuffer == (NOTE_ON | MIDI_channel) && velocitybyte == 0)) { //is it a note off? (there's 2 ways to trigger note off: note_off or Note_on with velocity =0) |
Clemo | 0:cb80470434eb | 500 | Hardware_LED_StartFlash(4,1); //flash midi led |
Clemo | 0:cb80470434eb | 501 | MIDI_NoteOff(notebyte); //release note |
Clemo | 0:cb80470434eb | 502 | } |
Clemo | 0:cb80470434eb | 503 | else if (statusbuffer == (PITCH_WHEEL | MIDI_channel)){ //is it pitch wheel? |
Clemo | 0:cb80470434eb | 504 | MIDI_pbend_level = velocitybyte - 64; //set pbend (may aswell do the offset here). only msb of pitch bend used |
Clemo | 0:cb80470434eb | 505 | } |
Clemo | 0:cb80470434eb | 506 | else if (statusbuffer == (CONTROLLER | MIDI_channel)){ //is it a controller message? I have attempted to use controller numbers appoximating the spec of official controller list. Used "MISC" controllers where necessary |
Clemo | 0:cb80470434eb | 507 | switch (notebyte) { |
Clemo | 0:cb80470434eb | 508 | case CC_PITCHLFO: //pitch lfo (mod wheel). This is just an override of the pitch lfo knob |
Clemo | 0:cb80470434eb | 509 | Hardware_Let_Ctrl(1,CTRL_LFO,velocitybyte >> 1); //default uses >>1 for typical mod wheel vibrato. use << 1 for full range (default full range = 1 octave) |
Clemo | 0:cb80470434eb | 510 | break; |
Clemo | 0:cb80470434eb | 511 | case CC_PORTAMENTO: //portamento |
Clemo | 0:cb80470434eb | 512 | Hardware_Let_Value(FUNC_PORTA,velocitybyte >> 3); //scale to values 0-15 |
Clemo | 0:cb80470434eb | 513 | break; |
Clemo | 0:cb80470434eb | 514 | case CC_FILTERENV: //filter envelope |
Clemo | 0:cb80470434eb | 515 | Hardware_Let_Ctrl(0,CTRL_ENV,velocitybyte << 1); //scale to values 0-255 |
Clemo | 0:cb80470434eb | 516 | break; |
Clemo | 0:cb80470434eb | 517 | case CC_DISTORTION: //distortion |
Clemo | 0:cb80470434eb | 518 | Hardware_Let_Ctrl(0,CTRL_FX,velocitybyte << 1); //scale to values 0-255 |
Clemo | 0:cb80470434eb | 519 | break; |
Clemo | 0:cb80470434eb | 520 | case CC_FILTCUTOFF: //filter cutoff frequency |
Clemo | 0:cb80470434eb | 521 | Hardware_Let_Ctrl(0,CTRL_FILT,velocitybyte << 1); //scale to values 0-255 |
Clemo | 0:cb80470434eb | 522 | break; |
Clemo | 0:cb80470434eb | 523 | case CC_AMPENVR: //amplitude envelope release |
Clemo | 0:cb80470434eb | 524 | Hardware_Let_Value(FUNC_AENVR,velocitybyte >> 3); //scale to values 0-15 |
Clemo | 0:cb80470434eb | 525 | break; |
Clemo | 0:cb80470434eb | 526 | case CC_AMPENVA: //amplitude envelope attack |
Clemo | 0:cb80470434eb | 527 | Hardware_Let_Value(FUNC_AENVA,velocitybyte >> 3); //scale to values 0-15 |
Clemo | 0:cb80470434eb | 528 | break; |
Clemo | 0:cb80470434eb | 529 | case CC_FILTRES: //filter resonance |
Clemo | 0:cb80470434eb | 530 | Hardware_Let_Ctrl(0,CTRL_Q,velocitybyte << 1); //scale to values 0-255 |
Clemo | 0:cb80470434eb | 531 | break; |
Clemo | 0:cb80470434eb | 532 | case CC_AMPENVD: //amplitude envelope decay |
Clemo | 0:cb80470434eb | 533 | Hardware_Let_Value(FUNC_AENVD,velocitybyte >> 3); //scale to values 0-15 |
Clemo | 0:cb80470434eb | 534 | break; |
Clemo | 0:cb80470434eb | 535 | case CC_LFOCLOCKDIV: //lfo rate (speed). ******DUBSTEP PRODUCERS THIS IS CONTROLLER 79!!!******** |
Clemo | 0:cb80470434eb | 536 | Hardware_Let_Value(FUNC_LFOSPEED,velocitybyte >> 3); //scale to values 0-15 |
Clemo | 0:cb80470434eb | 537 | break; |
Clemo | 0:cb80470434eb | 538 | case CC_PWM: //pulse width modulation |
Clemo | 0:cb80470434eb | 539 | Hardware_Let_Ctrl(1,CTRL_AMP,velocitybyte << 1); //scale to values (0-255) |
Clemo | 0:cb80470434eb | 540 | break; |
Clemo | 0:cb80470434eb | 541 | case CC_AMPLFO: //amplitude lfo |
Clemo | 0:cb80470434eb | 542 | Hardware_Let_Ctrl(0,CTRL_AMP,velocitybyte << 1); //scale to values (0-255) |
Clemo | 0:cb80470434eb | 543 | break; |
Clemo | 0:cb80470434eb | 544 | case CC_FILTLFO: //filter lfo |
Clemo | 0:cb80470434eb | 545 | Hardware_Let_Ctrl(0,CTRL_LFO,velocitybyte << 1); |
Clemo | 0:cb80470434eb | 546 | break; |
Clemo | 0:cb80470434eb | 547 | case CC_PITCHENV: //pitch envelope |
Clemo | 0:cb80470434eb | 548 | Hardware_Let_Ctrl(1,CTRL_ENV,velocitybyte << 1); |
Clemo | 0:cb80470434eb | 549 | break; |
Clemo | 0:cb80470434eb | 550 | case CC_FLANGE: //phaser |
Clemo | 0:cb80470434eb | 551 | Hardware_Let_Ctrl(1,CTRL_FX,velocitybyte << 1); |
Clemo | 0:cb80470434eb | 552 | break; |
Clemo | 0:cb80470434eb | 553 | } |
Clemo | 0:cb80470434eb | 554 | } |
Clemo | 0:cb80470434eb | 555 | notebyte = 0; //now reset them ready for next note |
Clemo | 0:cb80470434eb | 556 | velocitybyte = 0; |
Clemo | 0:cb80470434eb | 557 | firstbyte = true; |
Clemo | 0:cb80470434eb | 558 | } |
Clemo | 0:cb80470434eb | 559 | } |
Clemo | 0:cb80470434eb | 560 | } while (Serial.available() > 0); //loop until serial buffer is empty |
Clemo | 0:cb80470434eb | 561 | |
Clemo | 0:cb80470434eb | 562 | #ifdef __HAS_ARPEGGIATOR__ |
Clemo | 0:cb80470434eb | 563 | if (arp_triggernext==true && MIDI_totnoteson>0){ //midi clock tick was received and it's time to fire an arpeggiator note! |
Clemo | 0:cb80470434eb | 564 | do{ //nasty do loop. this is important, incase midi clock ticks are faster than Atmegatron polling loop and multiple notes need to be triggered now |
Clemo | 0:cb80470434eb | 565 | Arp_TriggerStep(); //trigger arpeggiator |
Clemo | 0:cb80470434eb | 566 | MIDI_clocknextarp += MIDI_clockticksperarpstep; //MIDI_clockticksperarpstep MUST never be 0 |
Clemo | 0:cb80470434eb | 567 | } while (MIDI_clocknextarp<MIDI_clocktick); //loop until all notes triggered that need to be are |
Clemo | 0:cb80470434eb | 568 | arp_triggernext = false; //triggered all notes, so set false |
Clemo | 0:cb80470434eb | 569 | } |
Clemo | 0:cb80470434eb | 570 | #endif // __HAS_ARPEGGIATOR__ |
Clemo | 0:cb80470434eb | 571 | } |
Clemo | 0:cb80470434eb | 572 | } |
Clemo | 0:cb80470434eb | 573 |