diff --git a/badge23/components/gc9a01/gc9a01.c b/badge23/components/gc9a01/gc9a01.c
index ac5770dc9a3067830339f926ec96b736985b607c..4c996427d728662921555b647c8b0a37dafef64f 100644
--- a/badge23/components/gc9a01/gc9a01.c
+++ b/badge23/components/gc9a01/gc9a01.c
@@ -409,6 +409,13 @@ void GC9A01_SetBL(uint8_t Value)
 		uint16_t color = ScreenBuff[y * GC9A01_Width + x];
 		SwapBytes(&color);
 		return color;
+    }
+
+    void GC9A01_DrawPixel(int16_t x, int16_t y, uint16_t color) {
+            if ((x < 0) || (x >= GC9A01_Width) || (y < 0) || (y >= GC9A01_Height))
+                return;
+            SwapBytes(&color);
+            ScreenBuff[y * GC9A01_Width + x] = color;
 	}
 
 	void GC9A01_FillRect(int16_t x, int16_t y, int16_t w, int16_t h,
diff --git a/badge23/components/gc9a01/gc9a01.h b/badge23/components/gc9a01/gc9a01.h
index 99b7cce17d598c9a6e0e27bc4dbef5b9b33332c6..c349bc08e46009cc34fc023376efcab0788edfd4 100644
--- a/badge23/components/gc9a01/gc9a01.h
+++ b/badge23/components/gc9a01/gc9a01.h
@@ -14,16 +14,6 @@
 
 extern uint16_t ScreenBuff[GC9A01_Height * GC9A01_Width];
 
-static inline void GC9A01_DrawPixel(int16_t x, int16_t y, uint16_t color) {
-		if ((x < 0) || (x >= GC9A01_Width) || (y < 0) || (y >= GC9A01_Height))
-			return;
-
-		//SwapBytes(&color);
-
-		ScreenBuff[y * GC9A01_Width + x] = color;
-	}
-
-
 uint16_t GC9A01_GetWidth();
 uint16_t GC9A01_GetHeight();
 
diff --git a/badge23/display.c b/badge23/display.c
index 38c7fbf7e03e9d779181005e0f95b626e7ca8130..ab60092a637aad6431c2f803a56a12bbe5c94efc 100644
--- a/badge23/display.c
+++ b/badge23/display.c
@@ -34,10 +34,28 @@ static void _display_init() {
     xTaskCreate(&display_task, "Display", 4096, NULL, configMAX_PRIORITIES - 3, &handle);
     */
     
+    /* SCOPE TASK
     TimerHandle_t aa = xTimerCreate("Display", pdMS_TO_TICKS(100), pdTRUE, (void *) 0, *display_task);
     if( xTimerStart(aa, 0 ) != pdPASS )
     {
     }
+    */
+}
+
+void display_update(){
+    GC9A01_Update();
+}
+
+void display_draw_pixel(uint8_t x, uint8_t y, uint16_t col){
+    GC9A01_DrawPixel(x, y, col);
+}
+
+uint16_t display_get_pixel(uint8_t x, uint8_t y){
+    return GC9A01_GetPixel(x,y);
+}
+
+void display_fill(uint16_t col){
+    GC9A01_FillRect(0, 0, 240, 240, col);
 }
 
 void display_draw_scope(){
@@ -59,8 +77,8 @@ void display_draw_scope(){
 
     //uint32_t td = esp_log_timestamp() - t0;
     // printf("it took %lu\n", td);
+    display_update();
 
-    GC9A01_Update();
 }
 //static void display_task(void* arg) {
 static void display_task(TimerHandle_t aaaaa) {
diff --git a/badge23/display.h b/badge23/display.h
index f775e573f0862ac7841a3956c6ac25c00713cc11..d923a061e8d10ebf6b215e920d578150bc24d93d 100644
--- a/badge23/display.h
+++ b/badge23/display.h
@@ -1,6 +1,11 @@
 #pragma once
 
 #include <stdbool.h>
+#include <stdint.h>
 
 void display_init();
 void display_draw_scope();
+void display_update();
+void display_draw_pixel(uint8_t x, uint8_t y, uint16_t col);
+uint16_t display_get_pixel(uint8_t x, uint8_t y);
+void display_fill(uint16_t col);
diff --git a/micropython/ports/esp32/badge23_mp_hardware.c b/micropython/ports/esp32/badge23_mp_hardware.c
index 360f43ccb4a65895d2008a2a4401be55c35fbb7c..14dca2cfc3a14a43852bc3cd8313e8f244afc8f4 100644
--- a/micropython/ports/esp32/badge23_mp_hardware.c
+++ b/micropython/ports/esp32/badge23_mp_hardware.c
@@ -14,6 +14,36 @@
 #include "../badge23/leds.h"
 #include "../badge23/captouch.h"
 
+#include "../badge23/display.h"
+STATIC mp_obj_t mp_display_update(size_t n_args, const mp_obj_t *args) {
+    display_update();
+    return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_display_update_obj, 0, 1, mp_display_update);
+
+STATIC mp_obj_t mp_display_draw_pixel(size_t n_args, const mp_obj_t *args) {
+    uint16_t x = mp_obj_get_int(args[0]);
+    uint16_t y = mp_obj_get_int(args[1]);
+    uint16_t col = mp_obj_get_int(args[2]);
+    display_draw_pixel(x, y, col);
+    return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_display_draw_pixel_obj, 3, 4, mp_display_draw_pixel);
+
+STATIC mp_obj_t mp_display_get_pixel(size_t n_args, const mp_obj_t *args) {
+    uint16_t x = mp_obj_get_int(args[0]);
+    uint16_t y = mp_obj_get_int(args[1]);
+    return mp_obj_new_int(display_get_pixel(x, y));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_display_get_pixel_obj, 2, 3, mp_display_get_pixel);
+
+STATIC mp_obj_t mp_display_fill(size_t n_args, const mp_obj_t *args) {
+    uint16_t col = mp_obj_get_int(args[0]);
+    display_fill(col);
+    return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_display_fill_obj, 1, 2, mp_display_fill);
+
 STATIC mp_obj_t mp_get_captouch(size_t n_args, const mp_obj_t *args) {
     uint16_t captouch = read_captouch();
     uint16_t pad = mp_obj_get_int(args[0]);
@@ -90,6 +120,10 @@ STATIC const mp_rom_map_elem_t mp_module_hardware_globals_table[] = {
     { MP_ROM_QSTR(MP_QSTR_set_led_rgb), MP_ROM_PTR(&mp_set_led_rgb_obj) },
     { MP_ROM_QSTR(MP_QSTR_set_led_hsv), MP_ROM_PTR(&mp_set_led_hsv_obj) },
     { MP_ROM_QSTR(MP_QSTR_update_leds), MP_ROM_PTR(&mp_update_leds_obj) },
+    { MP_ROM_QSTR(MP_QSTR_display_update), MP_ROM_PTR(&mp_display_update_obj) },
+    { MP_ROM_QSTR(MP_QSTR_display_draw_pixel), MP_ROM_PTR(&mp_display_draw_pixel_obj) },
+    { MP_ROM_QSTR(MP_QSTR_display_get_pixel), MP_ROM_PTR(&mp_display_get_pixel_obj) },
+    { MP_ROM_QSTR(MP_QSTR_display_fill), MP_ROM_PTR(&mp_display_fill_obj) },
 };
 
 STATIC MP_DEFINE_CONST_DICT(mp_module_hardware_globals, mp_module_hardware_globals_table);
diff --git a/python_payload/cap_touch_demo.py b/python_payload/cap_touch_demo.py
index 6a5f3ebcfea288df9ecdb585e8694ee12a349d9a..26b35f02845828620ca6c4df3c362b19dd642f12 100644
--- a/python_payload/cap_touch_demo.py
+++ b/python_payload/cap_touch_demo.py
@@ -1,18 +1,5 @@
 from synth import tinysynth
 from hardware import *
-import time
-from machine import Pin
-
-p = Pin(0, Pin.IN)
-
-set_global_volume_dB(0)
-synths = []
-for i in range(5):
-    synths += [tinysynth(440,1)]
-
-for synth in synths:
-    synth.decay(100)
-    synth.waveform(1)
 
 chords = [\
 [-4,0,3,8,10],\
@@ -22,8 +9,9 @@ chords = [\
 [3,7,10,14,15]\
 ]
 
+chord_index = 3
 chord = chords[3]
-chord_index = -1
+synths = []
 
 def set_chord(i):
     global chord_index
@@ -35,25 +23,40 @@ def set_chord(i):
             set_led_hsv(j, hue, 1, 0.5)
         chord = chords[i]
         print("set chord " +str(i))
+        update_leds()
 
-set_chord(3)
 
-def cap_touch_demo_start():
+def run():
     global chord_index
     global chord
-    global p
-    while True:
-        update_leds()
-        if(p.value() == 0):
-            captouch_autocalib()
-            time.sleep_ms(100)
-        for i in range(10):
-            if(get_captouch(i)):
-                if(i%2):
-                    k = int((i-1)/2)
-                    set_chord(k)
-                else:
-                    k = int(i/2)
-                    synths[k].tone(chord[k])
-                    synths[k].start()
-                    print("synth " +str(k))
+    global synths
+    for i in range(10):
+        if(get_captouch(i)):
+            if(i%2):
+                k = int((i-1)/2)
+                set_chord(k)
+            else:
+                k = int(i/2)
+                synths[k].tone(chord[k])
+                synths[k].start()
+                print("synth " +str(k))
+
+def init():
+    global chord_index
+    global chord
+    global synths
+
+    for i in range(5):
+        synths += [tinysynth(440,1)]
+
+    for synth in synths:
+        synth.decay(100)
+        synth.waveform(1)
+
+def foreground():
+    global chord_index
+    global chord
+    global synths
+    tmp = chord_index
+    chord_index = -1
+    set_chord(tmp)
diff --git a/python_payload/main.py b/python_payload/main.py
index 43337f80973bdbada9823c38a11b7ca1d34a09ae..a651bbf2b4d6305f67e1af67da5d83763eef308e 100644
--- a/python_payload/main.py
+++ b/python_payload/main.py
@@ -1,9 +1,156 @@
 from machine import Pin
+from hardware import *
+import time
+import cap_touch_demo
+import melodic_demo
+boot = Pin(0, Pin.IN)
+vol_up = Pin(35, Pin.IN, Pin.PULL_UP)
+vol_down = Pin(37, Pin.IN, Pin.PULL_UP)
+
+# pin numbers
+# right side: left 37, down 0, right 35
+# left side: left 7, down 6, right 5
+# NOTE: All except for 0 should be initialized with Pin.PULL_UP
+# 0 (bootsel) probably not but idk? never tried
+
+def clear_all_leds():
+    for i in range(40):
+        set_led_rgb(i, 0, 0, 0)
+    update_leds()
+
+select = [\
+[0,1,1,0,0,1,1,1,1,0,1,0,0,0,0,1,1,1,1,0,0,1,1,0,0,1,1,1,1,1,0,1],\
+[1,0,0,1,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1],\
+[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,1],\
+[0,1,1,0,0,1,1,1,1,0,1,0,0,0,0,1,1,1,1,0,1,0,0,0,0,0,0,1,0,0,0,1],\
+[0,0,0,1,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,1],\
+[1,0,0,1,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0],\
+[0,1,1,0,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,0,1,1,0,0,0,0,1,0,0,0,1],\
+]
 
-p = Pin(0, Pin.IN)
+def draw_text_big(text, x, y):
+    ypos = 120+int(len(text)/2) + int(y)
+    xpos = 120+int(len(text[0])/2) + int(x)
+    for l, line in enumerate(text):
+        for p, pixel in enumerate(line):
+            if(pixel == 1):
+                display_draw_pixel(xpos - 2*p, ypos - 2*l, r)
+                display_draw_pixel(xpos - 2*p, ypos - 2*l-1, b)
+                display_draw_pixel(xpos - 2*p-1, ypos - 2*l, b)
+                display_draw_pixel(xpos - 2*p-1, ypos - 2*l-1, r)
 
-while (p.value() == 1):
+def highlight_bottom_petal(num, r, g, b):
+    start = 4 + 8*num
+    for i in range(7):
+        set_led_rgb((i+start%40), r, g, b)
+    update_leds()
+    
+def long_bottom_petal_captouch_blocking(num, ms):
+    if(get_captouch((num*2) + 1) == 1):
+        time.sleep_ms(ms)
+        if(get_captouch((num*2) + 1) == 1):
+            return True
+    return False
+    
+foreground = 0
+volume = 0
+
+def init_menu():
     pass
 
-import cap_touch_demo
-cap_touch_demo.cap_touch_demo_start()
+def draw_rect(x,y,w,h,col):
+    for j in range(w):
+        for k in range(h):
+            display_draw_pixel(x+j,y+k,col)
+            
+    
+def draw_volume_slider():
+    global volume
+    length = 96 + ((volume - 20) * 1.6)
+    if length > 96:
+        length = 96
+    if length < 0:
+        length = 0
+    length = int(length)
+    draw_rect(70,20,100,10,g)
+    draw_rect(71,21,98,8, 0)
+    draw_rect(72+96-length,22,length,6,g)
+    
+
+def run_menu():
+    global foreground
+    display_fill(background)
+    draw_text_big(select, 0, 0)
+    draw_volume_slider()
+    display_update()
+
+    if long_bottom_petal_captouch_blocking(0,20):
+        clear_all_leds()
+        highlight_bottom_petal(0,255,0,0)
+        display_fill(background)
+        display_update()
+        foreground = cap_touch_demo.run
+        time.sleep_ms(100)
+        clear_all_leds()
+        captouch_autocalib()
+        cap_touch_demo.foreground()
+    if long_bottom_petal_captouch_blocking(1,20):
+        clear_all_leds()
+        highlight_bottom_petal(0,255,0,0)
+        display_fill(background)
+        display_update()
+        foreground = melodic_demo.run
+        time.sleep_ms(100)
+        clear_all_leds()
+        captouch_autocalib()
+        melodic_demo.foreground()
+
+def foreground_menu():
+    clear_all_leds()
+    highlight_bottom_petal(0,0,255,255);
+    highlight_bottom_petal(1,255,0,255);
+    display_fill(background)
+    draw_text_big(select, 0, 0)
+    display_update()
+
+background = 0;
+g = 0b0000011111100000;
+r = 0b1111100000000000;
+b = 0b0000000000011111;
+
+time.sleep_ms(5000)
+captouch_autocalib()
+cap_touch_demo.init()
+melodic_demo.init()
+
+init_menu()
+foreground = run_menu
+foreground_menu()
+set_global_volume_dB(volume)
+
+def set_rel_volume(vol):
+    global volume
+    vol += volume
+    if vol > 20:
+        vol = 20
+    if vol < -40:
+        vol = -40
+    volume = vol
+    if vol == -40: #mute
+        set_global_volume_dB(-90)
+    else:
+        set_global_volume_dB(volume)
+    time.sleep_ms(100)
+
+while True:
+    if(boot.value() == 0):
+        if foreground == run_menu:
+            captouch_autocalib()
+        else:
+            foreground = run_menu
+            foreground_menu()
+    if(vol_up.value() == 0):
+        set_rel_volume(+3)
+    if(vol_down.value() == 0):
+        set_rel_volume(-3)
+    foreground()
diff --git a/python_payload/melodic_demo.py b/python_payload/melodic_demo.py
new file mode 100644
index 0000000000000000000000000000000000000000..35ab7f03509d42784d2af894ee80c9af21d2502a
--- /dev/null
+++ b/python_payload/melodic_demo.py
@@ -0,0 +1,67 @@
+from synth import tinysynth
+from hardware import *
+
+
+octave = 0
+synths = []
+scale = [0,2,4,5,7,9,11]
+
+def set_chord(i):
+    global chord_index
+    global chord
+    if(i != chord_index):
+        chord_index = i
+        for j in range(40):
+            hue = int(72*(i+0.5)) % 360
+            set_led_hsv(j, hue, 1, 0.5)
+        chord = chords[i]
+        print("set chord " +str(i))
+        update_leds()
+
+def run():
+    global scale
+    global octave
+    global synths
+    for i in range(10):
+        if(get_captouch(i)):
+            if(i == 4):
+                octave = -1
+            elif(i == 5):
+                octave = 0
+            elif(i == 6):
+                octave = 1
+            else:
+                k = i
+                if(k>3):
+                    k -= 10
+                k = 3 - k
+                note = scale[k] + 12 * octave
+                synths[0].tone(note)
+                synths[0].start()
+
+def init():
+    global synths
+
+    for i in range(1):
+        synths += [tinysynth(440,1)]
+
+    for synth in synths:
+        synth.decay(100)
+        synth.waveform(1)
+
+def highlight_bottom_petal(num, r, g, b):
+    start = 4 + 8*num
+    for i in range(7):
+        set_led_rgb((i+start%40), r, g, b)
+    update_leds()
+
+def foreground():
+    highlight_bottom_petal(0, 0, 0, 255)
+    highlight_bottom_petal(1, 0, 0, 255)
+    highlight_bottom_petal(4, 0, 0, 255)
+    highlight_bottom_petal(3, 0, 0, 255)
+    set_led_rgb(18, 255, 0, 255)
+    set_led_rgb(19, 255, 0, 255)
+    set_led_rgb(27, 255, 0, 255)
+    set_led_rgb(28, 255, 0, 255)
+    highlight_bottom_petal(2, 255, 0, 255)