00001 #include "stdafx.h"
00002 #include "cphidgetanalog.h"
00003 #include "cusb.h"
00004 #include "csocket.h"
00005 #include "cthread.h"
00006 
00007 
00008 
00009 
00010 CPHIDGETCLEARVARS(Analog)
00011         int i = 0;
00012 
00013         for(i=0;i<ANALOG_MAXOUTPUTS;i++)
00014         {
00015                 phid->changedVoltage[i] = PUNK_BOOL;
00016                 phid->nextVoltage[i] = PUNK_DBL;
00017 
00018                 phid->changedEnabled[i] = PUNK_BOOL;
00019                 phid->nextEnabled[i] = PUNK_BOOL;
00020 
00021                 phid->enabled[i] = PUNK_BOOL;
00022                 phid->voltage[i] = PUNK_DBL;
00023 
00024                 phid->voltageEcho[i] = PUNI_DBL;
00025                 phid->enabledEcho[i] = PUNI_BOOL;
00026         }
00027         phid->voltageMax = PUNI_DBL;
00028         phid->voltageMin = PUNI_DBL;
00029 
00030         return EPHIDGET_OK;
00031 }
00032 
00033 
00034 
00035 CPHIDGETINIT(Analog)
00036         int i = 0;
00037 
00038         TESTPTR(phid);
00039 
00040         
00041         switch(phid->phid.deviceIDSpec)
00042         {
00043                 case PHIDID_ANALOG_4OUTPUT:
00044                         if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
00045                         {
00046                                 for(i=0;i<phid->phid.attr.analog.numAnalogOutputs;i++)
00047                                 {
00048                                         phid->changedVoltage[i] = PFALSE;
00049                                         phid->nextVoltage[i] = PUNK_DBL;
00050 
00051                                         phid->changedEnabled[i] = PFALSE;
00052                                         phid->nextEnabled[i] = PUNK_BOOL;
00053 
00054                                         phid->enabled[i] = PUNK_BOOL;
00055                                         phid->voltage[i] = PUNK_DBL;
00056 
00057                                         phid->voltageEcho[i] = PUNK_DBL;
00058                                         phid->enabledEcho[i] = PUNK_BOOL;
00059 
00060                                         phid->lastOvercurrent[i] = PFALSE;
00061                                 }
00062                                 phid->voltageMax = 10;
00063                                 phid->voltageMin = -10;
00064 
00065                                 phid->lastTsd = PFALSE;
00066                         }
00067                         else
00068                                 return EPHIDGET_BADVERSION;
00069                         break;
00070                 default:
00071                         return EPHIDGET_UNEXPECTED;
00072         }
00073         phid->controlPacketWaiting = PFALSE;
00074         
00075         
00076         CPhidget_read((CPhidgetHandle)phid);
00077         for(i=0;i<phid->phid.attr.analog.numAnalogOutputs;i++)
00078         {
00079                 phid->voltage[i] = phid->voltageEcho[i];
00080                 phid->enabled[i] = phid->enabledEcho[i];
00081         }
00082 
00083         return EPHIDGET_OK;
00084 }
00085 
00086 
00087 CPHIDGETDATA(Analog)
00088         int i = 0;
00089         char error_buffer[128];
00090         unsigned char overcurrent[ANALOG_MAXOUTPUTS] = {PFALSE};
00091         unsigned char tsd = PFALSE;
00092         int iVoltage;
00093 
00094         if (length < 0) return EPHIDGET_INVALIDARG;
00095         TESTPTR(phid);
00096         TESTPTR(buffer);
00097 
00098         switch(phid->phid.deviceIDSpec)
00099         {
00100                 case PHIDID_ANALOG_4OUTPUT:
00101                         if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
00102                         {
00103                                 
00104                                 
00105                                 
00106                                 
00107                                 
00108                                 
00109                                 
00110                                 
00111                                 
00112                                 
00113                                 
00114                                 for (i = 0; i < phid->phid.attr.analog.numAnalogOutputs; i++)
00115                                 {
00116                                         iVoltage =  (((signed char)buffer[i*2 + 3]) << 4) + (buffer[i*2 + 2] >> 4);
00117                                         phid->voltageEcho[i] = round_double((iVoltage * 10 / 2047.0), 3);
00118                                         phid->enabledEcho[i] = (buffer[0] & (0x01 << i)) ? PTRUE : PFALSE;
00119                                         overcurrent[i] = (buffer[0] & (0x10 << i)) ? PTRUE : PFALSE;
00120                                 }
00121                                 tsd = buffer[1];
00122                         }
00123                         else
00124                                 return EPHIDGET_UNEXPECTED;
00125                         break;
00126                 default:
00127                         return EPHIDGET_UNEXPECTED;
00128         }
00129         
00130         for (i = 0; i < phid->phid.attr.analog.numAnalogOutputs; i++)
00131         {
00132                 if(overcurrent[i] && !phid->lastOvercurrent[i])
00133                 {
00134                         FIRE_ERROR(EEPHIDGET_OVERCURRENT, "Output %d is trying to draw > 20mA - possible short circuit.", i);
00135                 }
00136                 else if(!overcurrent[i] && phid->lastOvercurrent[i])
00137                 {
00138                         FIRE_ERROR(EEPHIDGET_OK, "Output %d overcurrent state ended.", i);
00139                 }
00140                 phid->lastOvercurrent[i] = overcurrent[i];
00141         }
00142         if(tsd && !phid->lastTsd)
00143         {
00144                 FIRE_ERROR(EEPHIDGET_OVERTEMP, "Thermal shutdown detected. All outputs have been disabled.");
00145         }
00146         else if(!tsd && phid->lastTsd)
00147         {
00148                 FIRE_ERROR(EEPHIDGET_OK, "Thermal shutdown state ended.");
00149         }
00150         phid->lastTsd = tsd;
00151 
00152         return EPHIDGET_OK;
00153 }
00154 
00155 
00156 CPHIDGETINITEVENTS(Analog)
00157         phid = 0;
00158         return EPHIDGET_OK;
00159 }
00160 
00161 
00162 CGETPACKET(Analog)
00163         int i = 0;
00164         int iVoltage;
00165 
00166         CPhidgetAnalogHandle phid = (CPhidgetAnalogHandle)phidG;
00167 
00168         TESTPTRS(phid, buf)
00169         TESTPTR(lenp)
00170 
00171         if (*lenp < phid->phid.outputReportByteLength)
00172                 return EPHIDGET_INVALIDARG;
00173 
00174         CThread_mutex_lock(&phid->phid.outputLock);
00175         
00176         switch(phid->phid.deviceIDSpec)
00177         {
00178                 case PHIDID_ANALOG_4OUTPUT:
00179                         if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
00180                         {       
00181                                 
00182                                 
00183                                 
00184                                 
00185                                 
00186                                 
00187                                 
00188                                 
00189                                 
00190                                 for (i = 0; i < phid->phid.attr.analog.numAnalogOutputs; i++)
00191                                 {
00192                                         if (phid->changedVoltage[i]) {
00193                                                 phid->voltage[i] = phid->nextVoltage[i];
00194                                                 phid->changedVoltage[i] = PFALSE;
00195                                                 phid->nextVoltage[i] = PUNK_DBL;
00196                                         }
00197                                         if (phid->changedEnabled[i]) {
00198                                                 phid->enabled[i] = phid->nextEnabled[i];
00199                                                 phid->changedEnabled[i] = PFALSE;
00200                                                 phid->nextEnabled[i] = PUNK_BOOL;
00201                                         }
00202                                         
00203                                         iVoltage = round(phid->voltage[i] * 2047 / 10.0);
00204                                         buf[i*2] = iVoltage << 4;
00205                                         buf[i*2 + 1] = iVoltage >> 4;
00206                                         if(phid->enabled[i])
00207                                                 buf[0] |= 1<<i;
00208                                 }
00209                         }
00210                         else
00211                                 return EPHIDGET_UNEXPECTED;
00212                         break;
00213                 default:
00214                         return EPHIDGET_UNEXPECTED;
00215         }
00216 
00217         *lenp = phid->phid.outputReportByteLength;
00218 
00219         CThread_mutex_unlock(&phid->phid.outputLock);
00220 
00221         return EPHIDGET_OK;
00222 }
00223 
00224 
00225 
00226 static int CCONV CPhidgetAnalog_sendPacket_setVoltage(CPhidgetAnalogHandle phid, unsigned int index, double voltage)
00227 {
00228         int waitReturn;
00229         CThread_mutex_lock(&phid->phid.writelock);
00230 again:
00231         if (!CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_ATTACHED_FLAG))
00232         {
00233                 CThread_mutex_unlock(&phid->phid.writelock);
00234                 return EPHIDGET_NOTATTACHED;
00235         }
00236         CThread_mutex_lock(&phid->phid.outputLock);
00237         
00238         if (phid->changedVoltage[index]) {
00239                 
00240                 if (phid->nextVoltage[index] != voltage) {
00241                         CThread_mutex_unlock(&phid->phid.outputLock);
00242                         
00243                         waitReturn = CThread_wait_on_event(&phid->phid.writtenEvent, 2500);
00244                         switch(waitReturn)
00245                         {
00246                         case WAIT_OBJECT_0:
00247                                 break;
00248                         case WAIT_ABANDONED:
00249                                 CThread_mutex_unlock(&phid->phid.writelock);
00250                                 return EPHIDGET_UNEXPECTED;
00251                         case WAIT_TIMEOUT:
00252                                 CThread_mutex_unlock(&phid->phid.writelock);
00253                                 return EPHIDGET_TIMEOUT;
00254                         }
00255                         
00256                         goto again;
00257                 } else {
00258                         CThread_mutex_unlock(&phid->phid.outputLock);
00259                         CThread_mutex_unlock(&phid->phid.writelock);
00260                         return EPHIDGET_OK;
00261                 }
00262         
00263         } else {
00264                 
00265                 if (phid->voltage[index] != voltage) {
00266                         phid->changedVoltage[index] = PTRUE;
00267                         phid->nextVoltage[index] = voltage;
00268                         CThread_reset_event(&phid->phid.writtenEvent);
00269                         CThread_mutex_unlock(&phid->phid.outputLock);
00270                         CThread_set_event(&phid->phid.writeAvailableEvent);
00271                 }
00272                 
00273                 else
00274                 {
00275                         CThread_mutex_unlock(&phid->phid.outputLock);
00276                         CThread_mutex_unlock(&phid->phid.writelock);
00277                         return EPHIDGET_OK;
00278                 }
00279         }
00280         CThread_mutex_unlock(&phid->phid.writelock);
00281         return EPHIDGET_OK;
00282 }
00283 
00284 
00285 
00286 static int CCONV CPhidgetAnalog_sendPacket_setEnabled(CPhidgetAnalogHandle phid, unsigned int index, int enabled)
00287 {
00288         int waitReturn;
00289         CThread_mutex_lock(&phid->phid.writelock);
00290 again:
00291         if (!CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_ATTACHED_FLAG))
00292         {
00293                 CThread_mutex_unlock(&phid->phid.writelock);
00294                 return EPHIDGET_NOTATTACHED;
00295         }
00296         CThread_mutex_lock(&phid->phid.outputLock);
00297         
00298         if (phid->changedEnabled[index]) {
00299                 
00300                 if (phid->nextEnabled[index] != enabled) {
00301                         CThread_mutex_unlock(&phid->phid.outputLock);
00302                         
00303                         waitReturn = CThread_wait_on_event(&phid->phid.writtenEvent, 2500);
00304                         switch(waitReturn)
00305                         {
00306                         case WAIT_OBJECT_0:
00307                                 break;
00308                         case WAIT_ABANDONED:
00309                                 CThread_mutex_unlock(&phid->phid.writelock);
00310                                 return EPHIDGET_UNEXPECTED;
00311                         case WAIT_TIMEOUT:
00312                                 CThread_mutex_unlock(&phid->phid.writelock);
00313                                 return EPHIDGET_TIMEOUT;
00314                         }
00315                         
00316                         goto again;
00317                 } else {
00318                         CThread_mutex_unlock(&phid->phid.outputLock);
00319                         CThread_mutex_unlock(&phid->phid.writelock);
00320                         return EPHIDGET_OK;
00321                 }
00322         
00323         } else {
00324                 
00325                 if (phid->enabled[index] != enabled) {
00326                         phid->changedEnabled[index] = PTRUE;
00327                         phid->nextEnabled[index] = enabled;
00328                         CThread_reset_event(&phid->phid.writtenEvent);
00329                         CThread_mutex_unlock(&phid->phid.outputLock);
00330                         CThread_set_event(&phid->phid.writeAvailableEvent);
00331                 }
00332                 
00333                 else
00334                 {
00335                         CThread_mutex_unlock(&phid->phid.outputLock);
00336                         CThread_mutex_unlock(&phid->phid.writelock);
00337                         return EPHIDGET_OK;
00338                 }
00339         }
00340         CThread_mutex_unlock(&phid->phid.writelock);
00341         return EPHIDGET_OK;
00342 }
00343 
00344 
00345 
00346 
00347 CCREATE(Analog, PHIDCLASS_ANALOG)
00348 
00349 CGET(Analog,OutputCount,int)
00350         TESTPTRS(phid,pVal) 
00351         TESTDEVICETYPE(PHIDCLASS_ANALOG)
00352         TESTATTACHED
00353 
00354         MASGN(phid.attr.analog.numAnalogOutputs)
00355 }
00356 
00357 CGETINDEX(Analog,Voltage,double)
00358         TESTPTRS(phid,pVal)
00359         TESTDEVICETYPE(PHIDCLASS_ANALOG)
00360         TESTATTACHED
00361         TESTINDEX(phid.attr.analog.numAnalogOutputs)
00362         TESTMASGN(voltageEcho[Index], PUNK_DBL)
00363 
00364         MASGN(voltageEcho[Index])
00365 }
00366 
00367 CSETINDEX(Analog,Voltage,double)
00368         TESTPTR(phid)
00369         TESTDEVICETYPE(PHIDCLASS_ANALOG)
00370         TESTATTACHED
00371         TESTRANGE(phid->voltageMin, phid->voltageMax)
00372         TESTINDEX(phid.attr.analog.numAnalogOutputs)
00373 
00374         if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
00375                 ADDNETWORKKEYINDEXED(Voltage, "%lf", voltage);
00376         else
00377                 return CPhidgetAnalog_sendPacket_setVoltage(phid, Index, newVal);
00378 
00379         return EPHIDGET_OK;
00380 }
00381 
00382 CGETINDEX(Analog,VoltageMax,double)
00383         TESTPTRS(phid,pVal)     
00384         TESTDEVICETYPE(PHIDCLASS_ANALOG)
00385         TESTATTACHED
00386         TESTINDEX(phid.attr.analog.numAnalogOutputs)
00387         TESTMASGN(voltageMax, PUNK_DBL)
00388 
00389         MASGN(voltageMax)
00390 }
00391 
00392 CGETINDEX(Analog,VoltageMin,double)
00393         TESTPTRS(phid,pVal)     
00394         TESTDEVICETYPE(PHIDCLASS_ANALOG)
00395         TESTATTACHED
00396         TESTINDEX(phid.attr.analog.numAnalogOutputs)
00397         TESTMASGN(voltageMin, PUNK_DBL)
00398 
00399         MASGN(voltageMin)
00400 }
00401 
00402 CGETINDEX(Analog,Enabled,int)
00403         TESTPTRS(phid,pVal)
00404         TESTDEVICETYPE(PHIDCLASS_ANALOG)
00405         TESTATTACHED
00406         TESTINDEX(phid.attr.analog.numAnalogOutputs)
00407         TESTMASGN(enabledEcho[Index], PUNK_BOOL)
00408 
00409         MASGN(enabledEcho[Index])
00410 }
00411 CSETINDEX(Analog,Enabled,int)
00412         TESTPTR(phid)
00413         TESTDEVICETYPE(PHIDCLASS_ANALOG)
00414         TESTATTACHED
00415         TESTRANGE(PFALSE, PTRUE)
00416         TESTINDEX(phid.attr.analog.numAnalogOutputs)
00417 
00418         if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
00419                 ADDNETWORKKEYINDEXED(Enabled, "%d", enabled);
00420         else
00421                 return CPhidgetAnalog_sendPacket_setEnabled(phid, Index, newVal);
00422 
00423         return EPHIDGET_OK;
00424 }