cphidgetencoder.c
Go to the documentation of this file.
00001 #include "stdafx.h"
00002 #include "cphidgetencoder.h"
00003 #include <stdio.h>
00004 #include "cusb.h"
00005 #include "csocket.h"
00006 #include "cthread.h"
00007 
00008 // === Internal Functions === //
00009 
00010 //clearVars - sets all device variables to unknown state
00011 CPHIDGETCLEARVARS(Encoder)
00012         int i = 0;
00013         for (i = 0; i<ENCODER_MAXINPUTS; i++)
00014         {
00015                 phid->inputState[i] = PUNK_BOOL;
00016         }
00017         for (i = 0; i<ENCODER_MAXENCODERS; i++)
00018         {
00019                 phid->encoderPosition[i] = 0;
00020                 phid->encoderTimeStamp[i] = PUNK_INT;
00021                 phid->indexPosition[i] = PUNK_INT;
00022                 phid->enableStateEcho[i] = PUNI_BOOL;
00023         }
00024         return EPHIDGET_OK;
00025 }
00026 
00027 //initAfterOpen - sets up the initial state of an object, reading in packets from the device if needed
00028 //                                used during attach initialization - on every attach
00029 CPHIDGETINIT(Encoder)
00030         int i = 0;
00031         unsigned char buffer[8] = { 0 };
00032         int result;
00033 
00034         TESTPTR(phid);
00035 
00036         //Make sure no old writes are still pending
00037         phid->outputPacketLen = 0;
00038 
00039         //set data arrays to unknown, initial states
00040         for (i = 0; i<phid->phid.attr.encoder.numInputs; i++)
00041         {
00042                 phid->inputState[i] = PUNK_BOOL;
00043         }
00044         for (i = 0; i<phid->phid.attr.encoder.numEncoders; i++)
00045         {
00046                 phid->encoderPosition[i] = 0; //position set to zero on each attach
00047                 phid->encoderTimeStamp[i] = PUNK_INT;
00048                 phid->indexPosition[i] = PUNK_INT;
00049                 switch(phid->phid.deviceIDSpec) {
00050                         case PHIDID_ENCODER_HS_4ENCODER_4INPUT:
00051                                 phid->enableState[i] = PUNK_BOOL;
00052                                 phid->enableStateEcho[i] = PUNK_BOOL;
00053                                 break;
00054                         case PHIDID_ENCODER_1ENCODER_1INPUT:
00055                         case PHIDID_ENCODER_HS_1ENCODER:
00056                                 phid->enableState[i] = PTRUE;
00057                                 phid->enableStateEcho[i] = PTRUE;
00058                                 break;
00059                         default:
00060                                 break;
00061                 }
00062         }
00063 
00064         //send out any initial pre-read packets
00065         switch(phid->phid.deviceIDSpec) {
00066                 case PHIDID_ENCODER_1ENCODER_1INPUT:
00067                         if (phid->phid.deviceVersion <= 100)
00068                         {
00069                                 ZEROMEM(buffer,8);
00070                                 LOG(PHIDGET_LOG_INFO,"Sending workaround startup packet");
00071                                 if ((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
00072                                         return result;
00073                         }
00074                         break;
00075                 case PHIDID_ENCODER_HS_1ENCODER:
00076                 case PHIDID_ENCODER_HS_4ENCODER_4INPUT:
00077                 default:
00078                         break;
00079         }
00080 
00081         //issue a read on the 4-input HS to get enable states
00082         switch(phid->phid.deviceIDSpec) {
00083                 case PHIDID_ENCODER_HS_4ENCODER_4INPUT:
00084                         if (phid->phid.deviceVersion >= 100 && phid->phid.deviceVersion < 200)
00085                         {
00086                                 CPhidget_read((CPhidgetHandle)phid);
00087                         }
00088                         break;
00089                 case PHIDID_ENCODER_1ENCODER_1INPUT:
00090                 case PHIDID_ENCODER_HS_1ENCODER:
00091                 default:
00092                         break;
00093         }
00094 
00095         //fill in enabled states
00096         for (i = 0; i<phid->phid.attr.encoder.numEncoders; i++)
00097         {
00098                 phid->enableState[i] = phid->enableStateEcho[i];
00099         }
00100 
00101         return EPHIDGET_OK;
00102 }
00103 
00104 //dataInput - parses device packets
00105 CPHIDGETDATA(Encoder)
00106         int i=0,j=0;
00107 
00108         unsigned char input[ENCODER_MAXINPUTS];
00109         unsigned char indexTrue[ENCODER_MAXINPUTS];
00110         unsigned char enabledEcho[ENCODER_MAXINPUTS];
00111         short positionChange[ENCODER_MAXENCODERS];
00112         short indexChange[ENCODER_MAXENCODERS];
00113         int packetTime[ENCODER_MAXENCODERS];
00114         int curTime[ENCODER_MAXENCODERS];
00115         unsigned short timeChange = 0, timeStamp = 0;
00116         int timeChangeInt[ENCODER_MAXENCODERS];
00117 
00118         unsigned char lastInputState[ENCODER_MAXINPUTS];
00119 
00120         if (length<0) return EPHIDGET_INVALIDARG;
00121         TESTPTR(phid);
00122         TESTPTR(buffer);
00123 
00124         ZEROMEM(input, sizeof(input));
00125         ZEROMEM(positionChange, sizeof(positionChange));
00126         ZEROMEM(lastInputState, sizeof(lastInputState));
00127         ZEROMEM(indexTrue, sizeof(indexTrue));
00128         ZEROMEM(indexChange, sizeof(indexChange));
00129         ZEROMEM(packetTime, sizeof(packetTime));
00130         ZEROMEM(curTime, sizeof(curTime));
00131         ZEROMEM(timeChangeInt, sizeof(timeChangeInt));
00132 
00133         switch(phid->phid.deviceIDSpec)
00134         {
00135                 case PHIDID_ENCODER_1ENCODER_1INPUT:
00136                         /* OLD version here... */
00137                         if (phid->phid.deviceVersion < 110)
00138                         {
00139                                 if (buffer[1] & 0x04)
00140                                         input[0] = PFALSE;
00141                                 else
00142                                         input[0] = PTRUE;
00143 
00144                                 positionChange[0] = (signed char)buffer[2];
00145 
00146                                 timeStamp = (((unsigned short)buffer[4]) << 8) + buffer[3];
00147                         }
00148                         /* NEW version 1-encoder = 1.10+*/
00149                         else if (phid->phid.deviceVersion >= 110 && phid->phid.deviceVersion < 300)
00150                         {
00151                                 if (buffer[1] & 0x01)
00152                                         input[0] = PFALSE;
00153                                 else
00154                                         input[0] = PTRUE;
00155                                 
00156                                 positionChange[0] = (signed char)buffer[4];
00157 
00158                                 timeStamp = (((unsigned short)buffer[3]) << 8) + buffer[2];
00159                         }
00160                         else
00161                                 return EPHIDGET_UNEXPECTED;
00162                         break;
00163                 case PHIDID_ENCODER_HS_1ENCODER:
00164                         /* high speed encoder */
00165                         if (phid->phid.deviceVersion >= 300 && phid->phid.deviceVersion < 400) {
00166 
00167                                 //this will work for 8 inputs before we need to change the protocol
00168                                 //currently no high-speed encoder has any inputs
00169                                 for (i = 0, j = 1; i < (phid->phid.attr.encoder.numInputs); i++, j<<=1)
00170                                 {
00171                                         if (buffer[1] & j)
00172                                                 input[i] = PFALSE;
00173                                         else
00174                                                 input[i] = PTRUE;
00175                                 }
00176                                 
00177                                 //this will work for two encoders before we need to change the protocol
00178                                 for(i=0;i<phid->phid.attr.encoder.numEncoders;i++) {
00179                                         positionChange[i] = (((unsigned short)buffer[2*i+5]) << 8) + buffer[2*i+4];
00180                                 }
00181 
00182                                 timeStamp = (((unsigned short)buffer[3]) << 8) + buffer[2];
00183                         }
00184                         else
00185                                 return EPHIDGET_UNEXPECTED;
00186                         break;
00187                 case PHIDID_ENCODER_HS_4ENCODER_4INPUT:
00188                         /* high speed encoder 4 input, with enable and index */
00189                         if (phid->phid.deviceVersion >= 100 && phid->phid.deviceVersion < 200)
00190                         {
00191                                 //this will work for two encoders before we need to change the protocol
00192                                 for(i=0;i<phid->phid.attr.encoder.numEncoders;i++) {
00193                                         positionChange[i] = (((unsigned short)buffer[10*i+0]) << 8) + buffer[10*i+1] - 0x7fff;
00194                                         indexChange[i] = (((unsigned short)buffer[10*i+2]) << 8) + buffer[10*i+3] - 0x7fff;
00195                                         packetTime[i] = (((int)buffer[10*i+4]) << 16) + (((unsigned short)buffer[10*i+5]) << 8) + buffer[10*i+6];
00196                                         curTime[i] = (((unsigned short)buffer[10*i+7]) << 8) + buffer[10*i+8];
00197                                         indexTrue[i] = (buffer[10*i+9] & 0x01) ? PTRUE : PFALSE;
00198                                         enabledEcho[i] = (buffer[10*i+9] & 0x02) ? PTRUE : PFALSE;
00199                                         if (buffer[10*i+9] & 0x04)
00200                                                 input[i] = PFALSE;
00201                                         else
00202                                                 input[i] = PTRUE;
00203                                 }
00204                         }
00205                         else
00206                                 return EPHIDGET_UNEXPECTED;
00207                         break;
00208                 default:
00209                         return EPHIDGET_UNEXPECTED;
00210         }
00211 
00212         //Make sure values are within defined range, and store to structure
00213         for (i = 0; i < phid->phid.attr.encoder.numInputs; i++)
00214         {
00215                 lastInputState[i] = phid->inputState[i];
00216                 phid->inputState[i] = input[i];
00217         }
00218         for(i=0; i < phid->phid.attr.encoder.numEncoders; i++) 
00219         {
00220                 //check for over/undershoots
00221                 if((positionChange[i] > 0 && (phid->encoderPosition[i] + positionChange[i]) < phid->encoderPosition[i])
00222                         || (positionChange[i] < 0 && (phid->encoderPosition[i] + positionChange[i]) > phid->encoderPosition[i]))
00223                 {
00224                         char error_buffer[50];
00225                         FIRE_ERROR(EEPHIDGET_WRAP, "Encoder %d position is wrapping around.", i);
00226                 }
00227 
00228                 phid->encoderPosition[i] += positionChange[i];
00229 
00230                 //Different timing stuff for different devices
00231                 switch(phid->phid.deviceIDSpec)
00232                 {
00233                         case PHIDID_ENCODER_1ENCODER_1INPUT:
00234                         case PHIDID_ENCODER_HS_1ENCODER:
00235                                 //this handles wraparounds because we're using unsigned shorts
00236                                 timeChange = (timeStamp - phid->encoderTimeStamp[i]);
00237 
00238                                 //TODO: this misses the case where timeChange > 65 seconds - we would need to add timing to the library
00239                                 if (timeChange > 30000 || phid->encoderTimeStamp[i] == PUNK_INT)
00240                                         timeChangeInt[i] = PUNK_INT;
00241                                 else
00242                                         timeChangeInt[i] = timeChange;
00243 
00244                                 phid->encoderTimeStamp[i] = timeStamp;
00245                                 break;
00246                         case PHIDID_ENCODER_HS_4ENCODER_4INPUT:
00247                                 //timing
00248                                 if (phid->encoderTimeStamp[i] == PUNK_INT)
00249                                         phid->encoderTimeStamp[i] = 0;
00250 
00251                                 phid->encoderTimeStamp[i] += packetTime[i];
00252 
00253                                 if(positionChange[i] != 0)
00254                                 {
00255                                         timeChangeInt[i] = phid->encoderTimeStamp[i] - curTime[i];
00256                                         // convert 1/12,000,000 to microseconds
00257                                         timeChangeInt[i] = round(timeChangeInt[i] / 12.0);
00258 
00259                                         phid->encoderTimeStamp[i] = curTime[i];
00260                                 }
00261                                 //index
00262                                 if(indexTrue[i])
00263                                         phid->indexPosition[i] = phid->encoderPosition[i] - indexChange[i];
00264                                 //enabled echo
00265                                 phid->enableStateEcho[i] = enabledEcho[i];
00266                                 break;
00267                         default:
00268                                 return EPHIDGET_UNEXPECTED;
00269                 }
00270         }
00271 
00272         //send out any events for changed data
00273         for (i = 0; i < phid->phid.attr.encoder.numInputs; i++)
00274         {
00275                 if(phid->inputState[i] != lastInputState[i])
00276                         FIRE(InputChange, i, phid->inputState[i]);
00277         }
00278         for(i=0; i < phid->phid.attr.encoder.numEncoders; i++) 
00279         {
00280                 if(positionChange[i] != 0)
00281                         FIRE(PositionChange, i, timeChangeInt[i], positionChange[i]);
00282                 if(indexTrue[i])
00283                         FIRE(Index, i, phid->indexPosition[i]);
00284         }
00285 
00286         return EPHIDGET_OK;
00287 }
00288 
00289 //eventsAfterOpen - sends out an event for all valid data, used during attach initialization
00290 CPHIDGETINITEVENTS(Encoder)
00291 
00292         for (i = 0; i < phid->phid.attr.encoder.numInputs; i++)
00293         {
00294                 if (phid->inputState[i] != PUNK_BOOL)
00295                 {
00296                         FIRE(InputChange, i, phid->inputState[i]);
00297                 }
00298         }
00299         return EPHIDGET_OK;
00300 }
00301 
00302 //getPacket - used by write thread to get the next packet to send to device
00303 CGETPACKET_BUF(Encoder)
00304 
00305 //sendpacket - sends a packet to the device asynchronously, blocking if the 1-packet queue is full
00306 CSENDPACKET_BUF(Encoder)
00307 
00308 //makePacket - constructs a packet using current device state
00309 CMAKEPACKET(Encoder)
00310         int i = 0, j = 0;
00311 
00312         TESTPTRS(phid, buffer);
00313 
00314         switch(phid->phid.deviceIDSpec)
00315         {
00316                 case PHIDID_ENCODER_HS_4ENCODER_4INPUT:
00317                         if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion  < 200))
00318                         {
00319                                 //have to make sure that everything to be sent has some sort of default value if the user hasn't set a value
00320                                 for (i = 0; i<phid->phid.attr.encoder.numEncoders; i++)
00321                                 {
00322                                         if (phid->enableState[i] == PUNK_BOOL)
00323                                                 phid->enableState[i] = PFALSE;
00324                                 }
00325 
00326                                 //construct the packet
00327                                 for (i = 0, j = 1; i < phid->phid.attr.encoder.numEncoders; i++, j<<=1)
00328                                 {
00329                                         if (phid->enableState[i])
00330                                                 buffer[0] |= j;
00331                                 }
00332                         }
00333                         else
00334                                 return EPHIDGET_UNEXPECTED;
00335                         break;
00336                 case PHIDID_ENCODER_HS_1ENCODER:
00337                 case PHIDID_ENCODER_1ENCODER_1INPUT:
00338                         return EPHIDGET_UNSUPPORTED; //these versions don't have OUT packets
00339                 default:
00340                         return EPHIDGET_UNEXPECTED;
00341         }
00342         return EPHIDGET_OK;
00343 }
00344 
00345 // === Exported Functions === //
00346 
00347 //create and initialize a device structure
00348 CCREATE(Encoder, PHIDCLASS_ENCODER)
00349 
00350 //event setup functions
00351 CFHANDLE(Encoder, InputChange, int, int)
00352 CFHANDLE(Encoder, PositionChange, int, int, int)
00353 CFHANDLE(Encoder, Index, int, int)
00354 
00355 CGET(Encoder,InputCount,int)
00356         TESTPTRS(phid,pVal) 
00357         TESTDEVICETYPE(PHIDCLASS_ENCODER)
00358         TESTATTACHED
00359 
00360         MASGN(phid.attr.encoder.numInputs)
00361 }
00362 
00363 CGETINDEX(Encoder,InputState,int)
00364         TESTPTRS(phid,pVal) 
00365         TESTDEVICETYPE(PHIDCLASS_ENCODER)
00366         TESTATTACHED
00367         TESTINDEX(phid.attr.encoder.numInputs)
00368         TESTMASGN(inputState[Index], PUNK_BOOL)
00369 
00370         MASGN(inputState[Index])
00371 }
00372 
00373 CGET(Encoder,EncoderCount,int)
00374         TESTPTRS(phid,pVal) 
00375         TESTDEVICETYPE(PHIDCLASS_ENCODER)
00376         TESTATTACHED
00377 
00378         MASGN(phid.attr.encoder.numEncoders)
00379 }
00380 
00381 CGETINDEX(Encoder,Position,int)
00382         TESTPTRS(phid,pVal) 
00383         TESTDEVICETYPE(PHIDCLASS_ENCODER)
00384         TESTATTACHED
00385         TESTINDEX(phid.attr.encoder.numEncoders)
00386 
00387         MASGN(encoderPosition[Index])
00388 }
00389 CSETINDEX(Encoder,Position,int)
00390         TESTPTR(phid) 
00391         TESTDEVICETYPE(PHIDCLASS_ENCODER)
00392         TESTATTACHED
00393         TESTINDEX(phid.attr.encoder.numEncoders)
00394 
00395         if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
00396                 ADDNETWORKKEYINDEXED(ResetPosition, "%d", encoderPosition);
00397         else
00398                 phid->encoderPosition[Index] = newVal;
00399 
00400         return EPHIDGET_OK;
00401 }
00402 
00403 CGETINDEX(Encoder,IndexPosition,int)
00404         TESTPTRS(phid,pVal) 
00405         TESTDEVICETYPE(PHIDCLASS_ENCODER)
00406         TESTATTACHED
00407         TESTINDEX(phid.attr.encoder.numEncoders)
00408         TESTMASGN(indexPosition[Index], PUNK_INT)
00409 
00410         MASGN(indexPosition[Index])
00411 }
00412 
00413 CGETINDEX(Encoder,Enabled,int)
00414         TESTPTRS(phid,pVal) 
00415         TESTDEVICETYPE(PHIDCLASS_ENCODER)
00416         TESTATTACHED
00417         TESTINDEX(phid.attr.encoder.numEncoders)
00418         TESTMASGN(enableStateEcho[Index], PUNK_BOOL)
00419 
00420         MASGN(enableStateEcho[Index])
00421 }
00422 CSETINDEX(Encoder,Enabled,int)
00423         TESTPTR(phid) 
00424         TESTDEVICETYPE(PHIDCLASS_ENCODER)
00425         TESTATTACHED
00426         
00427         //Only supported on the new 4-encoder board
00428         switch(phid->phid.deviceIDSpec) {
00429                 case PHIDID_ENCODER_HS_4ENCODER_4INPUT:
00430                         TESTINDEX(phid.attr.encoder.numEncoders)
00431                         TESTRANGE(PFALSE, PTRUE)
00432                         if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
00433                                 ADDNETWORKKEYINDEXED(Enabled, "%d", enableState);
00434                         else
00435                                 SENDPACKET(Encoder, enableState[Index]);
00436                         return EPHIDGET_OK;
00437                 case PHIDID_ENCODER_1ENCODER_1INPUT:
00438                 case PHIDID_ENCODER_HS_1ENCODER:
00439                 default:
00440                         return EPHIDGET_UNSUPPORTED;
00441         }
00442 
00443 }
00444 
00445 // === Deprecated Functions === //
00446 
00447 CGETINDEX(Encoder,EncoderPosition,int)
00448         return CPhidgetEncoder_getPosition(phid, Index, pVal);
00449 }
00450 CSETINDEX(Encoder,EncoderPosition,int)
00451         return CPhidgetEncoder_setPosition(phid, Index, newVal);
00452 }
00453 CGET(Encoder,NumInputs,int)
00454         return CPhidgetEncoder_getInputCount(phid, pVal);
00455 }
00456 CGET(Encoder,NumEncoders,int)
00457         return CPhidgetEncoder_getEncoderCount(phid, pVal);
00458 }


pedal_monitor
Author(s): Pedro Mendes
autogenerated on Fri Jun 6 2014 18:37:20