diff --git a/dynamixel_base/Makefile b/dynamixel_base/Makefile
index fef5dc81ca91d8ee5c4e03d28c6f842ab9f5af02..4f63efe978f1c1ef546c38a513cfb7ebcbe26bb3 100755
--- a/dynamixel_base/Makefile
+++ b/dynamixel_base/Makefile
@@ -14,8 +14,11 @@ COMPILE_OPTS_M3 = -mfloat-abi=softfp -mcpu=cortex-m3
 COMM_PATH = ../comm
 UTILS_PATH = ../utils
 MEMORY_PATH = ../memory
+SCHEDULER_PATH = ../scheduler
 
-INCLUDE_DIRS = -I./include/ -I$(COMM_PATH)/include -I$(UTILS_PATH)/include -I$(MEMORY_PATH)/include
+INCLUDE_DIRS = -I./include/ -I$(COMM_PATH)/include -I$(UTILS_PATH)/include -I$(MEMORY_PATH)/include -I$(SCHEDULER_PATH)/include
+
+MACROS = -DMAX_DYN_SLAVE_TX_BUFFER_LEN=256 -DMAX_DYN_SLAVE_RX_BUFFER_LEN=256 -DMAX_DYN_SLAVE_REG_BUFFER_LEN=256 -DMAX_NUM_SLAVE_DEVICES=4 -DMAX_DYN_MASTER_TX_BUFFER_LEN=256 -DMAX_DYN_MASTER_RX_BUFFER_LEN=256
 
 DOC_DIR = ./doc
 
