diff --git a/qthing/oled.cpp b/qthing/oled.cpp
index e7f63428ce5497fa45e977b1916cf1597551ac39..9abe2bb0953f52def9a884c2599189536625cc1f 100644
--- a/qthing/oled.cpp
+++ b/qthing/oled.cpp
@@ -1,30 +1,70 @@
 #include <qthing.h>
 
 #include "oled.h"
-#include "oled_symbols.h"
 #include "event.h"
 
 #include "Arduino.h"
 #include "SSD1306Wire.h"
+#include <time.h>
+
+#include "oled_symbols.h"
+
+//SSD1306Wire display(0x3c, GPIO_NUM_5, GPIO_NUM_4);
+SSD1306Wire display = SSD1306Wire(0x3c, GPIO_NUM_4, GPIO_NUM_15);
+
+#define OLED_LOG_MAX_LENGTH 5
+std::string oled_log_messages[OLED_LOG_MAX_LENGTH];
+uint8_t oled_log_first_message = 0;
+uint8_t oled_log_message_count = 0;
 
-SSD1306Wire display(0x3c, GPIO_NUM_5, GPIO_NUM_4);
+volatile long redraw_time = 1;
 
-std::string oled_log = "";
+#define FRAME_TIME_MS 100
 
-void draw_network_status(uint8_t x, uint8_t y) {
+#define RESET_AFTER_MS 10000
+long last_reset = 0;
+
+void redraw() {
+    redraw_time = millis();
+}
+
+void redraw_at_time(long time_in_ms) {
+    if (redraw_time == 0 || time_in_ms < redraw_time) {
+        redraw_time = time_in_ms;
+    }
+}
+
+void redraw_after_timespan(long timespan_in_ms) {
+    redraw_at_time(millis() + timespan_in_ms);
+}
+
+void draw_network_status(uint16_t& x, uint16_t y) {
+    x -= 10;
     connection_status_t wlan_status = get_wlan_connection_status();
     if (wlan_status == connected) {
         display.drawFastImage(x, y, 10, 8, wlan_connected_symbol);
     }
     else if (wlan_status == connecting) {
-        display.drawFastImage(x, y, 10, 8, wlan_connecting_symbol);
+        #define ICON_UPDATE_RATE 200
+        int m = millis() / ICON_UPDATE_RATE % 3;
+        if (m == 0) {
+            display.drawFastImage(x, y, 10, 8, wlan_connecting_symbol_1);
+        }
+        else if (m == 1) {
+            display.drawFastImage(x, y, 10, 8, wlan_connecting_symbol_2);
+        }
+        else {
+            display.drawFastImage(x, y, 10, 8, wlan_connecting_symbol_3);
+        }
+        redraw_after_timespan(ICON_UPDATE_RATE);
     }
     else if (wlan_status == disconnected) {
         display.drawFastImage(x, y, 10, 8, wlan_disconnected_symbol);
     }
 }
 
-void draw_mqtt_status(uint8_t x, uint8_t y) {
+void draw_mqtt_status(uint16_t& x, uint16_t y) {
+    x -= 8;
     connection_status_t mqtt_status = get_mqtt_connection_status();
     if (mqtt_status == connected) {
         display.drawFastImage(x, y, 8, 8, mqtt_connected_symbol);
@@ -37,37 +77,111 @@ void draw_mqtt_status(uint8_t x, uint8_t y) {
     }
 }
 
+void draw_text_indicator (uint16_t& x, uint16_t y, String text) {
+    int width = display.getStringWidth(text);
+    x -= width;
+    // offset of -2 to align with symbols (font has height 10, symbols 8)
+    display.drawString(x, y - 2, text);
+}
+
+bool draw_clock(uint16_t& x, uint16_t y) {
+    time_t t = time(0);
+    tm *now = localtime(&t);
+    if (now->tm_year < 100) {
+        return false;
+    }
+
+    auto hour = now->tm_hour;
+    auto minute = now->tm_min;
+
+    char time[6];
+    time[0] = '0' + hour / 10;
+    time[1] = '0' + hour % 10;
+    time[2] = ':';
+    time[3] = '0' + minute / 10;
+    time[4] = '0' + minute % 10;
+    time[5] = 0;
+
+    draw_text_indicator(x, y, time);
+    redraw_after_timespan((60 - now->tm_sec) * 1000);
+
+    return true;
+}
+
 void display_status() {
-    uint8_t iconPosition = 128;
-    iconPosition -= 10;
-    draw_network_status(iconPosition, 0);
-    iconPosition -= 2;
-    iconPosition -= 8;
-    draw_mqtt_status(iconPosition, 0);
+    uint16_t x = 128;
+    const uint16_t y = 2;
 
-    display.setFont(ArialMT_Plain_10);
-    display.setTextAlignment(TEXT_ALIGN_LEFT);
-    display.drawString(0, 10, "much wow, very secure");
-    display.drawString(0, 20, oled_log.c_str());
+    bool clock = draw_clock(x, y);
+    if (clock) {
+        x -= 2;
+    }
+
+    draw_network_status(x, y);
+    x -= 2;
+    draw_mqtt_status(x, y);
+    x -= 2;
+}
+
+void display_log() {
+    //display.setFont(ArialMT_Plain_10);
+    //display.setTextAlignment(TEXT_ALIGN_LEFT);
+    for (uint8_t i = 0; i < oled_log_message_count; i += 1) {
+        uint8_t line = (i + oled_log_first_message) % OLED_LOG_MAX_LENGTH;
+        display.drawString(0, 10 + (i * 10), oled_log_messages[line].c_str());
+    }
 }
 
 void oled_task(void *pvParameters) {
     while (true) {
-        display.clear();
+        long time_ms = millis();
+        bool reset = last_reset + RESET_AFTER_MS < time_ms;
 
-        display_status();
+        if (reset || (redraw_time > 0 && redraw_time <= time_ms)) {
+            redraw_time = 0;
 
-        display.setFont(ArialMT_Plain_10);
-        display.setTextAlignment(TEXT_ALIGN_RIGHT);
-        display.drawString(0, 20, String(millis()));
-        display.display();
+            if (reset) {
+                display.resetDisplay();
+                last_reset = time_ms;
+            }
+            else {
+                display.clear();
+            }
 
-        delay(100);
+            display_log();
+            display_status();
+
+            // display.setFont(ArialMT_Plain_10);
+            // display.setTextAlignment(TEXT_ALIGN_RIGHT);
+            // display.drawString(64, 0, String(millis()));
+
+            display.display();
+        }
+
+        vTaskDelay(pdMS_TO_TICKS(FRAME_TIME_MS));
     }
 }
 
+void oled_log(const std::string& message) {
+    if (oled_log_message_count < OLED_LOG_MAX_LENGTH) {
+        oled_log_messages[oled_log_message_count] = message;
+        oled_log_message_count += 1;
+    }
+    else {
+        oled_log_messages[oled_log_first_message] = message;
+        oled_log_first_message += 1;
+        oled_log_first_message %= OLED_LOG_MAX_LENGTH;
+    }
+    redraw();
+}
+
 void enable_oled() {
-    set_oled_log_callback([](const std::string& message) {oled_log = message;});
+    oled_log("qthing");
+    oled_log("much wow, very secure");
+
+    //display = SSD1306Wire(0x3c, GPIO_NUM_4, GPIO_NUM_15);
+
+    set_oled_log_callback(oled_log);
     display.init();
     display.flipScreenVertically();
     display.setFont(ArialMT_Plain_10);
diff --git a/qthing/oled_symbols.h b/qthing/oled_symbols.h
index c9ed614889c06ab2dd5f71bc3b7935f02fe47191..8ebb1c01e2c886b02aad1d72e1b28f895a6412fd 100644
--- a/qthing/oled_symbols.h
+++ b/qthing/oled_symbols.h
@@ -12,18 +12,42 @@ const uint8_t wlan_connected_symbol[] PROGMEM = {
     B00001001,
     B00000010
 };
-const uint8_t wlan_connecting_symbol[] PROGMEM = {
-    B00000000,
-    B00000000,
-    B00000000,
-    B00000000,
-    B11000000,
-    B11000000,
+const uint8_t wlan_connecting_symbol_1[] PROGMEM = {
     B00000000,
     B00000000,
+    B00100000,
+    B00010000,
+    B11010000,
+    B11010000,
+    B00010000,
+    B00100000,
     B00000000,
     B00000000
 };
+const uint8_t wlan_connecting_symbol_2[] PROGMEM = {
+    B00000000,
+    B00001000,
+    B00000100,
+    B00000100,
+    B11000100,
+    B11000100,
+    B00000100,
+    B00000100,
+    B00001000,
+    B00000000
+};
+const uint8_t wlan_connecting_symbol_3[] PROGMEM = {
+    B00000010,
+    B00000001,
+    B00000001,
+    B00000001,
+    B11000001,
+    B11000001,
+    B00000001,
+    B00000001,
+    B00000001,
+    B00000010
+};
 const uint8_t wlan_disconnected_symbol[] PROGMEM = {
     B00000000,
     B00000000,