diff --git a/circuitsim/.jupyter/desktop-workspaces/default-37a8.jupyterlab-workspace b/circuitsim/.jupyter/desktop-workspaces/default-37a8.jupyterlab-workspace
index 04bc81b3f970093890db43fb14747100038b7349..79abff054c2269d9040f61149bdb41c951134600 100644
--- a/circuitsim/.jupyter/desktop-workspaces/default-37a8.jupyterlab-workspace
+++ b/circuitsim/.jupyter/desktop-workspaces/default-37a8.jupyterlab-workspace
@@ -1 +1 @@
-{"data":{"layout-restorer:data":{"main":{"dock":{"type":"tab-area","currentIndex":2,"widgets":["notebook:circuit_sim.ipynb","notebook:lookup-tables.ipynb","notebook:envelope.ipynb"]},"current":"notebook:envelope.ipynb"},"down":{"size":0,"widgets":[]},"left":{"collapsed":false,"current":"filebrowser","widgets":["filebrowser","running-sessions","@jupyterlab/toc:plugin","extensionmanager.main-view"]},"right":{"collapsed":true,"widgets":["jp-property-inspector","debugger-sidebar"]},"relativeSizes":[0.26227795193312436,0.7377220480668757,0]},"notebook:circuit_sim.ipynb":{"data":{"path":"circuit_sim.ipynb","factory":"Notebook"}},"notebook:lookup-tables.ipynb":{"data":{"path":"lookup-tables.ipynb","factory":"Notebook"}},"notebook:envelope.ipynb":{"data":{"path":"envelope.ipynb","factory":"Notebook"}}},"metadata":{"id":"default"}}
\ No newline at end of file
+{"data":{"layout-restorer:data":{"main":{"dock":{"type":"tab-area","currentIndex":1,"widgets":["notebook:circuit_sim.ipynb","notebook:lookup-tables.ipynb","notebook:envelope.ipynb"]},"current":"notebook:lookup-tables.ipynb"},"down":{"size":0,"widgets":[]},"left":{"collapsed":false,"current":"filebrowser","widgets":["filebrowser","running-sessions","@jupyterlab/toc:plugin","extensionmanager.main-view"]},"right":{"collapsed":true,"widgets":["jp-property-inspector","debugger-sidebar"]},"relativeSizes":[0.13545601726929304,0.864543982730707,0]},"notebook:circuit_sim.ipynb":{"data":{"path":"circuit_sim.ipynb","factory":"Notebook"}},"notebook:lookup-tables.ipynb":{"data":{"path":"lookup-tables.ipynb","factory":"Notebook"}},"notebook:envelope.ipynb":{"data":{"path":"envelope.ipynb","factory":"Notebook"}}},"metadata":{"id":"default"}}
\ No newline at end of file
diff --git a/circuitsim/envelope.ipynb b/circuitsim/envelope.ipynb
index 24c5b4fb713131e438a18f9a576a88e31eb4bb7d..7bec7a59810757934a0fe0484d6d42c118d7a158 100644
--- a/circuitsim/envelope.ipynb
+++ b/circuitsim/envelope.ipynb
@@ -258,9 +258,42 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 121,
    "id": "2e2c2c7f-4bc6-4a1f-b6bd-bf5558b8f03f",
    "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "947364e8d6aa4d1ba675e14ddf866148",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "interactive(children=(FloatSlider(value=0.2, description='f', max=1.0, step=0.001), Output()), _dom_classes=('…"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/plain": [
+       "<function __main__.draw(f)>"
+      ]
+     },
+     "execution_count": 121,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": []
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "6112aebb-dc20-45e3-9ca6-280c76523469",
+   "metadata": {},
    "outputs": [],
    "source": []
   }
