diff --git a/circuitsim/lookup-tables.ipynb b/circuitsim/lookup-tables.ipynb
index 61b523fe8ff0473e06da32d61094b0a4e4c47b8a..8d29c763aaefa1ae18ddce5f39b650c3c122b2c7 100644
--- a/circuitsim/lookup-tables.ipynb
+++ b/circuitsim/lookup-tables.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "code",
-   "execution_count": 2,
+   "execution_count": 1,
    "id": "52c8bec3-db2d-4522-b692-b035a71410de",
    "metadata": {},
    "outputs": [
@@ -16,7 +16,7 @@
     {
      "data": {
       "application/vnd.jupyter.widget-view+json": {
-       "model_id": "41b995dfbdf246859dc4a9991f85540b",
+       "model_id": "ffe8405ccce2405c84171b7c83e66e65",
        "version_major": 2,
        "version_minor": 0
       },
@@ -136,14 +136,14 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 41,
+   "execution_count": 2,
    "id": "41562cc6-9911-4fb1-87ec-f2b3c8bfb3c2",
    "metadata": {},
    "outputs": [
     {
      "data": {
       "application/vnd.jupyter.widget-view+json": {
-       "model_id": "efcba863f7d145b390f1118f16070ad5",
+       "model_id": "eddca77aa50c47da8c24ed47bc863c0c",
        "version_major": 2,
        "version_minor": 0
       },
@@ -160,7 +160,7 @@
        "16"
       ]
      },
-     "execution_count": 41,
+     "execution_count": 2,
      "metadata": {},
      "output_type": "execute_result"
     },
@@ -246,14 +246,14 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 44,
+   "execution_count": 3,
    "id": "ecc666b0-8195-4276-a576-39d41753b540",
    "metadata": {},
    "outputs": [
     {
      "data": {
       "application/vnd.jupyter.widget-view+json": {
-       "model_id": "2c77d02991b94167ae4191faa991c4c6",
+       "model_id": "e17619a0890a4ab081293b27925c743d",
        "version_major": 2,
        "version_minor": 0
       },
@@ -270,7 +270,7 @@
        "0.0"
       ]
      },
-     "execution_count": 44,
+     "execution_count": 3,
      "metadata": {},
      "output_type": "execute_result"
     },
@@ -363,14 +363,14 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 42,
+   "execution_count": 4,
    "id": "2ecfda42-4a3c-489a-bc90-8576648c339c",
    "metadata": {},
    "outputs": [
     {
      "data": {
       "application/vnd.jupyter.widget-view+json": {
-       "model_id": "0a1fd320498041f5b5d7edd19c64d36a",
+       "model_id": "56f51bfc443847a0adda4da0ff439e8a",
        "version_major": 2,
        "version_minor": 0
       },
@@ -387,7 +387,7 @@
        "0.9999999999999999"
       ]
      },
-     "execution_count": 42,
+     "execution_count": 4,
      "metadata": {},
      "output_type": "execute_result"
     },
@@ -480,14 +480,14 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 15,
+   "execution_count": 5,
    "id": "e51416f3-f34d-4513-9f0c-fa52c468274e",
    "metadata": {},
    "outputs": [
     {
      "data": {
       "application/vnd.jupyter.widget-view+json": {
-       "model_id": "098c400f3b684499968bef484bd18f3d",
+       "model_id": "74318935b12f4752aec3807327bea0fe",
        "version_major": 2,
        "version_minor": 0
       },
@@ -501,7 +501,7 @@
     {
      "data": {
       "application/vnd.jupyter.widget-view+json": {
-       "model_id": "59ad9d541c5340b2980b7531a9a1a285",
+       "model_id": "51bcd6adaa2a492d9f61fdd4dcca7232",
        "version_major": 2,
        "version_minor": 0
       },
@@ -730,14 +730,14 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 11,
+   "execution_count": 26,
    "id": "f35f1609-3a10-4dce-b7dd-201d79f2c39c",
    "metadata": {},
    "outputs": [
     {
      "data": {
       "application/vnd.jupyter.widget-view+json": {
-       "model_id": "2cffc24c8bc34b569e6e7c74e064bcbb",
+       "model_id": "b0e2832a8efa405790ad1cfd4529aa3b",
        "version_major": 2,
        "version_minor": 0
       },
@@ -751,7 +751,7 @@
     {
      "data": {
       "application/vnd.jupyter.widget-view+json": {
-       "model_id": "c7d59ce714284b299d5406aab8d5ae5e",
+       "model_id": "1dcfe3c0ccad4e4a92ea2d43a92ad01f",
        "version_major": 2,
        "version_minor": 0
       },
@@ -761,6 +761,13 @@
      },
      "metadata": {},
      "output_type": "display_data"
+    },
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "19\n"
+     ]
     }
    ],
    "source": [
@@ -769,17 +776,17 @@
     "# X / Y / Curvature\n",
     "lines_orig = [\n",
     "    [-1.5, -1.0, 1.0],\n",
-    "    [-0.7, -0.7, 0.0],\n",
+    "    [-0.9, -0.8, 0.0],\n",
     "    [0.0, 0.0, 0.0],\n",
-    "    [0.7, 0.7, -1.4],\n",
+    "    [0.9, 0.8, -1.1],\n",
     "    [1.5, 1.0, 0.0],\n",
     "]\n",
     "\n",
-    "lines = make_lines(lines_orig, 20)\n",
+    "lines = make_lines(lines_orig, 8)\n",
     "\n",
     "\n",
     "x = [a[0] for a in lines]\n",
-    "y = [a[1]*0.5 for a in lines]\n",
+    "y = [min(1.0, a[1]) for a in lines]\n",
     "c = [a[2] for a in lines]\n",
     "# draw(x, y, 0.45/2)\n",
     "\n",
@@ -803,6 +810,7 @@
     "mybtn.on_click(mybtn_event_handler)\n",
     "\n",
     "display(mybtn)\n",
+    "print(len(x))\n",
     "\n"
    ]
   },
diff --git a/code/daisy-looper/daisy-looper.ino b/code/daisy-looper/daisy-looper.ino
index 3287a84ad9ab99c8c01f537d6d698321e5499fcb..621936ee3c9aa3137650a64fa6b38f9d12a18703 100644
--- a/code/daisy-looper/daisy-looper.ino
+++ b/code/daisy-looper/daisy-looper.ino
@@ -12,6 +12,7 @@
 #include "helpers.h"
 #include "luts.h"
 #include "ui.h"
+#include "lfo.h"
 
 MIDI_CREATE_DEFAULT_INSTANCE();
 #define BUFFER_LENGTH_SECONDS 5
@@ -84,8 +85,9 @@ float reverb_tone = 15000.0f;
 float reverb_decay = 0.95f;
 float lfo_speed = 8.0f;
 int lfo_kind = 0;
+float rand_pitch_mod = 0.0f;
 
-float pressure = 0.0f;
+//float pressure = 0.0f;
 
 // Actual audio-processing is orchestrated here
 void AudioCallback(float **in, float **out, size_t size) {
@@ -98,10 +100,33 @@ void AudioCallback(float **in, float **out, size_t size) {
   
   // Iterate through the samples in the buffer
   for (size_t i = 0; i < size; i++) {
+    float lfo_value = 0.0f;
+    switch (lfo_kind) {
+      case LfoKind::LFO_KIND_TRI:
+        lfo.SetWaveform(Oscillator::WAVE_TRI);
+        lfo_value = lfo.Process();
+        break;
+      case LfoKind::LFO_KIND_SQR:
+        lfo.SetWaveform(Oscillator::WAVE_SQUARE);
+        lfo_value = lfo.Process();
+        break;
+      default:
+        break;
+    }
+    
+    tick.SetFreq(0.25f+lfo_speed*49.75f);
     uint8_t trig = tick.Process();
-    float lfo_value = lfo.Process();
     float noise_value = noise.Process();
 
+    switch (lfo_kind) {
+      case LfoKind::LFO_KIND_RAND:
+        easer.setFactor(0.01);
+        break;
+      case LfoKind::LFO_KIND_JUMP:
+        easer.setFactor(1.0);
+        break;
+    }
+
     float rand = easer.Process(
       sample_and_hold.Process(
         trig, 
@@ -114,21 +139,36 @@ void AudioCallback(float **in, float **out, size_t size) {
     }
     // When the metro ticks, trigger the envelope to start.
     float random_amount = lfo_amount * 2.0;
+    
     if (trig) {
       // Random LFO
-      if (lfo_kind == 1) {
-        // Chance
-        if (random(0.0f, 1.0f) < lfo_amount) {
-          ui.activeLooper()->addToPlayhead(rand * random_amount * 48000.0f);
-        }
+      switch (lfo_kind) {
+        case LfoKind::LFO_KIND_RAND:
+          rand_pitch_mod = rand * random_amount * 5.0f;
+          break;
+        case LfoKind::LFO_KIND_JUMP:
+          // Chance
+          if (drand(0.0f, 1.0f) < lfo_amount) {
+            ui.activeLooper()->addToPlayhead(rand * random_amount * 8000.0f);
+          }
+          break;
+        default:
+          break;
       }
     }
 
     // Add the LFO to the signal if it is active
-    if (lfo_kind == 0) {
-      ui.activeLooper()->setPlaybackSpeed(pitch_val + lfo_value * lfo_amount + midi_pitch_offset);
-    } else {
-      ui.activeLooper()->setPlaybackSpeed(pitch_val + midi_pitch_offset);
+    switch (lfo_kind) {
+      case LfoKind::LFO_KIND_TRI:
+      case LfoKind::LFO_KIND_SQR:
+        ui.activeLooper()->setPlaybackSpeed(pitch_val + lfo_value * lfo_amount + midi_pitch_offset);
+        break;
+      case LfoKind::LFO_KIND_RAND:
+        ui.activeLooper()->setPlaybackSpeed(pitch_val + rand_pitch_mod + midi_pitch_offset);
+        break;
+      default:
+        ui.activeLooper()->setPlaybackSpeed(pitch_val + midi_pitch_offset);
+        break;
     }
     
 
@@ -137,6 +177,11 @@ void AudioCallback(float **in, float **out, size_t size) {
     if (ui.rec_source == REC_SOURCE_PRE) {
      ui.activeLooper()->Record(in[1][i]);
     }
+
+    if (ui.rec_source == REC_SOURCE_LAST_BUF) {
+      // FIXME: This might process the previous looper twice later below, add check...
+      ui.activeLooper()->Record(ui.previousLooper()->Process());
+    }
     
     // Process the input envelope
     input_envelope_follower.Process(in[1][i]);
@@ -145,7 +190,7 @@ void AudioCallback(float **in, float **out, size_t size) {
     switch (ui.buffer_summing_mode) {
       case BUFFER_SUM_MODE_SOLO:
         // Only play active looper
-        looper_out = saturate(ui.activeLooper()->Process());
+        looper_out = ui.activeLooper()->Process();
         break;
       case BUFFER_SUM_MODE_SUM:
         // Sum all loopers
@@ -154,7 +199,7 @@ void AudioCallback(float **in, float **out, size_t size) {
         looper_out += looper_c.Process();
         looper_out += looper_d.Process();
         looper_out += looper_e.Process();
-        looper_out = saturate(looper_out);
+        looper_out = looper_out;
         break;
       case BUFFER_SUM_MODE_RING:
         // Sum all loopers and ringmodulate with input
@@ -170,12 +215,12 @@ void AudioCallback(float **in, float **out, size_t size) {
           deadbanded_input = max(0.0f, in[1][i] - 0.05f);
         }
         looper_out *= deadbanded_input*2.0f;
-        looper_out = saturate(looper_out);
+        looper_out = looper_out;
         break;
     }
 
     // looper_out = pressure * looper_out;
-    looper_out = volume * looper_out;
+    looper_out = saturate(volume * looper_out);
 
     // Mix the dry/Wet of the looper
     output = drywetmix * looper_out + in[1][i] * (1.0f - drywetmix);
@@ -187,7 +232,8 @@ void AudioCallback(float **in, float **out, size_t size) {
     reverb.Process(output, output, &out1, &out2);
 
     // Short decays are silent, so increase level here
-    out1 = out1 * map(reverb_decay, 0.0f, 1.0f, 2.0f, 1.0f);
+    float dec_fac = 1.0f + (1.0f - reverb_decay) * 2.0f;
+    out1 = out1 * dec_fac;
 
     // Mix reverb with the dry signal depending on the amount dialed
     output = output * (1.0f - reverbmix) + out1 * reverbmix;
@@ -238,16 +284,16 @@ void handleNoteOff(byte inChannel, byte inNote, byte inVelocity) {
   midi_pitch_offset = 0.0f;
 }
 
-void handleAftertouch(byte channel, byte channel_pressure) {
-  #ifdef DEBUGMODE
-  Serial.print("[MIDI AFTER] chn<");
-  Serial.print((int) channel);
-  Serial.print("> pressure<");
-  Serial.print((int) channel_pressure);
-  Serial.println(">");
-  #endif
-  pressure = float(channel_pressure)/127.0f;
-}
+// void handleAftertouch(byte channel, byte channel_pressure) {
+//   #ifdef DEBUGMODE
+//   Serial.print("[MIDI AFTER] chn<");
+//   Serial.print((int) channel);
+//   Serial.print("> pressure<");
+//   Serial.print((int) channel_pressure);
+//   Serial.println(">");
+//   #endif
+//   pressure = float(channel_pressure)/127.0f;
+// }
 
 
 
@@ -261,6 +307,7 @@ void setup() {
   blocksize = 64.0f;
 
   // Create a Tick and a noise source for the Sample and Hold
+  tick.SetFreq(1.0f+lfo_amount*99.0f);
   tick.Init(10, sample_rate);
   noise.Init();
   
@@ -313,14 +360,14 @@ void setup() {
   // Setup MIDI handlers
   MIDI.setHandleNoteOn(handleNoteOn);
   MIDI.setHandleNoteOff(handleNoteOff);
-  MIDI.setHandleAfterTouchChannel(handleAftertouch);
+  // MIDI.setHandleAfterTouchChannel(handleAftertouch);
   
   MIDI.begin(MIDI_CHANNEL_OMNI); // Listen to all incoming messages
 
   // Set Knob names and display functions
   pot_1.name = "Start";
   pot_2.name = "Length";
-  pot_3.setDisplayMode("Pitch", 1000.0f, POT_DISPLAY_MODE_PERCENT);
+  pot_3.setDisplayMode("Speed", 1000.0f, POT_DISPLAY_MODE_PERCENT);
   pot_4.setDisplayMode("Mix", 100.0f, POT_DISPLAY_MODE_PERCENT);
   pot_5.setDisplayMode("LFO", 100.0f, POT_DISPLAY_MODE_PERCENT);
   pot_6.setDisplayMode("Volume", 400.0f, POT_DISPLAY_MODE_PERCENT);
diff --git a/code/daisy-looper/helpers.h b/code/daisy-looper/helpers.h
index 964bfa37810cb2f80ddb517659b9493e1d421846..2f6601ac9522345ecb78328232270987587998ba 100644
--- a/code/daisy-looper/helpers.h
+++ b/code/daisy-looper/helpers.h
@@ -139,4 +139,20 @@ int button_multi(const char *buf, int x, int y, int color, int underline_line=0,
   return w;
 }
 
+float saturate(float x) {
+  if (x < -3.0f) {
+    return -1.0f;
+  } else if (x > 3.0f) {
+    return 1.0f;
+  } else {
+    return x * (27.0f + x * x ) / (27.0f + 9.0f * x * x);
+  }
+}
+
+
+double drand(double minf, double maxf){
+  return minf + random(1UL << 31) * (maxf - minf) / (1UL << 31);  // use 1ULL<<63 for max double values)
+}
+
+
 #endif
\ No newline at end of file
diff --git a/code/daisy-looper/lfo.h b/code/daisy-looper/lfo.h
new file mode 100644
index 0000000000000000000000000000000000000000..a91cdb6d496e4ed4b3da4cecc5eeaeb31ca85869
--- /dev/null
+++ b/code/daisy-looper/lfo.h
@@ -0,0 +1,9 @@
+#pragma once
+
+enum LfoKind {
+	LFO_KIND_TRI,
+	LFO_KIND_SQR,
+	LFO_KIND_RAND,
+	LFO_KIND_JUMP,
+	LFO_KIND_NONE,
+};
\ No newline at end of file
diff --git a/code/daisy-looper/looper.h b/code/daisy-looper/looper.h
index 5cb2016ac07253e9b9e709273987021460d544a6..a9a0575ade1d75b4449f2a1931ef39ffd5155d66 100644
--- a/code/daisy-looper/looper.h
+++ b/code/daisy-looper/looper.h
@@ -6,7 +6,6 @@ namespace atoav {
 
 enum RecPitchMode {
   REC_PITCH_MODE_NORMAL,
-  REC_PITCH_MODE_PITCHED,
   REC_PITCH_MODE_UNPITCHED,
   REC_PITCH_MODE_LAST,
 };
@@ -236,11 +235,6 @@ void Looper::Record(float in) {
       case REC_PITCH_MODE_UNPITCHED: 
         rec_head.setIncrement(playheads[0].increment); 
         break;
-      case REC_PITCH_MODE_PITCHED:
-        if (playheads[0].increment != 0.0) {
-          rec_head.setIncrement(1.0f/playheads[0].increment);
-        }
-        break;
     }
     // Increment recording head
     rec_head.update();
@@ -307,32 +301,41 @@ float Looper::Process() {
     if (!playheads[i].isActive()) continue;
 
     // Ensure we are actually inside the buffer
-    int play_pos = int(loop_start + playheads[i].read()) % buffer_length;
+    int from_start = int(playheads[i].read()) % loop_length;
+    int play_pos = loop_start + from_start;
+
+    float vol = 1.0f;
+    if (from_start <= kFadeLength) {
+      vol = from_start / float(kFadeLength);
+    }
+    int from_end = abs(int(loop_length) - from_start);
+    if (from_end <= kFadeLength) {
+      vol = from_end / float(kFadeLength);
+    }
 
     // Read from the buffer
-    mix += buffer[play_pos];
+    mix += buffer[play_pos] * vol;
 
     // Advance the playhead
     playheads[i].update();
 
     // Ensure the playhead stays within bounds of the loop
-    if ((playheads[i].read()) >= loop_length) {
-        playheads[i].setPosition(0.0f);
-      } else if (playheads[i].read() <= 0.0f) {
-        playheads[i].setPosition(loop_length);
-      }
+    float pos = playheads[i].read();
+    if (pos >= loop_length || pos <= 0.0f) {
+      playheads[i].setPosition(fmod(pos, float(loop_length)));
+    }
   }
-  return saturate(mix);
+  return mix;
 }
 
 float Looper::GetPlayhead() {
-  return float(playheads[0].read()) / float(buffer_length);
+  return float(int(playheads[0].read()) % loop_length) / float(buffer_length);
 }
 
 float* Looper::GetPlayheads() {
   static float playhead_positions[9];
   for (size_t i=0; i<9; i++) {
-    playhead_positions[i] = float(playheads[i].read()) / float(buffer_length);
+    playhead_positions[i] = float(int(playheads[i].read()) % loop_length) / float(buffer_length);
   }
   return playhead_positions;
 }
diff --git a/code/daisy-looper/luts.h b/code/daisy-looper/luts.h
index 7974c6dd9ff07a44a084b642c603d24a01b34c42..3a2e1dfe18613f55fa9d3ce71dcf6c3b33504b73 100644
--- a/code/daisy-looper/luts.h
+++ b/code/daisy-looper/luts.h
@@ -13,11 +13,6 @@ float pitch_knob_lookup_y[] = {-1.0, -1.0, -0.9, -0.9, -0.8, -0.8, -0.7, -0.7, -
 size_t pitch_knob_lookup_length = 62;
 
 
-// Lookup Curves for Saturation b
-float saturation_lookup_x[] = {-1.5, -1.46, -1.42, -1.38, -1.3399999999999999, -1.3, -1.26, -1.22, -0.7, 0.0, 0.7, 0.74, 0.78, 0.82, 0.86, 0.8999999999999999, 0.94, 0.98, 1.5};
-float saturation_lookup_y[] = {-0.5, -0.49998125, -0.49985, -0.49949375, -0.4988, -0.49765625, -0.49595, -0.49356875, -0.35, 0.0, 0.35, 0.367475, 0.38389999999999996, 0.399275, 0.41359999999999997, 0.426875, 0.4391, 0.450275, 0.5};
-size_t saturation_lookup_length = 19;
-
 
 class Easer {
   float output = 0.0f;
@@ -67,13 +62,5 @@ float get_from_xy_table(float* xtable, float* ytable, float f, size_t length) {
   return multiMap<float>(f, xtable, ytable, length);
 }
 
-float saturate(float input) {
-  return get_from_xy_table(
-    saturation_lookup_x, 
-    saturation_lookup_y, 
-    min(1.5f, max(-1.5f, input)), 
-    saturation_lookup_length
-  );
-}
 
 #endif
\ No newline at end of file
diff --git a/code/daisy-looper/potentiometers.h b/code/daisy-looper/potentiometers.h
index 0af8ca43be537ed53e6744cb172dbc62a7e47bda..f5e6aa356f3f2ee7dcb6bc44f7d14fa226f5c1f4 100644
--- a/code/daisy-looper/potentiometers.h
+++ b/code/daisy-looper/potentiometers.h
@@ -69,7 +69,7 @@ class Potentiometer {
     bool last_was_nan = false;
     uint8_t switch_positions;
     uint8_t switch_offset = 0;
-    const char* const switch_labels[2] = {"LFO", "RANDOM"};
+    const char* const switch_labels[4] = {"TRI", "SQR", "RAND", "JUMP"};
 };
 
 Potentiometer::Potentiometer(int pin) {
diff --git a/code/daisy-looper/ui.h b/code/daisy-looper/ui.h
index 04218079b0f7eb305bfcc6b7a14eabb207f61763..19c4720d4839913bfe7c2d92c07bc297e8eb5bd3 100644
--- a/code/daisy-looper/ui.h
+++ b/code/daisy-looper/ui.h
@@ -46,7 +46,7 @@ enum RecMode {
 // Represents possible recording sources
 enum RecSource {
   REC_SOURCE_PRE,            // Record Incoming audio
-  REC_SOURCE_POST,           // Record effects
+  REC_SOURCE_LAST_BUF,       // Record Last selected Buffer
   REC_SOURCE_OUT,            // Record the buffer output
   REC_SOURCE_NOISE,          // Record Noise
   REC_SOURCE_LAST
@@ -104,11 +104,11 @@ class Ui {
     Ui() : button_grids {
       ButtonGrid((int) UI_MODE_REC_MENU, {
         GridButton("REC\nMENU", &button_1, true),
-        GridButton("MOM\nTOGGLE", &button_2, false, BUTTON_TYPE_TOGGLE, 0, "REC/OVERDUB BUTTONS\n\nMOM->Record while    \n     Button is held\n\nTOGGLE->Press once to\n        start, press \n        again to stop"),
-        GridButton("PRE\nPOST\nOUT\nNOISE", &button_3, false, BUTTON_TYPE_MULTITOGGLE, 0, "REC/OVERDUB SOURCE\n\nPRE----->Direct Input\nPOST---->With Effects\nOUT---->Looper Output\nNOISE--->Noise Source"),
-        GridButton("FULL\nLOOP\nSHOT", &button_4, false, BUTTON_TYPE_MULTITOGGLE, 1, "RECORDING REGION\n\nFULL---->Whole Buffer\nLOOP----->Loop Bounds\nSHOT->Full Buffer but\n      stop at the end"),
-        GridButton("NORMAL\nPITCHD\nUNPTCH", &button_5, false, BUTTON_TYPE_MULTITOGGLE, 0, "SPEED OF THE REC HEAD\n\nNORMAL--->Fixed Speed\nPITCHD->Inverse Playh\nUNPITCH----->Playhead\n             Speed"),
-        GridButton("START\nLOOPST\nPLAYHD", &button_6, false, BUTTON_TYPE_MULTITOGGLE, 0, "START RECORDING AT\n\nSTART--->Start of the\n         Buffer\nLOOP---->Start of the\n         Loop\nPLAYH--->Position of\n         the Playhead"),
+        GridButton("MOM\nTOGGLE", &button_2, false, BUTTON_TYPE_TOGGLE, 0),
+        GridButton("PRE\nLAST\nOUT\nNOISE", &button_3, false, BUTTON_TYPE_MULTITOGGLE, 0),
+        GridButton("FULL\nLOOP\nSHOT", &button_4, false, BUTTON_TYPE_MULTITOGGLE, 1),
+        GridButton("NORMAL\nUNPTCH", &button_5, false, BUTTON_TYPE_MULTITOGGLE, 0),
+        GridButton("START\nLOOPST\nPLAYHD", &button_6, false, BUTTON_TYPE_MULTITOGGLE, 0),
       }),
       ButtonGrid((int) UI_MODE_PLAY_MENU, {
         GridButton("STOP\nLOOP\nMULTI\nMIDI", &button_1, false, BUTTON_TYPE_MULTITOGGLE, 1),
@@ -158,6 +158,7 @@ class Ui {
 
     // Default active buffer
     ActiveBuffer active_buffer = ACTIVE_BUFFER_A;
+    ActiveBuffer previous_buffer = ACTIVE_BUFFER_A;
 
     // Default active summing mode
     BufferSummingMode buffer_summing_mode = BUFFER_SUM_MODE_SOLO;
@@ -208,28 +209,6 @@ class Ui {
     // Renders a splash screen (runs once)
     void renderSplash() {
       display.setTextSize(1);
-      if (show_splash) {
-        display.setTextColor(SH110X_BLACK);
-        // Play a fancy intro splash screen
-        for (int i=0; i < 91; i++) {
-          display.clearDisplay();
-          display.fillCircle(display.width()/2, display.height()/2, i, SH110X_WHITE);
-          display.fillCircle(display.width()/2, display.height()/2, max(0, i-2), SH110X_BLACK);
-          if (i < 50) {
-            centeredText("DAISYY", display.width()/2, display.height()/2-4, SH110X_WHITE);
-            centeredText("LOOPER", display.width()/2, display.height()/2+4, SH110X_WHITE);
-          }
-          
-          display.display();
-          delay(1);
-        }
-        display.invertDisplay(true);
-        display.display();
-        delay(800);
-        display.clearDisplay();
-        display.invertDisplay(false);
-        display.display();
-      }
 
       // Splash rendering is now done, go to next UI Mode
       setMode(UI_MODE_DEFAULT);
@@ -354,22 +333,27 @@ class Ui {
         Button* home_button = setupButtonGrid(n);
 
         button_1.onPress([this, n](){ 
+          previous_buffer = active_buffer;
           active_buffer = ACTIVE_BUFFER_A;
           waveform_cache_dirty = true;
         });
         button_2.onPress([this, n](){ 
+          previous_buffer = active_buffer;
           active_buffer = ACTIVE_BUFFER_B;
           waveform_cache_dirty = true;
         });
         button_3.onPress([this, n](){ 
+          previous_buffer = active_buffer;
           active_buffer = ACTIVE_BUFFER_C;
           waveform_cache_dirty = true;
         });
         button_4.onPress([this, n](){ 
+          previous_buffer = active_buffer;
           active_buffer = ACTIVE_BUFFER_D;
           waveform_cache_dirty = true;
         });
         button_5.onPress([this, n](){ 
+          previous_buffer = active_buffer;
           active_buffer = ACTIVE_BUFFER_E;
           waveform_cache_dirty = true;
         });
@@ -443,7 +427,7 @@ class Ui {
           fx_mode = FX_MODE_LFO;
           pot_5.setDisplayMode("LFO Mode", 100.0f, POT_DISPLAY_MODE_SWITCH);
           pot_5.setSwitch();
-          pot_5.switch_positions = 2;
+          pot_5.switch_positions = 4;
           pot_5.switch_offset = 0;
           pot_6.setDisplayMode("LFO Speed", 100.0f, POT_DISPLAY_MODE_PERCENT);
           pot_7.setDisplayMode("LFO Amount", 100.0f, POT_DISPLAY_MODE_PERCENT);
@@ -818,6 +802,40 @@ class Ui {
       return ptr;
     }
 
+    // Returns a pointer to the currently active looper
+    atoav::Looper * previousLooper() {
+      switch(previous_buffer) {
+        case ACTIVE_BUFFER_A: {
+          atoav::Looper * ptr = &looper_a;
+          return ptr;
+          break;
+        }
+        case ACTIVE_BUFFER_B: {
+          atoav::Looper * ptr = &looper_b;
+          return ptr;
+          break;
+        }
+        case ACTIVE_BUFFER_C: {
+          atoav::Looper * ptr = &looper_c;
+          return ptr;
+          break;
+        }
+        case ACTIVE_BUFFER_D: {
+          atoav::Looper * ptr = &looper_d;
+          return ptr;
+          break;
+        }
+        case ACTIVE_BUFFER_E: {
+          atoav::Looper * ptr = &looper_e;
+          return ptr;
+          break;
+        }
+      }
+      // Unreachable, but makes the compiler shut up
+      atoav::Looper * ptr = &looper_a;
+      return ptr;
+    }
+
     // Set the Looper start/length to a given value
     void setLoop(float start, float length) {
       activeLooper()->SetLoop(start, length);