From 076acb0f56b735bf245a70b2a255391a6d95c63b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergi=20Hern=C3=A0ndez=20Juan?= <shernand@iri.upc.edu> Date: Thu, 17 Dec 2015 07:21:34 +0000 Subject: [PATCH] Added a Dynamixel slave modules. Work in progress. --- src/dynamixel.h | 18 +-- src/dynamixel_common.h | 23 ++++ src/dynamixel_slave.cpp | 286 ++++++++++++++++++++++++++++++++++++++++ src/dynamixel_slave.h | 234 ++++++++++++++++++++++++++++++++ 4 files changed, 544 insertions(+), 17 deletions(-) create mode 100644 src/dynamixel_common.h create mode 100644 src/dynamixel_slave.cpp create mode 100644 src/dynamixel_slave.h diff --git a/src/dynamixel.h b/src/dynamixel.h index a361d6a..eebb8cf 100644 --- a/src/dynamixel.h +++ b/src/dynamixel.h @@ -2,6 +2,7 @@ #define _DYNAMIXEL_H //#include "dynamixelserver.h" +#include "dynamixel_common.h" #include "eventserver.h" #include "comm.h" #include "mutex.h" @@ -14,23 +15,6 @@ class CDynamixelServer; const int NUM_RETRIES=10; -typedef enum {dyn_version1=1,dyn_version2=2} dyn_version_t; - -typedef enum {dyn_ping=0x01, - dyn_read=0x02, - dyn_write=0x03, - dyn_reg_write=0x04, - dyn_action=0x05, - dyn_factory_reset=0x06, - dyn_reboot=0x08, - dyn_status=0x55, - dyn_sync_read=0x82, - dyn_sync_write=0x83, - dyn_bulk_read=0x92, - dyn_bulk_write=0x93} dyn_inst_t; - -typedef enum {dyn_reset_all=0xFF,dyn_reset_keep_id=0x01,dyn_reset_keep_id_baud=0x02} dyn_reset_mode_t; - /** * \brief * diff --git a/src/dynamixel_common.h b/src/dynamixel_common.h new file mode 100644 index 0000000..b1223bc --- /dev/null +++ b/src/dynamixel_common.h @@ -0,0 +1,23 @@ +#ifndef _DYNAMIXEL_COMMON_H +#define _DYNAMIXEL_COMMON_H + +typedef enum {dyn_version1=1,dyn_version2=2} dyn_version_t; + +typedef enum {dyn_ping=0x01, + dyn_read=0x02, + dyn_write=0x03, + dyn_reg_write=0x04, + dyn_action=0x05, + dyn_factory_reset=0x06, + dyn_reboot=0x08, + dyn_status=0x55, + dyn_sync_read=0x82, + dyn_sync_write=0x83, + dyn_bulk_read=0x92, + dyn_bulk_write=0x93} dyn_inst_t; + +typedef enum {dyn_reset_all=0xFF,dyn_reset_keep_id=0x01,dyn_reset_keep_id_baud=0x02} dyn_reset_mode_t; + +typedef enum{no_return=0x00,return_only_read=0x01,return_all=0x02} return_level_t; + +#endif diff --git a/src/dynamixel_slave.cpp b/src/dynamixel_slave.cpp new file mode 100644 index 0000000..cfc0809 --- /dev/null +++ b/src/dynamixel_slave.cpp @@ -0,0 +1,286 @@ +#include "dynamixel_slave.h" + + +CDynamixelSlave::CDynamixelSlave(std::string& cont_id) +{ + this->event_server=CEventServer::instance(); + this->new_packet_available_event_id=cont_id + "new_packet_event_id"; + this->evetn_server->create_event(this->new_packet_available_event_id); + this->finish_thread_event_id=cont_id + "finish_thread_event_id"; + this->evetn_server->create_event(this->new_packet_available_event_id); + + this->thread_server=CThreadServer::instance(); + this->process_packets_thread_id=cont_id + "_thread_id"; + this->thread_server->create_thread(this->process_packets_thread_id); + this->thread_server->attach_thread(this->process_packets_thread_id,this->process_packets_thread,this); + + this->return_delay=0; + this->return_level=return_all; + + this->comm_dev=NULL; +} + +void *CDynamixelSlave::process_packets_thread(void *params) +{ + CDynamixelSlave *slave=(CDynamixelSlave *)param; + int event_index,num,i,num_bytes=0; + std::list<std::string> events; + unsigned char *data; + bool end=false; + + // wait until the comm device becomes valid + while(!end) + { + slave->comm_access.enter(); + if(slave->comm!=NULL) + end=true; + slave->comm_access.exit(); + } + end=false; + events.push_back(slave->comm->get_rx_event_id()); + events.push_back(slave->new_packet_available_event_id); + while(!end) + { + event_index=slave->event_server->wait_first(events); + if(event_index==0) + end=true; + else + { + // process the incomming data + num=slave->comm->get_num_data(); + data=new unsigned char[num]; + if(slave->comm->read(data,num)!=num) + std::cout << "Error while reading the communication device" << std::endl; + else + { + for(i=0;i<num;i++) + { + switch(num_bytes) + { + case 0: if(data[i]==0xFF) + { + dyn->rx_buffer[dyn->received_bytes]=byte; + dyn->received_bytes++; + } + break; + case 1: if(byte==0xFF) + { + dyn->rx_buffer[dyn->received_bytes]=byte; + dyn->received_bytes++; + } + else + dyn->received_bytes--; + break; + case 2: if(byte==0xFD)// version 2 header + { + if(dyn->version==DYN_VER2)// the module is configured for version 2 + { + dyn->rx_buffer[dyn->received_bytes]=byte; + dyn->received_bytes++; + } + else + dyn->received_bytes=0;// ignore packet and restart synchronization + } + else if(byte!=0xFF) + { + dyn->rx_buffer[dyn->received_bytes]=byte; + dyn->received_bytes++; + } + break; + case 3: dyn->rx_buffer[dyn->received_bytes]=byte; + if(dyn->version==DYN_VER1) + { + dyn->op_length=byte; + dyn->received_bytes=0; + /* finish reception by IRQ */ + comm_cancel_irq_receive(dyn->comm_dev); + /* enable dma RX */ + comm_receive_dma(dyn->comm_dev,&dyn->rx_buffer[4],dyn->op_length); + } + else + dyn->received_bytes++; + break; + case 4: dyn->rx_buffer[dyn->received_bytes]=byte; + dyn->received_bytes++; + break; + case 5: dyn->rx_buffer[dyn->received_bytes]=byte; + dyn->received_bytes++; + dyn->op_length=byte; + break; + case 6: dyn->rx_buffer[dyn->received_bytes]=byte; + dyn->received_bytes++; + dyn->op_length+=(byte<<8); + dyn->received_bytes=0; + /* finish reception by IRQ */ + comm_cancel_irq_receive(dyn->comm_dev); + /* enable dma RX */ + comm_receive_dma(dyn->comm_dev,&dyn->rx_buffer[7],dyn->op_length); + break; + default: break; + } + + } + } + } + } + + pthread_exit(NULL); +} + +void CDynamixelSlave::handle_error(unsigned char error) +{ + +} + +void CDynamixelServer::start(void) +{ + if(this->thread_server->get_thread_state(this->process_packets_thread_id)==attached) + this->thread_server->start_thread(this->process_packets_thread_id); +} + +void CDynamixelServer::stop(void) +{ + if(this->thread_server->get_thread_state(this->process_packets_thread_id)==active || this->thread_server->get_thread_state(this->process_packets_thread_id)==starting) + { + this->event_server->set_event(this->finish_thread_event_id); + this->thread_server->end_thread(this->process_packets_thread_id); + } +} + +std::string CDynamixelSlave::get_new_packet_available_event_id(void) +{ + return this->new_packet_available_event_id; +} + +void CDynamixelSlave::set_return_delay(unsigned int time_us) +{ + if(time_us<1000) + this->return_delay=time_us; + else + { + /* handle exceptions */ + } +} + +unsigned int CDynamixelSlave::get_return_delay(void) +{ + return this->return_delay; +} + +void CDynamixelSlave::set_return_level(return_level_t level) +{ + this->return_level=level; +} + +return_level_t CDynamixelSlave::get_return_level(void) +{ + return this->return_level; +} + +bool CDynamixelSlave::new_packet_available(void) +{ + if(this->event_server->event_is_set(this->new_packet_available_event_id)) + return true; + else + return false; +} + +unsigned char CDynamixelSlave::get_target_id(void) +{ + +} + +dyn_inst_t CDynamixelSlave::get_instruction_type(void) +{ + +} + +// instruction specific functions +/* read instruction */ +unsigned short int CDynamixelSlave::get_read_length(void) +{ + +} + +unsigned short int CDynamixelSlave::get_read_address(void) +{ + +} + +/* write instruction */ +unsigned short int CDynamixelSlave::get_write_address(void) +{ + +} + +unsigned short int CDynamixelSlave::get_write_length(void) +{ + +} + +void CDynamixelSlave::get_write_data(std::vector<unsigned char> &data) +{ + +} + +/* registered write instruction */ +unsigned short int CDynamixelSlave::get_reg_write_address(void) +{ + +} + +unsigned short int CDynamixelSlave::get_reg_write_length(void) +{ + +} + +void CDynamixelSlave::get_reg_write_data(std::vector<unsigned char> &data) +{ + +} + +/* sync write instruction */ +bool CDynamixelSlave::sync_write_id_present(unsigned char id,unsigned short int *address,unsigned short int *length,std::vector<unsigned char> &data) +{ + +} + +/* sync read instruction */ +bool CDynamixelSlave::sync_read_id_present(unsigned char id,unsigned short int *address,unsigned short int *length) +{ + +} + +/* bulk read instruction */ +bool CDynamixelSlave::bulk_read_id_present(unsigned char id,std::vector<unsigned short int> &address,std::vector<unsigned short int> &length) +{ + +} + +/* bulk write instruction */ +bool CDynamixelSlave::bulk_write_id_present(unsigned char id,std::vector<unsigned short int> &address,std::vector<unsigned short int> &length,std::vector<unsigned char> &data) +{ + +} + +// status return +void CDynamixelSlave::send_status_packet(unsigned char id,TDynError error,unsigned short int length,std::vector<unsigned char> &data) +{ + +} + +void CDynamixelSlave::next_packet(void) +{ + +} +CDynamixelSlave::~CDynamixelSlave() +{ + this->thread_server->detach_thread(this->process_packets_thread_id); + this->thread_server->delete_thread(this->process_packets_thread_id); + this->process_packets_thread_id=""; + + this->event_server->delete_event(this->finish_thread_event_id); + this->finish_thread_event_id=""; + this->event_server->delete_event(this->new_packet_available_event_id); + this->new_packet_available_event_id=""; +} diff --git a/src/dynamixel_slave.h b/src/dynamixel_slave.h new file mode 100644 index 0000000..7a47cd1 --- /dev/null +++ b/src/dynamixel_slave.h @@ -0,0 +1,234 @@ +#ifndef _DYNAMIXEL_SLAVE_H +#define _DYNAMIXEL_SLAVE_H + +#include "dynamixel_common.h" +#include "eventserver.h" +#include "thradserver.h" +#include "comm.h" +#include "mutex.h" +#include <stdio.h> +#include <stdlib.h> +#include <string> +#include <vector> + +/** + * \brief + * + */ +class CDynamixelSlave +{ + private: + /** + * \brief mutual exclusion mechanism to access the usb + * + */ + CMutex comm_access; + /** + * \brief Handle to the unique event server + * + */ + CEventServer *event_server; + /** + * \brief + * + */ + std::string new_packet_available_event_id; + /** + * \brief + * + */ + std::string finish_thread_event_id; + /** + * \brief + * + */ + CThreadServer *thread_server; + /** + * \brief + * + */ + std::string process_packets_thread_id; + /** + * \brief + * + */ + dyn_version_t version; + /** + * \brief + * + */ + unsigned int return_delay; + /** + * \brief + * + */ + return_level_t return_level; + protected: + /** + * \brief Handle to the communications device + * + */ + CComm *comm_dev; + /** + * \brief + * + */ + static void *process_packets_thread(void *params); + /** + * \brief + * + */ + void handle_error(unsigned char error); + /** + * \brief + * + */ + void start(void); + /** + * \brief + * + */ + void stop(void); + public: + /** + * \brief + * + */ + CDynamixelSlave(std::string& cont_id); + /** + * \brief + * + */ + std::string get_new_packet_available_event_id(void); + /** + * \brief + * + */ + virtual void set_baudrate(int baudrate)=0; + /** + * \brief + * + */ + virtual int get_baudrate(void)=0; + /** + * \brief + * + */ + void set_return_delay(unsigned int time_us); + /** + * \brief + * + */ + unsigned int get_return_delay(void); + /** + * \brief + * + */ + void set_return_level(return_level_t level); + /** + * \brief + * + */ + return_level_t get_return_level(void); + /** + * \brief + * + */ + bool new_packet_available(void); + /** + * \brief + * + */ + unsigned char get_target_id(void); + /** + * \brief + * + */ + dyn_inst_t get_instruction_type(void); + // instruction specific functions + /* read instruction */ + /** + * \brief + * + */ + unsigned short int get_read_length(void); + /** + * \brief + * + */ + unsigned short int get_read_address(void); + /* write instruction */ + /** + * \brief + * + */ + unsigned short int get_write_address(void); + /** + * \brief + * + */ + unsigned short int get_write_length(void); + /** + * \brief + * + */ + void get_write_data(std::vector<unsigned char> &data); + /* registered write instruction */ + /** + * \brief + * + */ + unsigned short int get_reg_write_address(void); + /** + * \brief + * + */ + unsigned short int get_reg_write_length(void); + /** + * \brief + * + */ + void get_reg_write_data(std::vector<unsigned char> &data); + /* sync write instruction */ + /** + * \brief + * + */ + bool sync_write_id_present(unsigned char id,unsigned short int *address,unsigned short int *length,std::vector<unsigned char> &data); + /* sync read instruction */ + /** + * \brief + * + */ + bool sync_read_id_present(unsigned char id,unsigned short int *address,unsigned short int *length); + /* bulk read instruction */ + /** + * \brief + * + */ + bool bulk_read_id_present(unsigned char id,std::vector<unsigned short int> &address,std::vector<unsigned short int> &length); + /* bulk write instruction */ + /** + * \brief + * + */ + bool bulk_write_id_present(unsigned char id,std::vector<unsigned short int> &address,std::vector<unsigned short int> &length,std::vector<unsigned char> &data); + // status return + /** + * \brief + * + */ + void send_status_packet(unsigned char id,TDynError error,unsigned short int length,std::vector<unsigned char> &data); + /** + * \brief + * + */ + void next_packet(void); + /** + * \brief + * + */ + virtual ~CDynamixelSlave(); +}; + +#endif -- GitLab