summaryrefslogtreecommitdiff
path: root/liboctopus/octopus.c
diff options
context:
space:
mode:
Diffstat (limited to 'liboctopus/octopus.c')
-rw-r--r--liboctopus/octopus.c815
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;
+}
+
+;