[external] / libphidgets / src / interfacekit.c
Project Root:

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.
 */

CVS Admin

Powered by ViewCVS 1.0-dev
(Powered by ViewCVS)

ViewCVS and CVS Help