diff options
Diffstat (limited to 'cphidgetled.c')
-rw-r--r-- | cphidgetled.c | 483 |
1 files changed, 328 insertions, 155 deletions
diff --git a/cphidgetled.c b/cphidgetled.c index 5c7bfd5..bcfe54a 100644 --- a/cphidgetled.c +++ b/cphidgetled.c @@ -20,6 +20,7 @@ CPHIDGETCLEARVARS(LED) phid->nextLED_Power[i] = PUNK_DBL; phid->LED_PowerEcho[i] = PUNK_DBL; + phid->LED_CurrentLimitEcho[i] = PUNK_DBL; phid->outputEnabledEcho[i] = PUNK_BOOL; phid->ledOpenDetectEcho[i] = PUNK_BOOL; @@ -28,7 +29,11 @@ CPHIDGETCLEARVARS(LED) phid->voltage = PHIDGET_LED_VOLTAGE_2_75V; phid->currentLimit = PHIDGET_LED_CURRENT_LIMIT_20mA; phid->faultEcho = PUNK_BOOL; - phid->TSDCount=0; + for(i=0;i<4;i++) + { + phid->TSDCount[i]=0; + phid->TWarnCount[i]=0; + } phid->PGoodErrState = PFALSE; phid->powerGoodEcho = PUNK_BOOL; phid->outputEnableEcho = PUNK_BOOL; @@ -66,6 +71,7 @@ CPHIDGETINIT(LED) phid->nextLED_Power[i] = PUNK_DBL; phid->LED_PowerEcho[i] = PUNK_DBL; + phid->LED_CurrentLimitEcho[i] = PUNK_DBL; phid->outputEnabledEcho[i] = PUNK_BOOL; phid->ledOpenDetectEcho[i] = PUNK_BOOL; @@ -78,11 +84,16 @@ CPHIDGETINIT(LED) phid->powerGoodEcho = PUNK_BOOL; phid->PGoodErrState = PFALSE; phid->outputEnableEcho = PUNK_BOOL; - phid->voltageEcho = -1; - phid->currentLimitEcho = -1; + phid->voltageEcho = 0; + phid->currentLimitEcho = 0; - phid->TSDCount=0; - phid->TSDClearCount = 0; + for(i=0;i<4;i++) + { + phid->TSDCount[i]=0; + phid->TSDClearCount[i] = 0; + phid->TWarnCount[i]=0; + phid->TWarnClearCount[i] = 0; + } phid->lastOutputPacket = 0; break; default: @@ -95,7 +106,6 @@ CPHIDGETINIT(LED) switch(phid->phid.deviceUID) { case PHIDUID_LED_64_ADV: - case PHIDUID_LED_64_ADV_M3: //need two reads to get the full state CPhidget_read((CPhidgetHandle)phid); CPhidget_read((CPhidgetHandle)phid); @@ -108,11 +118,27 @@ CPHIDGETINIT(LED) phid->lastLED_Power[i] = phid->LED_PowerEcho[i]; } - if(phid->voltageEcho != -1) + if(phid->voltageEcho > 0) phid->voltage = phid->voltageEcho; - if(phid->currentLimitEcho != -1) + if(phid->currentLimitEcho > 0) phid->currentLimit = phid->currentLimitEcho; break; + case PHIDUID_LED_64_ADV_M3: + //need three reads to get the full state + CPhidget_read((CPhidgetHandle)phid); + CPhidget_read((CPhidgetHandle)phid); + CPhidget_read((CPhidgetHandle)phid); + + for(i=0;i<phid->phid.attr.led.numLEDs;i++) + { + phid->LED_Power[i] = phid->LED_PowerEcho[i]; + phid->LED_CurrentLimit[i] = phid->LED_CurrentLimitEcho[i]; + } + + if(phid->voltageEcho > 0) + phid->voltage = phid->voltageEcho; + + break; case PHIDUID_LED_64: default: break; @@ -133,130 +159,275 @@ CPHIDGETDATA(LED) switch(phid->phid.deviceUID) { case PHIDUID_LED_64_ADV: - if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200)) + switch(buffer[0] & 0x80) { - switch(buffer[0] & 0x80) - { - case LED64_IN_LOW_PACKET: - //PowerGood - if(buffer[0] & LED64_PGOOD_FLAG) - { - phid->PGoodErrState = PFALSE; - phid->powerGoodEcho = PTRUE; - } - else - { - phid->powerGoodEcho = PFALSE; - } + case LED64_IN_LOW_PACKET: + //PowerGood + if(buffer[0] & LED64_PGOOD_FLAG) + { + phid->PGoodErrState = PFALSE; + phid->powerGoodEcho = PTRUE; + } + else + { + phid->powerGoodEcho = PFALSE; + } - //all outputs enabled (power on/off) - if(buffer[0] & LED64_OE_FLAG) - phid->outputEnableEcho = PTRUE; - else - phid->outputEnableEcho = PFALSE; + //all outputs enabled (power on/off) + if(buffer[0] & LED64_OE_FLAG) + phid->outputEnableEcho = PTRUE; + else + phid->outputEnableEcho = PFALSE; - //fault - if(buffer[0] & LED64_FAULT_FLAG) - phid->faultEcho = PTRUE; - else - phid->faultEcho = PFALSE; + //fault + if(buffer[0] & LED64_FAULT_FLAG) + phid->faultEcho = PTRUE; + else + phid->faultEcho = PFALSE; - //current limit - if(buffer[0] & LED64_CURSELA_FLAG) - { - if(buffer[0] & LED64_CURSELB_FLAG) - phid->currentLimitEcho = PHIDGET_LED_CURRENT_LIMIT_80mA; - else - phid->currentLimitEcho = PHIDGET_LED_CURRENT_LIMIT_40mA; - } - else if (buffer[0] & LED64_CURSELB_FLAG) - phid->currentLimitEcho = PHIDGET_LED_CURRENT_LIMIT_60mA; + //current limit + if(buffer[0] & LED64_CURSELA_FLAG) + { + if(buffer[0] & LED64_CURSELB_FLAG) + phid->currentLimitEcho = PHIDGET_LED_CURRENT_LIMIT_80mA; else - phid->currentLimitEcho = PHIDGET_LED_CURRENT_LIMIT_20mA; - - //voltage - if(buffer[0] & LED64_PWRSELA_FLAG) - { - if(buffer[0] & LED64_PWRSELB_FLAG) - phid->voltageEcho = PHIDGET_LED_VOLTAGE_5_0V; - else - phid->voltageEcho = PHIDGET_LED_VOLTAGE_2_75V; - } - else if (buffer[0] & LED64_PWRSELB_FLAG) - phid->voltageEcho = PHIDGET_LED_VOLTAGE_3_9V; + phid->currentLimitEcho = PHIDGET_LED_CURRENT_LIMIT_40mA; + } + else if (buffer[0] & LED64_CURSELB_FLAG) + phid->currentLimitEcho = PHIDGET_LED_CURRENT_LIMIT_60mA; + else + phid->currentLimitEcho = PHIDGET_LED_CURRENT_LIMIT_20mA; + + //voltage + if(buffer[0] & LED64_PWRSELA_FLAG) + { + if(buffer[0] & LED64_PWRSELB_FLAG) + phid->voltageEcho = PHIDGET_LED_VOLTAGE_5_0V; else - phid->voltageEcho = PHIDGET_LED_VOLTAGE_1_7V; + phid->voltageEcho = PHIDGET_LED_VOLTAGE_2_75V; + } + else if (buffer[0] & LED64_PWRSELB_FLAG) + phid->voltageEcho = PHIDGET_LED_VOLTAGE_3_9V; + else + phid->voltageEcho = PHIDGET_LED_VOLTAGE_1_7V; + + for(i=0;i<phid->phid.attr.led.numLEDs;i++) + { + phid->outputEnabledEcho[i] = (buffer[(i/8)+1] & (1 << (i%8))) ? 1 : 0; + phid->ledOpenDetectEcho[i] = (buffer[(i/8)+9] & (1 << (i%8))) ? 1 : 0; + } + + //1st 24 LED powers + for(i=0;i<24;i++) + { + double ledPowerTemp; + ledPowerTemp = ((double)buffer[i+17] / 127.0) * 100.0; + phid->LED_PowerEcho[i] = ledPowerTemp; + } + + //We can guess that the fault is a TSD if there is no LOD + if(phid->faultEcho) + { + phid->TSDCount[0]++; + phid->TSDClearCount[0] = 30; //500ms of no faults before we clear it for(i=0;i<phid->phid.attr.led.numLEDs;i++) { - phid->outputEnabledEcho[i] = (buffer[(i/8)+1] & (1 << (i%8))) ? 1 : 0; - phid->ledOpenDetectEcho[i] = (buffer[(i/8)+9] & (1 << (i%8))) ? 1 : 0; + if(phid->ledOpenDetectEcho[i]) + phid->TSDCount[0] = 0; } - //1st 24 LED powers - for(i=0;i<24;i++) + //send out some error events on faults + //TODO: we could also send LED Open Detect? + + //we have counted three fault flags with no LODs - TSD - only one error event is thrown until this is cleared + //less then 3 counts, and it could be a false positive + //if outputs are not enabled then the fault should be guaranteed as a TSD + if(phid->TSDCount[0] == 3 || (phid->TSDCount[0] < 3 && phid->outputEnableEcho == PFALSE)) { - double ledPowerTemp; - ledPowerTemp = ((double)buffer[i+17] / 127.0) * 100.0; - phid->LED_PowerEcho[i] = ledPowerTemp; + phid->TSDCount[0] = 3; + FIRE_ERROR(EEPHIDGET_OVERTEMP, "Thermal Shutdown detected."); } + } + else + { + if(phid->TSDClearCount[0] > 0) + phid->TSDClearCount[0]--; + else + phid->TSDCount[0]=0; + } + + if(!phid->powerGoodEcho && phid->PGoodErrState == PFALSE) + { + phid->PGoodErrState = PTRUE; + FIRE_ERROR(EEPHIDGET_BADPOWER, "Bad power supply detected."); + } + + break; + case LED64_IN_HIGH_PACKET: + + //last 40 LED powers + for(i=24;i<phid->phid.attr.led.numLEDs;i++) + { + double ledPowerTemp; + ledPowerTemp = ((double)buffer[i-23] / 127.0) * 100.0; + phid->LED_PowerEcho[i] = ledPowerTemp; + } - //We can guess that the fault is a TSD if there is no LOD - if(phid->faultEcho) + break; + } + break; + case PHIDUID_LED_64_ADV_M3: + switch(buffer[0] & 0x60) + { + case LED64_M3_IN_MISC_PACKET: + //PowerGood + if(buffer[0] & LED64_PGOOD_FLAG) + { + if(phid->PGoodErrState) { - phid->TSDCount++; - phid->TSDClearCount = 30; //500ms of no faults before we clear it + FIRE_ERROR(EEPHIDGET_OK, "Good power supply detected."); + } + phid->PGoodErrState = PFALSE; + phid->powerGoodEcho = PTRUE; + } + else + { + phid->powerGoodEcho = PFALSE; + } + + //voltage + if(buffer[0] & LED64_PWRSELA_FLAG) + { + if(buffer[0] & LED64_PWRSELB_FLAG) + phid->voltageEcho = PHIDGET_LED_VOLTAGE_5_0V; + else + phid->voltageEcho = PHIDGET_LED_VOLTAGE_2_75V; + } + else if (buffer[0] & LED64_PWRSELB_FLAG) + phid->voltageEcho = PHIDGET_LED_VOLTAGE_3_9V; + else + phid->voltageEcho = PHIDGET_LED_VOLTAGE_1_7V; + + if(!phid->powerGoodEcho && phid->PGoodErrState == PFALSE) + { + phid->PGoodErrState = PTRUE; + FIRE_ERROR(EEPHIDGET_BADPOWER, "Bad power supply detected."); + } + + //Temperature Warnings + for(i=0;i<4;i++) + { + if(buffer[1] & (0x01 << i)) + { + phid->TWarnCount[i]++; + phid->TWarnClearCount[i] = 20; //480ms of no faults before we clear it - for(i=0;i<phid->phid.attr.led.numLEDs;i++) + if(phid->TWarnCount[i] == 10) //240 ms of fault before we call it + { + FIRE_ERROR(EEPHIDGET_OVERTEMP, "Temperature Warning detected on chip %d.", i); + } + else if(phid->TWarnCount[i] > 10) + phid->TWarnCount[i]--; //so we don't overflow the char + } + else + { + if(phid->TWarnClearCount[i] > 0) + phid->TWarnClearCount[i]--; + else { - if(phid->ledOpenDetectEcho[i]) - phid->TSDCount = 0; + if(phid->TWarnCount[i] >= 10) + { + FIRE_ERROR(EEPHIDGET_OK, "Temperature Warning ended on chip %d.", i); + } + phid->TWarnCount[i]=0; } + } + } - //send out some error events on faults - //TODO: we could also send LED Open Detect? + //Temperature Errors + for(i=0;i<4;i++) + { + if(buffer[1] & (0x10 << i)) + { + phid->TSDCount[i]++; + phid->TSDClearCount[i] = 20; //480ms of no faults before we clear it - //we have counted three fault flags with no LODs - TSD - only one error event is thrown until this is cleared - //less then 3 counts, and it could be a false positive - //if outputs are not enabled then the fault should be guaranteed as a TSD - if(phid->TSDCount == 3 || (phid->TSDCount < 3 && phid->outputEnableEcho == PFALSE)) + if(phid->TSDCount[i] == 10) //240 ms of fault before we call it { - phid->TSDCount = 3; - FIRE_ERROR(EEPHIDGET_OVERTEMP, "Thermal Shutdown detected."); + FIRE_ERROR(EEPHIDGET_OVERTEMP, "Temperature Error detected on chip %d.", i); } + else if(phid->TSDCount[i] > 10) + phid->TSDCount[i]--; //so we don't overflow the char } else { - if(phid->TSDClearCount > 0) - phid->TSDClearCount--; + if(phid->TSDClearCount[i] > 0) + phid->TSDClearCount[i]--; else - phid->TSDCount=0; - } - - if(!phid->powerGoodEcho && phid->PGoodErrState == PFALSE) - { - phid->PGoodErrState = PTRUE; - FIRE_ERROR(EEPHIDGET_BADPOWER, "Bad power supply detected."); + { + if(phid->TSDCount[i] >= 10) + { + FIRE_ERROR(EEPHIDGET_OK, "Temperature Error ended on chip %d.", i); + } + phid->TSDCount[i]=0; + } } + } - break; - case LED64_IN_HIGH_PACKET: - - //last 40 LED powers - for(i=24;i<phid->phid.attr.led.numLEDs;i++) + //Current Limit + for(i=0;i<64;i++) + { + int index = (i*6)/8 + 2; + int currentLimitInt = 0; + switch(i%4) { - double ledPowerTemp; - ledPowerTemp = ((double)buffer[i-23] / 127.0) * 100.0; - phid->LED_PowerEcho[i] = ledPowerTemp; + case 0: + currentLimitInt = buffer[index] & 0x3F; + break; + case 1: + currentLimitInt = ((buffer[index] >> 6) & 0x03) + ((buffer[index+1] << 2) & 0x3C); + break; + case 2: + currentLimitInt = ((buffer[index] >> 4) & 0x0F) + ((buffer[index+1] << 4) & 0x30); + break; + case 3: + currentLimitInt = (buffer[index] >> 2) & 0x3F; + break; } + phid->LED_CurrentLimitEcho[i] = (currentLimitInt / 63.0) * LED64_M3_CURRENTLIMIT; + } - break; + break; + case LED64_M3_IN_LOW_PACKET: + for(i=0;i<32;i++) + { + int ledPowerInt; + int index = (i*12)/8+9; + + if(i%2 == 0) + ledPowerInt = buffer[index] + ((buffer[index+1] & 0x0F) << 8); + else + ledPowerInt = ((buffer[index] & 0xF0) >> 4) + (buffer[index+1] << 4); + + phid->LED_PowerEcho[i] = (ledPowerInt / 4097.0) * 100.0; + } + break; + case LED64_M3_IN_HIGH_PACKET: + for(i=0;i<32;i++) + { + int ledPowerInt; + int index = (i*12)/8+9; + + if(i%2 == 0) + ledPowerInt = buffer[index] + ((buffer[index+1] & 0x0F) << 8); + else + ledPowerInt = ((buffer[index] & 0xF0) >> 4) + (buffer[index+1] << 4); + + phid->LED_PowerEcho[i+32] = (ledPowerInt / 4097.0) * 100.0; + } + break; } - } - else - return EPHIDGET_UNEXPECTED; - break; - case PHIDUID_LED_64_ADV_M3: break; case PHIDUID_LED_64: default: @@ -451,22 +622,6 @@ CGETPACKET(LED) if(phid->controlPacketWaiting) { buf[0] = LED64_M3_CONTROL_PACKET; - - //TODO: we're getting rid of this probably - switch(phid->currentLimit) - { - case PHIDGET_LED_CURRENT_LIMIT_20mA: - break; - case PHIDGET_LED_CURRENT_LIMIT_40mA: - buf[0] |= LED64_CURSELA_FLAG; - break; - case PHIDGET_LED_CURRENT_LIMIT_60mA: - buf[0] |= LED64_CURSELB_FLAG; - break; - case PHIDGET_LED_CURRENT_LIMIT_80mA: - buf[0] |= (LED64_CURSELA_FLAG | LED64_CURSELB_FLAG); - break; - } switch(phid->voltage) { @@ -550,7 +705,7 @@ CGETPACKET(LED) for(i = startIndex;i<startIndex+32;i++) { int value; - int bufIndex = (i*12)/8 + 1; + int bufIndex = ((i-startIndex)*12)/8 + 1; if(phid->changedLED_Power[i]) { @@ -668,35 +823,6 @@ CGET(LED,LEDCount,int) MASGN(phid.attr.led.numLEDs) } -CGETINDEX(LED,DiscreteLED,int) - TESTPTRS(phid,pVal) - TESTDEVICETYPE(PHIDCLASS_LED) - TESTATTACHED - TESTINDEX(phid.attr.led.numLEDs) - if(phid->LED_Power[Index] == PUNK_DBL) - { - *pVal = PUNK_INT; - return EPHIDGET_UNKNOWNVAL; - } - - *pVal = round(phid->LED_Power[Index]); - return EPHIDGET_OK; -} -CSETINDEX(LED,DiscreteLED,int) - TESTPTR(phid) - TESTDEVICETYPE(PHIDCLASS_LED) - TESTATTACHED - TESTINDEX(phid.attr.led.numLEDs) - TESTRANGE(0, 100) - - if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG)) - ADDNETWORKKEYINDEXED(Brightness, "%d", LED_Power); - else - return CPhidgetLED_sendpacket(phid, Index, (double)newVal); - - return EPHIDGET_OK; -} - CGETINDEX(LED,Brightness,double) TESTPTRS(phid,pVal) TESTDEVICETYPE(PHIDCLASS_LED) @@ -747,9 +873,9 @@ CSETINDEX(LED,CurrentLimitIndexed,double) TESTATTACHED TESTINDEX(phid.attr.led.numLEDs) - switch(phid->phid.deviceIDSpec) + switch(phid->phid.deviceUID) { - case PHIDID_LED_64_ADV: + case PHIDUID_LED_64_ADV_M3: TESTRANGE(0, LED64_M3_CURRENTLIMIT) if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG)) @@ -765,7 +891,8 @@ CSETINDEX(LED,CurrentLimitIndexed,double) CThread_mutex_unlock(&phid->phid.writelock); } break; - case PHIDID_LED_64: + case PHIDUID_LED_64_ADV: + case PHIDUID_LED_64: default: return EPHIDGET_UNSUPPORTED; } @@ -778,11 +905,12 @@ CGET(LED,CurrentLimit,CPhidgetLED_CurrentLimit) TESTDEVICETYPE(PHIDCLASS_LED) TESTATTACHED - switch(phid->phid.deviceIDSpec) + switch(phid->phid.deviceUID) { - case PHIDID_LED_64_ADV: + case PHIDUID_LED_64_ADV: MASGN(currentLimitEcho) - case PHIDID_LED_64: + case PHIDUID_LED_64_ADV_M3: + case PHIDUID_LED_64: default: return EPHIDGET_UNSUPPORTED; } @@ -792,9 +920,9 @@ CSET(LED,CurrentLimit,CPhidgetLED_CurrentLimit) TESTDEVICETYPE(PHIDCLASS_LED) TESTATTACHED - switch(phid->phid.deviceIDSpec) + switch(phid->phid.deviceUID) { - case PHIDID_LED_64_ADV: + case PHIDUID_LED_64_ADV: TESTRANGE(PHIDGET_LED_CURRENT_LIMIT_20mA, PHIDGET_LED_CURRENT_LIMIT_80mA) @@ -811,7 +939,42 @@ CSET(LED,CurrentLimit,CPhidgetLED_CurrentLimit) CThread_mutex_unlock(&phid->phid.writelock); } break; - case PHIDID_LED_64: + case PHIDUID_LED_64_ADV_M3: + + TESTRANGE(PHIDGET_LED_CURRENT_LIMIT_20mA, PHIDGET_LED_CURRENT_LIMIT_80mA) + + if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG)) + ADDNETWORKKEY(CurrentLimit, "%d", currentLimit); + else + { + int i; + double limit; + switch(newVal) + { + case PHIDGET_LED_CURRENT_LIMIT_20mA: + limit = 20; + break; + case PHIDGET_LED_CURRENT_LIMIT_40mA: + limit = 40; + break; + case PHIDGET_LED_CURRENT_LIMIT_60mA: + limit = 60; + break; + case PHIDGET_LED_CURRENT_LIMIT_80mA: + limit = 80; + break; + } + CThread_mutex_lock(&phid->phid.writelock); + CThread_mutex_lock(&phid->phid.outputLock); + for(i=0;i<phid->phid.attr.led.numLEDs;i++) + phid->LED_CurrentLimit[i] = limit; + phid->controlPacketWaiting = PTRUE; + CThread_mutex_unlock(&phid->phid.outputLock); + CThread_set_event(&phid->phid.writeAvailableEvent); + CThread_mutex_unlock(&phid->phid.writelock); + } + break; + case PHIDUID_LED_64: default: return EPHIDGET_UNSUPPORTED; } @@ -870,3 +1033,13 @@ CSET(LED,Voltage,CPhidgetLED_Voltage) CGET(LED,NumLEDs,int) return CPhidgetLED_getLEDCount(phid, pVal); } +CGETINDEX(LED,DiscreteLED,int) + double val; + int ret; + ret = CPhidgetLED_getBrightness(phid, Index, &val); + *pVal = (int)round(val); + return ret; +} +CSETINDEX(LED,DiscreteLED,int) + return CPhidgetLED_setBrightness(phid, Index, (double)newVal); +} |