diff --git a/circuitsim/lookup-tables.ipynb b/circuitsim/lookup-tables.ipynb
index 0a086e42f16c7453e38f1d7b04efc91bbc582f42..d3401e064b9d0e652195d0b4b7ec48e0d9f6808c 100644
--- a/circuitsim/lookup-tables.ipynb
+++ b/circuitsim/lookup-tables.ipynb
@@ -480,9 +480,168 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 43,
    "id": "e51416f3-f34d-4513-9f0c-fa52c468274e",
    "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "880451c044ba49d5a1686f3db7453888",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "interactive(children=(FloatSlider(value=0.2, description='f', max=10.1, min=-10.0, step=0.001), Output()), _do…"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/plain": [
+       "<function __main__.draw(f)>"
+      ]
+     },
+     "execution_count": 43,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "from matplotlib import pyplot as plt\n",
+    "%matplotlib inline\n",
+    "from ipywidgets import interact, FloatSlider\n",
+    "import matplotlib.transforms as transforms\n",
+    "import math\n",
+    "\n",
+    "def draw(f):\n",
+    "    fig = plt.figure(figsize=(8, 4))\n",
+    "    ax = fig.add_axes([0, 0, 1, 1])\n",
+    "    b = scan2d(x, y, f)\n",
+    "    ax.axhline(y=b, color='red', linestyle='--')\n",
+    "    ax.axvline(x=f, color='red', linestyle='--')\n",
+    "    trans = transforms.blended_transform_factory(\n",
+    "    ax.get_yticklabels()[0].get_transform(), ax.transData)\n",
+    "    ax.text(0.95, b, \"{:.02f}\".format(b), color=\"red\", transform=trans, ha=\"right\", va=\"bottom\")\n",
+    "    ax.grid()\n",
+    "    ax.plot(x, y)\n",
+    "\n",
+    "def lerp(a, b, f=0.5) -> float:\n",
+    "    f = min(1.0, max(0.0, f))\n",
+    "    if f == 0.0:\n",
+    "        return a\n",
+    "    elif f == 1.0:\n",
+    "        return b\n",
+    "    else:\n",
+    "        return a * (1.0-f) + b * f\n",
+    "\n",
+    "def lerp2d(x1, y1, x2, y2, f=0.5):\n",
+    "    if f == 0.0:\n",
+    "        return [x1, x2]\n",
+    "    elif f == 1.0:\n",
+    "        return [x1, x2]\n",
+    "    else:\n",
+    "        x = lerp(x1, x2, f)\n",
+    "        y = lerp(y1, y2, f)\n",
+    "        return [x, y]\n",
+    "\n",
+    "def scan2d(x, y, f):\n",
+    "        # f = min(1.0, max(0.0, f))\n",
+    "        assert len(x) == len(y)\n",
+    "        # Find ax and bx for given factor\n",
+    "        xa = None\n",
+    "        last_value = None\n",
+    "        idx = None\n",
+    "        for i, v in enumerate(x):\n",
+    "            # this = abs(f-v)\n",
+    "            this = f-v\n",
+    "            if xa is None or this > 0:\n",
+    "                xa = this\n",
+    "                idx = i\n",
+    "        idx2 = min(idx+1, len(x)-1)\n",
+    "        if idx == idx2:\n",
+    "            return y[idx]\n",
+    "        xa = x[idx]\n",
+    "        xb = x[idx2]\n",
+    "        ya = y[idx]\n",
+    "        yb = y[idx2]\n",
+    "        xspan = xb-xa\n",
+    "        xscaler = 1/xspan\n",
+    "        new_f = (f-xa)*xscaler\n",
+    "        # print(f\"xa      {xa} [{idx}]\")\n",
+    "        # print(f\"xb      {xb} [{idx2}]\")\n",
+    "        # print(f\"ya      {ya} [{idx}]\")\n",
+    "        # print(f\"yb      {yb} [{idx2}]\")\n",
+    "        # print(f\"xspan   {xspan} [{xb} - {xa}]\")\n",
+    "        # print(f\"xscaler {xscaler} [1/{xspan}]\")\n",
+    "        # print(f\"new_f   {new_f} [({f}-{xa})/{xscaler}]\")\n",
+    "        return lerp(ya, yb, new_f)\n",
+    "        \n",
+    "    \n",
+    "lines_orig = [\n",
+    "    [0.0, 0.0, -0.5],\n",
+    "    [0.45, 0.5, 0.0],\n",
+    "    [0.55, 0.5, 1.0],\n",
+    "    [1.0, 1.0, 0.0],\n",
+    "]\n",
+    "\n",
+    "half_deadband = 0.1\n",
+    "\n",
+    "lines_orig = [\n",
+    "    [-10.0, -10.0, 0.0],\n",
+    "    [-10.0+half_deadband, -10.0, 0.0],\n",
+    "] \n",
+    "\n",
+    "steps = list(range(-9, 11))\n",
+    "for i in steps:\n",
+    "    f = float(i)\n",
+    "    lines_orig.append([f-half_deadband, f, 0.0])\n",
+    "    lines_orig.append([f+half_deadband, f, 0.0])\n",
+    "\n",
+    "\n",
+    "lines = []\n",
+    "for i, l in enumerate(lines_orig):\n",
+    "    i2 = min(len(lines_orig)-1, i+1)\n",
+    "    if l[2] == 0.0:\n",
+    "        lines.append(l)\n",
+    "    else:\n",
+    "        xa = lines_orig[i][0]\n",
+    "        xb = lines_orig[i2][0]\n",
+    "        ya = lines_orig[i][1]\n",
+    "        yb = lines_orig[i2][1]\n",
+    "        x_span = xb-xa\n",
+    "        y_span = yb-ya\n",
+    "        x_step = 1/20\n",
+    "        y_step = 1/20\n",
+    "        for j in range(20):\n",
+    "            x = x_step * j\n",
+    "            y = y_step * j\n",
+    "            y_curve = 0\n",
+    "            if l[2] > 0.0:\n",
+    "                y_curve = y*y*y\n",
+    "            else:\n",
+    "                y_curve = y*y\n",
+    "            y = (1.0-l[2]) * y + l[2] * y_curve\n",
+    "            lines.append([xa+x*x_span, ya+y*y_span, 0.0])\n",
+    "\n",
+    "\n",
+    "x = [a[0] for a in lines]\n",
+    "y = [a[1] for a in lines]\n",
+    "c = [a[2] for a in lines]\n",
+    "# draw(x, y, 0.45/2)\n",
+    "\n",
+    "interact(draw, f=FloatSlider(min=min(x), max=max(x), step=0.001, value=0.2))\n",
+    "\n",
+    "    "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "f35f1609-3a10-4dce-b7dd-201d79f2c39c",
+   "metadata": {},
    "outputs": [],
    "source": []
   }
diff --git a/code/daisy-looper/daisy-looper.ino b/code/daisy-looper/daisy-looper.ino
index f69de3883337a405757ffc084851f6b2502d862d..e798e3a2f4ac2a8aed7f05a017211dda53181d2d 100644
--- a/code/daisy-looper/daisy-looper.ino
+++ b/code/daisy-looper/daisy-looper.ino
@@ -20,13 +20,11 @@
 #include "helpers.h"
 #include "ui.h"
 
-#define UI_FPS 60.0
-
 static const size_t buffer_length = 48000 * 5;
 static float DSY_SDRAM_BSS buffer[buffer_length];
 
+// Create instances of audio stuff
 atoav::Looper looper;
-static PitchShifter pitch_shifter;
 static atoav::EnvelopeFollower input_envelope_follower;
 DelayLine<float, 24000> delayline;
 DSY_SDRAM_BSS ReverbSc reverb;
@@ -35,11 +33,8 @@ Oscillator lfo;
 static SampleHold sample_and_hold;
 static WhiteNoise noise;
 static Metro tick;
-// Resonator res;
-
-CpuLoadMeter load;
 
-// Buttons
+// Initialize Buttons
 Button button_1 = Button(D7);
 Button button_2 = Button(D8);
 Button button_3 = Button(D9);
@@ -47,7 +42,7 @@ Button button_4 = Button(D10);
 Button button_5 = Button(D13);
 Button button_6 = Button(D14);
 
-// Make Potentiometers
+// Initialize Potentiometers
 Potentiometer pot_1 = Potentiometer(A0);
 Potentiometer pot_2 = Potentiometer(A1);
 Potentiometer pot_3 = Potentiometer(A3);
@@ -56,7 +51,7 @@ Potentiometer pot_5 = Potentiometer(A4);
 Potentiometer pot_6 = Potentiometer(A5);
 Potentiometer pot_7 = Potentiometer(A6);
 