@@ -53,13 +56,13 @@ DYNAMIXEL_M3_OBJS = $(patsubst %,$(DYNAMIXEL_M3_OBJ_DIR)%,$(DYNAMIXEL_M3_OBJS_TM
 
 all: $(DYNAMIXEL_OUT_M4_FPU) $(DYNAMIXEL_OUT_M0) $(DYNAMIXEL_OUT_M0plus) $(DYNAMIXEL_OUT_M3)
 $(DYNAMIXEL_M4_FPU_OBJ_DIR)%.o: $(SRC_DIR)%.c
-	$(CC) -c $(CFLAGS) $(COMPILE_OPTS_M4_FPU) -o $@ $<
+	$(CC) -c $(CFLAGS) $(MACROS) $(COMPILE_OPTS_M4_FPU) -o $@ $<
 $(DYNAMIXEL_M0_OBJ_DIR)%.o: $(SRC_DIR)%.c
-	$(CC) -c $(CFLAGS) $(COMPILE_OPTS_M0) -o $@ $<
+	$(CC) -c $(CFLAGS) $(MACROS) $(COMPILE_OPTS_M0) -o $@ $<
 $(DYNAMIXEL_M0plus_OBJ_DIR)%.o: $(SRC_DIR)%.c
-	$(CC) -c $(CFLAGS) $(COMPILE_OPTS_M0plus) -o $@ $<
+	$(CC) -c $(CFLAGS) $(MACROS) $(COMPILE_OPTS_M0plus) -o $@ $<
 $(DYNAMIXEL_M3_OBJ_DIR)%.o: $(SRC_DIR)%.c
-	$(CC) -c $(CFLAGS) $(COMPILE_OPTS_M3) -o $@ $<
+	$(CC) -c $(CFLAGS) $(MACROS) $(COMPILE_OPTS_M3) -o $@ $<
 mkdir_build: 
 	mkdir -p build/m4_fpu
 	mkdir -p build/m0
diff --git a/dynamixel_base/include/dynamixel_master.h b/dynamixel_base/include/dynamixel_master.h
index 7da7c90be7873723a8b9b27c5db894b792ad787e..8ee13ea4ea16273afe5b31e7ec1b20ef404d227b 100644
--- a/dynamixel_base/include/dynamixel_master.h
+++ b/dynamixel_base/include/dynamixel_master.h
@@ -6,11 +6,11 @@
 #include "dynamixel2.h"
 
 #ifndef MAX_DYN_MASTER_TX_BUFFER_LEN
-  #define       MAX_DYN_MASTER_TX_BUFFER_LEN      256
+  #error "Please, specify the maximum TX buffer length with the MAX_DYN_MASTER_TX_BUFFER_LEN macro"
 #endif
 
 #ifndef MAX_DYN_MASTER_RX_BUFFER_LEN
-  #define       MAX_DYN_MASTER_RX_BUFFER_LEN      256
+  #error "Please, specify the maximum RX buffer length with the MAX_DYN_MASTER_TX_BUFFER_LEN macro"
 #endif
 
 /**
diff --git a/dynamixel_base/include/dynamixel_slave.h b/dynamixel_base/include/dynamixel_slave.h
index 37902b616fd26d24244cd6cfbba0adf54164e5d6..64f8d751f22e4f766651c3b764d9c2e19a78a6d8 100644
--- a/dynamixel_base/include/dynamixel_slave.h
+++ b/dynamixel_base/include/dynamixel_slave.h
@@ -4,52 +4,47 @@
 #include "comm.h"
 #include "dynamixel.h"
 #include "dynamixel2.h"
-#include "dynamixel_slave_registers.h"
-#include "ram.h"
+#include "scheduler.h"
+#include "dynamixel_slave_device.h"
 
 #ifndef MAX_DYN_SLAVE_TX_BUFFER_LEN
-  #define       MAX_DYN_SLAVE_TX_BUFFER_LEN      256
+  #error "Please, specify the maximum TX buffer length with the MAX_DYN_SLAVE_TX_BUFFER_LEN macro"
 #endif
 
 #ifndef MAX_DYN_SLAVE_RX_BUFFER_LEN
-  #define       MAX_DYN_SLAVE_RX_BUFFER_LEN      256
+  #error "Please, specify the maximum RX buffer length with the MAX_DYN_SLAVE_RX_BUFFER_LEN macro"
 #endif
 
-#ifndef MAX_DYN_SLAVE_REG_BUFFER_LEN
-  #define       MAX_DYN_SLAVE_REG_BUFFER_LEN     256
+#ifndef MAX_NUM_SLAVE_DEVICES
+  #error "Please, specify the maximum number of slave devices with the MAX_NUM_SLAVE_DEVICES macro"
 #endif
 
 /**
  * \brief
  *
  */
-typedef struct
+typedef struct TDynamixelSlave
 {
   /**
    * \brief
    *
    */
-  TComm *comm_dev;
-  /**
-   * \brief
-   *
-   */
-  TDynVersion version;
+  TScheduler *scheduler;
   /**
    * \brief
    *
    */
-  unsigned char address;
+  sched_channel_t sch_channel;
   /**
    * \brief
    *
    */
-  unsigned char return_delay;
+  TComm *comm_dev;
   /**
    * \brief
    *
    */
-  return_level_t return_level;
+  TDynVersion version;
   /**
    * \brief
    *
@@ -84,47 +79,12 @@ typedef struct
    * \brief
    *
    */
-  unsigned short int reg_address;
-  /**
-   * \brief
-   *
-   */
-  unsigned short int reg_length;
-  /**
-   * \brief
-   *
-   */
-  unsigned char reg_buffer[MAX_DYN_SLAVE_REG_BUFFER_LEN];
-  /**
-   * \brief
-   *
-   */
-  unsigned short int sync_bulk_address;
-  /**
-   * \brief
-   *
-   */
-  unsigned short int sync_bulk_length;
+  unsigned char num_slave_devices;
   /**
    * \brief
    *
    */
-  unsigned char sync_bulk_prev_id;
-  /**
-   * \brief
-   *
-   */
-  unsigned char sync_read_pending;
-  /**
-   * \brief
-   *
-   */
-  unsigned char bulk_read_pending;
-  /**
-   * \brief
-   *
-   */
-  TMemModule mem_module;
+  TDynamixelSlaveDevice *slave_devices[MAX_NUM_SLAVE_DEVICES];
   /**
    * \brief
    *
@@ -140,26 +100,6 @@ typedef struct
    *
    */
   void (*set_baudrate)(TComm *comm_dev,unsigned int baudrate);
-  /**
-   * \brief
-   *
-   */
-  void (*on_ping)(void);
-  /**
-   * \brief
-   *
-   */
-  unsigned char (*on_read)(unsigned short int address,unsigned short int length,unsigned char *data);
-  /**
-   * \brief
-   *
-   */
-  unsigned char (*on_write)(unsigned short int address,unsigned short int length,unsigned char *data);
-  /**
-   * \brief
-   *
-   */
-  unsigned char (*on_reset)(void);
   /**
    * \brief
    *
@@ -172,57 +112,36 @@ typedef struct
  * \brief
  *
  */
-unsigned char dyn_slave_init(TDynamixelSlave *slave,TMemory *memory,TComm *dev,unsigned char address,TDynVersion version);
+unsigned char dyn_slave_init(TDynamixelSlave *slave,TComm *dev,TScheduler *scheduler,sched_channel_t ch,TDynVersion version);
 /**
  * \brief
  *
  */
-void dyn_slave_set_baudrate(TDynamixelSlave *slave,unsigned int baudrate);
+unsigned char dyn_slave_add_device(TDynamixelSlave *slave, TDynamixelSlaveDevice *device);
 /**
  * \brief
  *
  */
-inline void dyn_slave_set_rx_timeout(TDynamixelSlave *slave,unsigned short int timeout_ms);
-/**
- * \brief
- *
- */
-inline void dyn_slave_set_address(TDynamixelSlave *slave,unsigned char address);
-/**
- * \brief
- *
- */
-inline unsigned char dyn_slave_get_address(TDynamixelSlave *slave);
-/**
- * \brief
- *
- */
-inline void dyn_slave_set_return_delay(TDynamixelSlave *slave,unsigned char delay);
-/**
- * \brief
- *
- */
-inline unsigned char dyn_slave_get_return_delay(TDynamixelSlave *slave);
+void dyn_slave_set_baudrate(TDynamixelSlave *slave,unsigned int baudrate);
 /**
  * \brief
  *
  */
-inline void dyn_slave_set_return_level(TDynamixelSlave *slave,return_level_t level);
+inline void dyn_slave_set_rx_timeout(TDynamixelSlave *slave,unsigned short int timeout_ms);
 /**
  * \brief
  *
  */
-inline return_level_t dyn_slave_get_return_level(TDynamixelSlave *slave);
+inline TDynVersion dyn_slave_get_version(TDynamixelSlave *slave);
 /**
  * \brief
  *
  */
-inline TDynVersion dyn_slave_get_version(TDynamixelSlave *slave);
+void dyn_slave_start(TDynamixelSlave *slave);
 /**
  * \brief
  *
  */
-void dyn_slave_loop(TDynamixelSlave *slave);
-
+void dyn_slave_stop(TDynamixelSlave *slave);
 
 #endif
diff --git a/dynamixel_base/include/dynamixel_slave_device.h b/dynamixel_base/include/dynamixel_slave_device.h
new file mode 100644
index 0000000000000000000000000000000000000000..c43300b02604378f4a2699ffc3c2d29a0989346c
--- /dev/null
+++ b/dynamixel_base/include/dynamixel_slave_device.h
@@ -0,0 +1,173 @@
+#ifndef _DYNAMIXEL_SLAVE_DEVICE_H
+#define _DYNAMIXEL_SLAVE_DEVICE_H
+
+#include "dynamixel_slave_registers.h"
+#include "dynamixel.h"
+#include "dynamixel2.h"
+#include "ram.h"
+
+#ifndef MAX_DYN_SLAVE_REG_BUFFER_LEN
+  #error "Please, specify the maximum registered buffer length with the MAX_DYN_SLAVE_REG_BUFFER_LEN macro"
+#endif
+
+/**
+ * \brief
+ *
+ */
+typedef struct 
+{
+  /**
+   * \brief
+   *
+   */
+  struct TDynamixelSlave *slave;
+  /**
+   * \brief
+   *
+   */
+  unsigned char address;
+  /**
+   * \brief
+   *
+   */
+  unsigned short int eeprom_base_address1;
+  /**
+   * \brief
+   *
+   */
+  unsigned short int eeprom_base_address2;
+  /**
+   * \brief
+   *
+   */
+  unsigned char return_delay;
+  /**
+   * \brief
+   *
+   */
+  return_level_t return_level;
+  /**
+   * \brief
+   *
+   */
+  unsigned short int reg_address;
+  /**
+   * \brief
+   *
+   */
+  unsigned short int reg_length;
+  /**
+   * \brief
+   *
+   */
+  unsigned char reg_buffer[MAX_DYN_SLAVE_REG_BUFFER_LEN];
+  /**
+   * \brief
+   *
+   */
+  unsigned short int sync_bulk_address;
+  /**
+   * \brief
+   *
+   */
+  unsigned short int sync_bulk_length;
+  /**
+   * \brief
+   *
+   */
+  unsigned char sync_bulk_prev_id;
+  /**
+   * \brief
+   *
+   */
+  unsigned char sync_read_pending;
+  /**
+   * \brief
+   *
+   */
+  unsigned char bulk_read_pending;
+  /**
+   * \brief
+   *
+   */
+  TMemory memory;
+  /**
+   * \brief
+   *
+   */
+  TMemModule mem_module;
+  /**
+   * \brief
+   *
+   */
+  void (*on_ping)(void);
+  /**
+   * \brief
+   *
+   */
+  unsigned char (*on_read)(unsigned short int address,unsigned short int length,unsigned char *data);
+  /**
+   * \brief
+   *
+   */
+  unsigned char (*on_write)(unsigned short int address,unsigned short int length,unsigned char *data);
+  /**
+   * \brief
+   *
+   */
+  unsigned char (*on_reset)(void);
+}TDynamixelSlaveDevice;
+
+/* public functions */
+/**
+ * \brief
+ *
+ */
+unsigned char dyn_slave_device_init(TDynamixelSlaveDevice *device,unsigned char address,unsigned char eeprom_base_address1,unsigned char eeprom_base_address2);
+/**
+ * \brief
+ *
+ */
+inline void dyn_slave_device_set_address(TDynamixelSlaveDevice *device,unsigned char address);
+/**
+ * \brief
+ *
+ */
+inline unsigned char dyn_slave_device_get_address(TDynamixelSlaveDevice *device);
+/**
+ * \brief
+ *
+ */
+inline void dyn_slave_device_set_return_delay(TDynamixelSlaveDevice *device,unsigned char delay);
+/**
+ * \brief
+ *
+ */
+inline unsigned char dyn_slave_device_get_return_delay(TDynamixelSlaveDevice *device);
+/**
+ * \brief
+ *
+ */
+inline void dyn_slave_device_set_return_level(TDynamixelSlaveDevice *device,return_level_t level);
+/**
+ * \brief
+ *
+ */
+inline return_level_t dyn_slave_device_get_return_level(TDynamixelSlaveDevice *device);
+/**
+ * \brief
+ *
+ */
+unsigned char dyn_v1_slave_loop(TDynamixelSlaveDevice *device,unsigned char *rx_buffer,unsigned char *error,unsigned char *length, unsigned char *data);
+/**
+ * \brief
+ *
+ */
+unsigned char dyn_v2_slave_loop(TDynamixelSlaveDevice *device,unsigned char *rx_buffer,unsigned char *error,unsigned short int *length, unsigned char *data);
+/**
+ * \brief
+ *
+ */
+inline TMemory *dyn_slave_device_get_memory(TDynamixelSlaveDevice *device);
+
+#endif
diff --git a/dynamixel_base/include/dynamixel_slave_registers.h b/dynamixel_base/include/dynamixel_slave_registers.h
index 8a3a01bd147a1913bc031aba1c32c97a49960954..46cef2b79342753136e2514c7ce41c79383306a1 100644
--- a/dynamixel_base/include/dynamixel_slave_registers.h
+++ b/dynamixel_base/include/dynamixel_slave_registers.h
@@ -1,45 +1,27 @@
 #ifndef _DYNAMIXEL_SLAVE_REGISTERS_H
 #define _DYNAMIXEL_SLAVE_REGISTERS_H
 
-#ifndef EEPROM_DYN_SLAVE_BASE_ADDRESS1
-  #define EEPROM_DYN_SLAVE_BASE_ADDRESS1      ((unsigned short int)0x0000)
-#endif
-
 #define EEPROM_DYN_SLAVE_LENGTH1              6 
 
-#ifndef EEPROM_DYN_SLAVE_BASE_ADDRESS2
-  #define EEPROM_DYN_SLAVE_BASE_ADDRESS2      ((unsigned short int)0x0000)
-#endif
-
 #define EEPROM_DYN_SLAVE_LENGTH2              1
 
-#define DEVICE_MODEL                          (EEPROM_DYN_SLAVE_BASE_ADDRESS1)
-#define FIRMWARE_VERSION                      (EEPROM_DYN_SLAVE_BASE_ADDRESS1+2)
-#define DEVICE_ID                             (EEPROM_DYN_SLAVE_BASE_ADDRESS1+3)
-#define BAUDRATE                              (EEPROM_DYN_SLAVE_BASE_ADDRESS1+4)
-#define RETURN_DELAY                          (EEPROM_DYN_SLAVE_BASE_ADDRESS1+5)
+#define DEVICE_MODEL                          0 
+#define FIRMWARE_VERSION                      2
+#define DEVICE_ID                             3
+#define BAUDRATE                              4
+#define RETURN_DELAY                          5
 
-#define RETURN_LEVEL                          (EEPROM_DYN_SLAVE_BASE_ADDRESS2)
+#define RETURN_LEVEL                          0
 
-#ifndef DEFAULT_DEVICE_MODEL
-  #define DEFAULT_DEVICE_MODEL                0x7300
-#endif
-#ifndef DEFAULT_FIRMWARE_VERSION
-  #define DEFAULT_FIRMWARE_VERSION            0x0001
-#endif
-#ifndef DEFAULT_DEVICE_ID
-  #define DEFAULT_DEVICE_ID                   0x0001
-#endif
-#ifndef DEFAULT_BAUDRATE
-  #define DEFAULT_BAUDRATE                    0x0010
-#endif
-#ifndef DEFAULT_RETURN_DELAY
-  #define DEFAULT_RETURN_DELAY                0x0000
-#endif
+#define dyn_slave_control_eeprom_data(name,section_name,base_address1,base_address2,DEFAULT_DEVICE_MODEL,DEFAULT_FIRMWARE_VERSION,DEFAULT_DEVICE_ID,DEFAULT_BAUDRATE,DEFAULT_RETURN_DELAY,DEFAULT_RETURN_LEVEL) \
+unsigned short int name##_eeprom_data[] __attribute__ ((section (section_name)))={DEFAULT_DEVICE_MODEL&0x00FF,(DEFAULT_DEVICE_ID<<8) + base_address1+DEVICE_MODEL, \
+                                                                                  (DEFAULT_DEVICE_MODEL>>8)&0x00FF,(DEFAULT_DEVICE_ID<<8) + base_address1+DEVICE_MODEL+1, \
+                                                                                  DEFAULT_FIRMWARE_VERSION,(DEFAULT_DEVICE_ID<<8) + base_address1+FIRMWARE_VERSION, \
+                                                                                  DEFAULT_DEVICE_ID,(DEFAULT_DEVICE_ID<<8) + base_address1+DEVICE_ID, \
+                                                                                  DEFAULT_BAUDRATE,(DEFAULT_DEVICE_ID<<8) + base_address1+BAUDRATE, \
+                                                                                  DEFAULT_RETURN_DELAY,(DEFAULT_DEVICE_ID<<8) + base_address1+RETURN_DELAY, \
+                                                                                  DEFAULT_RETURN_LEVEL,(DEFAULT_DEVICE_ID<<8) + base_address2+RETURN_LEVEL};
 
-#ifndef DEFAULT_RETURN_LEVEL
-  #define DEFAULT_RETURN_LEVEL                0x0002
-#endif
 
 #endif
 
diff --git a/dynamixel_base/src/dynamixel_slave.c b/dynamixel_base/src/dynamixel_slave.c
index e1818981fa23d44bc06a1f2ae9d8159010b2acab..6afdbe8076451d1cd205c32119123762182443af 100644
--- a/dynamixel_base/src/dynamixel_slave.c
+++ b/dynamixel_base/src/dynamixel_slave.c
@@ -1,44 +1,6 @@
 #include "dynamixel_slave.h"
 
-/* EEPROM data */
-unsigned short int dyn_slave_eeprom_data[] __attribute__ ((section (".eeprom")))={DEFAULT_DEVICE_MODEL&0x00FF,DEVICE_MODEL,
-                                                                                  (DEFAULT_DEVICE_MODEL>>8)&0x00FF,DEVICE_MODEL+1,
-                                                                                  DEFAULT_FIRMWARE_VERSION,FIRMWARE_VERSION,
-                                                                                  DEFAULT_DEVICE_ID,DEVICE_ID,
-                                                                                  DEFAULT_BAUDRATE,BAUDRATE,
-                                                                                  DEFAULT_RETURN_DELAY,RETURN_DELAY,
-                                                                                  DEFAULT_RETURN_LEVEL,RETURN_LEVEL};
-
-/* private functions */
-void dyn_slave_write_cmd(TDynamixelSlave *dyn_slave,unsigned short int address,unsigned short int length,unsigned char *data)
-{
-  if(ram_in_range(DEVICE_ID,address,length))
-  {
-    dyn_slave_set_address(dyn_slave,data[DEVICE_ID-address]);
-    ram_data[DEVICE_ID]=data[DEVICE_ID-address];
-  }
-  if(ram_in_range(BAUDRATE,address,length))
-  {
-    dyn_slave_set_baudrate(dyn_slave,2000000/(data[BAUDRATE-address]+1));
-    ram_data[BAUDRATE]=data[BAUDRATE-address];
-  }
-  if(ram_in_range(RETURN_DELAY,address,length))
-  {
-    dyn_slave_set_return_delay(dyn_slave,data[RETURN_DELAY-address]);
-    ram_data[RETURN_DELAY]=data[RETURN_DELAY-address];
-  }
-  if(ram_in_range(RETURN_LEVEL,address,length))
-  {
-    dyn_slave_set_return_level(dyn_slave,data[RETURN_LEVEL-address]);
-    ram_data[RETURN_LEVEL]=data[RETURN_LEVEL-address];
-  }
-}
-
-void dyn_slave_read_cmd(TDynamixelSlave *dyn_slave,unsigned short int address,unsigned short int length,unsigned char *data)
-{
-  ram_read_table(address,length,data);
-}
-
+// communication functions
 unsigned char dyn_slave_irq_receive_cb(TDynamixelSlave *dyn_slave,unsigned char byte)
 {
   if(dyn_slave!=0x00000000)
@@ -152,44 +114,24 @@ void dummy_dyn_slave_set_baudrate(TComm *comm_dev,unsigned int baudrate)
 
 }
 
-void dummy_dyn_slave_on_ping(void)
-{
-
-}
-
-unsigned char dummy_dyn_slave_on_read(unsigned short int address,unsigned short int length,unsigned char *data)
-{
-  return DYN_SUCCESS;
-}
-
-unsigned char dummy_dyn_slave_on_write(unsigned short int address,unsigned short int length,unsigned char *data)
-{
-  return DYN_SUCCESS;
-}
-
-unsigned char dummy_dyn_slave_on_reset(void)
-{
-  return DYN_SUCCESS;
-}
-
 unsigned char dummy_dyn_slave_on_relay(TDynVersion version,unsigned char *inst_pkt,unsigned char *status_pkt)
 {
   return DYN_NO_DEVICE;
 }
 
-void dyn_slave_send_status_packet(TDynamixelSlave *slave,unsigned char error,unsigned short int length, unsigned char *data)
+void dyn_slave_send_status_packet(TDynamixelSlave *slave,unsigned char address,unsigned char error,unsigned short int length, unsigned char *data,unsigned char return_delay)
 {
   if(slave!=0x00000000)
   {
     // wait until the previous transmission has ended (if any)
     while(comm_is_send_done(slave->comm_dev)==COMM_BUSY);
-    if(slave->return_delay>0)
+    if(return_delay>0)
       if(slave->comm_dev->time!=0x00000000)
-        time_delay_us(slave->comm_dev->time,slave->return_delay<<1);
+        time_delay_us(slave->comm_dev->time,return_delay<<1);
     if(slave->version==DYN_VER1)
     {
       // create the status packet
-      dyn_init_status_packet(slave->tx_buffer,slave->address,error,length,data);
+      dyn_init_status_packet(slave->tx_buffer,address,error,length,data);
       // set the tx mode, if necessary
       slave->set_tx_mode();
       // start transmission by DMA
@@ -198,7 +140,7 @@ void dyn_slave_send_status_packet(TDynamixelSlave *slave,unsigned char error,uns
     else
     {
       // create the status packet
-      dyn2_init_status_packet(slave->tx_buffer,slave->address,error,length,data);
+      dyn2_init_status_packet(slave->tx_buffer,address,error,length,data);
       // set the tx mode, if necessary
       slave->set_tx_mode();
       // start transmission by DMA
@@ -207,272 +149,46 @@ void dyn_slave_send_status_packet(TDynamixelSlave *slave,unsigned char error,uns
   }
 }
 
-void dyn_v1_slave_loop(TDynamixelSlave *slave)
-{
-  static unsigned char data[MAX_DYN_SLAVE_TX_BUFFER_LEN],error,length,address,prev_id,id;
-
-  if(slave!=0x000000000)
-  {
-    id=dyn_get_id(slave->rx_buffer);
-    if(id==slave->address || id==DYN_BROADCAST_ID)// the packet is addressed to this device or it is a broadcast
-    {
-      // check the packet checksum
-      if(dyn_check_checksum(slave->rx_buffer)==0xFF)// the incomming packet is okay
-      {
-        // process the packet
-        switch(dyn_get_instruction(slave->rx_buffer))
-        {
-          case DYN_PING: slave->on_ping();
-                         if(id!=DYN_BROADCAST_ID)
-                           dyn_slave_send_status_packet(slave,DYN_NO_ERROR,0,data);
-                         break;
-          case DYN_READ: error=slave->on_read(dyn_get_read_address(slave->rx_buffer),dyn_get_read_length(slave->rx_buffer),data);
-                         if(slave->return_level!=no_return && id!=DYN_BROADCAST_ID)
-                         {
-                           if(error==DYN_NO_ERROR)
-                             dyn_slave_send_status_packet(slave,DYN_NO_ERROR,dyn_get_read_length(slave->rx_buffer),data);
-                           else
-                             dyn_slave_send_status_packet(slave,DYN_INST_ERROR,0,data);
-                         }
-                         break;
-          case DYN_WRITE: length=dyn_get_write_data(slave->rx_buffer,data);
-                          error=slave->on_write(dyn_get_write_address(slave->rx_buffer),length,data);
-                          if(slave->return_level==return_all && id!=DYN_BROADCAST_ID)
-                          {
-                            if(error==DYN_NO_ERROR)
-                              dyn_slave_send_status_packet(slave,DYN_NO_ERROR,0,data);
-                            else
-                              dyn_slave_send_status_packet(slave,DYN_INST_ERROR,0,data);
-                          }
-                          break;
-          case DYN_REG_WRITE: slave->reg_length=dyn_get_reg_write_data(slave->rx_buffer,slave->reg_buffer);
-                              slave->reg_address=dyn_get_reg_write_address(slave->rx_buffer);
-                              if(slave->return_level==return_all && id!=DYN_BROADCAST_ID)
-                                dyn_slave_send_status_packet(slave,DYN_NO_ERROR,0,data);
-                              break;
-          case DYN_ACTION: if(slave->reg_address!=0xFFFF)
-                           {
-                             error=slave->on_write(slave->reg_address,slave->reg_length,slave->reg_buffer);
-                             slave->reg_address=0xFFFF;
-                           }
-                           else
-                             if(slave->return_level==return_all && id!=DYN_BROADCAST_ID)
-                               dyn_slave_send_status_packet(slave,DYN_INST_ERROR,0,data);
-                           break;
-          case DYN_RESET:
-                          break;
-          case DYN_SYNC_READ: dyn_slave_send_status_packet(slave,DYN_INST_ERROR,0,data);
-                              break;
-          case DYN_SYNC_WRITE: if(dyn_sync_write_id_present(slave->rx_buffer,slave->address,&address,&length,data))// the device is addressed
-                                 error=slave->on_write(address,length,data);
-                               break;
-          case DYN_BULK_READ: prev_id=dyn_bulk_read_id_present(slave->rx_buffer,slave->address,&address,&length);
-                              if(prev_id!=0xFF)
-                              {
-                                if(prev_id==0x00)// first device to answer
-                                {
-                                  error=slave->on_read(address,length,data);
-                                  if(error==DYN_NO_ERROR)
-                                    dyn_slave_send_status_packet(slave,DYN_NO_ERROR,length,data);
-                                  else
-                                    dyn_slave_send_status_packet(slave,DYN_INST_ERROR,0,data);
-                                }
-                                else// wait for the previous device in the sequence to send its data
-                                {
-                                  slave->sync_bulk_address=address;
-                                  slave->sync_bulk_length=length;
-                                  slave->sync_bulk_prev_id=prev_id;
-                                  slave->bulk_read_pending=0x01;       
-                                }
-                              }
-                              break;
-          case DYN_BULK_WRITE: dyn_slave_send_status_packet(slave,DYN_INST_ERROR,0,data);
-                               break;
-          default:
-                   break;
-        }
-      }
-      else
-      {
-        // send a checksum error answer
-        if(dyn_get_id(slave->rx_buffer)!=DYN_BROADCAST_ID)
-          dyn_slave_send_status_packet(slave,DYN_CHECKSUM_ERROR,0,0x00);
-      }
-    }
-    else
-    {
-      if(slave->bulk_read_pending)
-      {
-        if(id==slave->sync_bulk_prev_id)
-        {
-          slave->bulk_read_pending=0x00;
-          error=slave->on_read(slave->sync_bulk_address,slave->sync_bulk_length,data);
-          if(error==DYN_NO_ERROR)
-            dyn_slave_send_status_packet(slave,DYN_NO_ERROR,slave->sync_bulk_length,data);
-          else
-            dyn_slave_send_status_packet(slave,DYN_INST_ERROR,0,data);
-        }
-      }
-      else// the packet is addressed to another device, so relay it
-      {
-        if(slave->on_relay(slave->version,slave->rx_buffer,slave->tx_buffer)==DYN_SUCCESS)
-        {
-          // set the tx mode, if necessary
-          slave->set_tx_mode();
-          // start transmission by DMA
-          comm_send_dma(slave->comm_dev,slave->tx_buffer,dyn_get_length(slave->tx_buffer)+4);
-        }
-      }
-    }
-  }
-}
-
-void dyn_v2_slave_loop(TDynamixelSlave *slave)
+void dyn_slave_loop(TDynamixelSlave *slave)
 {
-  static unsigned char data[MAX_DYN_SLAVE_TX_BUFFER_LEN],error,prev_id,id;
-  static unsigned short int length,address;
+  unsigned char i,send_status,error,data[MAX_DYN_SLAVE_TX_BUFFER_LEN];
+  unsigned short int length;
 
   if(slave!=0x00000000)
   {
-    id=dyn2_get_id(slave->rx_buffer);
-    if(id==slave->address || id==DYN_BROADCAST_ID)// the packet is addressed to this device or it is a broadcast
+    if(slave->packet_ready)// check if a new instruction packet has been received
     {
-      // check the packet checksum
-      if(dyn2_check_checksum(slave->rx_buffer)==0x01)// the incomming packet is okay
-      {
-        // process the packet
-        switch(dyn2_get_instruction(slave->rx_buffer))
-        {
-          case DYN_PING: slave->on_ping();
-                         if(id!=DYN_BROADCAST_ID)
-                           dyn_slave_send_status_packet(slave,DYN_NO_ERROR,0,data);
-                         break;
-          case DYN_READ: error=slave->on_read(dyn2_get_read_address(slave->rx_buffer),dyn2_get_read_length(slave->rx_buffer),data);
-                         if(slave->return_level!=no_return && id!=DYN_BROADCAST_ID)
-                         {
-                           if(error==DYN_NO_ERROR)
-                             dyn_slave_send_status_packet(slave,DYN_NO_ERROR,dyn2_get_read_length(slave->rx_buffer),data);
-                           else
-                             dyn_slave_send_status_packet(slave,DYN_INST_ERROR,0,data);
-                         }
-                         break;
-          case DYN_WRITE: length=dyn2_get_write_data(slave->rx_buffer,data);
-                          error=slave->on_write(dyn2_get_write_address(slave->rx_buffer),length,data);
-                          if(slave->return_level==return_all && id!=DYN_BROADCAST_ID)
-                          {
-                            if(error==DYN_NO_ERROR)
-                              dyn_slave_send_status_packet(slave,DYN_NO_ERROR,0,data);
-                            else
-                              dyn_slave_send_status_packet(slave,DYN_INST_ERROR,0,data);
-                          }
-                          break;
-          case DYN_REG_WRITE: slave->reg_length=dyn2_get_reg_write_data(slave->rx_buffer,slave->reg_buffer);
-                              slave->reg_address=dyn2_get_reg_write_address(slave->rx_buffer);
-                              if(slave->return_level==return_all && id!=DYN_BROADCAST_ID)
-                                dyn_slave_send_status_packet(slave,DYN_NO_ERROR,0,data);
-                              break;
-          case DYN_ACTION: if(slave->reg_address!=0xFFFF)
-                           {
-                             error=slave->on_write(slave->reg_address,slave->reg_length,slave->reg_buffer);
-                             slave->reg_address=0xFFFF;
-                           }
-                           else
-                             if(slave->return_level==return_all && id!=DYN_BROADCAST_ID)
-                               dyn_slave_send_status_packet(slave,DYN_INST_ERROR,0,data);
-                           break;
-          case DYN_RESET:
-                          break;
-          case DYN_SYNC_READ: prev_id=dyn2_sync_read_id_present(slave->rx_buffer,slave->address,&address,&length);
-                              if(prev_id!=0xFF)
-                              {
-                                if(prev_id==0x00)// first device to answer
-                                {
-                                  error=slave->on_read(address,length,data);
-                                  if(error==DYN_NO_ERROR)
-                                    dyn_slave_send_status_packet(slave,DYN_NO_ERROR,length,data);
-                                  else
-                                    dyn_slave_send_status_packet(slave,DYN_INST_ERROR,0,data);
-                                }
-                                else// wait for the previous device in the sequence to send its data
-                                {
-                                  slave->sync_bulk_address=address;
-                                  slave->sync_bulk_length=length;
-                                  slave->sync_bulk_prev_id=prev_id;
-                                  slave->sync_read_pending=0x01;
-                                }
-                              }
-                              break;
-          case DYN_SYNC_WRITE: if(dyn2_sync_write_id_present(slave->rx_buffer,slave->address,&address,&length,data))// the device is addressed
-                                 error=slave->on_write(address,length,data);
-                               break;
-          case DYN_BULK_READ: prev_id=dyn2_bulk_read_id_present(slave->rx_buffer,slave->address,&address,&length);
-                              if(prev_id!=0xFF)
-                              {
-                                if(prev_id==0x00)// first device to answer
-                                {
-                                  error=slave->on_read(address,length,data);
-                                  if(error==DYN_NO_ERROR)
-                                    dyn_slave_send_status_packet(slave,DYN_NO_ERROR,length,data);
-                                  else
-                                    dyn_slave_send_status_packet(slave,DYN_INST_ERROR,0,data);
-                                }
-                                else// wait for the previous device in the sequence to send its data
-                                {
-                                  slave->sync_bulk_address=address;
-                                  slave->sync_bulk_length=length;
-                                  slave->sync_bulk_prev_id=prev_id;
-                                  slave->bulk_read_pending=0x01;       
-                                }
-                              }
-                              break;
-          case DYN_BULK_WRITE: if(dyn2_bulk_write_id_present(slave->rx_buffer,slave->address,&address,&length,data))
-                                 error=slave->on_write(address,length,data);
-                               break;
-          default:
-                   break;
-        }
-      }
-      else
+      slave->packet_ready=0x00;
+      // check address
+      for(i=0;i<slave->num_slave_devices;i++)
       {
-        // send a checksum error answer
-        if(dyn_get_id(slave->rx_buffer)!=DYN_BROADCAST_ID)
-          dyn_slave_send_status_packet(slave,DYN_CHECKSUM_ERROR,0,0x00);
+        if(slave->version==DYN_VER1)
+          send_status=dyn_v1_slave_loop(slave->slave_devices[i],slave->rx_buffer,&error,(unsigned char *)&length,data);
+        else
+          send_status=dyn_v2_slave_loop(slave->slave_devices[i],slave->rx_buffer,&error,&length,data);
+        if(send_status==0x01)
+          dyn_slave_send_status_packet(slave,slave->slave_devices[i]->address,error,length,data,slave->slave_devices[i]->return_delay);
       }
+      if(slave->on_relay(slave->version,slave->rx_buffer,slave->tx_buffer)==DYN_SUCCESS)
+      {   
+        // set the tx mode, if necessary           
+        slave->set_tx_mode();
+        // start transmission by DMA
+        comm_send_dma(slave->comm_dev,slave->tx_buffer,dyn_get_length(slave->tx_buffer)+4);         
+      } 
     }
     else
     {
-      if(slave->bulk_read_pending)
-      {
-        if(id==slave->sync_bulk_prev_id)
-        {
-          slave->bulk_read_pending=0x00;
-          error=slave->on_read(slave->sync_bulk_address,slave->sync_bulk_length,data);
-          if(error==DYN_NO_ERROR)
-            dyn_slave_send_status_packet(slave,DYN_NO_ERROR,slave->sync_bulk_length,data);
-          else
-            dyn_slave_send_status_packet(slave,DYN_INST_ERROR,0,data);
-        }
-      }
-      else if(slave->sync_read_pending)
-      {
-        if(id==slave->sync_bulk_prev_id)
-        {
-          slave->sync_read_pending=0x00;
-          error=slave->on_read(slave->sync_bulk_address,slave->sync_bulk_length,data);
-          if(error==DYN_NO_ERROR)
-            dyn_slave_send_status_packet(slave,DYN_NO_ERROR,slave->sync_bulk_length,data);
-          else
-            dyn_slave_send_status_packet(slave,DYN_INST_ERROR,0,data);
-        }
-      }
-      else// the packet is addressed to another device, so relay it
+      if(slave->comm_dev->time!=0x00000000)
       {
-        if(slave->on_relay(slave->version,slave->rx_buffer,slave->tx_buffer)==DYN_SUCCESS)
-        {
-          // set the tx mode, if necessary
-          slave->set_tx_mode();
-          // start transmission by DMA
-          comm_send_dma(slave->comm_dev,slave->tx_buffer,dyn2_get_length(slave->tx_buffer)+8);
+        if(time_is_timeout(slave->comm_dev->time))
+        { 
+          /* cancel any IRQ or DMA reception */
+          comm_cancel_irq_receive(slave->comm_dev);
+          comm_cancel_dma_receive(slave->comm_dev);
+          slave->received_bytes=0;
+          /* enable reception by IRQ */
+          comm_receive_irq(slave->comm_dev,0);
         }
       }
     }
@@ -480,8 +196,10 @@ void dyn_v2_slave_loop(TDynamixelSlave *slave)
 }
 
 /* public functions */
-unsigned char dyn_slave_init(TDynamixelSlave *slave,TMemory *memory,TComm *dev,unsigned char address,TDynVersion version)
+unsigned char dyn_slave_init(TDynamixelSlave *slave,TComm *dev,TScheduler *scheduler,sched_channel_t ch,TDynVersion version)
 {
+  unsigned char i;
+
   /* assign communication functions */
   dev->irq_receive_cb=(unsigned char (*)(void *,unsigned char))dyn_slave_irq_receive_cb;
   dev->dma_send_cb=(unsigned char (*)(void *))dyn_slave_dma_send_cb;
@@ -493,37 +211,20 @@ unsigned char dyn_slave_init(TDynamixelSlave *slave,TMemory *memory,TComm *dev,u
   slave->set_tx_mode=dummy_dyn_slave_set_tx_mode;
   slave->set_rx_mode=dummy_dyn_slave_set_rx_mode;
   slave->set_baudrate=dummy_dyn_slave_set_baudrate;
-  slave->on_ping=dummy_dyn_slave_on_ping;
-  slave->on_read=dummy_dyn_slave_on_read;
-  slave->on_write=dummy_dyn_slave_on_write;
-  slave->on_reset=dummy_dyn_slave_on_reset;
   slave->on_relay=dummy_dyn_slave_on_relay;
   /* initialize internal variables */
-  slave->address=address;
-  slave->return_delay=0x00;
-  slave->return_level=return_all;
   slave->packet_ready=0x00;
   slave->rx_timeout_ms=50;
   slave->received_bytes=0x00;
-  slave->reg_address=0xFFFF;
-  slave->reg_length=0x0000;
-  slave->sync_bulk_address=0x0000;
-  slave->sync_bulk_length=0x0000;
-  slave->sync_bulk_prev_id=0x00;
-  slave->sync_read_pending=0x00;
-  slave->bulk_read_pending=0x00;
+  /* initialize slave devices */
+  slave->num_slave_devices=0;
+  for(i=0;i<MAX_NUM_SLAVE_DEVICES;i++)
+    slave->slave_devices[i]=0x00000000;
 
-  /* initialize memory module */
-  mem_module_init(&slave->mem_module);
-  slave->mem_module.data=slave;
-  slave->mem_module.write_cmd=(void(*)(void *,unsigned short int, unsigned short int,unsigned char *))dyn_slave_write_cmd;
-  slave->mem_module.read_cmd=(void(*)(void *,unsigned short int, unsigned short int,unsigned char *))dyn_slave_read_cmd;
-  if(!mem_module_add_eeprom_segment(&slave->mem_module,EEPROM_DYN_SLAVE_BASE_ADDRESS1,EEPROM_DYN_SLAVE_LENGTH1))
-    return 0x00;
-  if(!mem_module_add_eeprom_segment(&slave->mem_module,EEPROM_DYN_SLAVE_BASE_ADDRESS2,EEPROM_DYN_SLAVE_LENGTH2))
-    return 0x00;
-  if(!mem_add_module(memory,&slave->mem_module))
-    return 0x00;
+  /* assigna a scheduler channel */
+  scheduler_set_channel(scheduler,ch,(void (*)(void *))dyn_slave_loop,1,slave);
+  slave->scheduler=scheduler;
+  slave->sch_channel=ch;
 
   slave->set_rx_mode();
   /* enable reception by IRQ */
@@ -532,57 +233,33 @@ unsigned char dyn_slave_init(TDynamixelSlave *slave,TMemory *memory,TComm *dev,u
   return 0x01;
 }
 
-void dyn_slave_set_baudrate(TDynamixelSlave *slave,unsigned int baudrate)
-{
-  slave->set_baudrate(slave->comm_dev,baudrate);
-}
-
-void dyn_slave_set_rx_timeout(TDynamixelSlave *slave,unsigned short int timeout_ms)
+unsigned char dyn_slave_add_device(TDynamixelSlave *slave, TDynamixelSlaveDevice *device)
 {
   if(slave!=0x00000000)
-    slave->rx_timeout_ms=timeout_ms;
-}
-
-void dyn_slave_set_address(TDynamixelSlave *slave,unsigned char address)
-{
-  if(slave!=0x00000000)
-    slave->address=address;
-}
-
-unsigned char dyn_slave_get_address(TDynamixelSlave *slave)
-{
-  if(slave!=0x00000000)
-    return slave->address;
-  else
-    return 0xFF;
-}
-
-void dyn_slave_set_return_delay(TDynamixelSlave *slave,unsigned char delay)
-{
-  if(slave!=0x00000000)
-    slave->return_delay=delay;
-}
-
-unsigned char dyn_slave_get_return_delay(TDynamixelSlave *slave)
-{
-  if(slave!=0x00000000)
-    return slave->return_delay;
+  {
+    if(slave->num_slave_devices<=(MAX_NUM_SLAVE_DEVICES-1))
+    {
+      slave->slave_devices[slave->num_slave_devices]=device;
+      slave->num_slave_devices++;
+      device->slave=slave;
+      return 0x01;
+    }
+    else
+      return 0x00;
+  }
   else
-    return 0xFF;
+    return 0x00;
 }
 
-void dyn_slave_set_return_level(TDynamixelSlave *slave,return_level_t level)
+void dyn_slave_set_baudrate(TDynamixelSlave *slave,unsigned int baudrate)
 {
-  if(slave!=0x00000000)
-    slave->return_level=level;
+  slave->set_baudrate(slave->comm_dev,baudrate);
 }
 
-return_level_t dyn_slave_get_return_level(TDynamixelSlave *slave)
+void dyn_slave_set_rx_timeout(TDynamixelSlave *slave,unsigned short int timeout_ms)
 {
   if(slave!=0x00000000)
-    return slave->return_level;
-  else
-    return return_all;
+    slave->rx_timeout_ms=timeout_ms;
 }
 
 TDynVersion dyn_slave_get_version(TDynamixelSlave *slave)
@@ -593,33 +270,13 @@ TDynVersion dyn_slave_get_version(TDynamixelSlave *slave)
     return DYN_VER1;
 }
 
-void dyn_slave_loop(TDynamixelSlave *slave)
+void dyn_slave_start(TDynamixelSlave *slave)
 {
-  if(slave!=0x00000000)
-  {
-    if(slave->packet_ready)// check if a new instruction packet has been received
-    {
-      slave->packet_ready=0x00;
-      // check address
-      if(slave->version==DYN_VER1)
-        dyn_v1_slave_loop(slave);
-      else
-        dyn_v2_slave_loop(slave);
-    }
-    else
-    {
-      if(slave->comm_dev->time!=0x00000000)
-      {
-        if(time_is_timeout(slave->comm_dev->time))
-        { 
-          /* cancel any IRQ or DMA reception */
-          comm_cancel_irq_receive(slave->comm_dev);
-          comm_cancel_dma_receive(slave->comm_dev);
-          slave->received_bytes=0;
-          /* enable reception by IRQ */
-          comm_receive_irq(slave->comm_dev,0);
-        }
-      }
-    }
-  }
+  scheduler_enable_channel(slave->scheduler,slave->sch_channel);
 }
+
+void dyn_slave_stop(TDynamixelSlave *slave)
+{
+  scheduler_disable_channel(slave->scheduler,slave->sch_channel);
+}
+
diff --git a/dynamixel_base/src/dynamixel_slave_device.c b/dynamixel_base/src/dynamixel_slave_device.c
new file mode 100644
index 0000000000000000000000000000000000000000..c11eecc6446d528b375a4c9dfb659730938d5642
--- /dev/null
+++ b/dynamixel_base/src/dynamixel_slave_device.c
@@ -0,0 +1,468 @@
+#include "dynamixel_slave_device.h"
+#include "dynamixel_slave.h"
+
+/* private functions */
+void dyn_slave_device_write_cmd(TDynamixelSlaveDevice *device,unsigned short int address,unsigned short int length,unsigned char *data)
+{
+  unsigned short int offset;
+
+  offset=address-device->eeprom_base_address1;
+  if(ram_in_window(device->eeprom_base_address1+DEVICE_MODEL,2,address,length))
+  {
+    if(ram_in_range(device->eeprom_base_address1+DEVICE_MODEL,address,length))
+      device->memory.data[device->eeprom_base_address1+DEVICE_MODEL]=data[DEVICE_MODEL-offset];
+    if(ram_in_range(device->eeprom_base_address1+DEVICE_MODEL+1,address,length))
+      device->memory.data[device->eeprom_base_address1+DEVICE_MODEL+1]=data[DEVICE_MODEL+1-offset];
+  }
+  if(ram_in_range(device->eeprom_base_address1+DEVICE_ID,address,length))
+  {
+    dyn_slave_device_set_address(device,data[DEVICE_ID-offset]);
+    device->memory.data[device->eeprom_base_address1+DEVICE_ID]=data[DEVICE_ID-offset];
+  }
+  if(ram_in_range(device->eeprom_base_address1+BAUDRATE,address,length))
+  {
+    dyn_slave_set_baudrate(device->slave,2000000/(data[BAUDRATE-offset]+1));
+    device->memory.data[device->eeprom_base_address1+BAUDRATE]=data[BAUDRATE-offset];
+  }
+  if(ram_in_range(device->eeprom_base_address1+RETURN_DELAY,address,length))
+  {
+    dyn_slave_device_set_return_delay(device,data[RETURN_DELAY-offset]);
+    device->memory.data[device->eeprom_base_address1+RETURN_DELAY]=data[RETURN_DELAY-offset];
+  }
+  offset=address-device->eeprom_base_address2;
+  if(ram_in_range(device->eeprom_base_address2+RETURN_LEVEL,address,length))
+  {
+    dyn_slave_device_set_return_level(device,data[RETURN_LEVEL-offset]);
+    device->memory.data[device->eeprom_base_address2+RETURN_LEVEL]=data[RETURN_LEVEL-offset];
+  }
+}
+
+void dyn_slave_device_read_cmd(TDynamixelSlaveDevice *device,unsigned short int address,unsigned short int length,unsigned char *data)
+{
+  ram_read_table(&device->memory,address,length,data);
+}
+
+void dummy_dyn_slave_device_on_ping(void)
+{
+
+}
+
+unsigned char dummy_dyn_slave_device_on_read(unsigned short int address,unsigned short int length,unsigned char *data)
+{
+  return DYN_SUCCESS;
+}
+
+unsigned char dummy_dyn_slave_device_on_write(unsigned short int address,unsigned short int length,unsigned char *data)
+{
+  return DYN_SUCCESS;
+}
+
+unsigned char dummy_dyn_slave_device_on_reset(void)
+{
+  return DYN_SUCCESS;
+}
+
+unsigned char dyn_v1_slave_loop(TDynamixelSlaveDevice *device,unsigned char *rx_buffer,unsigned char *error,unsigned char *length,unsigned char *data)
+{
+  static unsigned char address,prev_id,id;
+  unsigned char send_status=0x00;
+
+  if(device!=0x000000000)
+  {
+    id=dyn_get_id(rx_buffer);
+    if(id==device->address || id==DYN_BROADCAST_ID)// the packet is addressed to this device or it is a broadcast
+    {
+      // check the packet checksum
+      if(dyn_check_checksum(rx_buffer)==0xFF)// the incomming packet is okay
+      {
+        // process the packet
+        switch(dyn_get_instruction(rx_buffer))
+        {
+          case DYN_PING: device->on_ping();
+                         if(id!=DYN_BROADCAST_ID)
+                         {
+                           send_status=0x01;
+                           *error=DYN_NO_ERROR;
+                           *length=0;
+                         }
+                         break;
+          case DYN_READ: (*error)=device->on_read(dyn_get_read_address(rx_buffer),dyn_get_read_length(rx_buffer),data);
+                         if(device->return_level!=no_return && id!=DYN_BROADCAST_ID)
+                         {
+                           send_status=0x01;
+                           if((*error)==DYN_NO_ERROR)
+                             (*length)=dyn_get_read_length(rx_buffer);
+                           else
+                           {
+                             (*length)=0;
+                             (*error)=DYN_INST_ERROR;
+                           }
+                         }
+                         break;
+          case DYN_WRITE: (*length)=dyn_get_write_data(rx_buffer,data);
+                          (*error)=device->on_write(dyn_get_write_address(rx_buffer),*length,data);
+                          if(device->return_level==return_all && id!=DYN_BROADCAST_ID)
+                          {
+                            send_status=0x01;
+                            (*length)=0;
+                            if((*error)!=DYN_NO_ERROR)
+                              (*error)=DYN_INST_ERROR;
+                          }
+                          break;
+          case DYN_REG_WRITE: device->reg_length=dyn_get_reg_write_data(rx_buffer,device->reg_buffer);
+                              device->reg_address=dyn_get_reg_write_address(rx_buffer);
+                              if(device->return_level==return_all && id!=DYN_BROADCAST_ID)
+                              {
+                                send_status=0x01;
+                                (*error)=DYN_NO_ERROR;
+                                (*length)=0;
+                              }
+                              break;
+          case DYN_ACTION: if(device->reg_address!=0xFFFF)
+                           {
+                             (*error)=device->on_write(device->reg_address,device->reg_length,device->reg_buffer);
+                             device->reg_address=0xFFFF;
+                           }
+                           else
+                             if(device->return_level==return_all && id!=DYN_BROADCAST_ID)
+                             {
+                               send_status=0x01;
+                               (*error)=DYN_NO_ERROR;
+                               (*length)=0;
+                             }
+                           break;
+          case DYN_RESET:
+                          break;
+          case DYN_SYNC_READ: send_status=0x01;
+                              (*error)=DYN_INST_ERROR;
+                              (*length)=0;
+                              break;
+          case DYN_SYNC_WRITE: if(dyn_sync_write_id_present(rx_buffer,device->address,&address,length,data))// the device is addressed
+                                 (*error)=device->on_write(address,*length,data);
+                               break;
+          case DYN_BULK_READ: prev_id=dyn_bulk_read_id_present(rx_buffer,device->address,&address,length);
+                              if(prev_id!=0xFF)
+                              {
+                                if(prev_id==0x00)// first device to answer
+                                {
+                                  send_status=0x01;
+                                  (*error)=device->on_read(address,*length,data);
+                                  if((*error)!=DYN_NO_ERROR)
+                                  {
+                                    (*error)=DYN_INST_ERROR;
+                                    (*length)=0;
+                                  }
+                                }
+                                else// wait for the previous device in the sequence to send its data
+                                {
+                                  device->sync_bulk_address=address;
+                                  device->sync_bulk_length=*length;
+                                  device->sync_bulk_prev_id=prev_id;
+                                  device->bulk_read_pending=0x01;       
+                                }
+                              }
+                              break;
+          case DYN_BULK_WRITE: send_status=0x01;
+                               (*error)=DYN_INST_ERROR;
+                               (*length)=0;
+                               break;
+          default:
+                   break;
+        }
+      }
+      else
+      {
+        // send a checksum error answer
+        if(dyn_get_id(rx_buffer)!=DYN_BROADCAST_ID)
+        {
+          send_status=0x01;
+          (*error)=DYN_CHECKSUM_ERROR;
+          (*length)=0;
+        }
+      }
+    }
+    else
+    {
+      if(device->bulk_read_pending)
+      {
+        if(id==device->sync_bulk_prev_id)
+        {
+          device->bulk_read_pending=0x00;
+          send_status=0x01;
+          (*error)=device->on_read(device->sync_bulk_address,device->sync_bulk_length,data);
+          if((*error)==DYN_NO_ERROR)
+            (*length)=device->sync_bulk_length;
+          else
+          {
+            (*error)=DYN_INST_ERROR;
+            (*length)=0;
+          }
+        }
+      }
+    }
+  }
+  
+  return send_status;
+}
+
+unsigned char dyn_v2_slave_loop(TDynamixelSlaveDevice *device,unsigned char *rx_buffer,unsigned char *error,unsigned short int *length,unsigned char *data)
+{
+  static unsigned char prev_id,id;
+  static unsigned short int address;
+  unsigned char send_status=0x00;
+
+  if(device!=0x00000000)
+  {
+    id=dyn2_get_id(rx_buffer);
+    if(id==device->address || id==DYN_BROADCAST_ID)// the packet is addressed to this device or it is a broadcast
+    {
+      // check the packet checksum
+      if(dyn2_check_checksum(rx_buffer)==0x01)// the incomming packet is okay
+      {
+        // process the packet
+        switch(dyn2_get_instruction(rx_buffer))
+        {
+          case DYN_PING: device->on_ping();
+                         if(id!=DYN_BROADCAST_ID)
+                         {
+                           send_status=0x01;
+                           (*error)=DYN_NO_ERROR;
+                           (*length)=0;
+                         }
+                         break;
+          case DYN_READ: (*error)=device->on_read(dyn2_get_read_address(rx_buffer),dyn2_get_read_length(rx_buffer),data);
+                         if(device->return_level!=no_return && id!=DYN_BROADCAST_ID)
+                         {
+                           send_status=0x01;
+                           if((*error)==DYN_NO_ERROR)
+                             (*length)=dyn2_get_read_length(rx_buffer);
+                           else
+                           {
+                             (*length)=0;
+                             (*error)=DYN_INST_ERROR;
+                           }
+                         }
+                         break;
+          case DYN_WRITE: (*length)=dyn2_get_write_data(rx_buffer,data);
+                          (*error)=device->on_write(dyn2_get_write_address(rx_buffer),*length,data);
+                          if(device->return_level==return_all && id!=DYN_BROADCAST_ID)
+                          {
+                            send_status=0x01;
+                            (*length)=0;
+                            if((*error)!=DYN_NO_ERROR)
+                              (*error)=DYN_INST_ERROR;
+                          }
+                          break;
+          case DYN_REG_WRITE: device->reg_length=dyn2_get_reg_write_data(rx_buffer,device->reg_buffer);
+                              device->reg_address=dyn2_get_reg_write_address(rx_buffer);
+                              if(device->return_level==return_all && id!=DYN_BROADCAST_ID)
+                              {
+                                send_status=0x01;
+                                (*error)=DYN_NO_ERROR;
+                                (*length)=0;
+                              }
+                              break;
+          case DYN_ACTION: if(device->reg_address!=0xFFFF)
+                           {
+                             (*error)=device->on_write(device->reg_address,device->reg_length,device->reg_buffer);
+                             device->reg_address=0xFFFF;
+                           }
+                           else
+                             if(device->return_level==return_all && id!=DYN_BROADCAST_ID)
+                             {
+                               send_status=0x01;
+                               (*error)=DYN_NO_ERROR;
+                               (*length)=0;
+                             }
+                           break;
+          case DYN_RESET:
+                          break;
+          case DYN_SYNC_READ: prev_id=dyn2_sync_read_id_present(rx_buffer,device->address,&address,length);
+                              if(prev_id!=0xFF)
+                              {
+                                if(prev_id==0x00)// first device to answer
+                                {
+                                  (*error)=device->on_read(address,*length,data);
+                                  send_status=0x01;
+                                  if((*error)!=DYN_NO_ERROR)
+                                  {
+                                    (*error)=DYN_INST_ERROR;
+                                    (*length)=0;
+                                  }
+                                }
+                                else// wait for the previous device in the sequence to send its data
+                                {
+                                  device->sync_bulk_address=address;
+                                  device->sync_bulk_length=*length;
+                                  device->sync_bulk_prev_id=prev_id;
+                                  device->sync_read_pending=0x01;
+                                }
+                              }
+                              break;
+          case DYN_SYNC_WRITE: if(dyn2_sync_write_id_present(rx_buffer,device->address,&address,length,data))// the device is addressed
+                                 (*error)=device->on_write(address,*length,data);
+                               break;
+          case DYN_BULK_READ: prev_id=dyn2_bulk_read_id_present(rx_buffer,device->address,&address,length);
+                              if(prev_id!=0xFF)
+                              {
+                                if(prev_id==0x00)// first device to answer
+                                {
+                                  send_status=0x01;
+                                  (*error)=device->on_read(address,*length,data);
+                                  if((*error)!=DYN_NO_ERROR)
+                                  {
+                                    (*error)=DYN_INST_ERROR;
+                                    (*length)=0;   
+                                  }
+                                }
+                                else// wait for the previous device in the sequence to send its data
+                                {
+                                  device->sync_bulk_address=address;
+                                  device->sync_bulk_length=*length;
+                                  device->sync_bulk_prev_id=prev_id;
+                                  device->bulk_read_pending=0x01;       
+                                }
+                              }
+                              break;
+          case DYN_BULK_WRITE: if(dyn2_bulk_write_id_present(rx_buffer,device->address,&address,length,data))
+                                 (*error)=device->on_write(address,*length,data);
+                               break;
+          default:
+                   break;
+        }
+      }
+      else
+      {
+        // send a checksum error answer
+        if(dyn_get_id(rx_buffer)!=DYN_BROADCAST_ID)
+        {
+          send_status=0x01;
+          (*error)=DYN_CHECKSUM_ERROR;
+          (*length)=0;
+        }
+      }
+    }
+    else
+    {
+      if(device->bulk_read_pending)
+      {
+        if(id==device->sync_bulk_prev_id)
+        {
+          device->bulk_read_pending=0x00;
+          (*error)=device->on_read(device->sync_bulk_address,device->sync_bulk_length,data);
+          send_status=0x01;
+          if((*error)==DYN_NO_ERROR)
+            (*length)=device->sync_bulk_length;
+          else
+          {
+            (*length)=0;
+            (*error)=DYN_INST_ERROR;
+          }
+        }
+      }
+      else if(device->sync_read_pending)
+      {
+        if(id==device->sync_bulk_prev_id)
+        {
+          device->sync_read_pending=0x00;
+          (*error)=device->on_read(device->sync_bulk_address,device->sync_bulk_length,data);
+          send_status=0x01;
+          if((*error)==DYN_NO_ERROR)
+            (*length)=device->sync_bulk_length;
+          else
+          {
+            (*length)=0;
+            (*error)=DYN_INST_ERROR;
+          }
+        }
+      }
+    }
+  }
+
+  return send_status;
+}
+
+/* public functions */
+unsigned char dyn_slave_device_init(TDynamixelSlaveDevice *device,unsigned char address,unsigned char eeprom_base_address1,unsigned char eeprom_base_address2)
+{
+  /* initialize the internal callbacks */
+  device->on_ping=dummy_dyn_slave_device_on_ping;
+  device->on_read=dummy_dyn_slave_device_on_read;
+  device->on_write=dummy_dyn_slave_device_on_write;
+  device->on_reset=dummy_dyn_slave_device_on_reset;
+  /* initialize internal variables */
+  device->address=address;
+  device->return_delay=0x00;
+  device->return_level=return_all;
+  device->reg_address=0xFFFF;
+  device->reg_length=0x0000;
+  device->sync_bulk_address=0x0000;
+  device->sync_bulk_length=0x0000;
+  device->sync_bulk_prev_id=0x00;
+  device->sync_read_pending=0x00;
+  device->bulk_read_pending=0x00;
+
+  /* initialize memory module */
+  mem_init(&device->memory,address);
+  mem_module_init(&device->mem_module);
+  device->mem_module.data=device;
+  device->mem_module.write_cmd=(void(*)(void *,unsigned short int, unsigned short int,unsigned char *))dyn_slave_device_write_cmd;
+  device->mem_module.read_cmd=(void(*)(void *,unsigned short int, unsigned short int,unsigned char *))dyn_slave_device_read_cmd;
+  if(!mem_module_add_eeprom_segment(&device->mem_module,eeprom_base_address1,EEPROM_DYN_SLAVE_LENGTH1))
+    return 0x00;
+  if(!mem_module_add_eeprom_segment(&device->mem_module,eeprom_base_address2,EEPROM_DYN_SLAVE_LENGTH2))
+    return 0x00;
+  if(!mem_add_module(&device->memory,&device->mem_module))
+    return 0x00;
+  device->eeprom_base_address1=eeprom_base_address1;
+  device->eeprom_base_address2=eeprom_base_address2;
+
+  return 0x01;
+}
+
+void dyn_slave_device_set_address(TDynamixelSlaveDevice *device,unsigned char address)
+{
+  if(device!=0x00000000)
+    device->address=address;
+}
+
+unsigned char dyn_slave_device_get_address(TDynamixelSlaveDevice *device)
+{
+  if(device!=0x00000000)
+    return device->address;
+  else
+    return 0xFF;
+}
+
+void dyn_slave_device_set_return_delay(TDynamixelSlaveDevice *device,unsigned char delay)
+{
+  if(device!=0x00000000)
+    device->return_delay=delay;
+}
+
+unsigned char dyn_slave_device_get_return_delay(TDynamixelSlaveDevice *device)
+{
+  if(device!=0x00000000)
+    return device->return_delay;
+  else
+    return 0xFF;
+}
+
+void dyn_slave_device_set_return_level(TDynamixelSlaveDevice *device,return_level_t level)
+{
+  if(device!=0x00000000)
+    device->return_level=level;
+}
+
+return_level_t dyn_slave_device_get_return_level(TDynamixelSlaveDevice *device)
+{
+  if(device!=0x00000000)
+    return device->return_level;
+  else
+    return return_all;
+}
+
+TMemory *dyn_slave_device_get_memory(TDynamixelSlaveDevice *device)
+{
+  return &device->memory;
+}
diff --git a/dynamixel_manager/Makefile b/dynamixel_manager/Makefile
index 4ebb37992b0d459fc28f3864365f430b99e11ee1..020c8182f704eec57c52c1efec5a4c7590ff25d3 100755
--- a/dynamixel_manager/Makefile
+++ b/dynamixel_manager/Makefile
@@ -18,6 +18,8 @@ MEMORY_PATH = ../memory
 
 INCLUDE_DIRS = -I./include/ -I./include/modules -I$(COMM_PATH)/include -I$(UTILS_PATH)/include -I$(DYN_BASE_PATH)/include -I$(MEMORY_PATH)/include
 
+MACROS = -DMAX_DYN_MASTER_TX_BUFFER_LEN=256 -DMAX_DYN_MASTER_RX_BUFFER_LEN=256 -DDYN_MANAGER_MAX_NUM_MASTERS=4 -DDYN_MANAGER_MAX_NUM_MODULES=8 -DDYN_MANAGER_MAX_NUM_DEVICES=32 -DDYN_MANAGER_MAX_NUM_SINGLE_OP=16 -DDYN_MANAGER_MAX_NUM_SYNC_OP=4 -DDYN_MANAGER_MAX_NUM_BULK_OP=4 -DMODULE_MAX_NUM_MODELS=32 -DMM_MAX_NUM_MOTION_MODULES=8
+
 TCHAIN_PREFIX=arm-none-eabi-
 
 CC = $(TCHAIN_PREFIX)gcc
@@ -33,8 +35,8 @@ DYNAMIXEL_OUT_M3 = ./lib/dynamixel_manager_m3.a
 
 SRC_DIR=./src/
 SRC=$(wildcard $(SRC_DIR)*.c)
-SRC_DIR_MODULES=./src/modules/
-SRC+=$(wildcard $(SRC_DIR_MODULES)*.c)
+#SRC_DIR_MODULES=./src/modules/
+#SRC+=$(wildcard $(SRC_DIR_MODULES)*.c)
 
 DYNAMIXEL_M4_FPU_OBJ_DIR=build/m4_fpu/
 DYNAMIXEL_M4_FPU_OBJS_TMP = $(notdir $(SRC:.c=.o))
@@ -54,21 +56,21 @@ DYNAMIXEL_M3_OBJS = $(patsubst %,$(DYNAMIXEL_M3_OBJ_DIR)%,$(DYNAMIXEL_M3_OBJS_TM
 
 all: $(DYNAMIXEL_OUT_M4_FPU) $(DYNAMIXEL_OUT_M0) $(DYNAMIXEL_OUT_M0plus) $(DYNAMIXEL_OUT_M3)
 $(DYNAMIXEL_M4_FPU_OBJ_DIR)%.o: $(SRC_DIR)%.c
-	$(CC) -c $(CFLAGS) $(COMPILE_OPTS_M4_FPU) -o $@ $<
+	$(CC) -c $(CFLAGS) $(MACROS) $(COMPILE_OPTS_M4_FPU) -o $@ $<
 $(DYNAMIXEL_M4_FPU_OBJ_DIR)%.o: $(SRC_DIR_MODULES)%.c
-	$(CC) -c $(CFLAGS) $(COMPILE_OPTS_M4_FPU) -o $@ $<
+	$(CC) -c $(CFLAGS) $(MACROS) $(COMPILE_OPTS_M4_FPU) -o $@ $<
 $(DYNAMIXEL_M0_OBJ_DIR)%.o: $(SRC_DIR)%.c
-	$(CC) -c $(CFLAGS) $(COMPILE_OPTS_M0) -o $@ $<
+	$(CC) -c $(CFLAGS) $(MACROS) $(COMPILE_OPTS_M0) -o $@ $<
 $(DYNAMIXEL_M0_OBJ_DIR)%.o: $(SRC_DIR_MODULES)%.c
-	$(CC) -c $(CFLAGS) $(COMPILE_OPTS_M0) -o $@ $<
+	$(CC) -c $(CFLAGS) $(MACROS) $(COMPILE_OPTS_M0) -o $@ $<
 $(DYNAMIXEL_M0plus_OBJ_DIR)%.o: $(SRC_DIR)%.c
-	$(CC) -c $(CFLAGS) $(COMPILE_OPTS_M0plus) -o $@ $<
+	$(CC) -c $(CFLAGS) $(MACROS) $(COMPILE_OPTS_M0plus) -o $@ $<
 $(DYNAMIXEL_M0plus_OBJ_DIR)%.o: $(SRC_DIR_MODULES)%.c
-	$(CC) -c $(CFLAGS) $(COMPILE_OPTS_M0plus) -o $@ $<
+	$(CC) -c $(CFLAGS) $(MACROS) $(COMPILE_OPTS_M0plus) -o $@ $<
 $(DYNAMIXEL_M3_OBJ_DIR)%.o: $(SRC_DIR)%.c
-	$(CC) -c $(CFLAGS) $(COMPILE_OPTS_M3) -o $@ $<
+	$(CC) -c $(CFLAGS) $(MACROS) $(COMPILE_OPTS_M3) -o $@ $<
 $(DYNAMIXEL_M3_OBJ_DIR)%.o: $(SRC_DIR_MODULES)%.c
-	$(CC) -c $(CFLAGS) $(COMPILE_OPTS_M3) -o $@ $<
+	$(CC) -c $(CFLAGS) $(MACROS) $(COMPILE_OPTS_M3) -o $@ $<
 mkdir_build: 
 	mkdir -p build/m4_fpu
 	mkdir -p build/m0
diff --git a/dynamixel_manager/include/dyn_manager.h b/dynamixel_manager/include/dyn_manager.h
index b9f03388a2dcf3461dcad06f3d654ff32a2c3adf..b5c8cff1085b6254a1b1b635de67f422e1b78287 100644
--- a/dynamixel_manager/include/dyn_manager.h
+++ b/dynamixel_manager/include/dyn_manager.h
@@ -6,22 +6,22 @@
 #include "memory.h"
 
 #ifndef DYN_MANAGER_MAX_NUM_MASTERS
-  #define DYN_MANAGER_MAX_NUM_MASTERS        4
+  #error "Please, specify the maximum number of masters with the DYN_MANAGER_MAX_NUM_MASTERS macro"
 #endif
 #ifndef DYN_MANAGER_MAX_NUM_MODULES
-  #define DYN_MANAGER_MAX_NUM_MODULES        8
+  #error "Please, specify the maximum number of modules with the DYN_MANAGER_MAX_NUM_MODULES macro"
 #endif
 #ifndef DYN_MANAGER_MAX_NUM_DEVICES
-  #define DYN_MANAGER_MAX_NUM_DEVICES        32
+  #error "Please, specify the maximum number of devices with the DYN_MANAGER_MAX_NUM_DEVICES macro"
 #endif
 #ifndef DYN_MANAGER_MAX_NUM_SINGLE_OP
-  #define DYN_MANAGER_MAX_NUM_SINGLE_OP      16
+  #error "Please, specify the maximum number of single operations with the DYN_MANAGER_MAX_NUM_SINGLE_OP macro"
 #endif
 #ifndef DYN_MANAGER_MAX_NUM_SYNC_OP
-  #define DYN_MANAGER_MAX_NUM_SYNC_OP        4
+  #error "Please, specify the maximum number of sync operations with the DYN_MANAGER_MAX_NUM_SYNC_OP macro"
 #endif
 #ifndef DYN_MANAGER_MAX_NUM_BULK_OP
-  #define DYN_MANAGER_MAX_NUM_BULK_OP        4
+  #error "Please, specify the maximum number of bulk operations with the DYN_MANAGER_MAX_NUM_BULK_OP macro"
 #endif
 #define    DYN_MANAGER_MAX_NUM_OP            ((DYN_MANAGER_MAX_NUM_SINGLE_OP+DYN_MANAGER_MAX_NUM_SYNC_OP+DYN_MANAGER_MAX_NUM_BULK_OP)*DYN_MANAGER_MAX_NUM_MASTERS)
 
@@ -101,6 +101,8 @@ typedef struct{
 struct TDynModule;
 
 typedef struct{
+  unsigned short int eeprom_base_address;
+  unsigned short int ram_base_address;
   TDynamixelMaster *masters[DYN_MANAGER_MAX_NUM_MASTERS];
   TDynManagerOps operations[DYN_MANAGER_MAX_NUM_MASTERS];
   unsigned char num_masters;
@@ -113,11 +115,12 @@ typedef struct{
   unsigned short int period_us;
   void (*init_timer)(void);
   void (*set_period)(unsigned short int period_us);
+  TMemory *memory;
   TMemModule mem_module;
 }TDynManager;
 
 // public functions
-unsigned char dyn_manager_init(TDynManager *manager,TMemory *memory);
+unsigned char dyn_manager_init(TDynManager *manager,TMemory *memory,unsigned short int eeprom_base_address,unsigned short int ram_base_address);
 void dyn_manager_set_period(TDynManager *manager,unsigned short int period_us);
 unsigned short int dyn_manager_get_period(TDynManager *manager);
 void dyn_manager_scan(TDynManager *manager);
diff --git a/dynamixel_manager/include/dyn_manager_registers.h b/dynamixel_manager/include/dyn_manager_registers.h
index 7099cc7d5ce6a4292d3a7b7c2c96164bbe2e0264..c7d360be6c57731f044ba572f5d6af9b17b51455 100644
--- a/dynamixel_manager/include/dyn_manager_registers.h
+++ b/dynamixel_manager/include/dyn_manager_registers.h
@@ -1,26 +1,18 @@
 #ifndef _DYN_MANAGER_REGISTERS_H
 #define _DYN_MANAGER_REGISTERS_H
 
-#ifndef RAM_DYN_MANAGER_BASE_ADDRESS
-  #define RAM_DYN_MANAGER_BASE_ADDRESS        ((unsigned short int)0x0000)
-#endif
-
-#ifndef EEPROM_DYN_MANAGER_BASE_ADDRESS
-  #define EEPROM_DYN_MANAGER_BASE_ADDRESS     ((unsigned short int)0x0000)
-#endif
-
 #define RAM_DYN_MANAGER_LENGTH                2
 
 #define EEPROM_DYN_MANAGER_LENGTH             2
 
-#define DYN_MANAGER_PERIOD                    EEPROM_DYN_MANAGER_BASE_ADDRESS
+#define DYN_MANAGER_PERIOD                    0
 
-#define DYN_MANAGER_NUM_MODULES               RAM_DYN_MANAGER_BASE_ADDRESS
-#define DYN_MANAGER_NUM_MASTERS               (RAM_DYN_MANAGER_BASE_ADDRESS+1)
+#define DYN_MANAGER_NUM_MODULES               0
+#define DYN_MANAGER_NUM_MASTERS               1
 
-#ifndef DEFAULT_DYN_MANAGER_PERIOD
-  #define DEFAULT_DYN_MANAGER_PERIOD          0x1E78
-#endif
+#define dyn_manager_eeprom_data(name,section_name,base_address,DEFAULT_PERIOD) \
+unsigned short int name##_eeprom_data[] __attribute__ ((section (section_name)))={DEFAULT_PERIOD&0x00FF,base_address+DYN_MANAGER_PERIOD, \
+                                                                                  (DEFAULT_PERIOD>>8)&0x00FF,base_address+DYN_MANAGER_PERIOD+1};
 
 #endif
 
diff --git a/dynamixel_manager/include/dyn_module.h b/dynamixel_manager/include/dyn_module.h
index f4c6d44fad8636bfe75fb69f09f4484344900090..a79d6c6a7669d5c3a3405ac8d2546fb08e2a3ff9 100644
--- a/dynamixel_manager/include/dyn_module.h
+++ b/dynamixel_manager/include/dyn_module.h
@@ -2,7 +2,7 @@
 #define _DYN_MODULE_H
 
 #ifndef MODULE_MAX_NUM_MODELS
-  #define MODULE_MAX_NUM_MODELS     32
+  #error "Please, specify the maximum number of dynamixel master modules with the MODULE_MAX_NUM_MODELS macro"
 #endif
 
 #include "dyn_manager.h"
diff --git a/dynamixel_manager/include/dyn_module_registers.h b/dynamixel_manager/include/dyn_module_registers.h
index c4c7afdf264b1289021c6f3478da61db963cfe8e..fe27dbb309ebefbe6eb880dd716b8ce44518836e 100644
--- a/dynamixel_manager/include/dyn_module_registers.h
+++ b/dynamixel_manager/include/dyn_module_registers.h
@@ -5,15 +5,14 @@
 
 #define EEPROM_DYN_MODULE_LENGTH             1
 
-#define DYN_MODULE_PERIOD                    EEPROM_DYN_MODULE_BASE_ADDRESS
+#define DYN_MODULE_PERIOD                    0
 
-#define DYN_MODULE_CNTRL                     RAM_DYN_MODULE_BASE_ADDRESS
-#define DYN_MODULE_NUM_MODELS                (RAM_DYN_MODULE_BASE_ADDRESS+1)
-#define DYN_MODULE_NUM_DEVICES               (RAM_DYN_MODULE_BASE_ADDRESS+2)
+#define DYN_MODULE_CNTRL                     0
+#define DYN_MODULE_NUM_MODELS                1
+#define DYN_MODULE_NUM_DEVICES               2
 
-#ifndef DEFAULT_DYN_MODULE_PERIOD
-  #define DEFAULT_DYN_MODULE_PERIOD          0x01
-#endif
+#define dyn_module_eeprom_data(name,section_name,base_address,DEFAULT_PERIOD) \
+unsigned short int name##_eeprom_data[] __attribute__ ((section (section_name)))={DEFAULT_PERIOD,base_address+DYN_MODULE_PERIOD};
 
 #endif
 
diff --git a/dynamixel_manager/include/modules/motion_manager.h b/dynamixel_manager/include/modules/motion_manager.h
index b5d3bbe2e32678e5d0c055bb3bd27d08c02fa9c8..1a2e9aa525ec2a72902713300277b41e484ca573 100644
--- a/dynamixel_manager/include/modules/motion_manager.h
+++ b/dynamixel_manager/include/modules/motion_manager.h
@@ -4,10 +4,7 @@
 #include "dyn_module.h"
 
 #ifndef MM_MAX_NUM_MOTION_MODULES
-  #define MM_MAX_NUM_MOTION_MODULES        8
-#endif
-#ifdef MM_MAX_NUM_MODELS
-  #define MODULE_MAX_NUM_MODELS            MM_MAX_NUM_MODELS
+  #error "Please, specify the maximum number of motion modules with the MM_MAX_NUM_MOTION_MODULES macro"
 #endif
 
 typedef enum {MM_NONE          = -1,
diff --git a/dynamixel_manager/include/modules/motion_manager_registers.h b/dynamixel_manager/include/modules/motion_manager_registers.h
index 208e6b810965e8a28d47268820f151b25498137e..02fbc9ed572a7d596bada1c73b517df5bb13815a 100644
--- a/dynamixel_manager/include/modules/motion_manager_registers.h
+++ b/dynamixel_manager/include/modules/motion_manager_registers.h
@@ -3,60 +3,14 @@
 
 #include "dyn_module_registers.h"
 
-#ifndef RAM_MM_BASE_ADDRESS
-  #define RAM_MM_BASE_ADDRESS                ((unsigned short int)0x0000)
-#endif
-
-#ifndef EEPROM_MM_BASE_ADDRESS
-  #define EEPROM_MM_BASE_ADDRESS             ((unsigned short int)0x0000)
-#endif
-
-#define RAM_MM_LENGTH                        (RAM_DYN_MODULE_LENGTH + )
+#define RAM_MM_LENGTH                        (RAM_DYN_MODULE_LENGTH + 0)
 
-#define EEPROM_MM_LENGTH                     (EEPROM_DYN_MODULE_LENGTH + )
+#define EEPROM_MM_LENGTH                     (DYN_MANAGER_MAX_NUM_DEVICES)
 
-#define MM_PERIOD                            DYN_MODULE_PERIOD
-
-#define MM_CNTRL                             DYN_MODULE_CNTRL
-#define MM_NUM_MODELS                        DYN_MODULE_NUM_MODELS
-#define MM_NUM_DEVICES                       DYN_MODULE_NUM_DEVICES
-
-#ifndef DEFAULT_MM_PERIOD
-  #define DEFAULT_MM_PERIOD                  DEFAULT_DYN_MODULE_PERIOD
-#endif
-#define MM_SERVO0_OFFSET                ((unsigned short int)0x0011)
-#define MM_SERVO1_OFFSET                ((unsigned short int)0x0012)
-#define MM_SERVO2_OFFSET                ((unsigned short int)0x0013)
-#define MM_SERVO3_OFFSET                ((unsigned short int)0x0014)
-#define MM_SERVO4_OFFSET                ((unsigned short int)0x0015)
-#define MM_SERVO5_OFFSET                ((unsigned short int)0x0016)
-#define MM_SERVO6_OFFSET                ((unsigned short int)0x0017)
-#define MM_SERVO7_OFFSET                ((unsigned short int)0x0018)
-#define MM_SERVO8_OFFSET                ((unsigned short int)0x0019)
-#define MM_SERVO9_OFFSET                ((unsigned short int)0x001A)
-#define MM_SERVO10_OFFSET               ((unsigned short int)0x001B)
-#define MM_SERVO11_OFFSET               ((unsigned short int)0x001C)
-#define MM_SERVO12_OFFSET               ((unsigned short int)0x001D)
-#define MM_SERVO13_OFFSET               ((unsigned short int)0x001E)
-#define MM_SERVO14_OFFSET               ((unsigned short int)0x001F)
-#define MM_SERVO15_OFFSET               ((unsigned short int)0x0020)
-#define MM_SERVO16_OFFSET               ((unsigned short int)0x0021)
-#define MM_SERVO17_OFFSET               ((unsigned short int)0x0022)
-#define MM_SERVO18_OFFSET               ((unsigned short int)0x0023)
-#define MM_SERVO19_OFFSET               ((unsigned short int)0x0024)
-#define MM_SERVO20_OFFSET               ((unsigned short int)0x0025)
-#define MM_SERVO21_OFFSET               ((unsigned short int)0x0026)
-#define MM_SERVO22_OFFSET               ((unsigned short int)0x0027)
-#define MM_SERVO23_OFFSET               ((unsigned short int)0x0028)
-#define MM_SERVO24_OFFSET               ((unsigned short int)0x0029)
-#define MM_SERVO25_OFFSET               ((unsigned short int)0x002A)
-#define MM_SERVO26_OFFSET               ((unsigned short int)0x002B)
-#define MM_SERVO27_OFFSET               ((unsigned short int)0x002C)
-#define MM_SERVO28_OFFSET               ((unsigned short int)0x002D)
-#define MM_SERVO29_OFFSET               ((unsigned short int)0x002E)
-#define MM_SERVO30_OFFSET               ((unsigned short int)0x002F)
-#define MM_SERVO31_OFFSET               ((unsigned short int)0x0030)
+#define MM_SERVO_OFFSET                      0
 
+#define dyn_mm_eeprom_data(name,section_name,base_address) \
+unsigned short int name##_eeprom_data[] __attribute__ ((section (section_name)))={0,base_address+MM_SERVO_OFFSET};
 
 #endif
 
diff --git a/dynamixel_manager/src/dyn_manager.c b/dynamixel_manager/src/dyn_manager.c
index 8499d2c1a5130a45251b9d02167c47bba4e6338d..73db6b175604463e9a7c863b62610ea24b11530d 100644
--- a/dynamixel_manager/src/dyn_manager.c
+++ b/dynamixel_manager/src/dyn_manager.c
@@ -37,7 +37,7 @@ void dyn_manager_write_cmd(TDynManager *module,unsigned short int address,unsign
 
 void dyn_manager_read_cmd(TDynManager *module,unsigned short int address,unsigned short int length,unsigned char *data)
 {
-  ram_read_table(address,length,data);
+  ram_read_table(module->memory,address,length,data);
 }
 
 unsigned char dyn_manager_check_id(TDynManager *manager,unsigned char id)
@@ -211,7 +211,7 @@ void dyn_manager_delete_op_single_master(TDynManager *manager,unsigned char mast
 }
 
 // public functions
-unsigned char dyn_manager_init(TDynManager *manager,TMemory *memory)
+unsigned char dyn_manager_init(TDynManager *manager,TMemory *memory,unsigned short int eeprom_base_address,unsigned short int ram_base_address)
 {
   unsigned char i,j,k;
 
@@ -284,19 +284,20 @@ unsigned char dyn_manager_init(TDynManager *manager,TMemory *memory)
   /* initialize timer */
   if(manager->init_timer!=0x00000000)
     manager->init_timer();
-  manager->set_period(DEFAULT_DYN_MANAGER_PERIOD);
 
   /* initialize memory module */
   mem_module_init(&manager->mem_module);
   manager->mem_module.data=manager;
   manager->mem_module.write_cmd=(void(*)(void *,unsigned short int, unsigned short int,unsigned char *))dyn_manager_write_cmd;
   manager->mem_module.read_cmd=(void(*)(void *,unsigned short int, unsigned short int,unsigned char *))dyn_manager_read_cmd;
-  if(!mem_module_add_ram_segment(&manager->mem_module,RAM_DYN_MANAGER_BASE_ADDRESS,RAM_DYN_MANAGER_LENGTH))
+  if(!mem_module_add_ram_segment(&manager->mem_module,ram_base_address,RAM_DYN_MANAGER_LENGTH))
     return 0x00;
-  if(!mem_module_add_eeprom_segment(&manager->mem_module,EEPROM_DYN_MANAGER_BASE_ADDRESS,EEPROM_DYN_MANAGER_LENGTH))
+  if(!mem_module_add_eeprom_segment(&manager->mem_module,eeprom_base_address,EEPROM_DYN_MANAGER_LENGTH))
     return 0x00;
   if(!mem_add_module(memory,&manager->mem_module))
     return 0x00;
+  manager->eeprom_base_address=eeprom_base_address;
+  manager->ram_base_address=ram_base_address;
   
   return 0x01;
 }
@@ -312,8 +313,8 @@ void dyn_manager_set_period(TDynManager *manager,unsigned short int period_us)
       if(manager->modules[i]!=0x00000000 && manager->modules[i]->set_period!=0x00000000)
          manager->modules[i]->set_period(manager->modules[i]->data,period_us);
     manager->period_us=period_us;
-    ram_data[DYN_MANAGER_PERIOD]=period_us%256;
-    ram_data[DYN_MANAGER_PERIOD+1]=period_us/256;
+    manager->memory->data[DYN_MANAGER_PERIOD]=period_us%256;
+    manager->memory->data[DYN_MANAGER_PERIOD+1]=period_us/256;
   }
 }
 
@@ -368,7 +369,7 @@ void dyn_manager_add_master(TDynManager *manager,TDynamixelMaster *master)
   {
     manager->masters[i]=master;
     manager->num_masters++;
-    ram_data[DYN_MANAGER_NUM_MASTERS]++;
+    manager->memory->data[DYN_MANAGER_NUM_MASTERS]++;
   }
 }
 
@@ -402,7 +403,7 @@ void dyn_manager_add_module(TDynManager *manager,TDynModule *module)
     manager->modules[i]=module;
     manager->num_modules++;
     module->manager=manager;
-    ram_data[DYN_MANAGER_NUM_MODULES]++;
+    manager->memory->data[DYN_MANAGER_NUM_MODULES]++;
   }
 }
 
diff --git a/f1/usart/src/usart1_remap.c b/f1/usart/src/usart1_remap.c
index 9d17fb30df8ca20040f79212950894c20e0ff05f..5c5427c1687f71d9767471219143a15dfd84d1b6 100644
--- a/f1/usart/src/usart1_remap.c
+++ b/f1/usart/src/usart1_remap.c
@@ -275,6 +275,12 @@ void usart1_set_priorities(TComm *comm_dev,TUSART_IRQ_Priorities *priorities)
   }
 }
 
+void usart1_set_baudrate(TComm *comm_dev,unsigned int baudrate)
+{
+  Uart1Handle.Init.BaudRate = baudrate;
+  HAL_UART_Init(&Uart1Handle);
+}
+
 /* IRQ functions */
 unsigned char usart1_send_irq(unsigned char first_byte)
 {
diff --git a/memory/include/memory.h b/memory/include/memory.h
index 1829fee81dbbb353df3cc2791584e24bde51e00a..e01445f9abe68e5c69b74d720e65f5daf1ab78bf 100644
--- a/memory/include/memory.h
+++ b/memory/include/memory.h
@@ -15,11 +15,15 @@ typedef struct
 {
   unsigned char num_mem_modules;
   TMemModule *mem_modules[MAX_NUM_MEM_MODULES];
+  unsigned char device_id;
   unsigned short int (*eeprom_write_data)(unsigned short int address,unsigned short int data);
   unsigned short int (*eeprom_read_data)(unsigned short int address,unsigned short int *data);
+  unsigned char data[RAM_SIZE];
+  unsigned char total_eeprom;
+  unsigned char total_ram;
 }TMemory;
 
-void mem_init(TMemory *memory);
+void mem_init(TMemory *memory,unsigned char device_id);
 void mem_initialize_data(TMemory *memory);
 unsigned char mem_add_module(TMemory *memory, TMemModule *module);
 void mem_do_write(TMemory *memory,unsigned short int start_address,unsigned short int length,unsigned char *data);
diff --git a/memory/include/ram.h b/memory/include/ram.h
index ecc663695a1d6fa81089cbc8ee53c41889b9e683..1aa611f1bf238e8b1779bccfdccfcd54236d5579 100644
--- a/memory/include/ram.h
+++ b/memory/include/ram.h
@@ -13,17 +13,15 @@ extern "C" {
 #define      RAM_BAD_BIT      -3
 #define      RAM_BAD_ACCESS   -4
 
-extern unsigned char ram_data[RAM_SIZE];
-
 unsigned char ram_init(TMemory *memory);
-inline void ram_read_byte(unsigned short int address, unsigned char *data);
-inline void ram_read_word(unsigned short int address, unsigned short int *data);
-unsigned char ram_read_table(unsigned short int address, unsigned short int length,unsigned char *data);
-unsigned char ram_set_bit(unsigned short int address, unsigned char bit);
-unsigned char ram_clear_bit(unsigned short int address, unsigned char bit);
-unsigned char ram_write_byte(unsigned short int address, unsigned char data);
-unsigned char ram_write_word(unsigned short int address, unsigned short int data);
-unsigned char ram_write_table(unsigned short int address, unsigned short int length,unsigned char *data);
+inline void ram_read_byte(TMemory *memory,unsigned short int address, unsigned char *data);
+inline void ram_read_word(TMemory *memory,unsigned short int address, unsigned short int *data);
+unsigned char ram_read_table(TMemory *memory,unsigned short int address, unsigned short int length,unsigned char *data);
+unsigned char ram_set_bit(TMemory *memory,unsigned short int address, unsigned char bit);
+unsigned char ram_clear_bit(TMemory *memory,unsigned short int address, unsigned char bit);
+unsigned char ram_write_byte(TMemory *memory,unsigned short int address, unsigned char data);
+unsigned char ram_write_word(TMemory *memory,unsigned short int address, unsigned short int data);
+unsigned char ram_write_table(TMemory *memory,unsigned short int address, unsigned short int length,unsigned char *data);
 inline unsigned char ram_in_range(unsigned short int reg,unsigned short int address,unsigned short int length);
 unsigned char ram_in_window(unsigned short int start_reg,unsigned short int reg_length,unsigned short int start_address,unsigned short int address_length);
 
diff --git a/memory/src/memory.c b/memory/src/memory.c
index 68fbc806be5d15e471023bd8665b03b89caab7fb..af30fbf36f18d9c31e08b50fa672aa12e2b4cf57 100644
--- a/memory/src/memory.c
+++ b/memory/src/memory.c
@@ -1,10 +1,6 @@
 #include "memory.h"
 #include "mem_module.h"
 
-/* private variables */
-unsigned char memory_total_eeprom;
-unsigned char memory_total_ram;
-
 /* private functions */
 unsigned char mem_in_window(unsigned short int mem_start_address,unsigned short int mem_length,unsigned short int start_address,unsigned short int length)
 {
@@ -21,7 +17,7 @@ unsigned char mem_in_window(unsigned short int mem_start_address,unsigned short
 }
 
 /* public functions */
-void mem_init(TMemory *memory)
+void mem_init(TMemory *memory,unsigned char device_id)
 {
   unsigned char i;
 
@@ -30,10 +26,11 @@ void mem_init(TMemory *memory)
     memory->mem_modules[i]=0x00000000;
   memory->eeprom_write_data=0x00000000;
   memory->eeprom_read_data=0x00000000;
+  memory->device_id=device_id;
 
   /* initialize internal variables */
-  memory_total_eeprom=0;
-  memory_total_ram=0;
+  memory->total_eeprom=0;
+  memory->total_ram=0;
 }
 
 void mem_initialize_data(TMemory *memory)
@@ -48,7 +45,7 @@ void mem_initialize_data(TMemory *memory)
   {
     for(i=0;i<EEPROM_SIZE;i++)
     {
-      if(memory->eeprom_read_data(i,&data))
+      if(memory->eeprom_read_data((memory->device_id<<8)+i,&data))
         eeprom_data[i]=0x00;
       else
         eeprom_data[i]=data&0x00FF;
@@ -122,17 +119,17 @@ unsigned char mem_add_module(TMemory *memory, TMemModule *module)
     // check available memory
     for(new_seg=0;new_seg<module->num_ram_segments;new_seg++)
     {
-      memory_total_ram+=module->ram_segments[new_seg].length;
-      if(memory_total_ram>RAM_SIZE)
+      memory->total_ram+=module->ram_segments[new_seg].length;
+      if(memory->total_ram>RAM_SIZE)
         return 0x00;
     }
     for(new_seg=0;new_seg<module->num_eeprom_segments;new_seg++)
     {
-      memory_total_eeprom+=module->eeprom_segments[new_seg].length;
-      if(memory_total_eeprom>EEPROM_SIZE)
+      memory->total_eeprom+=module->eeprom_segments[new_seg].length;
+      if(memory->total_eeprom>EEPROM_SIZE)
         return 0x00;
-      memory_total_ram+=module->eeprom_segments[new_seg].length;
-      if(memory_total_ram>RAM_SIZE)
+      memory->total_ram+=module->eeprom_segments[new_seg].length;
+      if(memory->total_ram>RAM_SIZE)
         return 0x00;
     }
 
@@ -195,7 +192,7 @@ void mem_do_write(TMemory *memory,unsigned short int start_address,unsigned shor
           mem_module->write_cmd(mem_module->data,actual_address,actual_length,&data[actual_address-start_address]);
         if(memory->eeprom_write_data!=0x00000000)
           for(k=actual_address;k<(actual_address+actual_length);k++)
-            memory->eeprom_write_data(k,data[k-start_address]);
+            memory->eeprom_write_data((memory->device_id<<8)+k,data[k-start_address]);
       }
     }
   }
diff --git a/memory/src/ram.c b/memory/src/ram.c
index 444c73cb126562ff90a9daecb34deadf900cf33a..326ab7fd02830c2506f144983ebadf33558fd864 100644
--- a/memory/src/ram.c
+++ b/memory/src/ram.c
@@ -1,7 +1,5 @@
 #include "ram.h"
 
-unsigned char ram_data[RAM_SIZE]={0};
-
 unsigned char ram_init(TMemory *memory)
 {
   mem_initialize_data(memory);
@@ -9,66 +7,66 @@ unsigned char ram_init(TMemory *memory)
   return 0x01;
 }
 
-inline void ram_read_byte(unsigned short int address,unsigned char *data)
+inline void ram_read_byte(TMemory *memory,unsigned short int address,unsigned char *data)
 {
-  (*data)=ram_data[address];
+  (*data)=memory->data[address];
 }
 
-inline void ram_read_word(unsigned short int address, unsigned short int *data)
+inline void ram_read_word(TMemory *memory,unsigned short int address, unsigned short int *data)
 {
-  (*data)=ram_data[address];
-  (*data)+=ram_data[address+1]*256;
+  (*data)=memory->data[address];
+  (*data)+=memory->data[address+1]*256;
 }
 
-unsigned char ram_read_table(unsigned short int address, unsigned short int length,unsigned char *data)
+unsigned char ram_read_table(TMemory *memory,unsigned short int address, unsigned short int length,unsigned char *data)
 {
   unsigned short int i;
 
   if((address+length)<=(RAM_SIZE-1))
   {
     for(i=0;i<length;i++)
-      data[i]=ram_data[address+i];
+      data[i]=memory->data[address+i];
     return RAM_SUCCESS;
   }
   else
     return RAM_BAD_ADDRESS;
 }
 
-unsigned char ram_set_bit(unsigned short int address, unsigned char bit)
+unsigned char ram_set_bit(TMemory *memory,unsigned short int address, unsigned char bit)
 {
   if(bit>=0 && bit<8)
   {
-    ram_data[address]|=(0x01<<bit);
+    memory->data[address]|=(0x01<<bit);
     return RAM_SUCCESS;
   }
   else
     return RAM_BAD_BIT;
 }
 
-unsigned char ram_clear_bit(unsigned short int address, unsigned char bit)
+unsigned char ram_clear_bit(TMemory *memory,unsigned short int address, unsigned char bit)
 {
   if(bit>=0 && bit<8)
   {
-    ram_data[address]&=(~(0x01<<bit));
+    memory->data[address]&=(~(0x01<<bit));
     return RAM_SUCCESS;
   }
   else
     return RAM_BAD_BIT;
 }
 
-unsigned char ram_write_byte(unsigned short int address, unsigned char data)
+unsigned char ram_write_byte(TMemory *memory,unsigned short int address, unsigned char data)
 {
-  ram_data[address]=data;
+  memory->data[address]=data;
 
   return RAM_SUCCESS;
 }
 
-unsigned char ram_write_word(unsigned short int address, unsigned short int data)
+unsigned char ram_write_word(TMemory *memory,unsigned short int address, unsigned short int data)
 {
   if(address < (RAM_SIZE-1))
   {
-    ram_data[address]=data%256;
-    ram_data[address+1]=data/256;
+    memory->data[address]=data%256;
+    memory->data[address+1]=data/256;
 
     return RAM_SUCCESS;
   }
@@ -76,14 +74,14 @@ unsigned char ram_write_word(unsigned short int address, unsigned short int data
     return RAM_BAD_ADDRESS;  
 }
 
-unsigned char ram_write_table(unsigned short int address, unsigned short int length,unsigned char *data)
+unsigned char ram_write_table(TMemory *memory,unsigned short int address, unsigned short int length,unsigned char *data)
 {
   unsigned short int i;
 
   if((address+length)<RAM_SIZE)
   {
     for(i=0;i<length;i++)
-      ram_data[address+i]=data[i];
+      memory->data[address+i]=data[i];
     return RAM_SUCCESS;
   }
   else
diff --git a/pattern_frame_buffer/include/frame_buffer.h b/pattern_frame_buffer/include/frame_buffer.h
index 6b48631151c97075bff569fdc8c376095b4c3f50..aca02b27815ec1ae5a128b4eb32a522c67dcde83 100644
--- a/pattern_frame_buffer/include/frame_buffer.h
+++ b/pattern_frame_buffer/include/frame_buffer.h
@@ -5,6 +5,8 @@
 extern "C" {
 #endif
 
+#include "memory.h"
+
 #ifndef FB_MAX_BUFFER_LEN
   #error "Please, specify the maximum frame buffer length with the FB_MAX_BUFFER_LEN macro"
 #endif
@@ -13,6 +15,7 @@ extern "C" {
 
 typedef struct
 {
+  TMemory *memory;
   unsigned short int ram_base_address;
   unsigned short int eeprom_base_address;
   unsigned short int num_rows;
@@ -23,7 +26,7 @@ typedef struct
   unsigned char pixel_buffer[FB_MAX_BUFFER_LEN];
 }TFrameBuffer;
 
-void frame_buffer_init(TFrameBuffer *fb,unsigned short int ram_base_address,unsigned short int eeprom_base_address);
+void frame_buffer_init(TFrameBuffer *fb,TMemory *memory,unsigned short int ram_base_address,unsigned short int eeprom_base_address);
 void frame_buffer_set_num_rows(TFrameBuffer *fb,unsigned short int rows);
 unsigned short int frame_buffer_get_num_rows(TFrameBuffer *fb);
 void frame_buffer_set_pixels_per_row(TFrameBuffer *fb,unsigned short int pixels);
diff --git a/pattern_frame_buffer/include/frame_buffer_control.h b/pattern_frame_buffer/include/frame_buffer_control.h
index ed4deeed49e34676641ff1bf7423c07a28a3f337..934b906a7c40b29c483c62a814d9406a3a883466 100644
--- a/pattern_frame_buffer/include/frame_buffer_control.h
+++ b/pattern_frame_buffer/include/frame_buffer_control.h
@@ -32,6 +32,7 @@ typedef struct TFBControl
   TScheduler *scheduler;
   sched_channel_t sch_channel;
   unsigned short int period_ms;
+  TMemory *memory;
   TMemModule mem_module;
   unsigned short int ram_base_address;
   unsigned short int eeprom_base_address;
diff --git a/pattern_frame_buffer/include/frame_buffer_control_registers.h b/pattern_frame_buffer/include/frame_buffer_control_registers.h
index f44d32dd4e0a7187e457a68f0d1ac9294f072b83..1abce5667ef6cf0caf32b392cdcabc755bfbe948 100644
--- a/pattern_frame_buffer/include/frame_buffer_control_registers.h
+++ b/pattern_frame_buffer/include/frame_buffer_control_registers.h
@@ -48,15 +48,15 @@
   #define DEFAULT_FRAME_BUFFER_CONTROL_NUM_BUFFERS            0x0001
 #endif
 
-#define frame_buffer_control_eeprom_data(name,section_name,base_address) \
-unsigned short int name##_eeprom_data[] __attribute__ ((section (section_name)))={DEFAULT_FRAME_BUFFER_CONTROL_PERIOD&0x00FF,base_address+FRAME_BUFFER_CONTROL_PERIOD_OFFSET, \
-                                                                                  (DEFAULT_FRAME_BUFFER_CONTROL_PERIOD>>8)&0x00FF,base_address+FRAME_BUFFER_CONTROL_PERIOD_OFFSET+1, \
-                                                                                  DEFAULT_FRAME_BUFFER_CONTROL_NUM_ROWS&0x00FF,base_address+FRAME_BUFFER_CONTROL_NUM_ROWS_OFFSET, \
-                                                                                  (DEFAULT_FRAME_BUFFER_CONTROL_NUM_ROWS>>8)&0x00FF,base_address+FRAME_BUFFER_CONTROL_NUM_ROWS_OFFSET+1, \
-                                                                                  DEFAULT_FRAME_BUFFER_CONTROL_NUM_PIXELS&0x00FF,base_address+FRAME_BUFFER_CONTROL_NUM_PIXELS_OFFSET, \
-                                                                                  (DEFAULT_FRAME_BUFFER_CONTROL_NUM_PIXELS>>8)&0x00FF,base_address+FRAME_BUFFER_CONTROL_NUM_PIXELS_OFFSET+1, \
-                                                                                  DEFAULT_FRAME_BUFFER_CONTROL_NUM_BUFFERS&0x00FF,base_address+FRAME_BUFFER_CONTROL_NUM_BUFFERS_OFFSET, \
-                                                                                  (DEFAULT_FRAME_BUFFER_CONTROL_NUM_BUFFERS>>8)&0x00FF,base_address+FRAME_BUFFER_CONTROL_NUM_BUFFERS_OFFSET+1};
+#define frame_buffer_control_eeprom_data(name,section_name,base_address,device_id) \
+unsigned short int name##_eeprom_data[] __attribute__ ((section (section_name)))={DEFAULT_FRAME_BUFFER_CONTROL_PERIOD&0x00FF,(device_id<<8)+base_address+FRAME_BUFFER_CONTROL_PERIOD_OFFSET, \
+                                                                                  (DEFAULT_FRAME_BUFFER_CONTROL_PERIOD>>8)&0x00FF,(device_id<<8)+base_address+FRAME_BUFFER_CONTROL_PERIOD_OFFSET+1, \
+                                                                                  DEFAULT_FRAME_BUFFER_CONTROL_NUM_ROWS&0x00FF,(device_id<<8)+base_address+FRAME_BUFFER_CONTROL_NUM_ROWS_OFFSET, \
+                                                                                  (DEFAULT_FRAME_BUFFER_CONTROL_NUM_ROWS>>8)&0x00FF,(device_id<<8)+base_address+FRAME_BUFFER_CONTROL_NUM_ROWS_OFFSET+1, \
+                                                                                  DEFAULT_FRAME_BUFFER_CONTROL_NUM_PIXELS&0x00FF,(device_id<<8)+base_address+FRAME_BUFFER_CONTROL_NUM_PIXELS_OFFSET, \
+                                                                                  (DEFAULT_FRAME_BUFFER_CONTROL_NUM_PIXELS>>8)&0x00FF,(device_id<<8)+base_address+FRAME_BUFFER_CONTROL_NUM_PIXELS_OFFSET+1, \
+                                                                                  DEFAULT_FRAME_BUFFER_CONTROL_NUM_BUFFERS&0x00FF,(device_id<<8)+base_address+FRAME_BUFFER_CONTROL_NUM_BUFFERS_OFFSET, \
+                                                                                  (DEFAULT_FRAME_BUFFER_CONTROL_NUM_BUFFERS>>8)&0x00FF,(device_id<<8)+base_address+FRAME_BUFFER_CONTROL_NUM_BUFFERS_OFFSET+1};
 
 #endif
 
diff --git a/pattern_frame_buffer/include/image_patterns.h b/pattern_frame_buffer/include/image_patterns.h
index 69696474c272258aeb2b0e0c7b105b83a7b626bc..d61001fc0ae404aeb17a6403ecb97e37213825af 100644
--- a/pattern_frame_buffer/include/image_patterns.h
+++ b/pattern_frame_buffer/include/image_patterns.h
@@ -3,6 +3,7 @@
 
 #include "patterns.h"
 #include "frame_buffer_control.h"
+#include "memory.h"
 
 #ifndef IMG_MAX_NUM_IMAGES
   #error "Please, specify the maximum number of images with the IMG_MAX_NUM_IMAGES macro"
@@ -20,7 +21,7 @@
 
 extern unsigned char img_pattern_data[IMG_MAX_NUM_IMAGES][IMG_MAX_IMAGE_WIDTH][IMG_MAX_IMAGE_HEIGHT][3];
 
-void img_patterns_init(unsigned short int ram_base_address);
+void img_patterns_init(TMemory *memory,unsigned short int ram_base_address);
 
 #pragma pack (push, 1)
 typedef struct
diff --git a/pattern_frame_buffer/src/frame_buffer.c b/pattern_frame_buffer/src/frame_buffer.c
index 4e35ec0c62296d8b1c294fde8d6e280acb18deac..ec208cadcc8e039f16d594f3f1677f5d7e1545ab 100644
--- a/pattern_frame_buffer/src/frame_buffer.c
+++ b/pattern_frame_buffer/src/frame_buffer.c
@@ -7,12 +7,12 @@ void frame_buffer_compute_free_memory(TFrameBuffer *fb)
 {
   fb->buffer_size=fb->num_rows*fb->num_pixels_per_row*FB_BYTES_PER_PIXEL;
   fb->free_mem=FB_MAX_BUFFER_LEN-fb->buffer_size*fb->num_buffers;
-  ram_data[fb->ram_base_address+FRAME_BUFFER_CONTROL_FREE_MEMORY_OFFSET]=fb->free_mem&0x00FF;
-  ram_data[fb->ram_base_address+FRAME_BUFFER_CONTROL_FREE_MEMORY_OFFSET+1]=(fb->free_mem&0xFF00)>>8;
+  fb->memory->data[fb->ram_base_address+FRAME_BUFFER_CONTROL_FREE_MEMORY_OFFSET]=fb->free_mem&0x00FF;
+  fb->memory->data[fb->ram_base_address+FRAME_BUFFER_CONTROL_FREE_MEMORY_OFFSET+1]=(fb->free_mem&0xFF00)>>8;
 }
 
 // public functions
-void frame_buffer_init(TFrameBuffer *fb,unsigned short int ram_base_address,unsigned short int eeprom_base_address)
+void frame_buffer_init(TFrameBuffer *fb,TMemory *memory,unsigned short int ram_base_address,unsigned short int eeprom_base_address)
 {
   unsigned int i;
 
@@ -22,6 +22,7 @@ void frame_buffer_init(TFrameBuffer *fb,unsigned short int ram_base_address,unsi
   frame_buffer_set_num_buffers(fb,DEFAULT_FRAME_BUFFER_CONTROL_NUM_BUFFERS);
   fb->ram_base_address=ram_base_address;
   fb->eeprom_base_address=eeprom_base_address;
+  fb->memory=memory;
 
   for(i=0;i<FB_MAX_BUFFER_LEN;i++)
     fb->pixel_buffer[i]=0x00;
@@ -30,8 +31,8 @@ void frame_buffer_init(TFrameBuffer *fb,unsigned short int ram_base_address,unsi
 void frame_buffer_set_num_rows(TFrameBuffer *fb,unsigned short int rows)
 {
   fb->num_rows=rows;
-  ram_data[fb->eeprom_base_address+FRAME_BUFFER_CONTROL_NUM_ROWS_OFFSET]=rows&0x00FF;
-  ram_data[fb->eeprom_base_address+FRAME_BUFFER_CONTROL_NUM_ROWS_OFFSET+1]=(rows&0xFF00)>>8;
+  fb->memory->data[fb->eeprom_base_address+FRAME_BUFFER_CONTROL_NUM_ROWS_OFFSET]=rows&0x00FF;
+  fb->memory->data[fb->eeprom_base_address+FRAME_BUFFER_CONTROL_NUM_ROWS_OFFSET+1]=(rows&0xFF00)>>8;
   frame_buffer_compute_free_memory(fb);
 }
 
@@ -43,8 +44,8 @@ unsigned short int frame_buffer_get_num_rows(TFrameBuffer *fb)
 void frame_buffer_set_pixels_per_row(TFrameBuffer *fb,unsigned short int pixels)
 {
   fb->num_pixels_per_row=pixels;
-  ram_data[fb->eeprom_base_address+FRAME_BUFFER_CONTROL_NUM_PIXELS_OFFSET]=pixels&0x00FF;
-  ram_data[fb->eeprom_base_address+FRAME_BUFFER_CONTROL_NUM_PIXELS_OFFSET+1]=(pixels&0xFF00)>>8;
+  fb->memory->data[fb->eeprom_base_address+FRAME_BUFFER_CONTROL_NUM_PIXELS_OFFSET]=pixels&0x00FF;
+  fb->memory->data[fb->eeprom_base_address+FRAME_BUFFER_CONTROL_NUM_PIXELS_OFFSET+1]=(pixels&0xFF00)>>8;
   frame_buffer_compute_free_memory(fb);
 }
 
@@ -56,8 +57,8 @@ unsigned short int frame_buffer_get_pixels_per_row(TFrameBuffer *fb)
 void frame_buffer_set_num_buffers(TFrameBuffer *fb,unsigned char num)
 {
   fb->num_buffers=num;
-  ram_data[fb->eeprom_base_address+FRAME_BUFFER_CONTROL_NUM_BUFFERS_OFFSET]=num&0x00FF;
-  ram_data[fb->eeprom_base_address+FRAME_BUFFER_CONTROL_NUM_BUFFERS_OFFSET+1]=(num&0xFF00)>>8;
+  fb->memory->data[fb->eeprom_base_address+FRAME_BUFFER_CONTROL_NUM_BUFFERS_OFFSET]=num&0x00FF;
+  fb->memory->data[fb->eeprom_base_address+FRAME_BUFFER_CONTROL_NUM_BUFFERS_OFFSET+1]=(num&0xFF00)>>8;
   frame_buffer_compute_free_memory(fb);
 }
 
diff --git a/pattern_frame_buffer/src/frame_buffer_control.c b/pattern_frame_buffer/src/frame_buffer_control.c
index 12efbd809630cd1fe262fc46e5c4f34b7271bd68..f1e2277e793566d65bee38a062a5ce23e7487827 100644
--- a/pattern_frame_buffer/src/frame_buffer_control.c
+++ b/pattern_frame_buffer/src/frame_buffer_control.c
@@ -161,7 +161,9 @@ void frame_buffer_control_write_cmd(void *module,unsigned short int address,unsi
 
 void frame_buffer_control_read_cmd(void *module,unsigned short int address,unsigned short int length,unsigned char *data)
 {
-  ram_read_table(address,length,data);
+  TFBControl *control=(TFBControl *)module;
+
+  ram_read_table(control->memory,address,length,data);
 }
 
 void frame_buffer_control_scheduler(void *data)
@@ -180,7 +182,7 @@ unsigned char frame_buffer_control_init(TFBControl *control,TMemory *memory,TSch
   // initialize internal variables
   frame_buffer_control_clear_patterns(control);
   frame_buffer_control_clear_copy_functions(control);
-  frame_buffer_init(&control->frame_buffer,ram_base_address,eeprom_base_address);
+  frame_buffer_init(&control->frame_buffer,memory,ram_base_address,eeprom_base_address);
   control->ram_base_address=ram_base_address;
   control->eeprom_base_address=eeprom_base_address;
 
@@ -189,13 +191,14 @@ unsigned char frame_buffer_control_init(TFBControl *control,TMemory *memory,TSch
   control->scheduler=scheduler;
   control->sch_channel=ch;
 
-  img_patterns_init(ram_base_address);
+  img_patterns_init(memory,ram_base_address);
 
   /* initialize memory module */
   mem_module_init(&control->mem_module);
   control->mem_module.write_cmd=frame_buffer_control_write_cmd;
   control->mem_module.read_cmd=frame_buffer_control_read_cmd;
   control->mem_module.data=control;
+  control->memory=memory;
   if(!mem_module_add_ram_segment(&control->mem_module,ram_base_address,RAM_FRAME_BUFFER_CONTROL_LENGTH))
     return 0x00;
   if(!mem_module_add_eeprom_segment(&control->mem_module,eeprom_base_address,EEPROM_FRAME_BUFFER_CONTROL_LENGTH))
@@ -209,20 +212,20 @@ unsigned char frame_buffer_control_init(TFBControl *control,TMemory *memory,TSch
 void frame_buffer_control_start(TFBControl *control)
 {
   scheduler_enable_channel(control->scheduler,control->sch_channel);
-  ram_data[control->ram_base_address+FRAME_BUFFER_CONTROL_OFFSET]|=FRAME_BUFFER_CONTROL_RUNNING;
+  control->memory->data[control->ram_base_address+FRAME_BUFFER_CONTROL_OFFSET]|=FRAME_BUFFER_CONTROL_RUNNING;
 }
 
 void frame_buffer_control_stop(TFBControl *control)
 {
   scheduler_disable_channel(control->scheduler,control->sch_channel);
-  ram_data[control->ram_base_address+FRAME_BUFFER_CONTROL_OFFSET]&=(~FRAME_BUFFER_CONTROL_RUNNING);
+  control->memory->data[control->ram_base_address+FRAME_BUFFER_CONTROL_OFFSET]&=(~FRAME_BUFFER_CONTROL_RUNNING);
 }
 
 void frame_buffer_control_set_period(TFBControl *control,unsigned short int period_ms)
 {
   scheduler_change_period(control->scheduler,control->sch_channel,period_ms);
-  ram_data[control->eeprom_base_address+FRAME_BUFFER_CONTROL_PERIOD_OFFSET]=period_ms&0x00FF;
-  ram_data[control->eeprom_base_address+FRAME_BUFFER_CONTROL_PERIOD_OFFSET+1]=(period_ms&0xFF00)>>8;
+  control->memory->data[control->eeprom_base_address+FRAME_BUFFER_CONTROL_PERIOD_OFFSET]=period_ms&0x00FF;
+  control->memory->data[control->eeprom_base_address+FRAME_BUFFER_CONTROL_PERIOD_OFFSET+1]=(period_ms&0xFF00)>>8;
   control->period_ms=period_ms;
 }
 
@@ -241,22 +244,22 @@ unsigned char frame_buffer_control_add_pattern(TFBControl *control,pattern_func_
   num_cols=frame_buffer_get_pixels_per_row(&control->frame_buffer); 
   if(area->min_row>num_rows || area->max_row>num_rows || area->min_row>area->max_row)
   {
-    ram_data[control->ram_base_address+FRAME_BUFFER_CONTROL_PATTERN_INDEX_OFFSET]=0xFF;
+    control->memory->data[control->ram_base_address+FRAME_BUFFER_CONTROL_PATTERN_INDEX_OFFSET]=0xFF;
     return 0xFF;
   }
   if(area->min_col>num_cols || area->max_col>num_cols || area->min_col>area->max_col)
   {
-    ram_data[control->ram_base_address+FRAME_BUFFER_CONTROL_PATTERN_INDEX_OFFSET]=0xFF;
+    control->memory->data[control->ram_base_address+FRAME_BUFFER_CONTROL_PATTERN_INDEX_OFFSET]=0xFF;
     return 0xFF;
   }
   if(data_length>FBC_MAX_DATA_PATTERN_LEN)
   {
-    ram_data[control->ram_base_address+FRAME_BUFFER_CONTROL_PATTERN_INDEX_OFFSET]=0xFF;
+    control->memory->data[control->ram_base_address+FRAME_BUFFER_CONTROL_PATTERN_INDEX_OFFSET]=0xFF;
     return 0xFF;
   }
   if(buffer_id>=frame_buffer_get_num_buffers(&control->frame_buffer))
   {
-    ram_data[control->ram_base_address+FRAME_BUFFER_CONTROL_PATTERN_INDEX_OFFSET]=0xFF;
+    control->memory->data[control->ram_base_address+FRAME_BUFFER_CONTROL_PATTERN_INDEX_OFFSET]=0xFF;
     return 0xFF;
   }
 
@@ -274,13 +277,13 @@ unsigned char frame_buffer_control_add_pattern(TFBControl *control,pattern_func_
         control->pat_parameters[j][i]=((unsigned char *)data)[i];
       control->pat_functions[j]=function;
       control->num_patterns++;
-      ram_data[control->ram_base_address+FRAME_BUFFER_CONTROL_NUM_PATTERN_OFFSET]=control->num_patterns;
-      ram_data[control->ram_base_address+FRAME_BUFFER_CONTROL_PATTERN_INDEX_OFFSET]=j;
+      control->memory->data[control->ram_base_address+FRAME_BUFFER_CONTROL_NUM_PATTERN_OFFSET]=control->num_patterns;
+      control->memory->data[control->ram_base_address+FRAME_BUFFER_CONTROL_PATTERN_INDEX_OFFSET]=j;
       return j;
     }
   }
   // the pattern could not be added
-  ram_data[control->ram_base_address+FRAME_BUFFER_CONTROL_PATTERN_INDEX_OFFSET]=0xFF;
+  control->memory->data[control->ram_base_address+FRAME_BUFFER_CONTROL_PATTERN_INDEX_OFFSET]=0xFF;
   return 0xFF;
 }
 
diff --git a/pattern_frame_buffer/src/image_patterns.c b/pattern_frame_buffer/src/image_patterns.c
index f49a883511e192516bc59d9508efcc551d841141..85f7aadce9cb2cc2f5aeb8924d5fe203065bbc54 100644
--- a/pattern_frame_buffer/src/image_patterns.c
+++ b/pattern_frame_buffer/src/image_patterns.c
@@ -43,12 +43,12 @@ void img_patterns_compute_range(unsigned short int area_min,unsigned short int a
 }
 
 // public functions
-void img_patterns_init(unsigned short int ram_base_address)
+void img_patterns_init(TMemory *memory,unsigned short int ram_base_address)
 {
   //initialize internal variables (read only variables)
-  ram_data[ram_base_address+FRAME_BUFFER_CONTROL_IMG_MAX_WIDTH_OFFSET]=IMG_MAX_IMAGE_WIDTH;
-  ram_data[ram_base_address+FRAME_BUFFER_CONTROL_IMG_MAX_HEIGHT_OFFSET]=IMG_MAX_IMAGE_HEIGHT;
-  ram_data[ram_base_address+FRAME_BUFFER_CONTROL_IMG_NUM_IMGS_OFFSET]=IMG_MAX_NUM_IMAGES;
+  memory->data[ram_base_address+FRAME_BUFFER_CONTROL_IMG_MAX_WIDTH_OFFSET]=IMG_MAX_IMAGE_WIDTH;
+  memory->data[ram_base_address+FRAME_BUFFER_CONTROL_IMG_MAX_HEIGHT_OFFSET]=IMG_MAX_IMAGE_HEIGHT;
+  memory->data[ram_base_address+FRAME_BUFFER_CONTROL_IMG_NUM_IMGS_OFFSET]=IMG_MAX_NUM_IMAGES;
 }
 
 void img_general(TLEDArea *area,TIMGDisplayData *pattern_data,unsigned char buffer_id,unsigned short int period,TFBControl *control)