diff --git a/lib/cube/i2c_master.py b/lib/cube/i2c_master.py
index ee8b44de3ef6466568012d4b8f6fb6f98e59fcc7..1b6ffd24aa3fc32eff6c5a51343a7906a6c1c636 100644
--- a/lib/cube/i2c_master.py
+++ b/lib/cube/i2c_master.py
@@ -1,19 +1,21 @@
-from machine import I2C, Pin
+import time
+from machine import I2C, Pin, Timer
+from micropython import const
+
 
 from lib.hw_defs.pins import UTZ_I2C_SDA_PIN, UTZ_I2C_SCK_PIN, I2C_STRONG_PULL_RPIN_BIT 
-from lib.robot_consts import I2C_MULTICUBE_FREQ
+from lib.robot_consts import I2C_MULTICUBE_FREQ, I2C_NXT_UTZ_BUS
+
+I2C_TIME_TRIGGER_REG = const(256-4)
 
 class I2C_master:
-    def __init__(self, pcf_buttons, general_add=0x41):
-        self.general_add = general_add
+    def __init__(self, pcf_buttons):
         self.pcf_buttons = pcf_buttons
         self.data_received = None
         self.data_sending = None
-        self.start()
-
-    def start(self):
+        self.trigger_timer = Timer(-1)
         self.pcf_buttons.set_pin(I2C_STRONG_PULL_RPIN_BIT, False)
