void drvSIS3820::setLNEOutputDelay() { double value; epicsUInt32 ivalue; if (firmwareVersion_ < 0x0111) return; getDoubleParam(SIS38XXLNEOutputDelay_, &value); ivalue = epicsUInt32(value * SIS3820_INTERNAL_CLOCK + 0.5); registers_->lne_output_delay_reg = ivalue; }
////////////////////////////////////////////////////////////////////////////////////////////////// // // // bool CLeyboldSimPortDriver::process(USSPacket<NoOfPZD6>& USSWritePacket, int TableIndex) // // // // Description: // // Called from the listening thread to process a packet request. // // The response should resemble the behaviour of the 'real' pump controller. // // // // Parameters: // // USSWritePacket - this is the packet that will be returned as output. // // // ////////////////////////////////////////////////////////////////////////////////////////////////// void CLeyboldSimPortDriver::process(USSPacket<NoOfPZD6>& USSWritePacket, int TableIndex) { epicsInt32 IBuf; epicsFloat64 DBuf; // Converter temperature - actual value. This is equivalent to parameter 11. IBuf = getIntegerParam(TableIndex, CONVERTERTEMPERATURE); USSWritePacket.m_USSPacketStruct.m_PZD[2] = IBuf; // Motor current - actual value. This is equivalent to parameter 5. DBuf = getDoubleParam(TableIndex, MOTORCURRENT); USSWritePacket.m_USSPacketStruct.m_PZD[3] = epicsUInt32(10.0 * DBuf + 0.5); // Motor temperature - actual value. This is equivalent to parameter 7. IBuf = getIntegerParam(TableIndex, PUMPTEMPERATURE); USSWritePacket.m_USSPacketStruct.m_PZD[4] = IBuf; // Intermediate circuit voltage Uzk. This is equivalent to parameter 4. DBuf = getDoubleParam(TableIndex, CIRCUITVOLTAGE); USSWritePacket.m_USSPacketStruct.m_PZD[5] = epicsUInt32(10.0 * DBuf + 0.5); }
template<size_t NoOfPZD> bool CLeyboldSimPortDriver::process(asynUser* IOUser, USSPacket<NoOfPZD> const& USSReadPacket, USSPacket<NoOfPZD>& USSWritePacket, size_t TableIndex) { if ((TableIndex < 0) || (TableIndex >= m_RunRecord.size())) throw CException(IOUser, asynError, __FUNCTION__, "User / pump not configured"); RunStates RunState = static_cast<RunStates>(getIntegerParam(TableIndex, RUNNING)); // Means the running state is in effect or has been requested. bool Running = ((RunState == On) || (RunState == Accel)); // control bit 10 = 1 bool RemoteActivated = ((USSReadPacket.m_USSPacketStruct.m_PZD[0] & (1 << 10)) != 0); if (RemoteActivated) { // Running state change can be requested both ways! Running = (USSReadPacket.m_USSPacketStruct.m_PZD[0] & (1 << 0)); // 0 to 1 transition = Error reset Is only run provided if: // the cause for the error has been removed // and control bit 0 = 0 and control bit 10 = 1 if ((USSReadPacket.m_USSPacketStruct.m_PZD[0] & (1 << 7)) && (RunState==Off)) { // Clear the fault condition. setIntegerParam(TableIndex, FAULT, 0); } } { epicsGuard < epicsMutex > guard ( CLeyboldSimPortDriver::m_Mutex ); if ((Running) && (m_RunRecord[TableIndex].m_RunState != On)) { // The running state has just been enabled. if (m_RunRecord[TableIndex].m_RunState == Off) { setIntegerParam(TableIndex, RUNNING, Accel); setDoubleParam(TableIndex, MOTORCURRENT, 15.2); m_RunRecord[TableIndex].m_RunState = Accel; m_RunRecord[TableIndex].m_TimeStamp = getTickCount(); } else { // Accel. // It is intended that the (simulated) pump speed ramps up to full speed in Duration static const unsigned Duration = 2000; unsigned ElapsedTime = getTickCount() - m_RunRecord[TableIndex].m_TimeStamp; setIntegerParam(TableIndex, STATORFREQUENCY, (ElapsedTime * NormalStatorFrequency) / Duration); if (ElapsedTime >= Duration) { setDefaultValues(TableIndex); m_RunRecord[TableIndex].m_RunState = On; m_RunRecord[TableIndex].m_TimeStamp = getTickCount(); } } } else if ((!Running) && (m_RunRecord[TableIndex].m_RunState != Off)) { // The running state has just been disabled. if (m_RunRecord[TableIndex].m_RunState == On) { setIntegerParam(TableIndex, RUNNING, Decel); m_RunRecord[TableIndex].m_RunState = Decel; m_RunRecord[TableIndex].m_TimeStamp = getTickCount(); } else if (m_RunRecord[TableIndex].m_RunState == Decel) { // It is intended that the (simulated) pump speed ramps down to nothing in Duration static const int Duration = 2000; int ElapsedTime = getTickCount() - m_RunRecord[TableIndex].m_TimeStamp; int StatorFrequency = ((Duration - ElapsedTime) * NormalStatorFrequency) / Duration; if (StatorFrequency < 3) StatorFrequency = 3; setIntegerParam(TableIndex, STATORFREQUENCY, StatorFrequency); if (ElapsedTime >= Duration) { setIntegerParam(TableIndex, RUNNING, Moving); m_RunRecord[TableIndex].m_RunState = Moving; m_RunRecord[TableIndex].m_TimeStamp = getTickCount(); } } else if (m_RunRecord[TableIndex].m_RunState == Moving) { // It is intended that the pump remains in the 'Moving' state for another Duration static const unsigned Duration = 2000; unsigned ElapsedTime = getTickCount() - m_RunRecord[TableIndex].m_TimeStamp; if (ElapsedTime >= Duration) { setIntegerParam(TableIndex, STATORFREQUENCY, 0); setIntegerParam(TableIndex, RUNNING, Off); m_RunRecord[TableIndex].m_RunState = Off; m_RunRecord[TableIndex].m_TimeStamp = getTickCount(); } } } } USSWritePacket.m_USSPacketStruct.m_PZD[0] = 0; RunState = m_RunRecord[TableIndex].m_RunState; if (RunState == On) USSWritePacket.m_USSPacketStruct.m_PZD[0] |= (1 << 10); else if (RunState == Accel) USSWritePacket.m_USSPacketStruct.m_PZD[0] |= (1 << 4); else if (RunState == Decel) USSWritePacket.m_USSPacketStruct.m_PZD[0] |= (1 << 5); else if (RunState == Moving) USSWritePacket.m_USSPacketStruct.m_PZD[0] |= (1 << 11); // Remote has been activated 1 = start/stop (control bit 0) and reset(control bit 7) through serial interface is possible. USSWritePacket.m_USSPacketStruct.m_PZD[0] |= ((RemoteActivated ? 1 : 0) << 15); bool Fault = (getIntegerParam(TableIndex, FAULT) != 0); if (Fault) { // A fault condition causes the controller to stop the pump. USSWritePacket.m_USSPacketStruct.m_PZD[0] |= (1 << 3); setIntegerParam(TableIndex, STATORFREQUENCY, 0); setIntegerParam(TableIndex, RUNNING, Off); m_RunRecord[TableIndex].m_RunState = Off; } if (getIntegerParam(TableIndex, WARNINGTEMPERATURE) != 0) USSWritePacket.m_USSPacketStruct.m_PZD[0] |= (1 << 7); if (getIntegerParam(TableIndex, WARNINGHIGHLOAD) != 0) USSWritePacket.m_USSPacketStruct.m_PZD[0] |= (1 << 13); if (getIntegerParam(TableIndex, WARNINGPURGE) != 0) USSWritePacket.m_USSPacketStruct.m_PZD[0] |= (1 << 14); // Frequency - actual value. This is equivalent to parameter 3. Both packet types have this field. USSWritePacket.m_USSPacketStruct.m_PZD[1] = getIntegerParam(TableIndex, STATORFREQUENCY); epicsUInt16 PKE = 0; if (USSReadPacket.m_USSPacketStruct.m_PKE & (1 << 12)) // The requested parameter is in the least 12 bits. PKE = USSReadPacket.m_USSPacketStruct.m_PKE & 0X0FFF; switch (PKE) { case 3 : // Frequency - actual value. This is equivalent to PZD[1]. USSWritePacket.m_USSPacketStruct.m_PWE = getIntegerParam(TableIndex, STATORFREQUENCY); break; case 11: // Converter temperature - actual value. This is equivalent to PZD[2]. USSWritePacket.m_USSPacketStruct.m_PWE = getIntegerParam(TableIndex, CONVERTERTEMPERATURE); break; case 5 : // Motor current - actual value. This is equivalent to PZD[3]. USSWritePacket.m_USSPacketStruct.m_PWE = epicsUInt32(10.0 * getDoubleParam(TableIndex, MOTORCURRENT) + 0.5); break; case 7 : // Motor temperature - actual value. This is equivalent to PZD[4]. USSWritePacket.m_USSPacketStruct.m_PWE = getIntegerParam(TableIndex, PUMPTEMPERATURE); break; case 4 : // Intermediate circuit voltage Uzk. This is equivalent to PZD[5]. USSWritePacket.m_USSPacketStruct.m_PWE = epicsUInt32(10.0 * getDoubleParam(TableIndex, CIRCUITVOLTAGE) + 0.5); break; case 2 : // Software version (I assume this means firmware). e.g. 3.03.05 char CBuf[8]; // 7 chars plus null termination. int Major, Minor1, Minor2; getStringParam(TableIndex, FIRMWAREVERSION, sizeof(CBuf), CBuf); sscanf(CBuf, "%1d.%02d.%02d", &Major, &Minor1, &Minor2); USSWritePacket.m_USSPacketStruct.m_PWE = Major * 10000 + Minor1 * 100 + Minor2; break; case 171: // Error code USSWritePacket.m_USSPacketStruct.m_PWE = getIntegerParam(TableIndex, FAULT); break; case 227: // Temperature Warning code USSWritePacket.m_USSPacketStruct.m_PWE = getIntegerParam(TableIndex, WARNINGTEMPERATURE); break; case 228: // Load warning code. USSWritePacket.m_USSPacketStruct.m_PWE = getIntegerParam(TableIndex, WARNINGHIGHLOAD); break; case 230: // Purge warning code. USSWritePacket.m_USSPacketStruct.m_PWE = getIntegerParam(TableIndex, WARNINGPURGE); break; default: break; // No action. } USSWritePacket.GenerateChecksum(); USSWritePacket.m_USSPacketStruct.HToN(); size_t nbytesOut; asynStatus status = pasynOctetSyncIO->write(IOUser, reinterpret_cast<char*>(&USSWritePacket.m_Bytes), USSPacketStruct<NoOfPZD>::USSPacketSize, -1, &nbytesOut); if (status == asynDisconnected) return false; if (status != asynSuccess) throw CException(IOUser, status, __FUNCTION__, "Can't write/read:"); callParamCallbacks(int(TableIndex)); asynPrint(IOUser, ASYN_TRACE_FLOW, "Packet success %s %s\n", __FILE__, __FUNCTION__); return true; }