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
Clemo 0:cb80470434eb 20 #include "atmegatron.h"
Clemo 0:cb80470434eb 21
Clemo 0:cb80470434eb 22 #ifdef __HAS_ARPEGGIATOR__
Clemo 0:cb80470434eb 23
Clemo 0:cb80470434eb 24 //****THIS IS WHERE THE ARPEGGIATOR PATTERNS ARE STORED*******
Clemo 0:cb80470434eb 25 //The way its is by up the notes currently being held down
Clemo 0:cb80470434eb 26 //So if C,D,E,F,G were held down and pattern was {5,3,2,4,1},
Clemo 0:cb80470434eb 27 //the arp would be G,E,D,F,C. Minus nums count downwards
Clemo 0:cb80470434eb 28
Clemo 0:cb80470434eb 29
Clemo 0:cb80470434eb 30 const signed char arp_patstore[16][16] =
Clemo 0:cb80470434eb 31 {
Clemo 0:cb80470434eb 32 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, //THIS ONE SHOULD ALWAYS BE BLANK
Clemo 0:cb80470434eb 33 {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}, //up
Clemo 0:cb80470434eb 34 {-1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16}, //down
Clemo 0:cb80470434eb 35 {1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8}, //octave
Clemo 0:cb80470434eb 36 {1,1,2,3,4,4,5,6,7,7,8,9,10,10,11,12}, //5ths
Clemo 0:cb80470434eb 37 {1,3,2,4,3,5,4,6,5,7,6,8,7,9,8,10}, //skip 1 up
Clemo 0:cb80470434eb 38 {-1,-3,-2,-4,-3,-5,-4,-6,-5,-7,-6,-8,-7,-9,-8,-10}, //skip 1 down
Clemo 0:cb80470434eb 39 {-1,-1,-1,-1,-3,-3,-2,-2,-1,-1,-1,-1,-3,-3,-2,-2}, //I feel love
Clemo 0:cb80470434eb 40 {2,1,3,2,4,5,6,1,2,1,3,2,4,5,6,1}, //Horton
Clemo 0:cb80470434eb 41 {-1,-2,-1,-4,-2,-1,-4,-1,-4,-2,-3,-2,-1,-3,-2,-1}, //Etheridge
Clemo 0:cb80470434eb 42 {1,2,3,2,4,3,2,3,1,3,2,4,1,3,2,1}, //Meads
Clemo 0:cb80470434eb 43 {1,2,3,2,-1,6,5,4,0,0,-1,-2,0,0,4,0}, //Palmer
Clemo 0:cb80470434eb 44 {4,1,4,1,3,1,4,1,2,1,3,1,4,1,4,1}, //gwEm 1
Clemo 0:cb80470434eb 45 {1,1,4,4,1,1,4,4,3,3,6,6,2,2,5,5}, //gwEm 2
Clemo 0:cb80470434eb 46 {1,1,3,2,2,4,3,3,5,4,4,6,5,5,7,6}, //Triplet up
Clemo 0:cb80470434eb 47 {1,2,3,2,1,2,3,2,1,2,3,2,1,2,3,2}, //You Will Be Robyn
Clemo 0:cb80470434eb 48 };
Clemo 0:cb80470434eb 49
Clemo 0:cb80470434eb 50 //local vars
Clemo 0:cb80470434eb 51 unsigned long arp_ticksperstep = 250; //ticks each step of arp should hold for
Clemo 0:cb80470434eb 52 unsigned long arp_nexttick = 0; //tick when next step fires
Clemo 0:cb80470434eb 53 unsigned long arp_curtick = 0; //current tick
Clemo 0:cb80470434eb 54 unsigned long arp_starttick = 0; //start tick
Clemo 0:cb80470434eb 55
Clemo 0:cb80470434eb 56 byte arp_curpos = 0; //current position in pattern
Clemo 0:cb80470434eb 57 byte arp_curnote = 255; //current MIDI note in pattern
Clemo 0:cb80470434eb 58 boolean arp_pongdown = false; //current direction if in ping-pong mode
Clemo 0:cb80470434eb 59
Clemo 0:cb80470434eb 60 //lets and gets
Clemo 0:cb80470434eb 61 boolean arp_pingpong = false;
Clemo 0:cb80470434eb 62 byte arp_curpat = 0;
Clemo 0:cb80470434eb 63 unsigned int arp_speed = 8191;
Clemo 0:cb80470434eb 64
Clemo 0:cb80470434eb 65
Clemo 0:cb80470434eb 66 //lets and gets
Clemo 0:cb80470434eb 67 void Arp_Let_Type(byte newpat)
Clemo 0:cb80470434eb 68 { //set pattern number (0-15)
Clemo 0:cb80470434eb 69 //byte i;
Clemo 0:cb80470434eb 70 if (newpat!=arp_curpat){ //if new pattern is different to current
Clemo 0:cb80470434eb 71 arp_curpat = newpat; //set it
Clemo 0:cb80470434eb 72 Arp_Reset(); //Reset vars for safety
Clemo 0:cb80470434eb 73 }
Clemo 0:cb80470434eb 74 }
Clemo 0:cb80470434eb 75
Clemo 0:cb80470434eb 76
Clemo 0:cb80470434eb 77 byte Arp_Get_Type(void)
Clemo 0:cb80470434eb 78 {
Clemo 0:cb80470434eb 79 return arp_curpat;
Clemo 0:cb80470434eb 80 }
Clemo 0:cb80470434eb 81
Clemo 0:cb80470434eb 82
Clemo 0:cb80470434eb 83 void Arp_Let_Speed(unsigned int newspeed)
Clemo 0:cb80470434eb 84 { //Set speed (speed is stored as an integer multiplier (speed_store on hardware page))
Clemo 0:cb80470434eb 85 //unsigned long cticks;
Clemo 0:cb80470434eb 86 arp_speed = newspeed;
Clemo 0:cb80470434eb 87 arp_ticksperstep = ((unsigned long)arp_speed+1) * MASTER_BEATTICK >> 13; //multiplier * ticks-per-beat (500ms=120bpm) / 8192. This is a way of not storing speed as floats
Clemo 0:cb80470434eb 88 }
Clemo 0:cb80470434eb 89
Clemo 0:cb80470434eb 90
Clemo 0:cb80470434eb 91 unsigned int Arp_Get_Speed(void)
Clemo 0:cb80470434eb 92 {
Clemo 0:cb80470434eb 93 return arp_speed;
Clemo 0:cb80470434eb 94 }
Clemo 0:cb80470434eb 95
Clemo 0:cb80470434eb 96
Clemo 0:cb80470434eb 97 void Arp_Let_PingPong(boolean newpingpong)
Clemo 0:cb80470434eb 98 { //set ping-pong mode. This runs sequence forwards, backwards, forwards, backwards etc etc
Clemo 0:cb80470434eb 99 arp_pingpong = newpingpong;
Clemo 0:cb80470434eb 100 }
Clemo 0:cb80470434eb 101
Clemo 0:cb80470434eb 102
Clemo 0:cb80470434eb 103 boolean Arp_Get_PingPong(void)
Clemo 0:cb80470434eb 104 {
Clemo 0:cb80470434eb 105 return arp_pingpong;
Clemo 0:cb80470434eb 106 }
Clemo 0:cb80470434eb 107
Clemo 0:cb80470434eb 108
Clemo 0:cb80470434eb 109 //reset all local vars before starting arp
Clemo 0:cb80470434eb 110 void Arp_Reset(void)
Clemo 0:cb80470434eb 111 {
Clemo 0:cb80470434eb 112 arp_curpos = 0; //restart pattern at start
Clemo 0:cb80470434eb 113 arp_curnote = 0; //restart note search at bottom
Clemo 0:cb80470434eb 114 arp_starttick = master_tick; //set start tick
Clemo 0:cb80470434eb 115 arp_curtick = 0; //reset current tick
Clemo 0:cb80470434eb 116 arp_nexttick = 0; //reset current tick
Clemo 0:cb80470434eb 117 }
Clemo 0:cb80470434eb 118
Clemo 0:cb80470434eb 119
Clemo 0:cb80470434eb 120 //Poll arpegiator and see if it's time for a new note to fire
Clemo 0:cb80470434eb 121 void Arp_Poll(void)
Clemo 0:cb80470434eb 122 {
Clemo 0:cb80470434eb 123 // is MIDI clock off and pattern <> 0 (MIDI_ClockTick() handles arpeggiator when clock is present)
Clemo 0:cb80470434eb 124 if (MIDI_Get_ClockPresent()==false && arp_curpat>0)
Clemo 0:cb80470434eb 125 {
Clemo 0:cb80470434eb 126 //is it time for next note?
Clemo 0:cb80470434eb 127 if (arp_curtick>=arp_nexttick)
Clemo 0:cb80470434eb 128 {
Clemo 0:cb80470434eb 129 if (Hardware_Get_Ctrl_Shift()==GREEN)
Clemo 0:cb80470434eb 130 {
Clemo 0:cb80470434eb 131 Board_LED_Toggle(BOARD_LED1_GREEN);
Clemo 0:cb80470434eb 132 Board_LED_Set(BOARD_LED2_GREEN,!Board_LED_Test(BOARD_LED1_GREEN));
Clemo 0:cb80470434eb 133 }
Clemo 0:cb80470434eb 134 else
Clemo 0:cb80470434eb 135 {
Clemo 0:cb80470434eb 136 Board_LED_Toggle(BOARD_LED1_RED);
Clemo 0:cb80470434eb 137 Board_LED_Set(BOARD_LED2_RED,!Board_LED_Test(BOARD_LED1_RED));
Clemo 0:cb80470434eb 138 }
Clemo 0:cb80470434eb 139 //SysTick_LED_Flash(BOARD_LED1_GREEN,10);
Clemo 0:cb80470434eb 140 do
Clemo 0:cb80470434eb 141 {
Clemo 0:cb80470434eb 142 Arp_TriggerStep(); //fire note
Clemo 0:cb80470434eb 143 arp_nexttick += arp_ticksperstep; //set the next tick for a note
Clemo 0:cb80470434eb 144 }
Clemo 0:cb80470434eb 145 while (arp_nexttick<arp_curtick); //in a nasty do loop because there's a chance the poll time is slower than arp_ticksperstep
Clemo 0:cb80470434eb 146 }
Clemo 0:cb80470434eb 147 arp_curtick = master_tick - arp_starttick; //refresh current tick
Clemo 0:cb80470434eb 148 }
Clemo 0:cb80470434eb 149 }
Clemo 0:cb80470434eb 150
Clemo 0:cb80470434eb 151
Clemo 0:cb80470434eb 152 void Arp_TriggerStep(void)
Clemo 0:cb80470434eb 153 { //fire note in pattern
Clemo 0:cb80470434eb 154 arp_curnote = Arp_FindNote(arp_patstore[arp_curpat][arp_curpos]); //attempt to find a note to fire
Clemo 0:cb80470434eb 155 if (arp_curnote==255){ //255 = failed to find note
Clemo 0:cb80470434eb 156 if (arp_pingpong==true){ //if in ping-pong mode
Clemo 0:cb80470434eb 157 if (arp_pongdown==false){ //probably coz its hit the end of pattern and needs to flip direction
Clemo 0:cb80470434eb 158 arp_curpos -= 2; //flip direction and set position
Clemo 0:cb80470434eb 159 arp_pongdown = true;
Clemo 0:cb80470434eb 160 }
Clemo 0:cb80470434eb 161 else{
Clemo 0:cb80470434eb 162 arp_curpos += 2;
Clemo 0:cb80470434eb 163 arp_pongdown = false;
Clemo 0:cb80470434eb 164 }
Clemo 0:cb80470434eb 165 }
Clemo 0:cb80470434eb 166 else{ //if not ping-pong, give up and reset to start of pattern
Clemo 0:cb80470434eb 167 arp_curpos = 0;
Clemo 0:cb80470434eb 168 }
Clemo 0:cb80470434eb 169 arp_curnote = Arp_FindNote(arp_patstore[arp_curpat][arp_curpos]); //have another stab at finding a note now
Clemo 0:cb80470434eb 170 }
Clemo 0:cb80470434eb 171 if (arp_curnote!=255){ //assuming it now has found as note
Clemo 0:cb80470434eb 172 MIDI_TriggerNote(arp_curnote); //fire it
Clemo 0:cb80470434eb 173 }
Clemo 0:cb80470434eb 174 Arp_IncPatPos(); //increment current position in pattern (more complex than just arp_curpos++)
Clemo 0:cb80470434eb 175 }
Clemo 0:cb80470434eb 176
Clemo 0:cb80470434eb 177
Clemo 0:cb80470434eb 178 /*int Arp_FindNoteUp(int count)
Clemo 0:cb80470434eb 179 {
Clemo 0:cb80470434eb 180 int n = 0;
Clemo 0:cb80470434eb 181 while (count>0)
Clemo 0:cb80470434eb 182 {
Clemo 0:cb80470434eb 183 while (n<128)
Clemo 0:cb80470434eb 184 {
Clemo 0:cb80470434eb 185 n++;
Clemo 0:cb80470434eb 186 if (MIDI_Get_KeyDown(n)==true)
Clemo 0:cb80470434eb 187 {
Clemo 0:cb80470434eb 188 break;
Clemo 0:cb80470434eb 189 }
Clemo 0:cb80470434eb 190 }
Clemo 0:cb80470434eb 191 count--;
Clemo 0:cb80470434eb 192 }
Clemo 0:cb80470434eb 193 return n<128? n : 255;
Clemo 0:cb80470434eb 194 }
Clemo 0:cb80470434eb 195
Clemo 0:cb80470434eb 196
Clemo 0:cb80470434eb 197 int Arp_FindNoteDown(int count)
Clemo 0:cb80470434eb 198 {
Clemo 0:cb80470434eb 199 int n = 127;
Clemo 0:cb80470434eb 200 while (count>0)
Clemo 0:cb80470434eb 201 {
Clemo 0:cb80470434eb 202 while (n>0)
Clemo 0:cb80470434eb 203 {
Clemo 0:cb80470434eb 204 n--;
Clemo 0:cb80470434eb 205 if (MIDI_Get_KeyDown(n)==true)
Clemo 0:cb80470434eb 206 {
Clemo 0:cb80470434eb 207 break;
Clemo 0:cb80470434eb 208 }
Clemo 0:cb80470434eb 209 }
Clemo 0:cb80470434eb 210 count--;
Clemo 0:cb80470434eb 211 }
Clemo 0:cb80470434eb 212 return n>0? n : 255;
Clemo 0:cb80470434eb 213 }
Clemo 0:cb80470434eb 214
Clemo 0:cb80470434eb 215
Clemo 0:cb80470434eb 216 //this finds out which note to fire, based on which notes are held down
Clemo 0:cb80470434eb 217 byte Arp_FindNote(signed char pos)
Clemo 0:cb80470434eb 218 {
Clemo 0:cb80470434eb 219 user_interface_print_value(1,0,pos,false);
Clemo 0:cb80470434eb 220 if (pos<0)
Clemo 0:cb80470434eb 221 {
Clemo 0:cb80470434eb 222 return Arp_FindNoteDown(-pos);
Clemo 0:cb80470434eb 223 }
Clemo 0:cb80470434eb 224 if (pos>0)
Clemo 0:cb80470434eb 225 {
Clemo 0:cb80470434eb 226 return Arp_FindNoteUp(pos);
Clemo 0:cb80470434eb 227 }
Clemo 0:cb80470434eb 228 return 255;
Clemo 0:cb80470434eb 229 }*/
Clemo 0:cb80470434eb 230
Clemo 0:cb80470434eb 231
Clemo 0:cb80470434eb 232 byte Arp_FindNote(signed char pos)
Clemo 0:cb80470434eb 233 {
Clemo 0:cb80470434eb 234 byte i,j,n,l,o;
Clemo 0:cb80470434eb 235 //set to unused value = next note not found
Clemo 0:cb80470434eb 236 o = 255;
Clemo 0:cb80470434eb 237 if (pos<0)
Clemo 0:cb80470434eb 238 {
Clemo 0:cb80470434eb 239 //set start of search at top or bottom of keyboard (at the moment you can't arpeggiate top or bottom note)
Clemo 0:cb80470434eb 240 n = 127;
Clemo 0:cb80470434eb 241 }
Clemo 0:cb80470434eb 242 else
Clemo 0:cb80470434eb 243 {
Clemo 0:cb80470434eb 244 n = 0;
Clemo 0:cb80470434eb 245 }
Clemo 0:cb80470434eb 246 l = abs(pos);
Clemo 0:cb80470434eb 247 //now track up/down keyboard finding notes. loop l times, setting o=note if note is down
Clemo 0:cb80470434eb 248 for (i=0; i<l; i++)
Clemo 0:cb80470434eb 249 {
Clemo 0:cb80470434eb 250 for (j=0; j<128; j++)
Clemo 0:cb80470434eb 251 {
Clemo 0:cb80470434eb 252 if (pos>0)
Clemo 0:cb80470434eb 253 {
Clemo 0:cb80470434eb 254 if (n<127)
Clemo 0:cb80470434eb 255 {
Clemo 0:cb80470434eb 256 n++;
Clemo 0:cb80470434eb 257 }
Clemo 0:cb80470434eb 258 else
Clemo 0:cb80470434eb 259 {
Clemo 0:cb80470434eb 260 o = 255;
Clemo 0:cb80470434eb 261 break;
Clemo 0:cb80470434eb 262 }
Clemo 0:cb80470434eb 263 }
Clemo 0:cb80470434eb 264 else if (pos<0)
Clemo 0:cb80470434eb 265 {
Clemo 0:cb80470434eb 266 if (n>0)
Clemo 0:cb80470434eb 267 {
Clemo 0:cb80470434eb 268 n--;
Clemo 0:cb80470434eb 269 }
Clemo 0:cb80470434eb 270 else
Clemo 0:cb80470434eb 271 {
Clemo 0:cb80470434eb 272 o = 255;
Clemo 0:cb80470434eb 273 break;
Clemo 0:cb80470434eb 274 }
Clemo 0:cb80470434eb 275 }
Clemo 0:cb80470434eb 276 else
Clemo 0:cb80470434eb 277 {
Clemo 0:cb80470434eb 278 break; //safety
Clemo 0:cb80470434eb 279 }
Clemo 0:cb80470434eb 280 if (MIDI_Get_KeyDown(n)==true)
Clemo 0:cb80470434eb 281 {
Clemo 0:cb80470434eb 282 o = n;
Clemo 0:cb80470434eb 283 break;
Clemo 0:cb80470434eb 284 }
Clemo 0:cb80470434eb 285 }
Clemo 0:cb80470434eb 286 }
Clemo 0:cb80470434eb 287 //return o. It'll either be 255 if failed to find note, or the note num.
Clemo 0:cb80470434eb 288 return o;
Clemo 0:cb80470434eb 289 }
Clemo 0:cb80470434eb 290
Clemo 0:cb80470434eb 291
Clemo 0:cb80470434eb 292 //increments arp_curpos
Clemo 0:cb80470434eb 293 void Arp_IncPatPos(void)
Clemo 0:cb80470434eb 294 {
Clemo 0:cb80470434eb 295 if (arp_pingpong==false){ //if not in ping-pong mode
Clemo 0:cb80470434eb 296 if (arp_curpos==PATLEN-1){ //if at end of pattern
Clemo 0:cb80470434eb 297 arp_curpos = 0; //restart
Clemo 0:cb80470434eb 298 }
Clemo 0:cb80470434eb 299 else{
Clemo 0:cb80470434eb 300 arp_curpos++; //otherwise increment
Clemo 0:cb80470434eb 301 }
Clemo 0:cb80470434eb 302 }
Clemo 0:cb80470434eb 303 else{ //if in ping-pong
Clemo 0:cb80470434eb 304 if (arp_pongdown==false){ //and heading up through pattern
Clemo 0:cb80470434eb 305 if (arp_curpos>=PATLEN-1){ //if hit end of pattern flip direction
Clemo 0:cb80470434eb 306 arp_curpos--;
Clemo 0:cb80470434eb 307 arp_pongdown = true;
Clemo 0:cb80470434eb 308 }
Clemo 0:cb80470434eb 309 else{
Clemo 0:cb80470434eb 310 arp_curpos++; //otherwise decrement
Clemo 0:cb80470434eb 311 }
Clemo 0:cb80470434eb 312 }
Clemo 0:cb80470434eb 313 else{ //if heading down the pattern
Clemo 0:cb80470434eb 314 if (arp_curpos<=0){ //and hit the start, flip direction
Clemo 0:cb80470434eb 315 arp_curpos++;
Clemo 0:cb80470434eb 316 arp_pongdown = false;
Clemo 0:cb80470434eb 317 }
Clemo 0:cb80470434eb 318 else{
Clemo 0:cb80470434eb 319 arp_curpos--; //otherwise decrement
Clemo 0:cb80470434eb 320 }
Clemo 0:cb80470434eb 321 }
Clemo 0:cb80470434eb 322 }
Clemo 0:cb80470434eb 323 }
Clemo 0:cb80470434eb 324
Clemo 0:cb80470434eb 325
Clemo 0:cb80470434eb 326 #endif // __HAS_ARPEGGIATOR__