/*************************************************************************** octopus.c - description ------------------- begin : Aug 2007 author : Benedikt Sauter, sauter@embedded-projects.net ***************************************************************************/ /*************************************************************************** * * * This program is free software, you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License * * version 2.1 as published by the Free Software Foundation. * * * ***************************************************************************/ /** \mainpage liboctopus API documentation Library to talk to octopus devices. You find the latest versions of liboctopus at http://www.embedded-projects.net/octopus The library is easy to use. Have a look at this short example: \include simple.c More examples can be found in the "examples" directory. */ /** \addtogroup liboctopus */ /* @{ */ #include #include #include #include "octopus.h" #include "../firmware/protocol.h" #define F_CPU 16000000UL #define octopus_error_return(code, str) do { \ octopus->error_str = str; \ return code; \ } while(0); /* * initial octopus handle before use octopus_open */ int octopus_init(struct octopus_context *octopus) { if (octopus == NULL) octopus_error_return(-1,"octopus not valid"); octopus->error_str = NULL; octopus->usb_handle = NULL; return 1; } /* * open first octopus on usb */ int octopus_open(struct octopus_context *octopus) { if (octopus_open_id(octopus,VID,PID) < 0) octopus_error_return(-1,"could not found octopus device with pid and vid"); return 1; } /* * open octopus with a given usb vendor and product id */ int octopus_open_id(struct octopus_context *octopus, int vendor, int product) { struct usb_bus *busses; struct usb_bus *bus; struct usb_device *dev; usb_init(); if (usb_find_busses() < 0) octopus_error_return(-1, "usb_find_busses() failed"); if (usb_find_devices() < 0) octopus_error_return(-2, "usb_find_devices() failed"); busses = usb_get_busses(); if (busses == NULL) octopus_error_return(-3, "usb_get_busses() failed"); for (bus = busses; bus; bus = bus->next) { for (dev = bus->devices; dev; dev = dev->next) { if (dev->descriptor.idVendor == vendor && dev->descriptor.idProduct == product) { octopus_open_dev(octopus,dev); return 1; } } } octopus_error_return(-4,"could not found octopus device with pid and vid"); return -1; } /* * open octopus with a given usb name description (not tested!) */ int octopus_open_serial(struct octopus_context *octopus, char * serial) { struct usb_bus *busses; struct usb_dev_handle* usb_handle; struct usb_bus *bus; struct usb_device *dev; char usbserial[64]; int length=0; usb_init(); if (usb_find_busses() < 0) octopus_error_return(-1, "usb_find_busses() failed"); if (usb_find_devices() < 0) octopus_error_return(-2, "usb_find_devices() failed"); busses = usb_get_busses(); if(busses==NULL) octopus_error_return(-3, "usb_get_busses() failed"); for (bus = busses; bus; bus = bus->next) { for (dev = bus->devices; dev; dev = dev->next) { usb_handle = usb_open(dev); usb_set_configuration(usb_handle,0); length = usb_get_string_simple(usb_handle,3,usbserial,64); usb_close(usb_handle); if (strncmp(serial,usbserial,length) == 0) { octopus_open_dev(octopus,dev); return 1; } } } octopus_error_return(-4,"could not found octopus device with serial number"); return -1; } /* * open octopus with a libusb dev handle */ int octopus_open_dev(struct octopus_context *octopus, struct usb_device *dev) { if (octopus == NULL) octopus_error_return(-1,"octopus handle is wrong or missing"); if (dev == NULL) octopus_error_return(-2,"device handle is wrong or missing"); if (!(octopus->usb_handle = usb_open(dev))) octopus_error_return(-3,"can't open usb device"); if (usb_set_configuration (octopus->usb_handle,dev->config[0].bConfigurationValue) < 0) octopus_error_return(-4,"can't set configuration for given usb device"); if (usb_claim_interface(octopus->usb_handle, 0) < 0) octopus_error_return(-5,"can't claim interface for given usb device"); if (usb_set_altinterface(octopus->usb_handle,0) < 0) octopus_error_return(-6,"can't set altinterface for given usb device"); return 1; } /* * close a open octopus handle */ int octopus_close(struct octopus_context *octopus) { if (octopus == NULL) octopus_error_return(-1,"octopus is not a valid handle"); if (usb_close(octopus->usb_handle) < 0) octopus_error_return(-2,usb_strerror()); return 1; } /* * send message to octopus */ int octopus_message(struct octopus_context *octopus, char *msg, int msglen, char *answer, int answerlen) { int timeout=0; if (usb_bulk_write(octopus->usb_handle,1,msg,msglen,100) < msglen) octopus_error_return(-1,"transfer error occurred"); if (answerlen>0){ while(1) { if(usb_bulk_read(octopus->usb_handle,0x81,(char*)answer,answerlen,100)>0) break; if(timeout++ >= 1000) octopus_error_return(-2,"receive error occurred"); } if(answer[1]==RSP_OK) { return 1; } else if (answer[1]==RSP_UNKOWN_CMD) { octopus_error_return(-1,"unkown command"); } else if (answer[1]==RSP_UNKOWN_PIN) { octopus_error_return(-2,"unkown pin"); } else if (answer[1]==RSP_WRONG_PIN_CONFIG) { octopus_error_return(-3,"pin is in wrong configuration"); } else if (answer[1]==RSP_ERROR) { octopus_error_return(-4,"error in usb device"); } else if (answer[1]==RSP_TIMEOUT) { octopus_error_return(-4,"timeout error in usb device"); } else { octopus_error_return(-5,"unknown error"); } } return 1; } /* * get internal device description of octopus (octopus_1, octocan_01) */ char * octopus_get_hwdesc(struct octopus_context *octopus, char *desc) { char msg[] = {CMD_GET_HW_ID,0x00,0x00}; int i; char answer[64]; for (i=0;i<64;i++) answer[i]=0; if (octopus_message(octopus,msg,3,answer,14) == RSP_OK) { if ((int)answer[2] > 0) memcpy(desc,answer+3,(int)answer[2]); return desc; } else { octopus_error_return(NULL,octopus->error_str); } return desc; } /* * use pin as gpio */ int octopus_io_init(struct octopus_context *octopus, int pin) { char answer[3]; char msg[] = {CMD_IO_INIT_PIN,0x01,0x00}; msg[2] = (char)pin; if (octopus_message(octopus,msg,3,answer,3) > 0) return 1; else return -1; } int octopus_io_init_port(struct octopus_context *octopus, int port) { char msg[] = {CMD_IO_INIT_PORT,0x01,0x00}; char answer[3]; msg[2] = (char)port; if(octopus_message(octopus,msg,3,answer,3)>0) return 1; else return -1; } int octopus_io_set_port_direction_out(struct octopus_context *octopus, int port,unsigned char mask) { char answer[3]; char msg[] = {CMD_IO_PORT_DIRECTION_OUT,0x02,0x00,0x00}; msg[2] = (char)port; msg[3] = mask; if(octopus_message(octopus,msg,4,answer,3)) return 1; else return -1; } int octopus_io_set_port_direction_in(struct octopus_context *octopus, int port, unsigned char mask) { char answer[3]; char msg[] = {CMD_IO_PORT_DIRECTION_IN,0x02,0x00,0x00}; msg[2] = (char)port; msg[3] = mask; if(octopus_message(octopus,msg,4,answer,3)) return 1; else return -1; } int octopus_io_set_port_direction_tri(struct octopus_context *octopus, int port, unsigned char mask) { char answer[3]; char msg[] = {CMD_IO_PORT_DIRECTION_TRI,0x02,0x00,0x00}; msg[2] = (char)port; msg[3] = mask; if(octopus_message(octopus,msg,4,answer,3)) return 1; else return -1; } /* * use pin as output */ int octopus_io_set_pin_direction_out(struct octopus_context *octopus, int pin) { char answer[3]; char msg[] = {CMD_IO_PIN_DIRECTION_OUT,0x01,0x00}; msg[2] = (char)pin; if (octopus_message(octopus,msg,3,answer,3) == RSP_OK) return 1; else octopus_error_return(-1,octopus->error_str); } int octopus_io_set_pin_direction_in(struct octopus_context *octopus, int pin) { char answer[3]; char msg[] = {CMD_IO_PIN_DIRECTION_IN,0x01,0x00}; msg[2] = (char)pin; if(octopus_message(octopus,msg,3,answer,3)==RSP_OK) return 1; else octopus_error_return(-1,octopus->error_str); } int octopus_io_set_pin_direction_tri(struct octopus_context *octopus, int pin) { char answer[3]; char msg[] = {CMD_IO_PIN_DIRECTION_TRI,0x01,0x00}; msg[2] = (char)pin; if(octopus_message(octopus,msg,3,answer,3)==RSP_OK) return 1; else octopus_error_return(-1,octopus->error_str); } unsigned char octopus_io_get_port(struct octopus_context *octopus, int port) { char answer[3]; char msg[] = {CMD_IO_PORT_GET,0x01,0x00}; msg[2] = (char)port; if(octopus_message(octopus,msg,3,answer,3)==RSP_OK) return (unsigned char) answer[2]; else return 0; //octopus_error_return((unsigned char)NULL,octopus->error_str); } int octopus_io_set_port(struct octopus_context *octopus, int port, unsigned char value) { char answer[3]; char msg[] = {CMD_IO_PORT_SET,0x01,0x00,0x00}; msg[2] = (char)port; msg[3] = (char)value; if(octopus_message(octopus,msg,4,answer,3)) return 1; else return -1; } int octopus_io_set_pin(struct octopus_context *octopus, int pin, int value) { char answer[3]; char msg[] = {CMD_IO_PIN_SET,0x01,0x00,0x00}; msg[2] = (char)pin; msg[3] = (char)value; if(octopus_message(octopus,msg,4,answer,3)==RSP_OK) return 1; else octopus_error_return(-1,octopus->error_str); } int octopus_io_get_pin(struct octopus_context *octopus, int pin) { char answer[3]; char msg[] = {CMD_IO_PIN_GET,0x01,0x00}; msg[2] = (char)pin; //msg[3] = 0x00; if(octopus_message(octopus,msg,3,answer,3)==RSP_OK) return (int)answer[2]; else octopus_error_return(-1,octopus->error_str); } /// part: adc int octopus_adc_init(struct octopus_context *octopus, int pin) { char answer[3]; char msg[] = {CMD_ADC_INIT_PIN,0x01,0x00}; msg[2] = (char)pin; if(octopus_message(octopus,msg,3,answer,3)>0) return 1; else return -1; } int octopus_adc_get(struct octopus_context *octopus, int pin) { unsigned char answer[4]; char msg[] = { CMD_ADC_GET, 0x01, 0x00 }; msg[2] = (char) pin; //XXX ???? if (octopus_message (octopus, msg, 3, (char *)answer, sizeof (answer)) >0) { unsigned int low = (unsigned int)answer[3]; unsigned int high = (unsigned int)answer[2]; return((int)((unsigned int)(low | (high << 8)))); } else return -1; } int octopus_adc_ref(struct octopus_context *octopus, int ref) { char answer[3]; char msg[] = {CMD_ADC_REF,0x01,0x00}; msg[2] = (char)ref; if(octopus_message(octopus,msg,3,answer,3)>0) return (int)answer[1]; else octopus_error_return(-1,octopus->error_str); } int octopus_adc_get_bulk(struct octopus_context *octopus, int pin, int number, int * buf) { return 1; } int octopus_i2c_init(struct octopus_context *octopus) { char answer[3]; char msg[] = {CMD_I2C_INIT,0x01,0x00}; if(octopus_message(octopus,msg,3,answer,3)>0) return 1; else return -1; } int octopus_i2c_deinit(struct octopus_context *octopus) { char answer[3]; char msg[] = {CMD_I2C_DEINIT,0x01,0x00}; if(octopus_message(octopus,msg,3,answer,3)>0) return 1; else return -1; } int octopus_i2c_set_bitrate(struct octopus_context *octopus, int scl_freq) { char answer[3]; char msg[] = {CMD_I2C_SET_BITRATE, 0x01, 0x00}; //XXX rounding XXX int bitrate = ((F_CPU/scl_freq)-16) / 2; msg[2] = bitrate; if(octopus_message(octopus,msg,3,answer,3)>0) return 1; else return -1; } int octopus_i2c_send_byte(struct octopus_context *octopus, char data) { char answer[3]; // cmd = cmd,len,timeout,address,data1,data2,..) char msg[] = {CMD_I2C_SEND,0x01,0x00}; msg[2] = (char)data; if(octopus_message(octopus,msg,3,answer,3)>0) return 1; else octopus_error_return(-1,octopus->error_str); } int octopus_i2c_send_bytes(struct octopus_context *octopus, char *buf, int len) { while(len > 0) { if(octopus_i2c_send_byte(octopus,buf[len--]) <= 0) return 0; } return 1; } unsigned char octopus_i2c_receive_byte(struct octopus_context *octopus, int address,int timeout) { char tmp[1]; if(octopus_i2c_receive_bytes(octopus,address,tmp,1,1)>0) return tmp[1]; else return -1; } int octopus_i2c_receive_bytes(struct octopus_context *octopus, int address,char *buf, int len, int timeout) { if(len>60){ return -1; // max 60 bytes } char msg[64] = {CMD_I2C_RECV,0x01,0x00}; msg[1] = (char)(len+4); msg[2] = (char)timeout; msg[3] = (char)address; char answer[64]; int i; if(octopus_message(octopus,msg,4,answer,len+3)>0){ for(i=0;ierror_str); return 1; } int octopus_i2c_send_start(struct octopus_context *octopus) { char answer[3]; char msg[] = {CMD_I2C_SEND_START,0x01,0x00}; if(octopus_message(octopus,msg,3,answer,3)>0) return 1; else return -1; return 1; } int octopus_i2c_send_stop(struct octopus_context *octopus) { char answer[3]; char msg[] = {CMD_I2C_SEND_STOP,0x00,0x00}; if(octopus_message(octopus,msg,3,answer,3)>0) return 1; else return -1; return 1; } /// part: SPI int octopus_spi_init(struct octopus_context *octopus) { char answer[2]; char msg[] = {CMD_SPI_INIT,0x00,0x00}; if(octopus_message(octopus,msg,3,answer,2)>0) return 1; else return -1; } int octopus_spi_deinit(struct octopus_context *octopus) { char answer[2]; char msg[] = {CMD_SPI_DEINIT,0x00,0x00}; if(octopus_message(octopus,msg,3,answer,2)>0) return 1; else return -1; } int octopus_spi_speed(struct octopus_context *octopus, int speed) { return 0; } int octopus_spi_send(struct octopus_context *octopus, unsigned char * buf, int length) { if(length>60){ return -1; // max 60 bytes } char answer[2]; // cmd = cmd,len,timeout,address,data1,data2,..) char msg[64] = {CMD_SPI_SEND,0x01,0x00}; msg[1] = (char)(length); // build send array int i; for(i=0;i0) return 1; else octopus_error_return(-1,octopus->error_str); return 1; } int octopus_spi_recv(struct octopus_context *octopus, unsigned char * buf, int length) { if(length>60){ return -1; // max 60 bytes } char answer[64]; char msg[64] = {CMD_SPI_RECV,0x01,0x00}; msg[1] = (char)(length); int i; if(octopus_message(octopus,msg,2,answer,2+length)>0) { for(i=0;ierror_str); } int octopus_spi_send_and_recv(struct octopus_context *octopus, unsigned char * buf, int length) { if(length>60){ return -1; // max 60 bytes } char answer[2]; // cmd = cmd,len,timeout,address,data1,data2,..) char msg[64] = {CMD_SPI_SEND_AND_RECV,0x01,0x00}; msg[1] = (char)(length); // build send array int i; for(i=0;i0) { for(i=0;ierror_str); return 1; } /// part: Flash 93c46 int octopus_93c46_init(struct octopus_context *octopus) { char answer[3]; char msg[] = {CMD_EXTERNAL_DEVICE,0x00,CMD_EXTERNAL_93C46,CMD_93C46_INIT}; msg[1] = 4; if(octopus_message(octopus,msg,4,answer,3)>0) return 1; else return -1; } int octopus_93c46_deinit(struct octopus_context *octopus) { char answer[3]; char msg[] = {CMD_EXTERNAL_DEVICE,CMD_EXTERNAL_93C46,CMD_93C46_DEINIT}; if (octopus_message(octopus,msg,3,answer,3) > 0) return 1; else return -1; } int octopus_93c46_write(struct octopus_context *octopus, unsigned char address, int length, unsigned char * buf) { /* if(length>59){ return -1; // max 60 bytes } */ char answer[3]; // cmd = cmd,len,timeout,address,data1,data2,..) char msg[150] = {CMD_EXTERNAL_DEVICE,0x00,CMD_EXTERNAL_93C46,CMD_93C46_WRITE}; msg[1] = (unsigned char)(6 + length); msg[4] = (unsigned char)(address); msg[5] = (unsigned char)(length); // build send array int i; for(i=0;i0) return 1; else octopus_error_return(-1,octopus->error_str); return 1; } int octopus_93c46_read(struct octopus_context *octopus, unsigned char address, int length, unsigned char * buf) { /* if(length>59) { return -1; // max 60 bytes }*/ char answer[150]; char msg[6] = {CMD_EXTERNAL_DEVICE,0x00,CMD_EXTERNAL_93C46,CMD_93C46_READ}; msg[1] = 6; msg[4] = (unsigned char)(address); msg[5] = (unsigned char)(length); int i; if (octopus_message(octopus, msg, 6, answer, 2 + length) > 0) { for(i=0;ierror_str); } /// part: PWM int octopus_pwm_init(struct octopus_context *octopus, int pin) { char answer[3]; char msg[] = {CMD_PWM_INIT_PIN,0x01,0x00}; msg[2] = (char)pin; if(octopus_message(octopus,msg,3,answer,3)>0) return 1; else return -1; } int octopus_pwm_deinit(struct octopus_context *octopus, int pin) { char answer[3]; char msg[] = {CMD_PWM_DEINIT_PIN,0x01,0x00}; msg[2] = (char)pin; if(octopus_message(octopus,msg,3,answer,3)>0) return 1; else return -1; } int octopus_pwm_speed(struct octopus_context *octopus, int pin, int speed) { char answer[3]; char msg[] = {CMD_PWM_SPEED,0x02,0x00,0x00}; msg[2] = (char)pin; msg[3] = (char)speed; if(octopus_message(octopus,msg,4,answer,3)>0) return 1; else return -1; } int octopus_pwm_value(struct octopus_context *octopus, int pin, unsigned char value) { char answer[3]; char msg[] = {CMD_PWM_VALUE,0x02,0x00,0x00}; msg[2] = (char)pin; msg[3] = (char)value; if(octopus_message(octopus,msg,4,answer,3)>0) return 1; else return -1; } ;