diff --git a/menu_programs/i2c_master.py b/menu_programs/i2c_master.py
index 65629d66a4709610ab42bffd2788bf73d87a039a..1df93a4c7d9b149693aa97e0e7658b4159131a06 100644
--- a/menu_programs/i2c_master.py
+++ b/menu_programs/i2c_master.py
@@ -6,60 +6,82 @@ from lib.hw_defs.pins import UTZ_I2C_SDA_PIN, UTZ_I2C_SCK_PIN, I2C_STRONG_PULL_R
 
 ASCII_a = 97
 ADDRESS = 0x44
+W_ADDRESS = 0x0b
+W_ADDRESS_MAX = 0x1b
+R_ADDRESS = 0x0a
+
+
+TIMEOUT = 3
 
 def i2c_master_run(robot):
     robot.init_i2c_master()
-    data_received_parsed = 0x5F
-    data_received = None
+    write_mem_add = W_ADDRESS
     data_sending = 0
-    debounce = False
-    connected = False
-    robot.display.fill(0)
-    robot.display.centered_text(f"I2C master", 0, 1)
-    robot.display.text('< exit', 0, 54, 1)
-    robot.display.show()
 
-    utime.sleep(0.2)
-    while ADDRESS not in robot.i2c_master.i2c.scan():
+    while True:
+        data_received_parsed = 0x5F
+        data_received = None
+        debounce = False
+        timeout = 0
+
+        robot.display.fill(0)
         robot.display.centered_text(f"I2C master", 0, 1)
+        robot.display.text('< exit', 0, 54, 1)
         robot.display.centered_text(f"Slave", 18, 1)
         robot.display.centered_text(f"not found", 28, 1)
-        robot.display.text('< exit', 0, 54, 1)
-        robot.display.show()
-        buttons = robot.buttons.pressed_since()
-        if buttons[Button.LEFT]:
-            return
+        
+        robot.buttons.pressed_since()
+        utime.sleep(0.3)
+        all_add = robot.i2c_master.i2c.scan()
+        while not all_add:
+            robot.display.show()
+            all_add = robot.i2c_master.i2c.scan()
+            buttons = robot.buttons.pressed_since()
+            if buttons[Button.LEFT]:
+                return
+        slave_add = all_add[0]
 
-    while True:
-        robot.display.fill(0)
-        robot.display.centered_text(f"I2C master", 0, 1)
-        robot.display.text(f"Sending: {chr(data_sending+ASCII_a)}", 0, 16, 1)
-        robot.display.text(f"Received: {chr(data_received_parsed)}", 0, 26, 1)
-        robot.display.text('< exit      char', 0, 54, 1)
-        robot.display.draw_arrow(74, 56, robot.display.UP, 1)
-        robot.display.draw_arrow(84, 61, robot.display.DOWN, 1)
-        robot.display.show()
+        while timeout < TIMEOUT:
+            robot.display.fill(0)
+            robot.display.centered_text(f"I2C master", 0, 1)
+            robot.display.text(f"Slave add  {slave_add}", 0, 16, 1)
+            robot.display.text(f"Send to    {write_mem_add}: {chr(data_sending+ASCII_a)}", 0, 26, 1)
+            robot.display.text(f"Read from  {R_ADDRESS}: {chr(data_received_parsed)}", 0, 36, 1)
+            robot.display.text('< exit      char', 0, 54, 1)
+            robot.display.draw_arrow(74, 56, robot.display.UP, 1)
+            robot.display.draw_arrow(84, 61, robot.display.DOWN, 1)
+            robot.display.show()
 
