external: libphidgets/src/interfacekit.c
File:
[external] /
libphidgets /
src / interfacekit.c
(
download)
(
as text)
Revision:
1.5,
Sun Feb 20 19:14:48 2005 UTC (5 years, 6 months ago) by
krafft
Branch:
MAIN
CVS Tags:
libphidgets_0_3_6-1, libphidgets_0_3_5-1, HEAD
Changes since
1.4: +1 -1 lines
see ChangeLog
also changed copyright to 2003-2005.
#define PHIDGETS_INTERNAL
/*
* File: interfacekit.c
* Author: Jason Watson <jason.watson@agrios.net>
* Date: 16-SEP-2004
*
* ChangeLog:
* 15-OCT-2004 - jdw - Digital inputs and outputs working for IK 0/16/16.
* 16-SEP-2004 - jdw - Initial version. Cloned quadservo.c as a starting point.
*/
#include <phidgets/interfacekit.h>
#include <debug.h>
#include <assert.h>
#include <limits.h>
PhidgetInterfaceKit* phidget_new_PhidgetInterfaceKit()
{
TRACE("creating a new PhidgetInterfaceKit instance...");
PhidgetInterfaceKit* ret = (PhidgetInterfaceKit*)malloc(sizeof(PhidgetInterfaceKit));
if (!ret) {
ERROR("could not allocate memory for PhidgetInterfaceKit instance.");
return 0;
}
ret->phidget = phidget_new_Phidget();
phidget_reset_PhidgetInterfaceKit(ret);
return ret;
}
void phidget_delete_PhidgetInterfaceKit(PhidgetInterfaceKit** const ik)
{
if (!ik || !*ik) {
ERROR("cannot delete NULL PhidgetInterfaceKit.");
return;
}
free(*ik);
*ik = 0;
}
void phidget_reset_PhidgetInterfaceKit(PhidgetInterfaceKit* const ik)
{
if (!ik) {
ERROR("cannot reset NULL PhidgetInterfaceKit.");
return;
}
ik->numAnalogInputs=0;
ik->numDigitalInputs=0;
ik->numDigitalOutputs=0;
int i;
for (i=0; i<PHIDGETS_INTERFACEKIT_MAX_ANALOG_INPUTS; i++) ik->analogInput[i]=0;
for (i=0; i<PHIDGETS_INTERFACEKIT_MAX_DIGITAL_INPUTS; i++) ik->digitalInput[i]=false;
for (i=0; i<PHIDGETS_INTERFACEKIT_MAX_DIGITAL_OUTPUTS; i++) ik->digitalOutput[i]=false;
phidget_reset_Phidget(ik->phidget);
}
phidget_return phidget_interfacekit_open(PhidgetInterfaceKit* const ik, unsigned short const productid, unsigned int const serial, unsigned short const retries)
{
if (!phidget_is_initialised()) {
ERROR("cannot open PhidgetInterfaceKit when Phidgets library has not been initialised.")
return PHIDGET_RET_NOT_INITIALISED;
}
if (!ik) {
ERROR("cannot open NULL PhidgetInterfaceKit.");
return PHIDGET_RET_INVALID_PARAMETER;
}
if (phidget_interfacekit_is_opened(ik)) {
ERROR("cannot open already opened PhidgetInterfaceKit.");
return PHIDGET_RET_DEVICE_ALREADY_OPENED;
}
switch (productid)
{
case PHIDGETS_USB_PRODUCTID_INTERFACEKIT_0_0_4:
ik->numAnalogInputs=0;
ik->numDigitalInputs=0;
ik->numDigitalOutputs=4;
break;
case PHIDGETS_USB_PRODUCTID_INTERFACEKIT_0_16_16:
ik->numAnalogInputs=0;
ik->numDigitalInputs=16;
ik->numDigitalOutputs=16;
break;
case PHIDGETS_USB_PRODUCTID_INTERFACEKIT_8_8_8:
ik->numAnalogInputs=8;
ik->numDigitalInputs=8;
ik->numDigitalOutputs=8;
break;
case PHIDGETS_USB_PRODUCTID_INTERFACEKIT_0_5_7:
ik->numAnalogInputs=0;
ik->numDigitalInputs=5;
ik->numDigitalOutputs=7;
break;
case PHIDGETS_USB_PRODUCTID_INTERFACEKIT_0_8_8:
ik->numAnalogInputs=0;
ik->numDigitalInputs=8;
ik->numDigitalOutputs=8;
break;
default:
ERROR("invalid or unsupported productid.");
return PHIDGET_RET_INVALID_PARAMETER;
}
TRACE("opening PhidgetInterfaceKit %d/%d/%d with serial number %d...", ik->numAnalogInputs, ik->numDigitalInputs, ik->numDigitalOutputs, serial);
HIDInterfaceMatcher matcher;
matcher.vendor_id = PHIDGETS_USB_VENDORID;
matcher.product_id = productid;
phidget_return ret = phidget_open(ik->phidget, 0, &matcher, serial, retries);
if (ret != PHIDGET_RET_SUCCESS) return ret;
NOTICE("successfully opened PhidgetInterfaceKit %s...", ik->phidget->id);
return PHIDGET_RET_SUCCESS;
}
phidget_return phidget_interfacekit_close(PhidgetInterfaceKit* const ik)
{
if (!ik) {
ERROR("cannot close NULL PhidgetInterfaceKit.");
return PHIDGET_RET_INVALID_PARAMETER;
}
if (phidget_interfacekit_is_opened(ik)) {
TRACE("closing PhidgetInterfaceKit %s...", ik->phidget->id);
phidget_return ret = phidget_close(ik->phidget);
if (ret != PHIDGET_RET_SUCCESS) return ret;
}
else WARNING("attempt to close unopened PhidgetInterfaceKit.");
NOTICE("successfully closed PhidgetInterfaceKit %s.", ik->phidget->id);
return PHIDGET_RET_SUCCESS;
}
bool phidget_interfacekit_is_opened(PhidgetInterfaceKit const* const ik)
{
if (!ik) WARNING("attempt to query open status of NULL PhidgetInterfaceKit.");
return ik && phidget_is_opened(ik->phidget);
}
phidget_return phidget_interfacekit_analoginputs_getcurrentstate(PhidgetInterfaceKit* const ik)
{
if (!phidget_interfacekit_is_opened(ik)) {
ERROR("cannot get interfacekit values of unopened PhidgetInterfaceKit.");
return PHIDGET_RET_DEVICE_NOT_OPENED;
}
if (ik->numAnalogInputs < 1)
{
ERROR("No analog inputs on this InterfaceKit.");
return PHIDGET_RET_INVALID_PARAMETER;
}
ERROR("not implemented yet");
return PHIDGET_RET_NOT_INITIALISED;
}
phidget_return phidget_interfacekit_digitalinputs_getcurrentstate(PhidgetInterfaceKit* const ik)
{
if (!phidget_interfacekit_is_opened(ik)) {
ERROR("cannot get interfacekit values of unopened PhidgetInterfaceKit.");
return PHIDGET_RET_DEVICE_NOT_OPENED;
}
if (ik->numDigitalInputs < 1)
{
ERROR("No digital inputs on this InterfaceKit.");
return PHIDGET_RET_INVALID_PARAMETER;
}
// get packet ready
char packet[PHIDGETS_INTERFACEKIT_USB_PACKET_LENGTH];
int i;
for (i=0; i<PHIDGETS_INTERFACEKIT_USB_PACKET_LENGTH; packet[i++]=0); // init packet all zero
// query board
usb_interrupt_read(ik->phidget->hid_iface->dev_handle, 1, \
packet, PHIDGETS_INTERFACEKIT_USB_PACKET_LENGTH, PHIDGETS_USB_TIMEOUT);
TRACE("got usb_interrupt_read DigitalInput currentstate packet 0x[%02hhx %02hhx %02hhx %02hhx] from PhidgetInterfaceKit %s.", packet[0], packet[1], packet[2], packet[3], ik->phidget->id);
// copy packet bytes to object values
// bits of first 2 bytes hold values of input states
int curDI=0, curByte=0, curBit=0;
for (curDI=0; curDI < ik->numDigitalInputs; curDI++)
{
curByte=curDI / 8;
curBit=curDI % 8;
if (curByte >= PHIDGETS_INTERFACEKIT_USB_PACKET_LENGTH)
{
ERROR("Packet size not big enough to hold all values (this should not happen)");
}
else
{
ik->digitalInput[curDI]=( (packet[curByte] & (1 << curBit)) > 0);
}
}
return PHIDGET_RET_SUCCESS;
}
phidget_return phidget_interfacekit_digitaloutputs_getcurrentstate(PhidgetInterfaceKit* const ik)
{
// TODO: This does not work yet. Is it even possible to read these values from the card?
if (!phidget_interfacekit_is_opened(ik)) {
ERROR("cannot get interfacekit values of unopened PhidgetInterfaceKit.");
return PHIDGET_RET_DEVICE_NOT_OPENED;
}
char packet[PHIDGETS_INTERFACEKIT_USB_PACKET_LENGTH];
int i;
for (i=0; i<PHIDGETS_INTERFACEKIT_USB_PACKET_LENGTH; packet[i++]=0); // init packet all zero
// WARNING: This seems to work most of the time, but I've seen strange results sometimes.
// sometimes the board will say that all of the outputs are on when they are not.
// I'm not sure if I'm reading all of the correct bytes.
// query board
usb_interrupt_read(ik->phidget->hid_iface->dev_handle, 1, \
packet, PHIDGETS_INTERFACEKIT_USB_PACKET_LENGTH, PHIDGETS_USB_TIMEOUT);
TRACE("got usb_interrupt_read DigitalOutput currentstate packet 0x[%02hhx %02hhx %02hhx %02hhx] from PhidgetInterfaceKit %s.", packet[0], packet[1], packet[2], packet[3], ik->phidget->id);
// bits of first 2 bytes hold values of input states (so ignore in this function)
// bits of next 2 bytes hold values of output states
// but in a strange order
int curDO=0, curByte=0, curBit=0;
for (curDO=0; curDO < ik->numDigitalOutputs; curDO++)
{
/*
Output# Byte Bit
0 0 4
1 0 3
2 0 1
3 0 2
4 1 4
5 1 3
6 1 1
7 1 2
8 0 8
9 0 7
10 0 5
11 0 6
12 1 8
13 1 7
14 1 5
15 1 6
// case statement - the easy way out
switch(curDO)
{
case 0: curByte= 0; curBit=4; break;
case 1: curByte= 0; curBit=3; break;
case 2: curByte= 0; curBit=1; break;
case 3: curByte= 0; curBit=2; break;
case 4: curByte= 1; curBit=4; break;
case 5: curByte= 1; curBit=3; break;
case 6: curByte= 1; curBit=1; break;
case 7: curByte= 1; curBit=2; break;
case 8: curByte= 0; curBit=8; break;
case 9: curByte= 0; curBit=7; break;
case 10: curByte= 0; curBit=5; break;
case 11: curByte= 0; curBit=6; break;
case 12: curByte= 1; curBit=8; break;
case 13: curByte= 1; curBit=7; break;
case 14: curByte= 1; curBit=5; break;
case 15: curByte= 1; curBit=6; break;
}
*/
// is this better than a case statement? Hehehe...
curByte= curDO/4 - ((curDO/8)*2);
curBit = (curDO%2 + (curDO/8)*4 + (3-(curDO%2)*2) - (3-(curDO%2)*2)*((curDO/2)-(curDO/4)*2) ) % 8;
// make sure we calculated correctly
//TRACE("curDO=%d, curByte=%d, curBit=%d", curDO, curByte, curBit);
//TRACE("i.do[%d] = %02hhx << %d / cby=%d cbi=%d", curDO, (packet+2)[curByte], curBit, curByte, curBit);
if (curByte >= PHIDGETS_INTERFACEKIT_USB_PACKET_LENGTH)
{
ERROR("Packet size not big enough to hold all values (this should not happen)");
}
else
{
// the "(packet+2)" skips over the first two bytes
ik->digitalOutput[curDO]=( ((packet+2)[curByte] & (1 << curBit)) > 0);
}
}
return PHIDGET_RET_SUCCESS;
}
phidget_return phidget_interfacekit_digitaloutputs_update(PhidgetInterfaceKit* const ik)
{
if (!phidget_interfacekit_is_opened(ik))
{
ERROR("cannot set interfacekit values of unopened PhidgetInterfaceKit.");
return PHIDGET_RET_DEVICE_NOT_OPENED;
}
char packet[PHIDGETS_INTERFACEKIT_USB_PACKET_LENGTH];
int i;
for (i=0; i<PHIDGETS_INTERFACEKIT_USB_PACKET_LENGTH; packet[i++]=0); // init packet all zero
// copy object values to packet bytes
// bits of first 2 bytes control output states
int curDO=0, curByte=0, curBit=0;
for (curDO=0; curDO < ik->numDigitalOutputs; curDO++)
{
if (ik->digitalOutput[curDO]==true)
{
curByte=curDO / 8;
curBit=curDO % 8;
if (curByte >= PHIDGETS_INTERFACEKIT_USB_PACKET_LENGTH)
{
ERROR("Packet size not big enough to hold all values (this should not happen)");
}
else
{
packet[curByte] |= (1 << curBit);
}
}
}
TRACE("sending DigitalOutput packet 0x[%02hhx %02hhx %02hhx %02hhx] to PhidgetInterfaceKit %s.", packet[0], packet[1], packet[2], packet[3], ik->phidget->id);
int const path[PHIDGETS_HID_PATH_DEPTH] = { PHIDGETS_HID_PATH_1, PHIDGETS_HID_PATH_2, PHIDGETS_HID_PATH_INTERFACEKIT_DIGITAL_OUTPUT_SET };
hid_return ret = hid_set_output_report(ik->phidget->hid_iface, path, PHIDGETS_HID_PATH_DEPTH, packet, PHIDGETS_INTERFACEKIT_USB_PACKET_LENGTH);
if (ret != HID_RET_SUCCESS)
{
ik->phidget->hid_error = ret;
WARNING("failed to send packet to PhidgetInterfaceKit %s.", ik->phidget->id);
return PHIDGET_RET_HID_ERROR;
}
TRACE("successfully sent a packet to PhidgetInterfaceKit %s.", ik->phidget->id);
return PHIDGET_RET_SUCCESS;
}
bool phidget_interfacekit_digitalinputs_get_one(PhidgetInterfaceKit* const ik, unsigned short const inputnum)
{
return ik->digitalInput[inputnum];
}
bool phidget_interfacekit_digitaloutputs_get_one(PhidgetInterfaceKit* const ik, unsigned short const outputnum)
{
return ik->digitalOutput[outputnum];
}
phidget_return phidget_interfacekit_digitaloutputs_set_one(PhidgetInterfaceKit* const ik, unsigned short const outputnum, bool const outputvalue)
{
if (!phidget_interfacekit_is_opened(ik))
{
ERROR("cannot set interfacekit values of unopened PhidgetInterfaceKit.");
return PHIDGET_RET_DEVICE_NOT_OPENED;
}
if (outputnum >= ik->numDigitalOutputs || outputnum >= PHIDGETS_INTERFACEKIT_MAX_DIGITAL_OUTPUTS)
{
ERROR("No digital outputs # %d on this InterfaceKit.", outputnum);
return PHIDGET_RET_INVALID_PARAMETER;
}
TRACE("setting output # %d to %d.", outputnum, outputvalue);
// set requested single value
ik->digitalOutput[outputnum]=outputvalue;
return PHIDGET_RET_SUCCESS;
}
phidget_return phidget_interfacekit_digitaloutputs_set_all(PhidgetInterfaceKit* const ik, bool const outputvalue)
{
if (!phidget_interfacekit_is_opened(ik))
{
ERROR("cannot set interfacekit values of unopened PhidgetInterfaceKit.");
return PHIDGET_RET_DEVICE_NOT_OPENED;
}
TRACE("setting all %d outputs to %d.", ik->numDigitalOutputs, outputvalue);
// set all outputs to requested value
int curDO;
for (curDO=0; curDO < ik->numDigitalOutputs; curDO++)
{
ik->digitalOutput[curDO]=outputvalue;
}
return PHIDGET_RET_SUCCESS;
}
/* COPYRIGHT --
*
* This file is part of libphidgets, a user-space library for phidgets.
* libphidgets is (c) 2003-2005 Martin F. Krafft <krafft@ailab.ch>
* and distributed under the terms of the Artistic Licence.
* See the ./COPYING file in the source tree root for more information.
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES
* OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/