diff --git a/SSD1306Ui.cpp b/SSD1306Ui.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bcdb751355cef4eb88932f8f8538bb0695ae5b0f
--- /dev/null
+++ b/SSD1306Ui.cpp
@@ -0,0 +1,249 @@
+#include "SSD1306Ui.h"
+
+
+SSD1306Ui::SSD1306Ui(SSD1306 *display) {
+  this->display = display;
+}
+
+void SSD1306Ui::init() {
+  this->display->init();
+}
+
+void SSD1306Ui::setTargetFPS(byte fps){
+  this->updateInterval = ((float) 1.0 / (float) fps) * 1000;
+  Serial.println(this->updateInterval);
+}
+
+// -/------ Automatic controll ------\-
+
+void SSD1306Ui::enableAutoTransition(){
+  autoTransition = true;
+}
+void SSD1306Ui::disableAutoTransition(){
+  autoTransition = false;
+}
+void SSD1306Ui::setAutoTransitionForwards(){
+  this->frameTransitionDirection = 1;
+}
+void SSD1306Ui::setAutoTransitionBackwards(){
+  this->frameTransitionDirection = 1;
+}
+void SSD1306Ui::setTimePerFrame(int time){
+  this->ticksPerFrame = (int) ( (float) time / (float) updateInterval);
+}
+void SSD1306Ui::setTimePerTransition(int time){
+  this->ticksPerTransition = (int) ( (float) time / (float) updateInterval);
+}
+
+
+// -/------ Customize indicator position and style -------\-
+void SSD1306Ui::setIndicatorPosition(IndicatorPosition pos) {
+  this->indicatorPosition = pos;
+  this->dirty = true;
+}
+void SSD1306Ui::setIndicatorDirection(IndicatorDirection dir) {
+  this->indicatorDirection = dir;
+}
+void SSD1306Ui::setActiveSymbole(const char* symbole) {
+  this->activeSymbole = symbole;
+  this->dirty = true;
+}
+void SSD1306Ui::setInactiveSymbole(const char* symbole) {
+  this->inactiveSymbole = symbole; 
+  this->dirty = true;
+}
+
+
+// -/----- Frame settings -----\-
+void SSD1306Ui::setFrameAnimation(AnimationDirection dir) {  
+  this->frameAnimationDirection = dir;
+}
+void SSD1306Ui::setFrames(bool (*frameFunctions[])(SSD1306 *display, int x, int y), int frameCount) {
+  this->frameCount     = frameCount;
+  this->frameFunctions = frameFunctions;
+}
+
+// -/----- Overlays ------\-
+void SSD1306Ui::setOverlays(bool (*overlayFunctions[])(SSD1306 *display), int overlayCount){
+  this->overlayCount     = overlayCount;
+  this->overlayFunctions = overlayFunctions;
+}
+
+
+// -/----- Manuel control -----\-
+void SSD1306Ui::nextFrame() {
+  this->frameState = IN_TRANSITION;
+  this->ticksSinceLastStateSwitch = 0;
+  this->frameTransitionDirection = 1;
+}
+void SSD1306Ui::previousFrame() {
+  this->frameState = IN_TRANSITION;
+  this->ticksSinceLastStateSwitch = 0;
+  this->frameTransitionDirection = -1;
+}
+
+
+// -/----- State information -----\-
+FrameState SSD1306Ui::getFrameState(){
+  return this->frameState;
+}
+int SSD1306Ui::getCurrentFrame(){
+  return this->currentFrame;
+}
+
+
+int SSD1306Ui::update(){
+  int timeBudget = this->updateInterval - (millis() - this->lastUpdate);
+  if ( timeBudget <= 0) {
+
+    // Implement frame skipping to ensure time budget is keept
+    if (this->autoTransition && this->lastUpdate != 0) this->ticksSinceLastStateSwitch += abs(timeBudget) / this->updateInterval;
+    
+    this->lastUpdate = millis();
+    this->tick();
+  } 
+  return timeBudget;
+}
+
+
+void SSD1306Ui::tick() {
+  this->ticksSinceLastStateSwitch++;
+
+  switch (this->frameState) {
+    case IN_TRANSITION:
+        this->dirty = true;
+        if (this->ticksSinceLastStateSwitch >= this->ticksPerTransition){
+          this->frameState = FIXED;
+          this->currentFrame = getNextFrameNumber();
+          this->ticksSinceLastStateSwitch = 0;
+        }
+      break;
+    case FIXED:
+      if (this->ticksSinceLastStateSwitch >= this->ticksPerFrame){
+          if (this->autoTransition){
+            this->frameState = IN_TRANSITION;
+            this->dirty = true;
+          }
+          this->ticksSinceLastStateSwitch = 0;
+      }
+      break;
+  }
+  
+  if (this->dirty) {
+    this->dirty = false;
+    this->display->clear();
+    this->drawIndicator();  
+    this->drawFrame();
+    this->drawOverlays();
+    this->display->display();
+  }
+}
+
+void SSD1306Ui::drawFrame(){
+  switch (this->frameState){
+     case IN_TRANSITION: {
+       float progress = (float) this->ticksSinceLastStateSwitch / (float) this->ticksPerTransition;
+       int x, y, x1, y1;
+       switch(this->frameAnimationDirection){
+        case SLIDE_LEFT:
+          x = -128 * progress;
+          y = 0;
+          x1 = x + 128;
+          y1 = 0;
+          break;
+        case SLIDE_RIGHT:
+          x = 128 * progress;
+          y = 0;
+          x1 = x - 128;
+          y1 = 0;
+          break;
+        case SLIDE_UP:
+          x = 0;
+          y = -64 * progress;
+          x1 = 0;
+          y1 = y + 64;
+          break;
+        case SLIDE_DOWN:
+          x = 0;
+          y = 64 * progress;
+          x1 = 0;
+          y1 = y - 64;
+          break;
+       }
+
+       // Invert animation if direction is reversed.
+       int dir = frameTransitionDirection >= 0 ? 1 : -1;
+       x *= dir; y *= dir; x1 *= dir; y1 *= dir;
+
+       this->dirty |= (*this->frameFunctions[this->currentFrame])(this->display, x, y);
+       this->dirty |= (*this->frameFunctions[this->getNextFrameNumber()])(this->display, x1, y1);
+       break;
+     }
+     case FIXED:
+      this->dirty |= (*this->frameFunctions[this->currentFrame])(this->display, 0, 0);
+      break;
+  }
+}
+
+void SSD1306Ui::drawIndicator() {
+    byte posOfCurrentFrame; 
+    
+    switch (this->indicatorDirection){
+      case LEFT_RIGHT:
+        posOfCurrentFrame = this->currentFrame;
+        break;
+      case RIGHT_LEFT:
+        posOfCurrentFrame = (this->frameCount - 1) - this->currentFrame;
+        break;
+    }
+    
+    for (byte i = 0; i < this->frameCount; i++) {
+      
+      const char *xbm;
+      
+      if (posOfCurrentFrame == i) {
+         xbm = this->activeSymbole;
+      } else {
+         xbm = this->inactiveSymbole;  
+      }
+
+      int x,y;
+      switch (this->indicatorPosition){
+        case TOP:
+          y = 0;
+          x = 64 - (12 * frameCount / 2) + 12 * i;
+          break;
+        case BOTTOM:
+          y = 56;
+          x = 64 - (12 * frameCount / 2) + 12 * i;
+          break;
+        case RIGHT:
+          x = 120;
+          y = 32 - (12 * frameCount / 2) + 12 * i;
+          break;
+        case LEFT:
+          x = 0;
+          y = 32 - (12 * frameCount / 2) + 12 * i;
+          break;
+      }
+      
+      this->display->drawXbm(x, y, 8, 8, xbm);
+    }  
+}
+
+void SSD1306Ui::drawOverlays() {
+ for (int i=0;i<this->overlayCount;i++){
+    this->dirty |= (*this->overlayFunctions[i])(this->display);
+ }
+}
+
+int SSD1306Ui::getNextFrameNumber(){
+  int nextFrame = (this->currentFrame + this->frameTransitionDirection) % this->frameCount;
+  if (nextFrame < 0){
+    nextFrame = this->frameCount + nextFrame;
+  }
+  return nextFrame;  
+}
+
+
+
diff --git a/SSD1306Ui.h b/SSD1306Ui.h
new file mode 100644
index 0000000000000000000000000000000000000000..d5d7257002dc9363d4fecf9a4f7c522936ef93f4
--- /dev/null
+++ b/SSD1306Ui.h
@@ -0,0 +1,202 @@
+/**The MIT License (MIT)
+
+Copyright (c) 2015 by Fabrice Weinberg
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Credits for parts of this code go to Daniel Eichhorn
+*/
+
+#pragma once
+
+#include <Arduino.h>
+#include "ssd1306_i2c.h"
+
+enum AnimationDirection {
+  SLIDE_UP,
+  SLIDE_DOWN,
+  SLIDE_LEFT,
+  SLIDE_RIGHT
+};
+
+enum IndicatorPosition {
+  TOP,
+  RIGHT,
+  BOTTOM,
+  LEFT
+};
+
+enum IndicatorDirection {
+  LEFT_RIGHT,
+  RIGHT_LEFT
+};
+
+enum FrameState {
+  IN_TRANSITION,
+  FIXED
+};
+
+const char ANIMATION_activeSymbole[] PROGMEM = {
+  0x00, 0x18, 0x3c, 0x7e, 0x7e, 0x3c, 0x18, 0x00
+};
+
+const char ANIMATION_inactiveSymbole[] PROGMEM = {
+  0x00, 0x0, 0x0, 0x18, 0x18, 0x0, 0x0, 0x00
+};
+
+class SSD1306Ui {
+  private:
+    SSD1306             *display;
+
+    // Global dirty flag to indicate that the display needs to be redraw.
+    bool                dirty                     = true;
+
+    // Symboles for the Indicator
+    IndicatorPosition   indicatorPosition         = BOTTOM;
+    IndicatorDirection  indicatorDirection        = LEFT_RIGHT;
+
+    const char*         activeSymbole             = ANIMATION_activeSymbole;
+    const char*         inactiveSymbole           = ANIMATION_inactiveSymbole;
+
+    // Values for the Frames
+    AnimationDirection  frameAnimationDirection   = SLIDE_RIGHT;
+    FrameState          frameState                = FIXED;
+
+    int                 frameTransitionDirection  = 1;
+
+    int                 ticksPerFrame             = 313; // ~ 5000ms at 60 FPS
+    int                 ticksPerTransition        = 32;  // ~  500ms at 60 FPS
+    int                 ticksSinceLastStateSwitch = 0;
+    int                 currentFrame              = 0;
+
+    bool                autoTransition            = true;
+
+    bool                (**frameFunctions)(SSD1306 *display, int x, int y);
+    int                 frameCount                = 0;
+
+    // Values for Overlays
+    bool                (**overlayFunctions)(SSD1306 *display);
+    int                 overlayCount              = 0;
+
+
+    // Bookeeping for update
+    int                 updateInterval            = 16;
+    unsigned long       lastUpdate                = 0;
+
+
+    int                 getNextFrameNumber();
+    void                drawIndicator();
+    void                drawFrame();
+    void                drawOverlays();
+    void                tick();
+
+  public:
+
+    SSD1306Ui(SSD1306 *display);
+
+    /**
+     * Initialise the display
+     */
+    void init();
+
+    /**
+     * Configure the internal used target FPS
+     */
+    void setTargetFPS(byte fps);
+
+    // Automatic Controll
+    /**
+     * Enable automatic transition to next frame after the some time can be configured with `setTimePerFrame` and `setTimePerTransition`.
+     */
+    void enableAutoTransition();
+
+    /**
+     * Disable automatic transition to next frame.
+     */
+    void disableAutoTransition();
+
+    /**
+     * Set the direction if the automatic transitioning
+     */
+    void setAutoTransitionForwards();
+    void setAutoTransitionBackwards();
+
+    /**
+     *  Set the approx. time a frame is displayed
+     */
+    void setTimePerFrame(int time);
+
+    /**
+     * Set the approx. time a transition will take
+     */
+    void setTimePerTransition(int time);
+
+    // Customize Indicator Position and style
+    /**
+     * Set the position of the indicator bar.
+     */
+    void setIndicatorPosition(IndicatorPosition pos);
+
+    /**
+     * Set the direction of the indicator bar. Defining the order of frames ASCENDING / DESCENDING
+     */
+    void setIndicatorDirection(IndicatorDirection dir);
+
+    /**
+     * Set the symbole to indicate an active frame in the indicator bar.
+     */
+    void setActiveSymbole(const char* symbole);
+
+    /**
+     * Set the symbole to indicate an inactive frame in the indicator bar.
+     */
+    void setInactiveSymbole(const char* symbole);
+
+    // Frame settings
+
+    /**
+     * Configure what animation is used to transition from one frame to another
+     */
+    void setFrameAnimation(AnimationDirection dir);
+
+    /**
+     * Add frame drawing functions
+     */
+    void setFrames(bool (*frameFunctions[])(SSD1306 *display, int x, int y), int frameCount);
+
+    // Overlay
+
+    /**
+     * Add overlays drawing functions that are draw independent of the Frames
+     */
+    void setOverlays(bool (*overlayFunctions[])(SSD1306 *display), int overlayCount);
+
+    // Manuell Controll
+    void  nextFrame();
+    void  previousFrame();
+
+    // State Info
+    FrameState getFrameState();
+    int        getCurrentFrame();
+
+
+    int update();
+};
+
+