This is a part of the Kinetiszer project.

Dependencies:   inc

Dependents:   kinetisizer

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?

UserRevisionLine numberNew 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