-        robot.i2c_master.write(ADDRESS, (data_sending + ASCII_a).to_bytes(1, 'big'), mem_add=1)
-        data_received = robot.i2c_master.read(ADDRESS, 1, mem_add=2)
-        if data_received and data_received != b'\x00':
-           data_received_parsed = int.from_bytes(data_received, 'big')
+            data_written = robot.i2c_master.write(slave_add, (data_sending + ASCII_a).to_bytes(1, 'big'), 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')
+            elif not data_written:
+                timeout += 1
+            print(data_written, data_received)
 
-        buttons = robot.buttons.pressed_since()
-        if buttons[Button.LEFT]:
-            break
-        if not debounce:
-            if buttons[Button.UP]:
-                robot.buttons.set_pin(I2C_STRONG_PULL_RPIN_BIT, True)
-                data_sending -= 1
-                data_sending = data_sending % 26
-                debounce = True
-            if buttons[Button.DOWN]:
-                robot.buttons.set_pin(I2C_STRONG_PULL_RPIN_BIT, False)
-                data_sending += 1
-                data_sending = data_sending % 26
-                debounce = True
-        
-        if not buttons[Button.UP] and not buttons[Button.DOWN]:
-            debounce = False
-        utime.sleep(0.1)
\ No newline at end of file
+            buttons = robot.buttons.pressed_since()
+            if buttons[Button.LEFT]:
+                return
+            if not debounce:
+                if buttons[Button.UP]:
+                    #robot.buttons.set_pin(I2C_STRONG_PULL_RPIN_BIT, False)
+                    data_sending -= 1
+                    data_sending = data_sending % 26
+                    debounce = True
+                if buttons[Button.DOWN]:
+                    data_sending += 1
+                    data_sending = data_sending % 26
+                    debounce = True
+                if buttons[Button.RIGHT]:
+                    #robot.buttons.set_pin(I2C_STRONG_PULL_RPIN_BIT, True)
+                    write_mem_add += 1
+                    if write_mem_add > W_ADDRESS_MAX:
+                        write_mem_add = W_ADDRESS 
+                    debounce = True
+
+            
+            if not buttons[Button.UP] and not buttons[Button.DOWN] and not buttons[Button.RIGHT] and not buttons[Button.LEFT]:
+                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 b8687b3447dd7ccf4794c9c2254bd652aee9f03e..c6d428ea19d80f69a71f697632e9ed2eef8f1694 100644
--- a/menu_programs/i2c_slave.py
+++ b/menu_programs/i2c_slave.py
@@ -1,43 +1,68 @@
 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_run(robot):
+def i2c_slave_irq(i2c_slave):
+    global drdy
+    if (i2c_slave.irq().flags() & i2c_slave.RECEIVED):
+        drdy = 1
 
-    def i2c_slave_irq(i2c_slave):
-        print(i2c_slave)
-        print(robot.i2c_slave.read(1))
+def i2c_slave_run(robot):
+    global drdy,irq_c
     
     robot.init_i2c_slave(ADDRESS)
-    robot.i2c_slave.irq(i2c_slave_irq, robot.i2c_slave.READ | robot.i2c_slave.RECEIVED, False)
+    robot.i2c_slave.irq(i2c_slave_irq, (robot.i2c_slave.READ | robot.i2c_slave.RECEIVED), False)
+
     data_received = None
     data_show = 0x5F
     data_sending = 0
     debounce = False
+    slave_add = ADDRESS
+    received_add = 0
+    
+    robot.i2c_slave.write(R_ADDRESS, data_sending + ASCII_a)
 
     robot.display.fill(0)
     robot.display.centered_text(f"I2C slave", 0, 1)
     robot.display.text('< exit', 0, 54, 1)
     robot.display.show()
     while True:
+        if drdy:
+            flags = robot.i2c_slave.written_flags()
+            for i in range(len(flags)):
+                flag_q = flags[i]
+                if flag_q > 0:
+                    received_add = i * 64
+                    for j in range(64):
+                        if flag_q & 1:
+                            received_add += j
+                            break
+                        flag_q = flag_q >> 1
+                    break
+            drdy = 0
+            
+            data_received = robot.i2c_slave.read(received_add)
+            if data_received:
+                data_show = data_received
+                
         robot.display.fill(0)
         robot.display.centered_text(f"I2C slave", 0, 1)
-        robot.display.text(f"Sending: {chr(data_sending+ASCII_a)}", 0, 16, 1)
-        robot.display.text(f"Received: {chr(data_show)}", 0, 26, 1)
+        robot.display.text(f"Slave add {slave_add}", 0, 16, 1)
+        robot.display.text(f"Send to   {R_ADDRESS}: {chr(data_sending+ASCII_a)}", 0, 26, 1)
+        robot.display.text(f"Read from {received_add}: {chr(data_show)}", 0, 36, 1)
         robot.display.text('< exit      char', 0, 54, 1)
         robot.display.draw_arrow(74, 56, robot.display.UP, 1)
         robot.display.draw_arrow(84, 61, robot.display.DOWN, 1)
         robot.display.show()
-        data_received = robot.i2c_slave.read(1)
-
-        if data_received:
-            print(data_received)
-            data_show = data_received
-
+    
         buttons = robot.buttons.pressed_since()
         if buttons[Button.LEFT]:
             break
@@ -45,14 +70,22 @@ def i2c_slave_run(robot):
             if buttons[Button.UP]:
                 data_sending -= 1
                 data_sending = data_sending % 26
-                robot.i2c_slave.write(2, data_sending + ASCII_a)
+                robot.i2c_slave.write(R_ADDRESS, data_sending + ASCII_a)
                 debounce = True
             if buttons[Button.DOWN]:
                 data_sending += 1
                 data_sending = data_sending % 26
-                robot.i2c_slave.write(2, data_sending + ASCII_a)
+                robot.i2c_slave.write(R_ADDRESS, data_sending + ASCII_a)
+                debounce = True
+            if buttons[Button.RIGHT]:
+                slave_add += 1
+                if slave_add > ADDRESS_MAX:
+                    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)
                 debounce = True
         
