00001 #include "stdafx.h"
00002 #include "cphidgetservo.h"
00003 #include "cusb.h"
00004 #include "csocket.h"
00005 #include "cthread.h"
00006
00007
00008
00009
00010 CPHIDGETCLEARVARS(Servo)
00011 int i = 0;
00012
00013 phid->motorPositionMaxLimit = PUNI_DBL;
00014 phid->motorPositionMinLimit = PUNI_DBL;
00015 phid->fullStateEcho = PUNK_BOOL;
00016
00017 for (i = 0; i<SERVO_MAXSERVOS; i++)
00018 {
00019 phid->motorPositionMax[i] = PUNI_DBL;
00020 phid->motorPositionMin[i] = PUNI_DBL;
00021 phid->motorPosition[i] = PUNK_DBL;
00022 phid->motorEngagedState[i] = PUNK_BOOL;
00023 phid->motorPositionEcho[i] = PUNI_DBL;
00024 phid->motorEngagedStateEcho[i] = PUNI_BOOL;
00025 phid->servoParams[i].state = PUNI_BOOL;
00026 }
00027
00028 return EPHIDGET_OK;
00029 }
00030
00031
00032
00033 CPHIDGETINIT(Servo)
00034 int i = 0;
00035
00036 TESTPTR(phid);
00037
00038
00039 phid->outputPacketLen = 0;
00040
00041
00042 switch(phid->phid.deviceIDSpec)
00043 {
00044 case PHIDID_SERVO_1MOTOR:
00045 case PHIDID_SERVO_4MOTOR:
00046 if (phid->phid.deviceVersion == 200)
00047 {
00048 phid->motorPositionMaxLimit = 2550;
00049 phid->motorPositionMinLimit = 1;
00050 phid->fullStateEcho = PFALSE;
00051 }
00052 else if ((phid->phid.deviceVersion >= 300) && (phid->phid.deviceVersion < 313))
00053 {
00054 phid->motorPositionMaxLimit = 4095;
00055 phid->motorPositionMinLimit = 1;
00056 phid->fullStateEcho = PFALSE;
00057 }
00058 else if ((phid->phid.deviceVersion >= 313) && (phid->phid.deviceVersion < 400))
00059 {
00060 phid->motorPositionMaxLimit = 4095;
00061 phid->motorPositionMinLimit = 1;
00062 phid->fullStateEcho = PTRUE;
00063 }
00064 else
00065 return EPHIDGET_BADVERSION;
00066 break;
00067 case PHIDID_SERVO_1MOTOR_OLD:
00068 case PHIDID_SERVO_4MOTOR_OLD:
00069 if (phid->phid.deviceVersion == 200)
00070 {
00071 phid->motorPositionMaxLimit = 2550;
00072 phid->motorPositionMinLimit = 1;
00073 phid->fullStateEcho = PFALSE;
00074 }
00075 else
00076 return EPHIDGET_BADVERSION;
00077 break;
00078 default:
00079 return EPHIDGET_UNEXPECTED;
00080 }
00081
00082 for (i = 0; i<phid->phid.attr.servo.numMotors; i++)
00083 {
00084
00085 phid->motorPositionEcho[i] = PUNK_DBL;
00086 phid->motorEngagedStateEcho[i] = PUNK_BOOL;
00087
00088 phid->servoParams[i] = Phid_Servo_Types[getServoParameterIndex(PHIDGET_SERVO_DEFAULT)];
00089 if(phid->servoParams[i].max_us > phid->motorPositionMaxLimit)
00090 phid->motorPositionMax[i] = phid->motorPositionMaxLimit;
00091 else
00092 phid->motorPositionMax[i] = phid->servoParams[i].max_us;
00093 phid->motorPositionMin[i] = phid->servoParams[i].min_us;
00094 }
00095
00096
00097 if(phid->fullStateEcho)
00098 {
00099 CPhidget_read((CPhidgetHandle)phid);
00100 }
00101
00102
00103 for (i = 0; i<phid->phid.attr.servo.numMotors; i++)
00104 {
00105 phid->motorPosition[i] = phid->motorPositionEcho[i];
00106 phid->motorEngagedState[i] = phid->motorEngagedStateEcho[i];
00107 }
00108
00109 return EPHIDGET_OK;
00110 }
00111
00112
00113 CPHIDGETDATA(Servo)
00114 int i = 0;
00115 double position[SERVO_MAXSERVOS];
00116 double lastPosition[SERVO_MAXSERVOS];
00117
00118 if (length<0) return EPHIDGET_INVALIDARG;
00119 TESTPTR(phid);
00120 TESTPTR(buffer);
00121
00122 ZEROMEM(position, sizeof(position));
00123 ZEROMEM(lastPosition, sizeof(lastPosition));
00124
00125
00126 switch(phid->phid.deviceIDSpec)
00127 {
00128 case PHIDID_SERVO_1MOTOR:
00129 if ((phid->phid.deviceVersion >= 313) && (phid->phid.deviceVersion < 400))
00130 {
00131 position[0] = (((unsigned short)buffer[0]) << 5) + buffer[1];
00132 }
00133 else
00134 return EPHIDGET_UNEXPECTED;
00135 break;
00136 case PHIDID_SERVO_4MOTOR:
00137 if ((phid->phid.deviceVersion >= 313) && (phid->phid.deviceVersion < 400))
00138 {
00139 for (i = 0; i < phid->phid.attr.servo.numMotors; i++)
00140 {
00141 position[i] = (((unsigned short)buffer[i*2]) << 5) + buffer[(i*2) + 1];
00142 }
00143 }
00144 else
00145 return EPHIDGET_UNEXPECTED;
00146 break;
00147 case PHIDID_SERVO_1MOTOR_OLD:
00148 case PHIDID_SERVO_4MOTOR_OLD:
00149 return EPHIDGET_UNSUPPORTED;
00150 default:
00151 return EPHIDGET_UNEXPECTED;
00152 }
00153
00154
00155 for (i = 0; i < phid->phid.attr.servo.numMotors; i++)
00156 {
00157 lastPosition[i] = phid->motorPositionEcho[i];
00158 if(position[i] > phid->motorPositionMaxLimit || position[i] < phid->motorPositionMinLimit)
00159 {
00160 if(position[i] == 0)
00161 phid->motorEngagedStateEcho[i] = PFALSE;
00162 else
00163 phid->motorEngagedStateEcho[i] = PUNK_BOOL;
00164 phid->motorPositionEcho[i] = PUNK_DBL;
00165 }
00166 else
00167 {
00168 phid->motorPositionEcho[i] = position[i];
00169 phid->motorEngagedStateEcho[i] = PTRUE;
00170 }
00171 }
00172
00173
00174 for (i = 0; i < phid->phid.attr.servo.numMotors; i++)
00175 {
00176 if(phid->motorPositionEcho[i] != PUNK_DBL && phid->motorPositionEcho[i] != lastPosition[i] && phid->motorEngagedStateEcho[i] == PTRUE)
00177 {
00178 FIRE(PositionChange, i, servo_us_to_degrees(phid->servoParams[i], phid->motorPositionEcho[i], PTRUE));
00179
00180 FIRE(MotorPositionChange, i, servo_us_to_degrees(phid->servoParams[i], phid->motorPositionEcho[i], PTRUE));
00181 }
00182 }
00183
00184 return EPHIDGET_OK;
00185 }
00186
00187
00188 CPHIDGETINITEVENTS(Servo)
00189
00190 for (i = 0; i < phid->phid.attr.servo.numMotors; i++)
00191 {
00192 if(phid->motorPositionEcho[i] != PUNK_DBL && phid->motorEngagedStateEcho[i] == PTRUE)
00193 {
00194 FIRE(PositionChange, i, servo_us_to_degrees(phid->servoParams[i], phid->motorPositionEcho[i], PTRUE));
00195
00196 FIRE(MotorPositionChange, i, servo_us_to_degrees(phid->servoParams[i], phid->motorPositionEcho[i], PTRUE));
00197 }
00198 }
00199
00200 return EPHIDGET_OK;
00201 }
00202
00203
00204 CGETPACKET_BUF(Servo)
00205
00206
00207 CSENDPACKET_BUF(Servo)
00208
00209
00210 CMAKEPACKETINDEXED(Servo)
00211 int i = 0;
00212
00213 TESTPTRS(phid, buffer);
00214
00215 switch(phid->phid.deviceIDSpec)
00216 {
00217 case PHIDID_SERVO_1MOTOR:
00218 if (phid->phid.deviceVersion == 200)
00219 {
00220 buffer[0] = 0;
00221 if(phid->motorPosition[0] == PUNK_DBL || phid->motorEngagedState[0] == PFALSE)
00222 buffer[1] = 0;
00223 else
00224 buffer[1] = (unsigned char)round(phid->motorPosition[Index] / 10.0);
00225 }
00226 else if ((phid->phid.deviceVersion >= 300) && (phid->phid.deviceVersion < 400))
00227 {
00228 int microsecondPulse = 0;
00229
00230 if(phid->motorPosition[0] == PUNK_DBL || phid->motorEngagedState[0] == PFALSE)
00231 microsecondPulse = 0;
00232 else
00233 microsecondPulse = round(phid->motorPosition[0]);
00234
00235 buffer[0] = (unsigned char)(microsecondPulse & 0xFF);
00236 buffer[1] = (unsigned char)(microsecondPulse >> 8);
00237 }
00238 else
00239 return EPHIDGET_UNEXPECTED;
00240 break;
00241 case PHIDID_SERVO_4MOTOR:
00242 if (phid->phid.deviceVersion == 200)
00243 {
00244 if (Index == 0) buffer[0] = 2;
00245 if (Index == 1) buffer[0] = 3;
00246 if (Index == 2) buffer[0] = 0;
00247 if (Index == 3) buffer[0] = 1;
00248 if(phid->motorPosition[Index] == PUNK_DBL || phid->motorEngagedState[Index] == PFALSE)
00249 buffer[1] = 0;
00250 else
00251 buffer[1] = (unsigned char)round(phid->motorPosition[Index]/10.0);
00252 }
00253 else if ((phid->phid.deviceVersion >= 300) && (phid->phid.deviceVersion < 400))
00254 {
00255 int microsecondPulse[4];
00256
00257 ZEROMEM(microsecondPulse, sizeof(microsecondPulse));
00258
00259 for (i = 0; i<phid->phid.attr.servo.numMotors; i++)
00260 {
00261 if(phid->motorPosition[i] == PUNK_DBL || phid->motorEngagedState[i] == PFALSE)
00262 {
00263 microsecondPulse[i] = 0;
00264 phid->motorEngagedState[i] = PFALSE;
00265 if (!(phid->fullStateEcho))
00266 phid->motorEngagedStateEcho[i] = PFALSE;
00267 }
00268 else
00269 {
00270 microsecondPulse[i] = round(phid->motorPosition[i]);
00271 phid->motorEngagedState[i] = PTRUE;
00272 if (!(phid->fullStateEcho))
00273 phid->motorEngagedStateEcho[i] = PTRUE;
00274 }
00275 }
00276
00277 buffer[0] = (unsigned char)(microsecondPulse[0] & 0xFF);
00278 buffer[1] = (unsigned char)((microsecondPulse[0] >> 8) & 0x0F);
00279
00280 buffer[2] = (unsigned char)(microsecondPulse[1] & 0xFF);
00281 buffer[1] |= (unsigned char)((microsecondPulse[1] >> 4) & 0xF0);
00282
00283 buffer[3] = (unsigned char)(microsecondPulse[2] & 0xFF);
00284 buffer[4] = (unsigned char)((microsecondPulse[2] >> 8) & 0x0F);
00285
00286 buffer[5] = (unsigned char)(microsecondPulse[3] & 0xFF);
00287 buffer[4] |= (unsigned char)((microsecondPulse[3] >> 4) & 0xF0);
00288 }
00289 else
00290 return EPHIDGET_UNEXPECTED;
00291 break;
00292 case PHIDID_SERVO_1MOTOR_OLD:
00293 if (phid->phid.deviceVersion == 200)
00294 {
00295 buffer[0] = 0;
00296 if(phid->motorPosition[0] == PUNK_DBL || phid->motorEngagedState[0] == PFALSE)
00297 buffer[1] = (unsigned char)0;
00298 else
00299 buffer[1] = (unsigned char)round(phid->motorPosition[Index]/10.0);
00300 }
00301 else
00302 return EPHIDGET_UNEXPECTED;
00303 break;
00304 case PHIDID_SERVO_4MOTOR_OLD:
00305 if (phid->phid.deviceVersion == 200)
00306 {
00307 if (Index == 0) buffer[0] = 2;
00308 if (Index == 1) buffer[0] = 3;
00309 if (Index == 2) buffer[0] = 0;
00310 if (Index == 3) buffer[0] = 1;
00311 if(phid->motorPosition[Index] == PUNK_DBL || phid->motorEngagedState[Index] == PFALSE)
00312 buffer[1] = (unsigned char)0;
00313 else
00314 buffer[1] = (unsigned char)round(phid->motorPosition[Index]/10.0);
00315 }
00316 else
00317 return EPHIDGET_UNEXPECTED;
00318 break;
00319 default:
00320 return EPHIDGET_UNEXPECTED;
00321 }
00322
00323 return EPHIDGET_OK;
00324 }
00325
00326
00327
00328
00329 CCREATE(Servo, PHIDCLASS_SERVO)
00330
00331
00332 CFHANDLE(Servo, PositionChange, int, double)
00333
00334 CGET(Servo,MotorCount,int)
00335 TESTPTRS(phid,pVal)
00336 TESTDEVICETYPE(PHIDCLASS_SERVO)
00337 TESTATTACHED
00338
00339 MASGN(phid.attr.servo.numMotors)
00340 }
00341
00342 CGETINDEX(Servo,Position,double)
00343 TESTPTRS(phid,pVal)
00344 TESTDEVICETYPE(PHIDCLASS_SERVO)
00345 TESTATTACHED
00346 TESTINDEX(phid.attr.servo.numMotors)
00347 TESTMASGN(motorPositionEcho[Index], PUNK_DBL)
00348
00349 if(phid->motorEngagedStateEcho[Index] != PTRUE) {*pVal = PUNK_DBL; return EPHIDGET_UNKNOWNVAL;}
00350
00351 *pVal = servo_us_to_degrees(phid->servoParams[Index], phid->motorPositionEcho[Index], PTRUE);
00352 return EPHIDGET_OK;
00353 }
00354 CSETINDEX(Servo,Position,double)
00355 TESTPTR(phid)
00356 TESTDEVICETYPE(PHIDCLASS_SERVO)
00357 TESTATTACHED
00358 TESTINDEX(phid.attr.servo.numMotors)
00359 TESTRANGE(servo_us_to_degrees(phid->servoParams[Index], phid->motorPositionMin[Index], PFALSE),
00360 servo_us_to_degrees(phid->servoParams[Index], phid->motorPositionMax[Index], PFALSE))
00361
00362 newVal = servo_degrees_to_us(phid->servoParams[Index], newVal);
00363
00364
00365 if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
00366 {
00367 if(phid->motorEngagedState[Index] != PTRUE)
00368 CPhidgetServo_setEngaged(phid, Index, PTRUE);
00369 ADDNETWORKKEYINDEXED(Position, "%lE", motorPosition);
00370 }
00371 else
00372 {
00373 phid->motorEngagedState[Index] = PTRUE;
00374 SENDPACKETINDEXED(Servo, motorPosition[Index], Index);
00375 if (!(phid->fullStateEcho))
00376 {
00377 phid->motorEngagedStateEcho[Index] = PTRUE;
00378 if (phid->motorPositionEcho[Index] == PUNK_BOOL || phid->motorPositionEcho[Index] != newVal)
00379 {
00380 phid->motorPositionEcho[Index] = newVal;
00381 {
00382 FIRE(PositionChange, Index, servo_us_to_degrees(phid->servoParams[Index], newVal, PTRUE));
00383
00384 FIRE(MotorPositionChange, Index, servo_us_to_degrees(phid->servoParams[Index], newVal, PTRUE));
00385 }
00386 }
00387 }
00388 }
00389
00390 return EPHIDGET_OK;
00391 }
00392
00393 CGETINDEX(Servo,PositionMax,double)
00394 TESTPTRS(phid,pVal)
00395 TESTDEVICETYPE(PHIDCLASS_SERVO)
00396 TESTATTACHED
00397 TESTINDEX(phid.attr.servo.numMotors)
00398 TESTMASGN(motorPositionMax[Index], PUNK_DBL)
00399
00400 *pVal = servo_us_to_degrees(phid->servoParams[Index], phid->motorPositionMax[Index], PFALSE);
00401 return EPHIDGET_OK;
00402 }
00403
00404 CGETINDEX(Servo,PositionMin,double)
00405 TESTPTRS(phid,pVal)
00406 TESTDEVICETYPE(PHIDCLASS_SERVO)
00407 TESTATTACHED
00408 TESTINDEX(phid.attr.servo.numMotors)
00409 TESTMASGN(motorPositionMin[Index], PUNK_DBL)
00410
00411 *pVal = servo_us_to_degrees(phid->servoParams[Index], phid->motorPositionMin[Index], PFALSE);
00412 return EPHIDGET_OK;
00413 }
00414
00415 CGETINDEX(Servo,Engaged,int)
00416 TESTPTRS(phid,pVal)
00417 TESTDEVICETYPE(PHIDCLASS_SERVO)
00418 TESTATTACHED
00419 TESTINDEX(phid.attr.servo.numMotors)
00420 TESTMASGN(motorEngagedStateEcho[Index], PUNK_BOOL)
00421
00422 MASGN(motorEngagedStateEcho[Index])
00423 }
00424 CSETINDEX(Servo,Engaged,int)
00425 TESTPTR(phid)
00426 TESTDEVICETYPE(PHIDCLASS_SERVO)
00427 TESTATTACHED
00428 TESTINDEX(phid.attr.servo.numMotors)
00429 TESTRANGE(PFALSE, PTRUE)
00430
00431 if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
00432 ADDNETWORKKEYINDEXED(Engaged, "%d", motorEngagedState);
00433 else
00434 SENDPACKETINDEXED(Servo, motorEngagedState[Index], Index);
00435
00436 return EPHIDGET_OK;
00437 }
00438
00439 int setupNewServoParams(CPhidgetServoHandle phid, int Index, CPhidgetServoParameters params)
00440 {
00441 char newVal[256];
00442
00443
00444 if(params.servoType == PHIDGET_SERVO_RAW_us_MODE)
00445 phid->motorPositionMinLimit = 0;
00446 else
00447 phid->motorPositionMinLimit = 1;
00448
00449
00450
00451 if(params.max_us > phid->motorPositionMaxLimit)
00452 phid->motorPositionMax[Index] = phid->motorPositionMaxLimit;
00453 else
00454 phid->motorPositionMax[Index] = params.max_us;
00455
00456 phid->motorPositionMin[Index] = params.min_us;
00457
00458 if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
00459 {
00460
00461 sprintf(newVal, "%d,%lE,%lE,%lE", params.servoType, params.min_us, params.max_us, params.us_per_degree);
00462 ADDNETWORKKEYINDEXED(ServoParameters, "%s", servoParamString);
00463 }
00464
00465 phid->servoParams[Index] = params;
00466
00467 return EPHIDGET_OK;
00468 }
00469
00470 CGETINDEX(Servo,ServoType,CPhidget_ServoType)
00471 TESTPTRS(phid,pVal)
00472 TESTDEVICETYPE(PHIDCLASS_SERVO)
00473 TESTATTACHED
00474 TESTINDEX(phid.attr.servo.numMotors)
00475
00476 MASGN(servoParams[Index].servoType)
00477 }
00478
00479 CSETINDEX(Servo,ServoType,CPhidget_ServoType)
00480 TESTPTR(phid)
00481 TESTDEVICETYPE(PHIDCLASS_SERVO)
00482 TESTATTACHED
00483 TESTINDEX(phid.attr.servo.numMotors)
00484
00485 TESTRANGE(PHIDGET_SERVO_DEFAULT, PHIDGET_SERVO_USER_DEFINED-1)
00486
00487 setupNewServoParams(phid, Index, Phid_Servo_Types[getServoParameterIndex(newVal)]);
00488
00489 return EPHIDGET_OK;
00490 }
00491
00492 PHIDGET21_API int CCONV CPhidgetServo_setServoParameters(CPhidgetServoHandle phid, int Index, double min_us, double max_us, double degrees)
00493 {
00494 CPhidgetServoParameters params;
00495 TESTPTR(phid)
00496 TESTDEVICETYPE(PHIDCLASS_SERVO)
00497 TESTATTACHED
00498 TESTINDEX(phid.attr.servo.numMotors)
00499
00500
00501 if(min_us < phid->motorPositionMinLimit)
00502 return EPHIDGET_INVALIDARG;
00503 if(max_us > phid->motorPositionMaxLimit)
00504 return EPHIDGET_INVALIDARG;
00505 if(max_us <= min_us)
00506 return EPHIDGET_INVALIDARG;
00507 if(degrees <= 0 || degrees > 1440)
00508 return EPHIDGET_INVALIDARG;
00509
00510 params.servoType = PHIDGET_SERVO_USER_DEFINED;
00511 params.min_us = min_us;
00512 params.max_us = max_us;
00513 params.us_per_degree = (max_us - min_us)/degrees;
00514
00515 return setupNewServoParams(phid, Index, params);
00516 }
00517
00518
00519
00520 CFHANDLE(Servo, MotorPositionChange, int, double)
00521 CGET(Servo,NumMotors,int)
00522 return CPhidgetServo_getMotorCount(phid, pVal);
00523 }
00524 CGETINDEX(Servo,MotorPosition,double)
00525 return CPhidgetServo_getPosition(phid, Index, pVal);
00526 }
00527 CSETINDEX(Servo,MotorPosition,double)
00528 return CPhidgetServo_setPosition(phid, Index, newVal);
00529 }
00530 CGETINDEX(Servo,MotorPositionMax,double)
00531 return CPhidgetServo_getPositionMax(phid, Index, pVal);
00532 }
00533 CGETINDEX(Servo,MotorPositionMin,double)
00534 return CPhidgetServo_getPositionMin(phid, Index, pVal);
00535 }
00536 CGETINDEX(Servo,MotorOn,int)
00537 return CPhidgetServo_getEngaged(phid, Index, pVal);
00538 }
00539 CSETINDEX(Servo,MotorOn,int)
00540 return CPhidgetServo_setEngaged(phid, Index, newVal);
00541 }