/*-------------------------------------------------------------------------- S L S V M E This file contains the driver for the PSI-DSP magnet controller as aquired from SLS. This version is for the new interface provided by the vmemaggi server program running on embedded linux on a computer in the VME crate which talks directly to the IP communication mudules on the VME bus. Copyright: see file COPYRIGHT Mark Koennecke, April 2008 ----------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include #include #include "evdriver.h" #include #include #include "vmemaggi.h" #include #define ABS(x) (x < 0 ? -(x) : (x)) extern char *trim(char *txt); #define DEVERR -2001 #define BADHIGHLIM -2002 #define BADLOWLIM -2003 /*-----------------------------------------------------------------------*/ typedef struct { prs232 controller; int iNum; int iError; int iDevError; char errorText[80]; } SLSDriv, *pSLSDriv; /*-------------------------------------------------------------------------*/ static int communicateSLS(pSLSDriv self, char *command, char *reply, int replyLen) { long lVal = 0; int iRet, i, address, status; char *pPtr; char text[80]; if (!self->controller) { self->iError = NOTCONNECTED; strcpy(self->errorText, "Not Connected"); return -1; } self->iDevError = 0; memset(reply, 0, replyLen); iRet = transactRS232(self->controller, command, strlen(command), reply, replyLen); if (iRet < 0) { return iRet; } if (strstr(reply, "ERROR") != NULL) { pPtr = reply; /* jump over error */ pPtr = stptok(pPtr, text, 80, ":"); /* read error number */ pPtr = stptok(pPtr, text, 80, ":"); self->iError = atoi(trim(text)); /* read error description */ pPtr = stptok(pPtr, text, 80, ":"); strlcpy(self->errorText, text, 80); return DEVERR; } return 1; } /*--------------------------------------------------------------------------*/ static void locateValue(char *rawReply, char *value, int valLen) { char *pPtr; pPtr = rawReply; pPtr = stptok(pPtr, value, valLen, " "); if(pPtr != NULL){ pPtr = stptok(pPtr, value, valLen, " "); } if(pPtr != NULL){ stptok(pPtr, value, valLen, " "); } } /*---------------------------------------------------------------------*/ static void slsdspCodeToText(int code, char *text, int textlen) { switch (code) { case 0x0: strlcpy(text, "NO", textlen); break; case 0x1: strlcpy(text, "DEVICE_STATE_ERROR", textlen); break; case 0x2: strlcpy(text, "DEVICE_SUPERVISOR_DISABLED", textlen); break; case 0x3: strlcpy(text, "COMMAND_ABORT", textlen); break; case 0x4: strlcpy(text, "DATA_NOT_STORED", textlen); break; case 0x5: strlcpy(text, "ERROR_ERASING_FLASH", textlen); break; case 0x6: strlcpy(text, "COMMUNICATION_BREAK", textlen); break; case 0x7: strlcpy(text, "INTERNAL_COMMUNICATION_ERROR", textlen); break; case 0x8: strlcpy(text, "MASTER_CARD_ERROR", textlen); break; case 0x9: strlcpy(text, "INTERNAL_BUFFER_FULL", textlen); break; case 0xa: strlcpy(text, "WRONG_SECTOR", textlen); break; case 0xb: strlcpy(text, "DATA_NOT_COPIED", textlen); break; case 0xc: strlcpy(text, "WRONG_DOWNLOAD_PARAMETERS", textlen); break; case 0xd: strlcpy(text, "DEVICE_PARAMETRIZATION_ERROR", textlen); break; case 0x10: strlcpy(text, "TIMEOUT_DC_LINK_VOLTAGE", textlen); break; case 0x11: strlcpy(text, "TIMEOUT_AUXILIARY_RELAY_ON", textlen); break; case 0x12: strlcpy(text, "TIMEOUT_AUXILIARY_RELAY_OFF", textlen); break; case 0x13: strlcpy(text, "TIMEOUT_MAIN_RELAY_ON", textlen); break; case 0x14: strlcpy(text, "TIMEOUT_MAIN_RELAY_OFF", textlen); break; case 0x15: strlcpy(text, "TIMEOUT_DATA_DOWNLOAD", textlen); break; case 0x20: strlcpy(text, "INTERLOCK", textlen); break; case 0x21: strlcpy(text, "MASTER_SWITCH", textlen); break; case 0x22: strlcpy(text, "MAGNET_INTERLOCK", textlen); break; case 0x23: strlcpy(text, "TEMPERATURE_TRANSFORMER", textlen); break; case 0x24: strlcpy(text, "TEMPERATURE_RECTIFIER", textlen); break; case 0x25: strlcpy(text, "TEMPERATURE_CONVERTER", textlen); break; case 0x26: strlcpy(text, "CURRENT_TRANSDUCER", textlen); break; case 0x27: strlcpy(text, "TEMPERATURE_POLARITY_SWITCH", textlen); break; case 0x28: strlcpy(text, "POWER_SEMICONDUCTOR", textlen); break; case 0x29: strlcpy(text, "MAIN_RELAY", textlen); break; case 0x2a: strlcpy(text, "AD_CONVERTER_CARD", textlen); break; case 0x2b: strlcpy(text, "POLARITY_SWITCH", textlen); break; case 0x2c: strlcpy(text, "AUXILIARY_RELAY", textlen); break; case 0x2d: strlcpy(text, "MASTER_SWITCH_T1", textlen); break; case 0x2e: strlcpy(text, "MASTER_SWITCH_T2", textlen); break; case 0x2f: strlcpy(text, "TEMPERATURE_MAGNET", textlen); break; case 0x30: strlcpy(text, "WATER_MAGNET", textlen); break; case 0x31: strlcpy(text, "WATER_RACK", textlen); break; case 0x40: strlcpy(text, "LOAD_CURRENT_TOO_HIGH", textlen); break; case 0x41: strlcpy(text, "DC_LINK_VOLTAGE_TOO_LOW", textlen); break; case 0x42: strlcpy(text, "DC_LINK_VOLTAGE_TOO_HIGH", textlen); break; case 0x43: strlcpy(text, "LOAD_VOLTAGE_TOO_HIGH", textlen); break; case 0x44: strlcpy(text, "LOAD_CURRENT_RIPPLE_TOO_HIGH", textlen); break; case 0x45: strlcpy(text, "DC_LINK_ISOLATION_NOT_OK", textlen); break; case 0x46: strlcpy(text, "LOAD_ISOLATION_NOT_OK", textlen); break; case 0x47: strlcpy(text, "LOAD_IMPEDANCE_OUT_OF_RANGE", textlen); break; case 0x48: strlcpy(text, "SHUT_OFF_CURRENT_TOO_HIGH", textlen); break; case 0x49: strlcpy(text, "LOAD_DC_CURRENT_TOO_HIGH", textlen); break; case 0x4a: strlcpy(text, "CURRENT_I1A1_TOO_HIGH", textlen); break; case 0x4b: strlcpy(text, "CURRENT_I1B1_TOO_HIGH", textlen); break; case 0x4c: strlcpy(text, "CURRENT_I1A2_TOO_HIGH", textlen); break; case 0x4d: strlcpy(text, "CURRENT_I1B2_TOO_HIGH", textlen); break; case 0x4e: strlcpy(text, "CURRENT_I2A1_TOO_HIGH", textlen); break; case 0x4f: strlcpy(text, "CURRENT_I2B1_TOO_HIGH", textlen); break; case 0x50: strlcpy(text, "CURRENT_I2A2_TOO_HIGH", textlen); break; case 0x51: strlcpy(text, "CURRENT_I2B2_TOO_HIGH", textlen); break; case 0x52: strlcpy(text, "CURRENT_I3P_TOO_HIGH", textlen); break; case 0x53: strlcpy(text, "CURRENT_I3N_TOO_HIGH", textlen); break; case 0x54: strlcpy(text, "CURRENT_IE_TOO_HIGH", textlen); break; case 0x55: strlcpy(text, "VOLTAGE_U1A_TOO_LOW", textlen); break; case 0x56: strlcpy(text, "VOLTAGE_U1B_TOO_LOW", textlen); break; case 0x57: strlcpy(text, "DIFF_CURRENT_I1A1_I1A2_TOO_HIGH", textlen); break; case 0x58: strlcpy(text, "DIFF_CURRENT_I1B1_I1B2_TOO_HIGH", textlen); break; case 0x59: strlcpy(text, "DIFF_CURRENT_I2A1_I2A2_TOO_HIGH", textlen); break; case 0x5a: strlcpy(text, "DIFF_CURRENT_I2B1_I2B2_TOO_HIGH", textlen); break; case 0x5b: strlcpy(text, "DIFF_CURRENT_I3P_I3N_TOO_HIGH", textlen); break; case 0x5c: strlcpy(text, "CURRENT_I1A_TOO_HIGH", textlen); break; case 0x5d: strlcpy(text, "CURRENT_I1B_TOO_HIGH", textlen); break; case 0x5e: strlcpy(text, "CURRENT_I3A1_TOO_HIGH", textlen); break; case 0x5f: strlcpy(text, "CURRENT_I3B1_TOO_HIGH", textlen); break; case 0x60: strlcpy(text, "CURRENT_I3A2_TOO_HIGH", textlen); break; case 0x61: strlcpy(text, "CURRENT_I3B2_TOO_HIGH", textlen); break; case 0x62: strlcpy(text, "CURRENT_I4_TOO_HIGH", textlen); break; case 0x63: strlcpy(text, "CURRENT_I5_TOO_HIGH", textlen); break; case 0x64: strlcpy(text, "DIFF_CURRENT_I3A1_I3A2_TOO_HIGH", textlen); break; case 0x65: strlcpy(text, "DIFF_CURRENT_I3B1_I3B2_TOO_HIGH", textlen); break; case 0x66: strlcpy(text, "DIFF_CURRENT_I4_I5_TOO_HIGH", textlen); break; case 0x67: strlcpy(text, "VOLTAGE_U3A_TOO_LOW", textlen); break; case 0x68: strlcpy(text, "VOLTAGE_U3B_TOO_LOW", textlen); break; case 0x69: strlcpy(text, "VOLTAGE_U1_TOO_LOW", textlen); break; case 0x6a: strlcpy(text, "VOLTAGE_U3A_TOO_HIGH", textlen); break; case 0x6b: strlcpy(text, "VOLTAGE_U3B_TOO_HIGH", textlen); break; case 0x6c: strlcpy(text, "SPEED_ERROR_TOO_HIGH", textlen); break; case 0x70: strlcpy(text, "MAIN_RELAY_A", textlen); break; case 0x71: strlcpy(text, "MAIN_RELAY_B", textlen); break; case 0x72: strlcpy(text, "POWER_SWITCH_A", textlen); break; case 0x73: strlcpy(text, "POWER_SWITCH_B", textlen); break; case 0x74: strlcpy(text, "MONITOR_TRAFO_A", textlen); break; case 0x75: strlcpy(text, "MONITOR_TRAFO_B", textlen); break; case 0x76: strlcpy(text, "TEMPERATURE_RECTIFIER_A", textlen); break; case 0x77: strlcpy(text, "TEMPERATURE_RECTIFIER_B", textlen); break; case 0x78: strlcpy(text, "TEMPERATURE_CONVERTER_A", textlen); break; case 0x79: strlcpy(text, "TEMPERATURE_CONVERTER_B", textlen); break; case 0x7a: strlcpy(text, "TEMPERATURE_CONVERTER_A1", textlen); break; case 0x7b: strlcpy(text, "TEMPERATURE_CONVERTER_B1", textlen); break; case 0x7c: strlcpy(text, "TEMPERATURE_CONVERTER_A2", textlen); break; case 0x7d: strlcpy(text, "TEMPERATURE_CONVERTER_B2", textlen); break; case 0x7e: strlcpy(text, "TEMPERATURE_TRANSFORMER_A", textlen); break; case 0x7f: strlcpy(text, "TEMPERATURE_TRANSFORMER_B", textlen); break; case 0x80: strlcpy(text, "WATER_RECTIFIER_A", textlen); break; case 0x81: strlcpy(text, "WATER_RECTIFIER_B", textlen); break; case 0x82: strlcpy(text, "WATER_CONVERTER_A", textlen); break; case 0x83: strlcpy(text, "WATER_CONVERTER_B", textlen); break; case 0x84: strlcpy(text, "WATER_CONVERTER_A1", textlen); break; case 0x85: strlcpy(text, "WATER_CONVERTER_B1", textlen); break; case 0x86: strlcpy(text, "WATER_CONVERTER_A2", textlen); break; case 0x87: strlcpy(text, "WATER_CONVERTER_B2", textlen); break; case 0x88: strlcpy(text, "WATER_TRANSFORMER_A", textlen); break; case 0x89: strlcpy(text, "WATER_TRANSFORMER_B", textlen); break; case 0x8a: strlcpy(text, "DOOR_A", textlen); break; case 0x8b: strlcpy(text, "DOOR_B", textlen); break; case 0x8c: strlcpy(text, "DOOR_C", textlen); break; case 0x8d: strlcpy(text, "POWER_SEMICONDUCTOR_CONVERTER_A", textlen); break; case 0x8e: strlcpy(text, "POWER_SEMICONDUCTOR_CONVERTER_B", textlen); break; case 0x8f: strlcpy(text, "POWER_SEMICONDUCTOR_CONVERTER_A1", textlen); break; case 0x90: strlcpy(text, "POWER_SEMICONDUCTOR_CONVERTER_B1", textlen); break; case 0x91: strlcpy(text, "POWER_SEMICONDUCTOR_CONVERTER_A2", textlen); break; case 0x92: strlcpy(text, "POWER_SEMICONDUCTOR_CONVERTER_B2", textlen); break; case 0x93: strlcpy(text, "CURRENT_TRANSDUCER_I3P", textlen); break; case 0x94: strlcpy(text, "CURRENT_TRANSDUCER_I3N", textlen); break; case 0x95: strlcpy(text, "MAGNET_INTERLOCK_1", textlen); break; case 0x96: strlcpy(text, "MAGNET_INTERLOCK_2", textlen); break; case 0x97: strlcpy(text, "VENTILATOR", textlen); break; case 0x98: strlcpy(text, "EMERGENCY_SWITCH", textlen); break; case 0x99: strlcpy(text, "CAPACITOR_DISCHARGE_A_ON", textlen); break; case 0x9a: strlcpy(text, "CAPACITOR_DISCHARGE_B_ON", textlen); break; case 0x9b: strlcpy(text, "CURRENT_TRANSDUCER_I4", textlen); break; case 0x9c: strlcpy(text, "CURRENT_TRANSDUCER_I5", textlen); break; case 0xb0: strlcpy(text, "TIMEOUT_DC_LINK_VOLTAGE_PART_A", textlen); break; case 0xb1: strlcpy(text, "TIMEOUT_DC_LINK_VOLTAGE_PART_B", textlen); break; case 0xb2: strlcpy(text, "TIMEOUT_AUXILIARY_RELAY_A_ON", textlen); break; case 0xb3: strlcpy(text, "TIMEOUT_AUXILIARY_RELAY_B_ON", textlen); break; case 0xb4: strlcpy(text, "TIMEOUT_AUXILIARY_RELAY_A_OFF", textlen); break; case 0xb5: strlcpy(text, "TIMEOUT_AUXILIARY_RELAY_B_OFF", textlen); break; case 0xb6: strlcpy(text, "TIMEOUT_MAIN_RELAY_A_ON", textlen); break; case 0xb7: strlcpy(text, "TIMEOUT_MAIN_RELAY_B_ON", textlen); break; case 0xb8: strlcpy(text, "TIMEOUT_MAIN_RELAY_A_OFF", textlen); break; case 0xb9: strlcpy(text, "TIMEOUT_MAIN_RELAY_B_OFF", textlen); break; } } /*---------------------------------------------------------------------------*/ static int GetSLSPos(pEVDriver self, float *fPos) { pSLSDriv pMe = NULL; char command[40], reply[132], value[40]; int iRet; assert(self); pMe = (pSLSDriv) self->pPrivate; assert(pMe); /* * first try to read the error code */ snprintf(command, 40, "r %d err\n", pMe->iNum); iRet = communicateSLS(pMe, command, reply, 132); if (iRet < 0) { return 0; } locateValue(reply, value, 40); sscanf(value, "%x", &iRet); if (iRet != 0) { slsdspCodeToText(iRet, pMe->errorText, 80); pMe->iError = DEVERROR; pMe->iDevError = iRet; return 0; } /* * really read the current */ snprintf(command, 40, "r %d cur\n", pMe->iNum); iRet = communicateSLS(pMe, command, reply, 132); if (iRet < 0) { return 0; } locateValue(reply, value, 40); sscanf(value, "%f", fPos); return 1; } /*----------------------------------------------------------------------------*/ static int SLSRun(pEVDriver self, float fVal) { pSLSDriv pMe = NULL; int iRet; char command[40], reply[132], value[40]; assert(self); pMe = (pSLSDriv) self->pPrivate; assert(pMe); /* * first check if this on */ snprintf(command, 40, "r %d onoff\n", pMe->iNum); iRet = communicateSLS(pMe, command, reply, 132); if (iRet < 0) { return 0; } locateValue(reply, value, 40); if (strstr(value, "1") == NULL) { /* * switch on */ snprintf(command, 40, "w %d on\n", pMe->iNum); iRet = communicateSLS(pMe, command, reply, 132); if (iRet < 0) { return 0; } } /* * set a new value */ snprintf(command, 40, "w %d cur %f\n", pMe->iNum, fVal); iRet = communicateSLS(pMe, command, reply, 132); if (iRet < 0) { return 0; } return 1; } /*--------------------------------------------------------------------------*/ static int SLSError(pEVDriver self, int *iCode, char *error, int iErrLen) { pSLSDriv pMe = NULL; char *pPtr = NULL; int i1, i2; char pBueffel[132]; assert(self); pMe = (pSLSDriv) self->pPrivate; assert(pMe); *iCode = pMe->iError; if (pMe->iError == DEVERROR) { strlcpy(error, pMe->errorText, iErrLen); return 1; } if (pMe->iError < -2000 || (pMe->iError >= 70 && pMe->iError < 83)) { strlcpy(error, pMe->errorText, iErrLen); return 1; } getRS232Error(*iCode, error, iErrLen); return 1; } /*-------------------------------------------------------------------------*/ static int SLSSend(pEVDriver self, char *pCommand, char *pReply, int iLen) { pSLSDriv pMe = NULL; int iRet, ival; char command[40]; assert(self); pMe = (pSLSDriv) self->pPrivate; assert(pMe); if (strcmp(pCommand, "off") == 0) { snprintf(command, 40, "w %d off\n", pMe->iNum); } else if (strcmp(pCommand, "on") == 0) { snprintf(command, 40, "w %d on\n", pMe->iNum); } else { strlcpy(command, pCommand, 40); } iRet = communicateSLS(pMe, command, pReply, iLen); if (iRet < 0) { return 0; } return 1; } /*--------------------------------------------------------------------------*/ static int SLSInit(pEVDriver self) { pSLSDriv pMe = NULL; int iRet, ival, i; char msg[40], reply[40]; assert(self); pMe = (pSLSDriv) self->pPrivate; assert(pMe); iRet = initRS232(pMe->controller); if (iRet < 0) { return 0; } setRS232SendTerminator(pMe->controller, "\n"); setRS232ReplyTerminator(pMe->controller, "\n"); setRS232Timeout(pMe->controller, 1000); snprintf(msg, 40, "w %d on\n", pMe->iNum); iRet = communicateSLS(pMe, msg, reply, 40); if (iRet < 0) { return 0; } return 1; } /*--------------------------------------------------------------------------*/ static int SLSClose(pEVDriver self) { pSLSDriv pMe = NULL; int iRet, ival; char msg[6], reply[6]; assert(self); pMe = (pSLSDriv) self->pPrivate; assert(pMe); closeRS232(pMe->controller); return 1; } /*---------------------------------------------------------------------------*/ static int SLSFix(pEVDriver self, int iError) { pSLSDriv pMe = NULL; int iRet, i, dataLen; char buffer[80]; char msg[6], reply[6]; float fVal = .0; assert(self); pMe = (pSLSDriv) self->pPrivate; assert(pMe); switch (iError) { case BADHIGHLIM: case BADLOWLIM: case BADSLOT: case BADMAP: case DSPSTOP: case LINKDWN: case MISPS: case PSRNG: case NOPAR: case NOVAL: case BADPAR: case SETRNG: case DEVERROR: return DEVFAULT; break; case SOFTTIM: case FPGATIM: case ADDRMIS: return DEVREDO; break; case TIMEOUT: for (i = 0; i < 10; i++) { iRet = availableRS232(pMe->controller); dataLen = 70; if (iRet == 1) { readRS232(pMe->controller, buffer, &dataLen); } } return DEVREDO; break; default: SLSClose(self); iRet = SLSInit(self); if (iRet) { return DEVREDO; } else { return DEVFAULT; } break; } } /*--------------------------------------------------------------------------*/ static int SLSHalt(pEVDriver * self) { assert(self); return 1; } /*------------------------------------------------------------------------*/ static void KillSLS(void *pData) { pSLSDriv pMe = NULL; pMe = (pSLSDriv) pData; assert(pMe); free(pMe); } /*------------------------------------------------------------------------*/ pEVDriver CreateSLSVMEDriv(int argc, char *argv[]) { pEVDriver pNew = NULL; pSLSDriv pSim = NULL; /* check for arguments */ if (argc < 2) { return NULL; } pNew = CreateEVDriver(argc, argv); pSim = (pSLSDriv) malloc(sizeof(SLSDriv)); memset(pSim, 0, sizeof(SLSDriv)); if (!pNew || !pSim) { return NULL; } pNew->pPrivate = pSim; pNew->KillPrivate = KillSLS; pSim->controller = FindCommandData(pServ->pSics, argv[0], "RS232 Controller"); if (pSim->controller == NULL) { return NULL; } pSim->iNum = atoi(argv[1]); /* initialise function pointers */ pNew->SetValue = SLSRun; pNew->GetValue = GetSLSPos; pNew->Send = SLSSend; pNew->GetError = SLSError; pNew->TryFixIt = SLSFix; pNew->Init = SLSInit; pNew->Close = SLSClose; return pNew; }