diff --git a/epicardium/api/common.h b/epicardium/api/common.h
index a929f301cabb530ed3e430a021dd4dd441acf372..0a94d87abb9e5330c74f83c9f0a4a18d3d2d9765 100644
--- a/epicardium/api/common.h
+++ b/epicardium/api/common.h
@@ -37,4 +37,4 @@ struct api_call_mem {
 
 /* TODO: Make this address part of the linker script */
 static __attribute__((unused)) struct api_call_mem* API_CALL_MEM =
-	(struct api_call_mem*)0x20080000;
+	(struct api_call_mem*)0x20080100;
diff --git a/epicardium/epicardium.h b/epicardium/epicardium.h
index 7886cc5f0bb28fbc2ba5d818e43ef5f7879c0e50..198b11366da2f1237f733e20f9c5c66268f5aa36 100644
--- a/epicardium/epicardium.h
+++ b/epicardium/epicardium.h
@@ -2,6 +2,9 @@
 #define _EPICARDIUM_H
 #include <stdint.h>
 
+#define INT_CTRL_C  1
+#define INT_BHI     2
+
 #ifndef API
 #define API(id, def) def
 #endif
diff --git a/epicardium/main.c b/epicardium/main.c
index e61f533c23628d999696431860b1e9d3f349c1dd..f7fa71d59dbc12165fa0dc6eb7b1c1cbddb35543 100644
--- a/epicardium/main.c
+++ b/epicardium/main.c
@@ -10,6 +10,7 @@
 #include "leds.h"
 #include "api/dispatcher.h"
 #include "modules/modules.h"
+#include "interrupt/interrupt.h"
 
 #include <Heart.h>
 #include "GUI_Paint.h"
@@ -46,6 +47,7 @@ int main(void)
 
 	cdcacm_init();
 	fatfs_init();
+    interrupt_init();
 
 	printf("=> Initializing tasks ...\n");
 
diff --git a/epicardium/meson.build b/epicardium/meson.build
index 26f36cd47e471bf658b35b6447a69489110197ea..1deb5842ba0e1cb9ec593e04da6c0f35a733cdcb 100644
--- a/epicardium/meson.build
+++ b/epicardium/meson.build
@@ -39,6 +39,24 @@ api_dispatcher_lib = static_library(
   dependencies: periphdriver,
 )
 
+##########################################################################
+#
+# Interrupts
+#
+##########################################################################
+int_receiver_lib = static_library(
+  'int-receiver',
+  'interrupt/receiver.c',
+  dependencies: periphdriver,
+)
+
+int_receiver = declare_dependency(
+  include_directories: include_directories('.'),
+  link_with: int_receiver_lib,
+  dependencies: periphdriver,
+)
+
+
 ##########################################################################
 #
 # FreeRTOS
@@ -69,6 +87,7 @@ elf = executable(
   'cdcacm.c',
   'main.c',
   'support.c',
+  'interrupt/interrupt.c',
   module_sources,
   dependencies: [libcard10, max32665_startup_core0, maxusb, libff13],
   link_with: [api_dispatcher_lib, freertos],
diff --git a/epicardium/modules/serial.c b/epicardium/modules/serial.c
index 2efc4b9219e1c43170ddb30d5d247bf1d9388a2c..095e8d89f2001f26ce17bf18512de94091a825b5 100644
--- a/epicardium/modules/serial.c
+++ b/epicardium/modules/serial.c
@@ -4,13 +4,14 @@
 #include "max32665.h"
 #include "cdcacm.h"
 #include "uart.h"
-#include "tmr_utils.h"
 
 #include "FreeRTOS.h"
 #include "task.h"
 #include "queue.h"
 
 #include "modules.h"
+#include "interrupt/interrupt.h"
+
 
 /* Task ID for the serial handler */
 TaskHandle_t serial_task_id = NULL;
@@ -56,9 +57,14 @@ static void enqueue_char(char chr)
 {
 	if (chr == 0x3) {
 		/* Control-C */
-		TMR_TO_Start(MXC_TMR5, 1, 0);
+        interrupt_ctrl_c();
 	}
 
+    if (chr == 0x0e) {
+		/* Control-N */
+        interrupt_bhi();
+    }
+
 	if (xQueueSend(read_queue, &chr, 100) == errQUEUE_FULL) {
 		/* Queue overran, wait a bit */
 		vTaskDelay(portTICK_PERIOD_MS * 50);
diff --git a/pycardium/meson.build b/pycardium/meson.build
index 67698112ed8be52f569fec2d4d087371bbe5cb91..dd7822c7b39eb596025a4f564b7586fca75ea42f 100644
--- a/pycardium/meson.build
+++ b/pycardium/meson.build
@@ -4,6 +4,7 @@ modsrc = files(
   'modules/utime.c',
   'modules/leds.c',
   'modules/vibra.c',
+  'modules/interrupt.c',
 )
 
 #################################
@@ -73,7 +74,7 @@ elf = executable(
   modsrc,
   mp_headers,
   include_directories: micropython_includes,
-  dependencies: [max32665_startup_core1, periphdriver, api_caller],
+  dependencies: [max32665_startup_core1, periphdriver, api_caller, int_receiver],
   link_with: upy,
   link_whole: [max32665_startup_core1_lib],
   link_args: [
diff --git a/pycardium/modules/qstrdefs.h b/pycardium/modules/qstrdefs.h
index 2a6dcbe6beb7ebe5a4a5a29226b7eca0a6b9c901..3466d79a5d6977c4e20d60243e21cdd35e7d9d84 100644
--- a/pycardium/modules/qstrdefs.h
+++ b/pycardium/modules/qstrdefs.h
@@ -25,3 +25,5 @@ Q(ticks_diff)
 /* vibra */
 Q(vibra)
 Q(vibrate)
+
+Q(set_bhi)
diff --git a/pycardium/mpconfigport.h b/pycardium/mpconfigport.h
index a6aafcb868d1b01dc1bd103015e3acb413225237..d1187611def6587d66334231d5e8031f252d9769 100644
--- a/pycardium/mpconfigport.h
+++ b/pycardium/mpconfigport.h
@@ -19,6 +19,8 @@
 #define MICROPY_HELPER_REPL                 (1)
 #define MICROPY_LONGINT_IMPL                (MICROPY_LONGINT_IMPL_LONGLONG)
 
+#define MICROPY_ENABLE_SCHEDULER            (1)
+
 /* Builtin function and modules */
 #define MICROPY_PY_BUILTINS_HELP            (1)
 #define MICROPY_PY_BUILTINS_HELP_MODULES    (1)
@@ -37,6 +39,7 @@
 #define MODULE_UTIME_ENABLED                (1)
 #define MODULE_LEDS_ENABLED                 (1)
 #define MODULE_VIBRA_ENABLED                (1)
+#define MODULE_INTERRUPT_ENABLED            (1)
 
 /*
  * This port is intended to be 32-bit, but unfortunately, int32_t for
diff --git a/pycardium/mphalport.c b/pycardium/mphalport.c
index fdfb592d8830699f8d222952d9a4f99095b60ae3..fbdae590c33a0f0a00dd2a336a3a974f3678735b 100644
--- a/pycardium/mphalport.c
+++ b/pycardium/mphalport.c
@@ -14,7 +14,7 @@
 #include "tmr.h"
 
 #include "epicardium.h"
-
+#include "interrupt/int-common.h"
 /******************************************************************************
  * Serial Communication
  */
@@ -64,21 +64,36 @@ long _write(int fd, const char *buf, size_t cnt)
 
 bool do_interrupt = false;
 
+mp_obj_t bhi_callback = NULL;
+
+void mp_hal_interrupt_set_bhi(mp_obj_t func)
+{
+    bhi_callback = func;
+}
+
 /* Timer Interrupt used for control char notification */
 void TMR5_IRQHandler(void)
 {
 	TMR_IntClear(MXC_TMR5);
 
-	if (do_interrupt) {
-		/* Taken from lib/micropython/micropython/lib/utils/interrupt_char.c */
-		MP_STATE_VM(mp_pending_exception) =
-			MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception));
-#if MICROPY_ENABLE_SCHEDULER
-		if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) {
-			MP_STATE_VM(sched_state) = MP_SCHED_PENDING;
-		}
-#endif
-	}
+    switch(INT_CALL_MEM->id) {
+    case INT_CTRL_C:
+        if (do_interrupt) {
+            /* Taken from lib/micropython/micropython/lib/utils/interrupt_char.c */
+            MP_STATE_VM(mp_pending_exception) =
+                MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception));
+    #if MICROPY_ENABLE_SCHEDULER
+            if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) {
+                MP_STATE_VM(sched_state) = MP_SCHED_PENDING;
+            }
+    #endif
+        }
+    break;
+    case INT_BHI:
+        mp_sched_schedule(bhi_callback, 0);
+    break;
+    }
+    INT_CALL_MEM->id = 0;
 }
 
 void mp_hal_set_interrupt_char(char c)
diff --git a/pycardium/mphalport.h b/pycardium/mphalport.h
index 79e25cde78d3836281bc2d03c1dec87fc1c19be6..df1e84caae306249dc03db570e0c858f5c778e73 100644
--- a/pycardium/mphalport.h
+++ b/pycardium/mphalport.h
@@ -1,4 +1,5 @@
 #include "py/mpconfig.h"
+#include "py/obj.h"
 
 /* TODO: Replace this with a proper implementation */
 static inline mp_uint_t mp_hal_ticks_ms(void)
@@ -7,3 +8,5 @@ static inline mp_uint_t mp_hal_ticks_ms(void)
 }
 
 void mp_hal_set_interrupt_char(char c);
+
+void mp_hal_interrupt_set_bhi(mp_obj_t func);