diff --git a/servo_firmware/ax12/include/dyn_slave.h b/servo_firmware/ax12/include/dyn_slave.h index 8d10a99668f2c68256b67176a953f0cad79378c6..99170561f52b897cf6ac4cd3fb19cc956cfe1d79 100644 --- a/servo_firmware/ax12/include/dyn_slave.h +++ b/servo_firmware/ax12/include/dyn_slave.h @@ -11,11 +11,10 @@ #define INST_REG_WRITE 0x04 #define INST_ACTION 0x05 #define INST_RESET 0x06 -#define INST_DIGITAL_RESET 0x07 -#define INST_SYSTEM_READ 0x0C -#define INST_SYSTEM_WRITE 0x0D +#define INST_SYNC_READ 0x82 #define INST_SYNC_WRITE 0x83 -#define INST_SYNC_REG_WRITE 0x84 +#define INST_BULK_READ 0x92 +#define INST_BULK_WRITE 0x93 // bus errors #define INSTRUCTION_ERROR 0x40 @@ -34,10 +33,21 @@ uint8_t dyn_slave_is_packet_ready(void); uint8_t dyn_slave_check_id(void); uint8_t dyn_slave_check_checksum(void); uint8_t dyn_slave_get_instruction(void); +uint8_t dyn_slave_get_received_id(void); +// read operation uint8_t dyn_slave_get_address(void); uint8_t dyn_slave_get_read_length(void); +// write operation uint8_t dyn_slave_get_write_length(void); uint8_t *dyn_slave_get_write_data(void); +// sync read operation +uint8_t dyn_slave_sync_read_id_present(void); +// sync write operation +uint8_t dyn_slave_sync_write_id_present(uint8_t **data); +// bulk read operation +uint8_t dyn_slave_bulk_read_id_present(uint8_t *address,uint8_t *length); +// bulk write operation +uint8_t dyn_slave_bulk_write_id_present(uint8_t *address,uint8_t *length,uint8_t **data); void dyn_slave_send_status(uint8_t error,uint8_t length, uint8_t *data); uint8_t dyn_slave_is_send_done(void); diff --git a/servo_firmware/ax12/include/mem.h b/servo_firmware/ax12/include/mem.h index aad100ccd8346653a77931825a937c3e987e44aa..b39ab683f5939153e6e31f3cd70a7954a49a61cb 100644 --- a/servo_firmware/ax12/include/mem.h +++ b/servo_firmware/ax12/include/mem.h @@ -51,7 +51,9 @@ #define KD_L 0X30 //48 - 0X20 R/W - Lowest byte of Punch #define KD_H 0X31 //49 - 0X00 R/W - Highest byte of Punch -extern unsigned char ram_data[50]; +#define RAM_SIZE 50 + +extern unsigned char ram_data[RAM_SIZE]; void ram_init(void); uint8_t ram_read(uint8_t address, uint8_t length, uint8_t **data); diff --git a/servo_firmware/ax12/src/comm.c b/servo_firmware/ax12/src/comm.c index bde386a84f7f6d2a4148af68f05b5c69a8b5b9c7..eef884ae0f30c6b89214cb295ee8225943576f79 100644 --- a/servo_firmware/ax12/src/comm.c +++ b/servo_firmware/ax12/src/comm.c @@ -4,6 +4,14 @@ #include "gpio.h" uint8_t dyn_error; +uint8_t tmp_data[RAM_SIZE]; +uint8_t tmp_address; +uint8_t tmp_length; +uint8_t reg_pending; +uint8_t sync_read_pending; +uint8_t sync_read_previous; +uint8_t bulk_read_pending; +uint8_t bulk_read_previous; void do_write(uint8_t address,uint8_t length,uint8_t *data) { @@ -28,11 +36,16 @@ void do_write(uint8_t address,uint8_t length,uint8_t *data) void comm_init(void) { dyn_error=NO_ERROR; + tmp_address=0x00; + tmp_length=0x00; + reg_pending=0x00; + sync_read_pending=0x00; + bulk_read_pending=0x00; } void comm_loop(void) { - uint8_t *data; + static uint8_t *data,i; if(dyn_slave_is_packet_ready()) { @@ -57,6 +70,71 @@ void comm_loop(void) else dyn_slave_send_status(dyn_error|INSTRUCTION_ERROR,0x00,0x00000000); break; + case INST_REG_WRITE: tmp_address=dyn_slave_get_address(); + tmp_length=dyn_slave_get_write_length(); + data=dyn_slave_get_write_data(); + for(i=0;i<tmp_length;i++) + tmp_data[i]=data[i]; + reg_pending=0x01; + dyn_slave_send_status(dyn_error|NO_ERROR,0x00,0x00000000); + break; + case INST_ACTION: if(reg_pending) + { + if(ram_write(tmp_address,tmp_length,tmp_data)) + { + do_write(tmp_address,tmp_length,tmp_data); + dyn_slave_send_status(dyn_error|NO_ERROR,0x00,0x00000000); + } + } + else + dyn_slave_send_status(dyn_error|INSTRUCTION_ERROR,0x00,0x00000000); + break; + case INST_RESET: + break; + case INST_SYNC_READ: sync_read_previous=dyn_slave_sync_read_id_present(); + if(sync_read_previous!=0xFF) + { + if(sync_read_previous==0x00)// first device on the list + { + if(ram_read(dyn_slave_get_address(),dyn_slave_get_read_length(),&data)) + dyn_slave_send_status(dyn_error|NO_ERROR,dyn_slave_get_read_length(),data); + else + dyn_slave_send_status(dyn_error|INSTRUCTION_ERROR,0x00,0x00000000); + } + else// sync read pending + { + tmp_address=dyn_slave_get_address(); + tmp_length=dyn_slave_get_read_length(); + sync_read_pending=0x01; + } + } + break; + case INST_SYNC_WRITE: if(dyn_slave_sync_write_id_present(&data)) + { + if(ram_write(dyn_slave_get_address(),dyn_slave_get_read_length(),data)) + do_write(dyn_slave_get_address(),dyn_slave_get_read_length(),data); + } + break; + case INST_BULK_READ: bulk_read_previous=dyn_slave_bulk_read_id_present(&tmp_address,&tmp_length); + if(bulk_read_previous!=0xFF) + { + if(bulk_read_previous==0x00)// first device on the list + { + if(ram_read(tmp_address,tmp_length,&data)) + dyn_slave_send_status(dyn_error|NO_ERROR,tmp_length,data); + else + dyn_slave_send_status(dyn_error|INSTRUCTION_ERROR,0x00,0x00000000); + } + else// sync read pending + bulk_read_pending=0x01; + } + break; + case INST_BULK_WRITE: if(dyn_slave_bulk_write_id_present(&tmp_address,&tmp_length,&data)) + { + if(ram_write(tmp_address,tmp_length,data)) + do_write(tmp_address,tmp_length,data); + } + break; default: dyn_slave_send_status(dyn_error|INSTRUCTION_ERROR,0x00,0x00000000); break; } @@ -64,6 +142,31 @@ void comm_loop(void) else dyn_slave_send_status(dyn_error|CHECKSUM_ERROR,0x00,0x00000000); } + else + { + if(sync_read_pending) + { + if(dyn_slave_get_received_id()==sync_read_previous) + { + sync_read_pending=0x00; + if(ram_read(tmp_address,tmp_length,&data)) + dyn_slave_send_status(dyn_error|NO_ERROR,tmp_length,data); + else + dyn_slave_send_status(dyn_error|INSTRUCTION_ERROR,0x00,0x00000000); + } + } + if(bulk_read_pending) + { + if(dyn_slave_get_received_id()==bulk_read_previous) + { + bulk_read_pending=0x00; + if(ram_read(tmp_address,tmp_length,&data)) + dyn_slave_send_status(dyn_error|NO_ERROR,tmp_length,data); + else + dyn_slave_send_status(dyn_error|INSTRUCTION_ERROR,0x00,0x00000000); + } + } + } } } diff --git a/servo_firmware/ax12/src/dyn_slave.c b/servo_firmware/ax12/src/dyn_slave.c index a43a39fdde5d2316bf8fa9a3676289ccae85a392..66b93b8f3c20a044bb0cc67479eb7e84da65e784 100644 --- a/servo_firmware/ax12/src/dyn_slave.c +++ b/servo_firmware/ax12/src/dyn_slave.c @@ -26,7 +26,6 @@ ISR(USART_TXC_vect) { if(dyn_slave_num_tx_bytes==dyn_slave_data[3]+4) { - dyn_slave_num_rx_bytes=0; dyn_slave_set_rx(); dyn_slave_send_done=1; } @@ -114,7 +113,7 @@ uint8_t dyn_slave_is_packet_ready(void) uint8_t dyn_slave_check_id(void) { - if(dyn_slave_id==dyn_slave_data[2]) + if(dyn_slave_id==dyn_slave_data[2] || dyn_slave_data[2]==0xFE) return 0x01; else { @@ -140,6 +139,12 @@ uint8_t dyn_slave_get_instruction(void) return dyn_slave_data[4]; } +uint8_t dyn_slave_get_received_id(void) +{ + return dyn_slave_data[2]; +} + +// read operation uint8_t dyn_slave_get_address(void) { return dyn_slave_data[5]; @@ -150,6 +155,7 @@ uint8_t dyn_slave_get_read_length(void) return dyn_slave_data[6]; } +// write operation uint8_t dyn_slave_get_write_length(void) { return dyn_slave_data[3]-3; @@ -160,6 +166,88 @@ uint8_t *dyn_slave_get_write_data(void) return &dyn_slave_data[6]; } +// sync read operation +uint8_t dyn_slave_sync_read_id_present(void) +{ + uint8_t i,num; + + num=dyn_slave_num_rx_bytes-8; + dyn_slave_num_rx_bytes=0; + for(i=0;i<num;i++) + { + if(dyn_slave_data[7+i]==dyn_slave_id) + { + if(i==0) + return 0x00; + else + return dyn_slave_data[6+i]; + } + } + return 0xFF; +} + +// sync write operation +uint8_t dyn_slave_sync_write_id_present(uint8_t **data) +{ + uint8_t i,num; + + num=(dyn_slave_num_rx_bytes-8)/(dyn_slave_data[6]+1); + dyn_slave_num_rx_bytes=0; + for(i=0;i<num;i++) + { + if(dyn_slave_data[7+i*(dyn_slave_data[6]+1)]==dyn_slave_id) + { + (*data)=&dyn_slave_data[7+i*(dyn_slave_data[6]+1)+1]; + return 0x01; + } + } + return 0x00; +} + +// bulk read operation +uint8_t dyn_slave_bulk_read_id_present(uint8_t *address,uint8_t *length) +{ + uint8_t i,num; + + num=(dyn_slave_num_rx_bytes-6)/3; + dyn_slave_num_rx_bytes=0; + for(i=0;i<num;i++) + { + if(dyn_slave_data[5+i*3]==dyn_slave_id) + { + (*address)=dyn_slave_data[6+i*3]; + (*length)=dyn_slave_data[7+i*3]; + if(i==0) + return 0x00; + else + return dyn_slave_data[5+(i-1)*3]; + } + } + return 0xFF; +} + +// bulk write operation +uint8_t dyn_slave_bulk_write_id_present(uint8_t *address,uint8_t *length,uint8_t **data) +{ + uint8_t i,num; + + num=dyn_slave_num_rx_bytes; + dyn_slave_num_rx_bytes=0; + for(i=5;i<num;) + { + if(dyn_slave_data[i]==dyn_slave_id) + { + (*address)=dyn_slave_data[i+1]; + (*length)=dyn_slave_data[i+2]; + (*data)=&dyn_slave_data[i+3]; + return 0x01; + } + else + i+=dyn_slave_data[i+2]+3; + } + return 0x00; +} + void dyn_slave_send_status(uint8_t error,uint8_t length, uint8_t *data) { uint8_t i,cs=0;