diff --git a/Makefile b/Makefile
index df277b5..78b51f2 100644
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,8 @@ CPP_SOURCES = src/main.cpp \
               src/droplets/droplet.cpp \
               src/droplets/noise_droplet.cpp \
               src/droplets/vco_droplet.cpp \
-              src/graphics/sprite.cpp
+              src/graphics/sprite.cpp \
+              src/graphics/wave.cpp
 
 LIBDAISY_DIR = ./lib/libDaisy
 DAISYSP_DIR = ./lib/daisySP
diff --git a/src/droplets/vco_droplet.cpp b/src/droplets/vco_droplet.cpp
index 7b95a5d..fa63d09 100644
--- a/src/droplets/vco_droplet.cpp
+++ b/src/droplets/vco_droplet.cpp
@@ -16,12 +16,6 @@ VCODroplet::VCODroplet(DaisyPatch* m_patch,
 		num_waves, Parameter::LINEAR);
   ampctrl.Init(Patch()->controls[Patch()->CTRL_4], 0.0,
 	       0.5f, Parameter::LINEAR);
-
-  wave->SetBlank();
-  for (int i = 0; i < sine_width; i++) {
-    int pixel = (int) round(std::sin(2*pi*((double)(i%sine_width)/sine_width)) * (GetTitleHeight()/2) + GetTitleHeight()/2);
-    wave->SetPixel(i, pixel, true);
-  }
 }
 
 VCODroplet::~VCODroplet() {
@@ -59,7 +53,7 @@ void VCODroplet::Draw() {
 	      WaveToString(wavectrl.Process()));
   wave->DrawTile(*Patch(), GetScreenMin(), 0, GetScreenMax(), GetTitleHeight());
   if(NeedUpdate()) {
-    wave->AdjustXShift(1);
+    //wave->AdjustXShift(1);
   }
   DrawName("VCO");
   AnimationInc();
diff --git a/src/droplets/vco_droplet.h b/src/droplets/vco_droplet.h
index 1bf0097..41b77fe 100644
--- a/src/droplets/vco_droplet.h
+++ b/src/droplets/vco_droplet.h
@@ -10,7 +10,7 @@
 
 #include "droplet.h"
 #include "../util.h"
-#include "../graphics/sprite.h"
+#include "../graphics/wave.h"
 
 using namespace daisy;
 using namespace daisysp;
@@ -22,7 +22,7 @@ private:
   std::string WaveToString(uint8_t);
   const double pi = std::acos(-1);
   int sine_width = 20;
-  Sprite* wave = new Sprite(sine_width, GetTitleHeight());
+  Wave* wave = new Wave(WaveShape::kTriangle, sine_width, GetTitleHeight());
 public:
   VCODroplet(DaisyPatch*, DropletState, float);
   ~VCODroplet();
diff --git a/src/graphics/sprite.cpp b/src/graphics/sprite.cpp
index b31ffa3..3548a92 100644
--- a/src/graphics/sprite.cpp
+++ b/src/graphics/sprite.cpp
@@ -19,10 +19,37 @@ Sprite::~Sprite() {
   delete[] sprite;
 }
 
-void Sprite::SetPixel(int x, int y, bool solid) {
+void Sprite::AddPixel(int x, int y, bool solid) {
   sprite[x][y] = solid;
 }
 
+void Sprite::AddLine(int x1,
+	     int y1,
+	     int x2,
+	     int y2,
+	     bool solid) {
+  uint8_t deltaX = abs(x2 - x1);
+  uint8_t deltaY = abs(y2 - y1);
+  int8_t  signX = ((x1 < x2) ? 1 : -1);
+  int8_t  signY = ((y1 < y2) ? 1 : -1);
+  int16_t error = deltaX - deltaY;
+  int16_t error2;
+  
+  AddPixel(x2, y2, solid);
+  while((x1 != x2) || (y1 != y2)) {
+    AddPixel(x1, y1, solid);
+    error2 = error * 2;
+    if(error2 > -deltaY) {
+      error -= deltaY;
+      x1 += signX;
+    }
+    if(error2 < deltaX) {
+      error += deltaX;
+      y1 += signY;
+    }
+  }
+}
+
 int Sprite::GetHeight() {
   return height;
 }
diff --git a/src/graphics/sprite.h b/src/graphics/sprite.h
index 38523f3..20a40bf 100644
--- a/src/graphics/sprite.h
+++ b/src/graphics/sprite.h
@@ -19,7 +19,8 @@ class Sprite {
  public:
   Sprite(int, int);
   ~Sprite();
-  void SetPixel(int, int, bool);
+  void AddPixel(int, int, bool);
+  void AddLine(int, int, int, int, bool);
   int GetHeight();
   int GetWidth();
   bool** GetSprite();
diff --git a/src/graphics/wave.cpp b/src/graphics/wave.cpp
new file mode 100644
index 0000000..f2bc3cf
--- /dev/null
+++ b/src/graphics/wave.cpp
@@ -0,0 +1,24 @@
+#include "wave.h"
+
+Wave::Wave(WaveShape m_wave, int width, int height) : Sprite(width, height) {
+  wave = m_wave;
+  DrawShape();
+}
+
+void Wave::DrawShape() {
+  SetBlank();
+  int mid = GetWidth()/2;
+  switch(wave) {
+  case WaveShape::kTriangle:
+    AddLine(0, GetHeight()+1, mid, 0, true);
+    AddLine(mid, 0, GetWidth()+1, GetHeight(), true);
+    return;
+  case WaveShape::kSine:
+  default:
+    for (int i = 0; i < GetWidth(); i++) {
+      int pixel = (int) round(std::sin(2*pi*((double)(i%GetWidth())/GetWidth())) * (GetHeight()/2) + GetHeight()/2);
+      AddPixel(i, pixel, true);
+    }
+    return;
+  }
+}
diff --git a/src/graphics/wave.h b/src/graphics/wave.h
new file mode 100644
index 0000000..f635f0a
--- /dev/null
+++ b/src/graphics/wave.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#ifndef CASCADE_GRAPHICS_WAVE_H_
+#define CASCADE_GRAPHICS_WAVE_H_
+
+#include "sprite.h"
+
+enum class WaveShape {kSine, kTriangle, kSaw, kSquare, kRamp};
+
+class Wave: public Sprite {
+ private:
+  WaveShape wave;
+  const double pi = std::acos(-1);
+  void DrawShape();
+ public:
+  Wave(WaveShape, int, int);
+};
+
+#endif