-        if not buttons[Button.UP] and not buttons[Button.DOWN]:
+        if not buttons[Button.UP] and not buttons[Button.DOWN] and not buttons[Button.RIGHT]:
             debounce = False
         utime.sleep(0.1)
\ No newline at end of file
diff --git a/micropython/modules/opencube_brick/oc_i2c_slave.c b/micropython/modules/opencube_brick/oc_i2c_slave.c
index 0c86d88c02ec7a771e2fe165eb8faaf07617473c..3b7411ee97c17df01fb2b11aa88868813d07796f 100644
--- a/micropython/modules/opencube_brick/oc_i2c_slave.c
+++ b/micropython/modules/opencube_brick/oc_i2c_slave.c
@@ -19,6 +19,8 @@
 // sequentially from the current memory address.
 typedef struct {
     uint8_t mem[256];
+    uint64_t mem_written[4];
+    uint64_t mem_read[4];
     uint8_t mem_address;
     bool mem_address_written;
 } oc_i2c_slave_memory;
@@ -27,11 +29,11 @@ typedef struct _oc_i2c_slave_obj_t {
     mp_obj_base_t base;
     bool enabled;
     uint8_t address;
-    oc_i2c_slave_memory context;
     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;
 } oc_i2c_slave_obj_t;
 
 const mp_obj_type_t oc_i2c_slave_type;
@@ -40,11 +42,11 @@ static oc_i2c_slave_obj_t oc_i2c_slave_obj = {
     {&oc_i2c_slave_type},
     false,
     0,
-    {{0}},
     0,
     0,
     0,
-    NULL
+    NULL,
+    {{0}},
 };
 
 static bool reserved_addr(uint8_t addr);
@@ -64,13 +66,15 @@ static void oc_i2c_slave_handler(i2c_inst_t *i2c, i2c_slave_event_t event) {
     
     switch (event) {
     case I2C_SLAVE_RECEIVE: // master has written some data
-        if (oc_i2c_slave_obj.context.mem_address_written) {
+        if (!oc_i2c_slave_obj.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;
         } 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++;
             oc_i2c_slave_obj.mp_irq_flags_unfinished |= OC_I2C_SLAVE_RECEIVE;
         }
@@ -79,12 +83,15 @@ static void oc_i2c_slave_handler(i2c_inst_t *i2c, i2c_slave_event_t event) {
     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]);
+        //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++;
         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 = 0;
         oc_i2c_slave_obj.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) {
@@ -118,10 +125,11 @@ 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);
         }
-        memset(&self->context, 0, sizeof(oc_i2c_slave_memory));
+        
         self->mp_irq_obj = NULL;
         self->mp_irq_trigger = 0;
         self->mp_irq_flags = 0;
+        memset(&self->context, 0, sizeof(oc_i2c_slave_memory));
         self->enabled = true;
         self->address = args[ARG_address].u_int;
 
@@ -168,7 +176,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, irq=%d", self->address,self->mp_irq_trigger);
+    mp_printf(print, "Open-Cube I2C slave at address %u, flags=%d", 
+        self->address,self->mp_irq_trigger, self->mp_irq_flags);
 }
 
 // I2C_slave.read()
