diff options
Diffstat (limited to 'liboctopus/octopus.c')
-rw-r--r-- | liboctopus/octopus.c | 815 |
1 files changed, 815 insertions, 0 deletions
diff --git a/liboctopus/octopus.c b/liboctopus/octopus.c new file mode 100644 index 0000000..5471d7b --- /dev/null +++ b/liboctopus/octopus.c @@ -0,0 +1,815 @@ +/*************************************************************************** + 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 <usb.h> +#include <string.h> +#include <errno.h> + +#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_BYTE,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_BYTES,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;i<len;i++) + buf[i]=answer[i+3]; + return (int)answer[2]; + } + else + octopus_error_return(-1,octopus->error_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;i<length;i++) + msg[i+2]=(char)buf[i]; + + if(octopus_message(octopus,msg,2+length,answer,2)>0) + 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;i<length;i++) + buf[i]=answer[i+2]; + + return 1; + } + else + octopus_error_return(-1,octopus->error_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;i<length;i++) + msg[i+2]=(char)buf[i]; + + if(octopus_message(octopus,msg,2+length,answer,2+length)>0) { + + for(i=0;i<length;i++) + buf[i]=answer[i+2]; + + return 1; + } + else + octopus_error_return(-1,octopus->error_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;i<length;i++) + msg[i+6]=(char)buf[i]; + + if(octopus_message(octopus,msg,6+length,answer,3)>0) + 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;i<length;i++) + buf[i]=answer[i+2]; + + return 1; + } + else + octopus_error_return(-1,octopus->error_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; +} + +; |