diff --git a/pycardium/meson.build b/pycardium/meson.build
index b43d0fc5cd7668e6db7e0bd3fe8a5301c954cb8a..4d976e0a4ba020cc9a938be041fc467d107118d3 100644
--- a/pycardium/meson.build
+++ b/pycardium/meson.build
@@ -1,6 +1,7 @@
 name = 'pycardium'
 
 modsrc = files(
+  'modules/buttons.c',
   'modules/fat_file.c',
   'modules/fat_reader_import.c',
   'modules/interrupt.c',
diff --git a/pycardium/modules/buttons.c b/pycardium/modules/buttons.c
new file mode 100644
index 0000000000000000000000000000000000000000..ab8dabd7d28692f7e586dc64d717c4c3cfb6aa31
--- /dev/null
+++ b/pycardium/modules/buttons.c
@@ -0,0 +1,39 @@
+#include "py/obj.h"
+#include "py/objlist.h"
+#include "py/runtime.h"
+#include <stdio.h>
+
+#include "epicardium.h"
+
+static mp_obj_t mp_buttons_read(mp_obj_t mask_in)
+{
+	uint8_t mask          = mp_obj_get_int(mask_in);
+	uint8_t button_states = epic_buttons_read(mask);
+	return MP_OBJ_NEW_SMALL_INT(button_states);
+}
+static MP_DEFINE_CONST_FUN_OBJ_1(buttons_read_obj, mp_buttons_read);
+
+static const mp_rom_map_elem_t buttons_module_globals_table[] = {
+	{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_buttons) },
+	{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&buttons_read_obj) },
+	{ MP_ROM_QSTR(MP_QSTR_BOTTOM_LEFT),
+	  MP_OBJ_NEW_SMALL_INT(BUTTON_LEFT_BOTTOM) },
+	{ MP_ROM_QSTR(MP_QSTR_BOTTOM_RIGHT),
+	  MP_OBJ_NEW_SMALL_INT(BUTTON_RIGHT_BOTTOM) },
+	{ MP_ROM_QSTR(MP_QSTR_TOP_RIGHT),
+	  MP_OBJ_NEW_SMALL_INT(BUTTON_RIGHT_TOP) },
+	{ MP_ROM_QSTR(MP_QSTR_TOP_LEFT),
+	  MP_OBJ_NEW_SMALL_INT(BUTTON_LEFT_TOP) },
+	{ MP_ROM_QSTR(MP_QSTR_RESET), MP_OBJ_NEW_SMALL_INT(BUTTON_RESET) },
+};
+static MP_DEFINE_CONST_DICT(
+	buttons_module_globals, buttons_module_globals_table
+);
+
+const mp_obj_module_t buttons_module = {
+	.base    = { &mp_type_module },
+	.globals = (mp_obj_dict_t *)&buttons_module_globals,
+};
+
+/* clang-format off */
+MP_REGISTER_MODULE(MP_QSTR_buttons, buttons_module, MODULE_BUTTONS_ENABLED);
diff --git a/pycardium/modules/qstrdefs.h b/pycardium/modules/qstrdefs.h
index 2da8ea8ecc6efdb5f24e287ec389725c4c72be97..e1bb0a02f0e69da49c6ab6b968b42437c2056797 100644
--- a/pycardium/modules/qstrdefs.h
+++ b/pycardium/modules/qstrdefs.h
@@ -24,6 +24,15 @@ Q(BOTTOM_RIGHT)
 Q(TOP_LEFT)
 Q(TOP_RIGHT)
 
+/* buttons */
+Q(buttons)
+Q(read)
+Q(BOTTOM_LEFT)
+Q(TOP_LEFT)
+Q(BOTTOM_RIGHT)
+Q(TOP_RIGHT)
+Q(RESET)
+
 /* utime */
 Q(utime)
 Q(alarm)
diff --git a/pycardium/mpconfigport.h b/pycardium/mpconfigport.h
index 5e4d09e907b1f7ee5c7abd191b5a4e7f2b2c1ac7..00430b2e457276b1eea295cb91d383e8c1007962 100644
--- a/pycardium/mpconfigport.h
+++ b/pycardium/mpconfigport.h
@@ -39,6 +39,7 @@
 #define MICROPY_PY_UERRNO                   (1)
 
 /* Modules */
+#define MODULE_BUTTONS_ENABLED              (1)
 #define MODULE_DISPLAY_ENABLED              (1)
 #define MODULE_INTERRUPT_ENABLED            (1)
 #define MODULE_LEDS_ENABLED                 (1)