home *** CD-ROM | disk | FTP | other *** search
/ Virtual Reality Homebrewer's Handbook / vr.iso / avril / drvcyman.c < prev    next >
C/C++ Source or Header  |  1996-03-19  |  5KB  |  152 lines

  1. /* Logitech Cyberman support for AVRIL */
  2.  
  3. /* Written by Bernie Roehl, July 1994 */
  4.  
  5. /* Copyright 1994 by Bernie Roehl */
  6.  
  7. /* You may use this code for your own non-commercial projects without
  8.    paying any fees or royalties.  "Non-commercial", in this context,
  9.    means that the software you write is given away for free to anyone
  10.    who wants it.
  11.    
  12.    Commercial use, including shareware, requires a licensing
  13.    fee and a specific written agreement with the author.
  14.  
  15.    All programs created using this software (both commercial and
  16.    non-commercial) must acknowledge the use of the AVRIL library,
  17.    both in the documentation and in a banner screen at the start or
  18.    end of the program.
  19.  
  20.    For more information, contact Bernie Roehl (broehl@uwaterloo.ca).
  21.  
  22. */
  23.  
  24. #include "avril.h"
  25.  
  26. static vrl_DeviceChannel cybchannel_defaults[] =
  27.     {
  28.         /* center, deadzone, range, scale, accum */
  29.         { 0, 5,  128, float2scalar(1000), 1 },  /* trans X */
  30.         { 0, 0,    1, float2scalar(1000), 1 },  /* trans Y */
  31.         { 0, 5, -128, float2scalar(1000), 1 },  /* trans Z */
  32.         { 0, 0,   -1, float2angle(20), 1 },  /* rot X */
  33.         { 0, 0,   -1, float2angle(20), 1 },  /* rot Y */
  34.         { 0, 0,    1, float2angle(20), 1 }   /* rot Z */
  35.     };
  36.  
  37. static void reset_cyberman(vrl_SerialPort *port)
  38.     {
  39.     vrl_SerialSetDTR(port, 1);  /* DTR high */
  40.     vrl_SerialSetRTS(port, 0);  /* RTS low */
  41.     vrl_TimerDelay(200);        /* spec says 100, but let's be generous */
  42.     vrl_SerialSetRTS(port, 1);  /* RTS high */
  43.     vrl_TimerDelay(400);        /* 110 for first char, 100 for second */
  44.     }
  45.  
  46. static int values[] = { 0, 1, -1, 0 };
  47.  
  48. int vrl_CybermanOutput(vrl_Device *dev, int parm1, vrl_Scalar parm2)
  49.     {
  50.     unsigned char val = ((vrl_32bit) scalar2float(parm2)) & 0xFF;
  51.     if (parm1) return -1;
  52.     vrl_SerialPutc('!', dev->port);
  53.     vrl_SerialPutc('T', dev->port);
  54.     vrl_SerialPutc(val, dev->port);
  55.     vrl_SerialPutc(255 - val, dev->port);
  56.     vrl_SerialPutc((val == 0) ? 0 : 7, dev->port);  /* 280 ms */
  57.     return 0;
  58.     }
  59.  
  60. int vrl_CybermanDevice(vrl_DeviceCommand cmd, vrl_Device *device)
  61.     {
  62.     switch (cmd)
  63.         {
  64.         case VRL_DEVICE_INIT:
  65.             if (device->port == NULL) return -4;
  66.             device->nchannels = 6;
  67.             device->channels = vrl_calloc(device->nchannels, sizeof(vrl_DeviceChannel));
  68.             if (device->channels == NULL) return -1;
  69.             device->localdata = vrl_DeviceCreatePacketBuffer(5);
  70.             if (device->localdata == NULL)
  71.                 {
  72.                 vrl_free(device->channels);
  73.                 device->channels = NULL;
  74.                 return -1;
  75.                 }
  76.             device->nbuttons = 3;
  77.             device->noutput_channels = 1;
  78.             device->outfunc = vrl_CybermanOutput;
  79.             device->desc = "Logitech Cyberman, direct serial";
  80.             device->version = 1;
  81.         case VRL_DEVICE_RESET:
  82.             vrl_SerialSetParameters(device->port, 1200, VRL_PARITY_NONE, 7, 1);
  83.             reset_cyberman(device->port);
  84.             /* look for the 'M3' identification sequence */
  85.             if (!vrl_SerialCheck(device->port)) return -2;
  86.             if (vrl_SerialGetc(device->port) != 'M') return -3;
  87.             if (!vrl_SerialCheck(device->port)) return -2;
  88.             if (vrl_SerialGetc(device->port) != '3') return -3;
  89.             /* enter Swift mode */
  90.             vrl_SerialPutc('*', device->port);  vrl_SerialPutc('S', device->port);
  91.             vrl_TimerDelay(500);
  92.             vrl_SerialSetParameters(device->port, 4800, VRL_PARITY_NONE, 8, 1);
  93.             vrl_TimerDelay(200);
  94.             vrl_SerialFlush(device->port);
  95.             /* request a Static Device Status report */
  96.             vrl_SerialPutc('!', device->port);  vrl_SerialPutc('S', device->port);
  97.             vrl_TimerDelay(500);  /* wait for the report to come in */
  98.             while (vrl_SerialCheck(device->port))
  99.                 if ((vrl_SerialGetc(device->port) & 0xE0) == 0xA0)
  100.                     break;
  101.             if (!vrl_SerialCheck(device->port))
  102.                 {
  103.                 reset_cyberman(device->port);
  104.                 return -2;  /* no report */
  105.                 }
  106.             vrl_SerialFlush(device->port);
  107.             memcpy(device->channels, cybchannel_defaults, sizeof(cybchannel_defaults));
  108.             return 0;
  109.         case VRL_DEVICE_POLL:
  110.             while (vrl_DeviceGetPacket(device->port, device->localdata))
  111.                 {
  112.                 unsigned char *p = vrl_DevicePacketGetBuffer(device->localdata);
  113.                 int x, y, i;
  114.                 unsigned int b;
  115.                 if ((p[0] & 0xE0) != 0x80) continue;  /* ignore non-data packets */
  116.                 b = p[0] & 0x1F;
  117.                 device->bchanged = b ^ device->buttons;
  118.                 device->buttons = b;
  119.                 x = (p[1] << 1) | ((p[2] >> 6) & 0x01);
  120.                 y = (p[2] << 2) | ((p[3] >> 5) & 0x03);
  121.                 if (x & 0x80) x |= 0xFF00;  /* sign extend */
  122.                 else x &= 0xFF;
  123.                 if (y & 0x80) y |= 0xFF00;  /* sign extend */
  124.                 else y &= 0xFF;
  125.                 device->channels[X].rawvalue = x;
  126.                 device->channels[Y].rawvalue = values[(p[3] >> 3) & 0x03];
  127.                 device->channels[Z].rawvalue = y;
  128.                 device->channels[XROT].rawvalue = values[(p[3] >> 1) & 0x03];
  129.                 device->channels[YROT].rawvalue = values[(p[4] >> 4) & 0x03];
  130.                 device->channels[ZROT].rawvalue = values[((p[3] << 1) | ((p[4] >> 6) & 0x01)) & 0x03];
  131.                 for (i = 0; i < 6; ++i)
  132.                     device->channels[i].changed = 1;
  133.                 }
  134.             return 0;
  135.         case VRL_DEVICE_QUIT:
  136.             reset_cyberman(device->port);
  137.             if (device->localdata)
  138.                 {
  139.                 vrl_DeviceDestroyPacketBuffer(device->localdata);
  140.                 device->localdata = NULL;
  141.                 }
  142.             if (device->channels)
  143.                 {
  144.                 vrl_free(device->channels);
  145.                 device->channels = NULL;
  146.                 }
  147.             return 0;
  148.         default: break;
  149.         }
  150.     return 1;  /* function not implemented */
  151.     }
  152.