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..cac4d0b20b0e4417b2902f36f1ad85d3ea1ac5dc 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; + unsigned char num_slave_devices; /** * \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 - * - */ - 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,27 @@ typedef struct * \brief * */ -unsigned char dyn_slave_init(TDynamixelSlave *slave,TMemory *memory,TComm *dev,unsigned char address,TDynVersion version); -/** - * \brief - * - */ -void dyn_slave_set_baudrate(TDynamixelSlave *slave,unsigned int baudrate); -/** - * \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); +unsigned char dyn_slave_init(TDynamixelSlave *slave,TComm *dev,TScheduler *scheduler,sched_channel_t ch,TDynVersion version); /** * \brief * */ -inline void dyn_slave_set_return_delay(TDynamixelSlave *slave,unsigned char delay); +unsigned char dyn_slave_add_device(TDynamixelSlave *slave, TDynamixelSlaveDevice *device); /** * \brief * */ -inline unsigned char dyn_slave_get_return_delay(TDynamixelSlave *slave); -/** - * \brief - * - */ -inline void dyn_slave_set_return_level(TDynamixelSlave *slave,return_level_t level); +void dyn_slave_set_baudrate(TDynamixelSlave *slave,unsigned int baudrate); /** * \brief * */ -inline return_level_t dyn_slave_get_return_level(TDynamixelSlave *slave); +inline void dyn_slave_set_rx_timeout(TDynamixelSlave *slave,unsigned short int timeout_ms); /** * \brief * */ inline TDynVersion dyn_slave_get_version(TDynamixelSlave *slave); -/** - * \brief - * - */ -void dyn_slave_loop(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..b7b9c40bc9d310ab8bda6f3c528e1f03c50b4b67 --- /dev/null +++ b/dynamixel_base/include/dynamixel_slave_device.h @@ -0,0 +1,159 @@ +#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 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); + + +#endif diff --git a/dynamixel_base/include/dynamixel_slave_registers.h b/dynamixel_base/include/dynamixel_slave_registers.h index 8a3a01bd147a1913bc031aba1c32c97a49960954..2a09dc5829e22af41fd05bd411e17e653d48c222 100644 --- a/dynamixel_base/include/dynamixel_slave_registers.h +++ b/dynamixel_base/include/dynamixel_slave_registers.h @@ -1,25 +1,17 @@ #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 @@ -41,5 +33,15 @@ #define DEFAULT_RETURN_LEVEL 0x0002 #endif +#define dyn_slave_control_eeprom_data(name,section_name,base_address1,base_address2) \ +unsigned short int name##_eeprom_data[] __attribute__ ((section (section_name)))={DEFAULT_DEVICE_MODEL&0x00FF,base_address1+DEVICE_MODEL, \ + (DEFAULT_DEVICE_MODEL>>8)&0x00FF,base_address1+DEVICE_MODEL+1, \ + DEFAULT_FIRMWARE_VERSION,base_address1+FIRMWARE_VERSION, \ + DEFAULT_DEVICE_ID,base_address1+DEVICE_ID, \ + DEFAULT_BAUDRATE,base_address1+BAUDRATE, \ + DEFAULT_RETURN_DELAY,base_address1+RETURN_DELAY, \ + DEFAULT_RETURN_LEVEL,base_address2+RETURN_LEVEL}; + + #endif diff --git a/dynamixel_base/src/dynamixel_slave.c b/dynamixel_base/src/dynamixel_slave.c index e1818981fa23d44bc06a1f2ae9d8159010b2acab..77232d7e05ac6300e7756d1ac487fe0a6be1c089 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) -{ - if(slave!=0x00000000) - slave->rx_timeout_ms=timeout_ms; -} - -void dyn_slave_set_address(TDynamixelSlave *slave,unsigned char address) +unsigned char dyn_slave_add_device(TDynamixelSlave *slave, TDynamixelSlaveDevice *device) { 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,3 @@ TDynVersion dyn_slave_get_version(TDynamixelSlave *slave) return DYN_VER1; } -void dyn_slave_loop(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); - } - } - } - } -} diff --git a/dynamixel_base/src/dynamixel_slave_device.c b/dynamixel_base/src/dynamixel_slave_device.c new file mode 100644 index 0000000000000000000000000000000000000000..19d833975dc93b2c8e15411e163c8c403f892012 --- /dev/null +++ b/dynamixel_base/src/dynamixel_slave_device.c @@ -0,0 +1,450 @@ +#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) +{ + if(ram_in_range(DEVICE_ID,address,length)) + { + dyn_slave_device_set_address(device,data[DEVICE_ID-address]); + ram_data[DEVICE_ID]=data[DEVICE_ID-address]; + } + if(ram_in_range(BAUDRATE,address,length)) + { + dyn_slave_set_baudrate(device->slave,2000000/(data[BAUDRATE-address]+1)); + ram_data[BAUDRATE]=data[BAUDRATE-address]; + } + if(ram_in_range(RETURN_DELAY,address,length)) + { + dyn_slave_device_set_return_delay(device,data[RETURN_DELAY-address]); + ram_data[RETURN_DELAY]=data[RETURN_DELAY-address]; + } + if(ram_in_range(RETURN_LEVEL,address,length)) + { + dyn_slave_device_set_return_level(device,data[RETURN_LEVEL-address]); + ram_data[RETURN_LEVEL]=data[RETURN_LEVEL-address]; + } +} + +void dyn_slave_device_read_cmd(TDynamixelSlaveDevice *devicee,unsigned short int address,unsigned short int length,unsigned char *data) +{ + ram_read_table(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); + 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; + + 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; +}