-        self.i2c = I2C(id=0,scl=Pin(UTZ_I2C_SCK_PIN), 
+        self.i2c = I2C(id=I2C_NXT_UTZ_BUS,scl=Pin(UTZ_I2C_SCK_PIN), 
                        sda=Pin(UTZ_I2C_SDA_PIN), freq=I2C_MULTICUBE_FREQ)
 
     def read(self, slave_add, len=1, mem_add=None):
@@ -37,6 +39,23 @@ class I2C_master:
             return False
         return True
     
+    def trigger(self, add, time_us, callback=None):
+        try:
+            time_start = time.ticks_us()
+            self.i2c.writeto_mem(add, I2C_TIME_TRIGGER_REG, time_us.to_bytes(4, 'little'))
+            time_diff = time_us-time.ticks_diff(time.ticks_us(), time_start)
+            print("Time diff: ", time_diff)
+            if callback:
+                if time_diff > 0:
+                    self.trigger_timer.init(freq=1000000/time_diff, mode=Timer.ONE_SHOT, callback=callback)
+                else:
+                    callback(None)
+
+        except Exception as e:
+            return False
+        return True
+    
     def deinit(self):
+        self.trigger_timer.deinit()
         self.i2c = None
-        self.pcf_buttons.set_pin(I2C_STRONG_PULL_RPIN_BIT, True)
\ No newline at end of file
+        self.pcf_buttons.set_pin(I2C_STRONG_PULL_RPIN_BIT, True)
diff --git a/menu_programs/i2c_master.py b/menu_programs/i2c_master.py
index 1df93a4c7d9b149693aa97e0e7658b4159131a06..9d633247f17a5e2ec49334df233b2cd0a689038c 100644
--- a/menu_programs/i2c_master.py
+++ b/menu_programs/i2c_master.py
@@ -9,19 +9,25 @@ ADDRESS = 0x44
 W_ADDRESS = 0x0b
 W_ADDRESS_MAX = 0x1b
 R_ADDRESS = 0x0a
+SLAVE_TRIGGER_TIME = 1000000 # us
+TIMEOUT = 2
 
 
-TIMEOUT = 3
 
 def i2c_master_run(robot):
+
+    def master_trigger_callback(timer):
+        robot.led.toggle()
+
     robot.init_i2c_master()
     write_mem_add = W_ADDRESS
     data_sending = 0
 
     while True:
+        robot.led.off()
         data_received_parsed = 0x5F
         data_received = None
-        debounce = False
+        debounce = True
         timeout = 0
 
         robot.display.fill(0)
@@ -41,6 +47,7 @@ def i2c_master_run(robot):
                 return
         slave_add = all_add[0]
 
+        robot.led.off()
         while timeout < TIMEOUT:
             robot.display.fill(0)
             robot.display.centered_text(f"I2C master", 0, 1)
@@ -52,14 +59,12 @@ def i2c_master_run(robot):
             robot.display.draw_arrow(84, 61, robot.display.DOWN, 1)
             robot.display.show()
 
-            data_written = robot.i2c_master.write(slave_add, (data_sending + ASCII_a).to_bytes(1, 'big'), mem_add=write_mem_add)
+            data_written = robot.i2c_master.write(slave_add, (data_sending + ASCII_a).to_bytes(1, 'little'), mem_add=write_mem_add)
             data_received = robot.i2c_master.read(slave_add, 1, mem_add=R_ADDRESS)
             if data_received and data_received != b'\x00':
-                print("Received: ", data_received)
-                data_received_parsed = int.from_bytes(data_received, 'big')
+                data_received_parsed = int.from_bytes(data_received, 'little')
             elif not data_written:
                 timeout += 1
-            print(data_written, data_received)
 
             buttons = robot.buttons.pressed_since()
             if buttons[Button.LEFT]:
@@ -74,6 +79,9 @@ def i2c_master_run(robot):
                     data_sending += 1
                     data_sending = data_sending % 26
                     debounce = True
+                if buttons[Button.OK]:
+                    robot.i2c_master.trigger(slave_add, SLAVE_TRIGGER_TIME, callback=master_trigger_callback)
+                    debounce = True
                 if buttons[Button.RIGHT]:
                     #robot.buttons.set_pin(I2C_STRONG_PULL_RPIN_BIT, True)
                     write_mem_add += 1
@@ -82,6 +90,6 @@ def i2c_master_run(robot):
                     debounce = True
 
             
-            if not buttons[Button.UP] and not buttons[Button.DOWN] and not buttons[Button.RIGHT] and not buttons[Button.LEFT]:
+            if not buttons[Button.UP] and not buttons[Button.DOWN] and not buttons[Button.RIGHT] and not buttons[Button.LEFT] and not buttons[Button.OK]:
                 debounce = False
             utime.sleep(0.1)
\ No newline at end of file
diff --git a/menu_programs/i2c_slave.py b/menu_programs/i2c_slave.py
index c6d428ea19d80f69a71f697632e9ed2eef8f1694..ab431f03baa55cc0a9b32973941f2c2e732f1c02 100644
--- a/menu_programs/i2c_slave.py
+++ b/menu_programs/i2c_slave.py
@@ -1,25 +1,29 @@
 import utime
-from machine import mem32,mem8,Pin, 
+from machine import mem32,mem8,Pin
+
 from lib.robot_consts import Button
-from lib.hw_defs.pins import UTZ_I2C_SDA_PIN, UTZ_I2C_SCK_PIN, I2C_STRONG_PULL_RPIN
 
 ASCII_a = 97
 ADDRESS = 0x44
 ADDRESS_MAX = 0x50
 W_ADDRESS = 0x0b
 R_ADDRESS = 0x0a
-drdy = 0
 
-def i2c_slave_irq(i2c_slave):
-    global drdy
-    if (i2c_slave.irq().flags() & i2c_slave.RECEIVED):
-        drdy = 1
+drdy = 0
 
 def i2c_slave_run(robot):
     global drdy,irq_c
+
+    def i2c_slave_irq(i2c_slave):
+        global drdy
+        if (i2c_slave.irq().flags() & i2c_slave.RECEIVED):
+            drdy = 1
+        if (i2c_slave.irq().flags() & i2c_slave.TRIGGER):
+            robot.led.toggle()
     
     robot.init_i2c_slave(ADDRESS)
-    robot.i2c_slave.irq(i2c_slave_irq, (robot.i2c_slave.READ | robot.i2c_slave.RECEIVED), False)
+    I2C_SLAVE_IRQ_FLAGS = robot.i2c_slave.TRIGGER | robot.i2c_slave.RECEIVED
+    robot.i2c_slave.irq(i2c_slave_irq, I2C_SLAVE_IRQ_FLAGS, False)
 
     data_received = None
     data_show = 0x5F
@@ -35,6 +39,8 @@ def i2c_slave_run(robot):
     robot.display.text('< exit', 0, 54, 1)
     robot.display.show()
     while True:
+        print(robot.i2c_slave)
+        print(robot.i2c_slave.written_flags())
         if drdy:
             flags = robot.i2c_slave.written_flags()
             for i in range(len(flags)):
@@ -83,7 +89,8 @@ def i2c_slave_run(robot):
                     slave_add = ADDRESS
                 robot.i2c_slave.init(address=slave_add)
                 robot.i2c_slave.write(R_ADDRESS, data_sending + ASCII_a)
-                robot.i2c_slave.irq(i2c_slave_irq, (robot.i2c_slave.READ | robot.i2c_slave.RECEIVED), False)
+                robot.i2c_slave.irq(i2c_slave_irq, I2C_SLAVE_IRQ_FLAGS, False)
+                robot.led.off()
                 debounce = True
         
         if not buttons[Button.UP] and not buttons[Button.DOWN] and not buttons[Button.RIGHT]:
diff --git a/micropython/modules/opencube_brick/oc_i2c_slave.c b/micropython/modules/opencube_brick/oc_i2c_slave.c
index 3b7411ee97c17df01fb2b11aa88868813d07796f..b40a1f1c85d9217b14e58362850ae093fe16b235 100644
--- a/micropython/modules/opencube_brick/oc_i2c_slave.c
+++ b/micropython/modules/opencube_brick/oc_i2c_slave.c
@@ -1,3 +1,9 @@
+/*
+* The OpenCube I2C slave module allows the RP2040 to act as an I2C slave device.
+* The slave can be enabled and disabled, and the I2C address can be set.
+* The slave can also be configured to trigger an IRQ when a specific event occurs.
+* The IRQ can be triggered on read, write, or time trigger events. 
+*/
 #include <string.h>
 #include <py/runtime.h>
 #include <py/mperrno.h>
@@ -5,13 +11,21 @@
 #include <hardware/gpio.h>
 #include <pico/i2c_slave.h>
 #include <shared/runtime/mpirq.h>
+#include "pico/time.h"
 
 #include <opencube_hw.h>
 #include "PCF8575.h"
 
+#define ALARM_ID_INVALID (-1)
+
 #define OC_I2C_SLAVE_READ           _u(0x00000001)
 #define OC_I2C_SLAVE_RECEIVE        _u(0x00000002)
-#define OC_I2C_SLAVE_ALLOWED_FLAGS  (OC_I2C_SLAVE_READ | OC_I2C_SLAVE_RECEIVE)
+#define OC_I2C_SLAVE_TRIGGER        _u(0x00000004)
+#define OC_I2C_SLAVE_ALLOWED_FLAGS  (OC_I2C_SLAVE_READ | OC_I2C_SLAVE_RECEIVE | OC_I2C_SLAVE_TRIGGER)
+
+#define OC_I2C_SLAVE_TIME_TRIGGER_REG_START (256-4)
+#define OC_I2C_SLAVE_TIME_TRIGGER_REG_END (256-1)
+
 
 // The slave implements a 256 byte memory. To write a series of bytes, the master first
 // writes the memory address, followed by the data. The address is automatically incremented
@@ -23,17 +37,20 @@ typedef struct {
     uint64_t mem_read[4];
     uint8_t mem_address;
     bool mem_address_written;
-} oc_i2c_slave_memory;
+} oc_i2c_slave_memory_t;
 
 typedef struct _oc_i2c_slave_obj_t {
     mp_obj_base_t base;
     bool enabled;
+    uint32_t time_trigger;
     uint8_t address;
     uint16_t mp_irq_trigger;   // user IRQ trigger mask
     uint16_t mp_irq_flags;     // user IRQ active IRQ flags
     uint16_t mp_irq_flags_unfinished;     // future IRQ flags
     mp_irq_obj_t *mp_irq_obj;  // user IRQ object
-    oc_i2c_slave_memory context;
+    struct alarm_pool *pool;    // alarm pool for master time trigger
+    alarm_id_t alarm_id;
+    oc_i2c_slave_memory_t context;
 } oc_i2c_slave_obj_t;
 
 const mp_obj_type_t oc_i2c_slave_type;
