cphidgetanalog.c
Go to the documentation of this file.
00001 #include "stdafx.h"
00002 #include "cphidgetanalog.h"
00003 #include "cusb.h"
00004 #include "csocket.h"
00005 #include "cthread.h"
00006 
00007 // === Internal Functions === //
00008 
00009 //clearVars - sets all device variables to unknown state
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 //initAfterOpen - sets up the initial state of an object, reading in packets from the device if needed
00034 //                                used during attach initialization - on every attach
00035 CPHIDGETINIT(Analog)
00036         int i = 0;
00037 
00038         TESTPTR(phid);
00039 
00040         //set data arrays to unknown
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         //issue a read - fill in data
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 //dataInput - parses device packets
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                                 // Bit-->       |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
00104                                 //Byte 0        | oc[3] | oc[2] | oc[1] | oc[0] | en[3] | en[2] | en[1] | en[0] |
00105                                 //Byte 1        |   0   |   0   |   0   |   0   |   0   |   0   |   0   |  TSD  |
00106                                 //Byte 2        |       voltage[0] bits 3-0     |   0   |   0   |   0   |   0   |
00107                                 //Byte 3        |                   voltage[0] bits 11-4                        |
00108                                 //Byte 4        |       voltage[1] bits 3-0     |   0   |   0   |   0   |   0   |
00109                                 //Byte 5        |                   voltage[1] bits 11-4                        |
00110                                 //Byte 6        |       voltage[2] bits 3-0     |   0   |   0   |   0   |   0   |
00111                                 //Byte 7        |                   voltage[2] bits 11-4                        |
00112                                 //Byte 8        |       voltage[3] bits 3-0     |   0   |   0   |   0   |   0   |
00113                                 //Byte 9        |                   voltage[3] bits 11-4                        |
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 //eventsAfterOpen - sends out an event for all valid data, used during attach initialization - not used
00156 CPHIDGETINITEVENTS(Analog)
00157         phid = 0;
00158         return EPHIDGET_OK;
00159 }
00160 
00161 //getPacket - used by write thread to get the next packet to send to device
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                                 // Bit-->       |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
00182                                 //Byte 0        |       voltage[0] bits 3-0     | en[3] | en[2] | en[1] | en[0] |
00183                                 //Byte 1        |                   voltage[0] bits 11-4                        |
00184                                 //Byte 2        |       voltage[1] bits 3-0     |   0   |   0   |   0   |   0   |
00185                                 //Byte 3        |                   voltage[1] bits 11-4                        |
00186                                 //Byte 4        |       voltage[2] bits 3-0     |   0   |   0   |   0   |   0   |
00187                                 //Byte 5        |                   voltage[2] bits 11-4                        |
00188                                 //Byte 6        |       voltage[3] bits 3-0     |   0   |   0   |   0   |   0   |
00189                                 //Byte 7        |                   voltage[3] bits 11-4                        |
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                                         //fill in buffer
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 //sends a packet to the device asynchronously, blocking if the 1-packet queue is full
00225 //      -every channel has its own 1 state mini-queue
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         //if we have already requested a change on this channel
00238         if (phid->changedVoltage[index]) {
00239                 //and it was different then this time
00240                 if (phid->nextVoltage[index] != voltage) {
00241                         CThread_mutex_unlock(&phid->phid.outputLock);
00242                         //then wait for it to get written
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                         //and try again
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         //otherwise
00263         } else {
00264                 //if it's different then current, queue it up
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                 //if it's the same, just return
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 //sends a packet to the device asynchronously, blocking if the 1-packet queue is full
00285 //      -every channel has its own 1 state mini-queue
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         //if we have already requested a change on this channel
00298         if (phid->changedEnabled[index]) {
00299                 //and it was different then this time
00300                 if (phid->nextEnabled[index] != enabled) {
00301                         CThread_mutex_unlock(&phid->phid.outputLock);
00302                         //then wait for it to get written
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                         //and try again
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         //otherwise
00323         } else {
00324                 //if it's different then current, queue it up
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                 //if it's the same, just return
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 // === Exported Functions === //
00345 
00346 //create and initialize a device structure
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 }


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