@@ -176,6 +185,8 @@ static mp_obj_t oc_i2c_slave_read(mp_obj_t self_in, mp_obj_t addr) {
     oc_i2c_slave_obj_t *self = MP_OBJ_TO_PTR(self_in);
     if (mp_obj_is_int(addr)) {
         uint8_t address = mp_obj_get_int(addr);
+        // clear the flag of write memory address
+        self->context.mem_written[address >> 6] &= ~(1 << (address & (0xff>>2)));
         return mp_obj_new_int(self->context.mem[address]);
     }
     return mp_const_none;
@@ -188,12 +199,40 @@ static mp_obj_t oc_i2c_slave_write(mp_obj_t self_in, mp_obj_t addr, mp_obj_t dat
     if (mp_obj_is_int(addr) && mp_obj_is_int(data)) {
         uint8_t address = mp_obj_get_int(addr);
         uint8_t value = mp_obj_get_int(data);
+        // clear the flag of read memory address
+        self->context.mem_read[address >> 6] &= ~(1 << (address & (0xff>>2)));
         self->context.mem[address] = value;
     }
     return mp_const_none;
 }
 static MP_DEFINE_CONST_FUN_OBJ_3(oc_i2c_slave_write_obj, oc_i2c_slave_write);
 
+// I2C_slave.read_flags()
+static mp_obj_t oc_i2c_slave_read_flags(mp_obj_t self_in) {
+    oc_i2c_slave_obj_t *self = MP_OBJ_TO_PTR(self_in);
+     mp_obj_t tuple[4] = {
+            tuple[0] = mp_obj_new_int_from_ull(self->context.mem_read[0]),
+            tuple[1] = mp_obj_new_int_from_ull(self->context.mem_read[1]),
+            tuple[2] = mp_obj_new_int_from_ull(self->context.mem_read[2]),
+            tuple[3] = mp_obj_new_int_from_ull(self->context.mem_read[3]),
+        };
+    return mp_obj_new_tuple(4, tuple);
+}
+static MP_DEFINE_CONST_FUN_OBJ_1(oc_i2c_slave_read_flags_obj, oc_i2c_slave_read_flags);
+
+// I2C_slave.written_flags()
+static mp_obj_t oc_i2c_slave_written_flags(mp_obj_t self_in) {
+    oc_i2c_slave_obj_t *self = MP_OBJ_TO_PTR(self_in);
+    mp_obj_t tuple[4] = {
+            tuple[0] = mp_obj_new_int_from_ull(self->context.mem_written[0]),
+            tuple[1] = mp_obj_new_int_from_ull(self->context.mem_written[1]),
+            tuple[2] = mp_obj_new_int_from_ull(self->context.mem_written[2]),
+            tuple[3] = mp_obj_new_int_from_ull(self->context.mem_written[3]),
+        };
+    return mp_obj_new_tuple(4, tuple);
+}
+static MP_DEFINE_CONST_FUN_OBJ_1(oc_i2c_slave_written_flags_obj, oc_i2c_slave_written_flags);
+
 // I2C_slave.irq()
 static mp_obj_t oc_i2c_slave_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
     mp_arg_val_t args[MP_IRQ_ARG_INIT_NUM_ARGS];
@@ -210,8 +249,10 @@ static mp_obj_t oc_i2c_slave_deinit(mp_obj_t self_in) {
     i2c_slave_deinit(UTZ_I2C_BUS);
     i2c_deinit(UTZ_I2C_BUS);
     self->enabled = false;
+    MP_STATE_PORT(oc_i2c_slave_irq_obj) = NULL;
     self->mp_irq_obj = NULL;
     self->mp_irq_trigger = 0;
+    
     return mp_const_none;
 }
 static MP_DEFINE_CONST_FUN_OBJ_1(oc_i2c_slave_deinit_obj, oc_i2c_slave_deinit);
@@ -241,6 +282,7 @@ static mp_irq_obj_t *oc_i2c_slave_irq_helper(oc_i2c_slave_obj_t *self, bool any_
     if (self->mp_irq_obj == NULL) {
         self->mp_irq_trigger = 0;
         self->mp_irq_obj = mp_irq_new(&oc_i2c_slave_irq_methods, MP_OBJ_FROM_PTR(self));
+        MP_STATE_PORT(oc_i2c_slave_irq_obj) = self->mp_irq_obj;
     }
 
     if (any_args) {
@@ -270,6 +312,8 @@ static mp_irq_obj_t *oc_i2c_slave_irq_helper(oc_i2c_slave_obj_t *self, bool any_
 static const mp_rom_map_elem_t oc_i2c_slave_locals_dict[] = {
     { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&oc_i2c_slave_read_obj) },
     { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&oc_i2c_slave_write_obj) },
+    { MP_ROM_QSTR(MP_QSTR_read_flags), MP_ROM_PTR(&oc_i2c_slave_read_flags_obj) },
+    { MP_ROM_QSTR(MP_QSTR_written_flags), MP_ROM_PTR(&oc_i2c_slave_written_flags_obj) },
     { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&oc_i2c_slave_init_obj) },
     { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&oc_i2c_slave_irq_obj) },
     { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&oc_i2c_slave_deinit_obj) },
@@ -288,4 +332,6 @@ MP_DEFINE_CONST_OBJ_TYPE(
     make_new, &oc_i2c_slave_make_new,
     locals_dict, &oc_i2c_slave_locals_dict_obj,
     print, &oc_i2c_slave_print
-);
\ No newline at end of file
+);
+
+MP_REGISTER_ROOT_POINTER(void *oc_i2c_slave_irq_obj);
\ No newline at end of file
diff --git a/micropython/mpy b/micropython/mpy
index af2770e02c1fcd9e6517223ae81c9a0d089a23e1..3823aeb0f14c04084eba6566164d9b7dbd9e7ced 160000
--- a/micropython/mpy
+++ b/micropython/mpy
@@ -1 +1 @@
-Subproject commit af2770e02c1fcd9e6517223ae81c9a0d089a23e1
+Subproject commit 3823aeb0f14c04084eba6566164d9b7dbd9e7ced