This is a part of the Kinetiszer project.

Dependencies:   inc

Dependents:   kinetisizer

Revision:
0:cb80470434eb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lfo.c	Tue Oct 28 12:19:42 2014 +0000
@@ -0,0 +1,126 @@
+/*
+Copyright 2013 Paul Soulsby www.soulsbysynths.com
+    This file is part of Atmegatron.
+
+    Atmegatron 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 3 of the License, or
+    (at your option) any later version.
+
+    Atmegatron is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with Atmegatron.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+//**********Bipolar LFO.  16 waveforms, each 64 samples long.*************** 
+
+#include "atmegatron.h"
+
+//lfo waveforms store in PROGMEM
+const signed char lfo_store[16][LFO_LEN] =
+{
+  {0,12,25,37,49,60,71,81,90,98,106,112,117,122,125,126,127,126,125,122,117,112,106,98,90,81,71,60,49,37,25,12,0,-12,-25,-37,-49,-60,-71,-81,-90,-98,-106,-112,-117,-122,-125,-126,-127,-126,-125,-122,-117,-112,-106,-98,-90,-81,-71,-60,-49,-37,-25,-12},  //sine
+  {0,8,16,24,32,40,48,56,64,71,79,87,95,103,111,119,127,119,111,103,95,87,79,71,64,56,48,40,32,24,16,8,0,-8,-16,-24,-32,-40,-48,-56,-64,-71,-79,-87,-95,-103,-111,-119,-127,-119,-111,-103,-95,-87,-79,-71,-64,-56,-48,-40,-32,-24,-16,-8},                  //triangle
+  {127,123,119,115,111,107,103,99,95,91,87,83,79,75,71,67,64,60,56,52,48,44,40,36,32,28,24,20,16,12,8,4,0,-4,-8,-12,-16,-20,-24,-28,-32,-36,-40,-44,-48,-52,-56,-60,-64,-67,-71,-75,-79,-83,-87,-91,-95,-99,-103,-107,-111,-115,-119,-123},                  //saw down
+  {-127,-127,-127,-127,-127,-126,-126,-126,-126,-126,-126,-125,-125,-125,-125,-124,-124,-124,-123,-123,-122,-122,-121,-121,-120,-119,-118,-118,-117,-116,-115,-113,-112,-111,-109,-107,-105,-103,-101,-99,-96,-93,-90,-87,-83,-79,-74,-69,-64,-58,-52,-45,-37,-29,-20,-11,0,12,24,38,53,69,87,107},  //Exponential ramp up
+  {0,25,48,70,88,102,112,118,120,118,114,108,101,95,89,86,85,86,89,95,101,108,114,118,120,118,112,102,88,70,48,25,0,-25,-48,-70,-88,-102,-112,-118,-120,-118,-114,-108,-101,-95,-89,-86,-85,-86,-89,-95,-101,-108,-114,-118,-120,-118,-112,-102,-88,-70,-48,-25},      //3rd sine harmonics
+  {127,127,127,127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127},  //5%
+  {127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127},              //25%
+  {127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127},                              //50% 
+  {127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127},                                              //75%
+  {127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,-127,-127,-127,-127},                                                          //95%
+  {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,67,71,75,79,83,87,91,95,99,103,107,111,115,119,123,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127},    //Ramp up and hold
+  {127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,123,119,115,111,107,103,99,95,91,87,83,79,75,71,67,64,60,56,52,48,44,40,36,32,28,24,20,16,12,8,4},  //Hold and ramp down
+  {127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,127,127,127,127,127,127,127,127,-127,-127,-127,-127,-127,-127,-127,-127,127,127,127,127,127,127,127,127,-127,-127,-127,-127,-127,-127,-127,-127},  //duh dugga
+  {127,127,127,127,127,127,127,127,-127,-127,-127,-127,-127,-127,-127,-127,127,127,127,127,127,127,127,127,-127,-127,-127,-127,-127,-127,-127,-127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,-127,-127,-127,-127,-127,-127,-127,-127},          //dugga duh
+  {-104,-72,-14,91,-35,38,-20,-21,83,47,22,-73,-111,-104,-28,27,79,25,34,-112,-45,20,36,-30,-124,-74,-95,56,63,-91,94,78,-121,-27,49,-110,-25,24,-9,11,-80,65,-10,-56,-101,116,105,58,-67,-108,-127,95,-71,88,54,-2,83,109,-37,59,40,-77,84,-28},    //noise
+  {127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127}    //DC offset                                                          //95%
+};
+unsigned long  lfo_ticklen = 500;          //ticks per LFO cycle.  only used when MIDI clock not present.  default = 500 ticks, therefore 1 cycle per beat
+unsigned long  lfo_clockticklen = 24;      //clock ticks per LFO cylcle.  only used when MIDI clock present.  24 ticks per beat, therefore 1 cycle per beat  
+unsigned long lfo_starttick = 0;           //tick lfo starts oscillating at
+unsigned long lfo_curtick = 0;             //cur tick of lfo
+
+//lets and gets
+unsigned int lfo_speed = 8191;             //speed of lfo.  not actual ticks, just a reference in a lookup table that is then divided to equal actual ticks.
+byte lfo_curtable = 0;                     //current lfo waveform
+boolean lfo_invert = false;                //lfo invert mode
+signed char lfo_level = 0;                        //lfo output (-127 - 127)
+
+//lets and gets
+//LFO speed.  Stored as a lookup table of multipliers, not actual ticks
+void LFO_Let_Speed(unsigned int newspeed)
+{
+  lfo_speed = newspeed;
+  lfo_ticklen = ((unsigned long)lfo_speed+1) * MASTER_BEATTICK >> 13;    //Calculate lfo tick length.  This method is a way of calculating ticks without using slow (and memory consuming) floating point maths.  e.g. 1 cycle per beat = 8192 * 500 >> 13 = 500 
+  if (lfo_ticklen<2){
+    lfo_ticklen = 2;                                                     //Speed must be 2 or great otherwise divide by 0 in LFO_calcval
+  }
+  lfo_clockticklen = ((unsigned long)lfo_speed+1) * 24 >> 13;            //same as above, this time for when MIDI clock is present
+  if (lfo_clockticklen<2){
+        lfo_clockticklen = 2;                                            //Speed must be 2 or great otherwise divide by 0 in LFO_calcval
+  }
+}
+unsigned int LFO_Get_Speed(void)
+{
+  return lfo_speed;
+}
+//set and get lfo waveform
+void LFO_Let_Type(byte newtable)
+{
+  lfo_curtable = newtable;
+}
+byte LFO_Get_Type(void)
+{
+  return lfo_curtable;
+}
+//set and get invert mode
+void LFO_Let_Invert(boolean newinv)
+{
+  lfo_invert = newinv;
+}
+boolean LFO_Get_Invert(void)
+{
+  return lfo_invert;
+}
+//return current lfo level (-127 - 127)
+signed char LFO_Get_Level(void)
+{
+  if (lfo_invert==true){
+    return -lfo_level;      //invert output if invert mode on
+  }
+  else{
+    return lfo_level;  
+  }
+}
+
+//LFO meat
+//reset lfo start tick.  lfo is reset when first key is pressed
+void LFO_Reset(void)
+{
+  if (MIDI_Get_ClockPresent()==false){
+    lfo_starttick = master_tick;
+  }
+}
+//calculate the current output of the lfo
+void LFO_CalcVal(void)
+{
+  unsigned long pos; 
+  int index;
+  //char lfoval;
+  if (MIDI_Get_ClockPresent()==false){                                    //if midi clock not used:
+    lfo_curtick = master_tick - lfo_starttick;                            //get ticks since lfo started
+    pos = lfo_curtick % lfo_ticklen;                                      //calculate position within cycle in ticks
+    index = (pos * LFO_LEN) / lfo_ticklen;                                //convert to position within wavetable array
+  }
+  else{
+    pos = MIDI_Get_ClockTick() % lfo_clockticklen;                        //calculate position within cycle in clock ticks
+    index = (pos * LFO_LEN) / lfo_clockticklen;                           //convert to position within wavetable array
+  }
+  lfo_level = lfo_store[lfo_curtable][index];      //set lfo level
+}
+