-// LED                  R    G    B
+// RGB LED               R    G    B
 RGBLed rgb_led = RGBLed(A10, A9, A11);
 
 
@@ -73,22 +68,25 @@ Ui ui;
 DaisyHardware hw;
 
 // Variables for the Audio-Callback
-size_t num_channels;
+size_t num_channels
+;
 float blocksize;
 float drywetmix = 0.0f;
 float delaymix = 0.0f;
 float delaytime = 100.0f;
 float reverbmix = 0.0f;
 float lfo_amount = 0.0f;
-auto pitch_val = 0.5f;
+float pitch_val = 0.5f;
 
 // Actual audio-processing is orchestrated here
 void AudioCallback(float **in, float **out, size_t size) {
   float output = 0.0f;
   float no_delay = 0.0f;
   float wet_delay;
-  delayline.SetDelay(delaytime);
   float out1, out2;
+  // set the delay
+  delayline.SetDelay(delaytime);
+  
   for (size_t i = 0; i < size; i++) {
     uint8_t trig = tick.Process();
     float lfo_value = lfo.Process();
@@ -111,9 +109,10 @@ void AudioCallback(float **in, float **out, size_t size) {
     
     // res.SetDamping(0.1+delaymix*0.2f);
     auto looper_out = looper.Process(in[1][i]);
-    // FIXME:
+
+    // 
     input_envelope_follower.Process(in[1][i]);
-    output = drywetmix * pitch_shifter.Process(looper_out) + in[1][i] * (1.0f - drywetmix);
+    output = drywetmix * looper_out + in[1][i] * (1.0f - drywetmix);
     // output = output * (1.0f - resmix) + res.Process(output*resmix);
     no_delay = output;
     wet_delay = delayline.Read();
@@ -132,13 +131,7 @@ void AudioCallback(float **in, float **out, size_t size) {
 }
 
 
-// void activate_rec() {
-//   ui.activateRecording();
-// }
 
-// void activate_overdub() {
-//   ui.activateOverdub();
-// }
 
 void setup() {
   float sample_rate;
@@ -149,36 +142,38 @@ void setup() {
   sample_rate = DAISY.get_samplerate();
   blocksize = 64.0f;
 
+  // Create a Tick and a noise source for the Sample and Hold
   tick.Init(10, sample_rate);
+  noise.Init();
   
+  // Initialize Looper with the buffer
   looper.Init(buffer, buffer_length);
+
+  // Initialize Envelope Follower for the Level LED
   input_envelope_follower.Init(sample_rate);
   input_envelope_follower.SetAttack(100.0);
   input_envelope_follower.SetDecay(1000.0);
 
+  // Initialize Reverb
   reverb.Init(sample_rate);
   reverb.SetFeedback(0.95f);
   reverb.SetLpFreq(18000.0f);
 
+  // Initialize Compressor
   compressor.SetThreshold(-64.0f);
   compressor.SetRatio(2.0f);
   compressor.SetAttack(0.005f);
   compressor.SetRelease(0.1250);
 
-  pitch_shifter.Init(sample_rate);
-
-  // set parameters for LFO oscillator object
+  // Initialize the LFO for modulations
   lfo.Init(sample_rate);
   lfo.SetWaveform(Oscillator::WAVE_TRI);
   lfo.SetAmp(1);
   lfo.SetFreq(8.0);
 
-  noise.Init();
-
+  // Initialize the Delay at a length of 1 second
   delayline.Init();
-  delayline.SetDelay(48000.0f);
-  // res.Init(.015, 24, sample_rate);
-  // res.SetStructure(-7.f);
+  delayline.SetDelay(samplerate);
 
   load.Init(sample_rate, blocksize);
 
@@ -189,10 +184,8 @@ void setup() {
   display.begin(0x3C, true);
   delay(50);
   ui.Render();
-
-  DAISY.begin(AudioCallback);
   
-
+  // Initialize the LED
   rgb_led.init();
 
   // Set the analog read and write resolution to 12 bits
@@ -210,21 +203,20 @@ void setup() {
   // Set Knob Scaling Modes
   pot_3.setBipolar();
 
-  // Initialize Buttons
+  // Initialize Buttons (callbacks are assigned in the Ui class)
   button_1.init();
   button_2.init();
   button_3.init();
   button_4.init();
   button_5.init();
   button_6.init();
-  // button_1.onPressed(activate_rec);
-  // button_2.onPress(toggleRecMode);
-  // button_3.onPressed(activate_overdub);
-  // button_4.onPressed(display_fx_menu);
+
+  // Start the audio Callback
+  DAISY.begin(AudioCallback);
 }
 
 void loop() {
-  // hw.ProcessAllControls();
+  // Read the values from the potentiometers
   float p1 = pot_1.read();
   float p2 = pot_2.read();
   float p3 = pot_3.read();
@@ -233,10 +225,10 @@ void loop() {
   float p6 = pot_6.read();
   float p7 = pot_7.read();
 
-  // Deactivate recording and overdub before reading buttons
+  // Update the UI
   ui.update();
 
-  // Read buttons
+  // Read the buttons
   button_1.read();
   button_2.read();
   button_3.read();
@@ -244,21 +236,26 @@ void loop() {
   button_5.read();
   button_6.read();
 
-  // Set loop start and loop length
+  // Set loop-start and loop-length with the potentiometers
   ui.setLoop(p1, p2);
   
-  // Value should go 10 octaves up/down (10*1.0 = 1000%)
+  // Tune the pitch to the ten-fold of the potentiometer 3,
+  // a bipolar pot, so it returns values from -1.0 to +1.0
+  // Pitch should go 10 octaves up/down (10*1.0 = 1000%)
   pitch_val = 10.0f * p3;
-  // res.SetFreq(10.0f + p3 * 1500.0f);
 
-  // Set other parameters
+  // Set other parameters (from 0.0 to 1.0)
   drywetmix = p4;
   delaymix = p5;
+  // Delaytime is in samples
   delaytime = 100.0f + p5 * 23900.0f;
   reverbmix = p6;
   lfo_amount = p7;
 
+  // Render the UI (frame rate limited by UI_MAX_FPS in ui.h)
   ui.Render();
+
+  // Set the Color and brightness of the RGB LED in 8 bits
   rgb_led.setAudioLevelIndicator(int(input_envelope_follower.getValue() * 255));
 }
 
diff --git a/code/daisy-looper/looper.h b/code/daisy-looper/looper.h
index 9624a92b60ca87b97b56e674345b1dc54cc5e731..a71079bceea8005804484778fa0147b08af46669 100644
--- a/code/daisy-looper/looper.h
+++ b/code/daisy-looper/looper.h
@@ -20,10 +20,10 @@ enum RecStartMode {
 class Looper {
   public:
     void Init(float *buf, size_t length) {
-      _buffer = buf;
-      _buffer_length = length;
+      buffer = buf;
+      buffer_length = length;
       // Reset buffer contents to zero
-      memset(_buffer, 0, sizeof(float) * _buffer_length);
+      memset(buffer, 0, sizeof(float) * buffer_length);
     }
 
     RecPitchMode rec_pitch_mode = REC_PITCH_MODE_NORMAL;
@@ -33,62 +33,62 @@ class Looper {
       this->is_overdub = is_overdub;
       this->is_recording = is_recording || is_overdub;
       //Initialize recording head position on start
-      if (_rec_env_pos_inc <= 0 && is_recording) {
-        // rec_head = (_loop_start + play_head) % _buffer_length;
+      if (rec_env_pos_inc <= 0 && is_recording) {
+        // rec_head = (loop_start + play_head) % buffer_length;
         switch (rec_start_mode) {
           case REC_START_MODE_LOOP:
-            rec_head = (_loop_start) % _buffer_length;
+            rec_head = (loop_start) % buffer_length;
             break;
           case REC_START_MODE_BUFFER:
             rec_head = 0.0f;
             break;
           case REC_START_MODE_PLAYHEAD:
-            rec_head = fmod(_loop_start + play_head, float(_buffer_length));
+            rec_head = fmod(loop_start + play_head, float(buffer_length));
             break;
         }
           
-        _is_empty = false;
+        is_empty = false;
       }
       // When record switch changes state it effectively
       // sets ramp to rising/falling, providing a
       // fade in/out in the beginning and at the end of 
       // the recorded region.
-      _rec_env_pos_inc = is_recording ? 1 : -1;
+      rec_env_pos_inc = is_recording ? 1 : -1;
     }
 
     void SetLoop(const float loop_start, const float loop_length) {
       // Set the start of the next loop
-      _pending_loop_start = static_cast<size_t>(loop_start * (_buffer_length - 1));
+      pending_loop_start = static_cast<size_t>(loop_start * (buffer_length - 1));
 
       // If the current loop start is not set yet, set it too
-      if (!_is_loop_set) _loop_start = _pending_loop_start;
+      if (!is_loop_set) loop_start = pending_loop_start;
 
       // Set the length of the next loop
-      _pending_loop_length = max(kMinLoopLength, static_cast<size_t>(loop_length * _buffer_length));
+      pendingloop_length = max(kMinLoopLength, static_cast<size_t>(loop_length * buffer_length));
 
       // CHECK if this is truly good
-      // _loop_length = _pending_loop_length;
-      // _loop_length = _pending_loop_length;
+      // loop_length = pendingloop_length;
+      // loop_length = pendingloop_length;
 
       //If the current loop length is not set yet, set it too
-      if (!_is_loop_set) _loop_length = _pending_loop_length;
-      _is_loop_set = true;
+      if (!is_loop_set) loop_length = pendingloop_length;
+      is_loop_set = true;
     }
   
     float Process(float in) {
       // Calculate iterator position on the record level ramp.
-      if (_rec_env_pos_inc > 0 && _rec_env_pos < kFadeLength
-       || _rec_env_pos_inc < 0 && _rec_env_pos > 0) {
-          _rec_env_pos += _rec_env_pos_inc;
+      if (rec_env_pos_inc > 0 && rec_env_pos < kFadeLength
+       || rec_env_pos_inc < 0 && rec_env_pos > 0) {
+          rec_env_pos += rec_env_pos_inc;
       }
       // If we're in the middle of the ramp - record to the buffer.
-      if (_rec_env_pos > 0) {
+      if (rec_env_pos > 0) {
         // Calculate fade in/out
-        float rec_attenuation = static_cast<float>(_rec_env_pos) / static_cast<float>(kFadeLength);
+        float rec_attenuation = static_cast<float>(rec_env_pos) / static_cast<float>(kFadeLength);
         if (this->is_overdub) {
-          _buffer[int(rec_head)] += in * rec_attenuation;
+          buffer[int(rec_head)] += in * rec_attenuation;
         } else {
-          _buffer[int(rec_head)] = in * rec_attenuation + _buffer[int(rec_head)] * (1.f - rec_attenuation);
+          buffer[int(rec_head)] = in * rec_attenuation + buffer[int(rec_head)] * (1.f - rec_attenuation);
         }
 
         // Set recording pitch mode
@@ -110,29 +110,29 @@ class Looper {
         if (!stop_after_recording) {
           if (!stay_within_loop) {
             // record into whole buffer
-            rec_head = fmod(rec_head, float(_buffer_length));
+            rec_head = fmod(rec_head, float(buffer_length));
           } else {
             // Limit rec head to stay inside the loop
-            rec_head = fmod(rec_head, float(_loop_start + _loop_length));
-            rec_head = max(float(_loop_start), rec_head);
+            rec_head = fmod(rec_head, float(loop_start + loop_length));
+            rec_head = max(float(loop_start), rec_head);
           }
         } else {
           if (!stay_within_loop) {
-            if (rec_head > _buffer_length) { SetRecording(false, false); }
+            if (rec_head > buffer_length) { SetRecording(false, false); }
           } else {
-            if (rec_head > _loop_start + _loop_length) { SetRecording(false, false); }
+            if (rec_head > loop_start + loop_length) { SetRecording(false, false); }
           }
         }
 
-        if (rec_head > _buffer_length) {
+        if (rec_head > buffer_length) {
           rec_head = 0.0f;
         } else if (rec_head < 0) {
-          rec_head = _buffer_length;
+          rec_head = buffer_length;
         }
         
       }
       
-      if (_is_empty) {
+      if (is_empty) {
         return 0;
       }
 
@@ -144,25 +144,25 @@ class Looper {
       if (play_head < kFadeLength) {
         attenuation = static_cast<float>(play_head) / static_cast<float>(kFadeLength);
       }
-      else if (play_head >= _loop_length - kFadeLength) {
-        attenuation = static_cast<float>(_loop_length - play_head) / static_cast<float>(kFadeLength);
+      else if (play_head >= loop_length - kFadeLength) {
+        attenuation = static_cast<float>(loop_length - play_head) / static_cast<float>(kFadeLength);
       }
       
       // Read from the buffer
-      auto play_pos = int(_loop_start + play_head) % _buffer_length;
-      output = _buffer[play_pos] * attenuation;
+      auto play_pos = int(loop_start + play_head) % buffer_length;
+      output = buffer[play_pos] * attenuation;
 
       // Advance playhead
       play_head += playback_increment;
       // Ensure the playhead stays within bounds
-      if (play_head >= _loop_length) {
-        _loop_start = _pending_loop_start;
-        _loop_length = _pending_loop_length;
+      if (play_head >= loop_length) {
+        loop_start = pending_loop_start;
+        loop_length = pendingloop_length;
         play_head = 0;
       } else if (play_head <= 0) {
-        _loop_start = _pending_loop_start;
-        _loop_length = _pending_loop_length;
-        play_head = _loop_length;
+        loop_start = pending_loop_start;
+        loop_length = pendingloop_length;
+        play_head = loop_length;
       }
       
       
@@ -170,11 +170,11 @@ class Looper {
     }
 
     float GetPlayhead() {
-      return  float(play_head) / float(_buffer_length);
+      return  float(play_head) / float(buffer_length);
     }
 
     float GetRecHead() {
-      return  float(rec_head) / float(_buffer_length);
+      return  float(rec_head) / float(buffer_length);
     }
 
     bool toggleRecMode() {
@@ -216,11 +216,11 @@ class Looper {
     }
 
     float* getBuffer() {
-      return _buffer;
+      return buffer;
     }
 
     size_t getBufferLength() {
-      return _buffer_length;
+      return buffer_length;
     }
 
     bool isRecording() {
@@ -248,26 +248,26 @@ class Looper {
     }
 
   private:
-    static const size_t kFadeLength = 200; //orig: 600
+    static const size_t kFadeLength = 200;
     static const size_t kMinLoopLength = 2 * kFadeLength;
 
-    float* _buffer;
+    float* buffer;
 
-    size_t _buffer_length       = 0;
-    size_t _loop_length         = 0;
-    size_t _pending_loop_length = 0;
-    size_t _loop_start          = 0;
-    size_t _pending_loop_start  = 0;
+    size_t buffer_length       = 0;
+    size_t loop_length         = 0;
+    size_t pendingloop_length = 0;
+    size_t loop_start          = 0;
+    size_t pending_loop_start  = 0;
 
     float play_head = 0.0f;
     float rec_head  = 0.0f;
 
     float playback_increment = 1.0f;
 
-    size_t _rec_env_pos      = 0;
-    int32_t _rec_env_pos_inc = 0;
-    bool _is_empty  = true;
-    bool _is_loop_set = false;
+    size_t rec_env_pos      = 0;
+    int32_t rec_env_pos_inc = 0;
+    bool is_empty  = true;
+    bool is_loop_set = false;
     bool stay_within_loop = false;
     bool is_overdub = false;
     bool is_recording = false;
diff --git a/code/daisy-looper/ui.h b/code/daisy-looper/ui.h
index 2d27771b6adb5bccd3782dde6b8fde5534100dbc..06134d752f06a3535bbe28bbded255accc2f96fc 100644
--- a/code/daisy-looper/ui.h
+++ b/code/daisy-looper/ui.h
@@ -18,52 +18,62 @@ extern Button button_1, button_2, button_3, button_4, button_5, button_6;
 extern Adafruit_SH1106G display;
 extern atoav::Looper looper;
 
+// Should the splash-screen be shown on boot?
+bool show_splash = true;
 
-
+// Represents the possible states of the UI
 enum UiMode {
-  UI_MODE_SPLASH,
-  UI_MODE_DEFAULT,
-  UI_MODE_REC_MENU,
-  UI_MODE_PLAY_MENU,
-  UI_MODE_TRIGGER_MENU,
-  UI_MODE_FX_MENU,
+  UI_MODE_SPLASH,         // A splash screen that is shown on startup
+  UI_MODE_DEFAULT,        // Default screen: Show Waveform and Parameters
+  UI_MODE_REC_MENU,       // ButtonGrid Menu: Recording Settings
+  UI_MODE_PLAY_MENU,      // ButtonGrid Menu: Playback Settings
+  UI_MODE_TRIGGER_MENU,   // ButtonGrid Menu: Trigger Settings
+  UI_MODE_FX_MENU,        // ButtonGrid Menu: FX Settings
   UI_MODE_LAST
 };
 
+// Represents possible recording modes
 enum RecMode {
-  REC_MODE_FULL,
-  REC_MODE_LOOP,
-  REC_MODE_FULL_SHOT,
-  REC_MODE_LAST = 6
+  REC_MODE_FULL,          // Record into full buffer (looping back to start)
+  REC_MODE_LOOP,          // Limit recording to the loop
+  REC_MODE_FULL_SHOT,     // Record into full buffer, stop at the end
+  REC_MODE_LAST
 };
 
+// Represents possible playback modes
 enum PlayMode {
-  PLAY_MODE_DRUNK,
-  PLAY_MODE_WINDOW,
-  PLAY_MODE_LOOP,
-  PLAY_MODE_GRAIN,
-  PLAY_MODE_ONESHOT,
+  PLAY_MODE_DRUNK,        // Drunken Walk
+  PLAY_MODE_WINDOW,       // Sliding window
+  PLAY_MODE_LOOP,         // Loop
+  PLAY_MODE_GRAIN,        // Granular ?
+  PLAY_MODE_ONESHOT,      // Play it once
   PLAY_MODE_LAST
 };
 
+// Represents possible recording states
 enum RecordingState {
-  REC_STATE_NOT_RECORDING,
-  REC_STATE_RECORDING,
-  REC_STATE_OVERDUBBING,
+  REC_STATE_NOT_RECORDING, // Not recording
+  REC_STATE_RECORDING,     // Recording (replace what is in the buffer)
+  REC_STATE_OVERDUBBING,   // Overdubbing (mix recorded values with the existing samples)
   REC_STATE_LAST
 };
 
-// Different types of buttons
+// Represents the different types of GridButtons in the UI
 enum ButtonType {
   BUTTON_TYPE_SIMPLE,       // Simple Button that can be pressed
-  BUTTON_TYPE_TOGGLE,       // Toggles between two values (name needs to have a break "\n" insided)
-  BUTTON_TYPE_MULTITOGGLE,  // Toggles between two or more values
+  BUTTON_TYPE_TOGGLE,       // Toggles between two values (name needs to have a break "\n")
+  BUTTON_TYPE_MULTITOGGLE,  // Toggles between two or more values (name needs to have a break "\n")
   BUTTON_TYPE_ENUM,         // Toggles between a group of buttons
   BUTTON_TYPE_LAST
 };
 
+// A Gridbutton is a single button within the Ui-Button Grid
+// The name can have multiple lines, delimited by "\n" which
+// will be used to represent different states for buttons of
+// the type BUTTON_TYPE_TOGGLE or BUTTON_TYPE_MULTITOGGLE
+// is_home tells us if this is the home button (and thus should
+// be rendered inverted)
 class GridButton {
-
   public:
     const char* name;
     GridButton(const char* name, Button& button, bool is_home=false, ButtonType type=BUTTON_TYPE_SIMPLE, int default_value=0)
@@ -81,11 +91,12 @@ class GridButton {
       }
     }
     Button button;
+    ButtonType type;
     bool is_home;
     int active;
-    ButtonType type;
     int lines = 0;
     
+    // Go to the next option
     void next() {
       active++;
       if (active > lines) {
@@ -94,6 +105,7 @@ class GridButton {
     }
 };
 
+// The ButtonGrid is a grid of 2×3 = 6 buttons
 class ButtonGrid {
   public:
     ButtonGrid(const GridButton (&grid_buttons)[6]) 
@@ -109,10 +121,13 @@ class ButtonGrid {
       // Draw boxes (2 rows, 3 columns)
       for (int box_y=0; box_y<2; box_y++) {
         for (int box_x=0; box_x<3; box_x++) {
+          // Get the current buttons name
           const char* name = grid_buttons_[i].name;
+
           // Prepare colors
           uint16_t bg_color = SH110X_BLACK;
           uint16_t text_color = SH110X_WHITE;
+
           // Home-Buttons have a inverted color scheme
           if (grid_buttons_[i].is_home) {
             bg_color = SH110X_WHITE;
@@ -140,11 +155,11 @@ class ButtonGrid {
             centeredText(name, xc, yc, text_color);
           }
           
-          // Counter for the number of the button
+          // Increase ounter for the index of the button
           i++;
         }
       }
-      // Draw divider Line
+      // Draw divider lines
       display.drawFastVLine(box_width, 0, height, SH110X_WHITE);
       display.drawFastVLine(box_width*2, 0, height, SH110X_WHITE);
       display.drawFastHLine(0, box_height, width, SH110X_WHITE);
@@ -152,6 +167,8 @@ class ButtonGrid {
 
 };
 
+// The Ui is _the_ coordinating class for the whole interaction.
+// The default mode
 class Ui {
   public:
     Ui() : button_grids {
@@ -188,11 +205,17 @@ class Ui {
         GridButton("FX\nMENU", button_6, true),
       }),
     } {};
-    UiMode ui_mode = UI_MODE_SPLASH;
+
+    // Store the Button Grids declared above (make sure the lenght matches!)
     ButtonGrid button_grids[4];
+
+    // Stores the current Ui Mode
+    UiMode ui_mode = UI_MODE_SPLASH;
+
     // RecMode rec_mode = REC_MODE_FULL;
     RecMode rec_mode = REC_MODE_LOOP;
 
+    // Set the mode of the UI (and thus change the screen)
     void setMode(UiMode mode) {
       if (last_ui_mode == mode) { return; }
       last_ui_mode = ui_mode;
@@ -213,6 +236,9 @@ class Ui {
       }
     }
 
+    // Render the UI
+    // Except for the splash screen this is expected to be called
+    // repeatedly in a loop
     void Render() {
       switch (ui_mode) {
         case UI_MODE_SPLASH:
@@ -238,10 +264,10 @@ class Ui {
       }
     }
 
-    // Render button grids
+    // Helper method to render a certain button grid
     void renderGrid(size_t num, int button_enum=0) {
       double now = millis();
-      if (now - last_render > UI_MAX_FPS) {
+      if (now - last_render > (1000.0/UI_MAX_FPS)) {
         display.clearDisplay();
         button_grids[num].render(button_enum);
         // Display all that stuff and store the time of the last render
@@ -250,49 +276,52 @@ class Ui {
       }
     }
 
-    // Renders a splash screen
+    // Renders a splash screen (runs once)
     void renderSplash() {
       display.setTextSize(1);
-      // 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 < 10) {
-      //     centeredText("I", display.width()/2, display.height()/2-4, SH110X_WHITE);
-      //     centeredText("O", display.width()/2, display.height()/2+4, SH110X_WHITE);
-      //   } else if (i < 20) {
-      //     centeredText("I S", display.width()/2, display.height()/2-4, SH110X_WHITE);
-      //     centeredText("O P", display.width()/2, display.height()/2+4, SH110X_WHITE);
-      //   } else if (i < 40) {
-      //     centeredText("A I S", display.width()/2, display.height()/2-4, SH110X_WHITE);
-      //     centeredText("O O P", display.width()/2, display.height()/2+4, SH110X_WHITE);
-      //   } else if (i < 50) {
-      //     centeredText("A I S Y", display.width()/2, display.height()/2-4, SH110X_WHITE);
-      //     centeredText("O O P E", display.width()/2, display.height()/2+4, SH110X_WHITE);
-      //   } else if (i < 60) {
-      //     centeredText("D A I S Y", display.width()/2, display.height()/2-4, SH110X_WHITE);
-      //     centeredText("L O O P E", display.width()/2, display.height()/2+4, SH110X_WHITE);
-      //   } else {
-      //     centeredText("D A I S Y Y", display.width()/2, display.height()/2-4, SH110X_WHITE);
-      //     centeredText("L O O P E R", 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();
+      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 < 10) {
+            centeredText("I", display.width()/2, display.height()/2-4, SH110X_WHITE);
+            centeredText("O", display.width()/2, display.height()/2+4, SH110X_WHITE);
+          } else if (i < 20) {
+            centeredText("I S", display.width()/2, display.height()/2-4, SH110X_WHITE);
+            centeredText("O P", display.width()/2, display.height()/2+4, SH110X_WHITE);
+          } else if (i < 40) {
+            centeredText("A I S", display.width()/2, display.height()/2-4, SH110X_WHITE);
+            centeredText("O O P", display.width()/2, display.height()/2+4, SH110X_WHITE);
+          } else if (i < 50) {
+            centeredText("A I S Y", display.width()/2, display.height()/2-4, SH110X_WHITE);
+            centeredText("O O P E", display.width()/2, display.height()/2+4, SH110X_WHITE);
+          } else if (i < 60) {
+            centeredText("D A I S Y", display.width()/2, display.height()/2-4, SH110X_WHITE);
+            centeredText("L O O P E", display.width()/2, display.height()/2+4, SH110X_WHITE);
+          } else {
+            centeredText("D A I S Y Y", display.width()/2, display.height()/2-4, SH110X_WHITE);
+            centeredText("L O O P E R", 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);
     }
 
+    // Helper method to reset the controls
     void resetControls() {
       button_1.reset();
       button_2.reset();
@@ -302,18 +331,21 @@ class Ui {
       button_6.reset();
     }
 
+    // Setup the Recording Menu
     void setupRecMenu() {
-      // Only run once
+      // Only run once when the ui_mode changed
       if (ui_mode == UI_MODE_REC_MENU && last_ui_mode != UI_MODE_REC_MENU) {
         Serial.println("[UI] Setup Rec Menu");
+
+        // Reset controls
         resetControls();
+
         // Stay in this menu as long as the button is pressed, otherwise return
         button_1.onPressed([this](){ this->setMode(UI_MODE_REC_MENU); });
         button_1.onReleased([this](){ this->setMode(UI_MODE_DEFAULT); });
 
         // Toggle between momentary and toggle recording modes
-        button_2.onPress([this](){ 
-          
+        button_2.onPress([this](){       
           Serial.print("[UI] Mom/Toggle option ");
           if (rec_button_momentary) {
             Serial.println("momentary -> toggle");
@@ -330,10 +362,10 @@ class Ui {
           button_grids[0].grid_buttons_[2].next();
         }); // FULL ONESHOT
 
-        // Switch Recording modes
+        // Switch Recording modes (Full/Loop/Oneshot)
         button_4.onPress([this](){ 
           button_grids[0].grid_buttons_[3].next();
-          // Button.active returns number according to mode:
+          // Button.active returns number according to mode, we cast it to a RecMode enum
           rec_mode = (RecMode) button_grids[0].grid_buttons_[3].active;
           switch (rec_mode) {
             case REC_MODE_FULL: looper.setRecModeFull(); break;
@@ -353,26 +385,36 @@ class Ui {
           button_grids[0].grid_buttons_[5].next();
           looper.setRecStartMode((atoav::RecStartMode) button_grids[0].grid_buttons_[5].active);
         });
+
+        // Store the last ui mode, for the check on top
         last_ui_mode = ui_mode;
       }
     }
 
+    // Setup the default (waveform) screen
     void setupDefault() {
-      // Only run once
+      // Only run once on mode change
       if (ui_mode == UI_MODE_DEFAULT && last_ui_mode != UI_MODE_DEFAULT) {
         Serial.println("[UI] Setup Default mode");
+
+        // Reset controls
         resetControls();
+
         // Set up the initial recording mode
         switch (rec_mode) {
           case REC_MODE_FULL: looper.setRecModeFull(); break;
           case REC_MODE_LOOP: looper.setRecModeLoop(); break;;
           case REC_MODE_FULL_SHOT: looper.setRecModeFullShot(); break;
         };
-        // Setup Button functions
+
+        // Setup Button functions (these should enter the ButtonGrid Menus)
         button_1.onPressed([this](){ this->setMode(UI_MODE_REC_MENU); });
         button_2.onPressed([this](){ this->setMode(UI_MODE_PLAY_MENU); });
         button_3.onPressed([this](){ this->setMode(UI_MODE_TRIGGER_MENU); });
-        // Momentary/Toggle Recording modes
+        button_6.onPressed([this](){ this->setMode(UI_MODE_FX_MENU); });
+
+        // Set the recording/overdub buttons to toggle or momentary
+        // depending on the value of the option
         if (rec_button_momentary) {
           Serial.println("[UI] Set to momentary mode");
           button_4.onPressed([this](){ this->activateRecording(); });
@@ -384,55 +426,77 @@ class Ui {
           button_4.onReleased([this](){ this->toggleRecording(); });
           button_5.onReleased([this](){ this->toggleOverdub(); });
         }
-        button_6.onPressed([this](){ this->setMode(UI_MODE_FX_MENU); });
+        
+        // Store the last ui mode, for the check on top
         last_ui_mode = ui_mode;
       }
     }
 
+    // Render the default screen (waveform)
     void renderDefault() {
+      // Store the current time and check how long ago the last frame was
+      // in ms
       double now = millis();
-      if (now - last_render > UI_MAX_FPS) {
+      if (now - last_render > (1000.0/UI_MAX_FPS)) {
+
+        // Clear the display
         display.clearDisplay();
-        // Render the waveform
+
+        // Waveform should be maximum screen-heigh
         int wave_height = display.height() * 1.0f;
+        // Ensure that when stepping from left to right we fit the waveform on the screen
         int step = looper.getBufferLength() / (display.width() * WAVEFORM_OVERSAMPLING);
+        // Helper variable for the bottom of the screen
         int bottom = display.height()-1;
-        // Render the waveform
+
+        // Render the waveform by iterating through the samples (oversampled by a factor
+        // defined on top of this file). Average the samples for each pixel of the 128 px
+        // wide screen and cache the resulting heights so we only have to recalculate when
+        // the waveform changes
         for (int i=0; i<display.width()*WAVEFORM_OVERSAMPLING; i+=WAVEFORM_OVERSAMPLING) {
           uint16_t x = int(i / WAVEFORM_OVERSAMPLING);
-          // Only recalculate if needed, else use cache
+          // Only recalculate if the cahce is dirty, else use cache
           if (waveform_cache_dirty) {
             float sig = 0.0f;
+            // Step through the buffer and sum the absolute values
             for (int s=0; s<WAVEFORM_OVERSAMPLING; s++) {
               float abs_sig = looper.getBuffer()[step*i];
               abs_sig = abs(abs_sig) * 100.0f;
               sig += abs_sig;
             }
+            // We oversampled so divide here
             sig = sig / float(WAVEFORM_OVERSAMPLING);
+
+            // Volume is logarithmic, we want to see silent noises as well
             if (sig != 0.0f) {
               sig = log10(sig)/3.6f;
             }
             waveform_cache[x] = int(sig * wave_height);
           }
-          // Serial.print(waveform_cache[x]);
-          // Serial.print(",");
+
+          // Draw the vertical lines from bottom up, depending on the level of the
+          // calulcated wave on this point of the screen
           display.drawFastVLine(x, bottom, -waveform_cache[x], SH110X_WHITE);
-          display.drawFastHLine(0, bottom, display.width(), SH110X_WHITE);
+          
         }
+        // Draw one horizontal line on bottom
+        display.drawFastHLine(0, bottom, display.width(), SH110X_WHITE);
+
+        // Cache is now marked as clean
         waveform_cache_dirty = false;
 
-        // Draw Line for loop start 
+        // Draw Indicator for loop start 
         int x_start_loop = int(loop_start * display.width());
         display.drawLine(x_start_loop, 0, x_start_loop, bottom, SH110X_WHITE);
         display.fillTriangle(x_start_loop, 6, x_start_loop, 0, x_start_loop+3, 0, SH110X_WHITE);
 
-        // Draw Line for Loop End
+        // Draw Indicator for Loop End
         int x_loop_length = int(loop_length * display.width());
         int x_loop_end = (x_start_loop + x_loop_length) % display.width();
         display.drawLine(x_loop_end, 0, x_loop_end, bottom, SH110X_WHITE);
         display.fillTriangle(x_loop_end, 6, x_loop_end-3, 0, x_loop_end, 0, SH110X_WHITE);
 
-        // Connecting line for start and end
+        // Draw connecting line for start and end
         if (x_loop_end >= x_start_loop) {
           display.drawLine(x_start_loop, 0, x_loop_end, 0, SH110X_WHITE);
         } else {
@@ -444,7 +508,7 @@ class Ui {
         int x_playhead = int(looper.GetPlayhead() * display.width()) + x_start_loop;
         display.drawLine(x_playhead, 6, x_playhead, 24, SH110X_WHITE);
 
-        // Draw Recording stuff
+        // Draw Recording Indicator and Recording Head
         if (recording_state == REC_STATE_RECORDING) {
           // Draw Rec Head
           int x_rec_head = int(looper.GetRecHead() * display.width());
@@ -457,8 +521,13 @@ class Ui {
           display.fillCircle(6, 6, 3, SH110X_WHITE);
         }
 
-        // Draw Overdub stuff
+        // Draw Overdub Indicator and Recording Head
         if (recording_state == REC_STATE_OVERDUBBING) {
+          // Draw Rec Head
+          int x_rec_head = int(looper.GetRecHead() * display.width());
+          display.drawLine(x_rec_head, 10, x_rec_head, bottom, SH110X_WHITE);
+          display.fillCircle(x_rec_head, 10, 3, SH110X_WHITE);
+
           // Overdub sign (a "plus")
           display.fillRect(0, 0, 13, 13, SH110X_WHITE);
           display.fillRect(2, 2, 12, 12, SH110X_WHITE);
@@ -476,11 +545,15 @@ class Ui {
         pot_6.renderUi();
         pot_7.renderUi();
 
+        // Display all the things done above
         display.display();
+
+        // Store the time of when we started rendering
         last_render = now;
       }
     }
 
+    // Activate recording and set the waveform cache to dirty
     void activateRecording() {
       if (recording_state != REC_STATE_RECORDING) {
         Serial.println("[UI] Activate Recording");
@@ -490,6 +563,7 @@ class Ui {
       }
     }
 
+    // Toggle recording
     void toggleRecording() {
       Serial.print("[UI] Toggle Recording ");
       Serial.print(recording_state);
@@ -508,10 +582,12 @@ class Ui {
       Serial.println(recording_state);
     }
 
+    // Returns true if we are recording
     bool isRecording() {
       return looper.isRecording();
     }
 
+    // Activates overdubbing
     void activateOverdub() {
       if (recording_state != REC_STATE_OVERDUBBING) {
         Serial.println("[UI] Activate Overdub");
@@ -521,6 +597,7 @@ class Ui {
       }
     }
 
+    // Stop the recording
     void stopRecording() {
       if (recording_state != REC_STATE_NOT_RECORDING) {
         Serial.println("[UI] Stop Recording");
@@ -529,6 +606,7 @@ class Ui {
       }
     }
 
+    // Toggle overdub off and on
     void toggleOverdub() {
       Serial.print("[UI] Toggle Overdub ");
       Serial.print(recording_state);
@@ -547,21 +625,24 @@ class Ui {
       Serial.println(recording_state);
     }
 
-
+    // Return true if overdub is running
     bool isOverdubbing() {
       return looper.isOverdubbing();
     }
 
+    // Reset the recording state (mark waveform cahce dirty)
     void resetRecordingState() {
       if (recording_state == REC_STATE_RECORDING || recording_state == REC_STATE_OVERDUBBING) {
         waveform_cache_dirty = true; 
       }
     }
 
+    // Update the Ui variables (expected to run repeatedly)
     void update() {
       resetRecordingState();
     }
 
+    // Set the Looper start/length to a given value
     void setLoop(float start, float length) {
       loop_start = start;
       loop_length = length;
diff --git a/menu.ods b/menu.ods
new file mode 100644
index 0000000000000000000000000000000000000000..1b5d3f6346eea013ef11936ddfbd7c26749045e6
Binary files /dev/null and b/menu.ods differ