@@ -45,12 +62,17 @@ static oc_i2c_slave_obj_t oc_i2c_slave_obj = {
     0,
     0,
     0,
+    0,
     NULL,
+    NULL,
+    ALARM_ID_INVALID,
     {{0}},
 };
 
 static bool reserved_addr(uint8_t addr);
 static void oc_i2c_slave_handler(i2c_inst_t *i2c, i2c_slave_event_t event);
+static int64_t alarm_callback(alarm_id_t id, void *user_data);
+static void oc_cancel_alarm(oc_i2c_slave_obj_t *self);
 static mp_obj_t oc_i2c_slave_init_helper(oc_i2c_slave_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
 static mp_irq_obj_t *oc_i2c_slave_irq_helper(oc_i2c_slave_obj_t *self, bool any_args, mp_arg_val_t *args);
 
@@ -63,36 +85,55 @@ static bool reserved_addr(uint8_t addr) {
 // Our handler is called from the I2C ISR, so it must complete quickly. Blocking calls /
 // printing to stdio may interfere with interrupt handling.
 static void oc_i2c_slave_handler(i2c_inst_t *i2c, i2c_slave_event_t event) {
-    
+    oc_i2c_slave_memory_t *context = &oc_i2c_slave_obj.context;
     switch (event) {
     case I2C_SLAVE_RECEIVE: // master has written some data
-        if (!oc_i2c_slave_obj.context.mem_address_written) {
+        if (!context->mem_address_written) {
             // writes always start with the memory address
-            oc_i2c_slave_obj.context.mem_address = i2c_read_byte_raw(i2c);
-            oc_i2c_slave_obj.context.mem_address_written = true;
+            context->mem_address = i2c_read_byte_raw(i2c);
+            context->mem_address_written = true;
         } else {
             // save into memory
-            oc_i2c_slave_obj.context.mem[oc_i2c_slave_obj.context.mem_address] = i2c_read_byte_raw(i2c);
-            // save a flag of the written memory address using bits withou using division uint64_t
-            oc_i2c_slave_obj.context.mem_written[oc_i2c_slave_obj.context.mem_address >> 6] |= 1 << (oc_i2c_slave_obj.context.mem_address & (0xff>>2));
-            oc_i2c_slave_obj.context.mem_address++;
+            context->mem[context->mem_address] = i2c_read_byte_raw(i2c);
+            if (context->mem_address == OC_I2C_SLAVE_TIME_TRIGGER_REG_END) {
+                uint32_t* delay_us = (uint32_t*) &context->mem[OC_I2C_SLAVE_TIME_TRIGGER_REG_START];
+                oc_i2c_slave_obj.time_trigger = *delay_us;
+                if (oc_i2c_slave_obj.mp_irq_trigger & OC_I2C_SLAVE_TRIGGER) {
+                    oc_cancel_alarm(&oc_i2c_slave_obj);
+                    oc_i2c_slave_obj.alarm_id = alarm_pool_add_alarm_in_us(oc_i2c_slave_obj.pool, 
+                        (uint64_t)(*delay_us), alarm_callback, &oc_i2c_slave_obj, true);
+                    if (oc_i2c_slave_obj.alarm_id == -1) {
+                        mp_raise_OSError(MP_ENOMEM);
+                    }
+                }
+                *delay_us = 0;
+            }
+            // save a flag of the written memory address
+            context->mem_written[context->mem_address >> 6] |= 1 << (context->mem_address & (0xff>>2));
+            context->mem_address++;
+            if (context->mem_address == OC_I2C_SLAVE_TIME_TRIGGER_REG_START) {
+                context->mem_address = 0;
+            }
             oc_i2c_slave_obj.mp_irq_flags_unfinished |= OC_I2C_SLAVE_RECEIVE;
         }
         break;
 
     case I2C_SLAVE_REQUEST: // master is requesting data
         // load from memory
-        i2c_write_byte_raw(i2c, oc_i2c_slave_obj.context.mem[oc_i2c_slave_obj.context.mem_address]);
+        i2c_write_byte_raw(i2c, context->mem[context->mem_address]);
         //save a flag of read memory address
-        oc_i2c_slave_obj.context.mem_read[oc_i2c_slave_obj.context.mem_address >> 6] |= 1 << (oc_i2c_slave_obj.context.mem_address & (0xff>>2));
-
-        oc_i2c_slave_obj.context.mem_address++;
+        context->mem_read[context->mem_address >> 6] |= 1 << (context->mem_address & (0xff>>2));
+        context->mem_address++;
+        if (context->mem_address == OC_I2C_SLAVE_TIME_TRIGGER_REG_START) {
+            context->mem_address = 0;
+        }
         oc_i2c_slave_obj.mp_irq_flags_unfinished |= OC_I2C_SLAVE_READ;
         break;
 
     case I2C_SLAVE_FINISH: // master has signalled Stop / Restart
-        //oc_i2c_slave_obj.context.mem_address = 0;
-        oc_i2c_slave_obj.context.mem_address_written = false;
+        // TODO: check osciloscope if I2C master sends stop condition during readfrom_mem
+        //context->mem_address = 0; 
+        context->mem_address_written = false;
         // Check the flags to see if the user handler should be called
         if (oc_i2c_slave_obj.mp_irq_trigger & oc_i2c_slave_obj.mp_irq_flags_unfinished) {
             oc_i2c_slave_obj.mp_irq_flags = oc_i2c_slave_obj.mp_irq_flags_unfinished;
@@ -105,6 +146,22 @@ static void oc_i2c_slave_handler(i2c_inst_t *i2c, i2c_slave_event_t event) {
     }
 }
 
+static int64_t alarm_callback(alarm_id_t id, void *user_data) {
+    oc_i2c_slave_obj_t *oc_i2c_slave = (oc_i2c_slave_obj_t*) user_data;
+    if (oc_i2c_slave->mp_irq_trigger & OC_I2C_SLAVE_TRIGGER) {
+        oc_i2c_slave->mp_irq_flags = OC_I2C_SLAVE_TRIGGER;
+        mp_irq_handler(oc_i2c_slave->mp_irq_obj);
+    }
+    return 0;
+}
+
+static void oc_cancel_alarm(oc_i2c_slave_obj_t *self) {
+    if (self->alarm_id != ALARM_ID_INVALID) {
+        alarm_pool_cancel_alarm(self->pool, self->alarm_id);
+        self->alarm_id = ALARM_ID_INVALID;
+    }
+}
+
 static mp_obj_t oc_i2c_slave_init_helper(oc_i2c_slave_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
     enum { ARG_address };
     static const mp_arg_t allowed_args[] = {
@@ -124,12 +181,15 @@ static mp_obj_t oc_i2c_slave_init_helper(oc_i2c_slave_obj_t *self, size_t n_args
         }
         if (self->enabled) {
             i2c_slave_deinit(UTZ_I2C_BUS);
+            oc_cancel_alarm(self);
         }
         
+        self->pool = alarm_pool_get_default();
+        self->alarm_id = ALARM_ID_INVALID;
         self->mp_irq_obj = NULL;
         self->mp_irq_trigger = 0;
         self->mp_irq_flags = 0;
-        memset(&self->context, 0, sizeof(oc_i2c_slave_memory));
+        memset(&self->context, 0, sizeof(oc_i2c_slave_memory_t));
         self->enabled = true;
         self->address = args[ARG_address].u_int;
 
@@ -176,8 +236,8 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(oc_i2c_slave_init_obj, 1, oc_i2c_slave_init);
 
 static void oc_i2c_slave_print(const mp_print_t *print, mp_obj_t self_in) {
     oc_i2c_slave_obj_t *self = MP_OBJ_TO_PTR(self_in);
-    mp_printf(print, "Open-Cube I2C slave at address %u, flags=%d", 
-        self->address,self->mp_irq_trigger, self->mp_irq_flags);
+    mp_printf(print, "Open-Cube I2C slave at address %u, flags=%d, time=%d, mem_add=%u", 
+        self->address, self->mp_irq_trigger, self->time_trigger, self->context.mem_address);
 }
 
 // I2C_slave.read()
@@ -246,6 +306,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(oc_i2c_slave_irq_obj, 1, oc_i2c_slave_irq);
 // Called on i2c_slave deinit
 static mp_obj_t oc_i2c_slave_deinit(mp_obj_t self_in) {
     oc_i2c_slave_obj_t *self = MP_OBJ_TO_PTR(self_in);
+    oc_cancel_alarm(self);
     i2c_slave_deinit(UTZ_I2C_BUS);
     i2c_deinit(UTZ_I2C_BUS);
     self->enabled = false;
@@ -321,6 +382,7 @@ static const mp_rom_map_elem_t oc_i2c_slave_locals_dict[] = {
 
     { MP_ROM_QSTR(MP_QSTR_RECEIVED), MP_ROM_INT(OC_I2C_SLAVE_RECEIVE) }, \
     { MP_ROM_QSTR(MP_QSTR_READ), MP_ROM_INT(OC_I2C_SLAVE_READ) }, \
+    { MP_ROM_QSTR(MP_QSTR_TRIGGER), MP_ROM_INT(OC_I2C_SLAVE_TRIGGER) }, \
 };
 static MP_DEFINE_CONST_DICT(oc_i2c_slave_locals_dict_obj, oc_i2c_slave_locals_dict);
 
diff --git a/micropython/mpy b/micropython/mpy
index 3823aeb0f14c04084eba6566164d9b7dbd9e7ced..af2770e02c1fcd9e6517223ae81c9a0d089a23e1 160000
--- a/micropython/mpy
+++ b/micropython/mpy
@@ -1 +1 @@
-Subproject commit 3823aeb0f14c04084eba6566164d9b7dbd9e7ced
+Subproject commit af2770e02c1fcd9e6517223ae81c9a0d089a23e1