diff --git a/epicardium/epicardium.h b/epicardium/epicardium.h
index 2c65e376d4f3741592d34e1e64f57cd3c9714db2..e6623a6f9ad2d77bfbf7df0d242d793721cc1d63 100644
--- a/epicardium/epicardium.h
+++ b/epicardium/epicardium.h
@@ -51,6 +51,12 @@ typedef _Bool bool;
 #define API_DISP_CIRC              0x27
 #define API_DISP_PIXEL             0x28
 #define API_DISP_FRAMEBUFFER       0x29
+#define API_DISP_TXT_UPDATE	   0x2A
+#define API_DISP_TXT_CLEAR	   0x2B
+#define API_DISP_TXT_PRINT	   0x2C
+#define API_DISP_TXT_SET_COLOR	   0x2D
+#define API_DISP_TXT_SET_CURSOR	   0x2E
+#define API_DISP_TXT_SET_AUTOUPDATE	0x2F
 
 #define API_FILE_OPEN              0x40
 #define API_FILE_CLOSE             0x41
@@ -695,6 +701,57 @@ API(API_DISP_CIRC,
  */
 API(API_DISP_FRAMEBUFFER, int epic_disp_framebuffer(union disp_framebuffer *fb));
 
+/**
+ * Redraw the framebuffer
+ *
+ * :return: ``0`` on success, can't fail
+ */
+API(API_DISP_TXT_UPDATE, int epic_disp_txt_update());
+
+/**
+ * Fills the framebuffer with ' ' characters. Does not update the framebuffer.
+ *
+ * :return: ``0`` on success, can't fail
+ */
+API(API_DISP_TXT_CLEAR, int epic_disp_txt_clear());
+
+/**
+ * Puts the string on the buffer. Updates the cursor. Does not update the
+ * framebuffer.
+ *
+ * :param string: A null-terminated ASCII string.
+ * :return: ``0`` on success, can't fail
+ */
+API(API_DISP_TXT_PRINT, int epic_disp_txt_print(const char *string));
+
+/**
+ * Updates the active background and foreground colors.  
+ *
+ * :param fg: The display-encoded foreground color
+ * :param bg: The display-encoded background color
+ * :return: ``0`` on success, can't fail
+ */
+API(API_DISP_TXT_SET_COLOR, int epic_disp_txt_set_color(uint16_t fg, uint16_t bg));
+
+/**
+ * Sets cursor location within the textbuffer space.
+ *
+ * :param x: new cursor column
+ * :param x: new cursor row
+ * :param draw_cursor: specifies whether the cursor should be drawn
+ * :return: ``0`` on success, can't fail
+ */
+API(API_DISP_TXT_SET_CURSOR, int epic_disp_txt_set_cursor(uint16_t x, uint16_t y, uint16_t draw_cursor));
+
+/**
+ * Enables/disables automatic framebuffer updates. Automatic updates occur
+ * with every character written to the buffer - epic_disp_txt_update() is
+ * implicitly called.
+ *
+ * :param enabled: if not zero, textbuffer will be updated automatically
+ * :return: ``0`` on success, can't fail
+ */
+API(API_DISP_TXT_SET_AUTOUPDATE, int epic_disp_txt_set_autoupdate(uint16_t enabled));
 
 /**
  * Start continuous readout of the light sensor. Will read light level
diff --git a/epicardium/modules/display.c b/epicardium/modules/display.c
index b6bf36249f61aed4b60b3fcbb62900ac72f15756..dfdb96c9d9bba60f096de4cc53698125ba97232c 100644
--- a/epicardium/modules/display.c
+++ b/epicardium/modules/display.c
@@ -194,6 +194,73 @@ int epic_disp_close()
 	}
 }
 
+int epic_disp_txt_update()
+{
+	int cl = check_lock();
+	if (cl < 0) {
+		return cl;
+	}
+
+	txt_update(&display_textb, 1);
+	return 0;
+}
+
+int epic_disp_txt_clear()
+{
+	int cl = check_lock();
+	if (cl < 0) {
+		return cl;
+	}
+
+	txt_clear(&display_textb);
+	return 0;
+}
+
+int epic_disp_txt_print(const char *string)
+{
+	int cl = check_lock();
+	if (cl < 0) {
+		return cl;
+	}
+
+	txt_puts(&display_textb, string);
+	return 0;
+}
+
+int epic_disp_txt_set_color(uint16_t fg, uint16_t bg)
+{
+	int cl = check_lock();
+	if (cl < 0) {
+		return cl;
+	}
+
+	txt_set_color(&display_textb, TEXT_FOREGROUND, (Color)(fg));
+	txt_set_color(&display_textb, TEXT_BACKGROUND, (Color)(bg));
+	return 0;
+}
+
+int epic_disp_txt_set_cursor(uint16_t x, uint16_t y, uint16_t draw_cursor)
+{
+	int cl = check_lock();
+	if (cl < 0) {
+		return cl;
+	}
+
+	txt_set_cursor(&display_textb, x, y, draw_cursor);
+	return 0;
+}
+
+int epic_disp_txt_set_autoupdate(uint16_t enabled)
+{
+	int cl = check_lock();
+	if (cl < 0) {
+		return cl;
+	}
+
+	display_textb.auto_update = enabled;
+	return 0;
+}
+
 void disp_forcelock()
 {
 	TaskHandle_t task = xTaskGetCurrentTaskHandle();
diff --git a/lib/gfx/textbuffer.c b/lib/gfx/textbuffer.c
index 000f2cadf75ef76f3ba9e2684feb92e5035424c0..38b2f1aa588c6dfd77a6d9a08b259cda6ac588fc 100644
--- a/lib/gfx/textbuffer.c
+++ b/lib/gfx/textbuffer.c
@@ -114,7 +114,7 @@ void txt_clear(struct txt_buffer *tm)
 
 	tm->needs_redraw = 1;
 	if (tm->auto_update)
-		txt_update(tm);
+		txt_update(tm, 0);
 }
 
 void txt_putchar(struct txt_buffer *tm, char ch)
@@ -139,7 +139,7 @@ void txt_putchar(struct txt_buffer *tm, char ch)
 
 	tm->needs_redraw = 1;
 	if (tm->auto_update)
-		txt_update(tm);
+		txt_update(tm, 0);
 }
 
 void txt_puts(struct txt_buffer *tm, const char *str)
@@ -219,8 +219,9 @@ void txt_set_color_f(
 	}
 }
 
-void txt_set_color(struct txt_buffer *tm, enum txt_color sw, int r, int g, int b)
-{
+void txt_set_color_rgb(
+	struct txt_buffer *tm, enum txt_color sw, int r, int g, int b
+) {
 	Color c = gfx_color_rgb(tm->reg, r, g, b);
 
 	switch (c) {
@@ -233,6 +234,18 @@ void txt_set_color(struct txt_buffer *tm, enum txt_color sw, int r, int g, int b
 	}
 }
 
+void txt_set_color(struct txt_buffer *tm, enum txt_color sw, Color c)
+{
+	switch (c) {
+	case TEXT_FOREGROUND:
+		tm->fg_color = c;
+		break;
+	case TEXT_BACKGROUND:
+		tm->bg_color = c;
+		break;
+	}
+}
+
 void txt_set_cursor(struct txt_buffer *tm, int x, int y, int draw_cursor)
 {
 	tm->draw_cursor = draw_cursor;
@@ -246,7 +259,7 @@ void txt_set_cursor(struct txt_buffer *tm, int x, int y, int draw_cursor)
 	tm->cursor_row    = y;
 
 	if (tm->auto_update)
-		txt_update(tm);
+		txt_update(tm, 0);
 }
 
 void txt_set_transparent(struct txt_buffer *tm)
@@ -254,9 +267,9 @@ void txt_set_transparent(struct txt_buffer *tm)
 	tm->bg_color = tm->fg_color;
 }
 
-void txt_update(struct txt_buffer *tm)
+void txt_update(struct txt_buffer *tm, int force_redraw)
 {
-	if (tm->needs_redraw)
+	if (tm->needs_redraw || force_redraw)
 		txt_draw(tm);
 	gfx_update(tm->reg);
 }
diff --git a/lib/gfx/textbuffer.h b/lib/gfx/textbuffer.h
index a2dc1134a78d1ec8cea80c874235a190b6a33443..e3599c58d894ceeff3f68cccd7d4228923b3a3f4 100644
--- a/lib/gfx/textbuffer.h
+++ b/lib/gfx/textbuffer.h
@@ -41,10 +41,11 @@ void txt_puts(struct txt_buffer *tm, const char *str);
 void txt_draw(struct txt_buffer *tm);
 void txt_set_color_f(struct txt_buffer *tm, enum txt_color sw, float r, float g,
 								     float b);
-void txt_set_color(struct txt_buffer *tm, enum txt_color sw, int r, int g,
-								 int b);
+void txt_set_color_rgb(struct txt_buffer *tm, enum txt_color sw, int r, int g,
+								       int b);
+void txt_set_color(struct txt_buffer *tm, enum txt_color sw, Color c);
 void txt_set_transparent(struct txt_buffer *tm);
 void txt_set_cursor(struct txt_buffer *tm, int x, int y, int draw_cursor);
-void txt_update(struct txt_buffer *tm);
+void txt_update(struct txt_buffer *tm, int force_redraw);
 
 #endif