diff --git a/.gitignore b/.gitignore index 622f4098..c2a4a5c6 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ CVSPSI *.d *.out *.sqlite +parser.out +parsetab.py diff --git a/asynnet.c b/asynnet.c index d59c854d..a30e209a 100644 --- a/asynnet.c +++ b/asynnet.c @@ -45,7 +45,7 @@ #define MAXCONNECTIONS 1024 #define RBUFFERSIZE 262144 /* 256kb */ #define WBUFFERSIZE 20*262144 -/* #define WBUFFERSIZE 100*262144 /* +/* #define WBUFFERSIZE 100*262144 */ /*--------------------------------------------------------------------------*/ typedef struct { int socket; diff --git a/commandlog.c b/commandlog.c index e6439ec7..50192665 100644 --- a/commandlog.c +++ b/commandlog.c @@ -536,7 +536,7 @@ int CommandLog(SConnection * pCon, SicsInterp * pSics, void *pData, if (iCompact > 0) iIntervall = 0; } - SCPrintf(pCon, eValue, "%s.compact [sec] = %d", argv[0], iCompact); + SCPrintf(pCon, eValue, "%s.compact [sec] = %d", argv[0], (int)iCompact); return 1; } else if (strcmp(argv[1], "close") == 0) { /* close command */ fclose(fd); diff --git a/conman.c b/conman.c index 50febe35..04ef37a3 100644 --- a/conman.c +++ b/conman.c @@ -770,6 +770,61 @@ static int testAndWriteSocket(SConnection * pCon, char *buffer, int iOut) return 0; } +/*--------------------------------------------------------------------------*/ +static int isOK(const char *buffer) +{ + if ((buffer[0] == 'O' && buffer[1] == 'K') + && (buffer[2] == '\0' || buffer[2] == '\r' || buffer[2] == '\n')) + return 1; + return 0; +} + +/*--------------------------------------------------------------------------*/ +static void testAndWriteSICSLog(SConnection * self, char *buffer, int iOut) +{ + char *tp; + /* We don't want to log the "OK" messages */ + if (isOK(buffer)) + return; + + if (SCinMacro(self)) { + tp = "M"; + if (sicsdebug()) + tp = "D"; + } else + tp = "N"; + switch (iOut) { + case eStatus: + case eStart: + case eFinish: + case eEvent: + case eHdbValue: + case eHdbEvent: + case eLog: + case eLogError: + case eError: + case eWarning: + /* Log it */ + SICSLogPrintf(iOut, "%s:%s", tp, buffer); + return; + case eValue: + if (sicsdebug() || !SCinMacro(self)) { + /* Log it */ + SICSLogPrintf(iOut, "%s:%s", tp, buffer); + return; + } else { + /* Suppressed */ + /* SICSLogPrintf(iOut, "%s!:%s", tp, buffer); */ + return; + } + break; + default: + printf("Unrecognized ouput code %d in testAndWriteSICSLog: FIXME!!!\n", iOut); + SICSLogPrintf(iOut, "%s:%s", tp, buffer); + return; + } +} + /*--------------------------------------------------------------------------*/ int SCNormalWrite(SConnection * self, char *buffer, int iOut) { @@ -784,10 +839,14 @@ int SCNormalWrite(SConnection * self, char *buffer, int iOut) } /* log it for any case */ +#if 0 if ( (sicsdebug() || !SCinMacro(self)) && !(iOut == eInternal || (buffer[0] == 'O' && buffer[1] == 'K' && (buffer[2] == '\0' || buffer[2] == '\r' || buffer[2] == '\n')))) SICSLogWrite(buffer, iOut); +#else + testAndWriteSICSLog(self, buffer, iOut); +#endif testAndWriteCommandLog(self, buffer, iOut); diff --git a/conman.h b/conman.h index 8f085332..40308a3b 100644 --- a/conman.h +++ b/conman.h @@ -91,7 +91,14 @@ void SCSignalFunction(void *pCon, int iSignal, void *pSigData); /* ***************************** I/O ************************************** */ void SCSetOutputClass(SConnection * self, int iClass); int SCWrite(SConnection * self, char *pBuffer, int iOut); -int SCPrintf(SConnection * self, int iOut, char *fmt, ...); +#if __GNUC__ > 2 +#define G_GNUC_PRINTF( format_idx, arg_idx ) \ + __attribute__((__format__ (__printf__, format_idx, arg_idx))) +#else +#define G_GNUC_PRINTF( format_idx, arg_idx ) +#endif +int SCPrintf(SConnection * self, int iOut, char *fmt, ...) G_GNUC_PRINTF (3, 4); +#undef G_GNUC_PRINTF int SCRead(SConnection * self, char *pBuffer, int iBufLen); int SCPrompt(SConnection * pCon, char *pPrompt, char *pResult, int iLen); int SCSendOK(SConnection * self); diff --git a/counter.c b/counter.c index 0c820901..b5d0cea6 100644 --- a/counter.c +++ b/counter.c @@ -1142,7 +1142,7 @@ int CountAction(SConnection * pCon, SicsInterp * pSics, void *pData, iRet = self->pDriv->Get(self->pDriv, PaRes.Arg[0].text, PaRes.Arg[1].iVal, &fVal); if (iRet == 1) { - snprintf(pBueffel,255, "%s.%s %d = %f", argv[0], PaRes.Arg[0].text, + snprintf(pBueffel,255, "%s.%s %s = %f", argv[0], PaRes.Arg[0].text, PaRes.Arg[1].text, fVal); SCWrite(pCon, pBueffel, eValue); return 1; diff --git a/diffscan.c b/diffscan.c index 6334b0c3..284cb8bb 100644 --- a/diffscan.c +++ b/diffscan.c @@ -376,7 +376,7 @@ static int DiffScanTask(void *pData) status = GetDrivablePosition(pVar->pObject, self->scanObject->pCon, &fPos); if (status == 0) { - ReleaseCountLock(pCount->pCountInt); + ReleaseCountLock(pCount->pCountInt); return finish; } AppendScanVar(pVar, fPos); @@ -396,21 +396,21 @@ static int DiffScanTask(void *pData) rawCount = data->lCount; rawMon = data->Monitors[self->scaleMonitor - 1]; if(rawMon > 100){ - self->normalizationScale = rawMon; - traceSys("diffscan","START:normalizing on %d, scale monitor is %d", - self->normalizationScale, self->scaleMonitor); + self->normalizationScale = rawMon; + traceSys("diffscan","START:normalizing on %d, scale monitor is %d", + self->normalizationScale, self->scaleMonitor); } else { - traceSys("diffscan","START:normalization count %d, on scale monitor is %d and is to low", - rawMon, self->scaleMonitor); - SCWrite(self->scanObject->pCon,"WARNING: Skipping first point because of low count rate", eWarning); - return finish; + traceSys("diffscan","START:normalization count %ld, on scale monitor is %d and is to low", + rawMon, self->scaleMonitor); + SCWrite(self->scanObject->pCon,"WARNING: Skipping first point because of low count rate", eWarning); + return finish; } } else { if (data->Monitors[self->scaleMonitor - 1] - self->last.Monitors[self->scaleMonitor - 1] < 5) { SCWrite(self->scanObject->pCon, "WARNING: low count rate", eLog); - traceSys("diffscan","RUN:low monitor difference from %d to %d",data->Monitors[self->scaleMonitor-1], - self->last.Monitors[self->scaleMonitor -1]); + traceSys("diffscan","RUN:low monitor difference from %ld to %ld",data->Monitors[self->scaleMonitor-1], + self->last.Monitors[self->scaleMonitor -1]); } rawCount = data->lCount; rawMon = data->Monitors[self->scaleMonitor - 1]; @@ -441,8 +441,8 @@ static int DiffScanTask(void *pData) ReleaseHdbValue(&v); } InvokeCallBack(self->scanObject->pCall, SCANPOINT, self->scanObject); - traceSys("diffscan","RUN: pos, count, rawcount, rawmon: %f, %d, %d, %d", - fPos, countValue, rawCount, rawMon); + traceSys("diffscan","RUN: pos, count, rawcount, rawmon: %f, %f, %ld, %ld", + fPos, countValue, rawCount, rawMon); /* check for interrupt @@ -455,7 +455,7 @@ static int DiffScanTask(void *pData) } if(finish == 0) { - ReleaseCountLock(pCount->pCountInt); + ReleaseCountLock(pCount->pCountInt); } return finish; diff --git a/errormsg.h b/errormsg.h index 5f792147..e7630edc 100644 --- a/errormsg.h +++ b/errormsg.h @@ -35,7 +35,14 @@ typedef struct { * \return the new error message list head */ -void ErrPutMsg(ErrList *list, char *fmt, ...); +#if __GNUC__ > 2 +#define G_GNUC_PRINTF( format_idx, arg_idx ) \ + __attribute__((__format__ (__printf__, format_idx, arg_idx))) +#else +#define G_GNUC_PRINTF( format_idx, arg_idx ) +#endif +void ErrPutMsg(ErrList *list, char *fmt, ...) G_GNUC_PRINTF (2, 3); +#undef G_GNUC_PRINTF /** \brief Get the most recent error message * \param list the error list diff --git a/nserver.c b/nserver.c index 99b76c3f..9207eca9 100644 --- a/nserver.c +++ b/nserver.c @@ -48,7 +48,7 @@ extern void StopExit(void); /* in SICSmain.c */ extern int openDevexecLog(); /* in devexec.c */ -extern void NetWatchInit(void); /* in nwatch.c */ +extern int NetWatchTask(void *pData); /* in nwatch.c */ /* ========================= Less dreadful file statics =================== */ #define DEFAULTINIFILE "servo.tcl" @@ -120,7 +120,7 @@ int InitServer(char *file, pServer * pServ) pSICSOptions = IFAddOption(pSICSOptions, "ConMask", "0"); /* initialize the network watcher */ - NetWatchInit(); + TaskRegister(self->pTasker, NetWatchTask, NULL, NULL, NULL, 1); /* initialise the server from script */ SetWriteHistory(0); diff --git a/nwatch.c b/nwatch.c index af95dfeb..54ab513f 100644 --- a/nwatch.c +++ b/nwatch.c @@ -36,27 +36,24 @@ typedef struct __netwatcher_s { /* Singleton pattern */ static pNetWatch instance = NULL; -static int NetWatchTask(void *pData); - /** * \brief Initialises the Net Watcher singleton and starts the task * * \return 1=success, 0=failure */ -int NetWatchInit(void) +static pNetWatch NetWatchGetInstance(void) { /* * If the singleton has not yet been created, do so now */ if (instance == NULL) { instance = (pNetWatch) malloc(sizeof(NetWatch)); - if (instance == NULL) - return 0; - memset(instance, 0, sizeof(NetWatch)); - instance->lMagic = NWMAGIC; - TaskRegister(pServ->pTasker, NetWatchTask, NULL, NULL, NULL, 1); + if (instance != NULL) { + memset(instance, 0, sizeof(NetWatch)); + instance->lMagic = NWMAGIC; + } } - return 1; + return instance; } /* @@ -162,7 +159,7 @@ int NetWatchRegisterTimer(pNWTimer * handle, int mSec, pNWCallback callback, void *context) { assert(callback); - pNetWatch self = instance; + pNetWatch self = NetWatchGetInstance(); if (!self || self->lMagic != NWMAGIC) return 0; pNWTimer pNew = (pNWTimer) malloc(sizeof(NWTimer)); @@ -238,7 +235,7 @@ int NetWatchSetTimerPeriod(pNWTimer handle, int mSecPeriod) int NetWatchRemoveTimer(pNWTimer handle) { - pNetWatch self = instance; + pNetWatch self = NetWatchGetInstance(); if (!self || self->lMagic != NWMAGIC) return 0; if (handle == NULL || handle->vrfy != NWMAGIC) @@ -317,7 +314,7 @@ int NetWatchRegisterCallback(pNWContext * handle, int iSocket, { assert(callback); pNWContext pNew = NULL; - pNetWatch self = instance; + pNetWatch self = NetWatchGetInstance(); if (!self || self->lMagic != NWMAGIC) return 0; if (iSocket < 0 || iSocket > 65535) @@ -337,7 +334,7 @@ int NetWatchRegisterCallback(pNWContext * handle, int iSocket, int NetWatchRemoveCallback(pNWContext handle) { - pNetWatch self = instance; + pNetWatch self = NetWatchGetInstance(); if (handle == NULL || handle->vrfy != NWMAGIC) return 0; if (!self || self->lMagic != NWMAGIC) @@ -379,7 +376,7 @@ int NetWatchTask(void *pData) int iCount; /* Check the singleton */ - self = (pNetWatch) instance; + self = NetWatchGetInstance(); if (!self || self->lMagic != NWMAGIC) return 0; diff --git a/nxdict.c b/nxdict.c index f4b9f3c5..fcdde680 100644 --- a/nxdict.c +++ b/nxdict.c @@ -1475,6 +1475,126 @@ NXstatus NXDinfoalias(NXhandle hFil, NXdict dict, char *pAlias, int *rank, return iRet; } +/*------------------------------------------------------------------------*/ +NXstatus NXDdefnamedlink(NXhandle hFil, NXdict dict, + char *pTarget, char *pVictim, char *newname) +{ + NXdict pDict; + ParDat pParseT, pParseV; + int iRet, i, iStat; + NXlink sLink; + + pDict = NXDIAssert(dict); + + +#ifdef DEFDEBUG + printf("Linking: %s\n", pVictim); + printf("To: %s\n", pTarget); +#endif + + + /* parse Victim */ + pParseV.iMayCreate = 0; + pParseV.pPtr = pVictim; + pParseV.iDepth = 0; + iRet = NXDIDefParse(hFil, pDict, &pParseV); + if (iRet == NX_ERROR) { + /* unwind and throw up */ + NXDIUnwind(hFil, pParseV.iDepth); + return NX_ERROR; + } + /* get link data */ + if (pParseV.iTerminal == TERMSDS) { + NXgetdataID(hFil, &sLink); + iRet = NXclosedata(hFil); + if (iRet != NX_OK) { + /* unwind and throw up */ + NXDIUnwind(hFil, pParseV.iDepth); + return NX_ERROR; + } + } else if (pParseV.iTerminal == TERMVG) { + NXgetgroupID(hFil, &sLink); + } else { + assert(0); /* serious programming error */ + } + /* Unwind */ + iRet = NXDIUnwind(hFil, pParseV.iDepth); + if (iRet != NX_OK) { + return NX_ERROR; + } + + /* parse Target */ + pParseT.iMayCreate = 1; + pParseT.pPtr = pTarget; + pParseT.iDepth = 0; + iRet = NXDIDefParse(hFil, pDict, &pParseT); + if (iRet == NX_ERROR) { + /* unwind and throw up */ + NXDIUnwind(hFil, pParseT.iDepth); + return NX_ERROR; + } + /* check it being a vGroup! */ + if (pParseT.iTerminal != TERMVG) { + NXReportError("ERROR: can link only into a vGroup"); + NXDIUnwind(hFil, pParseT.iDepth); + return NX_ERROR; + } + + /* link, finally */ + iRet = NXmakenamedlink(hFil, newname, &sLink); + /* Unwind anyway */ + iStat = NXDIUnwind(hFil, pParseT.iDepth); + if (iStat != NX_OK) { + return NX_ERROR; + } + return iStat; +} + +/*--------------------------------------------------------------------------*/ +NXstatus NXDaliasnamedlink(NXhandle hFil, NXdict dict, + char *pTarget, char *pVictim, char *newname) +{ + char pTargetDef[2048], pVictimDef[2048]; + int iRet; + NXdict pDict; + pDynString pRep1 = NULL, pRep2 = NULL; + + pDict = NXDIAssert(dict); + + /* get Target Definition String */ + iRet = NXDget(pDict, pTarget, pTargetDef, 2047); + if (iRet != NX_OK) { + sprintf(pTargetDef, "ERROR: alias %s not recognized", pTarget); + NXReportError(pTargetDef); + return NX_ERROR; + } + + /* get Victim definition string */ + iRet = NXDget(pDict, pVictim, pVictimDef, 2047); + if (iRet != NX_OK) { + sprintf(pTargetDef, "ERROR: alias %s not recognized", pTarget); + NXReportError(pTargetDef); + return NX_ERROR; + } + + /* do replacements */ + pRep1 = NXDItextreplace(dict, pTargetDef); + pRep2 = NXDItextreplace(dict, pVictimDef); + if ((!pRep1) || (!pRep2)) { + if (pRep1) + DeleteDynString(pRep1); + if (pRep2) + DeleteDynString(pRep2); + return NX_ERROR; + } + + /* call NXdeflin */ + iRet = NXDdefnamedlink(hFil, pDict, GetCharArray(pRep1), GetCharArray(pRep2), newname); + DeleteDynString(pRep1); + DeleteDynString(pRep2); + return iRet; +} + /*------------------------------------------------------------------------*/ NXstatus NXDdeflink(NXhandle hFil, NXdict dict, char *pTarget, char *pVictim) diff --git a/nxscript.c b/nxscript.c index ed3ad5c5..de704b75 100644 --- a/nxscript.c +++ b/nxscript.c @@ -1589,6 +1589,31 @@ static void makeLink(SConnection * pCon, SicsInterp * pSics, SCSendOK(pCon); } +/*----------------------------------------------------------------------*/ +static void makeNamedLink(SConnection * pCon, SicsInterp * pSics, + pNXScript self, int argc, char *argv[]) +{ + int status; + char pBueffel[256]; + + if (argc < 5) { + SCWrite(pCon, "ERROR: insufficient number of arguments to makenamedlink", + eLogError); + return; + } + + status = NXDaliasnamedlink(self->fileHandle, self->dictHandle, + argv[2], argv[3], argv[4]); + if (status != NX_OK) { + snprintf(pBueffel, 255, "ERROR: linking %s against %s as %s failed", + argv[2], argv[3], argv[4]); + SCWrite(pCon, pBueffel, eLogError); + return; + } + + SCSendOK(pCon); +} + /*----------------------------------------------------------------------*/ static void updateDictVar(SConnection * pCon, pNXScript self, int argc, char *argv[]) @@ -1698,6 +1723,10 @@ int NXScriptAction(SConnection * pCon, SicsInterp * pSics, void *pData, makeLink(pCon, pSics, self, argc, argv); return 1; } + if (strcmp(argv[1], "makenamedlink") == 0) { + makeNamedLink(pCon, pSics, self, argc, argv); + return 1; + } return 1; } diff --git a/nxxml.c b/nxxml.c index 12f4de16..131b3afe 100644 --- a/nxxml.c +++ b/nxxml.c @@ -779,7 +779,7 @@ NXstatus NXXputdatatable (NXhandle fid, const void *data){ } /*------------------------------------------------------------------------*/ -NXstatus NXXputdata (NXhandle fid, void *data){ +NXstatus NXXputdata (NXhandle fid, const void *data){ pXMLNexus xmlHandle = NULL; mxml_node_t *userData = NULL; mxml_node_t *current = NULL; @@ -1074,8 +1074,8 @@ NXstatus NXXputslabtable (NXhandle fid, const void *data, return NX_OK; } /*----------------------------------------------------------------------*/ -NXstatus NXXputslab64 (NXhandle fid, void *data, - int64_t iStart[], int64_t iSize[]){ +NXstatus NXXputslab64 (NXhandle fid, const void *data, + const int64_t iStart[], const int64_t iSize[]){ pXMLNexus xmlHandle = NULL; mxml_node_t *userData = NULL; @@ -1295,7 +1295,7 @@ static char *formatAttributeData(const void *data, int datalen, int iType){ return number; } /*---------------------------------------------------------------------*/ -NXstatus NXXputattr (NXhandle fid, CONSTCHAR *name, void *data, +NXstatus NXXputattr (NXhandle fid, CONSTCHAR *name, const void *data, int datalen, int iType){ char buffer[256]; pXMLNexus xmlHandle = NULL; diff --git a/nxxml.h b/nxxml.h index ee7e9ece..03c09a2c 100644 --- a/nxxml.h +++ b/nxxml.h @@ -44,15 +44,15 @@ NXstatus NXXmakedata64 (NXhandle fid, int rank, int64_t dimensions[]); NXstatus NXXopendata (NXhandle fid, CONSTCHAR *name); NXstatus NXXclosedata (NXhandle fid); -NXstatus NXXputdata (NXhandle fid, void *data); +NXstatus NXXputdata (NXhandle fid, const void *data); NXstatus NXXgetdata (NXhandle fid, void *data); NXstatus NXXgetinfo64 (NXhandle fid, int *rank, int64_t dimension[], int *iType); -NXstatus NXXputslab64 (NXhandle fid, void *data, - int64_t iStart[], int64_t iSize[]); +NXstatus NXXputslab64 (NXhandle fid, const void *data, + const int64_t iStart[], const int64_t iSize[]); NXstatus NXXgetslab64 (NXhandle fid, void *data, const int64_t iStart[], const int64_t iSize[]); -NXstatus NXXputattr (NXhandle fid, CONSTCHAR *name, void *data, +NXstatus NXXputattr (NXhandle fid, CONSTCHAR *name, const void *data, int datalen, int iType); NXstatus NXXgetattr (NXhandle fid, char *name, void *data, int* datalen, int* iType); diff --git a/protocol.c b/protocol.c index e1c87863..aa27a960 100644 --- a/protocol.c +++ b/protocol.c @@ -172,7 +172,7 @@ static int ContextDo(SConnection * pCon, SicsInterp * pSics, void *pData, comCon = SCCopyConnection(pCon); if (comCon == NULL) { - SCWrite(pCon, "EROOR: out of memory in contextdo", eError); + SCWrite(pCon, "ERROR: out of memory in contextdo", eError); return 0; } status = Tcl_GetInt(pSics->pTcl, argv[1], &comCon->transID); diff --git a/sansbc.c b/sansbc.c index 985d70ea..e40e1e44 100644 --- a/sansbc.c +++ b/sansbc.c @@ -204,7 +204,7 @@ static int StatCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode, } average = (double)sum/(double)length; - SCPrintf(pCon,eValue,"Stat:sum,max,min,av = %d,%d,%d,%f", sum,max,min,average); + SCPrintf(pCon,eValue,"Stat:sum,max,min,av = %ld,%ld,%ld,%f", sum,max,min,average); return 1; } diff --git a/scriptcontext.c b/scriptcontext.c index 74eb901f..cf5c7634 100644 --- a/scriptcontext.c +++ b/scriptcontext.c @@ -402,6 +402,7 @@ static char *SctActionHandler(void *actionData, char *lastReply, char *errorScript = NULL; char *send = NULL; int i; + int j; SConnection *con; char eprop[80]; char msg[1024]; @@ -516,6 +517,21 @@ static char *SctActionHandler(void *actionData, char *lastReply, if (strcasecmp(data->name, "read") == 0) { SetHdbProperty(node, "geterror", result); } + /* Sanitize the text to reduce TCL problems with unbalanced and substituted items */ + for (j = 0; msg[j]; ++j) { + switch (msg[j]) { + case '{': + case '}': + case '[': + case ']': + case '<': + case '>': + case '\'': + case '"': + case '$': + msg[j] = '_'; + } + } SetHdbProperty(node, eprop, msg); blank = strchr(origScript, ' '); if (blank != NULL) { @@ -531,6 +547,21 @@ static char *SctActionHandler(void *actionData, char *lastReply, } cnt++; snprintf(msg, sizeof msg, "%dx {%s}: %s", cnt, origScript, result); + /* Sanitize the text to reduce TCL problems with unbalanced and substituted items */ + for (j = 0; msg[j]; ++j) { + switch (msg[j]) { + case '{': + case '}': + case '[': + case ']': + case '<': + case '>': + case '\'': + case '"': + case '$': + msg[j] = '_'; + } + } SetHdbProperty(node, eprop, msg); send = NULL; free(script); diff --git a/servlog.c b/servlog.c index d5f9c02e..a4e0ec47 100644 --- a/servlog.c +++ b/servlog.c @@ -82,6 +82,28 @@ typedef struct __LogLog { static pCaptureEntry pCapture = NULL; /*------------------------------------------------------------------------*/ +static char* OutCodeToTxt(OutCode eOut) +{ + switch (eOut) { + case eInternal: return "Int"; /* internal */ + case eCommand: return "Cmd"; /* reserved, not used */ + case eHWError: return "ErH"; /* reserved, used only for SICSLog */ + case eInError: return "ErI"; /* reserved, used as a mark in the handling of output codes */ + case eStatus: return "Sta"; /* reserved, deprecated */ + case eValue: return "Val"; /* value reponse: copied into Tcl */ + case eStart: return "Beg"; /* start message */ + case eFinish: return "End"; /* finish message */ + case eEvent: return "Evt"; /* some callback messages */ + case eWarning: return "Wrn"; /* warnings */ + case eError: return "Err"; /* error: copied into Tcl */ + case eHdbValue: return "HVa"; /* hipadaba value chnage */ + case eHdbEvent: return "HEv"; /* Hipadaba event */ + case eLog: return "Log"; /* log message: is always written to client */ + case eLogError: return "ErL"; /* error message to log: is always written to client */ + } + return "???"; +} + int KillCapture(SConnection * pCon) { pCaptureEntry pCurrent, pTemp; @@ -325,7 +347,7 @@ static void SICSLogWriteFile(char *pText, OutCode eOut, struct timeval *tp) if (iLineCount == 0) fprintf(fLogFile, "%s: <<>>\n", timestamp(NULL)); - fprintf(fLogFile, "%s: ", timestamp(tp)); + fprintf(fLogFile, "%s:%s:", timestamp(tp), OutCodeToTxt(eOut)); fprintf(fLogFile, "%s", pText); if (text_len < 1 || pText[text_len - 1] != '\n') fprintf(fLogFile, "\n"); @@ -351,6 +373,8 @@ void SICSLogWriteTime(char *pText, OutCode eOut, struct timeval *tp) buf[idx++] = '\0'; SICSLogWriteFile(buf, eOut, tp); idx = 0; + buf[idx++] = '*'; + buf[idx++] = ':'; } else if (*cp == '\r') { buf[idx++] = '\\'; buf[idx++] = 'r'; @@ -372,6 +396,8 @@ void SICSLogWriteTime(char *pText, OutCode eOut, struct timeval *tp) buf[idx++] = '\0'; SICSLogWriteFile(buf, eOut, tp); idx = 0; + buf[idx++] = '*'; + buf[idx++] = ':'; } } if (idx > 0) { @@ -521,29 +547,3 @@ void SICSLogPrintf(OutCode eOut, const char *fmt, ...) SICSLogWrite(buf, eOut); return; } - -/* Test of the logging facilities */ -int testLogCmd(SConnection *pCon, SicsInterp *pInter, void *pData, - int argc, char *argv[]) { - char lbuf[2048]; - char sbuf[1000]; - int i; - SICSLogWrite("Multiline:\nLine 1\r\nLine 2\r\nLine 3\r\n", eStatus); - memset(lbuf, 0, sizeof(lbuf)); - memset(sbuf, ' ', sizeof(sbuf)); - SICSLogPrintf(eStatus, "Hexlog %d all zero bytes", sizeof(lbuf)); - SICSLogWriteHex(lbuf, sizeof(lbuf), eStatus); - for (i = 0; i <= 128; ++i) - sbuf[i] = sbuf[sizeof(sbuf) - 1 - i] = i; - sbuf[sizeof(sbuf) / 2] = '!'; - SICSLogPrintf(eStatus, "Hexlog %d mid space bytes", sizeof(sbuf)); - SICSLogWriteHex(sbuf, sizeof(sbuf), eStatus); - for (i = 0; i < 1000; ++i) - sbuf[i] = ' ' + (i % 96); - sbuf[sizeof(sbuf) - 1] = '\0'; - SICSLogWrite("Very long line 1000 bytes", eStatus); - SICSLogWrite(sbuf, eStatus); - SCSendOK(pCon); - return OKOK; -} - diff --git a/servlog.h b/servlog.h index 0b928cd7..ebe788d1 100644 --- a/servlog.h +++ b/servlog.h @@ -20,9 +20,16 @@ void SICSLogWriteTime(char *ptext, OutCode eOut, struct timeval *tp); void SICSLogWriteHex(const char *text, int count, OutCode eOut); void SICSLogWriteHexTime(const char *text, int count, OutCode eOut, struct timeval *tp); -void SICSLogPrintf(OutCode eOut, const char *fmt, ...); +#if __GNUC__ > 2 +#define G_GNUC_PRINTF( format_idx, arg_idx ) \ + __attribute__((__format__ (__printf__, format_idx, arg_idx))) +#else +#define G_GNUC_PRINTF( format_idx, arg_idx ) +#endif +void SICSLogPrintf(OutCode eOut, const char *fmt, ...) G_GNUC_PRINTF (2, 3); void SICSLogTimePrintf(OutCode eOut, struct timeval *tp, const char *fmt, - ...); + ...) G_GNUC_PRINTF (3, 4); +#undef G_GNUC_PRINTF void SICSLogEnable(int flag); int KillCapture(SConnection * pCon); diff --git a/simidx.h b/simidx.h index 17668ecc..b29d14df 100644 --- a/simidx.h +++ b/simidx.h @@ -85,6 +85,7 @@ int SimIdxRun(); * \param errCode pointer to an integer error code * \param error A text buffer to hold a description of the error * \param errLen The length of error + */ void SimIdxGetError(int *errCode, char *error, int errLen); /** diff --git a/site_ansto/Makefile b/site_ansto/Makefile index 7d046db8..a4d98ec4 100644 --- a/site_ansto/Makefile +++ b/site_ansto/Makefile @@ -163,6 +163,8 @@ kookaburra: all make -C instrument/kookaburra dingo: all make -C instrument/dingo +bilby: all +emu: all libansto.a: $(OBJ) rm -f libansto.a @@ -170,10 +172,10 @@ libansto.a: $(OBJ) ranlib libansto.a libhardsup: - $(MAKE) -C hardsup/ INC_TCL8="$(INC_TCL8)" + $(MAKE) -C hardsup/ INC_TCL8="$(INC_TCL8)" "CC=${CC}" libsics: - $(MAKE) -C .. -f site_ansto/Makefile_SICS INC_TCL8="$(INC_TCL8)" INC_HDF5="$(INC_HDF5)" all + $(MAKE) -C .. -f site_ansto/Makefile_SICS INC_TCL8="$(INC_TCL8)" INC_HDF5="$(INC_HDF5)" "CC=${CC}" all anstohm.o : anstohm.cpp $(CXX) -c anstohm.cpp $(CFLAGS) $(CXXFLAGS) -Wno-all diff --git a/site_ansto/ansto_sctdriveadapter.c b/site_ansto/ansto_sctdriveadapter.c index 5bf82502..6393af38 100644 --- a/site_ansto/ansto_sctdriveadapter.c +++ b/site_ansto/ansto_sctdriveadapter.c @@ -1,18 +1,18 @@ /** - * This is an adapter to a node under the control of the new - * scriptcontext generic device model. This is a wrapper around + * This is an adapter to a node under the control of the new + * scriptcontext generic device model. This is a wrapper around * such a node which implements the drivable interface. - * + * * Some cooperation from the node is required: It has to provide - * certain properties the value of which define scripts which + * certain properties the value of which define scripts which * have to be called at various stages. These are: - * + * * checklimits, for limits checking * checkstatus, for evaluating progress * halt , for halting things - * + * * copyright: see file COPYRIGHT - * + * * Mark Koennecke, June 2008 * --------------------------------------------------------------*/ #include @@ -24,16 +24,16 @@ #include "scriptcontext.h" /*---------------------------------------------------------------*/ typedef struct { - pObjectDescriptor pDes; - pIDrivable pDriv; - pHdb write_node; - pHdb read_node; - SctController *c; + pObjectDescriptor pDes; + pIDrivable pDriv; + pHdb write_node; + pHdb read_node; + SctController *c; }SctDrive, *pSctDrive; /*---------------------------------------------------------------*/ static void *SCTDRIVGetInterface(void *data, int iD){ - pSctDrive self = NULL; - + pSctDrive self = NULL; + self = (pSctDrive)data; if(self != NULL && iD == DRIVEID){ if (self->write_node == NULL) return NULL; @@ -48,51 +48,51 @@ static void *SCTDRIVGetInterface(void *data, int iD){ go wrong. However, the return value of Halt is usually ignored! ------------------------------------------------------------------*/ static int SCTDRIVHalt(void *data) { - pSctDrive self = NULL; + pSctDrive self = NULL; char dummy[16]; - + self = (pSctDrive)data; if (GetHdbProperty(self->write_node,"halt", dummy, sizeof dummy)) { SctQueueNode(self->c, self->write_node, HaltPRIO, "halt", NULL); } else if (GetHdbProperty(self->write_node, "status", dummy, sizeof dummy)) { SetHdbProperty(self->write_node, "status", "idle"); } - return OKOK; + return OKOK; } /*---------------------------------------------------------------- - This routine can return either 1 or 0. 1 means the position can + This routine can return either 1 or 0. 1 means the position can be reached, 0 NOT If 0, error shall contain up to errlen characters of information about which limit was violated ------------------------------------------------------------------*/ static int SCTDRIVCheckLimits(void *data, float val, char *error, int errlen){ - pSctDrive self = NULL; + pSctDrive self = NULL; char script[1024]; int status; Tcl_Interp *pTcl = NULL; char *result; - + self = (pSctDrive)data; snprintf(script,1024,"%f", val); SetHdbProperty(self->write_node,"target", script); if(GetHdbProperty(self->write_node,"checklimits",script,1024)){ - status = SctCallInContext(pServ->dummyCon, script, - self->write_node, self->c, &result); - if(SctVerbose(self->c)){ - SCPrintf(pServ->dummyCon, eWarning, "script %s called with result %s\n ", - script, result); - } - if(status == 0){ - strncpy(error,result,errlen); - return 0; - } + status = SctCallInContext(pServ->dummyCon, script, + self->write_node, self->c, &result); + if(SctVerbose(self->c)){ + SCPrintf(pServ->dummyCon, eWarning, "script %s called with result %s\n ", + script, result); + } + if(status == 0){ + strncpy(error,result,errlen); + return 0; + } } return 1; } /*---------------------------------------------------------------- - This routine can return 0 when a limit problem occurred - OKOK when the motor was successfully started + This routine can return 0 when a limit problem occurred + OKOK when the motor was successfully started HWFault when a problem occured starting the device Possible errors shall be printed to pCon For real motors, this is supposed to try at least three times @@ -100,19 +100,19 @@ static int SCTDRIVCheckLimits(void *data, float val, val is the value to drive the motor too ------------------------------------------------------------------*/ static long SCTDRIVSetValue(void *data, SConnection *pCon, float val){ - pSctDrive self = NULL; + pSctDrive self = NULL; int status; hdbValue v; - + self = (pSctDrive)data; v.dataType = HIPFLOAT; v.v.doubleValue = (double)val; SetHdbProperty(self->write_node,"writestatus", "start"); status = SetHipadabaPar(self->write_node, v, pCon); if(status == 1){ - return OKOK; + return OKOK; } else { - return HWFault; + return HWFault; } } /*---------------------------------------------------------------- @@ -122,28 +122,28 @@ static long SCTDRIVSetValue(void *data, SConnection *pCon, float val){ HWFault when a hardware problem ocurred HWPosFault when the hardware cannot reach a position Errors are duly to be printed to pCon - For real motors CheckStatus again shall try hard to fix any - issues with the motor + For real motors CheckStatus again shall try hard to fix any + issues with the motor ------------------------------------------------------------------*/ static int SCTDRIVCheckStatus(void *data, SConnection *pCon){ - pSctDrive self = NULL; + pSctDrive self = NULL; char script[1024]; int status; Tcl_Interp *pTcl = NULL; char *result; SConnection *con; - + self = (pSctDrive)data; - + /* * check if the write command has gone through */ if(GetHdbProperty(self->write_node,"writestatus", script,1024)){ - if(strcmp(script,"start") == 0){ - return HWBusy; - } + if(strcmp(script,"start") == 0){ + return HWBusy; + } } - + /* * run the checkstatus script */ @@ -155,16 +155,16 @@ static int SCTDRIVCheckStatus(void *data, SConnection *pCon){ } result = script; } else { - status = SctCallInContext(pCon,script, self->write_node, + status = SctCallInContext(pCon,script, self->write_node, self->c, &result); if (status == 0) { - SCPrintf(pCon,eError," script %s returned %s", - script, result); + SCPrintf(pCon,eError," script %s returned %s", + script, result); return HWFault; } if(SctVerbose(self->c)){ - SCPrintf(pCon,eError," script %s returned %s", - script, result); + SCPrintf(pCon,eError," script %s returned %s", + script, result); } } if(strstr(result,"busy") != NULL){ @@ -188,16 +188,16 @@ static int SCTDRIVCheckStatus(void *data, SConnection *pCon){ On errors, -99999999.99 is returned and messages printed to pCon ------------------------------------------------------------------*/ static float SCTDRIVGetValue(void *data, SConnection *pCon){ - pSctDrive self = NULL; + pSctDrive self = NULL; float val = -99999999.99; int status; char error[256]; hdbValue v; - + self = (pSctDrive)data; if(GetHdbProperty(self->read_node,"geterror", error, 256)){ - SCWrite(pCon,error, eError); - return val; + SCWrite(pCon,error, eError); + return val; } return (float)self->read_node->value.v.doubleValue; } @@ -205,19 +205,19 @@ static float SCTDRIVGetValue(void *data, SConnection *pCon){ returns NULL on failure, a new datastructure else ------------------------------------------------------------------*/ static pSctDrive SCTDRIVMakeObject(){ - pSctDrive self = NULL; + pSctDrive self = NULL; self = calloc(sizeof(SctDrive),1); if(self == NULL){ - return NULL; + return NULL; } self->pDes = CreateDescriptor("SctDriveAdapter"); self->pDriv = CreateDrivableInterface(); if(self->pDes == NULL || self->pDriv == NULL){ - free(self); - return NULL; + free(self); + return NULL; } - + self->pDes->GetInterface = SCTDRIVGetInterface; self->pDriv->Halt = SCTDRIVHalt; self->pDriv->CheckLimits = SCTDRIVCheckLimits; @@ -230,36 +230,36 @@ static pSctDrive SCTDRIVMakeObject(){ /*-----------------------------------------------------------------*/ static int SctDriveCommand(SConnection *pCon, SicsInterp *sics, void *object, int argc, char *argv[]) { - pSctDrive self = (pSctDrive)object; - float val; - - assert(self != NULL); - - if (self->write_node == NULL) { - SCWrite(pCon, "ERROR: defunct object", eError); - return 0; - } - /* - * only action: print value - */ - val = self->pDriv->GetValue(self,pCon); - SCPrintf(pCon,eValue,"%s = %f", argv[0], val); - return 1; + pSctDrive self = (pSctDrive)object; + float val; + + assert(self != NULL); + + if (self->write_node == NULL) { + SCWrite(pCon, "ERROR: defunct object", eError); + return 0; + } + /* + * only action: print value + */ + val = self->pDriv->GetValue(self,pCon); + SCPrintf(pCon,eValue,"%s = %f", argv[0], val); + return 1; } /*----------------------------------------------------------------*/ static void SctDriveKill(void *data){ - pSctDrive self = (pSctDrive)data; - - if(self == NULL){ - return; - } - if(self->pDriv != NULL){ - free(self->pDriv); - } - if(self->pDes != NULL){ - DeleteDescriptor(self->pDes); - } - free(self); + pSctDrive self = (pSctDrive)data; + + if(self == NULL){ + return; + } + if(self->pDriv != NULL){ + free(self->pDriv); + } + if(self->pDes != NULL){ + DeleteDescriptor(self->pDes); + } + free(self); } /*----------------------------------------------------------------*/ static hdbCallbackReturn SctDummyCallback(Hdb *node, void *userData, @@ -274,44 +274,44 @@ static void SctDriveDeleteNode(void *data) { /*---------------------------------------------------------------*/ int ANSTO_SctMakeDriveAdapter(SConnection *pCon, SicsInterp *pSics, void *object, int argc, char *argv[]) { - pSctDrive pNew = NULL; - pSICSOBJ obj = NULL; + pSctDrive pNew = NULL; + pSICSOBJ obj = NULL; hdbCallback *cb; - - pNew = SCTDRIVMakeObject(); - if(pNew == NULL){ - SCWrite(pCon,"ERROR: out of memory in ANSTO_SctMakeDriveAdapter", - eError); - return 0; - } - - if(argc < 4){ - SCWrite(pCon,"ERROR: not enough arguments for ANSTO_SctMakeDriveAdapter", eError); - return 0; - } - - pNew->write_node = FindHdbNode(NULL,argv[2], pCon); - pNew->read_node = FindHdbNode(NULL,argv[3], pCon); - obj = FindCommandData(pSics,argv[4], "SctController"); - if(pNew->write_node == NULL || obj == NULL){ - SCWrite(pCon,"ERROR: node or controller not found", eError); - SctDriveKill(pNew); - return 0; - } - pNew->c =(SctController *)obj->pPrivate; - + + if(argc < 4){ + SCWrite(pCon,"ERROR: not enough arguments for ANSTO_SctMakeDriveAdapter", eError); + return 0; + } + + pNew = SCTDRIVMakeObject(); + if(pNew == NULL){ + SCWrite(pCon,"ERROR: out of memory in ANSTO_SctMakeDriveAdapter", + eError); + return 0; + } + + pNew->write_node = FindHdbNode(NULL,argv[2], pCon); + pNew->read_node = FindHdbNode(NULL,argv[3], pCon); + obj = FindCommandData(pSics,argv[4], "SctController"); + if(pNew->write_node == NULL || obj == NULL){ + SCWrite(pCon,"ERROR: node or controller not found", eError); + SctDriveKill(pNew); + return 0; + } + pNew->c =(SctController *)obj->pPrivate; + if (strcasecmp(argv[0],"dynsctdrive") == 0) { /* make object dynamic by defining a descriptor command */ SetDescriptorKey(pNew->pDes, "creationCommand", "0"); } - AddCommand(pSics, argv[1], SctDriveCommand, SctDriveKill, pNew); - SetHdbProperty(pNew->write_node,"sicsdev",argv[1]); - + AddCommand(pSics, argv[1], SctDriveCommand, SctDriveKill, pNew); + SetHdbProperty(pNew->write_node,"sicsdev",argv[1]); + cb = MakeHipadabaCallback(SctDummyCallback, pNew, SctDriveDeleteNode); assert(cb); AppendHipadabaCallback(pNew->write_node, cb); - - return 1; + + return 1; } /*---------------------------------------------------------------*/ diff --git a/site_ansto/ansto_tclmotdriv.c b/site_ansto/ansto_tclmotdriv.c index 57b447df..753a58f3 100644 --- a/site_ansto/ansto_tclmotdriv.c +++ b/site_ansto/ansto_tclmotdriv.c @@ -397,27 +397,29 @@ static int TclSetPar(void *self, SConnection * pCon, char *name, if (result == NULL) { pDriv->errorCode = NOTCLRESULT; free(tclCommand); - free(tclCommandPara);; + free(tclCommandPara); return HWFault; } if (status != TCL_OK) { pDriv->errorCode = TCLERROR; strncpy(pDriv->tclError, result, 1023); free(tclCommand); - free(tclCommandPara);; + free(tclCommandPara); return HWFault; } else { snprintf(pBuffer, 511, "%s.%s = %s", pDriv->motName, name, result); SCWrite(pCon, pBuffer, eValue); } free(tclCommand); - free(tclCommandPara);; + free(tclCommandPara); return OKOK; } else { pDriv->errorCode = PARANOTFOUND; + free(tclCommand); return 0; } + free(tclCommand); return OKOK; } } diff --git a/site_ansto/hardsup/Monitor/sock.c b/site_ansto/hardsup/Monitor/sock.c index 5f957fc3..e3ce1be7 100644 --- a/site_ansto/hardsup/Monitor/sock.c +++ b/site_ansto/hardsup/Monitor/sock.c @@ -422,6 +422,7 @@ void sock_accept(int n) fdv[num_fds].device = fdv[n].device; fdv[num_fds].line_len = 0; fdv[num_fds].state = 0; + fdv[num_fds].match = 0; fds[num_fds].fd = sock_n; fds[num_fds].events = POLLIN; ++num_fds; diff --git a/site_ansto/hardsup/chopper.c b/site_ansto/hardsup/chopper.c index 218b2b89..1958708f 100644 --- a/site_ansto/hardsup/chopper.c +++ b/site_ansto/hardsup/chopper.c @@ -1,9 +1,9 @@ /*-------------------------------------------------------------- - This is a driver for the newer Astrium == Dornier chopper + This is a driver for the newer Astrium == Dornier chopper systems which use a TCP/IP server for communication. This driver has to take care of some ugliness: - As of december 2005, the communication is in unicode! - To go from ASCII to unicode and back one has to + To go from ASCII to unicode and back one has to add a 0x00 before each character or to remove it. - The controller is slow in responding and the controller must be watched in the environment monitor. This is taken @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include /*======================================================================== Our private data structure @@ -62,7 +62,7 @@ Error codes: #define BADVALUE -8310 extern char *trim(char *str); -#define ABS(x) (x < 0 ? -(x) : (x)) +#define ABS(x) (x < 0 ? -(x) : (x)) #define SPEEDTOL 2 #define PHASETOL 0.2 @@ -76,15 +76,15 @@ static int asciiToUnicode(char *input, char **output){ len = strlen(input); result = (char *)malloc(2*len*sizeof(char)); if(result == NULL){ - return 0; + return 0; } memset(result,0,2*len*sizeof(char)); for(i = 0; i < len; i++){ - result[i*2] = input[i]; + result[i*2] = input[i]; } - *output = result; + *output = result; return 2*len; -} +} #endif /*-------------------------------------------------------------------*/ #if 0 @@ -96,11 +96,11 @@ static int unicodeToAscii(char *input, int len, char **output){ result = (char *)malloc((alen+1)*sizeof(char)); if(result == NULL){ - return 0; + return 0; } memset(result,0,(alen+1)*sizeof(char)); for(i = 0; i < alen; i++){ - result[i] = input[i*2]; + result[i] = input[i*2]; } *output = result; return alen; @@ -108,7 +108,7 @@ static int unicodeToAscii(char *input, int len, char **output){ #endif /*----------------------------------------------------------------*/ static int tcpDoChoSend(pTcpDoCho self, char *command, int choNum, - char *value){ + char *value){ char buffer[1024]; int sendlen, status; @@ -117,22 +117,22 @@ static int tcpDoChoSend(pTcpDoCho self, char *command, int choNum, */ self->lastError = 0; if(choNum < 0){ - snprintf(buffer,1023,"#SOS#%s \r\n",command); + snprintf(buffer,1023,"#SOS#%s \r\n",command); } else if(value != NULL){ - snprintf(buffer,1023,"#SOS#%s%1.1d: %s\r\n",command, choNum, - value); + snprintf(buffer,1023,"#SOS#%s%1.1d: %s\r\n",command, choNum, + value); } else { - snprintf(buffer,1023,"#SOS#%s%1.1d:\r\n",command, choNum); + snprintf(buffer,1023,"#SOS#%s%1.1d:\r\n",command, choNum); } sendlen = strlen(buffer); if(sendlen == 0){ - self->lastError = BADCONVERSION; - return 0; + self->lastError = BADCONVERSION; + return 0; } status = send(self->controller->pSock->sockid,buffer,sendlen,0); if(status < 0){ - self->lastError = BADWRITE; - return 0; + self->lastError = BADWRITE; + return 0; } return 1; } @@ -147,14 +147,14 @@ static int statusComplete(char *statusMessage){ */ pPtr = strstr(statusMessage,"TIME"); if(pPtr != NULL){ - pPtr = strstr(pPtr+6,"#"); - if(pPtr != NULL){ - return 1; - } else { - return 0; - } + pPtr = strstr(pPtr+6,"#"); + if(pPtr != NULL){ + return 1; + } else { + return 0; + } } else { - return 0; + return 0; } } /*---------------------------------------------------------------*/ @@ -164,7 +164,7 @@ static int readChopperNum(char *entry){ pPtr = strstr(entry,"CH"); if(pPtr == NULL){ - return -1; + return -1; } sscanf(pPtr+3,"%d",&num); return num; @@ -194,27 +194,27 @@ static void addEntry(pTcpDoCho self, int choNum, char *entry){ StringDictAddPair(self->parameters,name,trim(value)); } } -} +} /*----------------------------------------------------------------*/ static int parseStatus(pTcpDoCho self, char *statusMessage){ int choNum; char entry[80], *pPtr; - + pPtr = statusMessage; /* skip over SOS */ pPtr = stptok(pPtr,entry,79,"#"); pPtr = stptok(pPtr,entry,79,"#"); pPtr = stptok(pPtr,entry,79,"#"); - + choNum = readChopperNum(entry); if(choNum < 0){ - self->lastError = BADRESPONSE; - return 0; + self->lastError = BADRESPONSE; + return 0; } while((pPtr = stptok(pPtr,entry,79,"#")) != NULL){ - addEntry(self,choNum,entry); - memset(entry,0,80); + addEntry(self,choNum,entry); + memset(entry,0,80); } return 1; } @@ -229,51 +229,51 @@ static int tcpDoChoReceive(pTcpDoCho self){ bytesRead = 0; memset(buffer,0,1024*sizeof(char)); while(time(NULL) < endTime){ - if(availableRS232(self->controller)){ - bytesRead += recv(self->controller->pSock->sockid,buffer+bufferStart, - 1024 - bytesRead,0); - if(bytesRead < 0){ - self->lastError = BADREAD; - return 0; - } + if(availableRS232(self->controller)){ + bytesRead += recv(self->controller->pSock->sockid,buffer+bufferStart, + 1024 - bytesRead,0); + if(bytesRead < 0){ + self->lastError = BADREAD; + return 0; + } if(strstr(buffer,"State") != NULL){ - if(statusComplete(buffer) == 0) { - continue; - } else { - status = parseStatus(self,buffer); - return status; - } - } - if(strstr(buffer,"ACCEPT") != NULL){ - return 1; + if(statusComplete(buffer) == 0) { + continue; + } else { + status = parseStatus(self,buffer); + return status; + } + } + if(strstr(buffer,"ACCEPT") != NULL){ + return 1; } else if(strstr(buffer,"NCCEPT") != NULL){ - self->lastError = FAILEDCOMMAND; - return 0; + self->lastError = FAILEDCOMMAND; + return 0; } else { - self->lastError = BADRESPONSE; - return 0; - } + self->lastError = BADRESPONSE; + return 0; + } } else { - SicsWait(1); - } + SicsWait(1); + } } self->lastError = TIMEOUT; return 0; } /*-----------------------------------------------------------------*/ static int tcpDoChoCommand(pTcpDoCho self, char *command, int choNum, - char *value){ + char *value){ int status; - + status = tcpDoChoSend(self,command,choNum,value); if(status == 0){ - return 0; + return 0; } return tcpDoChoReceive(self); } /*---------------------------------------------------------------*/ /* TODO Check for response on authentication - * authentication succeeded: #SES#Hello + * authentication succeeded: #SES#Hello * authentication failed: #SES#You are not a valid user, try again! * Make sure that ch2,3,4 are set to MW on init */ @@ -283,8 +283,8 @@ static int TcpDoChoConnect(pTcpDoCho self){ status = initRS232(self->controller); if(status != 1){ - self->lastError = status; - return 0; + self->lastError = status; + return 0; } setRS232Timeout(self->controller,5); @@ -297,36 +297,36 @@ static int TcpDoChoConnect(pTcpDoCho self){ snprintf(buffer,255,"user:%s\r\n",self->user); sendLen = strlen(buffer); if(sendLen == 0){ - self->lastError = BADCONVERSION; + self->lastError = BADCONVERSION; return 0; } status = send(self->controller->pSock->sockid,buffer,sendLen,0); if(status < 0){ - self->lastError = BADSEND; - return 0; - } - readLen = 255; - readRS232(self->controller,(void *)buffer,&readLen); - - /* - password - */ - snprintf(buffer,255,"password:%s\r\n",self->pword); - sendLen = strlen(buffer); - if(sendLen == 0){ - self->lastError = BADCONVERSION; + self->lastError = BADSEND; return 0; } - status = send(self->controller->pSock->sockid,buffer,sendLen,0); - if(status < 0){ - self->lastError = BADSEND; - return 0; - } readLen = 255; readRS232(self->controller,(void *)buffer,&readLen); /* - TODO: responses should be checked to test for a valid login. + password + */ + snprintf(buffer,255,"password:%s\r\n",self->pword); + sendLen = strlen(buffer); + if(sendLen == 0){ + self->lastError = BADCONVERSION; + return 0; + } + status = send(self->controller->pSock->sockid,buffer,sendLen,0); + if(status < 0){ + self->lastError = BADSEND; + return 0; + } + readLen = 255; + readRS232(self->controller,(void *)buffer,&readLen); + + /* + TODO: responses should be checked to test for a valid login. I do not know at this time how the controller reacts upon a bad login. */ @@ -348,32 +348,32 @@ static int TcpChopperTask(void *pData){ assert(pPriv); if(pPriv->stop == 1){ - return 0; + return 0; } - + if(time(NULL) > pPriv->nextRefresh){ - if(pPriv->lastError != 0){ - self->GetError(self,&code,buffer,79); - snprintf(error,511,"WARNING: chopper tries to fix: %s",buffer); - WriteToCommandLog("Chopper-task:>>", error); + if(pPriv->lastError != 0){ + self->GetError(self,&code,buffer,79); + snprintf(error,511,"WARNING: chopper tries to fix: %s",buffer); + WriteToCommandLog("Chopper-task:>>", error); status = self->TryFixIt(self,code); - if(status == CHFAIL){ - pPriv->nextRefresh = time(NULL) + pPriv->iRefreshIntervall; - return 1; - } - } else { - pPriv->busy = 1; - for(i = 0; i < pPriv->numChoppers; i++){ - status = tcpDoChoCommand(pPriv,"STATE ", i+1,NULL); - if(status != 1){ - /* - force error correction - */ - return 1; - } + if(status == CHFAIL){ + pPriv->nextRefresh = time(NULL) + pPriv->iRefreshIntervall; + return 1; } - pPriv->nextRefresh = time(NULL) + pPriv->iRefreshIntervall; - pPriv->busy = 0; + } else { + pPriv->busy = 1; + for(i = 0; i < pPriv->numChoppers; i++){ + status = tcpDoChoCommand(pPriv,"STATE ", i+1,NULL); + if(status != 1){ + /* + force error correction + */ + return 1; + } + } + pPriv->nextRefresh = time(NULL) + pPriv->iRefreshIntervall; + pPriv->busy = 0; } } return 1; @@ -388,13 +388,13 @@ static int TcpDoChoKill(pCodri self){ return 1; if(pPriv->controller != NULL){ - KillRS232(pPriv->controller); + KillRS232(pPriv->controller); } if(pPriv->parameters != NULL){ - DeleteStringDict(pPriv->parameters); + DeleteStringDict(pPriv->parameters); } if(pPriv->config != NULL){ - free(pPriv->config); + free(pPriv->config); } free(pPriv); return 1; @@ -411,11 +411,11 @@ static int TcpDoChoConfigure(pCodri pDriv){ assert(self != NULL); if(self->config != NULL){ - pPtr = self->config; - while( (pPtr = stptok(pPtr,command,79,"\n")) != NULL){ - status = tcpDoChoCommand(self,command,-1,NULL); - if(status != 1){ - return 0; + pPtr = self->config; + while( (pPtr = stptok(pPtr,command,79,"\n")) != NULL){ + status = tcpDoChoCommand(self,command,-1,NULL); + if(status != 1){ + return 0; } } } @@ -429,32 +429,32 @@ static int TcpDoChoInit(pCodri pDriv){ assert(pDriv != NULL); self = (pTcpDoCho)pDriv->pPrivate; assert(self != NULL); - + self->lastError = 0; self->stop = 0; self->nextRefresh = 0; - + status = TcpDoChoConnect(self); if(status != 1){ - return 0; + return 0; } status = TcpDoChoConfigure(pDriv); if(status != 1){ - return 0; + return 0; } #if 0 /* start the update task */ if(self->lTask == 0){ - self->lTask = TaskRegister(pServ->pTasker, - TcpChopperTask, - NULL, - NULL, - pDriv, - 1); + self->lTask = TaskRegister(pServ->pTasker, + TcpChopperTask, + NULL, + NULL, + pDriv, + 1); } #endif - return 1; + return 1; } /*-------------------------------------------------------------------*/ static void waitForBusy(pTcpDoCho self){ @@ -462,11 +462,11 @@ static void waitForBusy(pTcpDoCho self){ endTime = time(NULL) + 10 *60; /* max 10 min */ while(time(NULL) < endTime){ - if(self->busy == 1){ - SicsWait(3); + if(self->busy == 1){ + SicsWait(3); } else { - return; - } + return; + } } WriteToCommandLog("Chopper-task>> ","WARNING: timeout on busy flag, flag forced"); self->busy = 0; @@ -481,8 +481,8 @@ static int TcpDoChoClose(pCodri pDriv){ self->stop = 1; if(self->controller != NULL){ - KillRS232(self->controller); - self->controller = NULL; + KillRS232(self->controller); + self->controller = NULL; } return 1; } @@ -492,20 +492,20 @@ static int dissectName(char *name, char par[80], int *num){ pPtr = strrchr(name,(int)'_'); if(pPtr == NULL){ - return 0; + return 0; } memset(par,0,80*sizeof(char)); strncpy(par,name,pPtr - name); if(sscanf(pPtr+1,"%d",num) != 1){ - return 0; + return 0; } return 1; } /* Use this to coerce speed and phase for choppers 2 and 3 - * into the same coordinate convention as chopper 1. + * into the same coordinate convention as chopper 1. * errno = 0 if successful * on failure errorcode is set in lastError - */ + */ #if 0 static int fixDirection(pTcpDoCho self, int choNum, char *value, int value_len) { double dValue; @@ -523,52 +523,52 @@ static int fixDirection(pTcpDoCho self, int choNum, char *value, int value_len) #endif /*----------------------------------------------------------------------*/ static int TcpDoChoSetPar2(pCodri pDriv, char *parname, char *value){ - + pTcpDoCho self = NULL; int status, choNum; - char par[80], buffer[80], state[80]; + char par[80], buffer[80], state[80]; assert(pDriv != NULL); self = (pTcpDoCho)pDriv->pPrivate; assert(self != NULL); - + /* force status requests right after setting something in order to make the stored status represent the new target values */ if(dissectName(parname,par,&choNum)){ - /* - check for emergency stop - */ - snprintf(buffer,79,"State_%1.1d",choNum); - memset(state,0,80*sizeof(char)); - StringDictGet(self->parameters,buffer,state,79); - if(strstr(state,"E-Stop") != NULL){ - self->lastError = ESTOP; - return 0; + /* + check for emergency stop + */ + snprintf(buffer,79,"State_%1.1d",choNum); + memset(state,0,80*sizeof(char)); + StringDictGet(self->parameters,buffer,state,79); + if(strstr(state,"E-Stop") != NULL){ + self->lastError = ESTOP; + return 0; } - if(strcmp(par,"speed") == 0){ - waitForBusy(self); - status = tcpDoChoCommand(self,"SPEED ",choNum,trim(value)); - tcpDoChoCommand(self,"STATE ",choNum,NULL); - if(status != 1){ - return 0; - } else { - return 1; - } - } else if(strcmp(par,"phase") == 0){ - waitForBusy(self); + if(strcmp(par,"speed") == 0){ + waitForBusy(self); + status = tcpDoChoCommand(self,"SPEED ",choNum,trim(value)); + tcpDoChoCommand(self,"STATE ",choNum,NULL); + if(status != 1){ + return 0; + } else { + return 1; + } + } else if(strcmp(par,"phase") == 0){ + waitForBusy(self); if (errno != 0) return 0; - status = tcpDoChoCommand(self,"PHASE ",choNum,trim(value)); - tcpDoChoCommand(self,"STATE ",choNum,NULL); - if(status != 1){ - return 0; - } else { - return 1; - } + status = tcpDoChoCommand(self,"PHASE ",choNum,trim(value)); + tcpDoChoCommand(self,"STATE ",choNum,NULL); + if(status != 1){ + return 0; + } else { + return 1; + } } } self->lastError = UNDRIVABLE; @@ -576,7 +576,7 @@ static int TcpDoChoSetPar2(pCodri pDriv, char *parname, char *value){ } /*-----------------------------------------------------------------------*/ static int TcpDoChoHalt(pCodri pDriv){ - + pTcpDoCho self = NULL; assert(pDriv != NULL); @@ -589,7 +589,7 @@ static int TcpDoChoHalt(pCodri pDriv){ } /*-----------------------------------------------------------------------*/ static int TcpDoChoSetPar(pCodri pDriv, char *parname, float fValue){ - + pTcpDoCho self = NULL; int choNum; char value[80]; @@ -601,26 +601,26 @@ static int TcpDoChoSetPar(pCodri pDriv, char *parname, float fValue){ assert(self != NULL); if(dissectName(parname,par,&choNum)){ - if(strcmp(par,"speed") == 0){ - snprintf(value,79,"%5.1f", fValue); - return TcpDoChoSetPar2(pDriv,parname,value); - } else if(strcmp(par,"phase") == 0){ - snprintf(value,79,"%6.2f",fValue); - return TcpDoChoSetPar2(pDriv,parname,value); + if(strcmp(par,"speed") == 0){ + snprintf(value,79,"%5.1f", fValue); + return TcpDoChoSetPar2(pDriv,parname,value); + } else if(strcmp(par,"phase") == 0){ + snprintf(value,79,"%6.2f",fValue); + return TcpDoChoSetPar2(pDriv,parname,value); } - } + } if(strcmp(parname,"updateintervall") == 0){ sprintf(value,"%d",(int)fValue); StringDictUpdate(self->parameters,"updateintervall",value); self->iRefreshIntervall = (int)fValue; return 1; } else { - snprintf(value,79,"%f",fValue); - return TcpDoChoSetPar2(pDriv,parname,value); + snprintf(value,79,"%f",fValue); + return TcpDoChoSetPar2(pDriv,parname,value); } } /*---------------------------------------------------------------------*/ -static int TcpDoChoGetPar(pCodri pDriv, char *parname, +static int TcpDoChoGetPar(pCodri pDriv, char *parname, char *pBuffer, int iBuflen){ pTcpDoCho self = NULL; int status = 0, choNum, i, j, ready; @@ -744,12 +744,12 @@ static int TcpDoChoCheckPar(pCodri pDriv, char *parname){ check for flags first */ if(self->busy){ - return HWBusy; + return HWBusy; } if(self->lastError != 0) { - return HWFault; + return HWFault; } - + /* updateintervall is always Idle */ @@ -764,38 +764,38 @@ static int TcpDoChoCheckPar(pCodri pDriv, char *parname){ memset(state,0,80*sizeof(char)); StringDictGet(self->parameters,buffer,state,79); if(strstr(state,"E-Stop") != NULL){ - self->lastError = HWFault; - return 0; + self->lastError = HWFault; + return 0; } - + memset(par,0,80); dissectName(parname,par,&choNum); if(strcmp(par,"speed") == 0){ snprintf(buffer,79,"RSPEED_%1.1d", choNum); - StringDictGet(self->parameters,buffer,csoll,79); - sscanf(csoll,"%f",&soll); + StringDictGet(self->parameters,buffer,csoll,79); + sscanf(csoll,"%f",&soll); snprintf(buffer,79,"ASPEED_%1.1d", choNum); - StringDictGet(self->parameters,buffer,value,79); - sscanf(value,"%f",&val); - delta = ABS(soll - val); - if(delta > SPEEDTOL){ - return HWBusy; - } else { - return HWIdle; - } + StringDictGet(self->parameters,buffer,value,79); + sscanf(value,"%f",&val); + delta = ABS(soll - val); + if(delta > SPEEDTOL){ + return HWBusy; + } else { + return HWIdle; + } } else if(strcmp(par,"phase") == 0){ snprintf(buffer,79,"RPHASE_%1.1d", choNum); - StringDictGet(self->parameters,buffer,csoll,79); - sscanf(value,"%f",&soll); + StringDictGet(self->parameters,buffer,csoll,79); + sscanf(value,"%f",&soll); snprintf(buffer,79,"APHASE_%1.1d", choNum); - StringDictGet(self->parameters,buffer,value,79); - sscanf(value,"%f",&val); - delta = ABS(soll - val); - if(delta > PHASETOL){ - return HWBusy; - } else { - return HWIdle; - } + StringDictGet(self->parameters,buffer,value,79); + sscanf(value,"%f",&val); + delta = ABS(soll - val); + if(delta > PHASETOL){ + return HWBusy; + } else { + return HWIdle; + } } self->lastError = BADPAR; return HWFault; @@ -810,36 +810,36 @@ static int TcpDoChoError(pCodri pDriv, int *iCode, char *pError, int iLen){ *iCode = self->lastError; switch(self->lastError){ - case WRONGMODE: - strncpy(pError,"Chopper in wrong mode",iLen); - break; + case WRONGMODE: + strncpy(pError,"Chopper in wrong mode",iLen); + break; case BADCONVERSION: - strncpy(pError,"Bad ASCII to unicode conversion",iLen); + strncpy(pError,"Bad ASCII to unicode conversion",iLen); break; case FAILEDCOMMAND: - strncpy(pError,"Command not accepted",iLen); + strncpy(pError,"Command not accepted",iLen); break; case BADWRITE: - strncpy(pError,"Failed to write to chopper controller",iLen); + strncpy(pError,"Failed to write to chopper controller",iLen); break; case BADRESPONSE: - strncpy(pError,"Chopper controller send invalid command",iLen); + strncpy(pError,"Chopper controller send invalid command",iLen); break; case UNDRIVABLE: - strncpy(pError,"Parameter cannot be changed",iLen); + strncpy(pError,"Parameter cannot be changed",iLen); break; case BADPAR: - strncpy(pError,"No such parameter",iLen); + strncpy(pError,"No such parameter",iLen); break; case BADVALUE: strncpy(pError,"Invalid parameter value",iLen); break; - case ESTOP: - strncpy(pError,"Emergency stop is engaged",iLen); + case ESTOP: + strncpy(pError,"Emergency stop is engaged",iLen); + break; + default: + getRS232Error(self->lastError,pError,iLen); break; - default: - getRS232Error(self->lastError,pError,iLen); - break; } return 1; } @@ -847,8 +847,8 @@ static int TcpDoChoError(pCodri pDriv, int *iCode, char *pError, int iLen){ static int TcpDoChoFix(pCodri pDriv, int iCode){ pTcpDoCho self = NULL; int status = 0; - - + + assert(pDriv != NULL); self = (pTcpDoCho)pDriv->pPrivate; @@ -856,26 +856,26 @@ static int TcpDoChoFix(pCodri pDriv, int iCode){ self->lastError = 0; switch(iCode){ - case BADCONVERSION: + case BADCONVERSION: case BADRESPONSE: - return CHREDO; - break; + return CHREDO; + break; case WRONGMODE: case FAILEDCOMMAND: case UNDRIVABLE: case BADPAR: case ESTOP: return CHFAIL; - break; + break; default: - closeRS232(self->controller); - status = TcpDoChoConnect(self); - if(status == 1){ - return CHREDO; + closeRS232(self->controller); + status = TcpDoChoConnect(self); + if(status == 1){ + return CHREDO; } else { - return CHFAIL; - } - break; + return CHFAIL; + } + break; } return CHFAIL; } @@ -888,50 +888,54 @@ pCodri MakeTcpDoChoDriver(char *tclArray, SConnection *pCon){ int port, i, count; Tcl_DString pars; char *parnames[] = {"State", - "ASPEED", - "RSPEED", - "APHASE", - "RPHASE", - "AVETO", - "DIR", - "MONIT", - "FLOWR", - "WTEMP", - "MTEMP", - "MVIBR", - "MVACU", - "speed", - "phase", - NULL, + "ASPEED", + "RSPEED", + "APHASE", + "RPHASE", + "AVETO", + "DIR", + "MONIT", + "FLOWR", + "WTEMP", + "MTEMP", + "MVIBR", + "MVACU", + "speed", + "phase", + NULL, }; /* allocate memory */ pNew = (pCodri)malloc(sizeof(Codri)); + if(!pNew){ + return NULL; + } self = (pTcpDoCho)malloc(sizeof(TcpDoCho)); - if(!pNew || !self){ + if(!self){ + free(pNew); return NULL; } memset(pNew,0,sizeof(Codri)); memset(self,0,sizeof(TcpDoCho)); - + /* port and host name */ pPtr = Tcl_GetVar2(pServ->pSics->pTcl,tclArray,"port",TCL_GLOBAL_ONLY); if(!pPtr){ - SCWrite(pCon,"ERROR: port not found in configuration array for TCP Dornier Chopper", - eError); + SCWrite(pCon,"ERROR: port not found in configuration array for TCP Dornier Chopper", + eError); free(pNew); - free(self); + free(self); return NULL; } sscanf(pPtr,"%d",&port); pPtr = Tcl_GetVar2(pServ->pSics->pTcl,tclArray,"host",TCL_GLOBAL_ONLY); if(!pPtr){ - SCWrite(pCon,"ERROR: host not found in configuration array for TCP Dornier Chopper", - eError); + SCWrite(pCon,"ERROR: host not found in configuration array for TCP Dornier Chopper", + eError); free(pNew); - free(self); + free(self); return NULL; } memset(buffer,0,132); @@ -941,27 +945,28 @@ pCodri MakeTcpDoChoDriver(char *tclArray, SConnection *pCon){ /* number of choppers */ pPtr = Tcl_GetVar2(pServ->pSics->pTcl,tclArray,"nchopper",TCL_GLOBAL_ONLY); if(!pPtr){ - SCWrite(pCon,"ERROR: nchopper not found in configuration array for TCP Dornier Chopper", - eError); + SCWrite(pCon,"ERROR: nchopper not found in configuration array for TCP Dornier Chopper", + eError); free(pNew); - free(self); + free(self); return NULL; } sscanf(pPtr,"%d",&port); if(port < 0 || port > 8){ - SCWrite(pCon,"ERROR: number of choppers not in range 1 - 8",eError); + SCWrite(pCon,"ERROR: number of choppers not in range 1 - 8",eError); free(pNew); - free(self); + free(self); + return NULL; } self->numChoppers = port; /* timeout */ pPtr = Tcl_GetVar2(pServ->pSics->pTcl,tclArray,"timeout",TCL_GLOBAL_ONLY); if(!pPtr){ - SCWrite(pCon,"ERROR: timeout not found in configuration array for TCP Dornier Chopper", - eError); + SCWrite(pCon,"ERROR: timeout not found in configuration array for TCP Dornier Chopper", + eError); free(pNew); - free(self); + free(self); return NULL; } sscanf(pPtr,"%d",&port); @@ -970,19 +975,19 @@ pCodri MakeTcpDoChoDriver(char *tclArray, SConnection *pCon){ /* username and password */ pPtr = Tcl_GetVar2(pServ->pSics->pTcl,tclArray,"user",TCL_GLOBAL_ONLY); if(!pPtr){ - SCWrite(pCon,"ERROR: user not found in configuration array for TCP Dornier Chopper", - eError); + SCWrite(pCon,"ERROR: user not found in configuration array for TCP Dornier Chopper", + eError); free(pNew); - free(self); + free(self); return NULL; } strncpy(self->user,pPtr, 131); pPtr = Tcl_GetVar2(pServ->pSics->pTcl,tclArray,"password",TCL_GLOBAL_ONLY); if(!pPtr){ - SCWrite(pCon,"ERROR: password not found in configuration array for TCP Dornier Chopper", - eError); + SCWrite(pCon,"ERROR: password not found in configuration array for TCP Dornier Chopper", + eError); free(pNew); - free(self); + free(self); return NULL; } strncpy(self->pword,pPtr, 131); @@ -992,16 +997,16 @@ pCodri MakeTcpDoChoDriver(char *tclArray, SConnection *pCon){ */ pPtr = Tcl_GetVar2(pServ->pSics->pTcl,tclArray,"config",TCL_GLOBAL_ONLY); if(pPtr != NULL){ - self->config = strdup(pPtr); + self->config = strdup(pPtr); } /* initialize some more */ self->parameters = CreateStringDict(); if(self->parameters == NULL || self->controller == NULL){ - SCWrite(pCon,"ERROR: out of memory in MakeTcpDoCho",eError); + SCWrite(pCon,"ERROR: out of memory in MakeTcpDoCho",eError); free(pNew); - free(self); + free(self); return NULL; } self->iRefreshIntervall = 60; @@ -1025,11 +1030,11 @@ pCodri MakeTcpDoChoDriver(char *tclArray, SConnection *pCon){ count = 0; Tcl_DStringAppend(&pars,"updateintervall",15); while(parnames[count] != NULL){ - for(i = 0; i < self->numChoppers; i++){ - snprintf(buffer,131,",%s_%1.1d", parnames[count], i + 1); - Tcl_DStringAppend(&pars,buffer,strlen(buffer)); + for(i = 0; i < self->numChoppers; i++){ + snprintf(buffer,131,",%s_%1.1d", parnames[count], i + 1); + Tcl_DStringAppend(&pars,buffer,strlen(buffer)); } - count++; + count++; } pNew->pParList = strdup(Tcl_DStringValue(&pars)); Tcl_DStringFree(&pars); diff --git a/site_ansto/hardsup/sct_asyncqueue.c b/site_ansto/hardsup/sct_asyncqueue.c index 1dcfae9f..78f4eb35 100644 --- a/site_ansto/hardsup/sct_asyncqueue.c +++ b/site_ansto/hardsup/sct_asyncqueue.c @@ -191,7 +191,11 @@ static int scaqaProtHandler(Ascon *a) return 0; } if (pp->txn.transWait < 0) { - a->state = AsconTimeout; + if (GetDynStringLength(a->rdBuffer) == 0) { + a->state = AsconTimeout; + } else { + a->state = AsconReadDone; + } } else if (pp->txn.transWait == 0) { a->state = AsconReadDone; } diff --git a/site_ansto/hardsup/sinqhttpprot.c b/site_ansto/hardsup/sinqhttpprot.c index 8490ff0c..87e887aa 100644 --- a/site_ansto/hardsup/sinqhttpprot.c +++ b/site_ansto/hardsup/sinqhttpprot.c @@ -203,19 +203,21 @@ static int HttpProtInit(Ascon *a, SConnection *con, int argc, char *argv[]){ pHttpProt pHttp = NULL; + if(argc < 3){ + SCWrite(con,"ERROR: too few arguments in HttpProtInit", eError); + return 0; + } pHttp = calloc(sizeof(HttpProt), 1); if(pHttp == NULL){ SCWrite(con,"ERROR: out of memory in HttpProtInit", eError); return 0; } - if(argc < 3){ - return 0; - } a->hostport = strdup(argv[1]); pHttp->binData = (pSICSData)FindCommandData(pServ->pSics, argv[2], "SICSData"); if(pHttp->binData == NULL){ - SCWrite(con,"ERROR: SICSData objct not found", eError); + SCWrite(con,"ERROR: SICSData object not found", eError); + free(pHttp); return 0; } if(argc > 3){ diff --git a/site_ansto/hardsup/west4100util.c b/site_ansto/hardsup/west4100util.c index a6dde8dd..10a2d2a6 100644 --- a/site_ansto/hardsup/west4100util.c +++ b/site_ansto/hardsup/west4100util.c @@ -346,7 +346,7 @@ /*--------------------------------------------------------------------------*/ int WEST4100_Query(pWEST4100 *pData, int parAddress, int *parValue) { - unsigned char pCommand[20], pReply[132], pAddress[1]; + unsigned char pCommand[20], pReply[132], pAddress[2]; int iRet; pWEST4100 self; @@ -374,7 +374,7 @@ /* -------------------------------------------------------------------------*/ int WEST4100_Write(pWEST4100 *pData, int parAddress, int parValue) { - unsigned char displaytext[20]; + unsigned char displaytext[40]; int iRet; pWEST4100 self; diff --git a/site_ansto/instrument/TEST_SICS/fakeGalil/SIM_GALIL.py b/site_ansto/instrument/TEST_SICS/fakeGalil/SIM_GALIL.py index 1bac84de..a5615c70 100755 --- a/site_ansto/instrument/TEST_SICS/fakeGalil/SIM_GALIL.py +++ b/site_ansto/instrument/TEST_SICS/fakeGalil/SIM_GALIL.py @@ -77,8 +77,9 @@ class MyScreen(Screen): def main(**kwargs): global screen, devices, factories - parser = argparse.ArgumentParser( description="Generates fake Galil controllers for testing SICS" ) - parser.add_argument("instrument", help="The instrument name") + parser = argparse.ArgumentParser( description='Generates fake Galil controllers for testing SICS' ) + parser.add_argument('instrument', help='The instrument name') + parser.add_argument('-w', '--window', help='Create a display window', action='store_true', default=False) args = parser.parse_args() basePort = { @@ -89,7 +90,7 @@ def main(**kwargs): log.startLogging(open(("/tmp/Fake_Galil_%d.log" % basePort[args.instrument]), "w")) devices = {} factories = {} - for dev in range(0, 6): + for dev in range(0, 8): port = basePort[args.instrument] + dev controllerName = "mc%d" % (dev + 1) factory = GalilFactory(port) @@ -97,9 +98,10 @@ def main(**kwargs): factories[controllerName] = factory reactor.listenTCP(port, factory) - stdscr = curses.initscr() - screen = MyScreen(stdscr) - reactor.addReader(screen) + if (args.window): + stdscr = curses.initscr() + screen = MyScreen(stdscr) + reactor.addReader(screen) #lc = LoopingCall(device_iterator) #lc.start(0.5) diff --git a/site_ansto/instrument/TEST_SICS/fakeRFGen/SIM_RFGen.tcl b/site_ansto/instrument/TEST_SICS/fakeRFGen/SIM_RFGen.tcl old mode 100644 new mode 100755 index 86180a99..8564a287 --- a/site_ansto/instrument/TEST_SICS/fakeRFGen/SIM_RFGen.tcl +++ b/site_ansto/instrument/TEST_SICS/fakeRFGen/SIM_RFGen.tcl @@ -1,3 +1,4 @@ +#!/usr//bin/env tclsh # $Revision: 1.1.2.5 $ # $Date: 2010-05-20 00:51:15 $ # Author: Ferdi Franceschini (ffr@ansto.gov.au) diff --git a/site_ansto/instrument/bilby/MANIFEST.TXT b/site_ansto/instrument/bilby/MANIFEST.TXT new file mode 100644 index 00000000..06aa801e --- /dev/null +++ b/site_ansto/instrument/bilby/MANIFEST.TXT @@ -0,0 +1,6 @@ +runsics_def.py +bilby_configuration.tcl +config +util +hostport_config.tcl +hostport_config_test.tcl diff --git a/site_ansto/instrument/bilby/bilby_configuration.tcl b/site_ansto/instrument/bilby/bilby_configuration.tcl new file mode 100644 index 00000000..a96cbd51 --- /dev/null +++ b/site_ansto/instrument/bilby/bilby_configuration.tcl @@ -0,0 +1,63 @@ +# Author: Ferdi Franceschini (ffr@ansto.gov.au) + +# Required by server_config.tcl +VarMake Instrument Text Internal +Instrument bilby +Instrument lock + +#START SERVER CONFIGURATION SECTION +source util/dmc2280/dmc2280_util.tcl +source server_config.tcl +MakeDrive +#END SERVER CONFIGURATION SECTION + +######################################## +# INSTRUMENT SPECIFIC CONFIGURATION + +fileeval $cfPath(motors)/motor_configuration.tcl + + +fileeval $cfPath(source)/source.tcl +source $cfPath(hipadaba)/hipadaba_configuration.tcl +fileeval $cfPath(motors)/positmotor_configuration.tcl +fileeval $cfPath(velsel)/velsel.tcl +fileeval $cfPath(parameters)/parameters.tcl +fileeval $cfPath(plc)/plc.tcl +fileeval $cfPath(chopper)/chopper.tcl +fileeval $cfPath(optics)/optics.tcl +fileeval $cfPath(counter)/counter.tcl +fileeval $cfPath(environment)/temperature/sct_lakeshore_340.tcl +fileeval $cfPath(environment)/temperature/sct_lakeshore_336.tcl +fileeval $cfPath(hmm)/hmm_configuration.tcl +fileeval $cfPath(nexus)/nxscripts.tcl +fileeval $cfPath(hmm)/detector.tcl +fileeval $cfPath(scan)/scan.tcl +fileeval $cfPath(commands)/commands.tcl +fileeval $cfPath(anticollider)/anticollider.tcl +fileeval $cfPath(environment)/temperature/sct_julabo_lh45.tcl +fileeval $cfPath(environment)/temperature/sct_qlink.tcl +fileeval $cfPath(environment)/temperature/sct_watlow_st4.tcl +fileeval $cfPath(environment)/temperature/sct_watlow_rm.tcl +fileeval $cfPath(environment)/temperature/sct_rvasm2.tcl +fileeval $cfPath(environment)/temperature/sct_oxford_itc.tcl +fileeval $cfPath(environment)/magneticField/oxford_labview.tcl +fileeval $cfPath(environment)/magneticField/sct_bruker_BEC1.tcl +fileeval $cfPath(environment)/environment.tcl +fileeval $cfPath(environment)/sct_rheometer.tcl +fileeval $cfPath(environment)/sct_protek_common.tcl +fileeval $cfPath(beamline)/spin_flipper.tcl +fileeval $cfPath(commands)/pulser.tcl +fileeval $cfPath(commands)/hvcommands.tcl + +source gumxml.tcl + +::utility::mkVar ::anticollider::protect_detector text manager protect_detector false detector true false +::anticollider::protect_detector "true" + +server_init +########################################### +# WARNING: Do not add any code below server_init, if you do SICS may fail to initialise properly. + +# You can add extra-configuration code in ../extraconfig.tcl +sicspoll intervall /instrument/detector/max_binrate 1 +sicspoll intervall /instrument/detector/total_maprate 1 diff --git a/site_ansto/instrument/bilby/config/INSTCFCOMMON.TXT b/site_ansto/instrument/bilby/config/INSTCFCOMMON.TXT new file mode 100644 index 00000000..0f1607f8 --- /dev/null +++ b/site_ansto/instrument/bilby/config/INSTCFCOMMON.TXT @@ -0,0 +1,32 @@ +config/source/sct_reactor_status.tcl +config/source/source.tcl +config/anticollider/anticollider_common.tcl +config/plc/plc_common_1.tcl +config/counter/counter_common_1.tcl +config/hipadaba/hipadaba_configuration_common.tcl +config/hipadaba/common_instrument_dictionary.tcl +config/hipadaba/instdict_specification.tcl +config/hmm/hmm_configuration_common_1.tcl +config/hmm/hmm_object.tcl +config/hmm/anstohm_linked.xml +config/hmm/sct_orhvps_common.tcl +config/scan/scan_common_1.hdd +config/scan/scan_common_1.tcl +config/nexus/nxscripts_common_1.tcl +config/commands/commands_common.tcl +config/commands/pulser.tcl +config/commands/hvcommands.tcl +config/motors/sct_positmotor_common.tcl +config/environment/sct_protek_common.tcl +config/environment/temperature/sct_julabo_lh45.tcl +config/environment/temperature/sct_lakeshore_340.tcl +config/environment/temperature/sct_lakeshore_336.tcl +config/environment/temperature/sct_qlink.tcl +config/environment/temperature/sct_watlow_st4.tcl +config/environment/temperature/sct_rvasm2.tcl +config/environment/temperature/sct_oxford_itc.tcl +config/environment/magneticField/sct_bruker_BEC1.tcl +config/environment/magneticField/sct_oxford_ips.tcl +config/environment/magneticField/sct_oxford_labview.tcl + +config/motors/sct_jogmotor_common.tcl diff --git a/site_ansto/instrument/bilby/config/anticollider/acscript.txt b/site_ansto/instrument/bilby/config/anticollider/acscript.txt new file mode 100644 index 00000000..e69de29b diff --git a/site_ansto/instrument/bilby/config/anticollider/anticollider.tcl b/site_ansto/instrument/bilby/config/anticollider/anticollider.tcl new file mode 100644 index 00000000..aad90bb9 --- /dev/null +++ b/site_ansto/instrument/bilby/config/anticollider/anticollider.tcl @@ -0,0 +1,128 @@ +# Author: Ferdi Franceschini (ffr@ansto.gov.au) + +fileeval $cfPath(anticollider)/anticollider_common.tcl + +namespace eval ::anticollider { + set guide_posit 1 + set aperture_posit 2 + set apD10_posit 1 + set coltol 0.5 + set aptol 0.1 + + for {set n 1} {$n < 8} {incr n} { + foreach {col ap} "col$n ap$n" { + set col_limit [expr [SplitReply [$col posit2unit $aperture_posit]] - $coltol] + set ap_limit [expr [SplitReply [$ap posit2unit $apD10_posit]] - $aptol] + set acrule [subst {forbid {-inf inf} for $ap when $col in {-inf $col_limit} }] + lappend ::anticollider::veto_rules $acrule + set acrule [subst {forbid {-inf inf} for $col when $ap in {$ap_limit inf} }] + lappend ::anticollider::veto_rules $acrule + anticollision register $col + anticollision register $ap + } + } + + proc ::anticollider::load_acrules {} { + variable proximity_rules + # Proximity rules have the following form, + # m1 m2 mdist + # This means that the position of m2 is always >= m1 and that a drive or + # run command which tries to drive them closer than mdist will be rejected. + # TODO Abort driving motors registered with the anticollider if one of them + # fails during the drive. +# TESTING WITH SLITS, uncomment this block and the foreach block to test with slits +# set proximity_rules { +# ss1l ss1r 10 +# } + # TODO UNCOMMENT FOLLOWING TO ENABLE ANTICOLLISION FOR DETECTOR CARRIAGES + # # Detector carriage proximity rules. + # # det1 = curtain detector + # # det2 = main detector which is at higher y-pos then det1 + # set proximity_rules { + # det1 det2 2000 + # } + # foreach {m1 m2 minsep} $proximity_rules { + # anticollision register $m1 + # anticollision register $m2 + # clientput "::anticollider::proximity_rule: $m1 $m2 minsep = $minsep" + # } + } + + # @brief Don't allow two axes to get closer than a minimum separation given in the 'proximity_rules' list. + # Assumes that both objects are on the same open track + # Both axes are required to move at the same speed with the same accel and decel values. + # NOTE: Doesn't check that the speeds and accel set by the Galil match what is requested. + # If axes are within the minimum distance then you can only drive them + # apart when the targets are greater than the minimum allowed separation. + proc proximity_script {args} { + set catch_status [ catch { + variable proximity_rules + + if {[info exists proximity_rules] == 0} { + return + } elseif {[len $proximity_rules] == 0} { + return + } + foreach {m1 m2 mdist} $proximity_rules { + set final($m1) [SplitReply [$m1]] + set final($m2) [SplitReply [$m2]] + } + foreach {mot val} $args { + set final($mot) $val + } + foreach {mot val} $args { + set rulenum 1 + foreach {m1 m2 mdist} $proximity_rules { + if {$m1 != $mot && $m2 != $mot} { + continue + } + if {$mdist <=0} { + error "Minimum separation for $m1 and $m2 must be > 0 in proximity_rule $rulenum" + } + set speed($m1) [SplitReply [$m1 speed]] + set accel($m1) [SplitReply [$m1 accel]] + set decel($m1) [SplitReply [$m1 decel]] + set pos($m1) [SplitReply [$m1]] + + set speed($m2) [SplitReply [$m2 speed]] + set accel($m2) [SplitReply [$m2 accel]] + set decel($m2) [SplitReply [$m2 decel]] + set pos($m2) [SplitReply [$m2]] + # NOTE Speed and accel tests assume that the Galil actually sets the + # speeds and accelerations to the same expected steps after taking gear + # ratios, transmission, (something else?) into account on both axes + # when we drive the motors. + if {$speed($m1) != $speed($m2)} { + error "$m1 and $m2 speeds must be equal to ensure they won't collide" + } + if {$accel($m1) != $accel($m2)} { + error "$m1 and $m2 accelerations must be equal to ensure they won't collide" + } + if {$decel($m1) != $decel($m2)} { + error "$m1 and $m2 decelerations must be equal to ensure they won't collide" + } + if {$pos($m2) - $pos($m1) < 0} { + error "Rule($rulenum): $m1 $m2 $mdist seems to be invalid. It assumes that $m2 pos is always >= $m1 pos but $m1 is at $pos($m1) and $m2 is at $pos($m2)" + } + if {$final($m2) - $final($m1) < $mdist} { + error "$m1 and $m2 will violate rule:$rulenum, the minimum allowed separation is positive $mdist" + } + incr rulenum + } + } + } message ] + handle_exception $catch_status $message + } + lappend ::anticollider::scripts ::anticollider::proximity_script +} + +# NOTE: This is called with a list of motorname target pairs +proc ::anticollider::enable {args} { + if {[SplitReply [::anticollider::protect_detector]] == "false"} { + return "false" + } else { + return "true" + } +} + +::anticollider::loadscript acscript.txt diff --git a/site_ansto/instrument/bilby/config/chopper/chopper.tcl b/site_ansto/instrument/bilby/config/chopper/chopper.tcl new file mode 100644 index 00000000..54cdfa05 --- /dev/null +++ b/site_ansto/instrument/bilby/config/chopper/chopper.tcl @@ -0,0 +1,34 @@ + +namespace eval chopper { + variable sim_mode [SplitReply [chopper_simulation]] + set master_chopper_id_simvar 1 +} + +if {$sim_mode == false} { + MakeAsyncProtocol std + MakeAsyncQueue chopsel std chopsel1-bilby 30000 +} +::utility::macro::getset int master_chopper_id {args} { + variable sim_mode [SplitReply [chopper_simulation]] + + if {$sim_mode == false} { + if {$args == ""} { + chopsel send {get master chopper} + return "master_chopper_id = [SplitReply [chopsel send {get master chopper}]]" + } else { + chopsel send "get master chopper" + chopsel send "enable chopper selection" + chopsel send "set master chopper=$args" + chopsel send "disable chopper selection" + } + } else { + if {$args == ""} { + return master_chopper_id = $::chopper::master_chopper_id_simvar + } else { + set ::chopper::master_chopper_id_simvar $args + } + } +} +sicslist setatt master_chopper_id klass NXdisk_chopper +sicslist setatt master_chopper_id long_name master_chopper_id +sicslist setatt master_chopper_id mutable false diff --git a/site_ansto/instrument/bilby/config/commands/commands.tcl b/site_ansto/instrument/bilby/config/commands/commands.tcl new file mode 100644 index 00000000..f6a0a1cc --- /dev/null +++ b/site_ansto/instrument/bilby/config/commands/commands.tcl @@ -0,0 +1,216 @@ +source $cfPath(commands)/commands_common.tcl + +namespace eval motor { +# is_homing_list = comma separated list of motors which are safe to send "home" + variable is_homing_list "" +} + +#namespace eval sample { +# command select {int=0:8 sampid} { +# SampleNum $sampid +# } +#} + +## +# @brief Beamstop select command +# @param bs beamstop, 1,2,3,4,5 or 6 +# @param bx beam position in detector coordinates +# @param bz beam position in detector coordinates +# Given +# (Xbf,Zbf) = beam pos in frame coords +# (Xbd,Zbd) = beam pos in detector coords +# (Xbbs, Zbbs) = beam pos in beamstop coords +# (Xdf,Zdf) = detector pos in frame coords +# (Xbsf,Zbsf) = beamstop pos in frame coords +# +# (Xbf,Zbf) = (Xdf+Xbd, Zdf+Zbd) = (Xbsf+Xbbs, Zbsf+Zbbs) +# Origin of detector coords = frame origin +# +# Detector and beamstop motor readings with beamstop disk centers +# overlapping over detector center mark. +# Xdf = 264.542 (7283813) Zdf = 0 +# Xbbs = 296.291 (8054270) +# Zbbs = 259.641 (13488244) +# Xbd = dethw, Zbd = (dethh) +# +# 264.542+dethw = Xbsf+296.291 +# 0+dethh = Zbsf+259.641 +# +# Xbsf = -31.749 + dethw, Zbsf = -259.641 + dethh +proc selbs {bs {bx "UNDEF"} {bz "UNDEF"}} { + set bsdriving false + set dethw [expr {[SplitReply [detector_active_height_mm]]/2.0}] + set dethh [expr {[SplitReply [detector_active_width_mm]]/2.0}] + set Xbsf [expr -31.749 + $dethw] + set Zbsf [expr -259.641 + $dethh] + array set bsl [subst { + 1 [SplitReply [bs1 softlowerlim]] + 2 [SplitReply [bs2 softlowerlim]] + 3 [SplitReply [bs3 softlowerlim]] + 4 [SplitReply [bs4 softlowerlim]] + 5 [SplitReply [bs5 softlowerlim]] + 6 [SplitReply [bs6 softlowerlim]] + }] + if [ catch { + switch $bs { + "1" { + set bsmot "bs1" + set bs_target 93.20 + set bs_diameter 110 + set bsdownCmd "drive bs2 $bsl(2) bs3 $bsl(3) bs4 $bsl(4) bs5 $bsl(5) bs6 $bsl(6)" + } + "2" { + set bsmot "bs2" + set bs_target 86.84 + set bs_diameter 88 + set bsdownCmd "drive bs1 $bsl(1) bs3 $bsl(3) bs4 $bsl(4) bs5 $bsl(5) bs6 $bsl(6)" + } + "3" { + set bsmot "bs3" + set bs_target 93.35 + set bs_diameter 66 + set bsdownCmd "drive bs2 $bsl(2) bs1 $bsl(1) bs4 $bsl(4) bs5 $bsl(5) bs6 $bsl(6)" + } + "4" { + set bsmot "bs4" + set bs_target 86.85 + set bs_diameter 44 + set bsdownCmd "drive bs2 $bsl(2) bs3 $bsl(3) bs1 $bsl(1) bs5 $bsl(5) bs6 $bsl(6)" + } + "5" { + set bsmot "bs5" + set bs_target 93.27 + set bs_diameter 22 + set bsdownCmd "drive bs2 $bsl(2) bs3 $bsl(3) bs4 $bsl(4) bs1 $bsl(1) bs6 $bsl(6)" + } + "6" { + set bsmot "bs6" + set bs_target 86.98 + set bs_diameter 11 + set bsdownCmd "drive bs2 $bsl(2) bs3 $bsl(3) bs4 $bsl(4) bs5 $bsl(5) bs1 $bsl(1)" + } + default { + error "beamstop selection must be an integer from 1 to 6" + } + } + + set detoff_val [SplitReply [detoff]] + + if {$bx == "UNDEF" || $bz == "UNDEF"} { + statemon start selbs + if {[info level] > 1} {statemon start [lindex [info level -1] 0]} + set bsdriving true + BeamStop -1 + BSdiam -1 + drive $bsmot $bs_target + eval $bsdownCmd + BeamStop $bs + BSdiam $bs_diameter + set bsdriving false + statemon stop selbs + if {[info level] > 1} {statemon stop [lindex [info level -1] 0]} + } else { + if { [string is double $bx] == false } { + if { [string is double $bz] == false } { + error "beam coordinates must be floats" + } + } + set bsx_target [expr {$bx-$Xbsf+$detoff_val}] + set bsz_target [expr {$bz-$Zbsf}] + + statemon start selbs + if {[info level] > 1} {statemon start [lindex [info level -1] 0]} + set bsdriving true + BeamStop -1 + BSdiam -1 + drive $bsmot $bs_target bsx $bsx_target bsz $bsz_target + eval $bsdownCmd + BeamStop $bs + BSdiam $bs_diameter + set bsdriving false + statemon stop selbs + if {[info level] > 1} {statemon stop [lindex [info level -1] 0]} + } + } msg ] { + if {$bsdriving} { + statemon stop selbs + if {[info level] > 1} {statemon stop [lindex [info level -1] 0]} + } + return -code error $msg + } +} +publish selbs user +namespace eval beamstops { + command selbsn {int=1,2,3,4,5,6 bs} { + selbs $bs "UNDEF" "UNDEF" + } + command selbsxz {int=1,2,3,4,5,6 bs float bx float bz} { + selbs $bs $bx $bz + } +} + +namespace eval optics { + VarMake ::optics::select::section text user + VarMake ::optics::polarizer::in text user + VarMake ::optics::lens::selection text user + + command rotary_attenuator {int=0,15,45,90,180 angle} { + drive att $angle + } + + command entrance_aperture { + int=0,45,90,135,180,270 angle + } { + drive srce $angle + } + +# TODO Do we need this +# command sample_aperture { +# int=25,50 size +# text=circ,squ,open,rect shape +# } { +# SApXmm $size +# SApZmm $size +# SApShape $shape +# } + +############################## +## +# @brief The "guide" command uses a lookup table to setup the collimation system +# @param row, selects a row from the guide configuration table +# +# eg\n +# guide ga + command guide " + text=[join [array names ::optics::guide_configuration] , ] configuration + " { + + variable guide_configuration + variable guide_configuration_columns + + if [ catch { + + foreach {compselection position} $guide_configuration($configuration) { + foreach el $compselection guide $guide_configuration_columns { + lappend to_config $guide + lappend to_config [set ::optics::${guide}_map($el)] + } + ::optics::guide -set feedback status BUSY + set msg [eval "drive $to_config"] + EApPosY $position + } + GuideConfig $configuration + } message ] { + ::optics::guide -set feedback status IDLE + if {$::errorCode=="NONE"} {return $message} + return -code error $message + } + ::optics::guide -set feedback status IDLE + } + ::optics::guide -addfb text status + ::optics::guide -set feedback status IDLE +} + +proc ::commands::isc_initialize {} { + ::commands::ic_initialize +} diff --git a/site_ansto/instrument/bilby/config/counter/counter.tcl b/site_ansto/instrument/bilby/config/counter/counter.tcl new file mode 100644 index 00000000..4f7e802b --- /dev/null +++ b/site_ansto/instrument/bilby/config/counter/counter.tcl @@ -0,0 +1,32 @@ +source $cfPath(counter)/counter_common_1.tcl + +## TODO Put all the counter macros in the counter namespace +namespace eval counter { + variable isc_numchannels + variable isc_monitor_address + variable isc_portlist + variable isc_beam_monitor_list + proc set_sobj_attributes {} { + } +} + +proc ::counter::isc_initialize {} { + if [catch { + variable isc_numchannels + variable isc_monitor_address + variable isc_portlist + + dict for {k v} $::MONITOR_HOSTPORT { + lappend monlist $k + lappend hostlist [dict get $v HOST] + lappend isc_portlist [dict get $v PORT] + } + variable isc_beam_monitor_list $monlist + set isc_monitor_address [lindex $hostlist 0] + set isc_numchannels [llength $isc_beam_monitor_list] + ::counter::ic_initialize + } message ] { + if {$::errorCode=="NONE"} {return $message} + return -code error "$message" + } +} diff --git a/site_ansto/instrument/bilby/config/hipadaba/hipadaba_configuration.tcl b/site_ansto/instrument/bilby/config/hipadaba/hipadaba_configuration.tcl new file mode 100644 index 00000000..3aaa4d83 --- /dev/null +++ b/site_ansto/instrument/bilby/config/hipadaba/hipadaba_configuration.tcl @@ -0,0 +1 @@ +source $cfPath(hipadaba)/hipadaba_configuration_common.tcl diff --git a/site_ansto/instrument/bilby/config/hmm/hmm_configuration.tcl b/site_ansto/instrument/bilby/config/hmm/hmm_configuration.tcl new file mode 100644 index 00000000..42d6507e --- /dev/null +++ b/site_ansto/instrument/bilby/config/hmm/hmm_configuration.tcl @@ -0,0 +1,70 @@ + +fileeval $cfPath(hmm)/hmm_configuration_common_1.tcl +set sim_mode [SplitReply [hmm_simulation]] + +proc ::histogram_memory::init_OAT_TABLE {} { + if [ catch { + # We don't need a MAX_CHAN parameter for time because the time channel + # is scaled by calling the ::histogram_memory::clock_scale function + OAT_TABLE X -setdata MAX_CHAN 240 + OAT_TABLE Y -setdata MAX_CHAN 256 + OAT_TABLE X -setdata BMIN -0.5 + OAT_TABLE X -setdata BMAX 239.5 + OAT_TABLE Y -setdata BMIN -0.5 + OAT_TABLE Y -setdata BMAX 255.5 + + set clock_scale 1000 + set freq 50 + hmm configure fat_clock_scale $clock_scale + hmm configure fat_frame_frequency $freq + hmm configure fat_frame_source INTERNAL + + OAT_TABLE -set X { 239.5 238.5 } NXC 240 Y { -0.5 0.5 } NYC 256 T { 0 20000 } NTC 1 + } message ] { + return -code error $message + } +} +proc ::histogram_memory::pre_count {} {} +proc ::histogram_memory::post_count {} {} +proc ::histogram_memory::isc_initialize {} { + # Instrument specific X and Y dimension names + variable INST_NXC "oat_nxc_eff" + variable INST_NYC "oat_nyc_eff" + + if [ catch { + ::histogram_memory::init_hmm_objs + if {$::sim_mode == "true"} { + hmm configure oat_ntc_eff 1 + hmm configure $INST_NYC 256 + hmm configure $INST_NXC 240 + } + BAT_TABLE -init + CAT_TABLE -init + SAT_TABLE -init + OAT_TABLE -init + FAT_TABLE -init + ::histogram_memory::ic_initialize + + detector_active_height_mm [expr 5.08 * 256] + detector_active_width_mm [expr 5.08 * 240] + detector_active_height_mm lock + detector_active_width_mm lock + + # hmm configure FAT_SIMULATED_EVENT_Y0 $y_bb0 + # hmm configure FAT_SIMULATED_EVENT_Y1 $ybbmax + # hmm configure FAT_SIMULATED_EVENT_X0 $x_bb0 + # hmm configure FAT_SIMULATED_EVENT_X1 $xbbmax + ::histogram_memory::init_OAT_TABLE + ::histogram_memory::upload_config Filler_defaults + + set ::histogram_memory::histmem_axes(HOR) /instrument/detector/x_pixel_offset + set ::histogram_memory::histmem_axes(VER) /instrument/detector/y_pixel_offset + } message ] { + return -code error $message + } +} + +proc histmem {cmd args} { + eval "_histmem $cmd $args" +} +publish histmem user diff --git a/site_ansto/instrument/bilby/config/motors/Bilby_motion_control_commissioning_checklist.csv b/site_ansto/instrument/bilby/config/motors/Bilby_motion_control_commissioning_checklist.csv new file mode 100755 index 00000000..469e4f8a --- /dev/null +++ b/site_ansto/instrument/bilby/config/motors/Bilby_motion_control_commissioning_checklist.csv @@ -0,0 +1,464 @@ +ap1_100X40,110608 +ap1_40X40,102604 +ap1_axis,A +ap1_axis_number,1 +ap1_cnts_per_x,364.088888888889 +ap1_D10,86208 +ap1_D20,91680 +ap1_D40,97116 +ap1_description,Aperture Selector (Collimator SEG 1 Start) +ap1_dflt_accel_steps,50000 +ap1_dflt_decel_steps,50000 +ap1_dflt_speed_steps,50000 +ap1_fwd_enc_lim,112188 +ap1_maxaccel,2.8125 +ap1_maxdecel,2.8125 +ap1_maxspeed,2.8125 +ap1_mc,mc1 +ap1_rev_enc_lim,73952 +ap1_steps_per_x,35555.5555555556 +ap2_100X40,93637 +ap2_40X40,85637 +ap2_axis,B +ap2_axis_number,2 +ap2_cnts_per_x,364.088888888889 +ap2_D10,69193 +ap2_D20,74677 +ap2_D40,80149 +ap2_description,Aperture Selector (COLLIMATION SEG 2) +ap2_dflt_accel_steps,50000 +ap2_dflt_decel_steps,50000 +ap2_dflt_speed_steps,50000 +ap2_fwd_enc_lim,95461 +ap2_maxaccel,2.8125 +ap2_maxdecel,2.8125 +ap2_maxspeed,2.8125 +ap2_mc,mc1 +ap2_rev_enc_lim,54293 +ap2_steps_per_x,35555.5555555556 +ap3_100X40,49584 +ap3_40X40,41532 +ap3_axis,C +ap3_axis_number,3 +ap3_cnts_per_x,364.088888888889 +ap3_D10,25168 +ap3_D20,30656 +ap3_D40,36080 +ap3_description,Aperture Selector (COLLIMATION SEG 3) +ap3_dflt_accel_steps,50000 +ap3_dflt_decel_steps,50000 +ap3_dflt_speed_steps,50000 +ap3_fwd_enc_lim,51616 +ap3_maxaccel,2.8125 +ap3_maxdecel,2.8125 +ap3_maxspeed,2.8125 +ap3_mc,mc1 +ap3_rev_enc_lim,13644 +ap3_steps_per_x,35555.5555555556 +ap4_100X40,43506 +ap4_40X40,35490 +ap4_axis,D +ap4_axis_number,4 +ap4_cnts_per_x,364.088888888889 +ap4_D10,19118 +ap4_D20,24578 +ap4_D40,30038 +ap4_description,Aperture Selector (COLLIMATION SEG 4) +ap4_dflt_accel_steps,50000 +ap4_dflt_decel_steps,50000 +ap4_dflt_speed_steps,50000 +ap4_fwd_enc_lim,45234 +ap4_maxaccel,2.8125 +ap4_maxdecel,2.8125 +ap4_maxspeed,2.8125 +ap4_mc,mc1 +ap4_rev_enc_lim,5666 +ap4_steps_per_x,35555.5555555556 +ap5_100X40,109480 +ap5_40X40,101476 +ap5_axis,E +ap5_axis_number,5 +ap5_cnts_per_x,364.088888888889 +ap5_D10,85076 +ap5_D20,90552 +ap5_D40,96008 +ap5_description,Aperture Selector (COLLIMATION SEG 5) +ap5_dflt_accel_steps,50000 +ap5_dflt_decel_steps,50000 +ap5_dflt_speed_steps,50000 +ap5_fwd_enc_lim,110696 +ap5_maxaccel,2.8125 +ap5_maxdecel,2.8125 +ap5_maxspeed,2.8125 +ap5_mc,mc1 +ap5_rev_enc_lim,72824 +ap5_steps_per_x,35555.5555555556 +ap6_100X40,110499 +ap6_40X40,102419 +ap6_axis,F +ap6_axis_number,6 +ap6_cnts_per_x,364.088888888889 +ap6_D10,86097 +ap6_D20,91587 +ap6_D40,97011 +ap6_description,Aperture Selector (COLLIMATION SEG 6) +ap6_dflt_accel_steps,50000 +ap6_dflt_decel_steps,50000 +ap6_dflt_speed_steps,50000 +ap6_fwd_enc_lim,112435 +ap6_maxaccel,2.8125 +ap6_maxdecel,2.8125 +ap6_maxspeed,2.8125 +ap6_mc,mc1 +ap6_rev_enc_lim,72115 +ap6_steps_per_x,35555.5555555556 +ap7_100X40,110371 +ap7_40X40,102343 +ap7_axis,G +ap7_axis_number,7 +ap7_cnts_per_x,364.088888888889 +ap7_D10,85929 +ap7_D20,91399 +ap7_D40,96871 +ap7_description,Aperture Selector (COLLIMATION SEG 7) +ap7_dflt_accel_steps,50000 +ap7_dflt_decel_steps,50000 +ap7_dflt_speed_steps,50000 +ap7_fwd_enc_lim,112391 +ap7_maxaccel,2.8125 +ap7_maxdecel,2.8125 +ap7_maxspeed,2.8125 +ap7_mc,mc1 +ap7_rev_enc_lim,74299 +ap7_steps_per_x,35555.5555555556 +ap8_100X40,46069 +ap8_40X40,38027 +ap8_axis,H +ap8_axis_number,8 +ap8_cnts_per_x,364.088888888889 +ap8_D10,21657 +ap8_D20,27115 +ap8_D40,32629 +ap8_description,Aperture Selector (Collimator SEG 8 End) +ap8_dflt_accel_steps,50000 +ap8_dflt_decel_steps,50000 +ap8_dflt_speed_steps,50000 +ap8_fwd_enc_lim,47639 +ap8_maxaccel,2.8125 +ap8_maxdecel,2.8125 +ap8_maxspeed,2.8125 +ap8_mc,mc1 +ap8_rev_enc_lim,6791 +ap8_steps_per_x,35555.5555555556 +att_axis,A +att_axis_number,25 +att_cnts_per_x,-1365.33333333333 +att_description,4 Position linear Attenuator +att_dflt_accel_steps,15000 +att_dflt_decel_steps,15000 +att_dflt_speed_steps,15000 +att_fwd_enc_lim,33394989 +att_maxaccel,3.6 +att_maxdecel,3.6 +att_maxspeed,3.6 +att_mc,mc4 +att_pos1,33373433 +att_pos2,33291514 +att_pos3,33209595 +att_pos4,33127674 +att_pos5,33045750 +att_rev_enc_lim,33021197 +att_steps_per_x,-4166.66666666667 +bs3_axis,C +bs3_axis_number,43 +bs3_cnts_per_x,728.177777777778 +bs3_description,beam stop 3 +bs3_dflt_accel_steps,12500 +bs3_dflt_decel_steps,12500 +bs3_dflt_speed_steps,12500 +bs3_fwd_enc_lim,300855 +bs3_maxaccel,5.625 +bs3_maxdecel,5.625 +bs3_maxspeed,5.625 +bs3_mc,mc6 +bs3_rev_enc_lim,351548 +bs3_steps_per_x,2222.22222222222 +cdd_axis,F +cdd_axis_number,62 +cdd_cnts_per_x,32768 +cdd_description,CURTAIN DETECTOR BOTTOM TRANSLATION +cdd_dflt_accel_steps,25000 +cdd_dflt_decel_steps,25000 +cdd_dflt_speed_steps,150000 +cdd_fwd_enc_lim,15618875 +cdd_maxaccel,8 +cdd_maxdecel,8 +cdd_maxspeed,8 +cdd_mc,mc8 +cdd_rev_enc_lim,4159255 +cdd_steps_per_x,100000 +cdl_axis,C +cdl_axis_number,59 +cdl_cnts_per_x,32768 +cdl_description,CURTAIN DETECTOR WEST TRANSLATION +cdl_dflt_accel_steps,25000 +cdl_dflt_decel_steps,25000 +cdl_dflt_speed_steps,150000 +cdl_fwd_enc_lim,17466632 +cdl_maxaccel,8 +cdl_maxdecel,8 +cdl_maxspeed,8 +cdl_mc,mc8 +cdl_rev_enc_lim,5769621 +cdl_steps_per_x,100000 +cdr_axis,D +cdr_axis_number,60 +cdr_cnts_per_x,32768 +cdr_description,CURTAIN DETECTOR EAST TRANSLATION +cdr_dflt_accel_steps,25000 +cdr_dflt_decel_steps,25000 +cdr_dflt_speed_steps,150000 +cdr_fwd_enc_lim,16104612 +cdr_maxaccel,8 +cdr_maxdecel,8 +cdr_maxspeed,8 +cdr_mc,mc8 +cdr_rev_enc_lim,4371043 +cdr_steps_per_x,100000 +cdu_axis,E +cdu_axis_number,61 +cdu_cnts_per_x,32768 +cdu_description,CURTAIN DETECTOR TOP TRANSLATION +cdu_dflt_accel_steps,25000 +cdu_dflt_decel_steps,25000 +cdu_dflt_speed_steps,150000 +cdu_fwd_enc_lim,33499670 +cdu_maxaccel,8 +cdu_maxdecel,8 +cdu_maxspeed,8 +cdu_mc,mc8 +cdu_rev_enc_lim,21804679 +cdu_steps_per_x,100000 +col1_axis,A +col1_axis_number,9 +col1_cnts_per_x,2048 +col1_description,Collimator Trans (Col SEG 1) VH +col1_dflt_accel_steps,50000 +col1_dflt_decel_steps,50000 +col1_dflt_speed_steps,100000 +col1_empty,541261 +col1_fwd_enc_lim,557470 +col1_guide,262369 +col1_maxaccel,0.833333333333333 +col1_maxdecel,0.833333333333333 +col1_maxspeed,0.833333333333333 +col1_mc,mc2 +col1_rev_enc_lim,3902 +col1_steps_per_x,150000 +col2_axis,B +col2_axis_number,10 +col2_cnts_per_x,2048 +col2_description,Collimator Trans (Col SEG 2) VH +col2_dflt_accel_steps,50000 +col2_dflt_decel_steps,50000 +col2_dflt_speed_steps,100000 +col2_empty,546816 +col2_fwd_enc_lim,564598 +col2_guide,273591 +col2_maxaccel,0.833333333333333 +col2_maxdecel,0.833333333333333 +col2_maxspeed,0.833333333333333 +col2_mc,mc2 +col2_rev_enc_lim,9598 +col2_steps_per_x,150000 +col3_axis,C +col3_axis_number,11 +col3_cnts_per_x,2048 +col3_description,Collimator Trans (Col SEG 3) VH +col3_dflt_accel_steps,50000 +col3_dflt_decel_steps,50000 +col3_dflt_speed_steps,100000 +col3_empty,558462 +col3_fwd_enc_lim,578556 +col3_guide,287471 +col3_maxaccel,0.833333333333333 +col3_maxdecel,0.833333333333333 +col3_maxspeed,0.833333333333333 +col3_mc,mc2 +col3_rev_enc_lim,29466 +col3_steps_per_x,150000 +col4_axis,D +col4_axis_number,12 +col4_cnts_per_x,4096 +col4_description,Collimator Trans (Col SEG 4) VH +col4_dflt_accel_steps,50000 +col4_dflt_decel_steps,50000 +col4_dflt_speed_steps,100000 +col4_empty,1062105 +col4_fwd_enc_lim,1116447 +col4_guide,539261 +col4_maxaccel,0.833333333333333 +col4_maxdecel,0.833333333333333 +col4_maxspeed,0.833333333333333 +col4_mc,mc2 +col4_rev_enc_lim,12861 +col4_steps_per_x,150000 +col5_axis,E +col5_axis_number,13 +col5_cnts_per_x,2048 +col5_description,Collimator Trans (Col SEG 5) VH +col5_dflt_accel_steps,50000 +col5_dflt_decel_steps,50000 +col5_dflt_speed_steps,100000 +col5_empty,904072 +col5_fwd_enc_lim,928235 +col5_guide,644380 +col5_maxaccel,0.833333333333333 +col5_maxdecel,0.833333333333333 +col5_maxspeed,0.833333333333333 +col5_mc,mc2 +col5_rev_enc_lim,377801 +col5_steps_per_x,150000 +col6_axis,F +col6_axis_number,14 +col6_cnts_per_x,2048 +col6_description,Collimator Trans (Col SEG 6) VH +col6_dflt_accel_steps,50000 +col6_dflt_decel_steps,50000 +col6_dflt_speed_steps,100000 +col6_empty,721132 +col6_fwd_enc_lim,747130 +col6_guide,457285 +col6_maxaccel,0.833333333333333 +col6_maxdecel,0.833333333333333 +col6_maxspeed,0.833333333333333 +col6_mc,mc2 +col6_rev_enc_lim,191508 +col6_steps_per_x,150000 +col7_axis,G +col7_axis_number,15 +col7_cnts_per_x,2048 +col7_description,Collimator Trans (Col SEG 7) VH +col7_dflt_accel_steps,50000 +col7_dflt_decel_steps,50000 +col7_dflt_speed_steps,100000 +col7_empty,555984 +col7_fwd_enc_lim,577633 +col7_guide,288216 +col7_maxaccel,0.833333333333333 +col7_maxdecel,0.833333333333333 +col7_maxspeed,0.833333333333333 +col7_mc,mc2 +col7_rev_enc_lim,24810 +col7_steps_per_x,150000 +col8_axis,H +col8_axis_number,16 +col8_cnts_per_x,2048 +col8_description,Collimator Trans (Col SEG 8) VH +col8_dflt_accel_steps,50000 +col8_dflt_decel_steps,50000 +col8_dflt_speed_steps,100000 +col8_empty,538544 +col8_fwd_enc_lim,561091 +col8_guide,273474 +col8_maxaccel,0.833333333333333 +col8_maxdecel,0.833333333333333 +col8_maxspeed,0.833333333333333 +col8_mc,mc2 +col8_rev_enc_lim,12893 +col8_steps_per_x,150000 +det_axis,B +det_axis_number,58 +det_cnts_per_x,524.288 +det_description,CURTAIN DETECTOR CARRIAGE Y TRANS +det_dflt_accel_steps,25000 +det_dflt_decel_steps,25000 +det_dflt_speed_steps,100000 +det_fwd_enc_lim,0 +det_maxaccel,25 +det_maxdecel,25 +det_maxspeed,25 +det_mc,mc8 +det_rev_enc_lim,0 +det_steps_per_x,3900 +sdh_5a_in,1535698 +sdh_5b_in,3747542 +sdh_axis,B +sdh_axis_number,26 +sdh_cnts_per_x,-12288 +sdh_description,SDH Box +sdh_fwd_enc_lim,1189505 +sdh_mc,mc4 +sdh_rev_enc_lim,4166803 +sdh_steps_per_x,37500 +ss1d_axis,D +ss1d_axis_number,20 +ss1d_cnts_per_x,-16384 +ss1d_description,Slit System 1 - Z DOWN +ss1d_dflt_accel_steps,25000 +ss1d_dflt_decel_steps,25000 +ss1d_dflt_speed_steps,25000 +ss1d_fwd_enc_lim,31525131 +ss1d_maxaccel,1 +ss1d_maxdecel,1 +ss1d_maxspeed,1 +ss1d_mc,mc3 +ss1d_rev_enc_lim,33398312 +ss1d_steps_per_x,50000 +ss1l_axis,A +ss1l_axis_number,17 +ss1l_cnts_per_x,16384 +ss1l_description,Slit System 1 - X WEST +ss1l_dflt_accel_steps,25000 +ss1l_dflt_decel_steps,25000 +ss1l_dflt_speed_steps,25000 +ss1l_fwd_enc_lim,31524107 +ss1l_maxaccel,1 +ss1l_maxdecel,1 +ss1l_maxspeed,1 +ss1l_mc,mc3 +ss1l_rev_enc_lim,32637740 +ss1l_steps_per_x,-50000 +ss1r_axis,C +ss1r_axis_number,19 +ss1r_cnts_per_x,16384 +ss1r_description,Slit System 1 - X EAST +ss1r_dflt_accel_steps,25000 +ss1r_dflt_decel_steps,25000 +ss1r_dflt_speed_steps,25000 +ss1r_fwd_enc_lim,32248545 +ss1r_maxaccel,1 +ss1r_maxdecel,1 +ss1r_maxspeed,1 +ss1r_mc,mc3 +ss1r_rev_enc_lim,33421848 +ss1r_steps_per_x,-50000 +ss1u_axis,B +ss1u_axis_number,18 +ss1u_cnts_per_x,-16384 +ss1u_description,Slit System 1 - Z UP +ss1u_dflt_accel_steps,25000 +ss1u_dflt_decel_steps,25000 +ss1u_dflt_speed_steps,25000 +ss1u_fwd_enc_lim,31434607 +ss1u_maxaccel,1 +ss1u_maxdecel,1 +ss1u_maxspeed,1 +ss1u_mc,mc3 +ss1u_rev_enc_lim,33297987 +ss1u_steps_per_x,50000 +vs_axis,D +vs_axis_number,28 +vs_cnts_per_x,-12288 +vs_description,Velocity Selector Trans +vs_dflt_accel_steps,15000 +vs_dflt_decel_steps,50000 +vs_dflt_speed_steps,50000 +vs_fwd_enc_lim,406690 +vs_glass_in,741128 +vs_maxaccel,1.33333333333333 +vs_maxdecel,1.33333333333333 +vs_maxspeed,1.33333333333333 +vs_mc,mc4 +vs_rev_enc_lim,3789130 +vs_steps_per_x,37500 diff --git a/site_ansto/instrument/bilby/config/motors/README.TXT b/site_ansto/instrument/bilby/config/motors/README.TXT new file mode 100644 index 00000000..4bbf6d53 --- /dev/null +++ b/site_ansto/instrument/bilby/config/motors/README.TXT @@ -0,0 +1,6 @@ +The generated_motor_configuration.tcl file was generated from the following CSV files, + +Bilby_motion_control_commissioning_checklist.csv: Extracted from spreadsheet of the same name +hdb_info.csv: Some parameters for hipadaba tree. Hand written. +sicsmot_attlist.csv: Extra parameters generated by the genmotconf.tcl script to complete the motor configurations. +userdef_attlist.csv: Parameters which were originally in sicsmot_attlist.csv but whose values have been changed from the defaults. diff --git a/site_ansto/instrument/bilby/config/motors/generated_motor_configuration.tcl b/site_ansto/instrument/bilby/config/motors/generated_motor_configuration.tcl new file mode 100644 index 00000000..cd11631e --- /dev/null +++ b/site_ansto/instrument/bilby/config/motors/generated_motor_configuration.tcl @@ -0,0 +1,863 @@ +#### SICS motor driver configuration #### +# Generated by: ../../../util/genmotconf.tcl Bilby_motion_control_commissioning_checklist.csv hdb_info.csv sicsmot_attlist.csv userdef_attlist.csv +# Generated from the following files, +# file1: Bilby_motion_control_commissioning_checklist.csv +# file2: hdb_info.csv +# file3: sicsmot_attlist.csv +# file4: userdef_attlist.csv + +# Load motor driver configuration parameters +set flist [list\ + {Bilby_motion_control_commissioning_checklist.csv}\ + {hdb_info.csv}\ + {sicsmot_attlist.csv}\ + {userdef_attlist.csv}\ + ] + +foreach fattfile $flist { + if [catch { + set fattpath config/motors/$fattfile + set fh [open $fattpath RDONLY] + while {[gets $fh line] >= 0} { + eval "set [split $line {,}]" + } + close $fh + } msg] { + clientput ERROR: $msg + } +} + + +set sim_mode [SplitReply [motor_simulation]] + +if {$sim_mode == true} { + set motor_driver_type asim +} else { + set motor_driver_type DMC2280 +} + +if {$sim_mode == false} { + MakeAsyncQueue mc1 DMC2280 [dict get $::MOTOR_HOSTPORT MC1 HOST] [dict get $::MOTOR_HOSTPORT MC1 PORT] + MakeAsyncQueue mc2 DMC2280 [dict get $::MOTOR_HOSTPORT MC2 HOST] [dict get $::MOTOR_HOSTPORT MC2 PORT] + MakeAsyncQueue mc3 DMC2280 [dict get $::MOTOR_HOSTPORT MC3 HOST] [dict get $::MOTOR_HOSTPORT MC3 PORT] + MakeAsyncQueue mc4 DMC2280 [dict get $::MOTOR_HOSTPORT MC4 HOST] [dict get $::MOTOR_HOSTPORT MC4 PORT] + MakeAsyncQueue mc6 DMC2280 [dict get $::MOTOR_HOSTPORT MC6 HOST] [dict get $::MOTOR_HOSTPORT MC6 PORT] + MakeAsyncQueue mc8 DMC2280 [dict get $::MOTOR_HOSTPORT MC8 HOST] [dict get $::MOTOR_HOSTPORT MC8 PORT] +} + +# ap1 configuration +# Aperture Selector (Collimator SEG 1 Start) +# Axis number 1 +Motor ap1 $motor_driver_type [params\ + asyncqueue mc1\ + axis A\ + units $ap1_units\ + hardlowerlim $ap1_rev_lim\ + hardupperlim $ap1_fwd_lim\ + maxSpeed $ap1_maxspeed\ + maxAccel $ap1_maxaccel\ + maxDecel $ap1_maxdecel\ + stepsPerX $ap1_steps_per_x\ + posit_count 5\ + posit_1 $ap1_D10\ + posit_2 $ap1_D20\ + posit_3 $ap1_D40\ + posit_4 $ap1_40X40\ + posit_5 $ap1_100X40\ + absEnc 1\ + absEncHome $ap1_absenchome\ + cntsPerX $ap1_cnts_per_x] +ap1 softlowerlim $ap1_rev_lim +ap1 softupperlim $ap1_fwd_lim +ap1 home $ap1_home +ap1 part $ap1_part +ap1 long_name ap1 +ap1 speed $ap1_speed +ap1 accel $ap1_accel +ap1 decel $ap1_decel + +# ap2 configuration +# Aperture Selector (COLLIMATION SEG 2) +# Axis number 2 +Motor ap2 $motor_driver_type [params\ + asyncqueue mc1\ + axis B\ + units $ap2_units\ + hardlowerlim $ap2_rev_lim\ + hardupperlim $ap2_fwd_lim\ + maxSpeed $ap2_maxspeed\ + maxAccel $ap2_maxaccel\ + maxDecel $ap2_maxdecel\ + stepsPerX $ap2_steps_per_x\ + posit_count 5\ + posit_1 $ap2_D10\ + posit_2 $ap2_D20\ + posit_3 $ap2_D40\ + posit_4 $ap2_40X40\ + posit_5 $ap2_100X40\ + absEnc 1\ + absEncHome $ap2_absenchome\ + cntsPerX $ap2_cnts_per_x] +ap2 softlowerlim $ap2_rev_lim +ap2 softupperlim $ap2_fwd_lim +ap2 home $ap2_home +ap2 part $ap2_part +ap2 long_name ap2 +ap2 speed $ap2_speed +ap2 accel $ap2_accel +ap2 decel $ap2_decel + +# ap3 configuration +# Aperture Selector (COLLIMATION SEG 3) +# Axis number 3 +Motor ap3 $motor_driver_type [params\ + asyncqueue mc1\ + axis C\ + units $ap3_units\ + hardlowerlim $ap3_rev_lim\ + hardupperlim $ap3_fwd_lim\ + maxSpeed $ap3_maxspeed\ + maxAccel $ap3_maxaccel\ + maxDecel $ap3_maxdecel\ + stepsPerX $ap3_steps_per_x\ + posit_count 5\ + posit_1 $ap3_D10\ + posit_2 $ap3_D20\ + posit_3 $ap3_D40\ + posit_4 $ap3_40X40\ + posit_5 $ap3_100X40\ + absEnc 1\ + absEncHome $ap3_absenchome\ + cntsPerX $ap3_cnts_per_x] +ap3 softlowerlim $ap3_rev_lim +ap3 softupperlim $ap3_fwd_lim +ap3 home $ap3_home +ap3 part $ap3_part +ap3 long_name ap3 +ap3 speed $ap3_speed +ap3 accel $ap3_accel +ap3 decel $ap3_decel + +# ap4 configuration +# Aperture Selector (COLLIMATION SEG 4) +# Axis number 4 +Motor ap4 $motor_driver_type [params\ + asyncqueue mc1\ + axis D\ + units $ap4_units\ + hardlowerlim $ap4_rev_lim\ + hardupperlim $ap4_fwd_lim\ + maxSpeed $ap4_maxspeed\ + maxAccel $ap4_maxaccel\ + maxDecel $ap4_maxdecel\ + stepsPerX $ap4_steps_per_x\ + posit_count 5\ + posit_1 $ap4_D10\ + posit_2 $ap4_D20\ + posit_3 $ap4_D40\ + posit_4 $ap4_40X40\ + posit_5 $ap4_100X40\ + absEnc 1\ + absEncHome $ap4_absenchome\ + cntsPerX $ap4_cnts_per_x] +ap4 softlowerlim $ap4_rev_lim +ap4 softupperlim $ap4_fwd_lim +ap4 home $ap4_home +ap4 part $ap4_part +ap4 long_name ap4 +ap4 speed $ap4_speed +ap4 accel $ap4_accel +ap4 decel $ap4_decel + +# ap5 configuration +# Aperture Selector (COLLIMATION SEG 5) +# Axis number 5 +Motor ap5 $motor_driver_type [params\ + asyncqueue mc1\ + axis E\ + units $ap5_units\ + hardlowerlim $ap5_rev_lim\ + hardupperlim $ap5_fwd_lim\ + maxSpeed $ap5_maxspeed\ + maxAccel $ap5_maxaccel\ + maxDecel $ap5_maxdecel\ + stepsPerX $ap5_steps_per_x\ + posit_count 5\ + posit_1 $ap5_D10\ + posit_2 $ap5_D20\ + posit_3 $ap5_D40\ + posit_4 $ap5_40X40\ + posit_5 $ap5_100X40\ + absEnc 1\ + absEncHome $ap5_absenchome\ + cntsPerX $ap5_cnts_per_x] +ap5 softlowerlim $ap5_rev_lim +ap5 softupperlim $ap5_fwd_lim +ap5 home $ap5_home +ap5 part $ap5_part +ap5 long_name ap5 +ap5 speed $ap5_speed +ap5 accel $ap5_accel +ap5 decel $ap5_decel + +# ap6 configuration +# Aperture Selector (COLLIMATION SEG 6) +# Axis number 6 +Motor ap6 $motor_driver_type [params\ + asyncqueue mc1\ + axis F\ + units $ap6_units\ + hardlowerlim $ap6_rev_lim\ + hardupperlim $ap6_fwd_lim\ + maxSpeed $ap6_maxspeed\ + maxAccel $ap6_maxaccel\ + maxDecel $ap6_maxdecel\ + stepsPerX $ap6_steps_per_x\ + posit_count 5\ + posit_1 $ap6_D10\ + posit_2 $ap6_D20\ + posit_3 $ap6_D40\ + posit_4 $ap6_40X40\ + posit_5 $ap6_100X40\ + absEnc 1\ + absEncHome $ap6_absenchome\ + cntsPerX $ap6_cnts_per_x] +ap6 softlowerlim $ap6_rev_lim +ap6 softupperlim $ap6_fwd_lim +ap6 home $ap6_home +ap6 part $ap6_part +ap6 long_name ap6 +ap6 speed $ap6_speed +ap6 accel $ap6_accel +ap6 decel $ap6_decel + +# ap7 configuration +# Aperture Selector (COLLIMATION SEG 7) +# Axis number 7 +Motor ap7 $motor_driver_type [params\ + asyncqueue mc1\ + axis G\ + units $ap7_units\ + hardlowerlim $ap7_rev_lim\ + hardupperlim $ap7_fwd_lim\ + maxSpeed $ap7_maxspeed\ + maxAccel $ap7_maxaccel\ + maxDecel $ap7_maxdecel\ + stepsPerX $ap7_steps_per_x\ + posit_count 5\ + posit_1 $ap7_D10\ + posit_2 $ap7_D20\ + posit_3 $ap7_D40\ + posit_4 $ap7_40X40\ + posit_5 $ap7_100X40\ + absEnc 1\ + absEncHome $ap7_absenchome\ + cntsPerX $ap7_cnts_per_x] +ap7 softlowerlim $ap7_rev_lim +ap7 softupperlim $ap7_fwd_lim +ap7 home $ap7_home +ap7 part $ap7_part +ap7 long_name ap7 +ap7 speed $ap7_speed +ap7 accel $ap7_accel +ap7 decel $ap7_decel + +# ap8 configuration +# Aperture Selector (Collimator SEG 8 End) +# Axis number 8 +Motor ap8 $motor_driver_type [params\ + asyncqueue mc1\ + axis H\ + units $ap8_units\ + hardlowerlim $ap8_rev_lim\ + hardupperlim $ap8_fwd_lim\ + maxSpeed $ap8_maxspeed\ + maxAccel $ap8_maxaccel\ + maxDecel $ap8_maxdecel\ + stepsPerX $ap8_steps_per_x\ + posit_count 5\ + posit_1 $ap8_D10\ + posit_2 $ap8_D20\ + posit_3 $ap8_D40\ + posit_4 $ap8_40X40\ + posit_5 $ap8_100X40\ + absEnc 1\ + absEncHome $ap8_absenchome\ + cntsPerX $ap8_cnts_per_x] +ap8 softlowerlim $ap8_rev_lim +ap8 softupperlim $ap8_fwd_lim +ap8 home $ap8_home +ap8 part $ap8_part +ap8 long_name ap8 +ap8 speed $ap8_speed +ap8 accel $ap8_accel +ap8 decel $ap8_decel + +# att configuration +# 4 Position linear Attenuator +# Axis number 25 +Motor att $motor_driver_type [params\ + asyncqueue mc4\ + axis A\ + units $att_units\ + hardlowerlim $att_rev_lim\ + hardupperlim $att_fwd_lim\ + maxSpeed $att_maxspeed\ + maxAccel $att_maxaccel\ + maxDecel $att_maxdecel\ + stepsPerX $att_steps_per_x\ + posit_count 5\ + posit_1 $att_pos1\ + posit_2 $att_pos2\ + posit_3 $att_pos3\ + posit_4 $att_pos4\ + posit_5 $att_pos5\ + absEnc 1\ + absEncHome $att_absenchome\ + cntsPerX $att_cnts_per_x] +att softlowerlim $att_rev_lim +att softupperlim $att_fwd_lim +att home $att_home +att part $att_part +att long_name att +att speed $att_speed +att accel $att_accel +att decel $att_decel + +# bs3 configuration +# beam stop 3 +# Axis number 43 +Motor bs3 $motor_driver_type [params\ + asyncqueue mc6\ + axis C\ + units $bs3_units\ + hardlowerlim $bs3_rev_lim\ + hardupperlim $bs3_fwd_lim\ + maxSpeed $bs3_maxspeed\ + maxAccel $bs3_maxaccel\ + maxDecel $bs3_maxdecel\ + stepsPerX $bs3_steps_per_x\ + posit_count 0\ + absEnc 1\ + absEncHome $bs3_absenchome\ + cntsPerX $bs3_cnts_per_x] +bs3 softlowerlim $bs3_rev_lim +bs3 softupperlim $bs3_fwd_lim +bs3 home $bs3_home +bs3 part $bs3_part +bs3 long_name bs3 +bs3 speed $bs3_speed +bs3 accel $bs3_accel +bs3 decel $bs3_decel + +# cdd configuration +# CURTAIN DETECTOR BOTTOM TRANSLATION +# Axis number 62 +Motor cdd $motor_driver_type [params\ + asyncqueue mc8\ + axis F\ + units $cdd_units\ + hardlowerlim $cdd_rev_lim\ + hardupperlim $cdd_fwd_lim\ + maxSpeed $cdd_maxspeed\ + maxAccel $cdd_maxaccel\ + maxDecel $cdd_maxdecel\ + stepsPerX $cdd_steps_per_x\ + posit_count 0\ + absEnc 1\ + absEncHome $cdd_absenchome\ + cntsPerX $cdd_cnts_per_x] +cdd softlowerlim $cdd_rev_lim +cdd softupperlim $cdd_fwd_lim +cdd home $cdd_home +cdd part $cdd_part +cdd long_name cdd +cdd speed $cdd_speed +cdd accel $cdd_accel +cdd decel $cdd_decel + +# cdl configuration +# CURTAIN DETECTOR WEST TRANSLATION +# Axis number 59 +Motor cdl $motor_driver_type [params\ + asyncqueue mc8\ + axis C\ + units $cdl_units\ + hardlowerlim $cdl_rev_lim\ + hardupperlim $cdl_fwd_lim\ + maxSpeed $cdl_maxspeed\ + maxAccel $cdl_maxaccel\ + maxDecel $cdl_maxdecel\ + stepsPerX $cdl_steps_per_x\ + posit_count 0\ + absEnc 1\ + absEncHome $cdl_absenchome\ + cntsPerX $cdl_cnts_per_x] +cdl softlowerlim $cdl_rev_lim +cdl softupperlim $cdl_fwd_lim +cdl home $cdl_home +cdl part $cdl_part +cdl long_name cdl +cdl speed $cdl_speed +cdl accel $cdl_accel +cdl decel $cdl_decel + +# cdr configuration +# CURTAIN DETECTOR EAST TRANSLATION +# Axis number 60 +Motor cdr $motor_driver_type [params\ + asyncqueue mc8\ + axis D\ + units $cdr_units\ + hardlowerlim $cdr_rev_lim\ + hardupperlim $cdr_fwd_lim\ + maxSpeed $cdr_maxspeed\ + maxAccel $cdr_maxaccel\ + maxDecel $cdr_maxdecel\ + stepsPerX $cdr_steps_per_x\ + posit_count 0\ + absEnc 1\ + absEncHome $cdr_absenchome\ + cntsPerX $cdr_cnts_per_x] +cdr softlowerlim $cdr_rev_lim +cdr softupperlim $cdr_fwd_lim +cdr home $cdr_home +cdr part $cdr_part +cdr long_name cdr +cdr speed $cdr_speed +cdr accel $cdr_accel +cdr decel $cdr_decel + +# cdu configuration +# CURTAIN DETECTOR TOP TRANSLATION +# Axis number 61 +Motor cdu $motor_driver_type [params\ + asyncqueue mc8\ + axis E\ + units $cdu_units\ + hardlowerlim $cdu_rev_lim\ + hardupperlim $cdu_fwd_lim\ + maxSpeed $cdu_maxspeed\ + maxAccel $cdu_maxaccel\ + maxDecel $cdu_maxdecel\ + stepsPerX $cdu_steps_per_x\ + posit_count 0\ + absEnc 1\ + absEncHome $cdu_absenchome\ + cntsPerX $cdu_cnts_per_x] +cdu softlowerlim $cdu_rev_lim +cdu softupperlim $cdu_fwd_lim +cdu home $cdu_home +cdu part $cdu_part +cdu long_name cdu +cdu speed $cdu_speed +cdu accel $cdu_accel +cdu decel $cdu_decel + +# col1 configuration +# Collimator Trans (Col SEG 1) VH +# Axis number 9 +Motor col1 $motor_driver_type [params\ + asyncqueue mc2\ + axis A\ + units $col1_units\ + hardlowerlim $col1_rev_lim\ + hardupperlim $col1_fwd_lim\ + maxSpeed $col1_maxspeed\ + maxAccel $col1_maxaccel\ + maxDecel $col1_maxdecel\ + stepsPerX $col1_steps_per_x\ + posit_count 2\ + posit_1 $col1_guide\ + posit_2 $col1_empty\ + absEnc 1\ + absEncHome $col1_absenchome\ + cntsPerX $col1_cnts_per_x] +col1 softlowerlim $col1_rev_lim +col1 softupperlim $col1_fwd_lim +col1 home $col1_home +col1 part $col1_part +col1 long_name col1 +col1 speed $col1_speed +col1 accel $col1_accel +col1 decel $col1_decel + +# col2 configuration +# Collimator Trans (Col SEG 2) VH +# Axis number 10 +Motor col2 $motor_driver_type [params\ + asyncqueue mc2\ + axis B\ + units $col2_units\ + hardlowerlim $col2_rev_lim\ + hardupperlim $col2_fwd_lim\ + maxSpeed $col2_maxspeed\ + maxAccel $col2_maxaccel\ + maxDecel $col2_maxdecel\ + stepsPerX $col2_steps_per_x\ + posit_count 2\ + posit_1 $col2_guide\ + posit_2 $col2_empty\ + absEnc 1\ + absEncHome $col2_absenchome\ + cntsPerX $col2_cnts_per_x] +col2 softlowerlim $col2_rev_lim +col2 softupperlim $col2_fwd_lim +col2 home $col2_home +col2 part $col2_part +col2 long_name col2 +col2 speed $col2_speed +col2 accel $col2_accel +col2 decel $col2_decel + +# col3 configuration +# Collimator Trans (Col SEG 3) VH +# Axis number 11 +Motor col3 $motor_driver_type [params\ + asyncqueue mc2\ + axis C\ + units $col3_units\ + hardlowerlim $col3_rev_lim\ + hardupperlim $col3_fwd_lim\ + maxSpeed $col3_maxspeed\ + maxAccel $col3_maxaccel\ + maxDecel $col3_maxdecel\ + stepsPerX $col3_steps_per_x\ + posit_count 2\ + posit_1 $col3_guide\ + posit_2 $col3_empty\ + absEnc 1\ + absEncHome $col3_absenchome\ + cntsPerX $col3_cnts_per_x] +col3 softlowerlim $col3_rev_lim +col3 softupperlim $col3_fwd_lim +col3 home $col3_home +col3 part $col3_part +col3 long_name col3 +col3 speed $col3_speed +col3 accel $col3_accel +col3 decel $col3_decel + +# col4 configuration +# Collimator Trans (Col SEG 4) VH +# Axis number 12 +Motor col4 $motor_driver_type [params\ + asyncqueue mc2\ + axis D\ + units $col4_units\ + hardlowerlim $col4_rev_lim\ + hardupperlim $col4_fwd_lim\ + maxSpeed $col4_maxspeed\ + maxAccel $col4_maxaccel\ + maxDecel $col4_maxdecel\ + stepsPerX $col4_steps_per_x\ + posit_count 2\ + posit_1 $col4_guide\ + posit_2 $col4_empty\ + absEnc 1\ + absEncHome $col4_absenchome\ + cntsPerX $col4_cnts_per_x] +col4 softlowerlim $col4_rev_lim +col4 softupperlim $col4_fwd_lim +col4 home $col4_home +col4 part $col4_part +col4 long_name col4 +col4 speed $col4_speed +col4 accel $col4_accel +col4 decel $col4_decel + +# col5 configuration +# Collimator Trans (Col SEG 5) VH +# Axis number 13 +Motor col5 $motor_driver_type [params\ + asyncqueue mc2\ + axis E\ + units $col5_units\ + hardlowerlim $col5_rev_lim\ + hardupperlim $col5_fwd_lim\ + maxSpeed $col5_maxspeed\ + maxAccel $col5_maxaccel\ + maxDecel $col5_maxdecel\ + stepsPerX $col5_steps_per_x\ + posit_count 2\ + posit_1 $col5_guide\ + posit_2 $col5_empty\ + absEnc 1\ + absEncHome $col5_absenchome\ + cntsPerX $col5_cnts_per_x] +col5 softlowerlim $col5_rev_lim +col5 softupperlim $col5_fwd_lim +col5 home $col5_home +col5 part $col5_part +col5 long_name col5 +col5 speed $col5_speed +col5 accel $col5_accel +col5 decel $col5_decel + +# col6 configuration +# Collimator Trans (Col SEG 6) VH +# Axis number 14 +Motor col6 $motor_driver_type [params\ + asyncqueue mc2\ + axis F\ + units $col6_units\ + hardlowerlim $col6_rev_lim\ + hardupperlim $col6_fwd_lim\ + maxSpeed $col6_maxspeed\ + maxAccel $col6_maxaccel\ + maxDecel $col6_maxdecel\ + stepsPerX $col6_steps_per_x\ + posit_count 2\ + posit_1 $col6_guide\ + posit_2 $col6_empty\ + absEnc 1\ + absEncHome $col6_absenchome\ + cntsPerX $col6_cnts_per_x] +col6 softlowerlim $col6_rev_lim +col6 softupperlim $col6_fwd_lim +col6 home $col6_home +col6 part $col6_part +col6 long_name col6 +col6 speed $col6_speed +col6 accel $col6_accel +col6 decel $col6_decel + +# col7 configuration +# Collimator Trans (Col SEG 7) VH +# Axis number 15 +Motor col7 $motor_driver_type [params\ + asyncqueue mc2\ + axis G\ + units $col7_units\ + hardlowerlim $col7_rev_lim\ + hardupperlim $col7_fwd_lim\ + maxSpeed $col7_maxspeed\ + maxAccel $col7_maxaccel\ + maxDecel $col7_maxdecel\ + stepsPerX $col7_steps_per_x\ + posit_count 2\ + posit_1 $col7_guide\ + posit_2 $col7_empty\ + absEnc 1\ + absEncHome $col7_absenchome\ + cntsPerX $col7_cnts_per_x] +col7 softlowerlim $col7_rev_lim +col7 softupperlim $col7_fwd_lim +col7 home $col7_home +col7 part $col7_part +col7 long_name col7 +col7 speed $col7_speed +col7 accel $col7_accel +col7 decel $col7_decel + +# col8 configuration +# Collimator Trans (Col SEG 8) VH +# Axis number 16 +Motor col8 $motor_driver_type [params\ + asyncqueue mc2\ + axis H\ + units $col8_units\ + hardlowerlim $col8_rev_lim\ + hardupperlim $col8_fwd_lim\ + maxSpeed $col8_maxspeed\ + maxAccel $col8_maxaccel\ + maxDecel $col8_maxdecel\ + stepsPerX $col8_steps_per_x\ + posit_count 2\ + posit_1 $col8_guide\ + posit_2 $col8_empty\ + absEnc 1\ + absEncHome $col8_absenchome\ + cntsPerX $col8_cnts_per_x] +col8 softlowerlim $col8_rev_lim +col8 softupperlim $col8_fwd_lim +col8 home $col8_home +col8 part $col8_part +col8 long_name col8 +col8 speed $col8_speed +col8 accel $col8_accel +col8 decel $col8_decel + +# det configuration +# CURTAIN DETECTOR CARRIAGE Y TRANS +# Axis number 58 +Motor det $motor_driver_type [params\ + asyncqueue mc8\ + axis B\ + units $det_units\ + hardlowerlim $det_rev_lim\ + hardupperlim $det_fwd_lim\ + maxSpeed $det_maxspeed\ + maxAccel $det_maxaccel\ + maxDecel $det_maxdecel\ + stepsPerX $det_steps_per_x\ + posit_count 0\ + absEnc 1\ + absEncHome $det_absenchome\ + cntsPerX $det_cnts_per_x] +det softlowerlim $det_rev_lim +det softupperlim $det_fwd_lim +det home $det_home +det part $det_part +det long_name det +det speed $det_speed +det accel $det_accel +det decel $det_decel + +# sdh configuration +# SDH Box +# Axis number 26 +Motor sdh $motor_driver_type [params\ + asyncqueue mc4\ + axis B\ + units $sdh_units\ + hardlowerlim $sdh_rev_lim\ + hardupperlim $sdh_fwd_lim\ + maxSpeed $sdh_maxspeed\ + maxAccel $sdh_maxaccel\ + maxDecel $sdh_maxdecel\ + stepsPerX $sdh_steps_per_x\ + posit_count 2\ + posit_1 $sdh_5b_in\ + posit_2 $sdh_5a_in\ + absEnc 1\ + absEncHome $sdh_absenchome\ + cntsPerX $sdh_cnts_per_x] +sdh softlowerlim $sdh_rev_lim +sdh softupperlim $sdh_fwd_lim +sdh home $sdh_home +sdh part $sdh_part +sdh long_name sdh + +# ss1d configuration +# Slit System 1 - Z DOWN +# Axis number 20 +Motor ss1d $motor_driver_type [params\ + asyncqueue mc3\ + axis D\ + units $ss1d_units\ + hardlowerlim $ss1d_rev_lim\ + hardupperlim $ss1d_fwd_lim\ + maxSpeed $ss1d_maxspeed\ + maxAccel $ss1d_maxaccel\ + maxDecel $ss1d_maxdecel\ + stepsPerX $ss1d_steps_per_x\ + posit_count 0\ + absEnc 1\ + absEncHome $ss1d_absenchome\ + cntsPerX $ss1d_cnts_per_x] +ss1d softlowerlim $ss1d_rev_lim +ss1d softupperlim $ss1d_fwd_lim +ss1d home $ss1d_home +ss1d part $ss1d_part +ss1d long_name ss1d +ss1d speed $ss1d_speed +ss1d accel $ss1d_accel +ss1d decel $ss1d_decel + +# ss1l configuration +# Slit System 1 - X WEST +# Axis number 17 +Motor ss1l $motor_driver_type [params\ + asyncqueue mc3\ + axis A\ + units $ss1l_units\ + hardlowerlim $ss1l_rev_lim\ + hardupperlim $ss1l_fwd_lim\ + maxSpeed $ss1l_maxspeed\ + maxAccel $ss1l_maxaccel\ + maxDecel $ss1l_maxdecel\ + stepsPerX $ss1l_steps_per_x\ + posit_count 0\ + absEnc 1\ + absEncHome $ss1l_absenchome\ + cntsPerX $ss1l_cnts_per_x] +ss1l softlowerlim $ss1l_rev_lim +ss1l softupperlim $ss1l_fwd_lim +ss1l home $ss1l_home +ss1l part $ss1l_part +ss1l long_name ss1l +ss1l speed $ss1l_speed +ss1l accel $ss1l_accel +ss1l decel $ss1l_decel + +# ss1r configuration +# Slit System 1 - X EAST +# Axis number 19 +Motor ss1r $motor_driver_type [params\ + asyncqueue mc3\ + axis C\ + units $ss1r_units\ + hardlowerlim $ss1r_rev_lim\ + hardupperlim $ss1r_fwd_lim\ + maxSpeed $ss1r_maxspeed\ + maxAccel $ss1r_maxaccel\ + maxDecel $ss1r_maxdecel\ + stepsPerX $ss1r_steps_per_x\ + posit_count 0\ + absEnc 1\ + absEncHome $ss1r_absenchome\ + cntsPerX $ss1r_cnts_per_x] +ss1r softlowerlim $ss1r_rev_lim +ss1r softupperlim $ss1r_fwd_lim +ss1r home $ss1r_home +ss1r part $ss1r_part +ss1r long_name ss1r +ss1r speed $ss1r_speed +ss1r accel $ss1r_accel +ss1r decel $ss1r_decel + +# ss1u configuration +# Slit System 1 - Z UP +# Axis number 18 +Motor ss1u $motor_driver_type [params\ + asyncqueue mc3\ + axis B\ + units $ss1u_units\ + hardlowerlim $ss1u_rev_lim\ + hardupperlim $ss1u_fwd_lim\ + maxSpeed $ss1u_maxspeed\ + maxAccel $ss1u_maxaccel\ + maxDecel $ss1u_maxdecel\ + stepsPerX $ss1u_steps_per_x\ + posit_count 0\ + absEnc 1\ + absEncHome $ss1u_absenchome\ + cntsPerX $ss1u_cnts_per_x] +ss1u softlowerlim $ss1u_rev_lim +ss1u softupperlim $ss1u_fwd_lim +ss1u home $ss1u_home +ss1u part $ss1u_part +ss1u long_name ss1u +ss1u speed $ss1u_speed +ss1u accel $ss1u_accel +ss1u decel $ss1u_decel + +# vs configuration +# Velocity Selector Trans +# Axis number 28 +Motor vs $motor_driver_type [params\ + asyncqueue mc4\ + axis D\ + units $vs_units\ + hardlowerlim $vs_rev_lim\ + hardupperlim $vs_fwd_lim\ + maxSpeed $vs_maxspeed\ + maxAccel $vs_maxaccel\ + maxDecel $vs_maxdecel\ + stepsPerX $vs_steps_per_x\ + posit_count 1\ + posit_1 $vs_glass_in\ + absEnc 1\ + absEncHome $vs_absenchome\ + cntsPerX $vs_cnts_per_x] +vs softlowerlim $vs_rev_lim +vs softupperlim $vs_fwd_lim +vs home $vs_home +vs part $vs_part +vs long_name vs +vs speed $vs_speed +vs accel $vs_accel +vs decel $vs_decel + +proc motor_set_sobj_attributes {} {} diff --git a/site_ansto/instrument/bilby/config/motors/hdb_info.csv b/site_ansto/instrument/bilby/config/motors/hdb_info.csv new file mode 100644 index 00000000..699dbbc7 --- /dev/null +++ b/site_ansto/instrument/bilby/config/motors/hdb_info.csv @@ -0,0 +1,88 @@ +ap1_part,collimator +ap1_units,degrees +ap2_part,collimator +ap2_units,degrees +ap3_part,collimator +ap3_units,degrees +ap4_part,collimator +ap4_units,degrees +ap5_part,collimator +ap5_units,degrees +ap6_part,collimator +ap6_units,degrees +ap7_part,collimator +ap7_units,degrees +ap8_part,collimator +ap8_units,degrees +att_part,instrument +att_units,mm +bs1_part,detector +bs1_units,degrees +bs2_part,detector +bs2_units,degrees +bs3_part,detector +bs3_units,degrees +cdd_part,detector +cdd_units,mm +cdl_part,detector +cdl_units,mm +cdr_part,detector +cdr_units,mm +cdu_part,detector +cdu_units,mm +col1_part,collimator +col1_units,mm +col2_part,collimator +col2_units,mm +col3_part,collimator +col3_units,mm +col4_part,collimator +col4_units,mm +col5_part,collimator +col5_units,mm +col6_part,collimator +col6_units,mm +col7_part,collimator +col7_units,mm +col8_part,collimator +col8_units,mm +det_part,detector +det_units,mm +mdy_part,detector +mdy_units,mm +mirr1_part,disk_chopper +mirr1_units,xxx +mirr2_part,disk_chopper +mirr2_units,xxx +sap_part,sample +sap_units,mm +schi_part,sample +schi_units,degrees +sdh_part,instrument +sdh_units,mm +som_part,sample +som_units,degrees +sphi_part,sample +sphi_units,degrees +ss1d_part,collimator +ss1d_units,mm +ss1l_part,collimator +ss1l_units,mm +ss1r_part,collimator +ss1r_units,mm +ss1u_part,collimator +ss1u_units,mm +ss2d_part,collimator +ss2d_units,mm +ss2l_part,collimator +ss2l_units,mm +ss2r_part,collimator +ss2r_units,mm +ss2u_part,collimator +ss2u_units,mm +sx_part,sample +sx_units,mm +sy_part,sample +sy_units,mm +vs_part,instrument +vs_units,mm diff --git a/site_ansto/instrument/bilby/config/motors/motor_configuration.tcl b/site_ansto/instrument/bilby/config/motors/motor_configuration.tcl new file mode 100644 index 00000000..497fab44 --- /dev/null +++ b/site_ansto/instrument/bilby/config/motors/motor_configuration.tcl @@ -0,0 +1,23 @@ +# @file Loads the generated_motor_configuration.tcl file which is created by util/genmotconf.tcl from CSV files. +fileeval config/motors/generated_motor_configuration.tcl +fileeval config/motors/sct_shutters.tcl +fileeval config/motors/sct_tank.tcl +add_shutters shutters aqadapter mc4 +add_tank tank aqadapter mc8 +# Motors which should not be driven should be set as "fixed" here. +# Configurable virtual motors can be defined here. +# Eg, mot fixed 1 +# Define "proc motor_set_sobj_attributes {}" if we need to define extra sicslist attributes for some motors. + +for {set n 1} {$n <= 8} {incr n} { + make_coll_motor_1 c$n c$n col$n count + make_coll_motor_1 a$n a$n ap$n count +} + +# Make a position-motor for the attenuator +make_coll_motor_1 att_pos att_pos att count +sicslist setatt att_pos klass instrument + +# make gap/offset motors for the slits +make_gap_motors ss1hg gap ss1ho offset ss1r ss1l mm first/horizontal +make_gap_motors ss1vg gap ss1vo offset ss1u ss1d mm first/vertical diff --git a/site_ansto/instrument/bilby/config/motors/sct_shutters.tcl b/site_ansto/instrument/bilby/config/motors/sct_shutters.tcl new file mode 100644 index 00000000..17829270 --- /dev/null +++ b/site_ansto/instrument/bilby/config/motors/sct_shutters.tcl @@ -0,0 +1,317 @@ +# Generated driver for shutters +# vim: ft=tcl tabstop=8 softtabstop=2 shiftwidth=2 nocindent smartindent +# + +namespace eval ::scobj::shutters { + set debug_threshold 0 +} + +proc ::scobj::shutters::debug_log {debug_level debug_string} { + set catch_status [ catch { + if {${debug_level} >= ${::scobj::shutters::debug_threshold}} { + set fd [open "/tmp/shutters.log" "a"] + set line "[clock format [clock seconds] -format "%T"] ${debug_string}" + puts ${fd} "${line}" + close ${fd} + } + } catch_message ] +} + +# check function for hset change +proc ::scobj::shutters::checkrange {tc_root} { + set catch_status [ catch { + debug_log 1 "checkrange tc_root=${tc_root} sct=[sct] target=[sct target]" + set setpoint [sct target] + if { [hpropexists [sct] lowerlimit] } { + set lolimit [sct lowerlimit] + } else { + # lowerlimit not set, use target + set lolimit [sct target] + } + if { [hpropexists [sct] upperlimit] } { + set hilimit [sct upperlimit] + } else { + # upperlimit not set, use target + set hilimit [sct target] + } +# hook code goes here + if { ${setpoint} < ${lolimit} || ${setpoint} > ${hilimit} } { + error "setpoint ${setpoint} violates limits (${lolimit}..${hilimit}) on [sct]" + } + return OK + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to request the read of a parameter on a device +proc ::scobj::shutters::getValue {tc_root nextState cmd_str} { + set catch_status [ catch { + debug_log 1 "getValue tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set cmd "${cmd_str}" +# hook code goes here + debug_log 1 "getValue sct send ${cmd}" + if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { + sct send "${cmd}" + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to check the write parameter on a device +proc ::scobj::shutters::noResponse {tc_root} { + set catch_status [ catch { + debug_log 1 "noResponse tc_root=${tc_root} sct=[sct] resp=[sct result]" +# hook code goes here + return "idle" + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to parse the read of a parameter on a device +proc ::scobj::shutters::read_switch_pair {tc_root} { + set catch_status [ catch { + debug_log 1 "read_switch_pair tc_root=${tc_root} sct=[sct] result=[sct result]" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set data [sct result] + set nextState "idle" + if {[string equal -nocase -length 7 ${data} "ASCERR:"]} { + # the protocol driver has reported an error + sct geterror "${data}" + error "[sct geterror]" + } +# hook code starts + if { [string equal -nocase -length 1 "${data}" "?"] } { + sct geterror "Galil error in: '${data}'" + } else { + set data_list [split [string trim "${data}"]] + if { [llength ${data_list}] > 2 && [lindex ${data_list} end] == ":" } { + set data_list [lrange ${data_list} 0 1] + } + if { [llength ${data_list}] == 2 } { + set left [expr [lindex ${data_list} 0]] + set right [expr [lindex ${data_list} 1]] + if { ${left} == 1 && ${right} == 0 } { # open + set data "out" + } elseif { ${left} == 0 && ${right} == 1 } { # closed + set data "in" + } else { # indeterminate + set data "moving" + } + } else { + sct geterror "Syntax error in: '${data}'=>'${data_list}'" + } + } +# hook code ends + if { [hpropexists [sct] geterror] } { + debug_log 1 "[sct] error: [sct geterror]" + error "[sct geterror]" + } + if { ${data} != [sct oldval] } { + debug_log 1 "[sct] changed to new:${data}, from old:[sct oldval]" + sct oldval ${data} + sct update ${data} + sct utime readtime + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to write a parameter value on a device +proc ::scobj::shutters::setValue {tc_root nextState cmd_str} { + set catch_status [ catch { + debug_log 1 "setValue tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set par [sct target] + set cmd "${cmd_str}${par}" +# hook code goes here + if { [hpropexists [sct] driving] } { + if { [hpropexists [sct] writestatus] && [sct writestatus] == "start" } { + sct driving 1 + } + } + debug_log 1 "setValue sct send ${cmd}" + if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { + sct send "${cmd}" + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to write a parameter value on a device +proc ::scobj::shutters::write_switch {tc_root nextState cmd_str} { + set catch_status [ catch { + debug_log 1 "write_switch tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set par [sct target] + set cmd "${cmd_str}${par}" +# hook code starts + if { [string equal -nocase -length 2 "${par}" "in"] } { + set cmd "SB${cmd_str}" + } elseif { [string equal -nocase -length 2 "${par}" "out"] } { + set cmd "CB${cmd_str}" + } else { + sct geterror "Value error: '${par}' not in ('in', 'out')" + } +# hook code ends + if { [hpropexists [sct] geterror] } { + debug_log 1 "[sct] error: [sct geterror]" + error "[sct geterror]" + } + if { [hpropexists [sct] driving] } { + if { [hpropexists [sct] writestatus] && [sct writestatus] == "start" } { + sct driving 1 + } + } + debug_log 1 "write_switch sct send ${cmd}" + if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { + sct send "${cmd}" + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +proc ::scobj::shutters::mk_sct_shutters { sct_controller name } { + debug_log 1 "mk_sct_shutters for ${name}" + set ns "[namespace current]" + set catch_status [ catch { + + MakeSICSObj ${name} SCT_OBJECT + + sicslist setatt ${name} klass instrument + sicslist setatt ${name} long_name ${name} + + set scobj_hpath /sics/${name} + + hfactory ${scobj_hpath}/fast_shutter plain user text + hsetprop ${scobj_hpath}/fast_shutter read ${ns}::getValue ${scobj_hpath} read_switch_pair {MG @IN[5], @IN[6]} + hsetprop ${scobj_hpath}/fast_shutter read_switch_pair ${ns}::read_switch_pair ${scobj_hpath} + hsetprop ${scobj_hpath}/fast_shutter control true + hsetprop ${scobj_hpath}/fast_shutter data true + hsetprop ${scobj_hpath}/fast_shutter mutable false + hsetprop ${scobj_hpath}/fast_shutter nxsave true + hsetprop ${scobj_hpath}/fast_shutter oldval UNKNOWN + hsetprop ${scobj_hpath}/fast_shutter klass "collimator" + hsetprop ${scobj_hpath}/fast_shutter nxalias "fast_shutter" + hsetprop ${scobj_hpath}/fast_shutter sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/fast_shutter type "part" + + hfactory ${scobj_hpath}/rough_100 plain user text + hsetprop ${scobj_hpath}/rough_100 read ${ns}::getValue ${scobj_hpath} read_switch_pair {MG @IN[15], @IN[16]} + hsetprop ${scobj_hpath}/rough_100 read_switch_pair ${ns}::read_switch_pair ${scobj_hpath} + hsetprop ${scobj_hpath}/rough_100 write ${ns}::write_switch ${scobj_hpath} noResponse {11} + hsetprop ${scobj_hpath}/rough_100 noResponse ${ns}::noResponse ${scobj_hpath} + hsetprop ${scobj_hpath}/rough_100 check ${ns}::checkrange ${scobj_hpath} + hsetprop ${scobj_hpath}/rough_100 control true + hsetprop ${scobj_hpath}/rough_100 data true + hsetprop ${scobj_hpath}/rough_100 mutable false + hsetprop ${scobj_hpath}/rough_100 nxsave true + hsetprop ${scobj_hpath}/rough_100 values in,out + hsetprop ${scobj_hpath}/rough_100 oldval UNKNOWN + hsetprop ${scobj_hpath}/rough_100 klass "collimator" + hsetprop ${scobj_hpath}/rough_100 nxalias "rough_100" + hsetprop ${scobj_hpath}/rough_100 sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/rough_100 type "part" + + hfactory ${scobj_hpath}/rough_40 plain user text + hsetprop ${scobj_hpath}/rough_40 read ${ns}::getValue ${scobj_hpath} read_switch_pair {MG @IN[13], @IN[14]} + hsetprop ${scobj_hpath}/rough_40 read_switch_pair ${ns}::read_switch_pair ${scobj_hpath} + hsetprop ${scobj_hpath}/rough_40 write ${ns}::write_switch ${scobj_hpath} noResponse {10} + hsetprop ${scobj_hpath}/rough_40 noResponse ${ns}::noResponse ${scobj_hpath} + hsetprop ${scobj_hpath}/rough_40 check ${ns}::checkrange ${scobj_hpath} + hsetprop ${scobj_hpath}/rough_40 control true + hsetprop ${scobj_hpath}/rough_40 data true + hsetprop ${scobj_hpath}/rough_40 mutable false + hsetprop ${scobj_hpath}/rough_40 nxsave true + hsetprop ${scobj_hpath}/rough_40 values in,out + hsetprop ${scobj_hpath}/rough_40 oldval UNKNOWN + hsetprop ${scobj_hpath}/rough_40 klass "collimator" + hsetprop ${scobj_hpath}/rough_40 nxalias "rough_40" + hsetprop ${scobj_hpath}/rough_40 sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/rough_40 type "part" + + hsetprop ${scobj_hpath} data "true" + hsetprop ${scobj_hpath} nxsave "true" + + if {[SplitReply [motor_simulation]]=="false"} { + ${sct_controller} poll ${scobj_hpath}/fast_shutter 1 + ${sct_controller} poll ${scobj_hpath}/rough_100 1 + ${sct_controller} poll ${scobj_hpath}/rough_40 1 + ${sct_controller} write ${scobj_hpath}/rough_100 + ${sct_controller} write ${scobj_hpath}/rough_40 + } + hsetprop ${scobj_hpath} klass instrument +# hook code starts +# hook code ends + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +namespace eval ::scobj::shutters { + namespace export debug_log + namespace export mk_sct_shutters +} + +proc add_shutters {name IP port} { + set catch_status [ catch { + set ns "::scobj::shutters" + ${ns}::debug_log 1 "add_shutters ${name} ${IP} ${port}" + if {[SplitReply [motor_simulation]]=="false"} { + if {[string equal -nocase "aqadapter" "${IP}"]} { + ${ns}::debug_log 1 "makesctcontroller sct_${name} aqadapter ${port}" + makesctcontroller sct_${name} aqadapter ${port} + } else { + ${ns}::debug_log 1 "makesctcontroller sct_${name} dmc2280 ${IP}:${port}" + makesctcontroller sct_${name} dmc2280 ${IP}:${port} + } + } + ${ns}::debug_log 1 "mk_sct_shutters sct_${name} ${name}" + ${ns}::mk_sct_shutters sct_${name} ${name} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +puts stdout "file evaluation of sct_shutters.tcl" +::scobj::shutters::debug_log 1 "file evaluation of sct_shutters.tcl" + +proc ::scobj::shutters::read_config {} { + set catch_status [ catch { + set ns "::scobj::shutters" + ${ns}::debug_log 1 "Processing Config" + dict for {k v} $::config_dict { + ${ns}::debug_log 1 "Inspecting $k:$v" + if { [dict exists $v "driver"] } { + ${ns}::debug_log 1 "Has driver [dict get $v driver]" + if { [dict get $v "driver"] == "shutters" } { + ${ns}::debug_log 1 "Correct driver, enabled = [dict get $v enabled]" + if { [dict get $v enabled] } { + set IP [dict get $v ip] + set PORT [dict get $v port] + set name [dict get $v name] + MakeAsyncProtocol ${name}_protocol + MakeAsyncQueue ${name}_queue ${name}_protocol ${IP} ${PORT} + add_shutters ${name} "aqadapter" ${name}_queue + } + } + } + } + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} +if { [info exists ::config_dict] } { + ::scobj::shutters::read_config +} else { + ::scobj::shutters:debug_log 1 "No config dict" +} diff --git a/site_ansto/instrument/bilby/config/motors/sct_tank.tcl b/site_ansto/instrument/bilby/config/motors/sct_tank.tcl new file mode 100644 index 00000000..ac65b618 --- /dev/null +++ b/site_ansto/instrument/bilby/config/motors/sct_tank.tcl @@ -0,0 +1,282 @@ +# Generated driver for tank +# vim: ft=tcl tabstop=8 softtabstop=2 shiftwidth=2 nocindent smartindent +# + +namespace eval ::scobj::tank { + set debug_threshold 0 +} + +proc ::scobj::tank::debug_log {debug_level debug_string} { + set catch_status [ catch { + if {${debug_level} >= ${::scobj::tank::debug_threshold}} { + set fd [open "/tmp/tank.log" "a"] + set line "[clock format [clock seconds] -format "%T"] ${debug_string}" + puts ${fd} "${line}" + close ${fd} + } + } catch_message ] +} + +# check function for hset change +proc ::scobj::tank::checkrange {tc_root} { + set catch_status [ catch { + debug_log 1 "checkrange tc_root=${tc_root} sct=[sct] target=[sct target]" + set setpoint [sct target] + if { [hpropexists [sct] lowerlimit] } { + set lolimit [sct lowerlimit] + } else { + # lowerlimit not set, use target + set lolimit [sct target] + } + if { [hpropexists [sct] upperlimit] } { + set hilimit [sct upperlimit] + } else { + # upperlimit not set, use target + set hilimit [sct target] + } +# hook code goes here + if { ${setpoint} < ${lolimit} || ${setpoint} > ${hilimit} } { + error "setpoint ${setpoint} violates limits (${lolimit}..${hilimit}) on [sct]" + } + return OK + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to request the read of a parameter on a device +proc ::scobj::tank::getValue {tc_root nextState cmd_str} { + set catch_status [ catch { + debug_log 1 "getValue tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set cmd "${cmd_str}" +# hook code goes here + debug_log 1 "getValue sct send ${cmd}" + if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { + sct send "${cmd}" + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to check the write parameter on a device +proc ::scobj::tank::noResponse {tc_root} { + set catch_status [ catch { + debug_log 1 "noResponse tc_root=${tc_root} sct=[sct] resp=[sct result]" +# hook code goes here + return "idle" + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to parse the read of a parameter on a device +proc ::scobj::tank::read_switch {tc_root} { + set catch_status [ catch { + debug_log 1 "read_switch tc_root=${tc_root} sct=[sct] result=[sct result]" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set data [sct result] + set nextState "idle" + if {[string equal -nocase -length 7 ${data} "ASCERR:"]} { + # the protocol driver has reported an error + sct geterror "${data}" + error "[sct geterror]" + } +# hook code starts + if { [string equal -nocase -length 1 "${data}" "?"] } { + sct geterror "Galil error in: '${data}'" + } else { + set data_list [split [string trim "${data}"]] + if { [llength ${data_list}] > 1 && [lindex ${data_list} end] == ":" } { + set data_list [lrange ${data_list} 0 0] + } + if { [llength ${data_list}] == 1 } { + set left [expr [lindex ${data_list} 0]] + if { ${left} == 1 } { # open + set data "open" + } else { # closed + set data "closed" + } + } else { + sct geterror "Syntax error in: '${data}'=>'${data_list}'" + } + } +# hook code ends + if { [hpropexists [sct] geterror] } { + debug_log 1 "[sct] error: [sct geterror]" + error "[sct geterror]" + } + if { ${data} != [sct oldval] } { + debug_log 1 "[sct] changed to new:${data}, from old:[sct oldval]" + sct oldval ${data} + sct update ${data} + sct utime readtime + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to write a parameter value on a device +proc ::scobj::tank::setValue {tc_root nextState cmd_str} { + set catch_status [ catch { + debug_log 1 "setValue tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set par [sct target] + set cmd "${cmd_str}${par}" +# hook code goes here + if { [hpropexists [sct] driving] } { + if { [hpropexists [sct] writestatus] && [sct writestatus] == "start" } { + sct driving 1 + } + } + debug_log 1 "setValue sct send ${cmd}" + if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { + sct send "${cmd}" + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +proc ::scobj::tank::mk_sct_tank { sct_controller name } { + debug_log 1 "mk_sct_tank for ${name}" + set ns "[namespace current]" + set catch_status [ catch { + + MakeSICSObj ${name} SCT_OBJECT + + sicslist setatt ${name} klass instrument + sicslist setatt ${name} long_name ${name} + + set scobj_hpath /sics/${name} + + hfactory ${scobj_hpath}/limits plain spy none + + hfactory ${scobj_hpath}/limits/forward plain user text + hsetprop ${scobj_hpath}/limits/forward read ${ns}::getValue ${scobj_hpath} read_switch {MG _LFH} + hsetprop ${scobj_hpath}/limits/forward read_switch ${ns}::read_switch ${scobj_hpath} + hsetprop ${scobj_hpath}/limits/forward control true + hsetprop ${scobj_hpath}/limits/forward data true + hsetprop ${scobj_hpath}/limits/forward mutable false + hsetprop ${scobj_hpath}/limits/forward nxsave true + hsetprop ${scobj_hpath}/limits/forward oldval UNKNOWN + hsetprop ${scobj_hpath}/limits/forward sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/limits/forward type "part" + hsetprop ${scobj_hpath}/limits/forward nxalias "${name}_limits_forward" + + hfactory ${scobj_hpath}/limits/reverse plain user text + hsetprop ${scobj_hpath}/limits/reverse read ${ns}::getValue ${scobj_hpath} read_switch {MG _LRH} + hsetprop ${scobj_hpath}/limits/reverse read_switch ${ns}::read_switch ${scobj_hpath} + hsetprop ${scobj_hpath}/limits/reverse control true + hsetprop ${scobj_hpath}/limits/reverse data true + hsetprop ${scobj_hpath}/limits/reverse mutable false + hsetprop ${scobj_hpath}/limits/reverse nxsave true + hsetprop ${scobj_hpath}/limits/reverse oldval UNKNOWN + hsetprop ${scobj_hpath}/limits/reverse sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/limits/reverse type "part" + hsetprop ${scobj_hpath}/limits/reverse nxalias "${name}_limits_reverse" + + if {[SplitReply [motor_simulation]]=="false"} { + ${sct_controller} poll ${scobj_hpath}/limits/forward 1 + ${sct_controller} poll ${scobj_hpath}/limits/reverse 1 + } + + hfactory ${scobj_hpath}/switches plain spy none + + hfactory ${scobj_hpath}/switches/forward plain user text + hsetprop ${scobj_hpath}/switches/forward read ${ns}::getValue ${scobj_hpath} read_switch {MG @IN[5]} + hsetprop ${scobj_hpath}/switches/forward read_switch ${ns}::read_switch ${scobj_hpath} + hsetprop ${scobj_hpath}/switches/forward control true + hsetprop ${scobj_hpath}/switches/forward data true + hsetprop ${scobj_hpath}/switches/forward mutable false + hsetprop ${scobj_hpath}/switches/forward nxsave true + hsetprop ${scobj_hpath}/switches/forward oldval UNKNOWN + hsetprop ${scobj_hpath}/switches/forward sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/switches/forward type "part" + hsetprop ${scobj_hpath}/switches/forward nxalias "${name}_switches_forward" + + hfactory ${scobj_hpath}/switches/reverse plain user text + hsetprop ${scobj_hpath}/switches/reverse read ${ns}::getValue ${scobj_hpath} read_switch {MG @IN[6]} + hsetprop ${scobj_hpath}/switches/reverse read_switch ${ns}::read_switch ${scobj_hpath} + hsetprop ${scobj_hpath}/switches/reverse control true + hsetprop ${scobj_hpath}/switches/reverse data true + hsetprop ${scobj_hpath}/switches/reverse mutable false + hsetprop ${scobj_hpath}/switches/reverse nxsave true + hsetprop ${scobj_hpath}/switches/reverse oldval UNKNOWN + hsetprop ${scobj_hpath}/switches/reverse sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/switches/reverse type "part" + hsetprop ${scobj_hpath}/switches/reverse nxalias "${name}_switches_reverse" + + if {[SplitReply [motor_simulation]]=="false"} { + ${sct_controller} poll ${scobj_hpath}/switches/forward 1 + ${sct_controller} poll ${scobj_hpath}/switches/reverse 1 + } + hsetprop ${scobj_hpath} klass instrument +# hook code starts +# hook code ends + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +namespace eval ::scobj::tank { + namespace export debug_log + namespace export mk_sct_tank +} + +proc add_tank {name IP port} { + set catch_status [ catch { + set ns "::scobj::tank" + ${ns}::debug_log 1 "add_tank ${name} ${IP} ${port}" + if {[SplitReply [motor_simulation]]=="false"} { + if {[string equal -nocase "aqadapter" "${IP}"]} { + ${ns}::debug_log 1 "makesctcontroller sct_${name} aqadapter ${port}" + makesctcontroller sct_${name} aqadapter ${port} + } else { + ${ns}::debug_log 1 "makesctcontroller sct_${name} dmc2280 ${IP}:${port}" + makesctcontroller sct_${name} dmc2280 ${IP}:${port} + } + } + ${ns}::debug_log 1 "mk_sct_tank sct_${name} ${name}" + ${ns}::mk_sct_tank sct_${name} ${name} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +puts stdout "file evaluation of sct_tank.tcl" +::scobj::tank::debug_log 1 "file evaluation of sct_tank.tcl" + +proc ::scobj::tank::read_config {} { + set catch_status [ catch { + set ns "::scobj::tank" + ${ns}::debug_log 1 "Processing Config" + dict for {k v} $::config_dict { + ${ns}::debug_log 1 "Inspecting $k:$v" + if { [dict exists $v "driver"] } { + ${ns}::debug_log 1 "Has driver [dict get $v driver]" + if { [dict get $v "driver"] == "tank" } { + ${ns}::debug_log 1 "Correct driver, enabled = [dict get $v enabled]" + if { [dict get $v enabled] } { + set IP [dict get $v ip] + set PORT [dict get $v port] + set name [dict get $v name] + MakeAsyncProtocol ${name}_protocol + MakeAsyncQueue ${name}_queue ${name}_protocol ${IP} ${PORT} + add_tank ${name} "aqadapter" ${name}_queue + } + } + } + } + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} +if { [info exists ::config_dict] } { + ::scobj::tank::read_config +} else { + ::scobj::tank:debug_log 1 "No config dict" +} diff --git a/site_ansto/instrument/bilby/config/motors/shutters.sct b/site_ansto/instrument/bilby/config/motors/shutters.sct new file mode 100644 index 00000000..46c428b4 --- /dev/null +++ b/site_ansto/instrument/bilby/config/motors/shutters.sct @@ -0,0 +1,92 @@ +# +# Simple driver generator for the non-motor galil controls on mc4 +# vim: ts=8 sts=2 sw=2 expandtab autoindent smartindent nocindent +# +driver shutters = { + vendor = galil; device = mc4; protocol = dmc2280; + class = instrument + simulation_group = motor_simulation +# +# Unnamed group has variables at device level +# +# +# The named group is at the device level, variables below that +# + group = { + type = text + priv = user + group_property 'data' = 'true' + group_property 'nxsave' = 'true' + property 'type' = 'part' + property 'klass' = 'collimator' + property 'sdsinfo' = '::nexus::scobj::sdsinfo' + var fast_shutter = { + readable = 1 + read_command = 'MG @IN[5], @IN[6]' + read_function = read_switch_pair + property 'nxalias' = 'fast_shutter' + } + var rough_40 = { + readable = 1; + read_function = read_switch_pair; + read_command = 'MG @IN[13], @IN[14]' + writeable = 1 + write_function = write_switch; + write_command = '10' + allowed = 'in,out' + property 'nxalias' = 'rough_40' + } + var rough_100 = { + readable = 1; + read_function = read_switch_pair; + read_command = 'MG @IN[15], @IN[16]' + writeable = 1 + write_function = write_switch; + write_command = '11' + allowed = 'in,out' + property 'nxalias' = 'rough_100' + } + }; + +# +# Code lines start with '@' which is stripped before being emitted +# The code is emitted at the appropriate place in the given function +# + code read_function read_switch_pair = { +@ if { [string equal -nocase -length 1 "${data}" "?"] } { +@ sct geterror "Galil error in: '${data}'" +@ } else { +@ set data_list [split [string trim "${data}"]] +@ if { [llength ${data_list}] > 2 && [lindex ${data_list} end] == ":" } { +@ set data_list [lrange ${data_list} 0 1] +@ } +@ if { [llength ${data_list}] == 2 } { +@ set left [expr [lindex ${data_list} 0]] +@ set right [expr [lindex ${data_list} 1]] +@ if { ${left} == 1 && ${right} == 0 } { # open +@ set data "out" +@ } elseif { ${left} == 0 && ${right} == 1 } { # closed +@ set data "in" +@ } else { # indeterminate +@ set data "moving" +@ } +@ } else { +@ sct geterror "Syntax error in: '${data}'=>'${data_list}'" +@ } +@ } + } + code write_function write_switch = { +@ if { [string equal -nocase -length 2 "${par}" "in"] } { +@ set cmd "SB${cmd_str}" +@ } elseif { [string equal -nocase -length 2 "${par}" "out"] } { +@ set cmd "CB${cmd_str}" +@ } else { +@ sct geterror "Value error: '${par}' not in ('in', 'out')" +@ } + } +# +# This code is after database creation +# + code mkDriver = { + } +}; diff --git a/site_ansto/instrument/bilby/config/motors/sicsmot_attlist.csv b/site_ansto/instrument/bilby/config/motors/sicsmot_attlist.csv new file mode 100644 index 00000000..c00fed42 --- /dev/null +++ b/site_ansto/instrument/bilby/config/motors/sicsmot_attlist.csv @@ -0,0 +1,203 @@ +ap1_absenchome,73952.0000 +ap1_accel,1.4062 +ap1_decel,1.4062 +ap1_fwd_lim,105.0183 +ap1_home,0.0000 +ap1_rev_lim,0.0000 +ap1_speed,1.4062 +ap2_absenchome,54293.0000 +ap2_accel,1.4062 +ap2_decel,1.4062 +ap2_fwd_lim,113.0713 +ap2_home,0.0000 +ap2_rev_lim,0.0000 +ap2_speed,1.4062 +ap3_absenchome,13644.0000 +ap3_accel,1.4062 +ap3_decel,1.4062 +ap3_fwd_lim,104.2932 +ap3_home,0.0000 +ap3_rev_lim,0.0000 +ap3_speed,1.4062 +ap4_absenchome,5666.0000 +ap4_accel,1.4062 +ap4_decel,1.4062 +ap4_fwd_lim,108.6768 +ap4_home,0.0000 +ap4_rev_lim,0.0000 +ap4_speed,1.4062 +ap5_absenchome,72824.0000 +ap5_accel,1.4062 +ap5_decel,1.4062 +ap5_fwd_lim,104.0186 +ap5_home,0.0000 +ap5_rev_lim,0.0000 +ap5_speed,1.4062 +ap6_absenchome,72115.0000 +ap6_accel,1.4062 +ap6_decel,1.4062 +ap6_fwd_lim,110.7422 +ap6_home,0.0000 +ap6_rev_lim,0.0000 +ap6_speed,1.4062 +ap7_absenchome,74299.0000 +ap7_accel,1.4062 +ap7_decel,1.4062 +ap7_fwd_lim,104.6228 +ap7_home,0.0000 +ap7_rev_lim,0.0000 +ap7_speed,1.4062 +ap8_absenchome,6791.0000 +ap8_accel,1.4062 +ap8_decel,1.4062 +ap8_fwd_lim,112.1924 +ap8_home,0.0000 +ap8_rev_lim,0.0000 +ap8_speed,1.4062 +att_absenchome,33394989.0000 +att_accel,3.6000 +att_decel,3.6000 +att_fwd_lim,273.7734 +att_home,0.0000 +att_rev_lim,0.0000 +att_speed,3.6000 +bs3_absenchome,351548.0000 +bs3_accel,5.6250 +bs3_decel,5.6250 +bs3_fwd_lim,-69.6162 +bs3_home,0.0000 +bs3_rev_lim,0.0000 +bs3_speed,5.6250 +cdd_absenchome,4159255.0000 +cdd_accel,0.2500 +cdd_decel,0.2500 +cdd_fwd_lim,349.7198 +cdd_home,0.0000 +cdd_rev_lim,0.0000 +cdd_speed,1.5000 +cdl_absenchome,5769621.0000 +cdl_accel,0.2500 +cdl_decel,0.2500 +cdl_fwd_lim,356.9644 +cdl_home,0.0000 +cdl_rev_lim,0.0000 +cdl_speed,1.5000 +cdr_absenchome,4371043.0000 +cdr_accel,0.2500 +cdr_decel,0.2500 +cdr_fwd_lim,358.0801 +cdr_home,0.0000 +cdr_rev_lim,0.0000 +cdr_speed,1.5000 +cdu_absenchome,21804679.0000 +cdu_accel,0.2500 +cdu_decel,0.2500 +cdu_fwd_lim,356.9028 +cdu_home,0.0000 +cdu_rev_lim,0.0000 +cdu_speed,1.5000 +col1_absenchome,3902.0000 +col1_accel,0.3333 +col1_decel,0.3333 +col1_fwd_lim,270.2969 +col1_home,0.0000 +col1_rev_lim,0.0000 +col1_speed,0.6667 +col2_absenchome,9598.0000 +col2_accel,0.3333 +col2_decel,0.3333 +col2_fwd_lim,270.9961 +col2_home,0.0000 +col2_rev_lim,0.0000 +col2_speed,0.6667 +col3_absenchome,29466.0000 +col3_accel,0.3333 +col3_decel,0.3333 +col3_fwd_lim,268.1104 +col3_home,0.0000 +col3_rev_lim,0.0000 +col3_speed,0.6667 +col4_absenchome,12861.0000 +col4_accel,0.3333 +col4_decel,0.3333 +col4_fwd_lim,269.4302 +col4_home,0.0000 +col4_rev_lim,0.0000 +col4_speed,0.6667 +col5_absenchome,377801.0000 +col5_accel,0.3333 +col5_decel,0.3333 +col5_fwd_lim,268.7666 +col5_home,0.0000 +col5_rev_lim,0.0000 +col5_speed,0.6667 +col6_absenchome,191508.0000 +col6_accel,0.3333 +col6_decel,0.3333 +col6_fwd_lim,271.2998 +col6_home,0.0000 +col6_rev_lim,0.0000 +col6_speed,0.6667 +col7_absenchome,24810.0000 +col7_accel,0.3333 +col7_decel,0.3333 +col7_fwd_lim,269.9331 +col7_home,0.0000 +col7_rev_lim,0.0000 +col7_speed,0.6667 +col8_absenchome,12893.0000 +col8_accel,0.3333 +col8_decel,0.3333 +col8_fwd_lim,267.6748 +col8_home,0.0000 +col8_rev_lim,0.0000 +col8_speed,0.6667 +det_absenchome,0.0000 +det_accel,6.4103 +det_decel,6.4103 +det_fwd_lim,0.0000 +det_home,0.0000 +det_rev_lim,0.0000 +det_speed,25.6410 +sdh_absenchome,4166803.0000 +sdh_fwd_lim,242.2931 +sdh_home,0.0000 +sdh_maxaccel,1.0000 +sdh_maxdecel,1.0000 +sdh_maxspeed,1.0000 +sdh_rev_lim,0.0000 +ss1d_absenchome,33398312.0000 +ss1d_accel,0.5000 +ss1d_decel,0.5000 +ss1d_fwd_lim,114.3299 +ss1d_home,0.0000 +ss1d_rev_lim,0.0000 +ss1d_speed,0.5000 +ss1l_absenchome,31524107.0000 +ss1l_accel,0.5000 +ss1l_decel,0.5000 +ss1l_fwd_lim,67.9708 +ss1l_home,0.0000 +ss1l_rev_lim,0.0000 +ss1l_speed,0.5000 +ss1r_absenchome,32248545.0000 +ss1r_accel,0.5000 +ss1r_decel,0.5000 +ss1r_fwd_lim,71.6127 +ss1r_home,0.0000 +ss1r_rev_lim,0.0000 +ss1r_speed,0.5000 +ss1u_absenchome,33297987.0000 +ss1u_accel,0.5000 +ss1u_decel,0.5000 +ss1u_fwd_lim,113.7317 +ss1u_home,0.0000 +ss1u_rev_lim,0.0000 +ss1u_speed,0.5000 +vs_absenchome,3789130.0000 +vs_accel,0.4000 +vs_decel,1.3333 +vs_fwd_lim,275.2637 +vs_home,0.0000 +vs_rev_lim,0.0000 +vs_speed,1.3333 diff --git a/site_ansto/instrument/bilby/config/motors/tank.sct b/site_ansto/instrument/bilby/config/motors/tank.sct new file mode 100644 index 00000000..4f7cf468 --- /dev/null +++ b/site_ansto/instrument/bilby/config/motors/tank.sct @@ -0,0 +1,69 @@ +# +# Simple driver generator for the non-motor galil controls on mc8 +# vim: ts=8 sts=2 sw=2 expandtab autoindent smartindent nocindent +# +driver tank = { + vendor = galil; device = mc8; protocol = dmc2280; + class = instrument + simulation_group = motor_simulation +# +# Unnamed group has variables at device level +# +# +# The named group is at the device level, variables below that +# + group switches = { + type = text; + priv = user; + readable = 1; + read_function = read_switch; + var forward = { + read_command = 'MG @IN[5]' + } + var reverse = { + read_command = 'MG @IN[6]' + } + }; + group limits = { + type = text; + priv = user; + readable = 1; + read_function = read_switch; + var forward = { + read_command = 'MG _LFH' + } + var reverse = { + read_command = 'MG _LRH' + } + }; + +# +# Code lines start with '@' which is stripped before being emitted +# The code is emitted at the appropriate place in the given function +# + code read_function read_switch = { +@ if { [string equal -nocase -length 1 "${data}" "?"] } { +@ sct geterror "Galil error in: '${data}'" +@ } else { +@ set data_list [split [string trim "${data}"]] +@ if { [llength ${data_list}] > 1 && [lindex ${data_list} end] == ":" } { +@ set data_list [lrange ${data_list} 0 0] +@ } +@ if { [llength ${data_list}] == 1 } { +@ set left [expr [lindex ${data_list} 0]] +@ if { ${left} == 1 } { # open +@ set data "open" +@ } else { # closed +@ set data "closed" +@ } +@ } else { +@ sct geterror "Syntax error in: '${data}'=>'${data_list}'" +@ } +@ } + } +# +# This code is after database creation +# + code mkDriver = { + } +}; diff --git a/site_ansto/instrument/bilby/config/motors/userdef_attlist.csv b/site_ansto/instrument/bilby/config/motors/userdef_attlist.csv new file mode 100644 index 00000000..2245989b --- /dev/null +++ b/site_ansto/instrument/bilby/config/motors/userdef_attlist.csv @@ -0,0 +1,24 @@ +col1_maxaccel,0.75 +col1_maxdecel,0.75 +col1_maxspeed,0.75 +col2_maxaccel,0.75 +col2_maxdecel,0.75 +col2_maxspeed,0.75 +col3_maxaccel,0.75 +col3_maxdecel,0.75 +col3_maxspeed,0.75 +col4_maxaccel,0.75 +col4_maxdecel,0.75 +col4_maxspeed,0.75 +col5_maxaccel,0.75 +col5_maxdecel,0.75 +col5_maxspeed,0.75 +col6_maxaccel,0.75 +col6_maxdecel,0.75 +col6_maxspeed,0.75 +col7_maxaccel,0.75 +col7_maxdecel,0.75 +col7_maxspeed,0.75 +col8_maxaccel,0.75 +col8_maxdecel,0.75 +col8_maxspeed,0.75 diff --git a/site_ansto/instrument/bilby/config/nexus/nxscripts.tcl b/site_ansto/instrument/bilby/config/nexus/nxscripts.tcl new file mode 100644 index 00000000..5f4166ab --- /dev/null +++ b/site_ansto/instrument/bilby/config/nexus/nxscripts.tcl @@ -0,0 +1,4 @@ +source $cfPath(nexus)/nxscripts_common_1.tcl +proc ::nexus::isc_initialize {} { + ::nexus::ic_initialize +} diff --git a/site_ansto/instrument/bilby/config/optics/README.TXT b/site_ansto/instrument/bilby/config/optics/README.TXT new file mode 100644 index 00000000..bd84ac14 --- /dev/null +++ b/site_ansto/instrument/bilby/config/optics/README.TXT @@ -0,0 +1 @@ +Optical Components: Neutron Guides, Apertures, Polariser, Focussing Lenses and Prisms diff --git a/site_ansto/instrument/bilby/config/optics/aperture_configuration.tcl b/site_ansto/instrument/bilby/config/optics/aperture_configuration.tcl new file mode 100644 index 00000000..d795ba10 --- /dev/null +++ b/site_ansto/instrument/bilby/config/optics/aperture_configuration.tcl @@ -0,0 +1,94 @@ +namespace eval optics { + array set AttRotLookupTable { + 0 { 0.0 1 } + 30 { 1.3 0.498782 } + 60 { 3.3 0.176433 } + 90 { 4.9 0.0761367 } + 120 { 6.4 0.0353985 } + 150 { 8.3 0.0137137 } + 180 { 9.6 0.00614167 } + 210 {11.2 0.00264554 } + 240 {13.1 0.000994504 } + 270 {15.0 0.000358897 } + 300 {18.0 7.2845e-05 } + 330 {25.0 1.67827e-06 } + } + + array set EApLookupTable { + 0 { 5 circ} + 30 {10 circ} + 60 {20 circ} + 90 {30 circ} + 120 {40 circ} + 150 {50 circ} + 180 {50 squ } + 210 {open open} + 240 {open open} + 270 {open open} + 300 {open open} + 330 {open open} + } +} + +proc ::optics::AttRotLookup {angle column tol} { + variable AttRotLookupTable + + set catch_status [ catch { + set foundit false + foreach vangle [array names AttRotLookupTable] { + if {$vangle >= [expr {$angle-$tol}] && $vangle <= [expr {$angle+$tol}]} { + set foundit true + break + } + } + if {$foundit == true} { + switch $column { + "plex" { set index 0 } + "attfactor" { set index 1 } + default { error "$column is unknown, allowed values are plex or attfactor" } + } + return [lindex $AttRotLookupTable($vangle) $index] + } else { + return -1 + } + } message ] + handle_exception $catch_status $message +} + +proc ::optics::EApLookUp {angle param tol} { + variable EApLookupTable + + set foundit false + if [ catch { + if {$param == "size"} { + set cgf [SplitReply [GuideConfig]] + if {[string first $cgf "g1 g2 g3 g4 g5 g6 g7 g8 g9 p1 p2 p3 p4 p5 p6 p7 p8 p9"] != -1} { + return 50 + } + } + switch $param { + "size" {set index 0} + "shape" {set index 1} + default { + error "ERROR: Invalid lookup parameter $param" + } + } + foreach vangle [array names EApLookupTable] { + if {$vangle >= [expr {$angle-$tol}] && $vangle <= [expr {$angle+$tol}]} { + set foundit true + break + } + } + if {$foundit == true} { + return [lindex $EApLookupTable($vangle) $index] + } else { + switch $param { + "size" {return 0} + "shape" {return "UNKNOWN"} + } + } + } message ] { + if {$::errorCode == "NONE"} {return $message} + return -code error "$message" + } +} diff --git a/site_ansto/instrument/bilby/config/optics/guide_configuration.tcl b/site_ansto/instrument/bilby/config/optics/guide_configuration.tcl new file mode 100644 index 00000000..a66f2b84 --- /dev/null +++ b/site_ansto/instrument/bilby/config/optics/guide_configuration.tcl @@ -0,0 +1,66 @@ +## +# @file +# A guide configuration table where each line describes the setup +# for a mode of operation. +# The table will have a corresponding interpretation list which provides +# commands to setup the instrument. + +namespace eval optics { +## +# @brief These arrays map the component identifiers (G, MT, etc) to the +# position index for each guide motor (c1, c2 ... c9) + array set c1_map {G 1 MT 2 P 3} + array set c2_map {MT 1 G 2 A 3} + array set c3_map {MT 1 G 2 A 3} + array set c4_map {MT 1 G 2 A 3} + array set c5_map {MT 1 G 2 A 3} + array set c6_map {MT 1 G 2 A 3} + array set c7_map {MT 1 G 2 A 3} + array set c8_map {MT 1 G 2 A 3} + array set c9_map {L 1 MT 2 G 3 A 4 LP 5} + +# The guide configuration table is indexed by a configuration +# identifier (ga, mt, lp, etc). Each row has two elements, +# 1. A list of components selected for each guide (MT A ... etc) +# 2. The entrance aperature position in mm +# Eg $guide_configuration(p2) returns the following list +# {{P G A A A A A A A } 6934} +array set guide_configuration { + ga {{MT A A A A A A A A } 675} + mt {{MT MT MT MT MT MT MT MT MT} 675} + lp {{MT MT MT MT MT MT MT MT LP} 675} + lens {{MT A A A A A A A L } 675} + p1 {{P A MT MT MT MT MT MT MT} 4621} + p1lp {{P A MT MT MT MT MT MT LP} 4621} + p1lens {{P A MT MT MT MT MT MT L } 4621} + g1 {{G A A A A A A A A } 4929} + p2 {{P G A A A A A A A } 6934} + g2 {{G G A A A A A A A } 6934} + p3 {{P G G A A A A A A } 8949} + g3 {{G G G A A A A A A } 8949} + p4 {{P G G G A A A A A } 10955} + g4 {{G G G G A A A A A } 10955} + p5 {{P G G G G A A A A } 12943} + g5 {{G G G G G A A A A } 12943} + p6 {{P G G G G G A A A } 14970} + g6 {{G G G G G G A A A } 14970} + p7 {{P G G G G G G A A } 16971} + g7 {{G G G G G G G A A } 16971} + p8 {{P G G G G G G G A } 18937} + g8 {{G G G G G G G G A } 18937} + p9 {{P G G G G G G G G } 19925} + g9 {{G G G G G G G G G } 19925} +} + +# This list maps the motor names to columns of the +# guide_configuration table. +set guide_configuration_columns { + c1 c2 c3 c4 c5 c6 c7 c8 c9 +} + +} + +namespace eval optics { + variable guide_configuration + variable guide_configuration_columns +} diff --git a/site_ansto/instrument/bilby/config/optics/optics.tcl b/site_ansto/instrument/bilby/config/optics/optics.tcl new file mode 100644 index 00000000..766cd383 --- /dev/null +++ b/site_ansto/instrument/bilby/config/optics/optics.tcl @@ -0,0 +1,2 @@ +fileeval $cfPath(optics)/guide_configuration.tcl +fileeval $cfPath(optics)/aperture_configuration.tcl diff --git a/site_ansto/instrument/bilby/config/plc/plc.tcl b/site_ansto/instrument/bilby/config/plc/plc.tcl new file mode 100644 index 00000000..739abdb7 --- /dev/null +++ b/site_ansto/instrument/bilby/config/plc/plc.tcl @@ -0,0 +1,7 @@ +set sim_mode [SplitReply [plc_simulation]] +if {$sim_mode == "false"} { + MakeAsyncQueue plc_chan SafetyPLC [dict get $::PLC_HOSTPORT HOST] [dict get $::PLC_HOSTPORT PORT] + MakeSafetyPLC plc plc_chan 0 +} +source $cfPath(plc)/plc_common_1.tcl + diff --git a/site_ansto/instrument/bilby/config/scan/scan.tcl b/site_ansto/instrument/bilby/config/scan/scan.tcl new file mode 100644 index 00000000..dd396f62 --- /dev/null +++ b/site_ansto/instrument/bilby/config/scan/scan.tcl @@ -0,0 +1,6 @@ +source $cfPath(scan)/scan_common_1.tcl +proc ::scan::pre_hmm_scan_prepare {} {} + +proc ::scan::isc_initialize {} { + ::scan::ic_initialize +} diff --git a/site_ansto/instrument/bilby/hostport_config.tcl b/site_ansto/instrument/bilby/hostport_config.tcl new file mode 100644 index 00000000..cbfb6b23 --- /dev/null +++ b/site_ansto/instrument/bilby/hostport_config.tcl @@ -0,0 +1,52 @@ +# MOTOR HOST AND PORT +foreach {mc host port} { + MC1 mc1-bilby 1034 + MC2 mc2-bilby 1034 + MC3 mc3-bilby 1034 + MC4 mc4-bilby 1034 + MC5 mc5-bilby 1034 + MC6 mc6-bilby 1034 + MC7 mc7-bilby 1034 + MC8 mc8-bilby 1034 +} { + dict set MOTOR_HOSTPORT $mc HOST $host + dict set MOTOR_HOSTPORT $mc PORT $port +} + +# BEAM MONITOR HOST AND PORT +foreach {bm host port} { + MONITOR_1 das1-bilby 30000 +} { + dict set MONITOR_HOSTPORT $bm HOST $host + dict set MONITOR_HOSTPORT $bm PORT $port +} + +# HISTOGRAM SERVER HOST AND PORT +# TODO HV control +foreach {key host port} { + HMM das1-bilby.nbi.ansto.gov.au 8080 + HMSTAT das1-bilby.nbi.ansto.gov.au 8081 + ORDELA 137.157.202.71 4001 + NHQ200 ca1-bilby 4002 +} { + dict set HISTMEM_HOSTPORT $key HOST $host + dict set HISTMEM_HOSTPORT $key PORT $port +} + +# VELOCITY SELECTOR HOST AND PORT +# TODO +foreach {key host port} { + NVS IP 10000 +} { + dict set VELSEL_HOSTPORT $key HOST $host + dict set VELSEL_HOSTPORT $key PORT $port +} + +# Safety Interlock System +# TODO +foreach {host port} { + IP PORT +} { + dict set PLC_HOSTPORT HOST $host + dict set PLC_HOSTPORT PORT $port +} diff --git a/site_ansto/instrument/bilby/hostport_config_test.tcl b/site_ansto/instrument/bilby/hostport_config_test.tcl new file mode 100644 index 00000000..e96d125c --- /dev/null +++ b/site_ansto/instrument/bilby/hostport_config_test.tcl @@ -0,0 +1,52 @@ +# Specify NONE for HOST and PORT if there is no fake device to talk to. + +# TEST MOTOR HOST AND PORT +foreach {key host port} { + MC1 localhost 63030 + MC2 localhost 63031 + MC3 localhost 63032 + MC4 localhost 63033 + MC5 localhost 63034 + MC6 localhost 63035 + MC7 localhost 63036 + MC8 localhost 63037 +} { + dict set MOTOR_HOSTPORT $key HOST $host + dict set MOTOR_HOSTPORT $key PORT $port +} + +# TEST BEAM MONITOR HOST AND PORT +foreach {key host port} { + MONITOR_1 localhost 30000 +} { + dict set MONITOR_HOSTPORT $key HOST $host + dict set MONITOR_HOSTPORT $key PORT $port +} + +# TEST HISTOGRAM SERVER HOST AND PORT +foreach {key host port} { + HMM das1-test.nbi.ansto.gov.au 8080 + HMSTAT das1-test.nbi.ansto.gov.au 8081 + ORDELA localhost 4001 + NHQ200 localhost 4002 +} { + dict set HISTMEM_HOSTPORT $key HOST $host + dict set HISTMEM_HOSTPORT $key PORT $port +} + +# VELOCITY SELECTOR HOST AND PORT +foreach {key host port} { + NVS localhost 10000 +} { + dict set VELSEL_HOSTPORT $key HOST $host + dict set VELSEL_HOSTPORT $key PORT $port +} + +# Safety Interlock System +# TODO +foreach {host port} { + NONE NONE +} { + dict set PLC_HOSTPORT HOST $host + dict set PLC_HOSTPORT PORT $port +} diff --git a/site_ansto/instrument/bilby/runsics_def.py b/site_ansto/instrument/bilby/runsics_def.py new file mode 100644 index 00000000..45b2f839 --- /dev/null +++ b/site_ansto/instrument/bilby/runsics_def.py @@ -0,0 +1,3 @@ +inst_user = 'bilby_sics' +inst_name = 'bilby' +inst_config = 'bilby_configuration.tcl' diff --git a/site_ansto/instrument/config/anticollider/anticollider_common.tcl b/site_ansto/instrument/config/anticollider/anticollider_common.tcl index 76d27224..81e08ad0 100644 --- a/site_ansto/instrument/config/anticollider/anticollider_common.tcl +++ b/site_ansto/instrument/config/anticollider/anticollider_common.tcl @@ -1,10 +1,6 @@ # Author: Ferdi Franceschini (ffr@ansto.gov.au) # TODO Handle sequencing when simultaneously moving multiple axes -# TODO Handle functional dependencies (just write your own tcl script) -# or get the generic acscript to call a user proc -# FIXME The anticollider module does not report the error messages from the -# anticollision script, we currently get around this by using broadcast. AntiCollisionInstall namespace eval anticollider { @@ -13,11 +9,41 @@ namespace eval anticollider { array unset ::anticollider::veto_region array set ::anticollider::veto_region "" +# Don't show 'acscript' call on error. This is done by the anticollider +# module. +proc handle_acscript_exception {status message args} { + switch $status { + 0 { + # TCL_OK, This is raised when you just drop out of the + # bottom of a 'catch' command. + return -code ok + } + 1 { + # TCL_ERROR + return -code error "$message: $args" + } + 2 { + # TCL_RETURN + return -code return "$message" + } + 3 { + # TCL_BREAK + return -code break + } + 4 { + # TCL_CONTINUE + return -code continue + } + default { + # Propogate user defined return codes with message + return -code $status "$message" + } + } +} ## # @brief Load an anticollider script proc ::anticollider::loadscript {args} { - variable prog - set prog "" + variable veto_rules set fh [open $::cfPath(anticollider)/[lindex $args 0] RDONLY ] while {[gets $fh line] >= 0} { @@ -25,7 +51,7 @@ proc ::anticollider::loadscript {args} { if [regexp {^\s*$|^ *#} $line] { continue } - lappend prog $line + lappend veto_rules $line } } @@ -33,7 +59,7 @@ proc ::anticollider::loadscript {args} { # @brief Compile compile an anticollider declaration into a veto region table # for the anticollider script. # -# @param vprog, an anticollider declaration as a list of quote enclosed lines. +# @param veto_rules, an anticollider declaration as a list of quote enclosed lines. # @return Generates the ::anticollider::veto_region lookup table. # # Example\n @@ -44,14 +70,16 @@ proc ::anticollider::loadscript {args} { # for sphi forbid { {0 5} {10 15} } when schi in { {5 10} {15 20} }\n # forbid {-inf 5} when mtth in {0 10} for sphi\n # forbid {0 10} for samx whenall { samrot in {0 5} samy in {0 15} }\n -proc ::anticollider::genveto {vprog} { +proc ::anticollider::genveto {veto_rules} { variable veto_region array unset veto_region set lnum 1 - foreach line $vprog { + foreach line $veto_rules { array unset vp array set vp $line + clientput "::anticollider::veto_rule: $line" + if [info exists vp(whenall)] { foreach {mot in range} $vp(whenall) { # if {[llength [join $range]] != 2} { @@ -88,16 +116,14 @@ proc ::anticollider::enable {args} { # # The ::anticollider::veto_region is a hash indexed by the names of the motors # which have been registered with the anticollision module. -proc ::anticollider::acscript {args} { +proc ::anticollider::veto_region_acscript {args} { variable veto_region - if {[::anticollider::enable $args] == "false"} { - foreach {regmot target} $args { - anticollision add 0 $regmot $target - } - return - } + set catch_status [ catch { foreach {regmot target} $args { + if { ! [info exists veto_region($regmot)] } { + continue + } foreach row $veto_region($regmot) { if { [lindex $row 1] == "@and"} { set forbid [lindex $row 0] @@ -116,7 +142,6 @@ proc ::anticollider::acscript {args} { } else { foreach {min max} $forbid {} if {$min <= $target && $target <= $max} { - broadcast "ERROR:The range ($forbid) is forbidden for $regmot when [lindex $row 2]" error "ERROR:The range ($forbid) is forbidden for $regmot when [lindex $row 2]" } } @@ -126,17 +151,14 @@ proc ::anticollider::acscript {args} { if {$obstrange == "@all"} { foreach {min max} [join $forbidden_range] { if {$min <= $target && $target <= $max} { - broadcast "ERROR: $regmot target ($target) is in the forbidden region ($forbidden_range)" error "ERROR: $regmot target ($target) is in the forbidden region ($forbidden_range)" } } } else { - broadcast "ERROR: veto table must use @all with @any" error "ERROR: veto table must use @all with @any" } } else { if {$obstrange == "@all"} { - broadcast "ERROR: veto table must use @any with @all" error "ERROR: veto table must use @any with @all" } else { foreach {lower upper} [join $obstrange] { @@ -144,7 +166,6 @@ proc ::anticollider::acscript {args} { if {$lower <= $pos && $pos <= $upper} { foreach {min max} [join $forbidden_range] { if {$min <= $target && $target <= $max} { - broadcast "ERROR:The range $min to $max is forbidden for $regmot when $obstmot is in this region ($obstrange)" error "ERROR:The range $min to $max is forbidden for $regmot when $obstmot is in this region ($obstrange)" } @@ -156,8 +177,9 @@ proc ::anticollider::acscript {args} { } } } - anticollision add 0 $regmot $target } + } message ] + handle_exception $catch_status $message } ## @@ -166,16 +188,37 @@ proc ::anticollider::init {} { variable evp variable veto_region - if [ catch { - ::anticollider::genveto $::anticollider::prog + set catch_status [ catch { + if { ![info exists ::anticollider::veto_rules] } { + return + } + clientput Load anticollider rules: + if { [info procs ::anticollider::load_acrules] == "::anticollider::load_acrules" } { + ::anticollider::load_acrules + } + ::anticollider::genveto $::anticollider::veto_rules foreach motor [array names veto_region] { anticollision register $motor } - } message ] { - clientput [info level 0] ERROR: $message - if {$::errorCode=="NONE"} {return $message} - return -code error $message - } + } message ] + handle_exception $catch_status $message +} + +lappend ::anticollider::scripts ::anticollider::veto_region_acscript +proc ::anticollider::acscript {args} { + set catch_status [ catch { + if {[::anticollider::enable $args] == "false"} { + return + } else { + foreach {regmot target} $args { + anticollision add 0 $regmot $target + } + } + foreach script $::anticollider::scripts { + $script {*}$args + } + } message ] + handle_acscript_exception $catch_status $message } publish ::anticollider::acscript user diff --git a/site_ansto/instrument/config/counter/counter_common_1.tcl b/site_ansto/instrument/config/counter/counter_common_1.tcl index a44c0027..a902ca53 100644 --- a/site_ansto/instrument/config/counter/counter_common_1.tcl +++ b/site_ansto/instrument/config/counter/counter_common_1.tcl @@ -60,6 +60,7 @@ proc ::counter::ic_initialize {} { ::utility::macro::getset float monitor_counts {} { + bm status return "monitor_counts = [SplitReply [bm getcounts]]" } sicslist setatt monitor_counts klass monitor @@ -67,6 +68,7 @@ proc ::counter::ic_initialize {} { sicslist setatt monitor_counts mutable true ::utility::macro::getset float monitor_time {} { + bm status return "monitor_time = [SplitReply [bm gettime]]" } sicslist setatt monitor_time klass monitor @@ -77,6 +79,7 @@ proc ::counter::ic_initialize {} { set bm_counts bm${bm_num}_counts set bmon bm${bm_num} ::utility::macro::getset int $bm_counts {} [subst -nocommands { + $bmon status return "[$bmon getcounts]" }] sicslist setatt $bm_counts klass monitor @@ -86,6 +89,7 @@ proc ::counter::ic_initialize {} { set bm_time bm${bm_num}_time set bmon bm${bm_num} ::utility::macro::getset float $bm_time {} [subst -nocommands { + $bmon status return "[$bmon gettime]" }] sicslist setatt $bm_time klass monitor diff --git a/site_ansto/instrument/config/environment/hiden_xcs.sct b/site_ansto/instrument/config/environment/hiden_xcs.sct new file mode 100644 index 00000000..2aeaa292 --- /dev/null +++ b/site_ansto/instrument/config/environment/hiden_xcs.sct @@ -0,0 +1,302 @@ +# +# Simple driver generator for the Hiden Isochema XCS vapour delivery system +# vim: ts=8 sts=2 sw=2 expandtab autoindent smartindent nocindent +# +driver hiden_xcs = { + # driver_property douglas = clowes + vendor = hiden; device = xcs; protocol = std; + class = environment + simulation_group = environment_simulation + add_args = 'terminator {tol 0.5}'; + make_args = 'tol'; + protocol_args = '${terminator}'; +# +# Unnamed group has variables at device level +# + group = { + # group_property douglas = clowes + type = float + priv = user + group_property 'data' = 'true' + group_property 'nxsave' = 'true' + property 'klass' = 'environment' + property 'sdsinfo' = '::nexus::scobj::sdsinfo' + var enabled = { + type = int; + priv = user; + readable = 10; + writeable = 1; + read_function = read_digital; + write_Function = write_digital; + read_command = '?DOUT,2'; + write_command = '!DOUT,2,'; + allowed = '0,1'; + readable = 10; + # property junk = junk; + } + var flow = { + driveable = flow + mutable = true + readable = 1 + read_command = 'None' + fetch_function = fetch_flow + read_function = read_flow + write_function = write_flow + lowerlimit = 0 + upperlimit = 500 + tolerance = 1 + pid_function = pid_flow + property pid_error = 0 + property pid_deriv = 0 + property pid_integ = 0 + property pid_pvalue = 0.2 + property pid_ivalue = 0.1 + property pid_dvalue = 0.0 + property pid_imax = 30 + } + var humidity = { + driveable = humidity + mutable = true + readable = 1 + read_command = '?ALL DATA' + read_function = read_all_data + write_function = write_humidity + checkrange_function = chkrange_function + value = 50 + lowerlimit = 10 + upperlimit = 90 + tolerance = 1 + pid_function = pid_humidity + property pid_error = 0 + property pid_deriv = 0 + property pid_integ = 0 + property pid_pvalue = 0.2 + property pid_ivalue = 0.1 + property pid_dvalue = 0.0 + property pid_imax = 30 + property settle_time = 5.250 + } + var gas_factor = { value = 1.0; } + control = false + data = false + nxsave = false + var temperature + var flow1 + var flow2 + var flow3 + } +# +# The named group is at the device level, variables below that +# + group analog = { + # group_property 'data' = true + type = float; + priv = user; + control = false + data = false + nxsave = false + readable = 5; + read_function = read_sixteen; + property base = 0; # applies to all following vars + var pv1 = { read_command = '?AIN,0'; property span = 500; }; # ain0 + var pv2 = { read_command = '?AIN,1'; property span = 500; }; # ain1 + var pv3 = { read_command = '?AIN,2'; property span = 500; }; # ain2 + var rhtemp = { read_command = '?AIN,8'; property span = 100; }; # ain8 + var rhsense = { read_command = '?AIN,9'; property span = 100; }; # ain9 + var ansto_temp = { read_command = '?AIN,12'; property span = 100; }; # ain12 + writeable = 1; + read_function = read_twelve; + write_function = write_twelve; + var sp1 = { read_command = '?AOUT,0'; write_command = '!AOUT,0,'; property span = 500; } # aout0 + var sp2 = { read_command = '?AOUT,1'; write_command = '!AOUT,1,'; property span = 500; } # aout1 + var sp3 = { read_command = '?AOUT,2'; write_command = '!AOUT,2,'; property span = 500; } # aout2 + }; + +# +# Code lines start with '@' which is stripped before being emitted into generated driver +# The code is emitted at the appropriate place in the given function +# + code read_function read_digital = { +@ if { [string equal -nocase -length 5 "${data}" "DOUT ="] } { +@ set result [scan "${data}" "DOUT = %d OK" val] +@ if { ${result} == 1 } { +@ set data ${val} +@ } else { +@ sct geterror "Syntax error (Result=${result}) in: '${data}'" +@ } +@ } else { +@ sct geterror "Syntax error in: '${data}'" +@ } + } + code read_function read_twelve = { +@ if { [string equal -nocase -length 5 "${data}" "AOUT ="] } { +@ set result [scan "${data}" "AOUT = %d OK" val] +@ if { ${result} == 1 } { +@ if { [hpropexists [sct] base] } { +@ set base [sct base] +@ } else { +@ set base 0.0 +@ } +@ if { [hpropexists [sct] span] } { +@ set span [sct span] +@ } else { +@ set span 500.0 +@ } +@ set data [expr (${span} * (${val} - ${base})) / 4095.0] +@ } else { +@ sct geterror "Syntax (Result=${result}) error in: '${data}'" +@ } +@ } else { +@ sct geterror "Syntax error in: '${data}'" +@ } + } + code read_function read_sixteen = { +@ if { [string equal -nocase -length 5 "${data}" "AIN ="] } { +@ set result [scan "${data}" "AIN = %d OK" val] +@ if { ${result} == 1 } { +@ if { [hpropexists [sct] base] } { +@ set base [sct base] +@ } else { +@ set base 0.0 +@ } +@ if { [hpropexists [sct] span] } { +@ set span [sct span] +@ } else { +@ set span 500.0 +@ } +@ set data [expr (${span} * (${val} - ${base})) / 65535.0] +@ } else { +@ sct geterror "Syntax error (Result=${result}) in: '${data}'" +@ } +@ } else { +@ sct geterror "Syntax error in: '${data}'" +@ } + } + code read_function read_all_data = { +@ if { [string equal -nocase -length 2 "${data}" "A "] } { +@ set data_list [split [string range "${data}" 2 end-3] ','] +@ if { [llength ${data_list}] == 8 } { +@ set data [expr [lindex ${data_list} 0]] +@ hupdate ${tc_root}/temperature [expr [lindex ${data_list} 1]] +@ hupdate ${tc_root}/flow1 [expr [lindex ${data_list} 3] / [hval ${tc_root}/gas_factor]] +@ hupdate ${tc_root}/flow2 [expr [lindex ${data_list} 4] / [hval ${tc_root}/gas_factor]] +@ hupdate ${tc_root}/flow3 [expr [lindex ${data_list} 5] / [hval ${tc_root}/gas_factor]] +@ } else { +@ sct geterror "Syntax error (Result=${result}) in: '${data}'" +@ } +@ } else { +@ sct geterror "Syntax error for read_all_data in: '${data}'" +@ } +@ if { [hpropexists [sct] target] } { +@ set pid [pid_humidity ${tc_root} [sct target] ${data}] +@ } +} + code pid_function pid_humidity = { +@ set path [pathname [sct]] +@ set sign 1 +@ foreach node [list analog/sp1 analog/sp2] { +@ set sign [expr -${sign}] +@ set signed_pid [expr ${sign} * ${pid}] +@ hsetprop ${path}/${node} bias_humidity ${signed_pid} +@ if { [hpropexists ${path}/${node} target] } { +@ hset ${path}/${node} [hgetpropval ${path}/${node} target] +@ } else { +@ hset ${path}/${node} [hval ${path}/${node}] +@ } +@ } +@ } + } + code fetch_function fetch_flow = { +@ set data 0.0 +@ set targets 0.0 +@ set path [pathname [sct]] +@ foreach node [list flow1 flow2] { +@ set data [expr ${data} + [hval ${path}/${node}]] +@ } +@ sct result ${data} +@ foreach node [list analog/sp1 analog/sp2] { +@ set targets [expr ${targets} + [hval ${path}/${node}]] +@ } +@ sct targets ${targets} +@ if { [hpropexists [sct] target] } { +@ set pid [pid_flow ${tc_root} [sct target] ${data}] +@ } +@# cut this function short +@ return ${nextState} +} + code pid_function pid_flow = { +@ set path [pathname [sct]] +@ foreach node [list analog/sp1 analog/sp2] { +@ hsetprop ${path}/${node} bias_flow ${pid} +@ if { [hpropexists ${path}/${node} target] } { +@ hset ${path}/${node} [hgetpropval ${path}/${node} target] +@ } else { +@ hset ${path}/${node} [hval ${path}/${node}] +@ } +@ } +@ } + } + code write_function write_digital = { + } + code write_function write_twelve = { +@ if { [hpropexists [sct] base] } { +@ set base [sct base] +@ } else { +@ set base 0.0 +@ } +@ if { [hpropexists [sct] span] } { +@ set span [sct span] +@ } else { +@ set span 500.0 +@ } +@ if { [hpropexists [sct] bias_humidity] } { +@ set par [expr ${par} + [sct bias_humidity]] +@ } +@ if { [hpropexists [sct] bias_flow] } { +@ set par [expr ${par} + [sct bias_flow]] +@ } +@ if { ${par} < 0.0 } { +@ set par 0.0 +@ } +@ if { ${par} > ${span} } { +@ set par ${span} +@ } +@ set par [expr int(${base} + (4095.0 * ${par} / ${span}))] +@ set cmd "${cmd_str}${par}" + } + code write_function write_flow = { +@ if { [hpropexists ${tc_root}/humidity target] } { +@ set humidity_target [hgetpropval ${tc_root}/humidity target] +@ } else { +@ set humidity_target [hval ${tc_root}/humidity] +@ } +@ set flow1_target [expr (0.01 * (100.0 - ${humidity_target})) * [sct target]] +@ set flow2_target [expr (0.01 * ( ${humidity_target})) * [sct target]] +@ hset ${tc_root}/analog/sp1 ${flow1_target} +@ hset ${tc_root}/analog/sp2 ${flow2_target} +@ set cmd "@@NOSEND@@" + } + code write_function write_humidity = { +@ if { [hpropexists ${tc_root}/flow target] } { +@ set flow_target [hgetpropval ${tc_root}/flow target] +@ } else { +@ set flow_target [hval ${tc_root}/flow] +@ } +@ set flow1_target [expr (0.01 * (100.0 - [sct target])) * ${flow_target}] +@ set flow2_target [expr (0.01 * ( [sct target])) * ${flow_target}] +@ hset ${tc_root}/analog/sp1 ${flow1_target} +@ hset ${tc_root}/analog/sp2 ${flow2_target} +@ set cmd "@@NOSEND@@" + } + code write_function no_op = { +@ set cmd "@@NOSEND@@" + } +# +# This code is after database creation +# + code mkDriver = { + } + code chkrange_function = { + @ # hooked + } +}; diff --git a/site_ansto/instrument/config/environment/isotech_ps.sct b/site_ansto/instrument/config/environment/isotech_ps.sct new file mode 100644 index 00000000..585a29d4 --- /dev/null +++ b/site_ansto/instrument/config/environment/isotech_ps.sct @@ -0,0 +1,57 @@ +# Simple driver generator for the ISOTECH Power Supply +# vim: ts=8 sts=2 sw=2 expandtab autoindent smartindent +# +driver isotech_ps = { + vendor = isotech; device = ps; protocol = std; + class = environment; + simulation_group = environment_simulation; + protocol_args = '"\r"'; + group = { + readable = 5 + mutable = true + var relay = { + type = int; + read_command = 'F'; + read_function = read_relay; + writeable = 1 + write_command = 'KO'; + write_function = write_relay; + } + var amps = { + type = float; + read_command = 'A'; + units = 'A' + } + var volts = { + type = float; + read_command = 'V'; + writeable = 1; + write_command = 'SV'; + write_function = write_voltage; + units = 'V' + } + } + code read_function rdValue = { + @ set data [string range [sct result] 1 end] + } + code read_function read_relay = { + @ if { [string equal -nocase -length 2 "F1" "${data}"] } { + @ set data 1 + @ } elseif { [string equal -nocase -length 2 "F0" "${data}"] } { + @ set data 0 + @ } else { + @ sct geterror "Unexpected response '${data}' not 'F1' nor 'F0'" + @ } + } + code write_function write_relay = { + @ if { ${par} == 0 } { + @ set cmd "KOD" + @ } else { + @ set cmd "KOE" + @ } + } + code write_function write_voltage = { + @ set par "[format "%05.2f" [sct target]]" + @ set cmd "SV ${par}" + } +} diff --git a/site_ansto/instrument/config/environment/magneticField/sct_bruker_BEC1.tcl b/site_ansto/instrument/config/environment/magneticField/sct_bruker_BEC1.tcl index 1fc1cfef..80c413d8 100644 --- a/site_ansto/instrument/config/environment/magneticField/sct_bruker_BEC1.tcl +++ b/site_ansto/instrument/config/environment/magneticField/sct_bruker_BEC1.tcl @@ -1125,7 +1125,7 @@ proc createNode {scobj_hpath sct_controller cmdGroup varName readable writable p if {$drivable == 1} { hsetprop $nodeName check ${ns}::check $scobj_hpath 1 hsetprop $nodeName driving 0 - hsetprop $nodeName checklimits ${ns}::check $scobj_hpath + hsetprop $nodeName checklimits ${ns}::check $scobj_hpath 1 hsetprop $nodeName checkstatus ${ns}::drivestatus $scobj_hpath hsetprop $nodeName halt ${ns}::halt $scobj_hpath } @@ -1322,6 +1322,7 @@ proc mk_sct_bruker_BEC1 {sct_controller klasse tempobj tol} { # Changed ffr 20100625: do not call hinitprops to avoid a conflict with a change in SICServer vers. 2_5 #::scobj::hinitprops $tempobj/sensor nominal_outp_current hsetprop $scobj_hpath/pwrctrl/statusByte control false + hsetprop $scobj_hpath/sensor/desired_current type drivable ansto_makesctdrive ${tempobj}_driveable $scobj_hpath/sensor/desired_current $scobj_hpath/sensor/nominal_outp_current $sct_controller diff --git a/site_ansto/instrument/config/environment/sct_cybaman.tcl b/site_ansto/instrument/config/environment/sct_cybaman.tcl index 787d52df..61b88d9d 100644 --- a/site_ansto/instrument/config/environment/sct_cybaman.tcl +++ b/site_ansto/instrument/config/environment/sct_cybaman.tcl @@ -16,26 +16,6 @@ namespace eval ::scobj::cybaman { close $fd } - proc basename {node} { - set point [string last "/" $node] - if { $point < 0 } { - return $node - } else { - incr point - return "[string range $node $point end]" - } - } - proc pathname {node} { - set point [string last "/" $node] - if { $point < 0 } { - return "" - } else { - incr point -1 - return "[string range $node 0 $point]" - } - return "[join [lrange [split $node '/'] 0 end-1] '/']" - } - proc splitxml {str} { set my_list [list] set idx 0 diff --git a/site_ansto/instrument/config/environment/sct_hiden_xcs.tcl b/site_ansto/instrument/config/environment/sct_hiden_xcs.tcl new file mode 100644 index 00000000..e2c83925 --- /dev/null +++ b/site_ansto/instrument/config/environment/sct_hiden_xcs.tcl @@ -0,0 +1,1126 @@ +# Generated driver for hiden_xcs +# vim: ft=tcl tabstop=8 softtabstop=2 shiftwidth=2 nocindent smartindent +# + +namespace eval ::scobj::hiden_xcs { + set debug_threshold 0 +} + +proc ::scobj::hiden_xcs::debug_log {debug_level debug_string} { + set catch_status [ catch { + if {${debug_level} >= ${::scobj::hiden_xcs::debug_threshold}} { + set fd [open "/tmp/hiden_xcs.log" "a"] + set line "[clock format [clock seconds] -format "%T"] ${debug_string}" + puts ${fd} "${line}" + close ${fd} + } + } catch_message ] +} + +# checklimits function for driveable interface +proc ::scobj::hiden_xcs::checklimits {tc_root} { + set catch_status [ catch { + debug_log 1 "checklimits tc_root=${tc_root} sct=[sct] target=[sct target]" + set setpoint [sct target] + if { [hpropexists [sct] lowerlimit] } { + set lolimit [sct lowerlimit] + } else { + # lowerlimit not set, use target + set lolimit [sct target] + } + if { [hpropexists [sct] upperlimit] } { + set hilimit [sct upperlimit] + } else { + # upperlimit not set, use target + set hilimit [sct target] + } +# hook code goes here + if { ${setpoint} < ${lolimit} || ${setpoint} > ${hilimit} } { + sct driving 0 + error "setpoint ${setpoint} violates limits (${lolimit}..${hilimit}) on [sct]" + } + return OK + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# check function for hset change +proc ::scobj::hiden_xcs::checkrange {tc_root} { + set catch_status [ catch { + debug_log 1 "checkrange tc_root=${tc_root} sct=[sct] target=[sct target]" + set setpoint [sct target] + if { [hpropexists [sct] lowerlimit] } { + set lolimit [sct lowerlimit] + } else { + # lowerlimit not set, use target + set lolimit [sct target] + } + if { [hpropexists [sct] upperlimit] } { + set hilimit [sct upperlimit] + } else { + # upperlimit not set, use target + set hilimit [sct target] + } +# hook code goes here + if { ${setpoint} < ${lolimit} || ${setpoint} > ${hilimit} } { + error "setpoint ${setpoint} violates limits (${lolimit}..${hilimit}) on [sct]" + } + return OK + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# checkstatus function for driveable interface +proc ::scobj::hiden_xcs::checkstatus {tc_root} { + set catch_status [ catch { +# hook code goes here + if {[sct driving]} { + set sp "[sct target]" + set pv "[hval ${tc_root}/[sct driveable]]" + if { abs(${pv} - ${sp}) <= [sct tolerance] } { + if { [hpropexists [sct] settle_time] } { + if { [hpropexists [sct] settle_time_start] } { + if { [sct utime] - [sct settle_time_start] >= [sct settle_time]} { + sct driving 0 + return "idle" + } + return "busy" + } else { + sct utime settle_time_start + return "busy" + } + } + sct driving 0 + return "idle" + } + if { [hpropexists [sct] settle_time_start] } { + hdelprop [sct] settle_time_start + } + return "busy" + } else { + return "idle" + } + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# check function for hset change +proc ::scobj::hiden_xcs::chkrange_function {tc_root} { + set catch_status [ catch { + debug_log 1 "chkrange_function tc_root=${tc_root} sct=[sct] target=[sct target]" + set setpoint [sct target] + if { [hpropexists [sct] lowerlimit] } { + set lolimit [sct lowerlimit] + } else { + # lowerlimit not set, use target + set lolimit [sct target] + } + if { [hpropexists [sct] upperlimit] } { + set hilimit [sct upperlimit] + } else { + # upperlimit not set, use target + set hilimit [sct target] + } +# hook code starts + # hooked +# hook code ends + if { ${setpoint} < ${lolimit} || ${setpoint} > ${hilimit} } { + error "setpoint ${setpoint} violates limits (${lolimit}..${hilimit}) on [sct]" + } + return OK + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to request the read of a parameter on a device +proc ::scobj::hiden_xcs::fetch_flow {tc_root nextState cmd_str} { + set catch_status [ catch { + debug_log 1 "fetch_flow tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set cmd "${cmd_str}" +# hook code starts + set data 0.0 + set targets 0.0 + set path [pathname [sct]] + foreach node [list flow1 flow2] { + set data [expr ${data} + [hval ${path}/${node}]] + } + sct result ${data} + foreach node [list analog/sp1 analog/sp2] { + set targets [expr ${targets} + [hval ${path}/${node}]] + } + sct targets ${targets} + if { [hpropexists [sct] target] } { + set pid [pid_flow ${tc_root} [sct target] ${data}] + } +# cut this function short + return ${nextState} +# hook code ends + if { [hpropexists [sct] geterror] } { + debug_log 1 "[sct] error: [sct geterror]" + error "[sct geterror]" + } + debug_log 1 "fetch_flow sct send ${cmd}" + if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { + sct send "${cmd}" + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to request the read of a parameter on a device +proc ::scobj::hiden_xcs::getValue {tc_root nextState cmd_str} { + set catch_status [ catch { + debug_log 1 "getValue tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set cmd "${cmd_str}" +# hook code goes here + debug_log 1 "getValue sct send ${cmd}" + if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { + sct send "${cmd}" + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# halt function for driveable interface +proc ::scobj::hiden_xcs::halt {tc_root} { + set catch_status [ catch { + debug_log 1 "halt tc_root=${tc_root} sct=[sct] driving=[sct driving]" + ### TODO hset [sct] [hval [sct]] +# hook code goes here + sct driving 0 + return "idle" + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to check the write parameter on a device +proc ::scobj::hiden_xcs::noResponse {tc_root} { + set catch_status [ catch { + debug_log 1 "noResponse tc_root=${tc_root} sct=[sct] resp=[sct result]" +# hook code goes here + return "idle" + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to write a parameter value on a device +proc ::scobj::hiden_xcs::no_op {tc_root nextState cmd_str} { + set catch_status [ catch { + debug_log 1 "no_op tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set par [sct target] + set cmd "${cmd_str}${par}" +# hook code starts + set cmd "@@NOSEND@@" +# hook code ends + if { [hpropexists [sct] geterror] } { + debug_log 1 "[sct] error: [sct geterror]" + error "[sct geterror]" + } + if { [hpropexists [sct] driving] } { + if { [hpropexists [sct] writestatus] && [sct writestatus] == "start" } { + sct driving 1 + } + } + debug_log 1 "no_op sct send ${cmd}" + if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { + sct send "${cmd}" + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# pid function for PID control +proc ::scobj::hiden_xcs::pid_flow {tc_root sp pv} { + set catch_status [ catch { + debug_log 1 "pid_flow tc_root=${tc_root} sct=[sct] pv=${pv} sp=${sp}" + sct pid_error [expr ${sp} - ${pv}] + set p_value [expr [sct pid_pvalue] * [sct pid_error]] + set d_value [expr [sct pid_dvalue] * (${pv} - [sct oldval])] + sct pid_deriv [sct pid_error] + sct pid_integ [expr [sct pid_integ] + [sct pid_error]] + if { [sct pid_integ] > [sct pid_imax] } { + sct pid_integ [sct pid_imax] + } + if { [sct pid_integ] < -[sct pid_imax] } { + sct pid_integ -[sct pid_imax] + } + set i_value [expr [sct pid_ivalue] * [sct pid_integ]] + set pid [expr ${p_value} + ${i_value} + ${d_value}] +# hook code starts + set path [pathname [sct]] + foreach node [list analog/sp1 analog/sp2] { + hsetprop ${path}/${node} bias_flow ${pid} + if { [hpropexists ${path}/${node} target] } { + hset ${path}/${node} [hgetpropval ${path}/${node} target] + } else { + hset ${path}/${node} [hval ${path}/${node}] + } + } + } +# hook code ends + sct pid_output ${pid} + } catch_message ] + handle_exception ${catch_status} ${catch_message} + return ${pid} +} + +# pid function for PID control +proc ::scobj::hiden_xcs::pid_humidity {tc_root sp pv} { + set catch_status [ catch { + debug_log 1 "pid_humidity tc_root=${tc_root} sct=[sct] pv=${pv} sp=${sp}" + sct pid_error [expr ${sp} - ${pv}] + set p_value [expr [sct pid_pvalue] * [sct pid_error]] + set d_value [expr [sct pid_dvalue] * (${pv} - [sct oldval])] + sct pid_deriv [sct pid_error] + sct pid_integ [expr [sct pid_integ] + [sct pid_error]] + if { [sct pid_integ] > [sct pid_imax] } { + sct pid_integ [sct pid_imax] + } + if { [sct pid_integ] < -[sct pid_imax] } { + sct pid_integ -[sct pid_imax] + } + set i_value [expr [sct pid_ivalue] * [sct pid_integ]] + set pid [expr ${p_value} + ${i_value} + ${d_value}] +# hook code starts + set path [pathname [sct]] + set sign 1 + foreach node [list analog/sp1 analog/sp2] { + set sign [expr -${sign}] + set signed_pid [expr ${sign} * ${pid}] + hsetprop ${path}/${node} bias_humidity ${signed_pid} + if { [hpropexists ${path}/${node} target] } { + hset ${path}/${node} [hgetpropval ${path}/${node} target] + } else { + hset ${path}/${node} [hval ${path}/${node}] + } + } + } +# hook code ends + sct pid_output ${pid} + } catch_message ] + handle_exception ${catch_status} ${catch_message} + return ${pid} +} + +# function to parse the read of a parameter on a device +proc ::scobj::hiden_xcs::rdValue {tc_root} { + set catch_status [ catch { + debug_log 1 "rdValue tc_root=${tc_root} sct=[sct] result=[sct result]" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set data [sct result] + set nextState "idle" + if {[string equal -nocase -length 7 ${data} "ASCERR:"]} { + # the protocol driver has reported an error + sct geterror "${data}" + error "[sct geterror]" + } +# hook code goes here + if { ${data} != [sct oldval] } { + debug_log 1 "[sct] changed to new:${data}, from old:[sct oldval]" + sct oldval ${data} + sct update ${data} + sct utime readtime + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to parse the read of a parameter on a device +proc ::scobj::hiden_xcs::read_all_data {tc_root} { + set catch_status [ catch { + debug_log 1 "read_all_data tc_root=${tc_root} sct=[sct] result=[sct result]" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set data [sct result] + set nextState "idle" + if {[string equal -nocase -length 7 ${data} "ASCERR:"]} { + # the protocol driver has reported an error + sct geterror "${data}" + error "[sct geterror]" + } +# hook code starts + if { [string equal -nocase -length 2 "${data}" "A "] } { + set data_list [split [string range "${data}" 2 end-3] ','] + if { [llength ${data_list}] == 8 } { + set data [expr [lindex ${data_list} 0]] + hupdate ${tc_root}/temperature [expr [lindex ${data_list} 1]] + hupdate ${tc_root}/flow1 [expr [lindex ${data_list} 3] / [hval ${tc_root}/gas_factor]] + hupdate ${tc_root}/flow2 [expr [lindex ${data_list} 4] / [hval ${tc_root}/gas_factor]] + hupdate ${tc_root}/flow3 [expr [lindex ${data_list} 5] / [hval ${tc_root}/gas_factor]] + } else { + sct geterror "Syntax error (Result=${result}) in: '${data}'" + } + } else { + sct geterror "Syntax error for read_all_data in: '${data}'" + } + if { [hpropexists [sct] target] } { + set pid [pid_humidity ${tc_root} [sct target] ${data}] + } +# hook code ends + if { [hpropexists [sct] geterror] } { + debug_log 1 "[sct] error: [sct geterror]" + error "[sct geterror]" + } + if { ${data} != [sct oldval] } { + debug_log 1 "[sct] changed to new:${data}, from old:[sct oldval]" + sct oldval ${data} + sct update ${data} + sct utime readtime + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to parse the read of a parameter on a device +proc ::scobj::hiden_xcs::read_digital {tc_root} { + set catch_status [ catch { + debug_log 1 "read_digital tc_root=${tc_root} sct=[sct] result=[sct result]" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set data [sct result] + set nextState "idle" + if {[string equal -nocase -length 7 ${data} "ASCERR:"]} { + # the protocol driver has reported an error + sct geterror "${data}" + error "[sct geterror]" + } +# hook code starts + if { [string equal -nocase -length 5 "${data}" "DOUT ="] } { + set result [scan "${data}" "DOUT = %d OK" val] + if { ${result} == 1 } { + set data ${val} + } else { + sct geterror "Syntax error (Result=${result}) in: '${data}'" + } + } else { + sct geterror "Syntax error in: '${data}'" + } +# hook code ends + if { [hpropexists [sct] geterror] } { + debug_log 1 "[sct] error: [sct geterror]" + error "[sct geterror]" + } + if { ${data} != [sct oldval] } { + debug_log 1 "[sct] changed to new:${data}, from old:[sct oldval]" + sct oldval ${data} + sct update ${data} + sct utime readtime + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to parse the read of a parameter on a device +proc ::scobj::hiden_xcs::read_flow {tc_root} { + set catch_status [ catch { + debug_log 1 "read_flow tc_root=${tc_root} sct=[sct] result=[sct result]" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set data [sct result] + set nextState "idle" + if {[string equal -nocase -length 7 ${data} "ASCERR:"]} { + # the protocol driver has reported an error + sct geterror "${data}" + error "[sct geterror]" + } +# hook code goes here + if { ${data} != [sct oldval] } { + debug_log 1 "[sct] changed to new:${data}, from old:[sct oldval]" + sct oldval ${data} + sct update ${data} + sct utime readtime + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to parse the read of a parameter on a device +proc ::scobj::hiden_xcs::read_sixteen {tc_root} { + set catch_status [ catch { + debug_log 1 "read_sixteen tc_root=${tc_root} sct=[sct] result=[sct result]" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set data [sct result] + set nextState "idle" + if {[string equal -nocase -length 7 ${data} "ASCERR:"]} { + # the protocol driver has reported an error + sct geterror "${data}" + error "[sct geterror]" + } +# hook code starts + if { [string equal -nocase -length 5 "${data}" "AIN ="] } { + set result [scan "${data}" "AIN = %d OK" val] + if { ${result} == 1 } { + if { [hpropexists [sct] base] } { + set base [sct base] + } else { + set base 0.0 + } + if { [hpropexists [sct] span] } { + set span [sct span] + } else { + set span 500.0 + } + set data [expr (${span} * (${val} - ${base})) / 65535.0] + } else { + sct geterror "Syntax error (Result=${result}) in: '${data}'" + } + } else { + sct geterror "Syntax error in: '${data}'" + } +# hook code ends + if { [hpropexists [sct] geterror] } { + debug_log 1 "[sct] error: [sct geterror]" + error "[sct geterror]" + } + if { ${data} != [sct oldval] } { + debug_log 1 "[sct] changed to new:${data}, from old:[sct oldval]" + sct oldval ${data} + sct update ${data} + sct utime readtime + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to parse the read of a parameter on a device +proc ::scobj::hiden_xcs::read_twelve {tc_root} { + set catch_status [ catch { + debug_log 1 "read_twelve tc_root=${tc_root} sct=[sct] result=[sct result]" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set data [sct result] + set nextState "idle" + if {[string equal -nocase -length 7 ${data} "ASCERR:"]} { + # the protocol driver has reported an error + sct geterror "${data}" + error "[sct geterror]" + } +# hook code starts + if { [string equal -nocase -length 5 "${data}" "AOUT ="] } { + set result [scan "${data}" "AOUT = %d OK" val] + if { ${result} == 1 } { + if { [hpropexists [sct] base] } { + set base [sct base] + } else { + set base 0.0 + } + if { [hpropexists [sct] span] } { + set span [sct span] + } else { + set span 500.0 + } + set data [expr (${span} * (${val} - ${base})) / 4095.0] + } else { + sct geterror "Syntax (Result=${result}) error in: '${data}'" + } + } else { + sct geterror "Syntax error in: '${data}'" + } +# hook code ends + if { [hpropexists [sct] geterror] } { + debug_log 1 "[sct] error: [sct geterror]" + error "[sct geterror]" + } + if { ${data} != [sct oldval] } { + debug_log 1 "[sct] changed to new:${data}, from old:[sct oldval]" + sct oldval ${data} + sct update ${data} + sct utime readtime + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to write a parameter value on a device +proc ::scobj::hiden_xcs::setValue {tc_root nextState cmd_str} { + set catch_status [ catch { + debug_log 1 "setValue tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set par [sct target] + set cmd "${cmd_str}${par}" +# hook code goes here + if { [hpropexists [sct] driving] } { + if { [hpropexists [sct] writestatus] && [sct writestatus] == "start" } { + sct driving 1 + } + } + debug_log 1 "setValue sct send ${cmd}" + if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { + sct send "${cmd}" + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to write a parameter value on a device +proc ::scobj::hiden_xcs::write_digital {tc_root nextState cmd_str} { + set catch_status [ catch { + debug_log 1 "write_digital tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set par [sct target] + set cmd "${cmd_str}${par}" +# hook code goes here + if { [hpropexists [sct] driving] } { + if { [hpropexists [sct] writestatus] && [sct writestatus] == "start" } { + sct driving 1 + } + } + debug_log 1 "write_digital sct send ${cmd}" + if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { + sct send "${cmd}" + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to write a parameter value on a device +proc ::scobj::hiden_xcs::write_flow {tc_root nextState cmd_str} { + set catch_status [ catch { + debug_log 1 "write_flow tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set par [sct target] + set cmd "${cmd_str}${par}" +# hook code starts + if { [hpropexists ${tc_root}/humidity target] } { + set humidity_target [hgetpropval ${tc_root}/humidity target] + } else { + set humidity_target [hval ${tc_root}/humidity] + } + set flow1_target [expr (0.01 * (100.0 - ${humidity_target})) * [sct target]] + set flow2_target [expr (0.01 * ( ${humidity_target})) * [sct target]] + hset ${tc_root}/analog/sp1 ${flow1_target} + hset ${tc_root}/analog/sp2 ${flow2_target} + set cmd "@@NOSEND@@" +# hook code ends + if { [hpropexists [sct] geterror] } { + debug_log 1 "[sct] error: [sct geterror]" + error "[sct geterror]" + } + if { [hpropexists [sct] driving] } { + if { [hpropexists [sct] writestatus] && [sct writestatus] == "start" } { + sct driving 1 + } + } + debug_log 1 "write_flow sct send ${cmd}" + if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { + sct send "${cmd}" + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to write a parameter value on a device +proc ::scobj::hiden_xcs::write_humidity {tc_root nextState cmd_str} { + set catch_status [ catch { + debug_log 1 "write_humidity tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set par [sct target] + set cmd "${cmd_str}${par}" +# hook code starts + if { [hpropexists ${tc_root}/flow target] } { + set flow_target [hgetpropval ${tc_root}/flow target] + } else { + set flow_target [hval ${tc_root}/flow] + } + set flow1_target [expr (0.01 * (100.0 - [sct target])) * ${flow_target}] + set flow2_target [expr (0.01 * ( [sct target])) * ${flow_target}] + hset ${tc_root}/analog/sp1 ${flow1_target} + hset ${tc_root}/analog/sp2 ${flow2_target} + set cmd "@@NOSEND@@" +# hook code ends + if { [hpropexists [sct] geterror] } { + debug_log 1 "[sct] error: [sct geterror]" + error "[sct geterror]" + } + if { [hpropexists [sct] driving] } { + if { [hpropexists [sct] writestatus] && [sct writestatus] == "start" } { + sct driving 1 + } + } + debug_log 1 "write_humidity sct send ${cmd}" + if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { + sct send "${cmd}" + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to write a parameter value on a device +proc ::scobj::hiden_xcs::write_twelve {tc_root nextState cmd_str} { + set catch_status [ catch { + debug_log 1 "write_twelve tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set par [sct target] + set cmd "${cmd_str}${par}" +# hook code starts + if { [hpropexists [sct] base] } { + set base [sct base] + } else { + set base 0.0 + } + if { [hpropexists [sct] span] } { + set span [sct span] + } else { + set span 500.0 + } + if { [hpropexists [sct] bias_humidity] } { + set par [expr ${par} + [sct bias_humidity]] + } + if { [hpropexists [sct] bias_flow] } { + set par [expr ${par} + [sct bias_flow]] + } + if { ${par} < 0.0 } { + set par 0.0 + } + if { ${par} > ${span} } { + set par ${span} + } + set par [expr int(${base} + (4095.0 * ${par} / ${span}))] + set cmd "${cmd_str}${par}" +# hook code ends + if { [hpropexists [sct] geterror] } { + debug_log 1 "[sct] error: [sct geterror]" + error "[sct geterror]" + } + if { [hpropexists [sct] driving] } { + if { [hpropexists [sct] writestatus] && [sct writestatus] == "start" } { + sct driving 1 + } + } + debug_log 1 "write_twelve sct send ${cmd}" + if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { + sct send "${cmd}" + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +proc ::scobj::hiden_xcs::mk_sct_hiden_xcs { sct_controller name tol } { + debug_log 1 "mk_sct_hiden_xcs ${sct_controller} ${name} ${tol}" + set ns "[namespace current]" + set catch_status [ catch { + + MakeSICSObj ${name} SCT_OBJECT + + sicslist setatt ${name} klass environment + sicslist setatt ${name} long_name ${name} + + set scobj_hpath /sics/${name} + + hfactory ${scobj_hpath}/enabled plain user int + hsetprop ${scobj_hpath}/enabled read ${ns}::getValue ${scobj_hpath} read_digital {?DOUT,2} + hsetprop ${scobj_hpath}/enabled read_digital ${ns}::read_digital ${scobj_hpath} + hsetprop ${scobj_hpath}/enabled write ${ns}::write_digital ${scobj_hpath} noResponse {!DOUT,2,} + hsetprop ${scobj_hpath}/enabled noResponse ${ns}::noResponse ${scobj_hpath} + hsetprop ${scobj_hpath}/enabled check ${ns}::checkrange ${scobj_hpath} + hsetprop ${scobj_hpath}/enabled control true + hsetprop ${scobj_hpath}/enabled data true + hsetprop ${scobj_hpath}/enabled mutable false + hsetprop ${scobj_hpath}/enabled nxsave true + hsetprop ${scobj_hpath}/enabled values 0,1 + hsetprop ${scobj_hpath}/enabled oldval 0 + hsetprop ${scobj_hpath}/enabled klass "environment" + hsetprop ${scobj_hpath}/enabled sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/enabled type "part" + hsetprop ${scobj_hpath}/enabled nxalias "${name}_enabled" + + hfactory ${scobj_hpath}/flow plain user float + hsetprop ${scobj_hpath}/flow read ${ns}::fetch_flow ${scobj_hpath} read_flow {None} + hsetprop ${scobj_hpath}/flow read_flow ${ns}::read_flow ${scobj_hpath} + hsetprop ${scobj_hpath}/flow write ${ns}::write_flow ${scobj_hpath} noResponse {} + hsetprop ${scobj_hpath}/flow noResponse ${ns}::noResponse ${scobj_hpath} + hsetprop ${scobj_hpath}/flow check ${ns}::checkrange ${scobj_hpath} + hsetprop ${scobj_hpath}/flow driving 0 + hsetprop ${scobj_hpath}/flow checklimits ${ns}::checklimits ${scobj_hpath} + hsetprop ${scobj_hpath}/flow checkstatus ${ns}::checkstatus ${scobj_hpath} + hsetprop ${scobj_hpath}/flow halt ${ns}::halt ${scobj_hpath} + hsetprop ${scobj_hpath}/flow driveable flow + hsetprop ${scobj_hpath}/flow control true + hsetprop ${scobj_hpath}/flow data true + hsetprop ${scobj_hpath}/flow mutable true + hsetprop ${scobj_hpath}/flow nxsave true + hsetprop ${scobj_hpath}/flow lowerlimit 0 + hsetprop ${scobj_hpath}/flow upperlimit 500 + hsetprop ${scobj_hpath}/flow tolerance 1 + hsetprop ${scobj_hpath}/flow oldval 0.0 + hsetprop ${scobj_hpath}/flow klass "environment" + hsetprop ${scobj_hpath}/flow pid_deriv "0" + hsetprop ${scobj_hpath}/flow pid_dvalue "0.0" + hsetprop ${scobj_hpath}/flow pid_error "0" + hsetprop ${scobj_hpath}/flow pid_imax "30" + hsetprop ${scobj_hpath}/flow pid_integ "0" + hsetprop ${scobj_hpath}/flow pid_ivalue "0.1" + hsetprop ${scobj_hpath}/flow pid_pvalue "0.2" + hsetprop ${scobj_hpath}/flow sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/flow type "drivable" + hsetprop ${scobj_hpath}/flow nxalias "${name}_flow" + + hfactory ${scobj_hpath}/flow1 plain user float + hsetprop ${scobj_hpath}/flow1 control false + hsetprop ${scobj_hpath}/flow1 data false + hsetprop ${scobj_hpath}/flow1 mutable false + hsetprop ${scobj_hpath}/flow1 nxsave false + hsetprop ${scobj_hpath}/flow1 oldval 0.0 + hsetprop ${scobj_hpath}/flow1 klass "environment" + hsetprop ${scobj_hpath}/flow1 sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/flow1 type "part" + hsetprop ${scobj_hpath}/flow1 nxalias "${name}_flow1" + + hfactory ${scobj_hpath}/flow2 plain user float + hsetprop ${scobj_hpath}/flow2 control false + hsetprop ${scobj_hpath}/flow2 data false + hsetprop ${scobj_hpath}/flow2 mutable false + hsetprop ${scobj_hpath}/flow2 nxsave false + hsetprop ${scobj_hpath}/flow2 oldval 0.0 + hsetprop ${scobj_hpath}/flow2 klass "environment" + hsetprop ${scobj_hpath}/flow2 sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/flow2 type "part" + hsetprop ${scobj_hpath}/flow2 nxalias "${name}_flow2" + + hfactory ${scobj_hpath}/flow3 plain user float + hsetprop ${scobj_hpath}/flow3 control false + hsetprop ${scobj_hpath}/flow3 data false + hsetprop ${scobj_hpath}/flow3 mutable false + hsetprop ${scobj_hpath}/flow3 nxsave false + hsetprop ${scobj_hpath}/flow3 oldval 0.0 + hsetprop ${scobj_hpath}/flow3 klass "environment" + hsetprop ${scobj_hpath}/flow3 sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/flow3 type "part" + hsetprop ${scobj_hpath}/flow3 nxalias "${name}_flow3" + + hfactory ${scobj_hpath}/gas_factor plain user float + hsetprop ${scobj_hpath}/gas_factor control true + hsetprop ${scobj_hpath}/gas_factor data true + hsetprop ${scobj_hpath}/gas_factor mutable false + hsetprop ${scobj_hpath}/gas_factor nxsave true + hsetprop ${scobj_hpath}/gas_factor oldval 1.0 + hset ${scobj_hpath}/gas_factor 1.0 + hsetprop ${scobj_hpath}/gas_factor klass "environment" + hsetprop ${scobj_hpath}/gas_factor sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/gas_factor type "part" + hsetprop ${scobj_hpath}/gas_factor nxalias "${name}_gas_factor" + + hfactory ${scobj_hpath}/humidity plain user float + hsetprop ${scobj_hpath}/humidity read ${ns}::getValue ${scobj_hpath} read_all_data {?ALL DATA} + hsetprop ${scobj_hpath}/humidity read_all_data ${ns}::read_all_data ${scobj_hpath} + hsetprop ${scobj_hpath}/humidity write ${ns}::write_humidity ${scobj_hpath} noResponse {} + hsetprop ${scobj_hpath}/humidity noResponse ${ns}::noResponse ${scobj_hpath} + hsetprop ${scobj_hpath}/humidity check ${ns}::chkrange_function ${scobj_hpath} + hsetprop ${scobj_hpath}/humidity driving 0 + hsetprop ${scobj_hpath}/humidity checklimits ${ns}::checklimits ${scobj_hpath} + hsetprop ${scobj_hpath}/humidity checkstatus ${ns}::checkstatus ${scobj_hpath} + hsetprop ${scobj_hpath}/humidity halt ${ns}::halt ${scobj_hpath} + hsetprop ${scobj_hpath}/humidity driveable humidity + hsetprop ${scobj_hpath}/humidity control true + hsetprop ${scobj_hpath}/humidity data true + hsetprop ${scobj_hpath}/humidity mutable true + hsetprop ${scobj_hpath}/humidity nxsave true + hsetprop ${scobj_hpath}/humidity lowerlimit 10 + hsetprop ${scobj_hpath}/humidity upperlimit 90 + hsetprop ${scobj_hpath}/humidity tolerance 1 + hsetprop ${scobj_hpath}/humidity oldval 50 + hset ${scobj_hpath}/humidity 50 + hsetprop ${scobj_hpath}/humidity klass "environment" + hsetprop ${scobj_hpath}/humidity pid_deriv "0" + hsetprop ${scobj_hpath}/humidity pid_dvalue "0.0" + hsetprop ${scobj_hpath}/humidity pid_error "0" + hsetprop ${scobj_hpath}/humidity pid_imax "30" + hsetprop ${scobj_hpath}/humidity pid_integ "0" + hsetprop ${scobj_hpath}/humidity pid_ivalue "0.1" + hsetprop ${scobj_hpath}/humidity pid_pvalue "0.2" + hsetprop ${scobj_hpath}/humidity sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/humidity settle_time "5.25" + hsetprop ${scobj_hpath}/humidity type "drivable" + hsetprop ${scobj_hpath}/humidity nxalias "${name}_humidity" + + hfactory ${scobj_hpath}/temperature plain user float + hsetprop ${scobj_hpath}/temperature control false + hsetprop ${scobj_hpath}/temperature data false + hsetprop ${scobj_hpath}/temperature mutable false + hsetprop ${scobj_hpath}/temperature nxsave false + hsetprop ${scobj_hpath}/temperature oldval 0.0 + hsetprop ${scobj_hpath}/temperature klass "environment" + hsetprop ${scobj_hpath}/temperature sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/temperature type "part" + hsetprop ${scobj_hpath}/temperature nxalias "${name}_temperature" + + hsetprop ${scobj_hpath} data "true" + hsetprop ${scobj_hpath} nxsave "true" + + if {[SplitReply [environment_simulation]]=="false"} { + ${sct_controller} poll ${scobj_hpath}/enabled 10 + ${sct_controller} poll ${scobj_hpath}/flow 1 + ${sct_controller} poll ${scobj_hpath}/humidity 1 + ${sct_controller} write ${scobj_hpath}/enabled + ${sct_controller} write ${scobj_hpath}/flow + ansto_makesctdrive ${name}_temperature ${scobj_hpath}/flow ${scobj_hpath}/flow ${sct_controller} + ${sct_controller} write ${scobj_hpath}/humidity + ansto_makesctdrive ${name}_temperature ${scobj_hpath}/humidity ${scobj_hpath}/humidity ${sct_controller} + } + + hfactory ${scobj_hpath}/analog plain spy none + + hfactory ${scobj_hpath}/analog/ansto_temp plain user float + hsetprop ${scobj_hpath}/analog/ansto_temp read ${ns}::getValue ${scobj_hpath} read_sixteen {?AIN,12} + hsetprop ${scobj_hpath}/analog/ansto_temp read_sixteen ${ns}::read_sixteen ${scobj_hpath} + hsetprop ${scobj_hpath}/analog/ansto_temp control false + hsetprop ${scobj_hpath}/analog/ansto_temp data false + hsetprop ${scobj_hpath}/analog/ansto_temp mutable false + hsetprop ${scobj_hpath}/analog/ansto_temp nxsave false + hsetprop ${scobj_hpath}/analog/ansto_temp oldval 0.0 + hsetprop ${scobj_hpath}/analog/ansto_temp base "0" + hsetprop ${scobj_hpath}/analog/ansto_temp sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/analog/ansto_temp span "100" + hsetprop ${scobj_hpath}/analog/ansto_temp type "part" + hsetprop ${scobj_hpath}/analog/ansto_temp nxalias "${name}_analog_ansto_temp" + + hfactory ${scobj_hpath}/analog/pv1 plain user float + hsetprop ${scobj_hpath}/analog/pv1 read ${ns}::getValue ${scobj_hpath} read_sixteen {?AIN,0} + hsetprop ${scobj_hpath}/analog/pv1 read_sixteen ${ns}::read_sixteen ${scobj_hpath} + hsetprop ${scobj_hpath}/analog/pv1 control false + hsetprop ${scobj_hpath}/analog/pv1 data false + hsetprop ${scobj_hpath}/analog/pv1 mutable false + hsetprop ${scobj_hpath}/analog/pv1 nxsave false + hsetprop ${scobj_hpath}/analog/pv1 oldval 0.0 + hsetprop ${scobj_hpath}/analog/pv1 base "0" + hsetprop ${scobj_hpath}/analog/pv1 sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/analog/pv1 span "500" + hsetprop ${scobj_hpath}/analog/pv1 type "part" + hsetprop ${scobj_hpath}/analog/pv1 nxalias "${name}_analog_pv1" + + hfactory ${scobj_hpath}/analog/pv2 plain user float + hsetprop ${scobj_hpath}/analog/pv2 read ${ns}::getValue ${scobj_hpath} read_sixteen {?AIN,1} + hsetprop ${scobj_hpath}/analog/pv2 read_sixteen ${ns}::read_sixteen ${scobj_hpath} + hsetprop ${scobj_hpath}/analog/pv2 control false + hsetprop ${scobj_hpath}/analog/pv2 data false + hsetprop ${scobj_hpath}/analog/pv2 mutable false + hsetprop ${scobj_hpath}/analog/pv2 nxsave false + hsetprop ${scobj_hpath}/analog/pv2 oldval 0.0 + hsetprop ${scobj_hpath}/analog/pv2 base "0" + hsetprop ${scobj_hpath}/analog/pv2 sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/analog/pv2 span "500" + hsetprop ${scobj_hpath}/analog/pv2 type "part" + hsetprop ${scobj_hpath}/analog/pv2 nxalias "${name}_analog_pv2" + + hfactory ${scobj_hpath}/analog/pv3 plain user float + hsetprop ${scobj_hpath}/analog/pv3 read ${ns}::getValue ${scobj_hpath} read_sixteen {?AIN,2} + hsetprop ${scobj_hpath}/analog/pv3 read_sixteen ${ns}::read_sixteen ${scobj_hpath} + hsetprop ${scobj_hpath}/analog/pv3 control false + hsetprop ${scobj_hpath}/analog/pv3 data false + hsetprop ${scobj_hpath}/analog/pv3 mutable false + hsetprop ${scobj_hpath}/analog/pv3 nxsave false + hsetprop ${scobj_hpath}/analog/pv3 oldval 0.0 + hsetprop ${scobj_hpath}/analog/pv3 base "0" + hsetprop ${scobj_hpath}/analog/pv3 sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/analog/pv3 span "500" + hsetprop ${scobj_hpath}/analog/pv3 type "part" + hsetprop ${scobj_hpath}/analog/pv3 nxalias "${name}_analog_pv3" + + hfactory ${scobj_hpath}/analog/rhsense plain user float + hsetprop ${scobj_hpath}/analog/rhsense read ${ns}::getValue ${scobj_hpath} read_sixteen {?AIN,9} + hsetprop ${scobj_hpath}/analog/rhsense read_sixteen ${ns}::read_sixteen ${scobj_hpath} + hsetprop ${scobj_hpath}/analog/rhsense control false + hsetprop ${scobj_hpath}/analog/rhsense data false + hsetprop ${scobj_hpath}/analog/rhsense mutable false + hsetprop ${scobj_hpath}/analog/rhsense nxsave false + hsetprop ${scobj_hpath}/analog/rhsense oldval 0.0 + hsetprop ${scobj_hpath}/analog/rhsense base "0" + hsetprop ${scobj_hpath}/analog/rhsense sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/analog/rhsense span "100" + hsetprop ${scobj_hpath}/analog/rhsense type "part" + hsetprop ${scobj_hpath}/analog/rhsense nxalias "${name}_analog_rhsense" + + hfactory ${scobj_hpath}/analog/rhtemp plain user float + hsetprop ${scobj_hpath}/analog/rhtemp read ${ns}::getValue ${scobj_hpath} read_sixteen {?AIN,8} + hsetprop ${scobj_hpath}/analog/rhtemp read_sixteen ${ns}::read_sixteen ${scobj_hpath} + hsetprop ${scobj_hpath}/analog/rhtemp control false + hsetprop ${scobj_hpath}/analog/rhtemp data false + hsetprop ${scobj_hpath}/analog/rhtemp mutable false + hsetprop ${scobj_hpath}/analog/rhtemp nxsave false + hsetprop ${scobj_hpath}/analog/rhtemp oldval 0.0 + hsetprop ${scobj_hpath}/analog/rhtemp base "0" + hsetprop ${scobj_hpath}/analog/rhtemp sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/analog/rhtemp span "100" + hsetprop ${scobj_hpath}/analog/rhtemp type "part" + hsetprop ${scobj_hpath}/analog/rhtemp nxalias "${name}_analog_rhtemp" + + hfactory ${scobj_hpath}/analog/sp1 plain user float + hsetprop ${scobj_hpath}/analog/sp1 read ${ns}::getValue ${scobj_hpath} read_twelve {?AOUT,0} + hsetprop ${scobj_hpath}/analog/sp1 read_twelve ${ns}::read_twelve ${scobj_hpath} + hsetprop ${scobj_hpath}/analog/sp1 write ${ns}::write_twelve ${scobj_hpath} noResponse {!AOUT,0,} + hsetprop ${scobj_hpath}/analog/sp1 noResponse ${ns}::noResponse ${scobj_hpath} + hsetprop ${scobj_hpath}/analog/sp1 check ${ns}::checkrange ${scobj_hpath} + hsetprop ${scobj_hpath}/analog/sp1 control false + hsetprop ${scobj_hpath}/analog/sp1 data false + hsetprop ${scobj_hpath}/analog/sp1 mutable false + hsetprop ${scobj_hpath}/analog/sp1 nxsave false + hsetprop ${scobj_hpath}/analog/sp1 oldval 0.0 + hsetprop ${scobj_hpath}/analog/sp1 base "0" + hsetprop ${scobj_hpath}/analog/sp1 sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/analog/sp1 span "500" + hsetprop ${scobj_hpath}/analog/sp1 type "part" + hsetprop ${scobj_hpath}/analog/sp1 nxalias "${name}_analog_sp1" + + hfactory ${scobj_hpath}/analog/sp2 plain user float + hsetprop ${scobj_hpath}/analog/sp2 read ${ns}::getValue ${scobj_hpath} read_twelve {?AOUT,1} + hsetprop ${scobj_hpath}/analog/sp2 read_twelve ${ns}::read_twelve ${scobj_hpath} + hsetprop ${scobj_hpath}/analog/sp2 write ${ns}::write_twelve ${scobj_hpath} noResponse {!AOUT,1,} + hsetprop ${scobj_hpath}/analog/sp2 noResponse ${ns}::noResponse ${scobj_hpath} + hsetprop ${scobj_hpath}/analog/sp2 check ${ns}::checkrange ${scobj_hpath} + hsetprop ${scobj_hpath}/analog/sp2 control false + hsetprop ${scobj_hpath}/analog/sp2 data false + hsetprop ${scobj_hpath}/analog/sp2 mutable false + hsetprop ${scobj_hpath}/analog/sp2 nxsave false + hsetprop ${scobj_hpath}/analog/sp2 oldval 0.0 + hsetprop ${scobj_hpath}/analog/sp2 base "0" + hsetprop ${scobj_hpath}/analog/sp2 sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/analog/sp2 span "500" + hsetprop ${scobj_hpath}/analog/sp2 type "part" + hsetprop ${scobj_hpath}/analog/sp2 nxalias "${name}_analog_sp2" + + hfactory ${scobj_hpath}/analog/sp3 plain user float + hsetprop ${scobj_hpath}/analog/sp3 read ${ns}::getValue ${scobj_hpath} read_twelve {?AOUT,2} + hsetprop ${scobj_hpath}/analog/sp3 read_twelve ${ns}::read_twelve ${scobj_hpath} + hsetprop ${scobj_hpath}/analog/sp3 write ${ns}::write_twelve ${scobj_hpath} noResponse {!AOUT,2,} + hsetprop ${scobj_hpath}/analog/sp3 noResponse ${ns}::noResponse ${scobj_hpath} + hsetprop ${scobj_hpath}/analog/sp3 check ${ns}::checkrange ${scobj_hpath} + hsetprop ${scobj_hpath}/analog/sp3 control false + hsetprop ${scobj_hpath}/analog/sp3 data false + hsetprop ${scobj_hpath}/analog/sp3 mutable false + hsetprop ${scobj_hpath}/analog/sp3 nxsave false + hsetprop ${scobj_hpath}/analog/sp3 oldval 0.0 + hsetprop ${scobj_hpath}/analog/sp3 base "0" + hsetprop ${scobj_hpath}/analog/sp3 sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/analog/sp3 span "500" + hsetprop ${scobj_hpath}/analog/sp3 type "part" + hsetprop ${scobj_hpath}/analog/sp3 nxalias "${name}_analog_sp3" + + if {[SplitReply [environment_simulation]]=="false"} { + ${sct_controller} poll ${scobj_hpath}/analog/ansto_temp 5 + ${sct_controller} poll ${scobj_hpath}/analog/pv1 5 + ${sct_controller} poll ${scobj_hpath}/analog/pv2 5 + ${sct_controller} poll ${scobj_hpath}/analog/pv3 5 + ${sct_controller} poll ${scobj_hpath}/analog/rhsense 5 + ${sct_controller} poll ${scobj_hpath}/analog/rhtemp 5 + ${sct_controller} poll ${scobj_hpath}/analog/sp1 5 + ${sct_controller} poll ${scobj_hpath}/analog/sp2 5 + ${sct_controller} poll ${scobj_hpath}/analog/sp3 5 + ${sct_controller} write ${scobj_hpath}/analog/sp1 + ${sct_controller} write ${scobj_hpath}/analog/sp2 + ${sct_controller} write ${scobj_hpath}/analog/sp3 + } + hsetprop ${scobj_hpath} klass environment +# hook code starts +# hook code ends + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +namespace eval ::scobj::hiden_xcs { + namespace export debug_log + namespace export mk_sct_hiden_xcs +} + +proc add_hiden_xcs {name IP port terminator {tol 0.5}} { + set catch_status [ catch { + set ns "::scobj::hiden_xcs" + ${ns}::debug_log 1 "add_hiden_xcs ${name} ${IP} ${port} ${tol}" + if {[SplitReply [environment_simulation]]=="false"} { + if {[string equal -nocase "aqadapter" "${IP}"]} { + ${ns}::debug_log 1 "makesctcontroller sct_${name} aqadapter ${port}" + makesctcontroller sct_${name} aqadapter ${port} + } else { + ${ns}::debug_log 1 "makesctcontroller sct_${name} std ${IP}:${port} ${terminator}" + makesctcontroller sct_${name} std ${IP}:${port} ${terminator} + } + } + ${ns}::debug_log 1 "mk_sct_hiden_xcs sct_${name} ${name} ${tol}" + ${ns}::mk_sct_hiden_xcs sct_${name} ${name} ${tol} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +puts stdout "file evaluation of sct_hiden_xcs.tcl" +::scobj::hiden_xcs::debug_log 1 "file evaluation of sct_hiden_xcs.tcl" + +proc ::scobj::hiden_xcs::read_config {} { + set catch_status [ catch { + set ns "::scobj::hiden_xcs" + ${ns}::debug_log 1 "Processing Config" + dict for {k v} $::config_dict { + ${ns}::debug_log 1 "Inspecting $k:$v" + if { [dict exists $v "driver"] } { + ${ns}::debug_log 1 "Has driver [dict get $v driver]" + if { [dict get $v "driver"] == "hiden_xcs" } { + ${ns}::debug_log 1 "Correct driver, enabled = [dict get $v enabled]" + if { [dict get $v enabled] } { + set IP [dict get $v ip] + set PORT [dict get $v port] + set name [dict get $v name] + MakeAsyncProtocol ${name}_protocol + MakeAsyncQueue ${name}_queue ${name}_protocol ${IP} ${PORT} + set arg_list [list] + foreach arg {tol} { + if {[dict exists $v $arg]} { + lappend arg_list "[dict get $v $arg]" + } else { + ${ns}::debug_log 1 "Missing configuration value $arg" + error "Missing configuration value $arg" + } + } + ${ns}::debug_log 1 "arg_list = $arg_list" + ${ns}::debug_log 1 "add_hiden_xcs ${name} aqadapter ${name}_queue $arg_list" + add_hiden_xcs ${name} "aqadapter" ${name}_queue {*}$arg_list + } + } + } + } + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} +if { [info exists ::config_dict] } { + ::scobj::hiden_xcs::read_config +} else { + ::scobj::hiden_xcs:debug_log 1 "No config dict" +} diff --git a/site_ansto/instrument/config/environment/sct_isotech_ps.tcl b/site_ansto/instrument/config/environment/sct_isotech_ps.tcl new file mode 100644 index 00000000..4e4f0634 --- /dev/null +++ b/site_ansto/instrument/config/environment/sct_isotech_ps.tcl @@ -0,0 +1,357 @@ +# Generated driver for isotech_ps +# vim: ft=tcl tabstop=8 softtabstop=2 shiftwidth=2 nocindent smartindent +# + +namespace eval ::scobj::isotech_ps { + set debug_threshold 0 +} + +proc ::scobj::isotech_ps::debug_log {debug_level debug_string} { + set catch_status [ catch { + if {${debug_level} >= ${::scobj::isotech_ps::debug_threshold}} { + set fd [open "/tmp/isotech_ps.log" "a"] + set line "[clock format [clock seconds] -format "%T"] ${debug_string}" + puts ${fd} "${line}" + close ${fd} + } + } catch_message ] +} + +# check function for hset change +proc ::scobj::isotech_ps::checkrange {tc_root} { + set catch_status [ catch { + debug_log 1 "checkrange tc_root=${tc_root} sct=[sct] target=[sct target]" + set setpoint [sct target] + if { [hpropexists [sct] lowerlimit] } { + set lolimit [sct lowerlimit] + } else { + # lowerlimit not set, use target + set lolimit [sct target] + } + if { [hpropexists [sct] upperlimit] } { + set hilimit [sct upperlimit] + } else { + # upperlimit not set, use target + set hilimit [sct target] + } +# hook code goes here + if { ${setpoint} < ${lolimit} || ${setpoint} > ${hilimit} } { + error "setpoint ${setpoint} violates limits (${lolimit}..${hilimit}) on [sct]" + } + return OK + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to request the read of a parameter on a device +proc ::scobj::isotech_ps::getValue {tc_root nextState cmd_str} { + set catch_status [ catch { + debug_log 1 "getValue tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set cmd "${cmd_str}" +# hook code goes here + debug_log 1 "getValue sct send ${cmd}" + if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { + sct send "${cmd}" + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to check the write parameter on a device +proc ::scobj::isotech_ps::noResponse {tc_root} { + set catch_status [ catch { + debug_log 1 "noResponse tc_root=${tc_root} sct=[sct] resp=[sct result]" +# hook code goes here + return "idle" + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to parse the read of a parameter on a device +proc ::scobj::isotech_ps::rdValue {tc_root} { + set catch_status [ catch { + debug_log 1 "rdValue tc_root=${tc_root} sct=[sct] result=[sct result]" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set data [sct result] + set nextState "idle" + if {[string equal -nocase -length 7 ${data} "ASCERR:"]} { + # the protocol driver has reported an error + sct geterror "${data}" + error "[sct geterror]" + } +# hook code starts + set data [string range [sct result] 1 end] +# hook code ends + if { [hpropexists [sct] geterror] } { + debug_log 1 "[sct] error: [sct geterror]" + error "[sct geterror]" + } + if { ${data} != [sct oldval] } { + debug_log 1 "[sct] changed to new:${data}, from old:[sct oldval]" + sct oldval ${data} + sct update ${data} + sct utime readtime + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to parse the read of a parameter on a device +proc ::scobj::isotech_ps::read_relay {tc_root} { + set catch_status [ catch { + debug_log 1 "read_relay tc_root=${tc_root} sct=[sct] result=[sct result]" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set data [sct result] + set nextState "idle" + if {[string equal -nocase -length 7 ${data} "ASCERR:"]} { + # the protocol driver has reported an error + sct geterror "${data}" + error "[sct geterror]" + } +# hook code starts + if { [string equal -nocase -length 2 "F1" "${data}"] } { + set data 1 + } elseif { [string equal -nocase -length 2 "F0" "${data}"] } { + set data 0 + } else { + sct geterror "Unexpected response '${data}' not 'F1' nor 'F0'" + } +# hook code ends + if { [hpropexists [sct] geterror] } { + debug_log 1 "[sct] error: [sct geterror]" + error "[sct geterror]" + } + if { ${data} != [sct oldval] } { + debug_log 1 "[sct] changed to new:${data}, from old:[sct oldval]" + sct oldval ${data} + sct update ${data} + sct utime readtime + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to write a parameter value on a device +proc ::scobj::isotech_ps::setValue {tc_root nextState cmd_str} { + set catch_status [ catch { + debug_log 1 "setValue tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set par [sct target] + set cmd "${cmd_str}${par}" +# hook code goes here + if { [hpropexists [sct] driving] } { + if { [hpropexists [sct] writestatus] && [sct writestatus] == "start" } { + sct driving 1 + } + } + debug_log 1 "setValue sct send ${cmd}" + if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { + sct send "${cmd}" + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to write a parameter value on a device +proc ::scobj::isotech_ps::write_relay {tc_root nextState cmd_str} { + set catch_status [ catch { + debug_log 1 "write_relay tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set par [sct target] + set cmd "${cmd_str}${par}" +# hook code starts + if { ${par} == 0 } { + set cmd "KOD" + } else { + set cmd "KOE" + } +# hook code ends + if { [hpropexists [sct] geterror] } { + debug_log 1 "[sct] error: [sct geterror]" + error "[sct geterror]" + } + if { [hpropexists [sct] driving] } { + if { [hpropexists [sct] writestatus] && [sct writestatus] == "start" } { + sct driving 1 + } + } + debug_log 1 "write_relay sct send ${cmd}" + if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { + sct send "${cmd}" + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to write a parameter value on a device +proc ::scobj::isotech_ps::write_voltage {tc_root nextState cmd_str} { + set catch_status [ catch { + debug_log 1 "write_voltage tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set par [sct target] + set cmd "${cmd_str}${par}" +# hook code starts + set par "[format "%05.2f" [sct target]]" + set cmd "SV ${par}" +# hook code ends + if { [hpropexists [sct] geterror] } { + debug_log 1 "[sct] error: [sct geterror]" + error "[sct geterror]" + } + if { [hpropexists [sct] driving] } { + if { [hpropexists [sct] writestatus] && [sct writestatus] == "start" } { + sct driving 1 + } + } + debug_log 1 "write_voltage sct send ${cmd}" + if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { + sct send "${cmd}" + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +proc ::scobj::isotech_ps::mk_sct_isotech_ps { sct_controller name } { + debug_log 1 "mk_sct_isotech_ps for ${name}" + set ns "[namespace current]" + set catch_status [ catch { + + MakeSICSObj ${name} SCT_OBJECT + + sicslist setatt ${name} klass environment + sicslist setatt ${name} long_name ${name} + + set scobj_hpath /sics/${name} + + hfactory ${scobj_hpath}/amps plain user float + hsetprop ${scobj_hpath}/amps read ${ns}::getValue ${scobj_hpath} rdValue {A} + hsetprop ${scobj_hpath}/amps rdValue ${ns}::rdValue ${scobj_hpath} + hsetprop ${scobj_hpath}/amps control true + hsetprop ${scobj_hpath}/amps data true + hsetprop ${scobj_hpath}/amps mutable true + hsetprop ${scobj_hpath}/amps nxsave true + hsetprop ${scobj_hpath}/amps units A + hsetprop ${scobj_hpath}/amps oldval 0.0 + hsetprop ${scobj_hpath}/amps sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/amps type "part" + hsetprop ${scobj_hpath}/amps nxalias "${name}_amps" + + hfactory ${scobj_hpath}/relay plain user int + hsetprop ${scobj_hpath}/relay read ${ns}::getValue ${scobj_hpath} read_relay {F} + hsetprop ${scobj_hpath}/relay read_relay ${ns}::read_relay ${scobj_hpath} + hsetprop ${scobj_hpath}/relay write ${ns}::write_relay ${scobj_hpath} noResponse {KO} + hsetprop ${scobj_hpath}/relay noResponse ${ns}::noResponse ${scobj_hpath} + hsetprop ${scobj_hpath}/relay check ${ns}::checkrange ${scobj_hpath} + hsetprop ${scobj_hpath}/relay control true + hsetprop ${scobj_hpath}/relay data true + hsetprop ${scobj_hpath}/relay mutable true + hsetprop ${scobj_hpath}/relay nxsave true + hsetprop ${scobj_hpath}/relay oldval 0 + hsetprop ${scobj_hpath}/relay sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/relay type "part" + hsetprop ${scobj_hpath}/relay nxalias "${name}_relay" + + hfactory ${scobj_hpath}/volts plain user float + hsetprop ${scobj_hpath}/volts read ${ns}::getValue ${scobj_hpath} rdValue {V} + hsetprop ${scobj_hpath}/volts rdValue ${ns}::rdValue ${scobj_hpath} + hsetprop ${scobj_hpath}/volts write ${ns}::write_voltage ${scobj_hpath} noResponse {SV} + hsetprop ${scobj_hpath}/volts noResponse ${ns}::noResponse ${scobj_hpath} + hsetprop ${scobj_hpath}/volts check ${ns}::checkrange ${scobj_hpath} + hsetprop ${scobj_hpath}/volts control true + hsetprop ${scobj_hpath}/volts data true + hsetprop ${scobj_hpath}/volts mutable true + hsetprop ${scobj_hpath}/volts nxsave true + hsetprop ${scobj_hpath}/volts units V + hsetprop ${scobj_hpath}/volts oldval 0.0 + hsetprop ${scobj_hpath}/volts sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/volts type "part" + hsetprop ${scobj_hpath}/volts nxalias "${name}_volts" + + if {[SplitReply [environment_simulation]]=="false"} { + ${sct_controller} poll ${scobj_hpath}/amps 5 + ${sct_controller} poll ${scobj_hpath}/relay 5 + ${sct_controller} poll ${scobj_hpath}/volts 5 + ${sct_controller} write ${scobj_hpath}/relay + ${sct_controller} write ${scobj_hpath}/volts + } + hsetprop ${scobj_hpath} klass environment +# hook code goes here + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +namespace eval ::scobj::isotech_ps { + namespace export debug_log + namespace export mk_sct_isotech_ps +} + +proc add_isotech_ps {name IP port} { + set catch_status [ catch { + set ns "::scobj::isotech_ps" + ${ns}::debug_log 1 "add_isotech_ps ${name} ${IP} ${port}" + if {[SplitReply [environment_simulation]]=="false"} { + if {[string equal -nocase "aqadapter" "${IP}"]} { + ${ns}::debug_log 1 "makesctcontroller sct_${name} aqadapter ${port}" + makesctcontroller sct_${name} aqadapter ${port} + } else { + ${ns}::debug_log 1 "makesctcontroller sct_${name} std ${IP}:${port} \"\\r\"" + makesctcontroller sct_${name} std ${IP}:${port} "\r" + } + } + ${ns}::debug_log 1 "mk_sct_isotech_ps sct_${name} ${name}" + ${ns}::mk_sct_isotech_ps sct_${name} ${name} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +puts stdout "file evaluation of sct_isotech_ps.tcl" +::scobj::isotech_ps::debug_log 1 "file evaluation of sct_isotech_ps.tcl" + +proc ::scobj::isotech_ps::read_config {} { + set catch_status [ catch { + set ns "::scobj::isotech_ps" + ${ns}::debug_log 1 "Processing Config" + dict for {k v} $::config_dict { + ${ns}::debug_log 1 "Inspecting $k:$v" + if { [dict exists $v "driver"] } { + ${ns}::debug_log 1 "Has driver [dict get $v driver]" + if { [dict get $v "driver"] == "isotech_ps" } { + ${ns}::debug_log 1 "Correct driver, enabled = [dict get $v enabled]" + if { [dict get $v enabled] } { + set IP [dict get $v ip] + set PORT [dict get $v port] + set name [dict get $v name] + MakeAsyncProtocol ${name}_protocol + MakeAsyncQueue ${name}_queue ${name}_protocol ${IP} ${PORT} + add_isotech_ps ${name} "aqadapter" ${name}_queue + } + } + } + } + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} +if { [info exists ::config_dict] } { + ::scobj::isotech_ps::read_config +} else { + ::scobj::isotech_ps:debug_log 1 "No config dict" +} diff --git a/site_ansto/instrument/config/environment/sct_syr.tcl b/site_ansto/instrument/config/environment/sct_syr.tcl index 095cc989..326487b1 100755 --- a/site_ansto/instrument/config/environment/sct_syr.tcl +++ b/site_ansto/instrument/config/environment/sct_syr.tcl @@ -468,7 +468,7 @@ sct print "halt $tc_root" proc createNode {scobj_hpath sct_controller cmdGroup varName readable writable nexus gumtree\ drivable dataType permission rdCmd rdFunc wrCmd\ wrFunc allowedValues klass} { - +debug_log "createNode cmdGroup = $cmdGroup" set catch_status [ catch { set ns "[namespace current]" set nodeName "$scobj_hpath/$cmdGroup/$varName" @@ -568,11 +568,11 @@ debug_log "Registering node $nodeName for write callback" } set num_pumps 2 - for {set i 0} { i < $num_pumps } { incr i } { + for {set i 0} { $i < $num_pumps } { incr i } { set cmdGroup "Pump[set i]" hfactory $scobj_hpath/[set cmdGroup] plain spy none foreach {cmdGroup varName readable writable nexus gumtree drivable dataType permission rdCmd rdFunc wrCmd wrFunc allowedValues} $deviceCommand { - createNode $scobj_hpath $sct_controller $cmdGroup $varName $readable $writable $nexus $gumtree $drivable $dataType $permission $rdCmd $rdFunc $wrCmd $wrFunc $allowedValues $klass + createNode $scobj_hpath $sct_controller ${cmdGroup}$i $varName $readable $writable $nexus $gumtree $drivable $dataType $permission $rdCmd $rdFunc $wrCmd $wrFunc $allowedValues $klass } } diff --git a/site_ansto/instrument/config/environment/temperature/julabo_lh45.sct b/site_ansto/instrument/config/environment/temperature/julabo_lh45.sct new file mode 100644 index 00000000..9c3ad69f --- /dev/null +++ b/site_ansto/instrument/config/environment/temperature/julabo_lh45.sct @@ -0,0 +1,111 @@ +# +# Simple driver generator for the Julabo LH45 +# vim: ts=8 sts=2 sw=2 expandtab autoindent smartindent nocindent +# +driver julabo_lh45_gen = { + vendor = julabo; device = lh45; protocol = std; + class = environment + simulation_group = environment_simulation + add_args = '{sensor "bath"} {tol 5.0}'; + make_args = 'sensor tol'; + protocol_args = '"\r"'; +# +# Unnamed group has variables at device level +# + group = { + priv = user + type = float + var setpoint = { + driveable = sensor/'value' + readable = 1 + read_command = 'in_sp_00' + write_function = setPoint + write_command = 'out_sp_00' + lowerlimit = 10 + upperlimit = 90 + tolerance = 2 + } + var overtemp_warnlimit = { + readable = 1 + read_command = 'in_sp_03' + #write_command = 'out_sp_03' + } + var subtemp_warnlimit = { + readable = 1 + read_command = 'in_sp_04' + #write_command = 'out_sp_04' + } + var heating_power_percent = { + readable = 1 + read_command = 'in_pv_01'; + }; + var power = { + readable = 1 + read_command = 'in_mode_05'; + writeable = 1; + write_command = 'out_mode_05'; + }; + var lh45_state = { + readable = 1 + read_command = 'status'; + fetch_function = getState + read_function = rdState + } + var lh45_lasterror = { type = text; } + var remote_ctrl = { type = text; priv = spy; } + } +# +# The named group is at the device level, variables below that +# + group sensor = { + type = float; + priv = internal; + readable = 1; + var 'value' = { read_command = 'in_pv_00'; units = 'C' }; + var bathtemp = { read_command = 'in_pv_00'; units = 'C' }; + }; + +# +# Code lines start with '@' which is stripped before being emitted into generated driver +# The code is emitted at the appropriate place in the given function +# + code read_function rdValue = { + } + code Write_function setPoint = { + } +# +# This code is after database creation +# + code mkDriver = { + @# TODO use the ${sensor} and ${tol} arguments + } + + code read_function rdState = { + @ if {${data} != [sct oldval]} { + @ debug_log 1 "[sct] changed to new:${data}, from old:[sct oldval]" + @ sct oldval ${data} + @ sct update ${data} + @ sct utime readtime + @ switch -- [lindex ${data} 0] { + @ "00" { + @ hset ${tc_root}/remote_ctrl False + @ } + @ "01" { + @ hset ${tc_root}/remote_ctrl False + @ } + @ "02" { + @ hset ${tc_root}/remote_ctrl True + @ } + @ "03" { + @ hset ${tc_root}/remote_ctrl True + @ } + @ default { + @ hset ${tc_root}/remote_ctrl UNKNOWN + @ hset ${tc_root}/lh45_lasterror ${data} + @ sct geterror ${data} + @ } + @ } + @ } + } + +}; diff --git a/site_ansto/instrument/config/environment/temperature/sct_lakeshore_218.tcl b/site_ansto/instrument/config/environment/temperature/sct_lakeshore_218.tcl index 7565d2bb..181864ce 100644 --- a/site_ansto/instrument/config/environment/temperature/sct_lakeshore_218.tcl +++ b/site_ansto/instrument/config/environment/temperature/sct_lakeshore_218.tcl @@ -78,11 +78,9 @@ proc ::scobj::ls218::rdValue {nodeName varName idx} { set replyData [string trimright [sct result] " \r\n"] if {[string first "ASCERR" $replyData] != -1} { - #broadcast "Error in LS218 Response: ASCERR:" sct geterror $replyData return -code error "Error in LS218 Response: $replyData" } elseif {[string length $replyData] < 1} { - #broadcast "Error in LS218 Response: no message returned from device" return -code error "Error in LS218: no message returned from device" } else { set fields [split $replyData ,] @@ -119,7 +117,6 @@ proc ::scobj::ls218::rdValue {nodeName varName idx} { } } "Celsius" { hset $nodeName [lindex $fields 0] - #append $logString " Celsius - $fields;" set curValue [lindex $fields 0] } "CurveHd" { hset $nodeName/curve [lindex $fields 0] @@ -193,33 +190,34 @@ proc ::scobj::ls218::rdValue {nodeName varName idx} { } } "mnmxValue" { hset $nodeName "[lindex $fields 0] , [lindex $fields 1]"} - "status" { hset $nodeName "" + "status" { # RDGST? chID Reads input status returns an integer with the following meaning # Bit Weighting StatusIndicator # 4 16 temp underrange # 5 32 temp overrange # 6 64 units under range # 7 128 untis over range - set curValue $fields set field [string trimleft $fields 0] if {[string length $field] == 0} { set field 0 - } - set stateString "" - set i [format %x $field] + } + + set str "" + set i [format %x $field] set i [expr 0x$i >> 4] set bitValue [expr 0x$i & 0x01] - if {$bitValue == 1} { append $stateString "temp underrange; " } + if {$bitValue == 1} { append str "temp underrange, " } set i [expr 0x$i >> 1] set bitValue [expr 0x$i & 0x01] - if {$bitValue == 1} { append $stateString "temp overrange; " } + if {$bitValue == 1} { append str "temp overrange, " } set i [expr 0x$i >> 1] set bitValue [expr 0x$i & 0x01] - if {$bitValue == 1} { append $stateString "units under range; " } + if {$bitValue == 1} { append str "units under range, " } set i [expr 0x$i >> 1] set bitValue [expr 0x$i & 0x01] - if {$bitValue == 1} { append $stateString "untis over range; " } - hset $nodeName $stateString + if {$bitValue == 1} { append str "untis over range" } + + hset $nodeName $str } "SensorUnitValue" { hset $nodeName $fields #append $logString " SensorUnitValue - $fields;" @@ -350,7 +348,7 @@ proc createNode {scobj_hpath idx sct_controller cmdGroup varName readable pollEn if {$pollEnabled == 1} { if {[SplitReply [environment_simulation]]=="false"} { # puts "enabling polling for $nodeName" - $sct_controller poll $nodeName + $sct_controller poll $nodeName 3 } } } message ]} { @@ -622,14 +620,16 @@ proc ::scobj::ls218::mkLS218 {argList} { # @internal time internal in polling the nodes # @return nothing (well, the sct object) +MakeAsyncProtocol std +MakeAsyncQueue ls218 std 137.157.202.214 4002 ::scobj::ls218::mkLS218 { name ls218 - IP 137.157.202.214 - PORT 4002 + IP aqadapter + PORT ls218 tuning 1 interval 5 - inputChan {1 2} - outputChan {} - relayChan {} + inputChan {1 2 3 4 5 6 7 8} + outputChan {1 2} + relayChan {1 2 3 4 5 6 7 8} } diff --git a/site_ansto/instrument/config/environment/temperature/sct_lakeshore_336.tcl b/site_ansto/instrument/config/environment/temperature/sct_lakeshore_336.tcl index fe06d19d..968d16cf 100644 --- a/site_ansto/instrument/config/environment/temperature/sct_lakeshore_336.tcl +++ b/site_ansto/instrument/config/environment/temperature/sct_lakeshore_336.tcl @@ -1579,7 +1579,7 @@ proc createNode {scobj_hpath sct_controller cmdGroup varName readable writable p # @param tempobj short name for the temperature controller scriptcontext object (typ. tc1 or tc2) # @param tol temperature tolerance in Kelvin (typ. 1) # @return nothing (well, the sct object) - proc mk_sct_lakeshore_336 {sct_controller klasse tempobj tol1 tol2 verbose} { + proc mk_sct_lakeshore_336 {sct_controller klasse tempobj CID CTYPE tol1 tol2 verbose} { if {[ catch { MakeSICSObj $tempobj SCT_OBJECT sicslist setatt $tempobj klass $klasse @@ -1846,7 +1846,22 @@ proc createNode {scobj_hpath sct_controller cmdGroup varName readable writable p # Problem: Does not write non-numbers to the hdf file unless told differently - but how? # How can I make it write the NAME (or any character/string variable) to the hdf file? # ::scobj::hinitprops $tempobj/sensor sampleSensor + hsetprop $scobj_hpath/sensor/setpoint1 permlink data_set ${CTYPE}${CID}SP1 + hsetprop $scobj_hpath/sensor/setpoint1 @description ${CTYPE}${CID}SP1 + hsetprop $scobj_hpath/sensor/setpoint2 permlink data_set ${CTYPE}${CID}SP2 + hsetprop $scobj_hpath/sensor/setpoint2 @description ${CTYPE}${CID}SP2 + hsetprop $scobj_hpath/sensor/sensorValueA permlink data_set ${CTYPE}${CID}S1 + hsetprop $scobj_hpath/sensor/sensorValueA @description ${CTYPE}${CID}S1 + hsetprop $scobj_hpath/sensor/sensorValueB permlink data_set ${CTYPE}${CID}S2 + hsetprop $scobj_hpath/sensor/sensorValueB @description ${CTYPE}${CID}S2 + hsetprop $scobj_hpath/sensor/sensorValueC permlink data_set ${CTYPE}${CID}S3 + hsetprop $scobj_hpath/sensor/sensorValueC @description ${CTYPE}${CID}S3 + hsetprop $scobj_hpath/sensor/sensorValueD permlink data_set ${CTYPE}${CID}S4 + hsetprop $scobj_hpath/sensor/sensorValueD @description ${CTYPE}${CID}S4 + + hsetprop $scobj_hpath/sensor/setpoint1 type drivable + hsetprop $scobj_hpath/sensor/setpoint2 type drivable ansto_makesctdrive ${tempobj}_driveable $scobj_hpath/sensor/setpoint1 $scobj_hpath/sensor/ctrlLp1_value $sct_controller ansto_makesctdrive ${tempobj}_driveable2 $scobj_hpath/sensor/setpoint2 $scobj_hpath/sensor/ctrlLp2_value $sct_controller @@ -1871,7 +1886,7 @@ proc createNode {scobj_hpath sct_controller cmdGroup varName readable writable p # @param port port number on the moxabox (typ. 4001, 4002, 4003, or 4004) # @param tol temperature tolerance in Kelvin (typ. 1) # @return nothing (well, the sct object) -proc add_sct_ls336 {name IP port terminator {_tol1 1.0} {_tol2 1.0} {_verbose 0} } { +proc add_sct_ls336 {name IP port terminator {_tol1 1.0} {_tol2 1.0} {CID 1} {CTYPE T} {_verbose 0} } { # ffr 2009-11-09, Don't create a temperature controller for the script validator, this causes the # lakeshore to lock up. # NOTE: I put this outside the catch block because "return" raises an exception @@ -1885,9 +1900,9 @@ proc add_sct_ls336 {name IP port terminator {_tol1 1.0} {_tol2 1.0} {_verbose 0} makesctcontroller sct_ls336_$name aqadapter ${port} } else { puts "\nadd_ls336: makesctcontroller sct_ls336_$name std ${IP}:$port $terminator for Lakeshore model 336" - makesctcontroller sct_ls336_$name std ${IP}:$port $terminator + makesctcontroller sct_ls336_$name std ${IP}:$port {*}$terminator } - mk_sct_lakeshore_336 sct_ls336_$name environment $name $_tol1 $_tol2 $_verbose + ::scobj::ls336::mk_sct_lakeshore_336 sct_ls336_$name environment $name $CID $CTYPE $_tol1 $_tol2 $_verbose makesctemon $name /sics/$name/emon/monMode_Lp1 /sics/$name/emon/isInTolerance_Lp1 /sics/$name/emon/errhandler # set m2 "_2" # makesctemon $name$m2 /sics/$name/emon/monMode_Lp2 /sics/$name/emon/isInTolerance_Lp2 /sics/$name/emon/errhandler @@ -1896,4 +1911,34 @@ proc add_sct_ls336 {name IP port terminator {_tol1 1.0} {_tol2 1.0} {_verbose 0} } } +if {[ catch { +if { [ info exists ::config_dict ] } { + if { [ dict get $::config_dict ls336_1 enabled ] } { + set IP [dict get $::config_dict ls336_1 ip] + set PORT [dict get $::config_dict ls336_1 port] + set name [dict get $::config_dict ls336_1 name] + set ctype [dict get $::config_dict ls336_1 type] + set cid [dict get $::config_dict ls336_1 id] + set term [dict get $::config_dict ls336_1 terminator] + set tol1 [dict get $::config_dict ls336_1 tol1] + set tol2 [dict get $::config_dict ls336_1 tol2] + + add_sct_ls336 $name $IP $PORT $term $tol1 $tol2 $cid $ctype + } + if { [ dict get $::config_dict ls336_2 enabled ] } { + set IP [dict get $::config_dict ls336_2 ip] + set PORT [dict get $::config_dict ls336_2 port] + set name [dict get $::config_dict ls336_2 name] + set ctype [dict get $::config_dict ls336_2 type] + set cid [dict get $::config_dict ls336_2 id] + set term [dict get $::config_dict ls336_2 terminator] + set tol1 [dict get $::config_dict ls336_2 tol1] + set tol2 [dict get $::config_dict ls336_2 tol2] + + add_sct_ls336 $name $IP $PORT $term $tol1 $tol2 $cid $ctype + } + } +} message ]} { + puts "ERROR: $message" +} namespace import ::scobj::ls336::* diff --git a/site_ansto/instrument/config/environment/temperature/sct_lakeshore_340.tcl b/site_ansto/instrument/config/environment/temperature/sct_lakeshore_340.tcl index 06b67d83..38fc2e21 100644 --- a/site_ansto/instrument/config/environment/temperature/sct_lakeshore_340.tcl +++ b/site_ansto/instrument/config/environment/temperature/sct_lakeshore_340.tcl @@ -1755,7 +1755,7 @@ proc createNode {scobj_hpath sct_controller cmdGroup varName readable writable p # @param tempobj short name for the temperature controller scriptcontext object (typ. tc1 or tc2) # @param tol temperature tolerance in Kelvin (typ. 1) # @return nothing (well, the sct object) - proc mk_sct_lakeshore_340 {sct_controller klasse tempobj LSmodel tol1 tol2 verbose} { + proc mk_sct_lakeshore_340 {sct_controller klasse tempobj CID CTYPE LSmodel tol1 tol2 verbose} { if {[ catch { set ::scobj::ls340::ls340_driveTolerance1 $tol1 set ::scobj::ls340::ls340_driveTolerance2 $tol2 @@ -2050,6 +2050,19 @@ proc createNode {scobj_hpath sct_controller cmdGroup varName readable writable p # Problem: Does not write non-numbers to the hdf file unless told differently - but how? # How can I make it write the NAME (or any character/string variable) to the hdf file? # ::scobj::hinitprops $tempobj/sensor sampleSensor + hsetprop $scobj_hpath/sensor/setpoint1 permlink data_set ${CTYPE}${CID}SP1 + hsetprop $scobj_hpath/sensor/setpoint1 @description ${CTYPE}${CID}SP1 + hsetprop $scobj_hpath/sensor/setpoint2 permlink data_set ${CTYPE}${CID}SP2 + hsetprop $scobj_hpath/sensor/setpoint2 @description ${CTYPE}${CID}SP2 + + hsetprop $scobj_hpath/sensor/sensorValueA permlink data_set ${CTYPE}${CID}S1 + hsetprop $scobj_hpath/sensor/sensorValueA @description ${CTYPE}${CID}S1 + hsetprop $scobj_hpath/sensor/sensorValueB permlink data_set ${CTYPE}${CID}S2 + hsetprop $scobj_hpath/sensor/sensorValueB @description ${CTYPE}${CID}S2 + hsetprop $scobj_hpath/sensor/sensorValueC permlink data_set ${CTYPE}${CID}S3 + hsetprop $scobj_hpath/sensor/sensorValueC @description ${CTYPE}${CID}S3 + hsetprop $scobj_hpath/sensor/sensorValueD permlink data_set ${CTYPE}${CID}S4 + hsetprop $scobj_hpath/sensor/sensorValueD @description ${CTYPE}${CID}S4 hsetprop $scobj_hpath/sensor/setpoint1 type drivable hsetprop $scobj_hpath/sensor/setpoint2 type drivable @@ -2077,7 +2090,7 @@ proc createNode {scobj_hpath sct_controller cmdGroup varName readable writable p # @param port port number on the moxabox (typ. 4001, 4002, 4003, or 4004) # @param tol temperature tolerance in Kelvin (typ. 1) # @return nothing (well, the sct object) -proc add_sct_ls340 {name IP port terminator {_tol1 1.0} {_tol2 1.0} {_verbose 0} } { +proc add_sct_ls340 {name IP port terminator {_tol1 1.0} {_tol2 1.0} {CID 1} {CTYPE T} {_verbose 0} } { # ffr 2009-11-09, Don't create a temperature controller for the script validator, this causes the # lakeshore to lock up. # NOTE: I put this outside the catch block because "return" raises an exception @@ -2091,9 +2104,9 @@ proc add_sct_ls340 {name IP port terminator {_tol1 1.0} {_tol2 1.0} {_verbose 0} makesctcontroller sct_ls340_$name aqadapter ${port} } else { puts "\nadd_ls340: makesctcontroller sct_ls340_$name std ${IP}:$port $terminator for Lakeshore model 340" - makesctcontroller sct_ls340_$name std ${IP}:$port $terminator + makesctcontroller sct_ls340_$name std ${IP}:$port {*}$terminator } - mk_sct_lakeshore_340 sct_ls340_$name environment $name $_ls340_LSmodel $_tol1 $_tol2 $_verbose + ::scobj::ls340::mk_sct_lakeshore_340 sct_ls340_$name environment $name $CID $CTYPE $_ls340_LSmodel $_tol1 $_tol2 $_verbose makesctemon $name /sics/$name/emon/monMode_Lp1 /sics/$name/emon/isInTolerance_Lp1 /sics/$name/emon/errhandler # set m2 "_2" # makesctemon $name$m2 /sics/$name/emon/monMode_Lp2 /sics/$name/emon/isInTolerance_Lp2 /sics/$name/emon/errhandler @@ -2102,16 +2115,34 @@ proc add_sct_ls340 {name IP port terminator {_tol1 1.0} {_tol2 1.0} {_verbose 0} } } +if {[ catch { if { [ info exists ::config_dict ] } { if { [ dict get $::config_dict ls340_1 enabled ] } { - set IP [dict get $::config_dict ls340_1 ip] - set PORT [dict get $::config_dict ls340_1 port] - set name [dict get $::config_dict ls340_1 name] - set term [dict get $::config_dict ls340_1 terminator] - set tol1 [dict get $::config_dict ls340_1 tol1] - set tol2 [dict get $::config_dict ls340_1 tol2] + set IP [dict get $::config_dict ls340_1 ip] + set PORT [dict get $::config_dict ls340_1 port] + set name [dict get $::config_dict ls340_1 name] + set ctype [dict get $::config_dict ls340_1 type] + set cid [dict get $::config_dict ls340_1 id] + set term [dict get $::config_dict ls340_1 terminator] + set tol1 [dict get $::config_dict ls340_1 tol1] + set tol2 [dict get $::config_dict ls340_1 tol2] - add_sct_ls340 $name $IP $PORT $term $tol1 $tol2 + add_sct_ls340 $name $IP $PORT $term $tol1 $tol2 $cid $ctype } + if { [ dict get $::config_dict ls340_2 enabled ] } { + set IP [dict get $::config_dict ls340_2 ip] + set PORT [dict get $::config_dict ls340_2 port] + set name [dict get $::config_dict ls340_2 name] + set ctype [dict get $::config_dict ls340_2 type] + set cid [dict get $::config_dict ls340_2 id] + set term [dict get $::config_dict ls340_2 terminator] + set tol1 [dict get $::config_dict ls340_2 tol1] + set tol2 [dict get $::config_dict ls340_2 tol2] + + add_sct_ls340 $name $IP $PORT $term $tol1 $tol2 $cid $ctype + } + } +} message ]} { + puts "ERROR: $message" } namespace import ::scobj::ls340::* diff --git a/site_ansto/instrument/config/environment/temperature/sct_lakeshore_370.tcl b/site_ansto/instrument/config/environment/temperature/sct_lakeshore_370.tcl index 3efef3f9..8f0be9db 100644 --- a/site_ansto/instrument/config/environment/temperature/sct_lakeshore_370.tcl +++ b/site_ansto/instrument/config/environment/temperature/sct_lakeshore_370.tcl @@ -74,25 +74,6 @@ namespace eval ::scobj::[set vendor]_[set device] { debug_log 1 "Extract channel $result from argument $arg" return $result } - proc basename {node} { - set point [string last "/" $node] - if { $point < 0 } { - return $node - } else { - incr point - return "[string range $node $point end]" - } - } - proc pathname {node} { - set point [string last "/" $node] - if { $point < 0 } { - return "" - } else { - incr point -1 - return "[string range $node 0 $point]" - } - return "[join [lrange [split $node '/'] 0 end-1] '/']" - } proc setValue {tc_root nextState cmd} { # send a command to set a value @@ -948,13 +929,13 @@ namespace import ::scobj::[set vendor]_[set device]::* # add_lakeshore_370 "tc371" 127.0.0.1 7371 2.0 -if { [ info exists ::config_dict ] && [ dict get $::config_dict ls370_2 enabled ] } { +if { [ info exists ::config_dict ] && [ dict get $::config_dict ls370 enabled ] } { puts "ADD LAKESHORE 370" - set IP [dict get $::config_dict ls370_2 ip] - set PORT [dict get $::config_dict ls370_2 port] - set NAME [dict get $::config_dict ls370_2 name] - set TOL [dict get $::config_dict ls370_2 tol] - set TERM [dict get $::config_dict ls370_2 terminator] + set IP [dict get $::config_dict ls370 ip] + set PORT [dict get $::config_dict ls370 port] + set NAME [dict get $::config_dict ls370 name] + set TOL [dict get $::config_dict ls370 tol] + set TERM [dict get $::config_dict ls370 terminator] add_lakeshore_370 $NAME $IP $PORT $TOL } diff --git a/site_ansto/instrument/config/environment/temperature/sct_oxford_mercury.tcl b/site_ansto/instrument/config/environment/temperature/sct_oxford_mercury.tcl index e7413d9f..fada3e70 100644 --- a/site_ansto/instrument/config/environment/temperature/sct_oxford_mercury.tcl +++ b/site_ansto/instrument/config/environment/temperature/sct_oxford_mercury.tcl @@ -80,25 +80,6 @@ namespace eval ::scobj::[set vendor]_[set device] { debug_log 1 "Extract channel $result from argument $arg" return $result } - proc basename {node} { - set point [string last "/" $node] - if { $point < 0 } { - return $node - } else { - incr point - return "[string range $node $point end]" - } - } - proc pathname {node} { - set point [string last "/" $node] - if { $point < 0 } { - return "" - } else { - incr point -1 - return "[string range $node 0 $point]" - } - return "[join [lrange [split $node '/'] 0 end-1] '/']" - } proc setPoint {tc_root nextState cmd} { # send a command to set a value @@ -703,8 +684,8 @@ namespace eval ::scobj::[set vendor]_[set device] { return OK } - proc mk_sct_driver {sct_controller the_klass the_name tol} { - debug_log 1 "mk_sct_driver $sct_controller $the_klass $the_name $tol" + proc mk_sct_driver {sct_controller the_klass the_name tol CID CTYPE} { + debug_log 1 "mk_sct_driver $sct_controller $the_klass $the_name $tol $CID $CTYPE" set catch_status [ catch { MakeSICSObj $the_name SCT_OBJECT @@ -845,7 +826,31 @@ if {0} { debug_log 5 "error in [ns]::mk_sct_driver($point) $catch_message_2" return -code error "in [ns]::mk_sct_driver($point) $catch_message_2" } + hsetprop $scobj_hpath/Loop1/setpoint permlink data_set ${CTYPE}${CID}SP1 + hsetprop $scobj_hpath/Loop1/setpoint @description ${CTYPE}${CID}SP1 + hsetprop $scobj_hpath/Loop1/setpoint permlink data_set ${CTYPE}${CID}SP1 + hsetprop $scobj_hpath/Loop1/setpoint @description ${CTYPE}${CID}SP1 + hsetprop $scobj_hpath/Loop2/setpoint permlink data_set ${CTYPE}${CID}SP2 + hsetprop $scobj_hpath/Loop2/setpoint @description ${CTYPE}${CID}SP2 + hsetprop $scobj_hpath/Loop3/setpoint permlink data_set ${CTYPE}${CID}SP3 + hsetprop $scobj_hpath/Loop3/setpoint @description ${CTYPE}${CID}SP3 + hsetprop $scobj_hpath/Loop4/setpoint permlink data_set ${CTYPE}${CID}SP4 + hsetprop $scobj_hpath/Loop4/setpoint @description ${CTYPE}${CID}SP4 + + hsetprop $scobj_hpath/Loop1/sensor permlink data_set ${CTYPE}${CID}S1 + hsetprop $scobj_hpath/Loop1/sensor @description ${CTYPE}${CID}S1 + hsetprop $scobj_hpath/Loop2/sensor permlink data_set ${CTYPE}${CID}S2 + hsetprop $scobj_hpath/Loop2/sensor @description ${CTYPE}${CID}S2 + hsetprop $scobj_hpath/Loop3/sensor permlink data_set ${CTYPE}${CID}S3 + hsetprop $scobj_hpath/Loop3/sensor @description ${CTYPE}${CID}S3 + hsetprop $scobj_hpath/Loop4/sensor permlink data_set ${CTYPE}${CID}S4 + hsetprop $scobj_hpath/Loop4/sensor @description ${CTYPE}${CID}S4 + if {[SplitReply [environment_simulation]]=="false"} { + hsetprop $scobj_hpath/Loop1/setpoint type drivable + hsetprop $scobj_hpath/Loop2/setpoint type drivable + hsetprop $scobj_hpath/Loop3/setpoint type drivable + hsetprop $scobj_hpath/Loop4/setpoint type drivable ansto_makesctdrive ${the_name}_loop1 $scobj_hpath/Loop1/setpoint $scobj_hpath/Loop1/sensor $sct_controller ansto_makesctdrive ${the_name}_loop2 $scobj_hpath/Loop2/setpoint $scobj_hpath/Loop2/sensor $sct_controller ansto_makesctdrive ${the_name}_loop3 $scobj_hpath/Loop3/setpoint $scobj_hpath/Loop3/sensor $sct_controller @@ -858,9 +863,9 @@ if {0} { } } - proc add_[set vendor]_[set device] {the_name IP port {_tol 5.0}} { + proc add_[set vendor]_[set device] {the_name IP port CID CTYPE terminator {_tol 5.0}} { set [ns]::log_file "/tmp/[set [ns]::ven_dev]_[set the_name].log" - set fd [open [ns]::log_file "w"] + set fd [open [set [ns]::log_file] "w"] close $fd debug_log 1 "add_[set [ns]::vendor]_[set [ns]::device] ${the_name} ${IP} ${port} ${_tol}" puts "Namespace: [namespace current]" @@ -872,10 +877,10 @@ if {0} { puts "[namespace current]::log_file [set [namespace current]::log_file]" if {[SplitReply [environment_simulation]]=="false"} { debug_log 1 "makesctcontroller sct_${the_name} std ${IP}:${port}" - makesctcontroller sct_${the_name} std ${IP}:${port} "\r\n" + makesctcontroller sct_${the_name} std ${IP}:${port} {*}$terminator } - debug_log 1 "mk_sct_driver sct_${the_name} environment ${the_name} ${_tol}" - mk_sct_driver sct_${the_name} environment ${the_name} ${_tol} + debug_log 1 "::scobj::oxford_mercury::mk_sct_driver sct_${the_name} environment ${the_name} ${_tol} $CID $CTYPE" + ::scobj::oxford_mercury::mk_sct_driver sct_${the_name} environment ${the_name} ${_tol} $CID $CTYPE } @@ -890,8 +895,11 @@ if { [ info exists ::config_dict ] && [ dict get $::config_dict mercury_scipi en puts "ADD MERCURY SCIPI MODE" set IP [dict get $::config_dict mercury_scipi ip] set PORT [dict get $::config_dict mercury_scipi port] - set NAME [dict get $::config_dict mercury_scipi name] - set TOL [dict get $::config_dict mercury_scipi tol] - add_oxford_mercury $NAME $IP $PORT 2.0 "\r" + set name [dict get $::config_dict mercury_scipi name] + set ctype [dict get $::config_dict mercury_scipi type] + set cid [dict get $::config_dict mercury_scipi id] + set tol [dict get $::config_dict mercury_scipi tol] + set term [dict get $::config_dict mercury_scipi terminator] + add_oxford_mercury $name $IP $PORT $cid $ctype {*}$term $tol } diff --git a/site_ansto/instrument/config/environment/temperature/sct_rvasm2.tcl b/site_ansto/instrument/config/environment/temperature/sct_rvasm2.tcl index 323aba35..5c5021a1 100644 --- a/site_ansto/instrument/config/environment/temperature/sct_rvasm2.tcl +++ b/site_ansto/instrument/config/environment/temperature/sct_rvasm2.tcl @@ -62,7 +62,7 @@ debug_log "rdValue [sct] [sct result]" hsetprop $tc_root/setpoint driving 1 } # ANSTO special temperature - set temp [expr {10.0 * [sct target]}] + set temp [expr {20.0 * [sct target]}] set cmd "STT[format %04X [expr {int($temp)}]]" debug_log "sct send $cmd" sct send "$cmd" @@ -103,7 +103,7 @@ debug_log "rdValue [sct] [sct result]" debug_log "scan [string range $data 3 6] %4x data" set rslt [scan [string range $data 3 6] %4x data] # ANSTO special temp - set data [format "%.1f" [expr {0.1 * $data}]] + set data [format "%.1f" [expr {$data / 20.0}]] debug_log "scan result rslt=$rslt, data=$data, oldval=[sct oldval]" if {"$data" ne "[sct oldval]"} { debug_log "$data != [sct oldval] => [expr {"$data" != "[sct oldval]"}]" @@ -436,7 +436,7 @@ debug_log "rdVisc [sct] [sct result]" close $f set f [open "[sct datafile].csv" "a"] set my_time [expr {[sct test_time] + int($the_t / 45.0)}] - set my_temp [expr {0.1 * $the_c}] + set my_temp [expr {$the_c / 20.0}] if {$the_v > 0x7FFFFF} { set my_visc [expr {$the_v - 0x1000000}] } else { @@ -547,12 +547,12 @@ debug_log "setPoint $cmd $par" set the_valu [lindex $parts 2] set the_ramp [lindex $parts 3] if {$the_type == "I"} { - set the_valu [expr {round($the_valu * 10.0)}] - set the_ramp [expr {round($the_ramp * 10.0)}] + set the_valu [expr {round($the_valu * 20.0)}] + set the_ramp [expr {round($the_ramp * 20.0)}] } elseif {$the_type == "S"} { } elseif {$the_type == "T"} { - set the_valu [expr {round($the_valu * 10.0)}] - set the_ramp [expr {round($the_ramp * 10.0 /45 * 32768)}] + set the_valu [expr {round($the_valu * 20.0)}] + set the_ramp [expr {round($the_ramp * 20.0 /45 * 32768)}] } else { sct geterror "Profile error: $line" sct print "Profile error: $line" @@ -580,7 +580,7 @@ debug_log "setPoint $cmd $par" } set rslt [scan $line "LT%2x%1s%6x%4x%4x" the_line the_type the_time the_valu the_ramp] if {"$the_type" == "I"} { - set dec_temp [format "%.1f" [expr {0.1 * $the_valu}]] + set dec_temp [format "%.1f" [expr {$the_valu / 20.0}]] } set dec_time [expr {$the_time / 45.0}] lappend lines $line diff --git a/site_ansto/instrument/config/environment/temperature/sct_watlow_rm.tcl b/site_ansto/instrument/config/environment/temperature/sct_watlow_rm.tcl index cd9f143c..92067ff1 100644 --- a/site_ansto/instrument/config/environment/temperature/sct_watlow_rm.tcl +++ b/site_ansto/instrument/config/environment/temperature/sct_watlow_rm.tcl @@ -179,6 +179,7 @@ debug_log "setValue $dev:16:$cmd $par" if {[string first "ASCERR:" $data] >=0} { sct geterror $data } elseif {$data != [sct oldval]} { + hdelprop [sct] geterror sct oldval $data sct update $data sct utime readtime @@ -221,6 +222,13 @@ debug_log "setValue $dev:16:$cmd $par" proc setSP {tc_root nextState cmd} { debug_log "setSP $tc_root $nextState $cmd [sct]=[sct target] [hget [sct]]" + debug_log "setSP sct = [sct], sct writestatus = [sct writestatus]" + if {[sct writestatus] == "start"} { + # Called by drive adapter + hset $tc_root/status "busy" + debug_log "setSP hsetprop $tc_root/setpoint driving 1" + hsetprop $tc_root/setpoint driving 1 + } hset $tc_root/Loop1/setpoint [sct target] return idle } @@ -502,7 +510,7 @@ proc createNode {scobj_hpath sct_controller cmdGroup varName readable writable\ } ::scobj::hinitprops $tempobj - hsetprop $scobj_hpath klass NXenvironment + hsetprop $scobj_hpath klass environment ::scobj::set_required_props $scobj_hpath foreach {rootpath hpath klass priv} " $scobj_hpath sensor NXsensor spy @@ -523,6 +531,7 @@ proc createNode {scobj_hpath sct_controller cmdGroup varName readable writable\ hsetprop $scobj_hpath privilege spy ::scobj::hinitprops $tempobj setpoint hsetprop $scobj_hpath/setpoint data true + hsetprop $scobj_hpath/setpoint type drivable if {[SplitReply [environment_simulation]]=="false"} { ansto_makesctdrive ${tempobj}_driveable $scobj_hpath/setpoint $scobj_hpath/sensor/value $sct_controller } diff --git a/site_ansto/instrument/config/hipadaba/common_instrument_dictionary.tcl b/site_ansto/instrument/config/hipadaba/common_instrument_dictionary.tcl index c2d4e2bb..bf7960cb 100644 --- a/site_ansto/instrument/config/hipadaba/common_instrument_dictionary.tcl +++ b/site_ansto/instrument/config/hipadaba/common_instrument_dictionary.tcl @@ -27,7 +27,7 @@ set instrument_dictionary [subst { property {data true control true nxsave false klass @none type graphset} } instrument { - sobj {@any instrument @any NXvelocity_selector @any NXaperture @any NXcollimator @any NXdetector @any NXdisk_chopper @any NXfermi_chopper} + sobj {@any instrument @any NXvelocity_selector @any NXaperture @any NXcollimator @any NXdetector @any NXdisk_chopper @any NXfermi_chopper @any NXsource} privilege spy datatype @none property {data true control true nxsave false klass NXinstrument type instrument} @@ -211,6 +211,12 @@ set instrument_dictionary [subst { datatype @none property {data true control true nxsave false klass @none type part} } + control { + privilege spy + sobj {@any control} + datatype @none + property {data false control true nxsave false klass @none type nxvgroup} + } data { privilege spy sobj {@any data} diff --git a/site_ansto/instrument/config/hipadaba/hipadaba_configuration_common.tcl b/site_ansto/instrument/config/hipadaba/hipadaba_configuration_common.tcl index d1713c59..3f116246 100644 --- a/site_ansto/instrument/config/hipadaba/hipadaba_configuration_common.tcl +++ b/site_ansto/instrument/config/hipadaba/hipadaba_configuration_common.tcl @@ -888,6 +888,16 @@ proc ::hdb::prune {instdict} { return } +proc ::hdb::alias {parent linkpath NXtarget name } { + set catch_status [ catch { + if {$NXtarget != "data_set"} { + return -code error "Unhandled target alias $NXtarget" + } + hfactory $parent/$name alias $linkpath + } message ] + handle_exception $catch_status $message +} + ## # @brief Traverse the instrument dictionary and construct the hipadaba database. # @@ -913,6 +923,13 @@ upvar #0 $instDict dictionary } } } + foreach node [hmatchprop / permlink *] { + set plink [hgetpropval $node permlink] + set target [lindex $plink 0] + if {$target == "data_set" && [hgetpropval $node control]} { + ::hdb::alias "/control" $node {*}$plink + } + } } message ] handle_exception $catch_status $message } diff --git a/site_ansto/instrument/config/hipadaba/instdict_specification.tcl b/site_ansto/instrument/config/hipadaba/instdict_specification.tcl index 0952d7e3..0eaa8488 100644 --- a/site_ansto/instrument/config/hipadaba/instdict_specification.tcl +++ b/site_ansto/instrument/config/hipadaba/instdict_specification.tcl @@ -11,7 +11,7 @@ set boolean {true false} #} # SICS OBJECTS MUST PROVIDE THE FOLLOWING INFORMATION -set sobj_klass_list {@none aperture attenuator collimator command crystal data detector disk_chopper entry environment experiment fermi_chopper graphics instrument slits monitor monochromator parameter plc reduce sample scan sensor source user} +set sobj_klass_list {@none aperture attenuator collimator command control crystal data detector disk_chopper entry environment experiment fermi_chopper graphics instrument slits monitor monochromator parameter plc reduce sample scan sensor source user} set sobj_sicstype_list {chopperadapter environment_controller sicsvariable macro motor configurablevirtualmotor tasmot singlecounter histmem nxscript sicsdata scanobject sct_object} # Different kinds of things are added to the hdb in different ways. # command: This is something a client can run with hset /a/b/c start, it may have parameters and feedback. diff --git a/site_ansto/instrument/config/hmm/hmm_configuration_common_1.tcl b/site_ansto/instrument/config/hmm/hmm_configuration_common_1.tcl index c3627312..113e24c1 100644 --- a/site_ansto/instrument/config/hmm/hmm_configuration_common_1.tcl +++ b/site_ansto/instrument/config/hmm/hmm_configuration_common_1.tcl @@ -36,7 +36,7 @@ namespace eval histogram_memory { if [ catch { set ic_fsrce_values [ list INTERNAL EXTERNAL ] - set ic_count_methods [concat [list time unlimited period count frame] $::counter::isc_beam_monitor_list ] + set ic_count_methods [concat [list time unlimited period count frame count_roi] $::counter::isc_beam_monitor_list ] if {$histmem_simulation == "true"} { MakeHM hmm SIM hmm configure daq Stopped @@ -50,7 +50,7 @@ namespace eval histogram_memory { hmm configure ratemap_xy_total 321 hmm configure maximum_period 0 hmm configure fat_frame_frequency 50 - hmm configure fat_clock_scale 1000 + hmm configure fat_clock_scale 1000 foreach bm $::counter::isc_beam_monitor_list { set bm_num [string index $bm end] if [string is integer $bm_num] { @@ -67,19 +67,21 @@ namespace eval histogram_memory { # Frame source for each instrument if freq = 0, this can happen when automatically # setting frequencies from choppers. - array set default_frame_source_when_there_is_no_frame_signal { - echidna INTERNAL - koala INTERNAL - kowari EXTERNAL - pelican INTERNAL - platypus EXTERNAL - quokka INTERNAL - taipan INTERNAL - wombat INTERNAL - lyrebird INTERNAL - kookaburra INTERNAL - dingo INTERNAL - } + array set default_frame_source_when_there_is_no_frame_signal { + echidna INTERNAL + koala INTERNAL + kowari EXTERNAL + pelican INTERNAL + platypus EXTERNAL + quokka INTERNAL + taipan INTERNAL + wombat INTERNAL + lyrebird INTERNAL + kookaburra INTERNAL + dingo INTERNAL + bilby INTERNAL + emu INTERNAL + } array set default_frame_source_always_internal { echidna "true" @@ -93,6 +95,8 @@ namespace eval histogram_memory { lyrebird "false" kookaburra "false" dingo "false" + bilby "false" + emu "false" } ::utility::mkVar detector_active_height_mm Float user active_height true detector true true @@ -834,7 +838,7 @@ proc CAT_TABLE {args} { # proc FAT_TABLE {args} { if [ catch { - set attributes { FRAME_FREQUENCY FRAME_BUFFER FRAME_DUTYCYCLE SIZE_PERIOD NOS_PERIODS COUNT_METHOD COUNT_SIZE READ_DATA_TYPE VIEW_MAG_X VIEW_MAG_Y HISTO_STREAMING P7888_PLL_FREQ_CARD_X P7888_PLL_FREQ_CARD_Y P7888_CARD_MODE_X P7888_CARD_MODE_Y RAW_HISTO_XMIN RAW_HISTO_XMAX RAW_HISTO_YMIN RAW_HISTO_YMAX TEST_HISTO_1D_SIZES TEST_HISTO_2D_SIZES P7888_PLL_SYNC_METHOD } + set attributes { FRAME_FREQUENCY FRAME_BUFFER FRAME_DUTYCYCLE SIZE_PERIOD NOS_PERIODS COUNT_METHOD COUNT_SIZE READ_DATA_TYPE VIEW_MAG_X VIEW_MAG_Y HISTO_STREAMING P7888_PLL_FREQ_CARD_X P7888_PLL_FREQ_CARD_Y P7888_CARD_MODE_X P7888_CARD_MODE_Y RAW_HISTO_XMIN RAW_HISTO_XMAX RAW_HISTO_YMIN RAW_HISTO_YMAX TEST_HISTO_1D_SIZES TEST_HISTO_2D_SIZES P7888_PLL_SYNC_METHOD COUNT_ROI_XMIN COUNT_ROI_XMAX COUNT_ROI_YMIN COUNT_ROI_YMAX COUNT_ROI_TMIN COUNT_ROI_TMAX COUNT_ROI_TYPE COUNT_ROI_REGION COUNT_ROI_K1 } set elements {{ }} diff --git a/site_ansto/instrument/config/motors/sct_aerotech_soloist.tcl b/site_ansto/instrument/config/motors/sct_aerotech_soloist.tcl index c39a5790..858164d0 100644 --- a/site_ansto/instrument/config/motors/sct_aerotech_soloist.tcl +++ b/site_ansto/instrument/config/motors/sct_aerotech_soloist.tcl @@ -35,26 +35,6 @@ namespace eval ::scobj::[set vendor]_[set device] { } catch_message ] } - proc basename {node} { - set point [string last "/" $node] - if { $point < 0 } { - return $node - } else { - incr point - return "[string range $node $point end]" - } - } - proc pathname {node} { - set point [string last "/" $node] - if { $point < 0 } { - return "" - } else { - incr point -1 - return "[string range $node 0 $point]" - } - return "[join [lrange [split $node '/'] 0 end-1] '/']" - } - proc ns {} { return "[namespace current]" } diff --git a/site_ansto/instrument/config/nexus/nxscripts_common_1.tcl b/site_ansto/instrument/config/nexus/nxscripts_common_1.tcl index 03e8aed4..34b59969 100644 --- a/site_ansto/instrument/config/nexus/nxscripts_common_1.tcl +++ b/site_ansto/instrument/config/nexus/nxscripts_common_1.tcl @@ -54,6 +54,8 @@ namespace eval nexus { "taipan" "simple" "kookaburra" "simple" "dingo" "simple" + "bilby" "simple" + "emu" "simple" } } namespace eval ::nexus::histmem {} @@ -120,7 +122,7 @@ proc ::nexus::datapath {} { # @param postfix This is the filename suffix, must be one of: nx.hdf, hdf, h5, nx5, xml proc newFileName {idNum postfix} { if [ catch { - array set inst_mnem {quokka QKK wombat WBT echidna ECH kowari KWR koala KOL taipan TPN platypus PLP pelican PLN lyrebird LBD kookaburra KKB dingo DNG} + array set inst_mnem {quokka QKK wombat WBT echidna ECH kowari KWR koala KOL taipan TPN platypus PLP pelican PLN lyrebird LBD kookaburra KKB dingo DNG bilby BBY emu EMU} # set prefix [SplitReply [sicsdataprefix]] set date_time_arr [split [sicstime] " "] set isodate [lindex $date_time_arr 0] @@ -132,22 +134,47 @@ proc newFileName {idNum postfix} { return $fmtStr } +## +# @brief Make a link in the nexus file +# With two arguments the target name = the link name +# With three arguments you can give the target a new name. +# two args: arg0 = target, arg1 = link +# three args: arg0 = target, arg1 = new name, arg2 = link +proc ::nexus::link {args} { + set nargs [llength $args] + switch $nargs { + 2 { nxscript makelink [lindex $args 0] [lindex $args 1] } + 3 { nxscript makenamedlink [lindex $args 0] [lindex $args 2] [lindex $args 1] } + } +} proc ::nexus::process_filetype_policy {filetype} { if [ catch { if {$filetype == "BEAM_MONITOR"} { ::hdb::set_save / true ::hdb::set_save $::histogram_memory::HP_HMM false set ::counter::HP_BM [getatt monitor_counts hdb_path] - hsetprop $::counter::HP_BM link data_set + if [sicslist exists monitor_counts linkname] { + hsetprop $::counter::HP_BM link data_set [getatt monitor_counts linkname] + } else { + hsetprop $::counter::HP_BM link data_set + } hsetprop $::counter::HP_BM @signal 1 set nvars [SplitReply [bmonscan noscanvar]] + if {$nvars == 0} { + set axes "run_number" + } else { for { set i 0 } { $i < $nvars } { incr i } { set axis_name [lindex [split [lindex [split [bmonscan getvarpar $i]] 0] "."] 1] set node_name [SplitReply [sicslist $axis_name hdb_path]] - hsetprop $node_name link data_set + if [sicslist exists $axis_name linkname] { + hsetprop $node_name link data_set [getatt $axis_name linkname] + } else { + hsetprop $node_name link data_set + } lappend axes_list $axis_name } set axes [join $axes_list ":"] + } hsetprop $::counter::HP_BM @axes $axes } else { ::hdb::set_save / true @@ -156,10 +183,18 @@ proc newFileName {idNum postfix} { ::histogram_memory::set_axes $filetype } foreach sobj [sicslist link data_set] { - hsetprop [getatt $sobj hdb_path] link data_set + if [sicslist exists $sobj linkname] { + hsetprop [getatt $sobj hdb_path] link data_set [getatt $sobj linkname] + } else { + hsetprop [getatt $sobj hdb_path] link data_set + } } foreach sobj [sicslist link parameters_group] { - hsetprop [getatt $sobj hdb_path] link parameters_group + if [sicslist exists $sobj linkname] { + hsetprop [getatt $sobj hdb_path] link parameters_group [getatt $sobj linkname] + } else { + hsetprop [getatt $sobj hdb_path] link parameters_group + } } } message ] { return -code error "([info level 0]) $message" @@ -629,10 +664,10 @@ proc ::nexus::savetree {hpath pt filestatus} { } if {$filestatus == "newfile"} { if {[info exists p_arr(link)] && ($p_arr(link) != "@none")} { - nxscript makelink $p_arr(link) $p_arr(nxalias) + ::nexus::link {*}$p_arr(link) $p_arr(nxalias) } if {[info exists p_arr(permlink)] && ($p_arr(permlink) != "@none")} { - nxscript makelink $p_arr(permlink) $p_arr(nxalias) + ::nexus::link {*}$p_arr(permlink) $p_arr(nxalias) } } } @@ -884,7 +919,7 @@ proc ::nexus::histmem::save {hm nxalias hpath data_type filestatus args} { if {$filestatus == "newfile"} { if [hpropexists $hpath link] { set link [hgetpropval $hpath link] - nxscript makelink $link $nxalias + ::nexus::link {*}$link $nxalias } nxscript putattribute $nxalias axes $axes nxscript putattribute $nxalias signal $signal @@ -919,7 +954,7 @@ proc ::nexus::motor::save {motor nxalias hpath data_type filestatus args} { if {$filestatus == "newfile"} { if [hpropexists $hpath link] { set link [hgetpropval $hpath link] - nxscript makelink $link $nxalias + ::nexus::link {*}$link $nxalias } foreach {propName propValue} [hfindprop $hpath @*] { set attName [string range $propName 1 end] @@ -980,7 +1015,7 @@ proc ::nexus::macro::getset_save {sobj nxalias hpath data_type filestatus args} if {$filestatus == "newfile"} { if [hpropexists $hpath link] { set link [hgetpropval $hpath link] - nxscript makelink $link $nxalias + ::nexus::link {*}$link $nxalias } foreach {propName propValue} [hfindprop $hpath @*] { set attName [string range $propName 1 end] @@ -1029,7 +1064,7 @@ proc ::nexus::environment_controller::save {evc nxalias hpath data_type filestat if {$filestatus == "newfile"} { if [hpropexists $hpath link] { set link [hgetpropval $hpath link] - nxscript makelink $link $nxalias + ::nexus::link {*}$link $nxalias } foreach {propName propValue} [hfindprop $hpath @*] { set attName [string range $propName 1 end] @@ -1088,7 +1123,7 @@ proc ::nexus::sicsvariable::save {svar nxalias hpath data_type filestatus args} if {$filestatus == "newfile"} { if [hpropexists $hpath link] { set link [hgetpropval $hpath link] - nxscript makelink $link $nxalias + ::nexus::link {*}$link $nxalias } foreach {propName propValue} [hfindprop $hpath @*] { set attName [string range $propName 1 end] @@ -1176,7 +1211,7 @@ proc ::nexus::chopperadapter::save {sobj nxalias hpath data_type filestatus args if {$filestatus == "newfile"} { if [hpropexists $hpath link] { set link [hgetpropval $hpath link] - nxscript makelink $link $nxalias + ::nexus::link {*}$link $nxalias } foreach {propName propValue} [hfindprop $hpath @*] { set attName [string range $propName 1 end] @@ -1244,7 +1279,7 @@ proc ::nexus::script::save {script nxalias hpath data_type filestatus args} { if {$filestatus == "newfile"} { if [hpropexists $hpath link] { set link [hgetpropval $hpath link] - nxscript makelink $link $nxalias + ::nexus::link {*}$link $nxalias } foreach {propName propValue} [hfindprop $hpath @*] { set attName [string range $propName 1 end] diff --git a/site_ansto/instrument/config/scan/scan_common_1.tcl b/site_ansto/instrument/config/scan/scan_common_1.tcl index a03f9992..0c65f560 100644 --- a/site_ansto/instrument/config/scan/scan_common_1.tcl +++ b/site_ansto/instrument/config/scan/scan_common_1.tcl @@ -192,7 +192,7 @@ proc ::scan::check_scanvar {sobj uobj} { return -code error "ERROR: Can't drive scan variable, $scan_variable position is set to 'fixed'" } else { set mtype [getatt $scan_variable mtype] - if {$mtype != "tlcmot" && $check_thread0 && [SplitReply [$scan_variable thread0]] == -1} { + if {$mtype != "tclmot" && $check_thread0 && [SplitReply [$scan_variable thread0]] == -1} { return -code error "ERROR: Can't scan ${scan_variable}. Thread zero has stopped running on the motion controller" } } diff --git a/site_ansto/instrument/config/source/reactor_status.sct b/site_ansto/instrument/config/source/reactor_status.sct new file mode 100644 index 00000000..858a5307 --- /dev/null +++ b/site_ansto/instrument/config/source/reactor_status.sct @@ -0,0 +1,50 @@ +# vim: ts=8 sts=2 sw=2 expandtab autoindent smartindent nocindent +# http://neutron.ansto.gov.au/Bragg/proposal/reactor.jsp?type=ALL +# Power: 19.198232; CNS Out: 29.26; TG123: 1; CG123: 1; TG4: 3 +driver reactor_status = { + protocol = std; + class = NXsource; + simulation_group = opal_simulation; + + group = { + group_property 'data' = 'true'; + group_property 'control' = 'true'; + var status = { + type = text; + priv = spy; + readable = 10; + read_command = 'GET /Bragg/proposal/reactor.jsp?type=ALL HTTP/1.0'; + read_function = rdAll; + fetch_function = getState; + data = false; + control = false; + } + var power = { type = float; priv = spy; mutable = true; property klass = source;} + var cns_out = { type = float; priv = spy; mutable = true; property klass = source;} + var tg123 = { type = float; priv = spy; mutable = true; property klass = source;} + var cg123 = { type = float; priv = spy; mutable = true; property klass = source;} + var tg4 = { type = float; priv = spy; mutable = true; property klass = source;} + } + + code read_function rdValue = { + } + code Write_function setPoint = { + } + code mkDriver = { + } + + code read_function rdAll = { + @ set data [lindex [split [string trim ${data}] "\r\n"] end] + @ if {${data} != [sct oldval]} { + @ foreach {n v} [regexp -all -inline {[A-Z][A-Za-z0-9 ]+|[0-9][0-9.]*} ${data}] { + @ switch $n { + @ "Power" { hset ${tc_root}/power $v } + @ "CNS Out" { hset ${tc_root}/cns_out $v } + @ "TG123" { hset ${tc_root}/tg123 $v } + @ "CG123" { hset ${tc_root}/cg123 $v } + @ "TG4" { hset ${tc_root}/tg4 $v } + @ } + @ } + @ } + } +} diff --git a/site_ansto/instrument/config/source/sct_reactor_status.tcl b/site_ansto/instrument/config/source/sct_reactor_status.tcl new file mode 100644 index 00000000..a1225cb5 --- /dev/null +++ b/site_ansto/instrument/config/source/sct_reactor_status.tcl @@ -0,0 +1,356 @@ +# Generated driver for reactor_status +# vim: ft=tcl tabstop=8 softtabstop=2 shiftwidth=2 nocindent smartindent +# + +namespace eval ::scobj::reactor_status { + set debug_threshold 0 +} + +proc ::scobj::reactor_status::debug_log {debug_level debug_string} { + set catch_status [ catch { + if {${debug_level} >= ${::scobj::reactor_status::debug_threshold}} { + set fd [open "/tmp/reactor_status.log" "a"] + set line "[clock format [clock seconds] -format "%T"] ${debug_string}" + puts ${fd} "${line}" + close ${fd} + } + } catch_message ] +} + +# check function for hset change +proc ::scobj::reactor_status::checkrange {tc_root} { + set catch_status [ catch { + debug_log 1 "checkrange tc_root=${tc_root} sct=[sct] target=[sct target]" + set setpoint [sct target] + if { [hpropexists [sct] lowerlimit] } { + set lolimit [sct lowerlimit] + } else { + # lowerlimit not set, use target + set lolimit [sct target] + } + if { [hpropexists [sct] upperlimit] } { + set hilimit [sct upperlimit] + } else { + # upperlimit not set, use target + set hilimit [sct target] + } +# hook code goes here + if { ${setpoint} < ${lolimit} || ${setpoint} > ${hilimit} } { + error "setpoint ${setpoint} violates limits (${lolimit}..${hilimit}) on [sct]" + } + return OK + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to request the read of a parameter on a device +proc ::scobj::reactor_status::getState {tc_root nextState cmd_str} { + set catch_status [ catch { + debug_log 1 "getState tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set cmd "${cmd_str}" +# hook code goes here + debug_log 1 "getState sct send ${cmd}" + if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { + sct send "${cmd}" + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to request the read of a parameter on a device +proc ::scobj::reactor_status::getValue {tc_root nextState cmd_str} { + set catch_status [ catch { + debug_log 1 "getValue tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set cmd "${cmd_str}" +# hook code goes here + debug_log 1 "getValue sct send ${cmd}" + if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { + sct send "${cmd}" + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to check the write parameter on a device +proc ::scobj::reactor_status::noResponse {tc_root} { + set catch_status [ catch { + debug_log 1 "noResponse tc_root=${tc_root} sct=[sct] resp=[sct result]" +# hook code goes here + return "idle" + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to parse the read of a parameter on a device +proc ::scobj::reactor_status::rdAll {tc_root} { + set catch_status [ catch { + debug_log 1 "rdAll tc_root=${tc_root} sct=[sct] result=[sct result]" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set data [sct result] + set nextState "idle" + if {[string equal -nocase -length 7 ${data} "ASCERR:"]} { + # the protocol driver has reported an error + sct geterror "${data}" + error "[sct geterror]" + } +# hook code starts + set data [lindex [split [string trim ${data}] "\r\n"] end] + if {${data} != [sct oldval]} { + foreach {n v} [regexp -all -inline {[A-Z][A-Za-z0-9 ]+|[0-9][0-9.]*} ${data}] { + switch $n { + "Power" { hset ${tc_root}/power $v } + "CNS Out" { hset ${tc_root}/cns_out $v } + "TG123" { hset ${tc_root}/tg123 $v } + "CG123" { hset ${tc_root}/cg123 $v } + "TG4" { hset ${tc_root}/tg4 $v } + } + } + } +# hook code ends + if { [hpropexists [sct] geterror] } { + debug_log 1 "[sct] error: [sct geterror]" + error "[sct geterror]" + } + if { ${data} != [sct oldval] } { + debug_log 1 "[sct] changed to new:${data}, from old:[sct oldval]" + sct oldval ${data} + sct update ${data} + sct utime readtime + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to parse the read of a parameter on a device +proc ::scobj::reactor_status::rdValue {tc_root} { + set catch_status [ catch { + debug_log 1 "rdValue tc_root=${tc_root} sct=[sct] result=[sct result]" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set data [sct result] + set nextState "idle" + if {[string equal -nocase -length 7 ${data} "ASCERR:"]} { + # the protocol driver has reported an error + sct geterror "${data}" + error "[sct geterror]" + } +# hook code goes here + if { ${data} != [sct oldval] } { + debug_log 1 "[sct] changed to new:${data}, from old:[sct oldval]" + sct oldval ${data} + sct update ${data} + sct utime readtime + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to write a parameter value on a device +proc ::scobj::reactor_status::setPoint {tc_root nextState cmd_str} { + set catch_status [ catch { + debug_log 1 "setPoint tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set par [sct target] + set cmd "${cmd_str}${par}" +# hook code goes here + if { [hpropexists [sct] driving] } { + if { [hpropexists [sct] writestatus] && [sct writestatus] == "start" } { + sct driving 1 + } + } + debug_log 1 "setPoint sct send ${cmd}" + if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { + sct send "${cmd}" + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +# function to write a parameter value on a device +proc ::scobj::reactor_status::setValue {tc_root nextState cmd_str} { + set catch_status [ catch { + debug_log 1 "setValue tc_root=${tc_root} sct=[sct] cmd=${cmd_str}" + if { [hpropexists [sct] geterror] } { + hdelprop [sct] geterror + } + set par [sct target] + set cmd "${cmd_str}${par}" +# hook code goes here + if { [hpropexists [sct] driving] } { + if { [hpropexists [sct] writestatus] && [sct writestatus] == "start" } { + sct driving 1 + } + } + debug_log 1 "setValue sct send ${cmd}" + if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} { + sct send "${cmd}" + } + return ${nextState} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +proc ::scobj::reactor_status::mk_sct_reactor_status { sct_controller name } { + debug_log 1 "mk_sct_reactor_status for ${name}" + set ns "[namespace current]" + set catch_status [ catch { + + MakeSICSObj ${name} SCT_OBJECT + + sicslist setatt ${name} klass NXsource + sicslist setatt ${name} long_name ${name} + + set scobj_hpath /sics/${name} + + hfactory ${scobj_hpath}/cg123 plain spy float + hsetprop ${scobj_hpath}/cg123 control true + hsetprop ${scobj_hpath}/cg123 data true + hsetprop ${scobj_hpath}/cg123 mutable true + hsetprop ${scobj_hpath}/cg123 nxsave true + hsetprop ${scobj_hpath}/cg123 oldval 0.0 + hsetprop ${scobj_hpath}/cg123 klass "source" + hsetprop ${scobj_hpath}/cg123 sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/cg123 type "part" + hsetprop ${scobj_hpath}/cg123 nxalias "${name}_cg123" + + hfactory ${scobj_hpath}/cns_out plain spy float + hsetprop ${scobj_hpath}/cns_out control true + hsetprop ${scobj_hpath}/cns_out data true + hsetprop ${scobj_hpath}/cns_out mutable true + hsetprop ${scobj_hpath}/cns_out nxsave true + hsetprop ${scobj_hpath}/cns_out oldval 0.0 + hsetprop ${scobj_hpath}/cns_out klass "source" + hsetprop ${scobj_hpath}/cns_out sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/cns_out type "part" + hsetprop ${scobj_hpath}/cns_out nxalias "${name}_cns_out" + + hfactory ${scobj_hpath}/power plain spy float + hsetprop ${scobj_hpath}/power control true + hsetprop ${scobj_hpath}/power data true + hsetprop ${scobj_hpath}/power mutable true + hsetprop ${scobj_hpath}/power nxsave true + hsetprop ${scobj_hpath}/power oldval 0.0 + hsetprop ${scobj_hpath}/power klass "source" + hsetprop ${scobj_hpath}/power sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/power type "part" + hsetprop ${scobj_hpath}/power nxalias "${name}_power" + + hfactory ${scobj_hpath}/status plain spy text + hsetprop ${scobj_hpath}/status read ${ns}::getState ${scobj_hpath} rdAll {GET /Bragg/proposal/reactor.jsp?type=ALL HTTP/1.0} + hsetprop ${scobj_hpath}/status rdAll ${ns}::rdAll ${scobj_hpath} + hsetprop ${scobj_hpath}/status control false + hsetprop ${scobj_hpath}/status data false + hsetprop ${scobj_hpath}/status mutable false + hsetprop ${scobj_hpath}/status nxsave true + hsetprop ${scobj_hpath}/status oldval UNKNOWN + hsetprop ${scobj_hpath}/status sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/status type "part" + hsetprop ${scobj_hpath}/status nxalias "${name}_status" + + hfactory ${scobj_hpath}/tg123 plain spy float + hsetprop ${scobj_hpath}/tg123 control true + hsetprop ${scobj_hpath}/tg123 data true + hsetprop ${scobj_hpath}/tg123 mutable true + hsetprop ${scobj_hpath}/tg123 nxsave true + hsetprop ${scobj_hpath}/tg123 oldval 0.0 + hsetprop ${scobj_hpath}/tg123 klass "source" + hsetprop ${scobj_hpath}/tg123 sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/tg123 type "part" + hsetprop ${scobj_hpath}/tg123 nxalias "${name}_tg123" + + hfactory ${scobj_hpath}/tg4 plain spy float + hsetprop ${scobj_hpath}/tg4 control true + hsetprop ${scobj_hpath}/tg4 data true + hsetprop ${scobj_hpath}/tg4 mutable true + hsetprop ${scobj_hpath}/tg4 nxsave true + hsetprop ${scobj_hpath}/tg4 oldval 0.0 + hsetprop ${scobj_hpath}/tg4 klass "source" + hsetprop ${scobj_hpath}/tg4 sdsinfo "::nexus::scobj::sdsinfo" + hsetprop ${scobj_hpath}/tg4 type "part" + hsetprop ${scobj_hpath}/tg4 nxalias "${name}_tg4" + + hsetprop ${scobj_hpath} control "true" + hsetprop ${scobj_hpath} data "true" + + if {[SplitReply [opal_simulation]]=="false"} { + ${sct_controller} poll ${scobj_hpath}/status 10 + } + hsetprop ${scobj_hpath} klass NXsource +# hook code starts +# hook code ends + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +namespace eval ::scobj::reactor_status { + namespace export debug_log + namespace export mk_sct_reactor_status +} + +proc add_reactor_status {name IP port} { + set catch_status [ catch { + set ns "::scobj::reactor_status" + ${ns}::debug_log 1 "add_reactor_status ${name} ${IP} ${port}" + if {[SplitReply [opal_simulation]]=="false"} { + if {[string equal -nocase "aqadapter" "${IP}"]} { + ${ns}::debug_log 1 "makesctcontroller sct_${name} aqadapter ${port}" + makesctcontroller sct_${name} aqadapter ${port} + } else { + ${ns}::debug_log 1 "makesctcontroller sct_${name} std ${IP}:${port}" + makesctcontroller sct_${name} std ${IP}:${port} + } + } + ${ns}::debug_log 1 "mk_sct_reactor_status sct_${name} ${name}" + ${ns}::mk_sct_reactor_status sct_${name} ${name} + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} + +puts stdout "file evaluation of sct_reactor_status.tcl" +::scobj::reactor_status::debug_log 1 "file evaluation of sct_reactor_status.tcl" + +proc ::scobj::reactor_status::read_config {} { + set catch_status [ catch { + set ns "::scobj::reactor_status" + ${ns}::debug_log 1 "Processing Config" + dict for {k v} $::config_dict { + ${ns}::debug_log 1 "Inspecting $k:$v" + if { [dict exists $v "driver"] } { + ${ns}::debug_log 1 "Has driver [dict get $v driver]" + if { [dict get $v "driver"] == "reactor_status" } { + ${ns}::debug_log 1 "Correct driver, enabled = [dict get $v enabled]" + if { [dict get $v enabled] } { + set IP [dict get $v ip] + set PORT [dict get $v port] + set name [dict get $v name] + MakeAsyncProtocol ${name}_protocol + MakeAsyncQueue ${name}_queue ${name}_protocol ${IP} ${PORT} + add_reactor_status ${name} "aqadapter" ${name}_queue + } + } + } + } + } catch_message ] + handle_exception ${catch_status} ${catch_message} +} +if { [info exists ::config_dict] } { + ::scobj::reactor_status::read_config +} else { + ::scobj::reactor_status:debug_log 1 "No config dict" +} diff --git a/site_ansto/instrument/config/source/source.tcl b/site_ansto/instrument/config/source/source.tcl new file mode 100644 index 00000000..898d92a9 --- /dev/null +++ b/site_ansto/instrument/config/source/source.tcl @@ -0,0 +1,16 @@ +fileeval $cfPath(source)/sct_reactor_status.tcl + +if {[SplitReply [opal_simulation]]=="false"} { + MakeAsyncProtocol std + std sendterminator \r\n\r\n + std replyterminator 0x03 + MakeAsyncQueue aqreactor std portal.nbi.ansto.gov.au 80 + aqreactor timeout 2000 +} +add_reactor_status source aqadapter aqreactor + +namespace eval ::source { + proc isc_initialize {} { + } +} + diff --git a/site_ansto/instrument/deploySICS.sh b/site_ansto/instrument/deploySICS.sh index 1d719fd1..8e528cba 100755 --- a/site_ansto/instrument/deploySICS.sh +++ b/site_ansto/instrument/deploySICS.sh @@ -152,6 +152,14 @@ dingo|dingo) INSTRUMENT=dingo DESTHOST=${2:-ics1-dingo.nbi.ansto.gov.au} INSTSRC=$SRCDIR/dingo;; +bilby|bilby) +INSTRUMENT=bilby +DESTHOST=${2:-ics1-bilby.nbi.ansto.gov.au} +INSTSRC=$SRCDIR/bilby;; +emu|emu) +INSTRUMENT=emu +DESTHOST=${2:-ics1-emu.nbi.ansto.gov.au} +INSTSRC=$SRCDIR/emu;; esac INSTCFDIR=$INSTSRC/config diff --git a/site_ansto/instrument/dingo/config/INSTCFCOMMON.TXT b/site_ansto/instrument/dingo/config/INSTCFCOMMON.TXT index e9ca426e..f0ad4f76 100644 --- a/site_ansto/instrument/dingo/config/INSTCFCOMMON.TXT +++ b/site_ansto/instrument/dingo/config/INSTCFCOMMON.TXT @@ -1,4 +1,5 @@ -config/source/source_common.tcl +config/source/sct_reactor_status.tcl +config/source/source.tcl config/anticollider/anticollider_common.tcl config/plc/plc_common_1.tcl config/counter/counter_common_1.tcl diff --git a/site_ansto/instrument/dingo/config/source/source.tcl b/site_ansto/instrument/dingo/config/source/source.tcl deleted file mode 100644 index 50967ab8..00000000 --- a/site_ansto/instrument/dingo/config/source/source.tcl +++ /dev/null @@ -1,8 +0,0 @@ -# Author Jing Chen (jgn@ansto.gov.au) - -source $cfPath(source)/source_common.tcl - -proc ::source::isc_initialize {} { - ::source::ic_initialize "thermal" -} - diff --git a/site_ansto/instrument/gumxml.tcl b/site_ansto/instrument/gumxml.tcl index 67b5693b..32da525e 100644 --- a/site_ansto/instrument/gumxml.tcl +++ b/site_ansto/instrument/gumxml.tcl @@ -2,13 +2,25 @@ proc getdataType {path} { return [lindex [split [hinfo $path] ,] 0] } +proc encode {str} { + set result [string map -nocase { + {"} {"} + {'} {'} + {<} {<} + {>} {>} + {&} {&} + } $str] + return $result +} + proc make_nodes {path result indent} { set nodename [file tail $path]; set type [getdataType $path] set prefix [string repeat " " $indent] set newIndent [expr $indent + 2] set control "true" - foreach {key value} [string map {= " "} [hlistprop $path tcl]] { + foreach {key rvalue} [string map {= " "} [hlistprop $path tcl]] { + set value [encode $rvalue] if {[string compare -nocase $key "control"] == 0} { if {[string compare -nocase $value "false"] == 0} { set control "false" @@ -30,7 +42,8 @@ set control "true" proc property_elements {path indent} { set prefix [string repeat " " $indent] - foreach {key value} [string map {= " "} [hlistprop $path tcl]] { + foreach {key rvalue} [string map {= " "} [hlistprop $path tcl]] { + set value [encode $rvalue] if {[string compare -nocase $key "control"] == 0} {continue} lappend proplist "$prefix\n" if {[string compare -nocase $key "help"] == 0} { diff --git a/site_ansto/instrument/hipd/config/INSTCFCOMMON.TXT b/site_ansto/instrument/hipd/config/INSTCFCOMMON.TXT index a009ef39..f6e21877 100644 --- a/site_ansto/instrument/hipd/config/INSTCFCOMMON.TXT +++ b/site_ansto/instrument/hipd/config/INSTCFCOMMON.TXT @@ -1,4 +1,5 @@ -config/source/source_common.tcl +config/source/sct_reactor_status.tcl +config/source/source.tcl config/anticollider/anticollider_common.tcl config/plc/plc_common_1.tcl config/counter/counter_common_1.tcl diff --git a/site_ansto/instrument/hipd/config/motors/euler_configuration.tcl b/site_ansto/instrument/hipd/config/motors/euler_configuration.tcl index ff2010ce..1d0f3cee 100644 --- a/site_ansto/instrument/hipd/config/motors/euler_configuration.tcl +++ b/site_ansto/instrument/hipd/config/motors/euler_configuration.tcl @@ -1,7 +1,8 @@ # This must be loaded by motor_configuration.tcl -set ephi_Home 6647698 -set echi_Home 8919294 +set ephi_Home 26575217 +set echi_Home 24224381 +#set echi_Home 8919294 set eom_Home 23165482 # Sample Tilt 1, euler omega stage @@ -11,9 +12,9 @@ Motor eom $motor_driver_type [params \ units degrees\ hardlowerlim -45\ hardupperlim 80\ - maxSpeed 1\ - maxAccel 1\ - maxDecel 1\ + maxSpeed 2\ + maxAccel 2\ + maxDecel 2\ stepsPerX 25000\ absEnc 1\ absEncHome $eom_Home\ @@ -30,18 +31,18 @@ Motor echi $motor_driver_type [params \ asyncqueue mc2\ axis B\ units degrees\ - hardlowerlim -32\ - hardupperlim 97\ - maxSpeed 1\ - maxAccel 1\ - maxDecel 1\ + hardlowerlim -45\ + hardupperlim 100\ + maxSpeed 2\ + maxAccel 2\ + maxDecel 2\ stepsPerX -25000\ absEnc 1\ absEncHome $echi_Home\ cntsPerX 8192] setHomeandRange -motor echi -home 0 -lowrange 10 -uprange 95 echi softlowerlim -10 -echi softupperlim 90 +echi softupperlim 99 echi home 0 echi speed 1 echi movecount $move_count @@ -52,7 +53,7 @@ echi long_name euler_chi # Sample Trans 1, upper, y Motor ephi $motor_driver_type [params \ asyncqueue mc2\ - axis C\ + axis D\ units degrees\ hardlowerlim -185\ hardupperlim 185\ @@ -72,3 +73,96 @@ ephi movecount $move_count ephi precision 0.01 ephi part sample ephi long_name euler_phi + +# dummy motors for UB + +Motor fake_eom asim [params \ + asyncqueue mc2\ + axis A\ + units degrees\ + hardlowerlim -370\ + hardupperlim 370\ + maxSpeed 2\ + maxAccel 2\ + maxDecel 2\ + stepsPerX 25000\ + absEnc 1\ + absEncHome $eom_Home\ + cntsPerX -8192] +setHomeandRange -motor fake_eom -home 0 -lowrange -370 -uprange 370 +fake_eom softlowerlim -370 +fake_eom softupperlim 370 +fake_eom speed 1 +fake_eom movecount $move_count +fake_eom precision 0.01 +fake_eom part sample +fake_eom long_name fake_euler_omega + +Motor fake_ephi asim [params \ + asyncqueue mc2\ + axis A\ + units degrees\ + hardlowerlim -370\ + hardupperlim 370\ + maxSpeed 2\ + maxAccel 2\ + maxDecel 2\ + stepsPerX 25000\ + absEnc 1\ + absEncHome $eom_Home\ + cntsPerX -8192] +setHomeandRange -motor fake_ephi -home 0 -lowrange -370 -uprange 370 +fake_ephi softlowerlim -370 +fake_ephi softupperlim 370 +fake_ephi speed 1 +fake_ephi movecount $move_count +fake_ephi precision 0.01 +fake_ephi part sample +fake_ephi long_name fake_euler_phi + +Motor fake_twotheta asim [params \ + asyncqueue mc2\ + axis A\ + units degrees\ + hardlowerlim -370\ + hardupperlim 370\ + maxSpeed 2\ + maxAccel 2\ + maxDecel 2\ + stepsPerX 25000\ + absEnc 1\ + absEncHome $eom_Home\ + cntsPerX -8192] +setHomeandRange -motor fake_twotheta -home 0 -lowrange -370 -uprange 370 +fake_twotheta softlowerlim -370 +fake_twotheta softupperlim 370 +fake_twotheta speed 1 +fake_twotheta movecount $move_count +fake_twotheta precision 0.01 +fake_twotheta part sample +fake_twotheta long_name fake_euler_twotheta + +Motor fake_echi asim [params \ + asyncqueue mc2\ + axis A\ + units degrees\ + hardlowerlim -370\ + hardupperlim 370\ + maxSpeed 2\ + maxAccel 2\ + maxDecel 2\ + stepsPerX 25000\ + absEnc 1\ + absEncHome $eom_Home\ + cntsPerX -8192] +setHomeandRange -motor fake_echi -home 0 -lowrange -370 -uprange 370 +fake_echi softlowerlim -370 +fake_echi softupperlim 370 +fake_echi speed 1 +fake_echi movecount $move_count +fake_echi precision 0.01 +fake_echi part sample +fake_echi long_name fake_euler_echi + + + diff --git a/site_ansto/instrument/hipd/config/motors/eulinf_configuration.tcl b/site_ansto/instrument/hipd/config/motors/eulinf_configuration.tcl new file mode 100644 index 00000000..246d1854 --- /dev/null +++ b/site_ansto/instrument/hipd/config/motors/eulinf_configuration.tcl @@ -0,0 +1,168 @@ +# This must be loaded by motor_configuration.tcl + +set ephi_Home 31706258 +set echi_Home 24224381 +#set echi_Home 8919294 +set eom_Home 23165482 + +# Sample Tilt 1, euler omega stage +Motor eom $motor_driver_type [params \ + asyncqueue mc2\ + axis A\ + units degrees\ + hardlowerlim -45\ + hardupperlim 80\ + maxSpeed 2\ + maxAccel 2\ + maxDecel 2\ + stepsPerX 25000\ + absEnc 1\ + absEncHome $eom_Home\ + cntsPerX -8192] +setHomeandRange -motor eom -home 0 -lowrange 35 -uprange 80 +eom speed 1 +eom movecount $move_count +eom precision 0.01 +eom part sample +eom long_name euler_omega + +# Sample Tilt 2, euler chi stage +Motor echi $motor_driver_type [params \ + asyncqueue mc2\ + axis B\ + units degrees\ + hardlowerlim -32\ + hardupperlim 97\ + maxSpeed 2\ + maxAccel 2\ + maxDecel 2\ + stepsPerX -25000\ + absEnc 1\ + absEncHome $echi_Home\ + cntsPerX 8192] +setHomeandRange -motor echi -home 0 -lowrange 10 -uprange 95 +echi softlowerlim -10 +echi softupperlim 90 +echi home 0 +echi speed 1 +echi movecount $move_count +echi precision 0.01 +echi part sample +echi long_name euler_chi + +# Sample Trans 1, upper, y +Motor ephi $motor_driver_type [params \ + asyncqueue mc2\ + axis C\ + units degrees\ + hardlowerlim -360000\ + hardupperlim 360000\ + maxSpeed 5\ + maxAccel 5\ + maxDecel 1\ + stepsPerX -12500\ + absEnc 1\ + absEncHome $ephi_Home\ + cntsPerX -4096] +setHomeandRange -motor ephi -home 0 -lowrange 180 -uprange 180 +ephi softlowerlim -360000 +ephi softupperlim 360000 +ephi home 0 +ephi speed 1 +ephi movecount $move_count +ephi precision 0.01 +ephi part sample +ephi long_name euler_phi + +# dummy motors for UB + +Motor fake_eom asim [params \ + asyncqueue mc2\ + axis A\ + units degrees\ + hardlowerlim -370\ + hardupperlim 370\ + maxSpeed 2\ + maxAccel 2\ + maxDecel 2\ + stepsPerX 25000\ + absEnc 1\ + absEncHome $eom_Home\ + cntsPerX -8192] +setHomeandRange -motor fake_eom -home 0 -lowrange -370 -uprange 370 +fake_eom softlowerlim -370 +fake_eom softupperlim 370 +fake_eom speed 1 +fake_eom movecount $move_count +fake_eom precision 0.01 +fake_eom part sample +fake_eom long_name fake_euler_omega + +Motor fake_ephi asim [params \ + asyncqueue mc2\ + axis A\ + units degrees\ + hardlowerlim -370\ + hardupperlim 370\ + maxSpeed 2\ + maxAccel 2\ + maxDecel 2\ + stepsPerX 25000\ + absEnc 1\ + absEncHome $eom_Home\ + cntsPerX -8192] +setHomeandRange -motor fake_ephi -home 0 -lowrange -370 -uprange 370 +fake_ephi softlowerlim -370 +fake_ephi softupperlim 370 +fake_ephi speed 1 +fake_ephi movecount $move_count +fake_ephi precision 0.01 +fake_ephi part sample +fake_ephi long_name fake_euler_phi + +Motor fake_twotheta asim [params \ + asyncqueue mc2\ + axis A\ + units degrees\ + hardlowerlim -370\ + hardupperlim 370\ + maxSpeed 2\ + maxAccel 2\ + maxDecel 2\ + stepsPerX 25000\ + absEnc 1\ + absEncHome $eom_Home\ + cntsPerX -8192] +setHomeandRange -motor fake_twotheta -home 0 -lowrange -370 -uprange 370 +fake_twotheta softlowerlim -370 +fake_twotheta softupperlim 370 +fake_twotheta speed 1 +fake_twotheta movecount $move_count +fake_twotheta precision 0.01 +fake_twotheta part sample +fake_twotheta long_name fake_euler_twotheta + +Motor fake_echi asim [params \ + asyncqueue mc2\ + axis A\ + units degrees\ + hardlowerlim -370\ + hardupperlim 370\ + maxSpeed 2\ + maxAccel 2\ + maxDecel 2\ + stepsPerX 25000\ + absEnc 1\ + absEncHome $eom_Home\ + cntsPerX -8192] +setHomeandRange -motor fake_echi -home 0 -lowrange -370 -uprange 370 +fake_echi softlowerlim -370 +fake_echi softupperlim 370 +fake_echi speed 1 +fake_echi movecount $move_count +fake_echi precision 0.01 +fake_echi part sample +fake_echi long_name fake_euler_echi + + + diff --git a/site_ansto/instrument/hipd/config/motors/magnet_configuration.tcl b/site_ansto/instrument/hipd/config/motors/magnet_configuration.tcl new file mode 100644 index 00000000..91f0386c --- /dev/null +++ b/site_ansto/instrument/hipd/config/motors/magnet_configuration.tcl @@ -0,0 +1,19 @@ +set magmot "som" +Motor $magmot $motor_driver_type [params \ + asyncqueue mc2\ + axis D\ + units degrees\ + hardlowerlim -1440\ + hardupperlim 1440\ + maxSpeed 1\ + maxAccel 1\ + maxDecel 1\ + stepsPerX [expr 67.0 * 25000 / 360]\ + absEnc 1\ + absEncHome 31275743\ + cntsPerX [expr 67.0 * 8192 / 360]] +$magmot part sample +$magmot long_name $magmot +$magmot softlowerlim -180 +$magmot softupperlim 180 +$magmot home 0 diff --git a/site_ansto/instrument/hipd/config/motors/motor_configuration.tcl b/site_ansto/instrument/hipd/config/motors/motor_configuration.tcl index bf6933fd..86a213b8 100644 --- a/site_ansto/instrument/hipd/config/motors/motor_configuration.tcl +++ b/site_ansto/instrument/hipd/config/motors/motor_configuration.tcl @@ -24,7 +24,8 @@ if {$sim_mode == "true"} { #set mx_Home 23263535 set mx_Home 8390583 #set mom_Home 9274794 -set mom_Home 8391038 +#set mom_Home 8391038 +set mom_Home 8147038 set mtth_Home 19927837 #set mphi_Home 7613516 #set mphi_Home 27847793 @@ -35,7 +36,8 @@ set mchi_Home 8389526 #set my_Home 6767221 set my_Home 8378212 set som_Home 17214054 -set stth_Home 2896180 +set stth_Home 1036498 +#set stth_Home 32855991 set oct_Home 7743768 #Measured or computed slit motor steps per millimetre @@ -97,11 +99,46 @@ set move_count 10 # CHOOSE HERE for sample stage configuration +########################################## +# Set axis_config as follows to use different axis configurations +# 0: tilt stage configuration +# 1: eulerian cradle +# 2: small omega +# 3: Oxford magnet sample stick +set axis_config 0 + +switch $axis_config { + 0 { + set sample_stage_rotate "som" + fileeval $cfPath(motors)/tilt_configuration.tcl + } + 1 { + set sample_stage_rotate "som" + fileeval $cfPath(motors)/euler_configuration.tcl + } + 2 { + set sample_stage_rotate "som" + fileeval $cfPath(motors)/small_omega_config.tcl + } + 3 { + # Rename the sample stage som to somss because + # som now controls the magnet sample stick + set sample_stage_rotate "somss" + fileeval $cfPath(motors)/magnet_configuration.tcl + } +} #fileeval $cfPath(motors)/tilt_configuration.tcl -fileeval $cfPath(motors)/euler_configuration.tcl +#fileeval $cfPath(motors)/euler_configuration.tcl #fileeval $cfPath(motors)/small_omega_config.tcl +#use this next one ONLY if you have NO fridge on the euler +#cradle and you know what you're doing. This is a fudge that +#allows ephi to do lots of rotations + +#fileeval $cfPath(motors)/eulinf_configuration.tcl + + ############################ # Motor Controller 1 @@ -201,8 +238,8 @@ Motor mx $motor_driver_type [params \ asyncqueue mc1\ axis D\ units mm\ - hardlowerlim -10\ - hardupperlim 10\ + hardlowerlim -15\ + hardupperlim 15\ maxSpeed 1\ maxAccel 1\ maxDecel 1\ @@ -223,7 +260,7 @@ Motor mom $motor_driver_type [params \ axis E\ units degrees\ hardlowerlim -5\ - hardupperlim 103\ + hardupperlim 173\ maxSpeed 1\ maxAccel 1\ maxDecel 1\ @@ -231,7 +268,8 @@ Motor mom $motor_driver_type [params \ absEnc 1\ absEncHome $mom_Home\ cntsPerX -2048] -setHomeandRange -motor mom -home 0 -lowrange 5 -uprange 95 +setHomeandRange -motor mom -home 0 -lowrange 5 -uprange 165 +#setHomeandRange -motor mom -home 60.08 -lowrange 5 -uprange 165 mom speed 1 mom movecount $move_count mom precision 0.01 @@ -277,12 +315,12 @@ mtth long_name takeoff_angle # Motor Controller 2 ############################ # Sample Omega, rotate -Motor som $motor_driver_type [params \ +Motor $sample_stage_rotate $motor_driver_type [params \ asyncqueue mc2\ axis E\ units degrees\ - hardlowerlim -110\ - hardupperlim 160\ + hardlowerlim -71\ + hardupperlim 111\ maxSpeed 5\ maxAccel 1\ maxDecel 1\ @@ -290,29 +328,33 @@ Motor som $motor_driver_type [params \ absEnc 1\ absEncHome $som_Home\ cntsPerX 4096] -setHomeandRange -motor som -home 0 -lowrange -71 -uprange 111 -som speed 1 -som precision 0.02 -som part sample -som long_name rotate +setHomeandRange -motor $sample_stage_rotate -home 0 -lowrange -70 -uprange 110 +$sample_stage_rotate speed 1 +$sample_stage_rotate precision 0.02 +$sample_stage_rotate part sample +$sample_stage_rotate long_name rotate # Sample two-theta, detector rotate Motor stth $motor_driver_type [params \ asyncqueue mc2\ axis F\ units degrees\ - hardlowerlim -0.3\ - hardupperlim 30\ + hardlowerlim 15.8\ + hardupperlim 29.7\ maxSpeed 0.5\ maxAccel 0.1\ maxDecel 0.1\ stepsPerX 125000\ absEnc 1\ absEncHome $stth_Home\ + bias_bits 25\ + bias_bias 932070\ cntsPerX -93207] -stth softlowerlim -0.3 -stth softupperlim 30 -stth home 0 +stth softlowerlim 15.9 +stth softupperlim 29.6 +stth home 28.481113 +#stth home 18.981113 +#stth home 32 stth speed 0.5 stth movecount $move_count stth precision 0.01 @@ -324,20 +366,20 @@ Motor oct $motor_driver_type [params \ asyncqueue mc2\ axis G\ units degrees\ - hardlowerlim -2\ - hardupperlim 4.2\ + hardlowerlim -1.5\ + hardupperlim 2.5\ maxSpeed 2.0\ maxAccel 5.0\ maxDecel 5.0\ - stepsPerX 56762\ + stepsPerX 58762\ absEnc 1\ absEncHome $oct_Home\ cntsPerX -465] -oct softlowerlim -2 -oct softupperlim 4 +oct softlowerlim -1.4 +oct softupperlim 2.4 oct home 0 oct speed 0.5 -oct precision 0.01 +oct precision 0.02 oct part collimator oct long_name oct @@ -370,6 +412,14 @@ oct long_name oct #mf1 long_name mf1 # Monochromator Focusing (Ge) +## ffr 31/7/2012 +## absEncHome was found to be 16777217 on 31/7/2012 when the +## encoder clocked over to 114 counts to give a posn +## reading of 4793.458008 +## The encoder has a 12bit resolution (ie 12bits/turn 4096) +## and has a 24bit range (ie max cnt=16777216) +## I set a bias of 10000 counts with absenchome = 10000 +## so that SICS can drive the axis to the allowed limits. Motor mf2 $motor_driver_type [params \ asyncqueue mc3\ axis A\ @@ -381,7 +431,9 @@ Motor mf2 $motor_driver_type [params \ maxDecel 0.1\ stepsPerX 22000\ absEnc 1\ - absEncHome 8384341\ + absEncHome 42768\ + bias_bits 24\ + bias_bias 10000\ cntsPerX -3500] setHomeandRange -motor mf2 -home 0 -lowrange 0 -uprange 2 mf2 speed 0.02 diff --git a/site_ansto/instrument/hipd/config/motors/small_omega_config.tcl b/site_ansto/instrument/hipd/config/motors/small_omega_config.tcl new file mode 100644 index 00000000..ac904e5c --- /dev/null +++ b/site_ansto/instrument/hipd/config/motors/small_omega_config.tcl @@ -0,0 +1,91 @@ +# This must be loaded by motor_configuration.tcl + +set sphi_Home 7937974 +set schi_Home 7585956 +set sy_Home 7557524 +set sx_Home 7557304 + +# Sample Tilt 1, upper, phi +Motor sphi $motor_driver_type [params \ + asyncqueue mc2\ + axis A\ + units degrees\ + hardlowerlim -360\ + hardupperlim 360\ + maxSpeed 3\ + maxAccel 2\ + maxDecel 2\ + stepsPerX 25000\ + absEnc 0\ + absEncHome $sphi_Home\ + cntsPerX -8192] +setHomeandRange -motor sphi -home 0 -lowrange -360 -uprange 360 +sphi speed 2 +sphi movecount $move_count +sphi precision 0.02 +sphi part sample +sphi long_name phi + +# Sample Tilt 2, lower, chi +Motor schi $motor_driver_type [params \ + asyncqueue mc2\ + axis B\ + units degrees\ + hardlowerlim 75\ + hardupperlim 105\ + maxSpeed 1\ + maxAccel 1\ + maxDecel 1\ + stepsPerX 25000\ + absEnc 1\ + absEncHome $schi_Home\ + cntsPerX 8192] +setHomeandRange -motor schi -home 90 -lowrange 15 -uprange 15 +schi speed 1 +schi movecount $move_count +schi precision 0.01 +schi part sample +schi long_name chi + +# Sample Trans 1, upper, y +Motor sy $motor_driver_type [params \ + asyncqueue mc2\ + axis C\ + units mm\ + hardlowerlim -20\ + hardupperlim 20\ + maxSpeed 1\ + maxAccel 1\ + maxDecel 1\ + stepsPerX 25000\ + absEnc 1\ + absEncHome $sy_Home\ + cntsPerX 8192] +setHomeandRange -motor sy -home 0 -lowrange 20 -uprange 20 +sy speed 1 +sy movecount $move_count +sy precision 0.01 +sy part sample +sy long_name translate_y + +# Sample Trans2, lower, x +Motor sx $motor_driver_type [params \ + asyncqueue mc2\ + axis D\ + units mm\ + hardlowerlim -20\ + hardupperlim 20\ + maxSpeed 1\ + maxAccel 1\ + maxDecel 1\ + stepsPerX -25000\ + absEnc 1\ + absEncHome $sx_Home\ + cntsPerX -8192] +setHomeandRange -motor sx -home 0 -lowrange 20 -uprange 20 +sx speed 1 +sx movecount $move_count +sx precision 0.01 +sx part sample +sx long_name translate_x + diff --git a/site_ansto/instrument/hipd/config/motors/tilt_configuration.tcl b/site_ansto/instrument/hipd/config/motors/tilt_configuration.tcl index e0442777..f4d77b6e 100644 --- a/site_ansto/instrument/hipd/config/motors/tilt_configuration.tcl +++ b/site_ansto/instrument/hipd/config/motors/tilt_configuration.tcl @@ -10,8 +10,8 @@ Motor sphi $motor_driver_type [params \ asyncqueue mc2\ axis A\ units degrees\ - hardlowerlim -360\ - hardupperlim 360\ + hardlowerlim -15\ + hardupperlim 15\ maxSpeed 1\ maxAccel 1\ maxDecel 1\ diff --git a/site_ansto/instrument/hipd/config/source/source.tcl b/site_ansto/instrument/hipd/config/source/source.tcl deleted file mode 100644 index e9107319..00000000 --- a/site_ansto/instrument/hipd/config/source/source.tcl +++ /dev/null @@ -1,5 +0,0 @@ -source $cfPath(source)/source_common.tcl - -proc ::source::isc_initialize {} { - ::source::ic_initialize "thermal" -} diff --git a/site_ansto/instrument/hipd/util/sics_config.ini b/site_ansto/instrument/hipd/util/sics_config.ini new file mode 100644 index 00000000..d2ae2724 --- /dev/null +++ b/site_ansto/instrument/hipd/util/sics_config.ini @@ -0,0 +1,106 @@ +[12tmagnet_setup] +cascade = 12tmagnet,12tmagnet_sample_insert,mercury_scipi +enabled = False +group = 0setup + +[12tmagnet] +desc = "12 Tesla Oxford Magnet" +enabled = False +group = environment:magnet +ip = 10.157.205.3 +name = magnetic +type = B +id = 1 +port = 55001 + +[ls336_1] +desc = "tc1: Lakeshore 336 temperature controller" +enabled = False +group = environment:temperature +ip = 137.157.201.85 +name = tc1 +type = T +id = 1 +port = 7777 +terminator = \r\n +tol1 = 1.0 +tol2 = 1.0 + +[ls336_2] +desc = "tc2: Lakeshore 336 temperature controller" +enabled = False +group = environment:temperature +ip = 137.157.201.87 +name = tc2 +type = T +id = 2 +port = 7777 +terminator = \r\n +tol1 = 1.0 +tol2 = 1.0 + +[ls340_1] +desc = "tc3: Lakeshore 340 temperature controller" +enabled = False +group = environment:temperature +ip = 137.157.201.86 +name = tc3 +type = T +id = 3 +port = 4001 +terminator = \r\n +tol1 = 1.0 +tol2 = 1.0 + +[ls340_2] +desc = "tc4: Lakeshore 340 temperature controller" +enabled = False +group = environment:temperature +ip = 137.157.201.86 +name = tc4 +type = T +id = 4 +port = 4002 +terminator = \r\n +tol1 = 1.0 +tol2 = 1.0 + +[mercury_itc500] +addr = @1 +desc = "tc1: Oxford Mercury temperature controller in legacy mode" +enabled = False +group = environment:temperature +ip = 10.157.205.5 +name = tc1 +type = T +id = 1 +offifon = mercury_scipi +port = 7020 +tol = 2.0 + +[mercury_scipi] +desc = "tc1: Oxford Mercury temperature controller in Mercury mode" +enabled = False +group = environment:temperature +ip = 10.157.205.5 +name = tc1 +type = T +id = 1 +offifon = mercury_itc500 +port = 7020 +tol = 2.0 +terminator = \r + +[12tmagnet_sample_insert] +desc = "REVIEW THIS -> som will be redefined as the sample insert rotation. Sample stage will be renamed to somss" +enabled = False +group = motors + +[west4100] +desc = "tc1: Blue furnace temperature controller" +enabled = False +group = environment:temperature +ip = 10.157.205.19 +name = tc1 +type = T +id = 1 diff --git a/site_ansto/instrument/hipd/wombat_configuration.tcl b/site_ansto/instrument/hipd/wombat_configuration.tcl index d730fbb0..bea0534b 100644 --- a/site_ansto/instrument/hipd/wombat_configuration.tcl +++ b/site_ansto/instrument/hipd/wombat_configuration.tcl @@ -18,20 +18,27 @@ MakeDrive source $cfPath(hipadaba)/hipadaba_configuration.tcl fileeval $cfPath(motors)/motor_configuration.tcl -fileeval $cfPath(motors)/sct_oscmotor.tcl +#fileeval $cfPath(motors)/sct_oscmotor.tcl source instrument_vars.tcl fileeval $cfPath(source)/source.tcl fileeval $cfPath(motors)/positmotor_configuration.tcl fileeval $cfPath(plc)/plc.tcl fileeval $cfPath(counter)/counter.tcl +fileeval $cfPath(environment)/sct_keithley_2700.tcl +fileeval $cfPath(environment)/sct_protek_common.tcl #TODO Provide method for choosing environment controller +fileeval $cfPath(environment)/temperature/sct_eurotherm_2000.tcl fileeval $cfPath(environment)/temperature/sct_lakeshore_336.tcl fileeval $cfPath(environment)/temperature/sct_lakeshore_340.tcl +fileeval $cfPath(environment)/temperature/sct_lakeshore_370.tcl fileeval $cfPath(environment)/temperature/sct_julabo_lh45.tcl fileeval $cfPath(environment)/temperature/sct_qlink.tcl fileeval $cfPath(environment)/temperature/west400.tcl +fileeval $cfPath(environment)/temperature/sct_oxford_mercury.tcl fileeval $cfPath(environment)/magneticField/sct_oxford_labview.tcl +#fileeval $cfPath(environment)/he3/sct_he3.tcl +#fileeval $cfPath(environment)/he3/sct_hmp_power.tcl fileeval $cfPath(environment)/magneticField/sct_green_magnet.tcl fileeval $cfPath(hmm)/hmm_configuration.tcl fileeval $cfPath(nexus)/nxscripts.tcl @@ -45,21 +52,25 @@ fileeval $cfPath(hmm)/hmm_rapid.tcl source gumxml.tcl -########################################################## -# Current driver for Lakeshore temperature controllers # -########################################################## -# driverName shortName IP-address port LineTerminator Tolerance1 Tolerance2 optional_Verbose - add_sct_ls340 tc1 137.157.201.86 4001 "\r" 5.0 5.0 -# add_sct_ls336 tc1 137.157.201.85 7777 "\r\n" 5.0 5.0 - -# add_sct_ls336 tc1 137.157.201.86 7777 "\r\n" 5.0 5.0 - # The Alice Thing - add_qlink qlink 137.157.201.86 4004 5 - add_sct_ls340 tc1 137.157.201.86 4001 "\r" 5.0 5.0 - add_lh45 tc2 137.157.201.86 4003 1 +# Qlink : 9600, 8 data, 1 stop, No Parity, None Flow +# LS340 : 9600, 7 data, 1 stop, Odd Parity, None Flow +# Julabo: 9600, 7 data, 1 stop, Even Parity, RTS/CTS Flow +# add_qlink qlink 137.157.201.86 4004 5 +# add_sct_ls340 tc1 137.157.201.86 4001 "\r" 5.0 5.0 +# add_lh45 tc2 137.157.201.86 4003 1 + +# Eurotherm +# add_et2000 name IP PORT MODBUS_ADDR TOL +# add_et2000 et2000 10.157.205.19 502 1 5 + +# Using a Keithley 2700 mulitimeter to read pressure +# add_k2700 pressure 137.157.201.86 4004 "\r" + +# Lakeshore 370 Resistance Bridge +# add_lakeshore_370 ls370 137.157.201.86 4002 2.0 + -# ::environment::temperature::add_west400 137.157.201.88 server_init ########################################### # WARNING: Do not add any code below server_init, if you do SICS may fail to initialise properly. diff --git a/site_ansto/instrument/hrpd/config/INSTCFCOMMON.TXT b/site_ansto/instrument/hrpd/config/INSTCFCOMMON.TXT index 9cc6cf7b..e84f2219 100644 --- a/site_ansto/instrument/hrpd/config/INSTCFCOMMON.TXT +++ b/site_ansto/instrument/hrpd/config/INSTCFCOMMON.TXT @@ -1,11 +1,17 @@ -config/source/source_common.tcl +config/source/sct_reactor_status.tcl +config/source/source.tcl config/anticollider/anticollider_common.tcl config/plc/plc_common_1.tcl config/counter/counter_common_1.tcl config/environment/sct_keithley_2700.tcl -config/environment/temperature/sct_lakeshore_340.tcl +config/environment/temperature/sct_eurotherm_2000.tcl config/environment/temperature/sct_lakeshore_336.tcl +config/environment/temperature/sct_lakeshore_340.tcl +config/environment/temperature/sct_oxford_mercury.tcl +config/environment/temperature/sct_watlow_pm.tcl config/environment/temperature/west400.tcl +config/environment/magneticField/sct_oxford_labview.tcl +config/environment/magneticField/sct_green_magnet.tcl config/hipadaba/hipadaba_configuration_common.tcl config/hipadaba/common_instrument_dictionary.tcl config/hipadaba/instdict_specification.tcl diff --git a/site_ansto/instrument/hrpd/config/source/source.tcl b/site_ansto/instrument/hrpd/config/source/source.tcl deleted file mode 100644 index e9107319..00000000 --- a/site_ansto/instrument/hrpd/config/source/source.tcl +++ /dev/null @@ -1,5 +0,0 @@ -source $cfPath(source)/source_common.tcl - -proc ::source::isc_initialize {} { - ::source::ic_initialize "thermal" -} diff --git a/site_ansto/instrument/hrpd/echidna_configuration.tcl b/site_ansto/instrument/hrpd/echidna_configuration.tcl index 0101042a..4fadaefd 100644 --- a/site_ansto/instrument/hrpd/echidna_configuration.tcl +++ b/site_ansto/instrument/hrpd/echidna_configuration.tcl @@ -26,10 +26,15 @@ fileeval $cfPath(motors)/positmotor_configuration.tcl fileeval $cfPath(plc)/plc.tcl fileeval $cfPath(counter)/counter.tcl #TODO Provide method for choosing environment controller +fileeval $cfPath(environment)/temperature/sct_eurotherm_2000.tcl +fileeval $cfPath(environment)/sct_keithley_2700.tcl +fileeval $cfPath(environment)/magneticField/sct_green_magnet.tcl fileeval $cfPath(environment)/sct_keithley_2700.tcl fileeval $cfPath(environment)/temperature/sct_lakeshore_336.tcl fileeval $cfPath(environment)/temperature/sct_lakeshore_340.tcl +fileeval $cfPath(environment)/temperature/sct_oxford_mercury.tcl fileeval $cfPath(environment)/temperature/west400.tcl +fileeval $cfPath(environment)/temperature/sct_watlow_pm.tcl fileeval $cfPath(hmm)/hmm_configuration.tcl fileeval $cfPath(nexus)/nxscripts.tcl fileeval $cfPath(scan)/scan.tcl diff --git a/site_ansto/instrument/kookaburra/config/INSTCFCOMMON.TXT b/site_ansto/instrument/kookaburra/config/INSTCFCOMMON.TXT index e9ca426e..04f2a106 100644 --- a/site_ansto/instrument/kookaburra/config/INSTCFCOMMON.TXT +++ b/site_ansto/instrument/kookaburra/config/INSTCFCOMMON.TXT @@ -1,4 +1,5 @@ -config/source/source_common.tcl +config/source/sct_reactor_status.tcl +config/source/source.tcl config/anticollider/anticollider_common.tcl config/plc/plc_common_1.tcl config/counter/counter_common_1.tcl @@ -8,7 +9,6 @@ config/hipadaba/instdict_specification.tcl config/hmm/hmm_configuration_common_1.tcl config/hmm/hmm_cylindrical_detector_configuration.tcl config/hmm/hmm_object.tcl -config/hmm/anstohm_linked.xml config/hmm/sct_orhvps_common.tcl config/scan/scan_common_1.hdd config/scan/scan_common_1.tcl diff --git a/site_ansto/instrument/kookaburra/config/hmm/anstohm_linked.xml b/site_ansto/instrument/kookaburra/config/hmm/anstohm_linked.xml new file mode 100644 index 00000000..5d1ccb0f --- /dev/null +++ b/site_ansto/instrument/kookaburra/config/hmm/anstohm_linked.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + [BAT_TABLE] + [CAT_TABLE] + [FAT_TABLE] + + + -0.5 0.5 + + + 0 200000 + + + 4 3 2 1 0 5 6 7 8 9 10 11 12 13 14 15 + + + + [SAT_TABLE] + + + diff --git a/site_ansto/instrument/kookaburra/config/hmm/hmm_configuration.tcl b/site_ansto/instrument/kookaburra/config/hmm/hmm_configuration.tcl index 9c7bab69..5a13e190 100644 --- a/site_ansto/instrument/kookaburra/config/hmm/hmm_configuration.tcl +++ b/site_ansto/instrument/kookaburra/config/hmm/hmm_configuration.tcl @@ -8,10 +8,10 @@ set sim_mode [SplitReply [hmm_simulation]] proc ::histogram_memory::init_OAT_TABLE {} { if [ catch { - OAT_TABLE X -setdata MAX_CHAN 8 + OAT_TABLE X -setdata MAX_CHAN 16 OAT_TABLE Y -setdata MAX_CHAN 1024 OAT_TABLE X -setdata BMIN -0.5 - OAT_TABLE X -setdata BMAX 7.5 + OAT_TABLE X -setdata BMAX 15.5 OAT_TABLE Y -setdata BMIN -0.5 OAT_TABLE Y -setdata BMAX 1023.5 @@ -21,7 +21,7 @@ proc ::histogram_memory::init_OAT_TABLE {} { hmm configure fat_frame_frequency $freq hmm configure fat_frame_source INTERNAL - OAT_TABLE -set X { 7.5 6.5 } NXC 8 Y { -0.5 0.5 } NYC 1024 T { 0 200000 } NTC 1 + OAT_TABLE -set X { -0.5 0.5 } NXC 16 Y { -0.5 0.5 } NYC 1024 T { 0 200000 } NTC 1 } message ] { if {$::errorCode=="NONE"} {return $message} return -code error $message @@ -31,13 +31,13 @@ proc ::histogram_memory::init_OAT_TABLE {} { proc CAT_TABLE {args} { return { - + - + - + @@ -46,20 +46,20 @@ return { proc ::histogram_memory::init_CAT_TABLE {} { CAT_TABLE -set MESYTEC_MPSD8_CHANNEL_GAINS { - 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 + 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 } CAT_TABLE -set MESYTEC_MPSD8_THRESHOLDS { 10 } CAT_TABLE -set MESYTEC_TUBE_PAIR_RESISTANCE_RATIOS { - 1. 1. 1. 1. 1. 1. 1. 1. + 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. } CAT_TABLE -set MESYTEC_TUBE_MAGNIFICATIONS { - 1. 1. 1. 1. 1. 1. 1. 1. + 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. } CAT_TABLE -set MESYTEC_TUBE_OFFSETS { - 0. 0. 0. 0. 0. 0. 0. 0. + 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. } CAT_TABLE -set MESYTEC_TUBE_HISTOGRAM_WEIGHTS { - 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 } } @@ -81,7 +81,7 @@ proc ::histogram_memory::isc_initialize {} { if {$::sim_mode == "true"} { hmm configure oat_ntc_eff 1 hmm configure $INST_NYC 1024 - hmm configure $INST_NXC 8 + hmm configure $INST_NXC 16 } BAT_TABLE -init # CAT_TABLE -init @@ -92,7 +92,7 @@ proc ::histogram_memory::isc_initialize {} { ::histogram_memory::set_graphtype "two_theta" "boundaries" # MJL TODO detector geometry for Kookaburra TBD. Figures need revision during commissioning - # Width = 25mm spacing * 8 tubes = 5000mm (??? degree coverage) + # Width = 25mm spacing * 16 tubes = 5000mm (??? degree coverage) # Height = 1015mm (tube length) # Radius = 2400mm detector_active_height_mm 1015 @@ -107,13 +107,14 @@ proc ::histogram_memory::isc_initialize {} { # hmm configure FAT_SIMULATED_EVENT_X0 $x_bb0 # hmm configure FAT_SIMULATED_EVENT_X1 $xbbmax ::histogram_memory::init_OAT_TABLE - ::histogram_memory::init_SAT_TABLE +# ::histogram_memory::init_SAT_TABLE # ::histogram_memory::init_CAT_TABLE ::histogram_memory::upload_config Filler_defaults set ::histogram_memory::histmem_axes(HOR) /instrument/detector/x_pixel_angular_offset set ::histogram_memory::histmem_axes(VER) /instrument/detector/y_pixel_offset } message ] { + clientput ERROR:([info level 0]) $message if {$::errorCode=="NONE"} {return $message} return -code error $message } diff --git a/site_ansto/instrument/kookaburra/config/motors/motor_configuration.tcl b/site_ansto/instrument/kookaburra/config/motors/motor_configuration.tcl index 08230b28..44c7f618 100644 --- a/site_ansto/instrument/kookaburra/config/motors/motor_configuration.tcl +++ b/site_ansto/instrument/kookaburra/config/motors/motor_configuration.tcl @@ -48,6 +48,10 @@ dummy_motor home 0 # all motor rate is 25000steps/turn if no other specify set motorrate 25000.0 +# maxi motor speed for all slits +set maxSpeedSlit 300000.0 + + ############################ # Motor Controller 1 # Motor Controller 1 @@ -56,158 +60,148 @@ set motorrate 25000.0 # mc1: Be Filter Y Translation -# Gearbox -set bex_Home 0 -set bexStepRate [expr (300000.0/100.0)/2.0] +# Gearbox 1:1, pitch 2mm +# Encoder 2P12 +# center Bin position +set bex_Home 8671062 +set bexStepRate [expr $motorrate/2.0] Motor bex $motor_driver_type [params \ asyncqueue mc1\ host mc1-kookaburra\ port pmc1-kookaburra\ axis A\ units mm\ - hardlowerlim 0\ - hardupperlim 500\ - maxSpeed [expr 400000.0/300000.0]\ - maxAccel [expr 150000.0/300000.0]\ - maxDecel [expr 150000.0/300000.0]\ - stepsPerX $bexStepRate\ + hardlowerlim -7.373000\ + hardupperlim 134.001465\ + maxSpeed 2\ + maxAccel 2\ + maxDecel 2\ + stepsPerX -$bexStepRate\ absEnc 1\ absEncHome $bex_Home\ - cntsPerX 4096] + cntsPerX [expr -4096/2.0] ] +bex speed 2 bex part crystal bex long_name bex -bex softlowerlim 0 -bex softupperlim 500 +bex softlowerlim -7.000000 +bex softupperlim 133.000000 bex home 0 # mc1: Premonochromator Crystal Si(111) Tilt -# Gearbox 50:1, -set pmchi_Home 0 -set pmchiStepRate [expr (300000.0/100.0)/2.0] +# Gearbox 55:1, 0.5 degree +# Encoder 2P12, +set pmchi_Home 8410424 +set pmchiStepRate [expr $motorrate*55.0/0.5] Motor pmchi $motor_driver_type [params \ asyncqueue mc1\ host mc1-kookaburra\ port pmc1-kookaburra\ axis B\ units degrees\ - hardlowerlim 0\ - hardupperlim 500\ - maxSpeed [expr 400000.0/300000.0]\ - maxAccel [expr 150000.0/300000.0]\ - maxDecel [expr 150000.0/300000.0]\ - stepsPerX $pmchiStepRate\ + hardlowerlim -1.2\ + hardupperlim 1.309937\ + maxSpeed 0.018\ + maxAccel 0.05\ + maxDecel 0.05\ + stepsPerX -$pmchiStepRate\ absEnc 1\ absEncHome $pmchi_Home\ - cntsPerX 4096] + cntsPerX [expr 4096.0*2] ] +pmchi precision 0.0001 +pmchi speed 0.018 pmchi part crystal pmchi long_name pmchi -pmchi softlowerlim 0 -pmchi softupperlim 500 +pmchi softlowerlim -1.15 +pmchi softupperlim 1.309937 pmchi home 0 # mc1: Premonochromator Crystal Si(111) Rotate -# Gearbox 100:1, -set pmom_Home 0 -set pmomStepRate [expr (300000.0/100.0)/2.0] +# Gearbox 50:1, pitch 1 degree +# Encoder 2P25 +# Crystal B 0, 18889883 +# Crystal HOPG position 179.603806, 2149592 +# Crystal HOPG loading position 49.740612, 14253738 +set pmom_Home 2102963 +set pmomStepRate [expr $motorrate*50.0] Motor pmom $motor_driver_type [params \ asyncqueue mc1\ host mc1-kookaburra\ port pmc1-kookaburra\ axis C\ units degrees\ - hardlowerlim 0\ - hardupperlim 500\ - maxSpeed [expr 400000.0/300000.0]\ - maxAccel [expr 150000.0/300000.0]\ - maxDecel [expr 150000.0/300000.0]\ - stepsPerX $pmomStepRate\ + hardlowerlim -10\ + hardupperlim 80\ + maxSpeed 0.2\ + maxAccel 0.08\ + maxDecel 0.2\ + stepsPerX -$pmomStepRate\ absEnc 1\ absEncHome $pmom_Home\ - cntsPerX 4096] + cntsPerX 93206.755555556 ] +pmom precision 0.0001 +pmom speed 0.16 pmom part crystal pmom long_name pmom -pmom softlowerlim 0 -pmom softupperlim 500 +pmom softlowerlim -7 +pmom softupperlim 77 pmom home 0 -# mc1: Main Detector - Y Translate -# Gearbox 23:1 -set mdet_Home 0 -set mdetStepRate [expr (300000.0/100.0)/2.0] +# mc1: Main Detector - X Translate +# Gearbox 20:1, pitch 5mm +# Encoder 2p17 +set mdet_Home 521939864 +set mdetStepRate [expr $motorrate *20.0/5.0] Motor mdet $motor_driver_type [params \ asyncqueue mc1\ host mc1-kookaburra\ port pmc1-kookaburra\ axis D\ units mm\ - hardlowerlim 0\ - hardupperlim 500\ - maxSpeed [expr 400000.0/300000.0]\ - maxAccel [expr 150000.0/300000.0]\ - maxDecel [expr 150000.0/300000.0]\ - stepsPerX $mdetStepRate\ + hardlowerlim -3\ + hardupperlim 498\ + maxSpeed [expr 100000.0/$mdetStepRate]\ + maxAccel [expr 25000.0/$mdetStepRate]\ + maxDecel [expr 25000.0/$mdetStepRate]\ + stepsPerX -$mdetStepRate\ absEnc 1\ absEncHome $mdet_Home\ - cntsPerX 4096] -mdet part detector + cntsPerX [expr 131072/5.0] ] +mdet precision 0.01 +mdet speed 1 +mdet part crystal mdet long_name mdet -mdet softlowerlim 0 -mdet softupperlim 500 -mdet home 0 - - -# mc1: Tertiary Beam Shutter, status only and is controlled via PLC panel -# Gearbox -set plc_tertiary 0 -set plc_tertiaryStepRate [expr (300000.0/100.0)/2.0] -Motor plc_tertiary $motor_driver_type [params \ - asyncqueue mc1\ - host mc1-kookaburra\ - port pmc1-kookaburra\ - axis F\ - units mm\ - hardlowerlim 0\ - hardupperlim 2\ - maxSpeed [expr 250000.0/$plc_tertiarySetRate]\ - maxAccel [expr 25000.0/$plc_tertiarySetRate]\ - maxDecel [expr 25000.0/$plc_tertiarySetRate]\ - stepsPerX $plc_tertiarySetRate\ - absEnc 1\ - absEncHome $plc_tertiary_Home\ - cntsPerX 4096] -plc_tertiary part detector -plc_tertiary long_name plc_tertiary -plc_tertiary softlowerlim 0 -plc_tertiary softupperlim 2 -plc_tertiary home 0 +mdet softlowerlim -2.5 +mdet hardupperlim 497 # mc1: Detector Stage Y Attenuator # Gearbox -set att_Home 0 -set attSetRate 25000 +set att_Home 546986 +set attSetRate [expr $motorrate/5.0] Motor att $motor_driver_type [params \ asyncqueue mc1\ host mc1-kookaburra\ port pmc1-kookaburra\ - axis G\ + axis E\ units mm\ - hardlowerlim -125\ - hardupperlim 8\ + hardlowerlim -215\ + hardupperlim 5.8\ maxSpeed [expr 150000.0/$attSetRate]\ maxAccel [expr 5000.0/$attSetRate]\ maxDecel [expr 5000.0/$attSetRate]\ - stepsPerX $attSetRate\ + stepsPerX -$attSetRate\ absEnc 1\ absEncHome $att_Home\ - cntsPerX 4096] + cntsPerX [expr 8192/5.0]] +att precision 0.01 +att speed 2 att part detector att long_name att -att softlowerlim -125 -att softupperlim 8 +att softlowerlim -214.5 +att softupperlim 5.5 att home 0 @@ -216,195 +210,218 @@ att home 0 # Motor Controller 2 # Motor Controller 2 ############################ -# +# # mc2: CC1 Monochromator Stage Tilt -# Gearbox 50:1 -set m1chi_Home 0 -set m1chiSetRate 25000 +# Gearbox 20:1, screw pitch 356 +# Encoder 2p17 +# 68.681 +set m1chi_Home 15016533 +set m1chiSetRate [expr $motorrate*20*100/68.681] Motor m1chi $motor_driver_type [params \ asyncqueue mc2\ host mc2-kookaburra\ port pmc2-kookaburra\ axis A\ units degrees\ - hardlowerlim -2\ - hardupperlim 60\ - maxSpeed [expr 25000.0/$m1chiSetRate]\ + hardlowerlim -7.5\ + hardupperlim 7.5\ + maxSpeed [expr 100000.0/$m1chiSetRate]\ maxAccel [expr 25000.0/$m1chiSetRate]\ - maxDecel [expr 25000.0/$m1chiSetRate]\ - stepsPerX $m1chiSetRate\ + maxDecel [expr 250000.0/$m1chiSetRate]\ + stepsPerX -$m1chiSetRate\ absEnc 1\ absEncHome $m1chi_Home\ - cntsPerX 4096] + cntsPerX [expr 131072*100.0/68.681] ] +m1chi precision 0.001 +m1chi speed 0.200 m1chi part crystal m1chi long_name m1chi m1chi softlowerlim -2 -m1chi softupperlim 60 -m1chi home 0 +m1chi softupperlim 2 +m1chi home 0 # mc2: CC1 Monochromator Stage Rotation -# Gearbox 60:1 -set m1om_Home 0 -set m1omSetRate 25000 +# Gearbox 100:1, screw pitch 356 +# Encoder 2p25 +# m1om_Home 13617081 +set m1om_Home 30395150 +set m1omSetRate [expr $motorrate*100*356/360] Motor m1om $motor_driver_type [params \ asyncqueue mc2\ host mc2-kookaburra\ port pmc2-kookaburra\ axis B\ units degrees\ - hardlowerlim -2\ - hardupperlim 50\ - maxSpeed [expr 25000.0/$m1omSetRate]\ + hardlowerlim -0.01\ + hardupperlim 182\ + maxSpeed [expr 300000.0/$m1omSetRate]\ maxAccel [expr 25000.0/$m1omSetRate]\ maxDecel [expr 25000.0/$m1omSetRate]\ stepsPerX $m1omSetRate\ absEnc 1\ absEncHome $m1om_Home\ - cntsPerX 4096] + cntsPerX [expr 33554432.0/360.0]\ + nopowersave 1] +m1om precision 0.00001 +m1om speed 0.1 m1om part crystal m1om long_name m1om -m1om softlowerlim -2 -m1om softupperlim 50 -m1om home 0 +m1om softlowerlim 0 +m1om softupperlim 182 +m1om home 180 +m1om precision 0.00001 +m1om Creep_Offset 0.001 +m1om Creep_Precision 0.000009 +m1om Creep_Factor 0.5 +m1om Creep_Substep 0.04 -# mc2: CC1 Monochromator Stage Y Translation -# Gearbox 20:1 -set m1x_Home 0 -set m1xSetRate 25000 +# mc2: CC1 Monochromator Stage X Translation +# Gearbox 20:1, pitch 5mm +# Encoder 2p17 +set m1x_Home 3754723 +set m1xSetRate [expr $motorrate*20.0/5.0] Motor m1x $motor_driver_type [params \ asyncqueue mc2\ host mc2-kookaburra\ port pmc2-kookaburra\ axis C\ units mm\ - hardlowerlim -2\ - hardupperlim 40\ - maxSpeed [expr 25000.0/$m1xSetRate]\ + hardlowerlim -82.5\ + hardupperlim 50.0\ + maxSpeed [expr 100000.0/$m1xSetRate]\ maxAccel [expr 25000.0/$m1xSetRate]\ maxDecel [expr 25000.0/$m1xSetRate]\ stepsPerX $m1xSetRate\ absEnc 1\ absEncHome $m1x_Home\ - cntsPerX 4096] + cntsPerX [expr -131072/5.0]] +m1x speed 0.3 m1x part crystal m1x long_name m1x -m1x softlowerlim -2 -m1x softupperlim 40 +m1x softlowerlim -82 +m1x softupperlim 49 m1x home 0 - # mc2: Slit system - 1 TOP Blade -# Gearbox 55:1 -set ss1u_Home 0 -set ss1uSetRate 25000 +# Gearbox 55:1, pitch 0.5mm +# Encoder 2p13 +set ss1u_Home 918407 +set ss1uSetRate [expr $motorrate*55.0/0.5] Motor ss1u $motor_driver_type [params \ asyncqueue mc2\ host mc2-kookaburra\ port pmc2-kookaburra\ axis D\ units mm\ - hardlowerlim -2\ - hardupperlim 30\ - maxSpeed [expr 25000.0/$ss1uSetRate]\ - maxAccel [expr 25000.0/$ss1uSetRate]\ - maxDecel [expr 25000.0/$ss1uSetRate]\ - stepsPerX $ss1uSetRate\ + hardlowerlim -33.5\ + hardupperlim 37.8\ + maxSpeed [expr $maxSpeedSlit/$ss1uSetRate]\ + maxAccel [expr 5000.0/$ss1uSetRate/0.5]\ + maxDecel [expr 5000.0/$ss1uSetRate/0.5]\ + stepsPerX -$ss1uSetRate\ absEnc 1\ absEncHome $ss1u_Home\ - cntsPerX 4096] -ss1u parts slits + cntsPerX 16384] +ss1u speed 0.1 +ss1u part slits ss1u long_name ss1u -ss1u softlowerlim -2 -ss1u softupperlim 30 +ss1u softlowerlim -33 +ss1u softupperlim 37 ss1u home 0 # mc2: Slit system - 1 BOTTOM Blade -# Gearbox 55:1 -set ss1d_Home 0 -set ss1dSetRate 25000 +# Gearbox 55:1, pitch 0.5mm +# Encoder 2p13 +set ss1d_Home 1157895 +set ss1dSetRate [expr $motorrate*55.0/0.5] Motor ss1d $motor_driver_type [params \ asyncqueue mc2\ host mc2-kookaburra\ port pmc2-kookaburra\ axis E\ units mm\ - hardlowerlim 0\ - hardupperlim 15\ - maxSpeed [expr 50000.0/$ss1dSetRate]\ - maxAccel [expr 25000.0/$ss1dSetRate]\ - maxDecel [expr 25000.0/$ss1dSetRate]\ - stepsPerX $ss1dSetRate\ + hardlowerlim -38.866577\ + hardupperlim 35\ + maxSpeed [expr $maxSpeedSlit/$ss1dSetRate]\ + maxAccel [expr 5000.0/$ss1dSetRate/0.5]\ + maxDecel [expr 5000.0/$ss1dSetRate/0.5]\ + stepsPerX -$ss1dSetRate\ absEnc 1\ absEncHome $ss1d_Home\ - cntsPerX 4096] + cntsPerX 16384] +ss1d speed 0.1 ss1d part slits ss1d long_name ss1d -ss1d softlowerlim 0 -ss1d softupperlim 15 +ss1d softlowerlim -37.8 +ss1d softupperlim 35 ss1d home 0 # mc2: Slit system - 1 LEFT Blade -# Gearbox 55:1 -set ss1l_Home 0 -set ss1lSetRate 25000 +# Gearbox 55:1, pitch 0.5mm +# Encoder 2p13 +set ss1l_Home 32548210 +set ss1lSetRate [expr $motorrate*55.0/0.5] Motor ss1l $motor_driver_type [params \ asyncqueue mc2\ host mc2-kookaburra\ port pmc2-kookaburra\ axis F\ units mm\ - hardlowerlim 0\ - hardupperlim 360\ - maxSpeed [expr 50000.0/$ss1lSetRate]\ - maxAccel [expr 25000.0/$ss1lSetRate]\ - maxDecel [expr 25000.0/$ss1lSetRate]\ + hardlowerlim -58\ + hardupperlim 55\ + maxSpeed [expr $maxSpeedSlit/$ss1lSetRate]\ + maxAccel [expr 5000.0/$ss1lSetRate/0.5]\ + maxDecel [expr 5000.0/$ss1lSetRate/0.5]\ stepsPerX $ss1lSetRate\ absEnc 1\ absEncHome $ss1l_Home\ - cntsPerX 4096] + cntsPerX -16384] +ss1l speed 0.1 ss1l part slits ss1l long_name ss1l -ss1l softlowerlim 0 -ss1l softupperlim 360 +ss1l softlowerlim -56 +ss1l softupperlim 54 ss1l home 0 # mc2: Slit system - 1 RIGHT Blade -# Gearbox 55:1 -set ss1r_Home 0 -set ss1rSetRate 25000 +# Gearbox 55:1, pitch 0.5mm +# Encoder 2p13 +set ss1r_Home 1656697 +set ss1rSetRate [expr $motorrate*55.0/0.5] Motor ss1r $motor_driver_type [params \ asyncqueue mc2\ host mc2-kookaburra\ port pmc2-kookaburra\ axis G\ units mm\ - hardlowerlim 0\ - hardupperlim 15\ - maxSpeed [expr 50000.0/$ss1rSetRate]\ - maxAccel [expr 25000.0/$ss1rSetRate]\ - maxDecel [expr 25000.0/$ss1rSetRate]\ + hardlowerlim -57\ + hardupperlim 58\ + maxSpeed [expr $maxSpeedSlit/$ss1rSetRate]\ + maxAccel [expr 5000.0/$ss1rSetRate/0.5]\ + maxDecel [expr 5000.0/$ss1rSetRate/0.5]\ stepsPerX $ss1rSetRate\ absEnc 1\ absEncHome $ss1r_Home\ - cntsPerX 4096] + cntsPerX -16384] +ss1r speed 0.1 ss1r part slits ss1r long_name ss1r -ss1r softlowerlim 0 -ss1r softupperlim 15 +ss1r softlowerlim -55 +ss1r softupperlim 57 ss1r home 0 # mc2: Sample Changer (Sample Stage) Z Translation # Gearbox 1:1 -set samz_Home 0 -set samzSetRate 25000 -Motor samz $motor_driver_type [params \ +#set samz_Home +#set samzSetRate 25000 +#Motor samz $motor_driver_type [params \ asyncqueue mc2\ host mc2-kookaburra\ port pmc2-kookaburra\ @@ -419,11 +436,11 @@ Motor samz $motor_driver_type [params \ absEnc 1\ absEncHome $samz_Home\ cntsPerX 4096] -samz part sample -samz long_name samz -samz softlowerlim 0 -samz softupperlim 360 -samz home 0 +#samz part sample +#samz long_name samz +#samz softlowerlim 0 +#samz softupperlim 360 +#samz home 0 ############################ @@ -434,210 +451,239 @@ samz home 0 # # mc3: Slit system - 2 TOP Blade -# Gearbox 55:1 -set ss2u_Home 0 -set ss2uSetRate 25000 +# Gearbox 55:1, pitch 0.5mm +# Encoder 2p13 +set ss2u_Home 31240374 +set ss2uSetRate [expr $motorrate*55.0/0.5] +#maxSpeed [expr 400000.0/$ss1uSetRate] Motor ss2u $motor_driver_type [params \ asyncqueue mc3\ host mc3-kookaburra\ port pmc3-kookaburra\ axis A\ units mm\ - hardlowerlim -2\ - hardupperlim 30\ - maxSpeed [expr 25000.0/$ss1uSetRate]\ - maxAccel [expr 25000.0/$ss1uSetRate]\ - maxDecel [expr 25000.0/$ss1uSetRate]\ - stepsPerX $ss2uSetRate\ + hardlowerlim -33.1\ + hardupperlim 37\ + maxSpeed [expr $maxSpeedSlit/$ss1uSetRate]\ + maxAccel [expr 5000.0/$ss1uSetRate/0.5]\ + maxDecel [expr 5000.0/$ss1uSetRate/0.5]\ + stepsPerX -$ss2uSetRate\ absEnc 1\ absEncHome $ss2u_Home\ - cntsPerX 4096] -ss2u parts slits + cntsPerX 16384] +ss2u speed 0.1 +ss2u part slits ss2u long_name ss2u -ss2u softlowerlim -2 -ss2u softupperlim 30 +ss2u softlowerlim -32.0 +ss2u softupperlim 36 ss2u home 0 # mc3: Slit system - 2 BOTTOM Blade -# Gearbox 55:1 -set ss2d_Home 0 -set ss2dSetRate 25000 +# Gearbox 55:1, pitch 0.5mm +# Encoder 2p13 +set ss2d_Home 830475 +set ss2dSetRate [expr $motorrate*55.0/0.5] +#maxSpeed [expr 4000000.0/$ss2dSetRate] Motor ss2d $motor_driver_type [params \ asyncqueue mc3\ host mc3-kookaburra\ port pmc3-kookaburra\ axis B\ units mm\ - hardlowerlim 0\ - hardupperlim 15\ - maxSpeed [expr 50000.0/$ss2dSetRate]\ - maxAccel [expr 25000.0/$ss2dSetRate]\ - maxDecel [expr 25000.0/$ss2dSetRate]\ - stepsPerX $ss2dSetRate\ + hardlowerlim -39.5\ + hardupperlim 35\ + maxSpeed [expr $maxSpeedSlit/$ss2dSetRate]\ + maxAccel [expr 5000.0/$ss2dSetRate/0.5]\ + maxDecel [expr 5000.0/$ss2dSetRate/0.5]\ + stepsPerX -$ss2dSetRate\ absEnc 1\ absEncHome $ss2d_Home\ - cntsPerX 4096] + cntsPerX 16384] +ss2d speed 0.1 ss2d part slits ss2d long_name ss2d -ss2d softlowerlim 0 -ss2d softupperlim 15 +ss2d softlowerlim -39 +ss2d softupperlim 34 ss2d home 0 # mc3: Slit system - 2 LEFT Blade -# Gearbox 55:1 -set ss2l_Home 0 -set ss2lSetRate 25000 +# Gearbox 55:1, pitch 0.5mm +# Encoder 2p13 +set ss2l_Home 808402 +set ss2lSetRate [expr $motorrate*55.0/0.5] +#maxSpeed [expr 400000.0/$ss2lSetRate] Motor ss2l $motor_driver_type [params \ asyncqueue mc3\ host mc3-kookaburra\ port pmc3-kookaburra\ axis C\ units mm\ - hardlowerlim 0\ - hardupperlim 360\ - maxSpeed [expr 50000.0/$ss2lSetRate]\ - maxAccel [expr 25000.0/$ss2lSetRate]\ - maxDecel [expr 25000.0/$ss2lSetRate]\ - stepsPerX $ss2lSetRate\ + hardlowerlim -35\ + hardupperlim 34.5\ + maxSpeed [expr $maxSpeedSlit/$ss2lSetRate]\ + maxAccel [expr 5000.0/$ss2lSetRate/0.5]\ + maxDecel [expr 5000.0/$ss2lSetRate/0.5]\ + stepsPerX -$ss2lSetRate\ absEnc 1\ absEncHome $ss2l_Home\ - cntsPerX 4096] + cntsPerX 16384] +ss2l speed 0.1 ss2l part slits ss2l long_name ss2l -ss2l softlowerlim 0 -ss2l softupperlim 360 +ss2l softlowerlim -34.5 +ss2l softupperlim 33 ss2l home 0 # mc3: Slit system - 2 RIGHT Blade -# Gearbox 55:1 -set ss2r_Home 0 -set ss2rSetRate 25000 +# Gearbox 55:1, pitch 0.5mm +# Encoder 2p13 +set ss2r_Home 32713034 +set ss2rSetRate [expr $motorrate*55.0/0.5] +#maxSpeed [expr 400000.0/$ss2rSetRate] Motor ss2r $motor_driver_type [params \ asyncqueue mc3\ host mc3-kookaburra\ port pmc3-kookaburra\ axis D\ units mm\ - hardlowerlim 0\ - hardupperlim 15\ - maxSpeed [expr 50000.0/$ss2rSetRate]\ - maxAccel [expr 25000.0/$ss2rSetRate]\ - maxDecel [expr 25000.0/$ss2rSetRate]\ - stepsPerX $ss2rSetRate\ + hardlowerlim -36\ + hardupperlim 35\ + maxSpeed [expr $maxSpeedSlit/$ss2rSetRate]\ + maxAccel [expr 5000.0/$ss2rSetRate/0.5]\ + maxDecel [expr 5000.0/$ss2rSetRate/0.5]\ + stepsPerX -$ss2rSetRate\ absEnc 1\ absEncHome $ss2r_Home\ - cntsPerX 4096] + cntsPerX 16384] +ss2r speed 0.1 ss2r part slits ss2r long_name ss2r -ss2r softlowerlim 0 -ss2r softupperlim 15 +ss2r softlowerlim -35 +ss2r softupperlim 34 ss2r home 0 # mc3: CC2 Analyser Stage - Tilt -# Gearbox 50:1 -set m2chi_Home 0 -set m2chiSetRate 25000 +# Gearbox 20:1, screw pitch 356 +# Encoder 2p17 +# 68.681 +set m2chi_Home 15512615 +set m2chiSetRate [expr $motorrate*20*100/68.681] Motor m2chi $motor_driver_type [params \ asyncqueue mc3\ host mc3-kookaburra\ port pmc3-kookaburra\ axis E\ units degrees\ - hardlowerlim -2\ - hardupperlim 60\ - maxSpeed [expr 25000.0/$m2chiSetRate]\ + hardlowerlim -7.5\ + hardupperlim 7.5\ + maxSpeed [expr 100000.0/$m2chiSetRate]\ maxAccel [expr 25000.0/$m2chiSetRate]\ maxDecel [expr 25000.0/$m2chiSetRate]\ - stepsPerX $m2chiSetRate\ + stepsPerX -$m2chiSetRate\ absEnc 1\ absEncHome $m2chi_Home\ - cntsPerX 4096] + cntsPerX [expr 131072*100.0/68.681]] +m2chi precision 0.001 +m2chi speed 0.200 m2chi part crystal m2chi long_name m2chi m2chi softlowerlim -2 -m2chi softupperlim 60 +m2chi softupperlim 2 m2chi home 0 +# set m2om_Home 15776972 # mc3: CC2 Analyser Stage - Rotation -# Gearbox 60:1 -set m2om_Home 0 -set m2omSetRate 25000 +# Gearbox 100:1, screw pitch 356 +# Encoder 2p25 +set m2om_Home 23155978 +set m2omSetRate [expr $motorrate*100.0*356.0/360.0] Motor m2om $motor_driver_type [params \ asyncqueue mc3\ host mc3-kookaburra\ port pmc3-kookaburra\ axis F\ units degrees\ - hardlowerlim -2\ - hardupperlim 50\ - maxSpeed [expr 25000.0/$m2omSetRate]\ + hardlowerlim 0\ + hardupperlim 182\ + maxSpeed [expr 300000.0/$m2omSetRate]\ maxAccel [expr 25000.0/$m2omSetRate]\ maxDecel [expr 25000.0/$m2omSetRate]\ - stepsPerX $m2omSetRate\ + stepsPerX -$m2omSetRate\ absEnc 1\ absEncHome $m2om_Home\ - cntsPerX 4096] + cntsPerX [expr 33554432.0/360.0]\ + nopowersave 1] +m2om speed 0.1 m2om part crystal m2om long_name m2om -m2om softlowerlim -2 -m2om softupperlim 50 -m2om home 0 +m2om softlowerlim 0 +m2om softupperlim 182 +m2om home 180 +m2om precision 0.00001 +m2om Creep_Offset 0.001 +m2om Creep_Precision 0.000009 +m2om Creep_Factor 0.5 +m2om Creep_Substep 0.04 # mc3: CC2 Analyser Stage - X Translate -# Gearbox 20:1 -set m2x_Home 0 -set m2xSetRate 25000 +# Gearbox 20:1, pitch 5mm +# Encoder 2p17 +set m2x_Home 524680153 +set m2xSetRate [expr $motorrate*20.0/5.0] Motor m2x $motor_driver_type [params \ asyncqueue mc3\ host mc3-kookaburra\ port pmc3-kookaburra\ axis G\ units mm\ - hardlowerlim -2\ - hardupperlim 40\ - maxSpeed [expr 25000.0/$m2xSetRate]\ + hardlowerlim -130\ + hardupperlim 114.4\ + maxSpeed [expr 100000.0/$m2xSetRate]\ maxAccel [expr 25000.0/$m2xSetRate]\ maxDecel [expr 25000.0/$m2xSetRate]\ stepsPerX $m2xSetRate\ absEnc 1\ absEncHome $m2x_Home\ - cntsPerX 4096] + cntsPerX [expr -131072/5.0]] +m2x speed 0.5 m2x part crystal m2x long_name m2x -m2x softlowerlim -2 -m2x softupperlim 40 +m2x softlowerlim -129 +m2x softupperlim 114 m2x home 0 # mc3: CC2 Analyser Stage - Y Translation -# Gearbox 20:1 -set m2y_Home 0 -set m2ySetRate 25000 +# Gearbox 20:1, pitch 5mm +# Encoder 2p17 +set m2y_Home 516940434 +set m2ySetRate [expr $motorrate*20.0/5.0] Motor m2y $motor_driver_type [params \ asyncqueue mc3\ host mc3-kookaburra\ port pmc3-kookaburra\ axis H\ units mm\ - hardlowerlim -2\ - hardupperlim 40\ - maxSpeed [expr 25000.0/$m2ySetRate]\ + hardlowerlim -4.35\ + hardupperlim 357.9\ + maxSpeed [expr 100000.0/$m2ySetRate]\ maxAccel [expr 25000.0/$m2ySetRate]\ maxDecel [expr 25000.0/$m2ySetRate]\ stepsPerX $m2ySetRate\ absEnc 1\ absEncHome $m2y_Home\ - cntsPerX 4096] + cntsPerX [expr 131072/5.0]] +m2y speed 0.5 m2y part crystal m2y long_name m2y -m2y softlowerlim -2 -m2y softupperlim 40 +m2y softlowerlim -4.3 +m2y softupperlim 355 m2y home 0 diff --git a/site_ansto/instrument/kookaburra/config/parameters/parameters.tcl b/site_ansto/instrument/kookaburra/config/parameters/parameters.tcl new file mode 100644 index 00000000..518daa80 --- /dev/null +++ b/site_ansto/instrument/kookaburra/config/parameters/parameters.tcl @@ -0,0 +1,27 @@ +# TODO Make readonly getset macro for AttFactor + +## +# @file The velocity selector position is used as the reference for other instrument +# component positions. For simplicity we set it as the origin x=y=z=0. + +## +# Note EndFacePosY and RotApPosY are surveyed positions +foreach {var lname type priv units klass} { + wavelength wavelength float user Angstrom crystal + MainDeadTime MainDeadTime float user s detector + TransDeadTime TransDeadTime float user s detector + TransmissionTube TransmissionTube int user none detector + bkgLevel bkgLevel float user 1 experiment + deg2QConv deg2QConv float user none experiment + dOmega dOmega float user degrees experiment + empLevel empLevel float user none experiment + gDQv gDQv float user none experiment + level level float user none experiment + thickness thickness float user mm sample + defaultMCR defaultMCR float user count/sec monitor +} { + ::utility::mkVar $var $type $priv $lname true $klass true true + if {$units != "none"} { + sicslist setatt $var units $units + } +} diff --git a/site_ansto/instrument/kookaburra/config/scan/scan.tcl b/site_ansto/instrument/kookaburra/config/scan/scan.tcl index dd396f62..7eaef1f8 100644 --- a/site_ansto/instrument/kookaburra/config/scan/scan.tcl +++ b/site_ansto/instrument/kookaburra/config/scan/scan.tcl @@ -4,3 +4,57 @@ proc ::scan::pre_hmm_scan_prepare {} {} proc ::scan::isc_initialize {} { ::scan::ic_initialize } + +proc filecounts_log {fname txt} { + set fd [open $fname a] + puts $fd "$txt" + close $fd +} + +proc thresholdscan {minVoltage maxVoltage stepVoltage minBMThreshold manBMThreshold stepBMThreshold scantime} { + + # following is used to obtain an optimal BM threshold + set fileCounts ../log/bmcounts.log + set fileCountsDiff ../log/bmcountsdiff.log + + variable curCount + + set fd [open $fileCounts w] + close $fd + set fd [open $fileCountsDiff w] + close $fd + + set txt "" + for {set thres $minBMThreshold} {$thres <= $manBMThreshold} {incr thres $stepBMThreshold} { + lappend txt $thres + } + filecounts_log $fileCounts "Thres: $txt" + + clientput "Start scanning loop now" + for {set vol $minVoltage} {$vol <= $maxVoltage} {incr vol $stepVoltage} { + emHV1 $vol + set curCount "" + for {set thres $minBMThreshold} {$thres <= $manBMThreshold} {incr thres $stepBMThreshold} { + clientput "set thredshold to $thres" + bmthreshold $thres + + setcounter stop + clientput "Threshold= $thres, scanning $scantime seconds now..." + setcounter start time=$scantime + clientput "Store count now..." + lappend curCount [hval /sample/emHV/count1] + } + set txt "$vol : $curCount" + filecounts_log $fileCounts $txt + set diff "" + for {set ind 1} {$ind < [llength $curCount]} {incr ind} { + lappend diff [expr [lindex $curCount $ind]-[lindex $curCount [expr $ind-1]]] + } + set txt "$vol : $diff" + filecounts_log $fileCountsDiff $txt + + } +} + +publish thresholdscan user + diff --git a/site_ansto/instrument/kookaburra/config/source/source.tcl b/site_ansto/instrument/kookaburra/config/source/source.tcl deleted file mode 100644 index 50967ab8..00000000 --- a/site_ansto/instrument/kookaburra/config/source/source.tcl +++ /dev/null @@ -1,8 +0,0 @@ -# Author Jing Chen (jgn@ansto.gov.au) - -source $cfPath(source)/source_common.tcl - -proc ::source::isc_initialize {} { - ::source::ic_initialize "thermal" -} - diff --git a/site_ansto/instrument/kookaburra/kookaburra_configuration.tcl b/site_ansto/instrument/kookaburra/kookaburra_configuration.tcl index 920ed81b..dd68e0e2 100644 --- a/site_ansto/instrument/kookaburra/kookaburra_configuration.tcl +++ b/site_ansto/instrument/kookaburra/kookaburra_configuration.tcl @@ -19,16 +19,19 @@ source $cfPath(hipadaba)/hipadaba_configuration.tcl fileeval $cfPath(source)/source.tcl fileeval $cfPath(motors)/motor_configuration.tcl -fileeval $cfPath(motors)/positmotor_configuration.tcl +#fileeval $cfPath(motors)/positmotor_configuration.tcl #fileeval $cfPath(motors)/extraconfig.tcl fileeval $cfPath(plc)/plc.tcl fileeval $cfPath(counter)/counter.tcl +#fileeval $cfPath(environment)/temperature/sct_lakeshore_218.tcl +fileeval $cfPath(counter)/sct_bm.tcl fileeval $cfPath(hmm)/hmm_configuration.tcl fileeval $cfPath(nexus)/nxscripts.tcl fileeval $cfPath(scan)/scan.tcl fileeval $cfPath(commands)/commands.tcl -fileeval $cfPath(commands)/monodrive.tcl +#fileeval $cfPath(commands)/monodrive.tcl fileeval $cfPath(anticollider)/anticollider.tcl +fileeval $cfPath(parameters)/parameters.tcl source gumxml.tcl diff --git a/site_ansto/instrument/lyrebird/config/INSTCFCOMMON.TXT b/site_ansto/instrument/lyrebird/config/INSTCFCOMMON.TXT index eeee47e2..93b623e1 100644 --- a/site_ansto/instrument/lyrebird/config/INSTCFCOMMON.TXT +++ b/site_ansto/instrument/lyrebird/config/INSTCFCOMMON.TXT @@ -1,4 +1,5 @@ -config/source/source_common.tcl +config/source/sct_reactor_status.tcl +config/source/source.tcl config/anticollider/anticollider_common.tcl config/plc/plc_common_1.tcl config/counter/counter_common_1.tcl diff --git a/site_ansto/instrument/lyrebird/config/source/source.tcl b/site_ansto/instrument/lyrebird/config/source/source.tcl deleted file mode 100644 index 93a8dbc1..00000000 --- a/site_ansto/instrument/lyrebird/config/source/source.tcl +++ /dev/null @@ -1,6 +0,0 @@ -source $cfPath(source)/source_common.tcl - -proc ::source::isc_initialize {} { - ::source::ic_initialize "thermal" -} - diff --git a/site_ansto/instrument/pas/config/source/source.tcl b/site_ansto/instrument/pas/config/source/source.tcl deleted file mode 100644 index b4fa145f..00000000 --- a/site_ansto/instrument/pas/config/source/source.tcl +++ /dev/null @@ -1,7 +0,0 @@ -source $cfPath(source)/source_common.tcl - -proc ::source::isc_initialize {} { - ::source::ic_initialize "cold" -} - - diff --git a/site_ansto/instrument/pelican/config/INSTCFCOMMON.TXT b/site_ansto/instrument/pelican/config/INSTCFCOMMON.TXT index bbbf2f74..9231db47 100644 --- a/site_ansto/instrument/pelican/config/INSTCFCOMMON.TXT +++ b/site_ansto/instrument/pelican/config/INSTCFCOMMON.TXT @@ -1,4 +1,5 @@ -config/source/source_common.tcl +config/source/sct_reactor_status.tcl +config/source/source.tcl config/anticollider/anticollider_common.tcl config/plc/plc_common_1.tcl config/counter/counter_common_1.tcl diff --git a/site_ansto/instrument/pelican/config/beamline/sct_power.tcl b/site_ansto/instrument/pelican/config/beamline/sct_power.tcl index e65e3dd0..02472022 100644 --- a/site_ansto/instrument/pelican/config/beamline/sct_power.tcl +++ b/site_ansto/instrument/pelican/config/beamline/sct_power.tcl @@ -62,7 +62,10 @@ proc ::scobj::ag1010::getValue {tc_root nextState rdPara} { set CTRL [lindex $rdPara 1] set DATA 0 set CRC 0 - + + if {[hpropexists [sct] geterror]} { + hdelprop [sct] geterror + } if {$LEN < 2} { return -code error "Error in LF AG1010 Setting: wrong data length provided." } elseif {$LEN > 2} { @@ -109,8 +112,9 @@ proc ::scobj::ag1010::setValue {tc_root nextState rdPara wrPara} { return idle } else { # scale W to dW - set FPL [expr int([hval $ns/limits/ForwardPower] * 10)] - set data [format %04x%04x%04x%04x $newPara $FPL 0 0] + set FPL [expr $newPara * 10] + set RPL [expr int([hval $ns/limits/ReversePower] * 10)] + set data [format %04x%04x%04x%04x $FPL $RPL 0 0] } } "RPL" { if {$newPara > $RefPowerLimit || $newPara < 0} { @@ -118,12 +122,17 @@ proc ::scobj::ag1010::setValue {tc_root nextState rdPara wrPara} { return idle } else { # scale W to dW - set RPL [expr int([hval $ns/limits/ReversePower] * 10)] - set data [format %04x%04x%04x%04x $RPL $newPara 0 0] + set FPL [expr int([hval $ns/limits/ForwardPower] * 10)] + set RPL [expr $newPara * 10] + set data [format %04x%04x%04x%04x $FPL $RPL 0 0] } } - "PAGC" { set data [expr [format %04x int($newPara * 10)]] } - "PMGC" { set data [expr [format %04x int($newPara * 10)]] } + "PAGC" { set newPara [expr $newPara * 10] + set data [format %04x $newPara] + } + "PMGC" { set newPara [expr $newPara * 10] + set data [format %04x $newPara] + } "FREQ" { if {$newPara<$FreqDownLimit || $newPara>$FreqUpLimit} { broadcast "Error: Freqence shall be set between $FreqDownLimit Hz and $FreqUpLimit Hz" return idle @@ -377,14 +386,11 @@ proc ::scobj::ag1010::rdValue {} { hset $ns/responseMsg "$data" #broadcast "rdValue : $data" - if {[string first "failed" $data] != -1} { - broadcast "Error in LF AG1010 Response: $data" - return -code error "$data" - } elseif {[string first "read timeout" $data] != -1} { - broadcast "Error in LF AG1010 Response: $data" + if {[string first "ASCERR" $data] != -1} { + sct geterror $replyData return -code error "$data" } elseif {[string length $data] < 1} { - broadcast "Error in LF AG1010 Response: no message returned from device" + #broadcast "Error in LF AG1010 Response: no message returned from device" return -code error "Error in LF AG1010 Response: no message returned from device" } @@ -405,7 +411,7 @@ proc ::scobj::ag1010::rdValue {} { 3 { set AGCPoH [string range $data 6 7] set AGCPoL [string range $data 8 9] # scale dW to W - hset $ns/AGC/PAGC [expr [[format %d [expr 0x$AGCPoH$AGCPoL]]/10.0] + hset $ns/AGC/PAGC [expr [format %d [expr 0x$AGCPoH$AGCPoL]]/10.0] } 4 { set MGCPoH [string range $data 6 7] set MGCPoL [string range $data 8 9] @@ -726,7 +732,7 @@ proc ::scobj::ag1010::mkAG {argList} { P AGC 1 0 1 1 none {} user {2 19} {rdValue} {} {} AGC PAGC 0 0 0 1 float {W} user {} {} {} {} P MGC 1 0 1 1 none {} user {2 20} {rdValue} {} {} - MGC PMGC 0 0 0 1 float {} user {} {} {} {} + MGC PMGC 0 0 0 1 float {%} user {} {} {} {} P FRE 1 0 1 1 none {} user {2 21} {rdValue} {} {} FRE FREQ 0 0 0 1 int {Hz} user {} {} {} {} P SKEY 1 0 1 1 none {} spy {3 23} {rdValue} {} {} @@ -774,7 +780,7 @@ proc ::scobj::ag1010::mkAG {argList} { P SetLimitsFPL 0 1 1 1 float {W} user {10 2} {rdValue} {FPL} {} P SetLimitsRPL 0 1 1 1 float {W} user {10 2} {rdValue} {RPL} {} P SetPAGC 0 1 1 1 float {W} user {4 3} {rdValue} {PAGC} {} - P SetPMGC 0 1 1 1 float {} user {4 4} {rdValue} {PMGC} {} + P SetPMGC 0 1 1 1 float {%} user {4 4} {rdValue} {PMGC} {} P SetFREQ 0 1 1 1 int {Hz} user {6 5} {rdValue} {FREQ} {} P SetSoftOn 0 1 1 1 int {} user {3 7} {rdValue} {SoftOn} {1,0} P SetKey1 0 1 1 1 int {} user {3 7} {rdValue} {Key1} {1,0} @@ -841,22 +847,22 @@ namespace import ::scobj::ag1010::par proc lf_pagc {{para ""} args} { if {$para == ""} { - broadcast "[hget /instrument/ag1010/AGC/PAGC] W" + broadcast "[hget /sample/ag1010/AGC/PAGC] W" } else { set HEAD 0x96 set LEN 4 set CTRL 3 set CRC 0 - set ns /instrument/ag1010 + set ns /sample/ag1010 set newPara [string trim $para " "] # scale W to dW - set newPara [expr int($newPara * 10)] + set newPara [expr $newPara * 10] set data [format %04x $newPara] set cmd [format %02x%02x%02x%s%02x $HEAD $LEN $CTRL $data $CRC] - broadcast "Set Power Level for AGC mode to $newPara W" + broadcast "Set Power Level for AGC mode to $newPara dW" sct_ag1010 send "$cmd" } } @@ -864,18 +870,18 @@ proc lf_pagc {{para ""} args} { proc lf_pmgc {{para ""} args} { if {$para == ""} { - broadcast "[hget /instrument/ag1010/MGC/PMGC]%" + broadcast "[hget /sample/ag1010/MGC/PMGC] %" } else { set HEAD 0x96 set LEN 4 set CTRL 4 set CRC 0 - set ns /instrument/ag1010 + set ns /sample/ag1010 set newPara [string trim $para " "] # scale by 10 - set newPara [expr int($newPara * 10)] + set newPara [expr $newPara * 10] set data [format %04x $newPara] set cmd [format %02x%02x%02x%s%02x $HEAD $LEN $CTRL $data $CRC] @@ -887,26 +893,15 @@ proc lf_pmgc {{para ""} args} { proc lf_freq {{para ""} args} { if {$para == ""} { - broadcast "[hget /instrument/ag1010/FRE/FREQ] Hz" + broadcast "[hget /sample/ag1010/FRE/FREQ] Hz" } else { - set HEAD 0x96 - set LEN 6 - set CTRL 5 - set CRC 0 - - set ns /instrument/ag1010 + set ns /sample/ag1010 set newPara [string trim $para " "] if {$para < 0.02 || $para > 2000000} { broadcast "Error: Freqence shall be set between 0.02 Hz and 2 MHz" } else { - set Freq [expr $newPara / 1000] - set FreqHz [expr $newPara % 1000] - set data [format %04x%04x $Freq $FreqHz] - set cmd [format %02x%02x%02x%s%02x $HEAD $LEN $CTRL $data $CRC] - - broadcast "Set Frequency to $newPara Hz" - sct_ag1010 send "$cmd" + hset $ns/SetFREQ $newPara } } } @@ -939,63 +934,60 @@ proc lf_sweep_run {startF stepF np {mode 2} args} { proc lf_limits {args} { if {$args == ""} { - broadcast "[hget /instrument/ag1010/limits/ForwardPower] W" - broadcast "[hget /instrument/ag1010/limits/ReversePower] W" + broadcast "[hget /sample/ag1010/limits/ForwardPower] W" + broadcast "[hget /sample/ag1010/limits/ReversePower] W" } else { set HEAD 0x96 set LEN 10 set CTRL 2 set CRC 0 - set ns /instrument/ag1010 + set ns /sample/ag1010 foreach {arg val} $args { switch $arg { "FPL" { if {$val > 10040 || $val < 0} { broadcast "Error: The Limit for the Forward Power is 0~10040 W" + set FPL [expr [hval $ns/limits/ForwardPower]*10] } else { - set FPL [hval $ns/limits/ForwardPower] # scale W to dW - set FPL [expr int($FPL * 10)] - set data [format %04x%04x%04x%04x $val $FPL 0 0] - set cmd [format %02x%02x%02x%s%02x $HEAD $LEN $CTRL $data $CRC] - - broadcast "Set Forward Power Limits to $val W" - sct_ag1010 send "$cmd" + set FPL [expr $val * 10] } } "RPL" { if {$val > 1630 || $val < 0} { broadcast "Error: The Limit for the Reflected Power is 0~1630 dW" + set RPL [expr [hval $ns/limits/ReversePower]*10] } else { - set RPL [hval $ns/limits/ReversePower] # scale W to dW - set RPL [expr int($RPL * 10)] - set data [format %04x%04x%04x%04x $RPL $val 0 0] - set cmd [format %02x%02x%02x%s%02x $HEAD $LEN $CTRL $data $CRC] - - broadcast "Set Reverse Power Limits to $val dW" - sct_ag1010 send "$cmd" + set RPL [expr $val * 10] } } - default { error "ERROR: $arg should be 'FPL' or 'RPL'" } + default { error "ERROR: $arg should be 'FPL' or 'RPL'" + return idle + } } } + broadcast "Set Forward Power Limits to $FPL dW" + broadcast "Set Reverse Power Limits to $RPL dW" + set data [format %04x%04x%04x%04x $FPL $RPL 0 0] + set cmd [format %02x%02x%02x%s%02x $HEAD $LEN $CTRL $data $CRC] + sct_ag1010 send "$cmd" } } proc lf_burst {args} { if {$args == ""} { - broadcast "[hget /instrument/ag1010/BurstPar/BurstMode]" - broadcast "[hget /instrument/ag1010/BurstPar/BRepTime] ms" - broadcast "[hget /instrument/ag1010/BurstPar/TimeOfPower] us" + broadcast "[hget /sample/ag1010/BurstPar/BurstMode]" + broadcast "[hget /sample/ag1010/BurstPar/BRepTime] ms" + broadcast "[hget /sample/ag1010/BurstPar/TimeOfPower] us" } else { set HEAD 0x96 set LEN 7 set CTRL 8 set CRC 0 - set ns /instrument/ag1010 + set ns /sample/ag1010 set BurstMode 2 set BRepTime [hval $ns/BurstPar/BRepTime] @@ -1039,17 +1031,17 @@ proc lf_burst {args} { proc lf_sweep {args} { if {$args == ""} { - broadcast "[hget /instrument/ag1010/SweepPar/SweepMode]" - broadcast "[hget /instrument/ag1010/SweepPar/StartFreq] Hz" - broadcast "[hget /instrument/ag1010/SweepPar/StepFreq] Hz" - broadcast "[hget /instrument/ag1010/SweepPar/SCyc]" + broadcast "[hget /sample/ag1010/SweepPar/SweepMode]" + broadcast "[hget /sample/ag1010/SweepPar/StartFreq] Hz" + broadcast "[hget /sample/ag1010/SweepPar/StepFreq] Hz" + broadcast "[hget /sample/ag1010/SweepPar/SCyc]" } else { set HEAD 0x96 set LEN 13 set CTRL 9 set CRC 0 - set ns /instrument/ag1010 + set ns /sample/ag1010 set SweepMode 2 set SStr [expr [hval $ns/SweepPar/StartFreq] / 1000] @@ -1102,9 +1094,9 @@ proc lf_sweep {args} { proc lf_meas {} { - broadcast "[hget /instrument/ag1010/MEAS/ForwardPower] W" - broadcast "[hget /instrument/ag1010/MEAS/ReversePower] W" - broadcast "[hget /instrument/ag1010/MEAS/Temperature] Degree" + broadcast "[hget /sample/ag1010/MEAS/ForwardPower] W" + broadcast "[hget /sample/ag1010/MEAS/ReversePower] W" + broadcast "[hget /sample/ag1010/MEAS/Temperature] Degree" } publish lf_limits user @@ -1126,8 +1118,8 @@ publish lf_sweep user # IP 137.157.202.219 ::scobj::ag1010::mkAG { name "ag1010" - IP 137.157.202.219 - PORT 4001 + IP 137.157.202.214 + PORT 4003 tuning 1 interval 5 } diff --git a/site_ansto/instrument/pelican/config/hmm/hmm_configuration.tcl b/site_ansto/instrument/pelican/config/hmm/hmm_configuration.tcl index 2a89ce05..a85737c6 100644 --- a/site_ansto/instrument/pelican/config/hmm/hmm_configuration.tcl +++ b/site_ansto/instrument/pelican/config/hmm/hmm_configuration.tcl @@ -64,10 +64,10 @@ return { - 23 23 23 20 20 20 20 20 - 20 20 20 20 20 20 20 20 - 20 20 20 20 20 20 20 20 - 20 20 10 10 10 10 10 10 + 30 30 30 30 30 30 30 30 + 30 30 30 30 30 30 30 30 + 30 30 30 30 30 30 30 30 + 30 20 10 10 10 10 10 10 @@ -79,7 +79,7 @@ return { -} + } } proc ::histogram_memory::init_CAT_TABLE {} { @@ -193,8 +193,8 @@ proc ::histogram_memory::isc_initialize {} { # hmm configure FAT_SIMULATED_EVENT_X0 $x_bb0 # hmm configure FAT_SIMULATED_EVENT_X1 $xbbmax ::histogram_memory::init_OAT_TABLE - ::histogram_memory::init_SAT_TABLE - ::histogram_memory::init_CAT_TABLE +# ::histogram_memory::init_SAT_TABLE +# ::histogram_memory::init_CAT_TABLE ::histogram_memory::upload_config Filler_defaults set ::histogram_memory::histmem_axes(HOR) /instrument/detector/x_pixel_angular_offset diff --git a/site_ansto/instrument/pelican/config/hmm/sct_hv.tcl b/site_ansto/instrument/pelican/config/hmm/sct_hv.tcl index 2c94b895..d312bad7 100644 --- a/site_ansto/instrument/pelican/config/hmm/sct_hv.tcl +++ b/site_ansto/instrument/pelican/config/hmm/sct_hv.tcl @@ -179,7 +179,9 @@ proc ::scobj::hv::rdHVStatusFunc {basePath mode} { } elseif {$mode == "config"} { hset $basePath/config/mode "[lindex $replyText 3] [lindex $replyText 4]" - hset $basePath/config/hv [lindex $replyText 5] + if {[lindex $replyText 5] != ""} { + hset $basePath/config/hv [lindex $replyText 5] + } hset $basePath/config/pressure_threshold [lindex $replyText 6] hsetprop $basePath/config/pressure_threshold units [lindex $replyText 7] @@ -329,17 +331,17 @@ proc ::scobj::hv::mkHV {argList} { proc hv_status {} { set cmd "get status\r\n" - sct_hv send $cmd + sct_hv transact $cmd } proc hv_config {} { set cmd "get config\r\n" - sct_hv send $cmd + sct_hv transact $cmd } proc hv_clear_error {} { set cmd "clear error\r\n" - sct_hv send $cmd + sct_hv transact $cmd } proc hv_vol {{vol ""} args} { @@ -347,7 +349,7 @@ proc hv_vol {{vol ""} args} { hget /instrument/hv/config/hv } else { set cmd "set hv=$vol\r\n" - sct_hv send $cmd + sct_hv transact $cmd } } @@ -356,7 +358,7 @@ proc hv_pressure {{pressure ""} args} { hget /instrument/hv/config/pressure_threshold } else { set cmd "set pressure=$pressure\r\n" - sct_hv send $cmd + sct_hv transact $cmd } } @@ -365,7 +367,7 @@ proc hv_mode {{mode ""} args} { hget /instrument/hv/config/mode } else { set cmd "set mode=$mode\r\n" - sct_hv send $cmd + sct_hv transact $cmd } } @@ -373,23 +375,23 @@ proc hv_date {{date ""} args} { if {$date == ""} { } else { set cmd "set date=$date\r\n" - sct_hv send $cmd + sct_hv transact $cmd } } proc hv_powerup {} { set cmd "power up\r\n" - sct_hv send $cmd + sct_hv transact $cmd } proc hv_powerdown {} { set cmd "power down\r\n" - sct_hv send $cmd + sct_hv transact $cmd } proc hv_help {} { set cmd "help\r\n" - sct_hv send $cmd + sct_hv transact $cmd } proc set_data_record {args} { @@ -414,14 +416,17 @@ publish hv_powerdown user publish hv_help user publish set_data_record user + +MakeAsyncProtocol std +MakeAsyncQueue hvport std 10.157.205.10 4001 # Main process call to create the driver -#::scobj::hv::mkHV { -# name "hv" -# IP 137.157.202.215 -# PORT 55011 -# tuning 1 -# interval 5 -#} +::scobj::hv::mkHV { + name "hv" + IP aqadapter + PORT hvport + tuning 1 + interval 5 +} diff --git a/site_ansto/instrument/pelican/config/motors/motor_configuration.tcl b/site_ansto/instrument/pelican/config/motors/motor_configuration.tcl index fcae53c1..f67d0848 100644 --- a/site_ansto/instrument/pelican/config/motors/motor_configuration.tcl +++ b/site_ansto/instrument/pelican/config/motors/motor_configuration.tcl @@ -29,7 +29,8 @@ set sh1_Home 33414 set sv2_Home 33357369 set sh2_Home 33505668 set gom_Home 373521 -set scor_Home 20193638 +#set scor_Home 20193638 +set scor_Home 21831449 # AND abs Encoder Reading with FFF to get the lowest 12 bits only #set mra_Home 4286 @@ -168,7 +169,7 @@ Motor pom $motor_driver_type [params \ axis E\ units degrees\ hardlowerlim -1.5\ - hardupperlim 1.5\ + hardupperlim 2.5\ maxSpeed [expr { 200000.0 / $pomStepRate }]\ maxAccel [expr { 25000.0 / $pomStepRate }]\ maxDecel [expr { 25000.0 / $pomStepRate }]\ @@ -403,7 +404,7 @@ scor part sample scor long_name scor scor softlowerlim 0 scor softupperlim 360 -scor home 0 +scor home 180 ############################ # Motor Controller 3 diff --git a/site_ansto/instrument/pelican/config/source/source.tcl b/site_ansto/instrument/pelican/config/source/source.tcl deleted file mode 100644 index 50967ab8..00000000 --- a/site_ansto/instrument/pelican/config/source/source.tcl +++ /dev/null @@ -1,8 +0,0 @@ -# Author Jing Chen (jgn@ansto.gov.au) - -source $cfPath(source)/source_common.tcl - -proc ::source::isc_initialize {} { - ::source::ic_initialize "thermal" -} - diff --git a/site_ansto/instrument/pelican/pelican_configuration.tcl b/site_ansto/instrument/pelican/pelican_configuration.tcl index 68630464..917e4aff 100644 --- a/site_ansto/instrument/pelican/pelican_configuration.tcl +++ b/site_ansto/instrument/pelican/pelican_configuration.tcl @@ -29,6 +29,7 @@ fileeval $cfPath(plc)/plc.tcl fileeval $cfPath(counter)/counter.tcl fileeval $cfPath(beamline)/sct_power.tcl fileeval $cfPath(environment)/temperature/sct_lakeshore_218.tcl +fileeval $cfPath(environment)/temperature/sct_lakeshore_340.tcl fileeval $cfPath(hmm)/hmm_configuration.tcl fileeval $cfPath(hmm)/sct_hv.tcl fileeval $cfPath(nexus)/nxscripts.tcl diff --git a/site_ansto/instrument/reflectometer/config/INSTCFCOMMON.TXT b/site_ansto/instrument/reflectometer/config/INSTCFCOMMON.TXT index c5a4a06b..6e8f55be 100644 --- a/site_ansto/instrument/reflectometer/config/INSTCFCOMMON.TXT +++ b/site_ansto/instrument/reflectometer/config/INSTCFCOMMON.TXT @@ -1,4 +1,5 @@ -config/source/source_common.tcl +config/source/sct_reactor_status.tcl +config/source/source.tcl config/anticollider/anticollider_common.tcl config/plc/plc_common_1.tcl config/counter/counter_common_1.tcl diff --git a/site_ansto/instrument/reflectometer/config/hmm/detector.tcl b/site_ansto/instrument/reflectometer/config/hmm/detector.tcl index dfaac749..17bcf370 100644 --- a/site_ansto/instrument/reflectometer/config/hmm/detector.tcl +++ b/site_ansto/instrument/reflectometer/config/hmm/detector.tcl @@ -13,11 +13,11 @@ makeasyncqueue acq NHQ200 ca2-platypus 4001 evfactory new dhv1 nhq200 acq 1 dhv1 tolerance 5 dhv1 rate 25 -dhv1 upper 2800 +dhv1 upper 3000 #dhv1 lock evfactory new dhv2 nhq200 acq 2 dhv2 tolerance 5 dhv2 rate 25 -dhv2 upper 1000 +dhv2 upper 1500 #dhv2 lock } diff --git a/site_ansto/instrument/reflectometer/config/hmm/hmm_configuration.tcl b/site_ansto/instrument/reflectometer/config/hmm/hmm_configuration.tcl index ad22fc1c..10943be0 100644 --- a/site_ansto/instrument/reflectometer/config/hmm/hmm_configuration.tcl +++ b/site_ansto/instrument/reflectometer/config/hmm/hmm_configuration.tcl @@ -13,12 +13,12 @@ proc ::histogram_memory::init_OAT_TABLE {} { OAT_TABLE Y -setdata BMAX 110.5 set clock_scale 1000 - set freq 50 + set freq 24 hmm configure fat_clock_scale $clock_scale hmm configure fat_frame_frequency $freq hmm configure fat_frame_source EXTERNAL - OAT_TABLE -set X { -210.5 -209.5 } NXC 421 Y { -110.5 -109.5 } NYC 221 T { 0 20000 } NTC 1 + OAT_TABLE -set X { -210.5 -209.5 } NXC 421 Y { -110.5 -109.5 } NYC 221 T { 0 40 } NTC 1000 } message ] { if {$::errorCode=="NONE"} {return $message} return -code error $message diff --git a/site_ansto/instrument/reflectometer/config/source/source.tcl b/site_ansto/instrument/reflectometer/config/source/source.tcl deleted file mode 100644 index b4fa145f..00000000 --- a/site_ansto/instrument/reflectometer/config/source/source.tcl +++ /dev/null @@ -1,7 +0,0 @@ -source $cfPath(source)/source_common.tcl - -proc ::source::isc_initialize {} { - ::source::ic_initialize "cold" -} - - diff --git a/site_ansto/instrument/rsd/config/INSTCFCOMMON.TXT b/site_ansto/instrument/rsd/config/INSTCFCOMMON.TXT index da35e073..bd21df6c 100644 --- a/site_ansto/instrument/rsd/config/INSTCFCOMMON.TXT +++ b/site_ansto/instrument/rsd/config/INSTCFCOMMON.TXT @@ -1,13 +1,17 @@ -config/source/source_common.tcl +config/source/sct_reactor_status.tcl +config/source/source.tcl config/anticollider/anticollider_common.tcl config/plc/plc_common_1.tcl config/counter/counter_common_1.tcl +config/environment/sct_keithley_2700.tcl config/environment/temperature/sct_lakeshore_336.tcl config/environment/temperature/sct_lakeshore_340.tcl config/environment/temperature/sct_eurotherm_2000.tcl config/environment/sct_protek_common.tcl config/environment/temperature/sct_oxford_itc.tcl +config/environment/temperature/sct_oxford_mercury.tcl config/environment/magneticField/sct_oxford_ips.tcl +config/environment/magneticField/sct_oxford_labview.tcl config/hipadaba/hipadaba_configuration_common.tcl config/hipadaba/common_instrument_dictionary.tcl config/hipadaba/instdict_specification.tcl diff --git a/site_ansto/instrument/rsd/config/motors/euler_configuration.tcl b/site_ansto/instrument/rsd/config/motors/euler_configuration.tcl index 3ac6b99b..d436e9ea 100644 --- a/site_ansto/instrument/rsd/config/motors/euler_configuration.tcl +++ b/site_ansto/instrument/rsd/config/motors/euler_configuration.tcl @@ -7,7 +7,7 @@ # this is the Big Huber Eulerian C shaped cradle EC2 # set eom_Home 23165406 -set ephi_Home 6489396 +set ephi_Home 26573867 set echi_Home 24224404 set eom_stepsPerX [expr -25000.0] @@ -32,7 +32,7 @@ Motor eom $motor_driver_type [params \ absEnc 1\ absEncHome 20060684\ cntsPerX [expr -8192.0*(360.0/360.0)]] -setHomeandRange -motor som -home 0 -lowrange 178 -uprange 178 +setHomeandRange -motor eom -home 0 -lowrange 178 -uprange 178 eom Backlash_offset -0.5 eom speed 2 eom accel 0.1 @@ -83,7 +83,6 @@ Motor ephi $motor_driver_type [params \ setHomeandRange -motor ephi -home 0 -lowrange 400 -uprange 400 ephi softlowerlim -400 ephi softupperlim 400 -ephi home 182.5 ephi speed 3 ephi movecount $move_count ephi precision 0.01 diff --git a/site_ansto/instrument/rsd/config/motors/motor_configuration.tcl b/site_ansto/instrument/rsd/config/motors/motor_configuration.tcl index b54ae382..4105edf8 100644 --- a/site_ansto/instrument/rsd/config/motors/motor_configuration.tcl +++ b/site_ansto/instrument/rsd/config/motors/motor_configuration.tcl @@ -10,7 +10,9 @@ # 0: Secondary slit configuration # 1: Big Huber cradle # 2: Tiny black cradle -set axis_config 0 +# 3: Second sample stage +# 4: Loads config from /usr/local/sics/spare_motor_configuration.tcl +set axis_config 2 set animal kowari set sim_mode [SplitReply [motor_simulation]] @@ -38,8 +40,8 @@ set mtth_Home 11701800 # set sz_home 2147456531 # -set sx_Home 9052833 -set sy_Home 18812526 +set sx_Home 9053571 +set sy_Home 18812120 # # swapped sx with sy after rotation of vertical stage set sx_pitch 4.9995324 @@ -54,7 +56,8 @@ set sy_pitch 5.0 #set som_Home 26472736 #set som_Home 25275865 #set som_Home 25234969 -set som_Home 25177194 +#set som_Home 25177194 +set som_Home 25366950 #set stth_Home 28686300 #set stth_Home 29446192 @@ -65,7 +68,8 @@ set stth_pitch 0.99946 # #set psho_home 542093 -set psho_home 7576691 +#set psho_home 7576691 +set psho_home 7739630 #set psp_home 2040518 #set psp_home 3479157 #set psp_home 3783500 @@ -98,6 +102,8 @@ switch $axis_config { 0 { fileeval $cfPath(motors)/secondary_slit_configuration.tcl } 1 { fileeval $cfPath(motors)/euler_configuration.tcl } 2 { fileeval $cfPath(motors)/tiny_black_euler_configuration.tcl } + 3 { fileeval $cfPath(motors)/second_sample_stage_configuration.tcl } + 4 { fileeval $cfPath(motors)/spare_motor_configuration.tcl } } ############################ @@ -455,7 +461,7 @@ Motor stth $motor_driver_type [params \ asyncqueue mc2\ axis F\ units degrees\ - hardlowerlim 30\ + hardlowerlim 25\ hardupperlim 119.6\ maxSpeed 0.5\ maxAccel 0.1\ diff --git a/site_ansto/instrument/rsd/config/motors/secondary_slit_configuration.tcl b/site_ansto/instrument/rsd/config/motors/secondary_slit_configuration.tcl index cf04ce80..955e283b 100644 --- a/site_ansto/instrument/rsd/config/motors/secondary_slit_configuration.tcl +++ b/site_ansto/instrument/rsd/config/motors/secondary_slit_configuration.tcl @@ -1,4 +1,4 @@ -set ssw_home 8216527 +set ssw_home 8202207 # Secondary Slit, width Motor ssw $motor_driver_type [params \ @@ -19,3 +19,27 @@ ssw Backlash_offset 0.3 ssw part slits ssw long_name secondary_ssw setHomeandRange -motor ssw -home 0 -lowrange 0 -uprange 30 + +Motor eom2 $motor_driver_type [params \ + asyncqueue mc4\ + axis G\ + units degrees\ + hardlowerlim -360\ + hardupperlim 360\ + maxSpeed 10\ + maxAccel 0.5\ + maxDecel 0.5\ + stepsPerX 25000\ + absEnc 1\ + absEncHome 19785674\ + cntsPerX 8192] +setHomeandRange -motor eom2 -home 0 -lowrange -360 -uprange 360 +eom2 softlowerlim -360 +eom2 softupperlim 360 +eom2 home 0 +eom2 speed 5 +#eom2 movecount $move_count +eom2 precision 0.01 +eom2 part sample +eom2 long_name eom2 + diff --git a/site_ansto/instrument/rsd/config/motors/tiny_black_euler_configuration.tcl b/site_ansto/instrument/rsd/config/motors/tiny_black_euler_configuration.tcl index 9e388305..ee097fd1 100644 --- a/site_ansto/instrument/rsd/config/motors/tiny_black_euler_configuration.tcl +++ b/site_ansto/instrument/rsd/config/motors/tiny_black_euler_configuration.tcl @@ -6,18 +6,29 @@ # # this is our own tiny black cradle # -set eom_Home 23165406 -set ephi_Home 6405803 -set echi_Home 24224350 +set eom_Home 16062300 +set ephi_Home 20363820 +set echi_Home 26192788 + set eom_stepsPerX [expr -25000.0] set eom_cntsPerX [expr 8192.0] -set ephi_stepsPerX [expr 12500.0] -set ephi_cntsPerX [expr 4096.0] +set ephi_stepsPerX [expr -25000.0] +set ephi_cntsPerX [expr 8192.0] + +set echi_stepsPerX [expr -25000.0] +set echi_cntsPerX [expr 8192.0] + + +#set eom_stepsPerX [expr -25000.0] +#set eom_cntsPerX [expr 8192.0] + +#set ephi_stepsPerX [expr 12500.0] +#set ephi_cntsPerX [expr 4096.0] -set echi_stepsPerX [expr 25000.0] -set echi_cntsPerX [expr -8192.0] +#set echi_stepsPerX [expr 25000.0] +#set echi_cntsPerX [expr -8192.0] Motor eom $motor_driver_type [params \ @@ -31,9 +42,9 @@ Motor eom $motor_driver_type [params \ maxDecel 5\ stepsPerX [expr -25000.0*(360.0/360.0)]\ absEnc 1\ - absEncHome 20060684\ + absEncHome $eom_Home\ cntsPerX [expr -8192.0*(360.0/360.0)]] -setHomeandRange -motor som -home 0 -lowrange 178 -uprange 178 +setHomeandRange -motor eom -home 0 -lowrange 178 -uprange 178 eom Backlash_offset -0.5 eom speed 2 eom accel 0.1 @@ -59,7 +70,7 @@ Motor echi $motor_driver_type [params \ cntsPerX $echi_cntsPerX ] setHomeandRange -motor echi -home 0 -lowrange -390 -uprange 390 echi softlowerlim -10 -echi softupperlim 90 +echi softupperlim 100 echi home 0 echi speed 3 echi movecount $move_count @@ -84,7 +95,7 @@ Motor ephi $motor_driver_type [params \ setHomeandRange -motor ephi -home 0 -lowrange 400 -uprange 400 ephi softlowerlim -400 ephi softupperlim 400 -ephi home 182.5 +ephi home 0 ephi speed 3 ephi movecount $move_count ephi precision 0.01 diff --git a/site_ansto/instrument/rsd/config/source/source.tcl b/site_ansto/instrument/rsd/config/source/source.tcl deleted file mode 100644 index 93a8dbc1..00000000 --- a/site_ansto/instrument/rsd/config/source/source.tcl +++ /dev/null @@ -1,6 +0,0 @@ -source $cfPath(source)/source_common.tcl - -proc ::source::isc_initialize {} { - ::source::ic_initialize "thermal" -} - diff --git a/site_ansto/instrument/rsd/kowari_configuration.tcl b/site_ansto/instrument/rsd/kowari_configuration.tcl index 21a309d9..e3c9ceca 100644 --- a/site_ansto/instrument/rsd/kowari_configuration.tcl +++ b/site_ansto/instrument/rsd/kowari_configuration.tcl @@ -23,12 +23,15 @@ source $cfPath(hipadaba)/hipadaba_configuration.tcl fileeval $cfPath(motors)/positmotor_configuration.tcl fileeval $cfPath(plc)/plc.tcl fileeval $cfPath(counter)/counter.tcl +fileeval $cfPath(environment)/sct_keithley_2700.tcl +fileeval $cfPath(environment)/temperature/sct_oxford_mercury.tcl fileeval $cfPath(environment)/temperature/sct_lakeshore_336.tcl fileeval $cfPath(environment)/temperature/sct_lakeshore_340.tcl fileeval $cfPath(environment)/temperature/sct_eurotherm_2000.tcl fileeval $cfPath(environment)/sct_protek_common.tcl fileeval $cfPath(environment)/temperature/sct_oxford_itc.tcl fileeval $cfPath(environment)/magneticField/sct_oxford_ips.tcl +fileeval $cfPath(environment)/magneticField/sct_oxford_labview.tcl fileeval $cfPath(hmm)/hmm_configuration.tcl fileeval $cfPath(nexus)/nxscripts.tcl fileeval $cfPath(scan)/scan.tcl diff --git a/site_ansto/instrument/sans/config/INSTCFCOMMON.TXT b/site_ansto/instrument/sans/config/INSTCFCOMMON.TXT index e8a87ed3..0f1607f8 100644 --- a/site_ansto/instrument/sans/config/INSTCFCOMMON.TXT +++ b/site_ansto/instrument/sans/config/INSTCFCOMMON.TXT @@ -1,4 +1,5 @@ -config/source/source_common.tcl +config/source/sct_reactor_status.tcl +config/source/source.tcl config/anticollider/anticollider_common.tcl config/plc/plc_common_1.tcl config/counter/counter_common_1.tcl diff --git a/site_ansto/instrument/sans/config/motors/motor_configuration.tcl b/site_ansto/instrument/sans/config/motors/motor_configuration.tcl index 7eebc213..7a472cdc 100644 --- a/site_ansto/instrument/sans/config/motors/motor_configuration.tcl +++ b/site_ansto/instrument/sans/config/motors/motor_configuration.tcl @@ -240,6 +240,7 @@ samx long_name sample_x samx softlowerlim -500 samx softupperlim 500 samx home 0 +samx precision 0.01 # Sample translation along beam [0,1000] mm Motor samy $motor_driver_type [params \ diff --git a/site_ansto/instrument/sans/config/source/source.tcl b/site_ansto/instrument/sans/config/source/source.tcl deleted file mode 100644 index 730c4f55..00000000 --- a/site_ansto/instrument/sans/config/source/source.tcl +++ /dev/null @@ -1,6 +0,0 @@ -source $cfPath(source)/source_common.tcl - -proc ::source::isc_initialize {} { - ::source::ic_initialize "cold" -} - diff --git a/site_ansto/instrument/sans/quokka_configuration.tcl b/site_ansto/instrument/sans/quokka_configuration.tcl index fb468a57..eb087477 100644 --- a/site_ansto/instrument/sans/quokka_configuration.tcl +++ b/site_ansto/instrument/sans/quokka_configuration.tcl @@ -37,6 +37,7 @@ fileeval $cfPath(anticollider)/anticollider.tcl fileeval $cfPath(environment)/temperature/sct_julabo_lh45.tcl fileeval $cfPath(environment)/temperature/sct_qlink.tcl fileeval $cfPath(environment)/temperature/sct_watlow_st4.tcl +fileeval $cfPath(environment)/temperature/sct_watlow_rm.tcl fileeval $cfPath(environment)/temperature/sct_rvasm2.tcl #fileeval $cfPath(environment)/magneticField/sct_oxford_ips.tcl fileeval $cfPath(environment)/temperature/sct_oxford_itc.tcl diff --git a/site_ansto/instrument/tas/config/INSTCFCOMMON.TXT b/site_ansto/instrument/tas/config/INSTCFCOMMON.TXT index bf950b99..e66adad3 100644 --- a/site_ansto/instrument/tas/config/INSTCFCOMMON.TXT +++ b/site_ansto/instrument/tas/config/INSTCFCOMMON.TXT @@ -1,5 +1,6 @@ config/load_setup.tcl -config/source/source_common.tcl +config/source/sct_reactor_status.tcl +config/source/source.tcl config/anticollider/anticollider_common.tcl config/plc/plc_common_1.tcl config/counter/counter_common_1.tcl diff --git a/site_ansto/instrument/tas/config/source/source.tcl b/site_ansto/instrument/tas/config/source/source.tcl deleted file mode 100644 index 50967ab8..00000000 --- a/site_ansto/instrument/tas/config/source/source.tcl +++ /dev/null @@ -1,8 +0,0 @@ -# Author Jing Chen (jgn@ansto.gov.au) - -source $cfPath(source)/source_common.tcl - -proc ::source::isc_initialize {} { - ::source::ic_initialize "thermal" -} - diff --git a/site_ansto/instrument/tas/util/sics_config.ini b/site_ansto/instrument/tas/util/sics_config.ini index 084591e9..13022ad0 100644 --- a/site_ansto/instrument/tas/util/sics_config.ini +++ b/site_ansto/instrument/tas/util/sics_config.ini @@ -4,6 +4,8 @@ enabled = False group = environment:magnet ip = 10.157.205.3 name = magnetic +type = B +id = 1 port = 55001 [12tmagnet_setup] @@ -11,25 +13,42 @@ cascade = 12tmagnet,s1_sample_insert,mercury_scipi enabled = False group = 0setup +[ls336_1] +desc = "tc2: Lakeshore 336 temperature controller" +enabled = False +group = environment:temperature +ip = 10.157.xxx.xxx +name = tc2 +type = T +id = 2 +port = 7777 +terminator = \r\n +tol1 = 1.0 +tol2 = 1.0 + [ls340_1] desc = "tc1: Lakeshore 340 temperature controller" enabled = False group = environment:temperature ip = 137.157.203.137 name = tc1 +type = T +id = 1 port = 4001 -terminator = "\r\n" +terminator = \r\n tol1 = 1.0 tol2 = 1.0 -[ls370_2] -desc = "tc2: Lakeshore 370 temperature controller" +[ls370] +desc = "tc3: Lakeshore 370 temperature controller" enabled = False group = environment:temperature ip = 137.157.203.137 -name = tc2 +name = tc3 +type = T +id = 3 port = 4003 -terminator = "\r\n" +terminator = \r\n tol = 2.0 [mercury_itc500] @@ -39,6 +58,8 @@ enabled = False group = environment:temperature ip = 10.157.205.5 name = tc9 +type = T +id = 9 offifon = mercury_scipi port = 7020 tol = 2.0 @@ -49,9 +70,12 @@ enabled = False group = environment:temperature ip = 10.157.205.5 name = tc9 +type = T +id = 9 offifon = mercury_itc500 port = 7020 tol = 2.0 +terminator = \r [s1_sample_insert] desc = "s1 will be defined as the sample insert rotation. Sample stage will be renamed to s1ss and sgu and sgl will be simulated" @@ -62,5 +86,7 @@ group = motors desc = "tc1: Blue furnace temperature controller" enabled = False group = environment:temperature -ip = 137.157.203.141 +ip = 10.157.205.19 name = tc1 +type = T +id = 1 diff --git a/site_ansto/instrument/util/config_edit.py b/site_ansto/instrument/util/config_edit.py index e622735f..a7ecae23 100755 --- a/site_ansto/instrument/util/config_edit.py +++ b/site_ansto/instrument/util/config_edit.py @@ -11,6 +11,7 @@ config = None verbose = False depth_list = [] line_list = [] +Radio_Groups = {} def read_config_file(config_filename): import ConfigParser @@ -134,10 +135,21 @@ def main(config_filename): if 'desc' in config.options(txt): cb_text += config.get(txt, 'desc').strip("\"") cb_text += ")" - cb = urwid.AttrWrap(urwid.CheckBox(cb_text, - state=state, - on_state_change=checkbox_change, - user_data=txt), 'buttn', 'buttnf') + if 'radio' in config.options(txt): + radio = config.get(txt, 'radio').strip("\"") + if radio not in Radio_Groups: + Radio_Groups[radio] = [] + cb = urwid.AttrWrap(urwid.RadioButton( + Radio_Groups[radio], + cb_text, + state=state, + on_state_change=checkbox_change, + user_data=txt), 'buttn', 'buttnf') + else: + cb = urwid.AttrWrap(urwid.CheckBox(cb_text, + state=state, + on_state_change=checkbox_change, + user_data=txt), 'buttn', 'buttnf') cb_list.append(cb) lb_list.append(cb) diff --git a/site_ansto/instrument/util/extra_utility.tcl b/site_ansto/instrument/util/extra_utility.tcl index 1e5d3a0e..dd1aec36 100644 --- a/site_ansto/instrument/util/extra_utility.tcl +++ b/site_ansto/instrument/util/extra_utility.tcl @@ -1,3 +1,23 @@ +# utility functions like basename/dirname in bash (dcl) + proc basename {node} { + set point [string last "/" $node] + if { $point < 0 } { + return $node + } else { + incr point + return "[string range $node $point end]" + } + } + proc pathname {node} { + set point [string last "/" $node] + if { $point < 0 } { + return "" + } else { + incr point -1 + return "[string range $node 0 $point]" + } + } + # Many of these functions are also useful in test and debug code # running on an external Tcl interpreter. set errorInfo "" diff --git a/site_ansto/instrument/util/gen_sct.py b/site_ansto/instrument/util/gen_sct.py new file mode 100755 index 00000000..387b5d13 --- /dev/null +++ b/site_ansto/instrument/util/gen_sct.py @@ -0,0 +1,1477 @@ +#!/usr/bin/env python +# Script Context Driver Generator +# Author: Douglas Clowes (douglas.clowes@ansto.gov.au) Jan/Feb 2014 +# vim: ft=python ts=8 sts=2 sw=2 expandtab autoindent smartindent +# +# This program generates Script Context Driver TCL files. +# +# It takes one or more "Script Context Driver Description" files. +# Each file may contain one or more driver descriptions. Each driver +# description will result in one TCL file. +# +# The name of the file produced, the TCL namespace used and names within +# the file are based on the driver name givin in the driver description. +# +# TODO: +# implement attributes and units on vars +# - type part ??? +# - nxalias xxxxx +# - sdsinfo +# check simulation works +# handle environmental monitoring (emon) +# - figure out how to do it +# - make nodes monitorable +# - make it conditional +# handle the driving settling time in checkstatus +# Questions: +# what it the 'plain spy none' on hfactory +# what is 'mugger' vs 'manager' - seems like alias? +# should some hset commands be hupdate commands? +# + +import os +import ply.lex as lex +import ply.yacc as yacc + +global Verbose +global DriverDump +global CodeDump +global FunctionTypes +global DriveableFunctionTypes +global NumberOfLinesIn +global NumberOfLinesOut + +FunctionTypes = [ + 'read_function', + 'write_function', + 'fetch_function', + 'check_function', + 'pid_function', + 'checkrange_function', + ] + +DriveableFunctionTypes = [ + 'halt_function', + 'checklimits_function', + 'checkstatus_function', + ] + +Verbose = False +DriverDump = False +CodeDump = False + +# +# Tokenizer: This recognizes the tokens which can be keywords, identifiers, +# numbers or strings plus the punctuation. +# + +# +# Reserved words (keywords) in the form reserved['KEYWORD'] = 'TOKEN' +# + +reserved = { +# Driver keywords + 'DRIVER' : 'DRIVER', + 'VENDOR' : 'VENDOR', + 'DEVICE' : 'DEVICE', + 'PROTOCOL' : 'PROTOCOL', + 'DRIVER_PROPERTY' : 'DRIVER_PROPERTY', + 'CLASS' : 'CLASS', + 'SIMULATION_GROUP' : 'SIMULATION_GROUP', + 'CODE' : 'CODE', + 'ADD_ARGS' : 'ADD_ARGS', + 'MAKE_ARGS' : 'MAKE_ARGS', + 'PROTOCOL_ARGS' : 'PROTOCOL_ARGS', +# Group keywords + 'GROUP' : 'GROUP', + 'GROUP_PROPERTY' : 'GROUP_PROPERTY', +# Variable keywords + 'VAR' : 'VAR', + 'PROPERTY' : 'PROPERTY', + 'CONTROL' : 'CONTROL', + 'DATA' : 'DATA', + 'NXSAVE' : 'NXSAVE', + 'MUTABLE' : 'MUTABLE', + 'READABLE' : 'READABLE', + 'WRITEABLE' : 'WRITEABLE', + 'DRIVEABLE' : 'DRIVEABLE', + 'TRUE' : 'TRUE', + 'FALSE' : 'FALSE', +# Data Types + 'TYPE' : 'TYPE', + 'FLOAT' : 'FLOAT', + 'INT' : 'INT', + 'TEXT' : 'TEXT', + 'NONE' : 'NONE', +# Privilege levels + 'PRIV' : 'PRIV', + 'SPY' : 'SPY', + 'USER' : 'USER', + 'MANAGER' : 'MANAGER', + 'READONLY' : 'READONLY', + 'INTERNAL' : 'INTERNAL', +# Functions and Commands + 'READ_COMMAND' : 'READ_COMMAND', + 'READ_FUNCTION' : 'READ_FUNCTION', + 'FETCH_FUNCTION' : 'FETCH_FUNCTION', + 'WRITE_COMMAND' : 'WRITE_COMMAND', + 'WRITE_FUNCTION' : 'WRITE_FUNCTION', + 'CHECK_FUNCTION' : 'CHECK_FUNCTION', + 'PID_FUNCTION' : 'PID_FUNCTION', + 'CHECKRANGE_FUNCTION' : 'CHECKRANGE_FUNCTION', + 'CHECKLIMITS_FUNCTION' : 'CHECKLIMITS_FUNCTION', + 'CHECKSTATUS_FUNCTION' : 'CHECKSTATUS_FUNCTION', + 'HALT_FUNCTION' : 'HALT_FUNCTION', +# Value setting + 'VALUE' : 'VALUE', + 'ALLOWED' : 'ALLOWED', + 'LOWERLIMIT' : 'LOWERLIMIT', + 'UPPERLIMIT' : 'UPPERLIMIT', + 'TOLERANCE' : 'TOLERANCE', + 'UNITS' : 'UNITS', + } + +# +# Tokens list with keyword tokens added at the end +# + +tokens = [ + 'LBRACE', + 'RBRACE', + 'SLASH', + 'INTEGER', + 'FLOATER', + 'CODE_STRING', + 'TEXT_STRING1', + 'TEXT_STRING2', + 'EQUALS', + 'ID', + ] + list(reserved.values()) + +# +# Token rules +# + +t_EQUALS = r'=' +t_LBRACE = r'{' +t_RBRACE = r'}' +t_SLASH = r'/' + +def t_TEXT_STRING1(t): + r'\'[^\']+\'' + t.value = t.value[1:-1] + return t + +def t_TEXT_STRING2(t): + r"\"[^\"]+\"" + t.value = t.value[1:-1] + return t + +def t_CODE_STRING(t): + r'\@.*' + t.value = t.value[1:] + return t + +def t_COMMENT(t): + r'\#.*' + pass + # No Return Value. Token discarded + +def t_FLOATER(t): + r'\d+\.\d*([eE]\d+)?' + try: + t.value = float(t.value) + except ValueError: + print "Floating value invalid:", t.value + t.value = 0.0 + return t + +def t_INTEGER(t): + r'\d+' + try: + t.value = int(t.value) + except ValueError: + print "Integer value too large:", t.value + t.value = 0 + return t + +def t_ID(t): + r'[a-zA-Z_][a-zA-Z_0-9]*' + t.type = reserved.get(t.value.upper(), 'ID') # Check for reserved words + # Force reserved words to lower case for map lookup and comparisson + if t.value.upper() in reserved: + t.type = reserved[t.value.upper()] + t.value = t.value.lower() + return t + +# Ignored characters +t_ignore = " \t;" + +def t_newline(t): + r'\n+' + t.lexer.lineno += t.value.count("\n") + +def t_error(t): + print("Illegal character '%s'" % t.value[0]) + t.lexer.skip(1) + +# +# Parser +# + +# +# Parsing rules +# + +# +# We don't yet have a need for precedence so leave it empty here +# +precedence = ( + #('left','PLUS','MINUS'), + #('left','TIMES','DIVIDE'), + #('right','UMINUS'), + ) + +# +# The head token - it all reduces to this +# +def p_driver(p): + 'driver : DRIVER id_or_str EQUALS driver_block' + p[0] = [{ 'Driver' : {p[2] : p[4]}}] + if Verbose: + print "Driver:", p[0] + global PathName + global TheDrivers + TheDrivers[p[2]] = p[4] + [{'PathName':PathName}] + +def p_driver_block(p): + 'driver_block : LBRACE driver_statement_list RBRACE' + p[0] = p[2] + +def p_driver_statement_list(p): + '''driver_statement_list : driver_statement + | driver_statement_list driver_statement + ''' + if len(p) == 2: + p[0] = [p[1]] + else: + p[0] = p[1] + [p[2]] + +def p_driver_statement(p): + '''driver_statement : driver_assignment + | group + | code + | driver_property + ''' + p[0] = p[1] + +def p_driver_assignment(p): + ''' + driver_assignment : VENDOR EQUALS id_or_str + | DEVICE EQUALS id_or_str + | PROTOCOL EQUALS id_or_str + | CLASS EQUALS id_or_str + | SIMULATION_GROUP EQUALS id_or_str + | ADD_ARGS EQUALS text_string + | MAKE_ARGS EQUALS text_string + | PROTOCOL_ARGS EQUALS text_string + ''' + p[0] = { p[1] : p[3] } + +# +# The GROUP block +# +def p_group(p): + ''' + group : GROUP group_id EQUALS LBRACE group_statement_list RBRACE + ''' + p[0] = { 'Group' : [{'name': p[2]}] + p[5] } + +def p_group_id(p): + ''' + group_id : id_or_str + | empty + ''' + p[0] = p[1] + +def p_group_statement_list(p): + ''' + group_statement_list : group_statement + | group_statement_list group_statement + ''' + if len(p) == 2: + p[0] = [p[1]] + else: + p[0] = p[1] + [p[2]] + +def p_group_statement(p): + '''group_statement : group_assignment + | variable + | group + ''' + p[0] = p[1] + +def p_group_assignment(p): + '''group_assignment : group_property + | var_typ_ass + | property + ''' + p[0] = p[1] + +# +# The VAR block +# +def p_variable(p): + ''' + variable : VAR id_or_str EQUALS LBRACE variable_statement_list RBRACE + | VAR id_or_str + ''' + if len(p) > 3: + p[0] = { 'Variable' : [{'name' : p[2]}] + p[5] } + else: + p[0] = { 'Variable' : [{'name' : p[2]}] } + +def p_variable_statement_list(p): + '''variable_statement_list : variable_statement + | variable_statement_list variable_statement + ''' + if len(p) == 2: + p[0] = [p[1]] + else: + p[0] = p[1] + [p[2]] + +def p_variable_statement(p): + '''variable_statement : var_typ_ass + | var_val_ass + | property + ''' + p[0] = p[1] + +def p_var_typ_ass(p): + ''' + var_typ_ass : READABLE EQUALS INTEGER + | WRITEABLE EQUALS INTEGER + | READ_COMMAND EQUALS text_string + | READ_FUNCTION EQUALS id_or_str + | FETCH_FUNCTION EQUALS id_or_str + | WRITE_COMMAND EQUALS text_string + | WRITE_FUNCTION EQUALS id_or_str + | CHECK_FUNCTION EQUALS id_or_str + | PID_FUNCTION EQUALS id_or_str + | CHECKRANGE_FUNCTION EQUALS id_or_str + | CHECKLIMITS_FUNCTION EQUALS id_or_str + | CHECKSTATUS_FUNCTION EQUALS id_or_str + | HALT_FUNCTION EQUALS id_or_str + | TYPE EQUALS type_code + | PRIV EQUALS priv_code + | CONTROL EQUALS true_false + | DATA EQUALS true_false + | NXSAVE EQUALS true_false + | MUTABLE EQUALS true_false + ''' + p[0] = { p[1] : p[3] } + +def p_var_path(p): + ''' + var_path : id_or_str + | var_path SLASH id_or_str + ''' + if len(p) == 2: + p[0] = p[1] + else: + p[0] = p[1] + '/' + p[3] + +def p_var_val_ass(p): + ''' + var_val_ass : VALUE EQUALS FLOATER + | VALUE EQUALS text_string + | VALUE EQUALS INTEGER + | ALLOWED EQUALS text_string + | UNITS EQUALS text_string + | LOWERLIMIT EQUALS value + | UPPERLIMIT EQUALS value + | TOLERANCE EQUALS value + | DRIVEABLE EQUALS var_path + ''' + p[0] = { p[1] : p[3] } + +def p_driver_property(p): + ''' + driver_property : DRIVER_PROPERTY id_or_str EQUALS value + ''' + p[0] = { 'DriverProperty' : ( p[2], p[4] ) } + +def p_group_property(p): + ''' + group_property : GROUP_PROPERTY id_or_str EQUALS value + ''' + p[0] = { 'GroupProperty' : ( p[2], p[4] ) } + +def p_property(p): + ''' + property : PROPERTY id_or_str EQUALS value + ''' + p[0] = { 'Property' : ( p[2], p[4] ) } + +def p_value(p): + ''' + value : number + | id_or_str + | true_false + ''' + p[0] = p[1] + +def p_number(p): + ''' + number : INTEGER + | FLOATER + ''' + p[0] = p[1] + +def p_type_code(p): + ''' + type_code : FLOAT + | INT + | TEXT + | NONE + ''' + p[0] = p[1] + +def p_priv_code(p): + ''' + priv_code : SPY + | USER + | MANAGER + | READONLY + | INTERNAL + ''' + p[0] = p[1] + +def p_true_false(p): + ''' + true_false : TRUE + | FALSE + ''' + p[0] = p[1] + +# +# The CODE block +# +def p_code(p): + ''' + code : CODE code_type id_or_str EQUALS LBRACE code_block RBRACE + ''' + p[0] = { 'Code' : { 'name' : p[3], 'type' : p[2], 'text' : p[6] }} + +def p_code_type(p): + ''' + code_type : READ_FUNCTION + | FETCH_FUNCTION + | WRITE_FUNCTION + | CHECK_FUNCTION + | PID_FUNCTION + | CHECKRANGE_FUNCTION + | CHECKLIMITS_FUNCTION + | CHECKSTATUS_FUNCTION + | HALT_FUNCTION + | empty + ''' + p[0] = p[1] + +def p_code_block(p): + '''code_block : empty + | code_block CODE_STRING + ''' + if len(p) == 2: + p[0] = [] + else: + p[0] = p[1] + [p[2]] + +def p_id_or_str(p): + ''' + id_or_str : ID + | text_string + ''' + p[0] = p[1] + +def p_text_string(p): + ''' + text_string : TEXT_STRING1 + | TEXT_STRING2 + ''' + p[0] = p[1] + +def p_empty(p): + ''' + empty : + ''' + pass + +def p_error(t): + print("Syntax error at '%s'" % t.value), t + +# +# This section handles building a driver tree from the Abstract Syntax Tree +# generated by the parser. The driver tree has all of the defaults and +# cascading context explicitly stated to make the code generation simpler. +# +def init_context(): + global ContextStack, ContextIndex + ContextStack = [{}] + ContextIndex = 0 + ContextStack[ContextIndex]['type'] = 'none' + ContextStack[ContextIndex]['priv'] = 'user' + ContextStack[ContextIndex]['readable'] = 0 + ContextStack[ContextIndex]['writeable'] = 0 + ContextStack[ContextIndex]['driveable'] = None + ContextStack[ContextIndex]['control'] = 'true' + ContextStack[ContextIndex]['data'] = 'true' + ContextStack[ContextIndex]['mutable'] = 'false' + ContextStack[ContextIndex]['nxsave'] = 'true' + ContextStack[ContextIndex]['read_function'] = 'rdValue' + ContextStack[ContextIndex]['write_function'] = 'setValue' + ContextStack[ContextIndex]['fetch_function'] = 'getValue' + ContextStack[ContextIndex]['check_function'] = 'noResponse' + ContextStack[ContextIndex]['checkrange_function'] = 'checkrange' + ContextStack[ContextIndex]['path'] = '' + +def push_context(): + global ContextStack, ContextIndex + ContextIndex = ContextIndex + 1 + if len(ContextStack) <= ContextIndex: + ContextStack.append({}) + ContextStack[ContextIndex] = {} + for k in ContextStack[ContextIndex - 1].keys(): + ContextStack[ContextIndex][k] = ContextStack[ContextIndex - 1][k] + +def pop_context(): + global ContextStack, ContextIndex + ContextIndex = ContextIndex - 1 + +def build_code(MyDriver, p): + if Verbose: + print 'Code:', p + print "Function:", p['name'] + MyCode = {} + MyCode['name'] = p['name'] + MyCode['reference_count'] = 0 + if 'type' in p: + MyCode['type'] = p['type'] + MyCode['text'] = p['text'] + if Verbose: + for line in p['text']: + print " Line:", line + return MyCode + +def build_variable(MyDriver, p): + global FunctionTypes + global DriveableFunctionTypes + if Verbose: + print 'Variable:', p + MyVar = {} + MyVar['Property'] = {} + # Copy items for this variable + for item in p: + if Verbose: + print "Variable Item:", item + for key in item.keys(): + if key == 'Property': + MyVar['Property'][item[key][0]] = item[key][1] + else: + MyVar[key] = item[key] + # copy the defaults for missing items + for key in ContextStack[ContextIndex]: + if key == 'Property': + for key2 in ContextStack[ContextIndex][key]: + if key2 not in MyVar['Property']: + MyVar['Property'][key2] = ContextStack[ContextIndex][key][key2] + elif not key in MyVar: + MyVar[key] = ContextStack[ContextIndex][key] + if 'sdsinfo' not in MyVar['Property']: + MyVar['Property']['sdsinfo'] = '::nexus::scobj::sdsinfo' + # set the type if not explicitly set + if 'type' not in MyVar['Property']: + if 'driveable' in MyVar and MyVar['driveable']: + MyVar['Property']['type'] = 'drivable' + else: + MyVar['Property']['type'] = 'part' + # if this variable is driveable + if 'driveable' in MyVar and MyVar['driveable']: + # insert defaults for missing driveable functions + if 'checklimits_function' not in MyVar: + MyVar['checklimits_function'] = 'checklimits' + if 'checkstatus_function' not in MyVar: + MyVar['checkstatus_function'] = 'checkstatus' + if 'halt_function' not in MyVar: + MyVar['halt_function'] = 'halt' + + for func in FunctionTypes + DriveableFunctionTypes: + if func in MyVar and MyVar[func] != 'none': + if Verbose: + print 'Var:', MyVar['name'], 'Func:', func, '=', MyVar[func] + if MyVar[func] not in MyDriver['Funcs']: + MyDriver['Funcs'][MyVar[func]] = { 'type' : func, 'text' : [], 'reference_count' : 0 } + if Verbose: + print MyVar['name'], 'Add func ' + MyVar[func], MyDriver['Funcs'][MyVar[func]] + elif not MyDriver['Funcs'][MyVar[func]]['type'] == func: + # allow override of type none else error message + if not MyDriver['Funcs'][MyVar[func]]['type']: + if Verbose: + print MyVar['name'], 'Mod func type:', MyDriver['Funcs'][MyVar[func]], '= ' + func + MyDriver['Funcs'][MyVar[func]]['type'] = func + else: + # TODO FIXME error message + print 'Error: Function type mismatch: var = ' + str(MyVar) + ', code = ' + str(MyDriver['Funcs'][MyVar[func]]) + ', func = ' + str(func) + MyDriver['Funcs'][MyVar[func]]['reference_count'] += 1 + if Verbose: + print '==>>MyVar:', MyVar + return MyVar + +def build_group(MyDriver, p): + if Verbose: + print 'Group:', p[0]['name'], p + push_context() + MyGroup = {} + MyGroup['Groups'] = {} + MyGroup['Vars'] = {} + # the sequence of both variables and non-variables is significant + # Therefore, they have to be processed in a single sequence + if p[0]['name']: + if len(ContextStack[ContextIndex]['path']) > 0: + ContextStack[ContextIndex]['path'] += '/' + ContextStack[ContextIndex]['path'] += p[0]['name'] + MyGroup['path'] = ContextStack[ContextIndex]['path'] + for item in p: + if 'Variable' in item: + MyVar = build_variable(MyDriver, item['Variable']) + MyGroup['Vars'][MyVar['name']] = MyVar + elif 'Group' in item: + MySubGroup = build_group(MyDriver, item['Group']) + MyGroup['Groups'][MySubGroup['name']] = MySubGroup + else: + if Verbose: + print "Group Item:", item + if 'GroupProperty' in item: + if 'GroupProperty' not in MyGroup: + MyGroup['GroupProperty'] = {} + MyGroup['GroupProperty'][item['GroupProperty'][0]] = item['GroupProperty'][1] + elif 'Property' in item: + if 'Property' not in MyGroup: + MyGroup['Property'] = {} + MyGroup['Property'][item['Property'][0]] = item['Property'][1] + if 'Property' not in ContextStack[ContextIndex]: + ContextStack[ContextIndex]['Property'] = {} + ContextStack[ContextIndex]['Property'][item['Property'][0]] = item['Property'][1] + else: + for key in item: + MyGroup[key] = item[key] + if key in ContextStack[ContextIndex]: + ContextStack[ContextIndex][key] = item[key] + pop_context() + return MyGroup + +def build_driver(MyDriver, TheTree): + if Verbose: + print "TheTree:", TheTree + init_context() + for item in [x for x in TheTree if 'Code' in x]: + MyCode = build_code(MyDriver, item['Code']) + MyDriver['Funcs'][MyCode['name']] = MyCode + for item in [x for x in TheTree if 'Group' in x]: + MyGroup = build_group(MyDriver, item['Group']) + MyDriver['Groups'][MyGroup['name']] = MyGroup + for item in TheTree: + if Verbose: + print "Driver Item:", item + if 'Group' in item: + continue + elif 'Code' in item: + continue + else: + if 'DriverProperty' in item: + if 'DriverProperty' not in MyDriver: + MyDriver['DriverProperty'] = {} + MyDriver['DriverProperty'][item['DriverProperty'][0]] = item['DriverProperty'][1] + continue + for key in item: + MyDriver[key] = item[key] + if Verbose: + print "MyDriver:", MyDriver +# +# Driver Dump Functions +# +def dump_driver_vars(vars, indent): + global FunctionTypes + global DriveableFunctionTypes + for item in sorted(vars): + print indent + ' VAR %s = {' % item + for subitem in sorted([i for i in vars[item] if i not in FunctionTypes + DriveableFunctionTypes]): + print indent + ' %s =' % subitem, vars[item][subitem] + for subitem in sorted([i for i in vars[item] if i in FunctionTypes]): + print indent + ' %s =' % subitem, vars[item][subitem] + for subitem in sorted([i for i in vars[item] if i in DriveableFunctionTypes]): + print indent + ' %s =' % subitem, vars[item][subitem] + print indent + ' }' + +def dump_driver_groups(groups, indent): + for item in sorted(groups): + if item: + print indent + 'GROUP ' + item + ' = {' + else: + print indent + 'GROUP = {' + for subitem in sorted([x for x in groups[item] if not x in ['Groups', 'Vars']]): + print indent + ' ', subitem, '=', groups[item][subitem] + dump_driver_vars(groups[item]['Vars'], indent) + dump_driver_groups(groups[item]['Groups'], indent + ' ') + print indent + '}' + +def dump_driver_funcs(funcs): + for item in sorted(funcs): + if 'type' in funcs[item] and funcs[item]['type']: + print ' CODE ' + funcs[item]['type'] + ' ' + item + ' = {' + else: + print ' CODE ' + item + ' = {' + for line in funcs[item]['text']: + print ' @%s' % line + print ' }' + +def dump_driver(MyDriver): + print 'DRIVER ' + MyDriver['name'] + ' = {' + for item in sorted([x for x in MyDriver if x not in ['Groups', 'Funcs']]): + print ' ' + item + ' =', MyDriver[item] + #print 'Groups:', MyDriver['Groups'] + dump_driver_groups(MyDriver['Groups'], ' ') + #print 'Funcs:', MyDriver['Funcs'] + dump_driver_funcs(MyDriver['Funcs']) + print '}' +# +# Code Generation Functions +# +def emit(txt): + global NumberOfLinesOut + NumberOfLinesOut += len(txt) + for line in txt: + fdo.write(line) + if not line.endswith('\n'): + fdo.write('\n') + +def put_preamble(MyDriver): + txt = [] + txt += ['# Generated driver for %s' % MyDriver['name']] + txt += ['# vim: ft=tcl tabstop=8 softtabstop=2 shiftwidth=2 nocindent smartindent'] + txt += ['#'] + txt += [''] + txt += ['namespace eval %s {' % MyDriver['namespace']] + txt += [' set debug_threshold 0'] + txt += ['}'] + txt += [''] + txt += ['proc %s::debug_log {debug_level debug_string} {' % MyDriver['namespace']] + txt += [' set catch_status [ catch {'] + txt += [' if {${debug_level} >= ${%s::debug_threshold}} {' % MyDriver['namespace']] + txt += [' set fd [open "/tmp/%s.log" "a"]' % MyDriver['name']] + txt += [' set line "[clock format [clock seconds] -format "%T"] ${debug_string}"'] + txt += [' puts ${fd} "${line}"'] + txt += [' close ${fd}'] + txt += [' }'] + txt += [' } catch_message ]'] + txt += ['}'] + emit(txt) + +def put_write_function(MyDriver, func): + txt = [''] + txt += ['# function to write a parameter value on a device'] + txt += ['proc %s::%s {tc_root nextState cmd_str} {' % (MyDriver['namespace'], func)] + txt += [' set catch_status [ catch {'] + txt += [' debug_log 1 "%s tc_root=${tc_root} sct=[sct] cmd=${cmd_str}"' % func] + txt += [' if { [hpropexists [sct] geterror] } {'] + txt += [' hdelprop [sct] geterror'] + txt += [' }'] + txt += [' set par [sct target]'] + txt += [' set cmd "${cmd_str}${par}"'] + if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: + txt += ['# hook code starts'] + txt += MyDriver['Funcs'][func]['text'] + txt += ['# hook code ends'] + txt += [' if { [hpropexists [sct] geterror] } {'] + txt += [' debug_log 1 "[sct] error: [sct geterror]"'] + txt += [' error "[sct geterror]"'] + txt += [' }'] + else: + txt += ['# hook code goes here'] + txt += [' if { [hpropexists [sct] driving] } {'] + txt += [' if { [hpropexists [sct] writestatus] && [sct writestatus] == "start" } {'] + txt += [' sct driving 1'] + txt += [' }'] + txt += [' }'] + txt += [' debug_log 1 "%s sct send ${cmd}"' % func] + txt += [' if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} {'] + txt += [' sct send "${cmd}"'] + txt += [' }'] + txt += [' return ${nextState}'] + txt += [' } catch_message ]'] + txt += [' handle_exception ${catch_status} ${catch_message}'] + txt += ['}'] + emit(txt) + +def put_check_function(MyDriver, func): + txt = [''] + txt += ['# function to check the write parameter on a device'] + txt += ['proc %s::%s {tc_root} {' % (MyDriver['namespace'], func)] + txt += [' set catch_status [ catch {'] + txt += [' debug_log 1 "%s tc_root=${tc_root} sct=[sct] resp=[sct result]"' % func] + if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: + txt += ['# hook code starts'] + txt += MyDriver['Funcs'][func]['text'] + txt += ['# hook code ends'] + else: + txt += ['# hook code goes here'] + txt += [' return "idle"'] + txt += [' } catch_message ]'] + txt += [' handle_exception ${catch_status} ${catch_message}'] + txt += ['}'] + emit(txt) + +def put_fetch_function(MyDriver, func): + txt = [''] + txt += ['# function to request the read of a parameter on a device'] + txt += ['proc %s::%s {tc_root nextState cmd_str} {' % (MyDriver['namespace'], func)] + txt += [' set catch_status [ catch {'] + txt += [' debug_log 1 "%s tc_root=${tc_root} sct=[sct] cmd=${cmd_str}"' % func] + txt += [' if { [hpropexists [sct] geterror] } {'] + txt += [' hdelprop [sct] geterror'] + txt += [' }'] + txt += [' set cmd "${cmd_str}"'] + if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: + txt += ['# hook code starts'] + txt += MyDriver['Funcs'][func]['text'] + txt += ['# hook code ends'] + txt += [' if { [hpropexists [sct] geterror] } {'] + txt += [' debug_log 1 "[sct] error: [sct geterror]"'] + txt += [' error "[sct geterror]"'] + txt += [' }'] + else: + txt += ['# hook code goes here'] + txt += [' debug_log 1 "%s sct send ${cmd}"' % func] + txt += [' if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} {'] + txt += [' sct send "${cmd}"'] + txt += [' }'] + txt += [' return ${nextState}'] + txt += [' } catch_message ]'] + txt += [' handle_exception ${catch_status} ${catch_message}'] + txt += ['}'] + emit(txt) + +def put_read_function(MyDriver, func): + txt = [''] + txt += ['# function to parse the read of a parameter on a device'] + txt += ['proc %s::%s {tc_root} {' % (MyDriver['namespace'], func)] + txt += [' set catch_status [ catch {'] + txt += [' debug_log 1 "%s tc_root=${tc_root} sct=[sct] result=[sct result]"' % func] + txt += [' if { [hpropexists [sct] geterror] } {'] + txt += [' hdelprop [sct] geterror'] + txt += [' }'] + txt += [' set data [sct result]'] + txt += [' set nextState "idle"'] + txt += [' if {[string equal -nocase -length 7 ${data} "ASCERR:"]} {'] + txt += [' # the protocol driver has reported an error'] + txt += [' sct geterror "${data}"'] + txt += [' error "[sct geterror]"'] + txt += [' }'] + if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: + txt += ['# hook code starts'] + txt += MyDriver['Funcs'][func]['text'] + txt += ['# hook code ends'] + txt += [' if { [hpropexists [sct] geterror] } {'] + txt += [' debug_log 1 "[sct] error: [sct geterror]"'] + txt += [' error "[sct geterror]"'] + txt += [' }'] + else: + txt += ['# hook code goes here'] + txt += [' if { ${data} != [sct oldval] } {'] + txt += [' debug_log 1 "[sct] changed to new:${data}, from old:[sct oldval]"'] + txt += [' sct oldval ${data}'] + txt += [' sct update ${data}'] + txt += [' sct utime readtime'] + txt += [' }'] + txt += [' return ${nextState}'] + txt += [' } catch_message ]'] + txt += [' handle_exception ${catch_status} ${catch_message}'] + txt += ['}'] + emit(txt) + +def put_checkrange_function(MyDriver, func): + txt = [''] + txt += ['# check function for hset change'] + txt += ['proc %s::%s {tc_root} {' % (MyDriver['namespace'], func)] + txt += [' set catch_status [ catch {'] + txt += [' debug_log 1 "%s tc_root=${tc_root} sct=[sct] target=[sct target]"' % func] + txt += [' set setpoint [sct target]'] + txt += [' if { [hpropexists [sct] lowerlimit] } {'] + txt += [' set lolimit [sct lowerlimit]'] + txt += [' } else {'] + txt += [' # lowerlimit not set, use target'] + txt += [' set lolimit [sct target]'] + txt += [' }'] + txt += [' if { [hpropexists [sct] upperlimit] } {'] + txt += [' set hilimit [sct upperlimit]'] + txt += [' } else {'] + txt += [' # upperlimit not set, use target'] + txt += [' set hilimit [sct target]'] + txt += [' }'] + if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: + txt += ['# hook code starts'] + txt += MyDriver['Funcs'][func]['text'] + txt += ['# hook code ends'] + else: + txt += ['# hook code goes here'] + txt += [' if { ${setpoint} < ${lolimit} || ${setpoint} > ${hilimit} } {'] + txt += [' error "setpoint ${setpoint} violates limits (${lolimit}..${hilimit}) on [sct]"'] + txt += [' }'] + txt += [' return OK'] + txt += [' } catch_message ]'] + txt += [' handle_exception ${catch_status} ${catch_message}'] + txt += ['}'] + emit(txt) + +def put_checklimits_function(MyDriver, func): + txt = [''] + txt += ['# checklimits function for driveable interface'] + txt += ['proc %s::%s {tc_root} {' % (MyDriver['namespace'], func)] + txt += [' set catch_status [ catch {'] + txt += [' debug_log 1 "%s tc_root=${tc_root} sct=[sct] target=[sct target]"' % func] + txt += [' set setpoint [sct target]'] + txt += [' if { [hpropexists [sct] lowerlimit] } {'] + txt += [' set lolimit [sct lowerlimit]'] + txt += [' } else {'] + txt += [' # lowerlimit not set, use target'] + txt += [' set lolimit [sct target]'] + txt += [' }'] + txt += [' if { [hpropexists [sct] upperlimit] } {'] + txt += [' set hilimit [sct upperlimit]'] + txt += [' } else {'] + txt += [' # upperlimit not set, use target'] + txt += [' set hilimit [sct target]'] + txt += [' }'] + if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: + txt += ['# hook code starts'] + txt += MyDriver['Funcs'][func]['text'] + txt += ['# hook code ends'] + else: + txt += ['# hook code goes here'] + txt += [' if { ${setpoint} < ${lolimit} || ${setpoint} > ${hilimit} } {'] + txt += [' sct driving 0'] + txt += [' error "setpoint ${setpoint} violates limits (${lolimit}..${hilimit}) on [sct]"'] + txt += [' }'] + txt += [' return OK'] + txt += [' } catch_message ]'] + txt += [' handle_exception ${catch_status} ${catch_message}'] + txt += ['}'] + emit(txt) + +def put_checkstatus_function(MyDriver, func): + txt = [''] + txt += ['# checkstatus function for driveable interface'] + txt += ['proc %s::%s {tc_root} {' % (MyDriver['namespace'], func)] + txt += [' set catch_status [ catch {'] + if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: + txt += ['# hook code starts'] + txt += MyDriver['Funcs'][func]['text'] + txt += ['# hook code ends'] + else: + txt += ['# hook code goes here'] + txt += [' if {[sct driving]} {'] + txt += [' set sp "[sct target]"'] + txt += [' set pv "[hval ${tc_root}/[sct driveable]]"'] + txt += [' if { abs(${pv} - ${sp}) <= [sct tolerance] } {'] + txt += [' if { [hpropexists [sct] settle_time] } {'] + txt += [' if { [hpropexists [sct] settle_time_start] } {'] + txt += [' if { [sct utime] - [sct settle_time_start] >= [sct settle_time]} {'] + txt += [' sct driving 0'] + txt += [' return "idle"'] + txt += [' }'] + txt += [' return "busy"'] + txt += [' } else {'] + txt += [' sct utime settle_time_start'] + txt += [' return "busy"'] + txt += [' }'] + txt += [' }'] + txt += [' sct driving 0'] + txt += [' return "idle"'] + txt += [' }'] + txt += [' if { [hpropexists [sct] settle_time_start] } {'] + txt += [' hdelprop [sct] settle_time_start'] + txt += [' }'] + txt += [' return "busy"'] + txt += [' } else {'] + txt += [' return "idle"'] + txt += [' }'] + txt += [' } catch_message ]'] + txt += [' handle_exception ${catch_status} ${catch_message}'] + txt += ['}'] + emit(txt) + +def put_halt_function(MyDriver, func): + txt = [''] + txt += ['# halt function for driveable interface'] + txt += ['proc %s::%s {tc_root} {' % (MyDriver['namespace'], func)] + txt += [' set catch_status [ catch {'] + txt += [' debug_log 1 "%s tc_root=${tc_root} sct=[sct] driving=[sct driving]"' % func] + txt += [' ### TODO hset [sct] [hval [sct]]'] + if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: + txt += ['# hook code starts'] + txt += MyDriver['Funcs'][func]['text'] + txt += ['# hook code ends'] + else: + txt += ['# hook code goes here'] + txt += [' sct driving 0'] + txt += [' return "idle"'] + txt += [' } catch_message ]'] + txt += [' handle_exception ${catch_status} ${catch_message}'] + txt += ['}'] + emit(txt) + +def put_pid_function(MyDriver, func): + txt = [''] + txt += ['# pid function for PID control'] + txt += ['proc %s::%s {tc_root sp pv} {' % (MyDriver['namespace'], func)] + txt += [' set catch_status [ catch {'] + txt += [' debug_log 1 "%s tc_root=${tc_root} sct=[sct] pv=${pv} sp=${sp}"' % func] + txt += [' sct pid_error [expr ${sp} - ${pv}]'] + txt += [' set p_value [expr [sct pid_pvalue] * [sct pid_error]]'] + txt += [' set d_value [expr [sct pid_dvalue] * (${pv} - [sct oldval])]'] + txt += [' sct pid_deriv [sct pid_error]'] + txt += [' sct pid_integ [expr [sct pid_integ] + [sct pid_error]]'] + txt += [' if { [sct pid_integ] > [sct pid_imax] } {'] + txt += [' sct pid_integ [sct pid_imax]'] + txt += [' }'] + txt += [' if { [sct pid_integ] < -[sct pid_imax] } {'] + txt += [' sct pid_integ -[sct pid_imax]'] + txt += [' }'] + txt += [' set i_value [expr [sct pid_ivalue] * [sct pid_integ]]'] + txt += [' set pid [expr ${p_value} + ${i_value} + ${d_value}]'] + if func in MyDriver['Funcs'] and len(MyDriver['Funcs'][func]['text']) > 0: + txt += ['# hook code starts'] + txt += MyDriver['Funcs'][func]['text'] + txt += ['# hook code ends'] + else: + txt += ['# hook code goes here'] + txt += [' sct pid_output ${pid}'] + txt += [' } catch_message ]'] + txt += [' handle_exception ${catch_status} ${catch_message}'] + txt += [' return ${pid}'] + txt += ['}'] + emit(txt) + +def put_group(MyDriver, MyGroup): + readable_or_writeable = False + txt = [] + if MyGroup['name']: + txt += [''] + txt += [' hfactory ${scobj_hpath}/%s plain spy none' % MyGroup['path']] + if 'GroupProperty' in MyGroup: + for key in sorted(MyGroup['GroupProperty']): + txt += [' hsetprop ${scobj_hpath}/%s %s "%s"' % (MyGroup['path'], key, MyGroup['GroupProperty'][key])] + groupname = MyGroup['path'] + '/' + else: + groupname = '' + for var in sorted(MyGroup['Vars']): + txt += [''] + MyVar = MyGroup['Vars'][var] + nodename = groupname + MyVar['name'] + # Check driveable attributes are present if required + if 'driveable' in MyVar and MyVar['driveable']: + for attr in ('lowerlimit', 'upperlimit', 'tolerance'): + if attr not in MyVar: + msg = 'Driveable: %s does not have required attribute: %s' % (nodename, attr) + print 'Warning:', msg + txt += [' # Warning: ' + msg] + # Check PID attributes are present if required + if 'pid_function' in MyVar: + for attr in ('pid_pvalue', + 'pid_ivalue', + 'pid_dvalue', + 'pid_imax', + 'pid_error', + 'pid_deriv', + 'pid_integ', + ): + if attr not in MyVar['Property']: + msg = 'PID: %s does not have required attribute: %s' % (nodename, attr) + print 'Warning:', msg + txt += [' # Warning: ' + msg] + txt += [' hfactory ${scobj_hpath}/%s plain %s %s' % (nodename, MyVar['priv'], MyVar['type'])] + if MyVar['readable'] > 0: + readable_or_writeable = True + fetch_func = MyVar['fetch_function'] + if fetch_func == 'none': + fetch_func = 'getValue' + read_func = MyVar['read_function'] + read_command = MyVar['read_command'] + txt += [' hsetprop ${scobj_hpath}/%s read ${ns}::%s ${scobj_hpath} %s {%s}' % (nodename, fetch_func, read_func, read_command)] + txt += [' hsetprop ${scobj_hpath}/%s %s ${ns}::%s ${scobj_hpath}' % (nodename, read_func, read_func)] + if MyVar['writeable'] > 0 or MyVar['driveable']: + readable_or_writeable = True + check_func = MyVar['check_function'] + checkrange_func = MyVar['checkrange_function'] + write_func = MyVar['write_function'] + if 'write_command' in MyVar: + write_command = MyVar['write_command'] + else: + write_command = '' + txt += [' hsetprop ${scobj_hpath}/%s write ${ns}::%s ${scobj_hpath} %s {%s}' % (nodename, write_func, check_func, write_command)] + txt += [' hsetprop ${scobj_hpath}/%s %s ${ns}::%s ${scobj_hpath}' % (nodename, check_func, check_func)] + txt += [' hsetprop ${scobj_hpath}/%s check ${ns}::%s ${scobj_hpath}' % (nodename, checkrange_func)] + if MyVar['driveable']: + halt_func = MyVar['halt_function'] + checklimits_func = MyVar['checklimits_function'] + checkstatus_func = MyVar['checkstatus_function'] + txt += [' hsetprop ${scobj_hpath}/%s driving 0' % nodename] + txt += [' hsetprop ${scobj_hpath}/%s checklimits ${ns}::%s ${scobj_hpath}' % (nodename, checklimits_func)] + txt += [' hsetprop ${scobj_hpath}/%s checkstatus ${ns}::%s ${scobj_hpath}' % (nodename, checkstatus_func)] + txt += [' hsetprop ${scobj_hpath}/%s halt ${ns}::%s ${scobj_hpath}' % (nodename, halt_func)] + txt += [' hsetprop ${scobj_hpath}/%s driveable %s' % (nodename, MyVar['driveable'])] + if 'control' in MyVar: + txt += [' hsetprop ${scobj_hpath}/%s control %s' % (nodename, MyVar['control'])] + if 'data' in MyVar: + txt += [' hsetprop ${scobj_hpath}/%s data %s' % (nodename, MyVar['data'])] + if 'mutable' in MyVar: + txt += [' hsetprop ${scobj_hpath}/%s mutable %s' % (nodename, MyVar['mutable'])] + if 'nxsave' in MyVar: + txt += [' hsetprop ${scobj_hpath}/%s nxsave %s' % (nodename, MyVar['nxsave'])] + if 'lowerlimit' in MyVar: + txt += [' hsetprop ${scobj_hpath}/%s lowerlimit %s' % (nodename, MyVar['lowerlimit'])] + if 'upperlimit' in MyVar: + txt += [' hsetprop ${scobj_hpath}/%s upperlimit %s' % (nodename, MyVar['upperlimit'])] + if 'tolerance' in MyVar: + txt += [' hsetprop ${scobj_hpath}/%s tolerance %s' % (nodename, MyVar['tolerance'])] + if 'units' in MyVar: + txt += [' hsetprop ${scobj_hpath}/%s units %s' % (nodename, MyVar['units'])] + if 'allowed' in MyVar: + txt += [' hsetprop ${scobj_hpath}/%s values %s' % (nodename, MyVar['allowed'])] + if 'value' in MyVar: + txt += [' hsetprop ${scobj_hpath}/%s oldval %s' % (nodename, MyVar['value'])] + txt += [' hset ${scobj_hpath}/%s %s' % (nodename, MyVar['value'])] + else: + if MyVar['type'] == 'none': + pass + elif MyVar['type'] == 'int': + txt += [' hsetprop ${scobj_hpath}/%s oldval 0' % nodename] + elif MyVar['type'] == 'float': + txt += [' hsetprop ${scobj_hpath}/%s oldval 0.0' % nodename] + else: + txt += [' hsetprop ${scobj_hpath}/%s oldval UNKNOWN' % nodename] + for key in sorted(MyVar['Property']): + txt += [' hsetprop ${scobj_hpath}/%s %s "%s"' % (nodename, key, MyVar['Property'][key])] + # Generated at runtime __ for nxalias and driveable + path = MyVar['path'] + if len(path) > 0: + path = path.replace('/', '_') + '_' + path += MyVar['name'] + #print "Path: %s" % MyVar['path'] + nxalias = '${name}_' + path + if 'nxalias' not in MyVar['Property']: + txt += [' hsetprop ${scobj_hpath}/%s nxalias "%s"' % (nodename, nxalias)] + if not MyGroup['name']: + if 'GroupProperty' in MyGroup: + txt += [''] + for key in sorted(MyGroup['GroupProperty']): + txt += [' hsetprop ${scobj_hpath} %s "%s"' % (key, MyGroup['GroupProperty'][key])] + if readable_or_writeable: + txt += [''] + txt += [' if {[SplitReply [%s]]=="false"} {' % MyDriver['simulation_group']] + for var in sorted(MyGroup['Vars']): + MyVar = MyGroup['Vars'][var] + nodename = groupname + MyVar['name'] + if MyVar['readable'] > 0: + poll_period = MyVar['readable'] + if poll_period < 1 or poll_period > 300: + poll_period = 5 + txt += [' ${sct_controller} poll ${scobj_hpath}/%s %s' % (nodename, poll_period)] + for var in sorted(MyGroup['Vars']): + MyVar = MyGroup['Vars'][var] + nodename = groupname + MyVar['name'] + if MyVar['writeable'] > 0 or MyVar['driveable']: + txt += [' ${sct_controller} write ${scobj_hpath}/%s' % nodename] + if MyVar['driveable']: + txt += [' ansto_makesctdrive %s ${scobj_hpath}/%s ${scobj_hpath}/%s ${sct_controller}' % (nxalias, nodename, MyVar['driveable'])] + txt += [' }'] + for grp in sorted(MyGroup['Groups']): + txt += put_group(MyDriver, MyGroup['Groups'][grp]) + return txt + +def put_mk_sct_driver(MyDriver): + txt = [''] + if 'make_args' in MyDriver: + line = 'proc %s::mk_sct_%s { sct_controller name %s } {' % (MyDriver['namespace'], MyDriver['name'], MyDriver['make_args']) + else: + line = 'proc %s::mk_sct_%s { sct_controller name } {' % (MyDriver['namespace'], MyDriver['name']) + txt += [line] + if 'make_args' in MyDriver: + make_args = '' + for arg in MyDriver['make_args'].split(): + if len(make_args) > 0: + make_args += ' ' + make_args += '${' + arg + '}' + txt += [' debug_log 1 "mk_sct_%s ${sct_controller} ${name} %s"' % (MyDriver['name'], make_args)] + else: + txt += [' debug_log 1 "mk_sct_%s for ${name}"' % MyDriver['name']] + txt += [' set ns "[namespace current]"'] + txt += [' set catch_status [ catch {'] + txt += [''] + txt += [' MakeSICSObj ${name} SCT_OBJECT'] + txt += [''] + txt += [' sicslist setatt ${name} klass %s' % MyDriver['class']] + txt += [' sicslist setatt ${name} long_name ${name}'] + if 'DriverProperty' in MyDriver: + for key in MyDriver['DriverProperty']: + txt += [' sicslist setatt ${name} %s "%s"' % (key, MyDriver['DriverProperty'][key])] + txt += [''] + txt += [' set scobj_hpath /sics/${name}'] + + for group in sorted(MyDriver['Groups']): + txt += put_group(MyDriver, MyDriver['Groups'][group]) + + txt += [' hsetprop ${scobj_hpath} klass %s' % MyDriver['class']] + if 'mkDriver' in MyDriver['Funcs']: + txt += ['# hook code starts'] + txt += MyDriver['Funcs']['mkDriver']['text'] + txt += ['# hook code ends'] + else: + txt += ['# hook code goes here'] + txt += [' } catch_message ]'] + txt += [' handle_exception ${catch_status} ${catch_message}'] + txt += ['}'] + emit(txt) + +def put_postamble(MyDriver): + txt = [''] + txt += ['namespace eval %s {' % MyDriver['namespace']] + txt += [' namespace export debug_log'] + txt += [' namespace export mk_sct_%s' % MyDriver['name']] + txt += ['}'] + txt += [''] + if 'add_args' in MyDriver: + line = 'proc add_%s {name IP port %s} {' % (MyDriver['name'], MyDriver['add_args']) + else: + line = 'proc add_%s {name IP port} {' % MyDriver['name'] + txt += [line] + txt += [' set catch_status [ catch {'] + txt += [' set ns "%s"' % MyDriver['namespace']] + if 'make_args' in MyDriver: + make_args = '' + for arg in MyDriver['make_args'].split(): + if len(make_args) > 0: + make_args += ' ' + make_args += '${' + arg + '}' + txt += [' ${ns}::debug_log 1 "add_%s ${name} ${IP} ${port} %s"' % (MyDriver['name'], make_args)] + else: + txt += [' ${ns}::debug_log 1 "add_%s ${name} ${IP} ${port}"' % MyDriver['name']] + txt += [' if {[SplitReply [%s]]=="false"} {' % MyDriver['simulation_group']] + txt += [' if {[string equal -nocase "aqadapter" "${IP}"]} {'] + txt += [' ${ns}::debug_log 1 "makesctcontroller sct_${name} aqadapter ${port}"'] + txt += [' makesctcontroller sct_${name} aqadapter ${port}'] + txt += [' } else {'] + if 'protocol_args' in MyDriver: + protocol_args = MyDriver['protocol_args'].replace('\\', '\\\\').replace('"', '\\"') + txt += [' ${ns}::debug_log 1 "makesctcontroller sct_${name} %s ${IP}:${port} %s"' % (MyDriver['protocol'], protocol_args)] + txt += [' makesctcontroller sct_${name} %s ${IP}:${port} %s' % (MyDriver['protocol'], MyDriver['protocol_args'])] + else: + txt += [' ${ns}::debug_log 1 "makesctcontroller sct_${name} %s ${IP}:${port}"' % MyDriver['protocol']] + txt += [' makesctcontroller sct_${name} %s ${IP}:${port}' % MyDriver['protocol']] + txt += [' }'] + txt += [' }'] + if 'make_args' in MyDriver: + make_args = '' + for arg in MyDriver['make_args'].split(): + if len(make_args) > 0: + make_args += ' ' + make_args += '${' + arg + '}' + txt += [' ${ns}::debug_log 1 "mk_sct_%s sct_${name} ${name} %s"' % (MyDriver['name'], make_args)] + txt += [' ${ns}::mk_sct_%s sct_${name} ${name} %s' % (MyDriver['name'], make_args)] + else: + txt += [' ${ns}::debug_log 1 "mk_sct_%s sct_${name} ${name}"' % MyDriver['name']] + txt += [' ${ns}::mk_sct_%s sct_${name} ${name}' % MyDriver['name']] +# TODO +#txt += [' ${ns}::debug_log 1 "makesctemon ${name} /sics/${name}/emon/monmode /sics/${name}/emon/isintol /sics/${name}/emon/errhandler"'] +# txt += [' makesctemon ${name} /sics/${name}/emon/monmode /sics/${name}/emon/isintol /sics/${name}/emon/errhandler'] + txt += [' } catch_message ]'] + txt += [' handle_exception ${catch_status} ${catch_message}'] + txt += ['}'] + txt += [''] + txt += ['puts stdout "file evaluation of sct_%s.tcl"' % MyDriver['name']] + txt += ['%s::debug_log 1 "file evaluation of sct_%s.tcl"' % (MyDriver['namespace'], MyDriver['name'])] + emit(txt) + +def put_config(MyDriver): + txt = [''] + txt += ['proc %s::read_config {} {' % MyDriver['namespace']] + txt += [' set catch_status [ catch {'] + txt += [' set ns "%s"' % MyDriver['namespace']] + txt += [' ${ns}::debug_log 1 "Processing Config"'] + txt += [' dict for {k v} $::config_dict {'] + txt += [' ${ns}::debug_log 1 "Inspecting $k:$v"'] + txt += [' if { [dict exists $v "driver"] } {'] + txt += [' ${ns}::debug_log 1 "Has driver [dict get $v driver]"'] + txt += [' if { [dict get $v "driver"] == "%s" } {' % MyDriver['name']] + txt += [' ${ns}::debug_log 1 "Correct driver, enabled = [dict get $v enabled]"'] + txt += [' if { [dict get $v enabled] } {'] + txt += [' set IP [dict get $v ip]'] + txt += [' set PORT [dict get $v port]'] + txt += [' set name [dict get $v name]'] + txt += [' MakeAsyncProtocol ${name}_protocol'] + txt += [' MakeAsyncQueue ${name}_queue ${name}_protocol ${IP} ${PORT}'] + if 'make_args' in MyDriver: + txt += [' set arg_list [list]'] + txt += [' foreach arg {' + MyDriver['make_args'] + '} {'] + txt += [' if {[dict exists $v $arg]} {'] + txt += [' lappend arg_list "[dict get $v $arg]"'] + txt += [' } else {'] + txt += [' ${ns}::debug_log 1 "Missing configuration value $arg"'] + txt += [' error "Missing configuration value $arg"'] + txt += [' }'] + txt += [' }'] + txt += [' ${ns}::debug_log 1 "arg_list = $arg_list"'] + txt += [' ${ns}::debug_log 1 "add_%s ${name} aqadapter ${name}_queue $arg_list"' % MyDriver['name']] + txt += [' add_%s ${name} "aqadapter" ${name}_queue {*}$arg_list' % MyDriver['name']] + else: + txt += [' add_%s ${name} "aqadapter" ${name}_queue' % MyDriver['name']] + txt += [' }'] + txt += [' }'] + txt += [' }'] + txt += [' }'] + txt += [' } catch_message ]'] + txt += [' handle_exception ${catch_status} ${catch_message}'] + txt += ['}'] + txt += ['if { [info exists ::config_dict] } {'] + txt += [' %s::read_config' % MyDriver['namespace']] + txt += ['} else {'] + txt += [' %s:debug_log 1 "No config dict"' % MyDriver['namespace']] + txt += ['}'] + emit(txt) + +def put_standard_code(MyDriver): + # emit all of the functions in Funcs + for func in sorted(MyDriver['Funcs']): + theFunc = MyDriver['Funcs'][func] + # Don't generate functions which are not referenced + #if theFunc['reference_count'] == 0: + # continue + if theFunc['type'] == 'read_function': + put_read_function(MyDriver, func); + elif theFunc['type'] == 'write_function': + put_write_function(MyDriver, func); + elif theFunc['type'] == 'fetch_function': + put_fetch_function(MyDriver, func); + elif theFunc['type'] == 'check_function': + put_check_function(MyDriver, func); + elif theFunc['type'] == 'checkrange_function': + put_checkrange_function(MyDriver, func); + elif theFunc['type'] == 'checklimits_function': + put_checklimits_function(MyDriver, func); + elif theFunc['type'] == 'checkstatus_function': + put_checkstatus_function(MyDriver, func); + elif theFunc['type'] == 'halt_function': + put_halt_function(MyDriver, func); + elif theFunc['type'] == 'pid_function': + put_pid_function(MyDriver, func); + +def generate_driver(MyDriver): + global NumberOfLinesOut + global fdo + NumberOfLinesOut = 0 + full_filename = filename = "sct_%s.tcl" % MyDriver['name'] + if 'PathName' in MyDriver: + full_filename = os.path.join(MyDriver['PathName'], filename) + fdo = open(full_filename, 'w') + put_preamble(MyDriver) + put_standard_code(MyDriver) + put_mk_sct_driver(MyDriver) + put_postamble(MyDriver) + put_config(MyDriver) + fdo.close() + if CodeDump or Verbose: + print "Code Fragments:", MyDriver['Funcs'] + for f in sorted(MyDriver['Funcs'].keys()): + print "Function:", f, "Type:", MyDriver['Funcs'][f]['type'], '#Uses:', MyDriver['Funcs'][f]['reference_count'] + for l in MyDriver['Funcs'][f]['text']: + print " ", l + print "Produced file %s with %d lines." % (filename, NumberOfLinesOut) + +def process_drivers(TheDrivers): + if Verbose: + print "TheDrivers:", TheDrivers + for driver in TheDrivers: + MyDriver = {'name':driver} + MyDriver['namespace'] = '::scobj::%s' % driver + MyDriver['Groups'] = {} + MyDriver['Funcs'] = {} + build_driver(MyDriver, TheDrivers[driver]) + if Verbose: + print "MyDriver:", MyDriver['name'], '=', MyDriver + if DriverDump or Verbose: + dump_driver(MyDriver) + generate_driver(MyDriver) + +def process_source(source_files): + global PathName + global TheDrivers + global NumberOfLinesIn + + TheDrivers = {} + + # + # Build the lexer + # + lexer = lex.lex() + + + # + # Build the parser + # + yaccer = yacc.yacc() + + for source_file in source_files: + PathName = os.path.realpath(os.path.abspath(os.path.dirname(source_file))) + fd = open(source_file, 'r') + data = fd.read() + fd.close() + NumberOfLinesIn = data.count('\n') + print 'Consumed file %s with %d lines' % (source_file, NumberOfLinesIn) + yaccer.parse(data) + + process_drivers(TheDrivers) + +def main(): + global Verbose + global DriverDump + global CodeDump + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument("-c", "--code", help="dump code", + action="store_true") + parser.add_argument("-d", "--driver", help="dump driver", + action="store_true") + parser.add_argument("-v", "--verbose", help="verbose output", + action="store_true") + parser.add_argument("driver_source", help="driver source file", nargs="*") + args = parser.parse_args() + print args + if args.code: + CodeDump = True + else: + CodeDump = False + if args.driver: + DriverDump = True + else: + DriverDump = False + if args.verbose: + Verbose = True + else: + Verbose = False + source_files = args.driver_source + if source_files: + process_source(source_files) + +if __name__ == "__main__": + main() diff --git a/site_ansto/instrument/util/genmotconf.tcl b/site_ansto/instrument/util/genmotconf.tcl new file mode 100755 index 00000000..97f73af2 --- /dev/null +++ b/site_ansto/instrument/util/genmotconf.tcl @@ -0,0 +1,297 @@ +#!/usr/bin/env tclsh +# @file Generate a motor configuration file from CSV files of name value pairs. +# +# Input: List of CSV files. +# Output files: +# generated_motor_configuration.tcl +# genmotconf_report.log +# genmotconf_errors.log: Lists missing attributes if a spec is incomplete. +# missing_attlist.csv +# +# TODO +# Optionally split configuration accross multiple files for cases where +# axes are swapped out, eg Eulerian cradles, sample-stick rotation. +# This could be done by supplying a file which contains lines as follows, +# CFG_NAME1,m1 m2 m3 +# CFG_NAME2,m4 m5 m6 +# Where CFG_NAMEn is the name of a config file and mn's are motor names. +# In this case generated_motor_configuration.tcl will define the header and asyncqueues. +# The motor_configuration.tcl file would then be hand-coded to fileeval the CFG_NAMEn files as required. +# +source [file dirname $argv0]/genmotconf_procs.tcl + +set ERRCNT 0 +set MOTCFG_CNT 0 +set CANCFG_CNT 0 +set FAILED_MOTCFG_CNT 0 +# MOT_ATTLIST: Attributes required to configure an axis without an encoder +# ENC_ATTLIST: Attributes required to describe an encoder. +# NOTE Encoder readings for the limit switch positions are required. +# If the encoder "absenchome" reading is not supplied it is set equal to rev_enc_lim +# ENCMOT_ATTLIST: Attributes which describe an axis which has both a motor and encoder. +# OPT_ATTLIST: Optional attributes which may define recommended settings as well as descriptive information. +# REQ_ATTLIST: List of attributes required to generate a configuration for a motor object. +# SICS_CFG_MOTATTLIST: Extra attributes required to configure a motor object in SICS. +# SICS_CFG_ENCMOTATTLIST: Extra attributes required to configure a motor object with an encoder in SICS. +# ALL_ATTRIBUTES: List of all possible attributes recognised by this program. +# +# Attributes which are not in these lists are assumed to define the encoder +# readings for each position on an axis which has a set of meaningful positions +# such as apertures or multi-sample tables. +set MOT_ATTLIST [lsort {axis mc steps_per_x}] +set ENC_ATTLIST [lsort {cnts_per_x fwd_enc_lim rev_enc_lim}] +set ENCMOT_ATTLIST [lsort [concat $MOT_ATTLIST $ENC_ATTLIST]] +set OPT_ATTLIST [lsort {axis_number dflt_accel_steps dflt_decel_steps dflt_speed_steps description speed accel decel}] +set SICS_CFG_MOTATTLIST [lsort {home fwd_lim rev_lim maxspeed maxaccel maxdecel part units}] +set SICS_CFG_ENCMOTATTLIST [lsort [concat absenchome $SICS_CFG_MOTATTLIST]] +set REQ_ATTLIST [lsort [concat $MOT_ATTLIST $SICS_CFG_MOTATTLIST]] +set ALL_ATTRIBUTES [lsort [concat $ENCMOT_ATTLIST $SICS_CFG_ENCMOTATTLIST $OPT_ATTLIST]] + +set arg0 [lindex $argv 0] +if {[string match $arg0 "help"] || [string match $arg0 "--help"] || [string match $arg0 "-h"]} { + puts "\nUsage: $argv0 file1.csv file2.csv ..." + puts "\nThe following parameters must be provided in the CSV files," + puts " $MOT_ATTLIST" + puts "\nA motor with an encoder must also provide these parameters," + puts " $ENC_ATTLIST" + puts "\nOptionally these parameters may also be provided" + puts " $OPT_ATTLIST" + puts "\nIf these motor parameters are not provided they will be generated," + puts " $SICS_CFG_MOTATTLIST" + puts "\nIf an axis has an encoder these parameters will be generated," + puts " $SICS_CFG_ENCMOTATTLIST" + exit 0 +} + +array set autogen_attarr {} +set scriptname [file tail [file rootname $argv0]] +set file_list $argv + +set fhr [open ${scriptname}_report.log "w"] +set fhe [open ${scriptname}_errors.log "w"] + +# @brief Generate a default value for missing attributes. +# @param mot motor name +# @param att attribute name +# @return value for attribute or NOATT if no attribute should be generated. +proc gen_attval {mot att} { + + if {[set ::${mot}_attarr(steps_per_x)] < 0} { + set sign -1.0 + } else { + set sign 1.0 + } + if { [info exists ::${mot}_encatts(cnts_per_x)] } { + set cnts_per_x_val [expr double([set ::${mot}_encatts(cnts_per_x)])] + } + if { [info exists ::${mot}_encatts(rev_enc_lim)]} { + set rev_enc_lim_val [expr double([set ::${mot}_encatts(rev_enc_lim)])] + } + if { [info exists ::${mot}_encatts(fwd_enc_lim)]} { + set fwd_enc_lim_val [expr double([set ::${mot}_encatts(fwd_enc_lim)])] + } + if [info exists ::${mot}_attarr(absenchome)] { + set enc_home_val [expr double([set ::${mot}_attarr(absenchome)])] + } else { + if {$sign < 0} { + set enc_home_val [expr double([set ::${mot}_encatts(fwd_enc_lim)])] + } else { + set enc_home_val [expr double([set ::${mot}_encatts(rev_enc_lim)])] + } + } + if [info exists ::${mot}_attarr(home)] { + set home_val [expr double([set ::${mot}_attarr(home)])] + } else { + set home_val 0 + } + switch $att { + "absenchome" { + if [info exists ::${mot}_encatts(rev_enc_lim)] { + return $enc_home_val + } else { + return "NOATT" + } + } + "maxspeed" {return 1} + "maxaccel" {return 1} + "maxdecel" {return 1} + "rev_lim" { + if { [info exists ::${mot}_encatts(rev_enc_lim)] && [info exists ::${mot}_encatts(cnts_per_x)] } { + if {$sign < 0} { + return [expr {($fwd_enc_lim_val - $enc_home_val) / $cnts_per_x_val + $home_val}] + } else { + return [expr {($rev_enc_lim_val - $enc_home_val) / $cnts_per_x_val + $home_val}] + } + } else { + return 0 + } + } + "home" {return 0} + "fwd_lim" { + if { [info exists ::${mot}_encatts(fwd_enc_lim)] && [info exists ::${mot}_encatts(cnts_per_x)] } { + if {$sign < 0} { + return [expr {($rev_enc_lim_val - $enc_home_val) / $cnts_per_x_val + $home_val}] + } else { + return [expr {($fwd_enc_lim_val - $enc_home_val) / $cnts_per_x_val + $home_val}] + } + } else { + return 1 + } + } + "part" {return "instrument"} + "units" {return "xxx"} + } +} + +################################################################################ +# Parse all files and generate ::mn(matt) and ::controllers(cn) +foreach f $file_list { + parse_file $f $fhr $fhe +} + +################################################################################ +# GENERATE MOTOR CONFIGURATION FILE +puts $fhr "GENERATE MOTOR CONFIGURATIONS" +puts $fhe "GENERATE MOTOR CONFIGURATIONS" +puts $fhe "Required attributes: $REQ_ATTLIST" + +set fhmc [open "generated_motor_configuration.tcl" "w"] +# Write configuration file header and make asyncqueues +mk_cfg_header $fhmc +puts $fhmc "" +foreach mn [lsort -dictionary [array names motor_attcnt]] { + set encmot_attlist [lsort [array names ${mn}_encatts]] + set mot_attlist [lsort [concat [array names ${mn}_attarr] [array names ${mn}_encatts]]] + set num_encatts_defined [llength $encmot_attlist] + set posnum 0 + + # Decide if a motor configuration should be generated. + if [subset $ALL_ATTRIBUTES $mot_attlist] { + set mk_config 1 + } elseif [subset $REQ_ATTLIST $mot_attlist] { + set mk_config 1 + } else { + set mk_config 0 + } + + # Does this motor have an absolute encoder? + if {$num_encatts_defined > 0} { + set absenc 1 + } else { + set absenc 0 + } + + # Decide if a list missing attributes with default values should be written. + if [subset $ENCMOT_ATTLIST $mot_attlist] { + set mk_missing_atts 1 + } elseif [subset $MOT_ATTLIST $mot_attlist] { + set mk_missing_atts 1 + } else { + set mk_missing_atts 0 + } + + if [info exists ${mn}_encatts(cnts_per_x)] { + # Assume that the values of any attributes we don't recognise are encoder + # readings for a "posit" motor. + set posit_list {} + #TODO Sort posits by value can we take into acount if cnts_per_x is -ve or +ve? + set posit_nameval_list {} + foreach att [setdiff $mot_attlist $ALL_ATTRIBUTES] { + lappend posit_nameval_list "$att [set ${mn}_attarr($att)]" + } + if {[llength $posit_nameval_list] > 0} { + set posnum 0 + if { [set ${mn}_encatts(cnts_per_x)] > 0} { + set sorted_nv_list [join [lsort -integer -increasing -index 1 $posit_nameval_list]] + } else { + set sorted_nv_list [join [lsort -integer -decreasing -index 1 $posit_nameval_list]] + } + foreach {att v} $sorted_nv_list { + incr posnum + lappend posit_list "posit_${posnum} \$${mn}_$att" + # puts "posit_${posnum} \$${mn}_$att = $v" + } + } + } + + # Generate a motor configuration and/or a list of missing attributes. + if ${mk_config} { + mk_motconf $mn $fhmc $absenc $posnum posit_list + puts $fhr "Configured $mn" + incr MOTCFG_CNT + } else { + set missing_motatts [setdiff $MOT_ATTLIST $mot_attlist] + set missing_encatts [setdiff $ENC_ATTLIST $encmot_attlist] + set num_missing_motatts [llength $missing_motatts] + set num_missing_encatts [llength $missing_encatts] + if { $num_missing_encatts > 0 && $absenc} { + puts $fhe "$mn: found partial config for an axis with an absolute encoder," + puts $fhe " need: ([concat $missing_motatts $missing_encatts]) to configure the $mn motor with an encoder" + } elseif { $num_missing_motatts > 0 } { + puts $fhe "$mn: found partial config for an axis," + puts $fhe " need: ($missing_motatts) to configure $mn motor" + puts $fhe " also need: ($missing_encatts) if $mn has an encoder" + } + incr FAILED_MOTCFG_CNT + incr ERRCNT + if {$mk_missing_atts} { + set undef_atts [setdiff [lsort "absenchome $SICS_CFG_MOTATTLIST"] $mot_attlist] + foreach att $undef_atts { + set attval [gen_attval $mn $att] + if {$attval != "NOATT"} { + if [string is double $attval] { + set attval [format "%.4f" $attval] + } + lappend autogen_attarr($mn) "${mn}_$att,$attval" + } + } + } + } + if {[info exists ::${mn}_attarr(dflt_speed_steps)] && ![info exists ${mn}_attarr(speed)]} { + set speed_phys_units [ expr double([set ::${mn}_attarr(dflt_speed_steps)]) / abs([set ::${mn}_attarr(steps_per_x)]) ] + lappend ::autogen_attarr($mn) "${mn}_speed,[format "%.4f" $speed_phys_units]" + } + if {[info exists ::${mn}_attarr(dflt_accel_steps)] && ![info exists ${mn}_attarr(accel)]} { + set accel_phys_units [ expr double([set ::${mn}_attarr(dflt_accel_steps)]) / abs([set ::${mn}_attarr(steps_per_x)]) ] + lappend ::autogen_attarr($mn) "${mn}_accel,[format "%.4f" $accel_phys_units]" + } + if {[info exists ::${mn}_attarr(dflt_decel_steps)] && ![info exists ${mn}_attarr(decel)]} { + set decel_phys_units [ expr double([set ::${mn}_attarr(dflt_decel_steps)]) / abs([set ::${mn}_attarr(steps_per_x)]) ] + lappend ::autogen_attarr($mn) "${mn}_decel,[format "%.4f" $decel_phys_units]" + } +} + +# If there are any autogenerated attributes then write them to a file. +puts "" +if {[array size autogen_attarr] > 0} { + set fh [open "missing_attlist.csv" "w"] + puts "The attributes with default values needed to complete the configuration of the following motors has been written to missing_attlist.csv," + foreach n [lsort [array names autogen_attarr]] { + puts -nonewline "$n " + foreach attval [lsort $autogen_attarr($n)] { + puts $fh $attval + } + } + close $fh + puts "\n" + puts "Rename missing_attlist.csv and redo to generate a configuration file which also includes the motors listed above." + puts "Eg," + puts " mv missing_attlist.csv sicsmot_attlist.csv" + puts "" +} + +# The SICS init code calls motor_set_sobj_attributes. It can be redefined in +# the motor_configuration.tcl file. +puts $fhmc "proc motor_set_sobj_attributes {} {}" +puts stderr "Generated $MOTCFG_CNT motor driver configurations" +puts $fhr "Generated $MOTCFG_CNT motor driver configurations" +puts stderr "Found $FAILED_MOTCFG_CNT incomplete motor configurations. See ${scriptname}_errors.log and ${scriptname}_report.log" +puts $fhe "Found $FAILED_MOTCFG_CNT incomplete motor configurations" + +close $fhmc +close $fhr +close $fhe + +if {$ERRCNT > 0} { + puts stderr "Finished with $::ERRCNT errors" +} diff --git a/site_ansto/instrument/util/genmotconf_procs.tcl b/site_ansto/instrument/util/genmotconf_procs.tcl new file mode 100755 index 00000000..3869f450 --- /dev/null +++ b/site_ansto/instrument/util/genmotconf_procs.tcl @@ -0,0 +1,245 @@ + +# @brief Parse motor attribute file and make list of motor attributes and controllers +# @param fname Name of two column csv file of motor attribute names and values +# @param fhr Report log file-handle. +# @param fhe Error log file-handle. +# Requires The global ::ENC_ATTLIST +# Creates the following globals, +# ::mn(matt) is an array of motor attributes where mn = motor name and matt = the attribute name +# ::mn_encatts(matt) is an array of encoder attributes where mn = motor name and matt = an attributed from ENC_ATTLIST +# ::controllers(cn) Counts number of axes used on each controller, cn = controller name. +# ::motor_attcnt(mn) The keys of this array provide a list of motor names and each value is a count of attributes found for each motor. +proc parse_file {fname fhr fhe} { + puts $fhr "\nPARSE '$fname'" + set lcount 0 + set fh [open $fname "r"] + while {[gets $fh line] >= 0} { + incr lcount + foreach {name val} [split $line {,}] {} + if [regexp {(_?[a-zA-Z][a-zA-Z0-9]*[0-9]*)_([a-zA-Z0-9_]+)} $name rem mn matt] { + puts $fhr "Processing '$line'" + if {[lsearch $::ENC_ATTLIST $matt] != -1} { + puts $fhr "Add ::${mn}_encatts($matt) = $val" + set ::${mn}_encatts($matt) $val + } else { + puts $fhr "Add ::${mn}_attarr($matt) = $val" + set ::${mn}_attarr($matt) $val + } + incr ::motor_attcnt($mn) + if { $matt == "mc" } { + incr ::controllers($val) + } + } else { + incr ::ERRCNT + puts $fhe "Failed to match '$line'" + } + } + close $fh + puts -nonewline $fhr "CONTROLLER USAGE COUNT: " + foreach {cont} [lsort -dictionary [array names ::controllers]] { + set count $::controllers($cont) + puts -nonewline $fhr "$cont count=$count; " + } + puts $fhr "" + puts $fhr "PARSED $lcount lines in '$fname'; failed $::ERRCNT lines" + puts $fhe "$::ERRCNT ERRORS IN PARSE STAGE '$fname'. PROCESSED $lcount lines" +} + +# @brief Generate motor configuration file header and make asyncqueues +# @param fhmc Motor configuration file handle. +# Requires the following globals, +# ::argv0, ::argv, ::file_list, and ::controllers +proc mk_cfg_header {fhmc} { + puts $fhmc "#### SICS motor driver configuration ####" + puts $fhmc "# Generated by: $::argv0 $::argv" +# puts $fhmc "# Date: [clock format [clock seconds] -format %Y-%m-%dT%H:%M:%S]" + puts $fhmc "# Generated from the following files," + foreach f $::file_list { + incr fcntr + puts $fhmc "# file$fcntr: $f" + } + puts $fhmc "" + puts $fhmc "# Load motor driver configuration parameters" + puts $fhmc "set flist \[list\\" + foreach f $::file_list { + puts $fhmc " \{$f\}\\" + } + puts $fhmc " \]" +puts $fhmc { +foreach fattfile $flist { + if [catch { + set fattpath config/motors/$fattfile + set fh [open $fattpath RDONLY] + while {[gets $fh line] >= 0} { + eval "set [split $line {,}]" + } + close $fh + } msg] { + clientput ERROR: $msg + } +} + +} +puts $fhmc {set sim_mode [SplitReply [motor_simulation]]} + +# Setup addresses of Galil DMC2280 controllers. +puts $fhmc { +if {$sim_mode == true} { + set motor_driver_type asim +} else { + set motor_driver_type DMC2280 +} +} +puts $fhmc "if {\$sim_mode == false} \{" +foreach cont [lsort -dictionary [array names ::controllers]] { + set index [string toupper $cont] + puts $fhmc " [subst -nocommands {MakeAsyncQueue $cont DMC2280 [dict get \$::MOTOR_HOSTPORT $index HOST] [dict get \$::MOTOR_HOSTPORT $index PORT]}]" +} +puts $fhmc \} + +} + +# @brief Generate motor driver configuration +# @param mot Motor name +# @param fh Motor configuration file handle +# @param absEnc boolean, generate absolute encoder configuration if true. +# @param posnum Number of discrete positions +# @param posit_list Name of global list of name value pairs, "posit_n pos". Can be empty. +proc mk_motconf {mot fh absEnc posnum posit_list} { + set mc [set ::${mot}_attarr(mc)] + set axis [set ::${mot}_attarr(axis)] + set units ${mot}_units + set hardlowerlim ${mot}_rev_lim + set hardupperlim ${mot}_fwd_lim + set softlowerlim ${mot}_rev_lim + set softupperlim ${mot}_fwd_lim + set maxSpeed ${mot}_maxspeed + set maxAccel ${mot}_maxaccel + set maxDecel ${mot}_maxdecel + set stepsPerX ${mot}_steps_per_x + set cntsPerX ${mot}_cnts_per_x + set absEncHome ${mot}_absenchome + set home ${mot}_home + set part ${mot}_part + set long_name $mot + + puts $fh "# $mot configuration" + if [info exists ::${mot}_attarr(description)] { + puts $fh "# [set ::${mot}_attarr(description)]" + } + if [info exists ::${mot}_attarr(axis_number)] { + puts $fh "# Axis number [set ::${mot}_attarr(axis_number)]" + } + puts $fh "Motor $mot \$motor_driver_type \[params\\" + puts $fh " asyncqueue $mc\\" + puts $fh " axis $axis\\" + puts $fh " units \$$units\\" + puts $fh " hardlowerlim \$$hardlowerlim\\" + puts $fh " hardupperlim \$$hardupperlim\\" + puts $fh " maxSpeed \$$maxSpeed\\" + puts $fh " maxAccel \$$maxAccel\\" + puts $fh " maxDecel \$$maxDecel\\" + puts $fh " stepsPerX \$$stepsPerX\\" + puts $fh " posit_count $posnum\\" + foreach positline $::posit_list { + puts $fh " $positline\\" + } + if {$absEnc} { + puts $fh " absEnc 1\\" + puts $fh " absEncHome \$$absEncHome\\" + puts $fh " cntsPerX \$$cntsPerX\]" + } else { + puts $fh " absEnc 0\]" + } + puts $fh "$mot softlowerlim \$$softlowerlim" + puts $fh "$mot softupperlim \$$softupperlim" + puts $fh "$mot home \$$home" + puts $fh "$mot part \$$part" + puts $fh "$mot long_name $long_name" + if [info exists ::${mot}_attarr(dflt_speed_steps)] { + puts $fh "$mot speed \$${mot}_speed" + } + if [info exists ::${mot}_attarr(dflt_accel_steps)] { + puts $fh "$mot accel \$${mot}_accel" + } + if [info exists ::${mot}_attarr(dflt_decel_steps)] { + puts $fh "$mot decel \$${mot}_decel" + } + puts $fh "" +} + + + +################################################################################ +# UTILITY FUNCTIONS +################################################################################ + +# @brief Difference between sets A and B, ie A\B +# Invalid sets are allowed. Doesn't check for repetition. +# @return list of elements in A but not in B +proc setdiff {A B} { + set diff {} + foreach e $A { + if { [lsearch $B $e] == -1 } { + lappend diff $e + } + } + return $diff +} + +# @brief Tests if A is subset of B +# The sets must be sorted +# Doesn't check if sets are valid, eg repetition is allowed. +proc subset {A B} { + set Alen [llength $A] + set Blen [llength $B] + if { $Alen > $Blen } { + return false + } + set Aend [expr {$Alen - 1}] + set Bend [expr {$Blen - 1}] + set asi 0 + set aei 0 + set bsi 0 + set bei 0 + while { $asi <= [expr {$Aend - $aei}] } { +# puts "A = [lrange $A $asi end-$aei]" + set firstmatch false + set lastmatch false + while { $bsi <= [expr {$Bend - $bei}] } { +# puts " B = [lrange $B $bsi end-$bei]" + if { $firstmatch == false } { + set aval [lindex $A $asi] + set bval [lindex $B $bsi] + if { $aval == $bval} { + set firstmatch true +# puts " firstmatch = $firstmatch" + } elseif {$aval < $bval} { + return false + } + incr bsi + } + if { $lastmatch == false } { + set aval [lindex $A end-$aei] + set bval [lindex $B end-$bei] + if { $aval == $bval } { + set lastmatch true +# puts " lastmatch = $lastmatch" + } elseif {$aval > $bval} { + return false + } + incr bei + } + if { ($firstmatch == true) && ($lastmatch == true) } { + break + } + } + if { ($firstmatch == false) && ($lastmatch == false) } { + return false + } + incr asi + incr aei + } + + return true +} diff --git a/site_ansto/instrument/util/utility.tcl b/site_ansto/instrument/util/utility.tcl index 1722bc99..556e872a 100644 --- a/site_ansto/instrument/util/utility.tcl +++ b/site_ansto/instrument/util/utility.tcl @@ -197,7 +197,7 @@ sicslist setatt $setpoint_script mutable true ## TODO put all the utility macros in the utility namespace namespace eval utility { - variable instrument_names [list echidna wombat kowari quokka platypus pelican taipan lyrebird kookaburra] + variable instrument_names [list bilby dingo echidna emu kookaburra kowari lyrebird pelican platypus quokka taipan wombat] variable sics_port set base_port 60000 set currbase $base_port diff --git a/site_ansto/lakeshore340driv.c b/site_ansto/lakeshore340driv.c index 287b67ef..f462c03c 100644 --- a/site_ansto/lakeshore340driv.c +++ b/site_ansto/lakeshore340driv.c @@ -1,10 +1,10 @@ /*-------------------------------------------------------------------------- - L A K E S H O R E 3 4 0 D R I V + L A K E S H O R E 3 4 0 D R I V This file contains the implementation of a driver for the Lakeshore 340 Temperature controller. - + Mark Koennecke, Juli 1997 Mark Lesha, January 2006 (based on ITC4 code) @@ -50,7 +50,7 @@ typedef struct __EVDriver *pEVDriver; -#include +#include /* Do we need these ? #include #include @@ -65,8 +65,8 @@ pEVDriver CreateLAKESHORE340Driver(int argc, char *argv[]); int ConfigLAKESHORE340(pEVDriver self); - - + + /*-----------------------------------------------------------------------*/ typedef struct { pLAKESHORE340 pData; @@ -85,12 +85,12 @@ { pLAKESHORE340Driv pMe = NULL; int iRet; - + assert(self); pMe = (pLAKESHORE340Driv)self->pPrivate; assert(pMe); - - iRet = LAKESHORE340_Read(&pMe->pData,fPos); + + iRet = LAKESHORE340_Read(&pMe->pData,fPos); if(iRet <= 0 ) { pMe->iLastError = iRet; @@ -103,13 +103,13 @@ return 0; } return 1; - } + } /*----------------------------------------------------------------------------*/ static int LAKESHORE340Run(pEVDriver self, float fVal) { pLAKESHORE340Driv pMe = NULL; int iRet; - + assert(self); pMe = (pLAKESHORE340Driv )self->pPrivate; assert(pMe); @@ -126,7 +126,7 @@ static int LAKESHORE340Error(pEVDriver self, int *iCode, char *error, int iErrLen) { pLAKESHORE340Driv pMe = NULL; - + assert(self); pMe = (pLAKESHORE340Driv)self->pPrivate; assert(pMe); @@ -138,7 +138,7 @@ } else { - LAKESHORE340_ErrorTxt(&pMe->pData,pMe->iLastError,error,iErrLen); + LAKESHORE340_ErrorTxt(&pMe->pData,pMe->iLastError,error,iErrLen); } return 1; } @@ -147,7 +147,7 @@ { pLAKESHORE340Driv pMe = NULL; int iRet; - + assert(self); pMe = (pLAKESHORE340Driv )self->pPrivate; assert(pMe); @@ -160,13 +160,13 @@ } return 1; - } + } /*--------------------------------------------------------------------------*/ static int LAKESHORE340Init(pEVDriver self) { pLAKESHORE340Driv pMe = NULL; int iRet; - + assert(self); pMe = (pLAKESHORE340Driv )self->pPrivate; assert(pMe); @@ -183,28 +183,28 @@ { pMe->iLastError = iRet; return 0; - } + } } return 1; - } + } /*--------------------------------------------------------------------------*/ static int LAKESHORE340Close(pEVDriver self) { pLAKESHORE340Driv pMe = NULL; - + assert(self); pMe = (pLAKESHORE340Driv )self->pPrivate; assert(pMe); LAKESHORE340_Close(&pMe->pData); return 1; - } + } /*---------------------------------------------------------------------------*/ static int LAKESHORE340Fix(pEVDriver self, int iError) { pLAKESHORE340Driv pMe = NULL; int iRet; - + assert(self); pMe = (pLAKESHORE340Driv )self->pPrivate; assert(pMe); @@ -230,11 +230,11 @@ if(iRet) { return DEVREDO; - } + } else { return DEVFAULT; - } + } break; /* handable protocoll errors */ case EL734__BAD_TMO: @@ -243,19 +243,19 @@ case -501: /* Bad_COM */ return DEVREDO; case -504: /* Badly formatted */ - return DEVREDO; + return DEVREDO; default: return DEVFAULT; - break; + break; } return DEVFAULT; } - + /*--------------------------------------------------------------------------*/ /* static int LAKESHORE340Halt(pEVDriver *self) { assert(self); - + return 1; } */ @@ -263,54 +263,57 @@ void KillLAKESHORE340(void *pData) { pLAKESHORE340Driv pMe = NULL; - + pMe = (pLAKESHORE340Driv)pData; assert(pMe); - + if(pMe->pHost) { free(pMe->pHost); } free(pMe); - } + } /*------------------------------------------------------------------------*/ pEVDriver CreateLAKESHORE340Driver(int argc, char *argv[]) { pEVDriver pNew = NULL; pLAKESHORE340Driv pSim = NULL; - + /* check for arguments */ if(argc < 3) { return NULL; } - + pNew = CreateEVDriver(argc,argv); - pSim = (pLAKESHORE340Driv)malloc(sizeof(LAKESHORE340Driv)); - memset(pSim,0,sizeof(LAKESHORE340Driv)); - if(!pNew || !pSim) - { + if (!pNew) { return NULL; } + pSim = (pLAKESHORE340Driv)malloc(sizeof(LAKESHORE340Driv)); + if (!pSim) { + free(pNew); + return NULL; + } + memset(pSim,0,sizeof(LAKESHORE340Driv)); pNew->pPrivate = pSim; pNew->KillPrivate = KillLAKESHORE340; - + /* initalise pLAKESHORE340Driver */ pSim->iControl = atoi(argv[2]); pSim->iRead = atoi(argv[1]); pSim->iLastError = 0; pSim->iTmo = 10; - + /* The LAKESHORE340 doesn't require divisors or multipliers and they are always forced to 1.0 */ pSim->fDiv = 1.0; pSim->fMult = 1.0; - + pSim->pHost = strdup(argv[0]); pSim->iPort = 0; pSim->iChannel = 0; - - + + /* initialise function pointers */ pNew->SetValue = LAKESHORE340Run; pNew->GetValue = GetLAKESHORE340Pos; @@ -319,20 +322,20 @@ pNew->TryFixIt = LAKESHORE340Fix; pNew->Init = LAKESHORE340Init; pNew->Close = LAKESHORE340Close; - - return pNew; - } + + return pNew; + } /*--------------------------------------------------------------------------*/ int ConfigLAKESHORE340(pEVDriver self) { pLAKESHORE340Driv pMe = NULL; int iRet; - + assert(self); pMe = (pLAKESHORE340Driv )self->pPrivate; assert(pMe); - iRet = LAKESHORE340_Config(&pMe->pData, pMe->iTmo, pMe->iRead, + iRet = LAKESHORE340_Config(&pMe->pData, pMe->iTmo, pMe->iRead, pMe->iControl,pMe->fDiv,pMe->fMult); if(iRet < 0) { @@ -345,17 +348,17 @@ int SetSensorLAKESHORE340(pEVDriver self, int iSensor) { pLAKESHORE340Driv pMe = NULL; - + assert(self); pMe = (pLAKESHORE340Driv )self->pPrivate; assert(pMe); - + /* The LAKESHORE340 allows bath temp, external temp and tank temp to be read so allow iRead=1 to 4 for A,B,C,D respectively. */ if( (iSensor < 1) || (iSensor > 4) ) { return 0; - } + } pMe->iRead = iSensor; pMe->pData->iRead = iSensor; return 1; @@ -364,17 +367,17 @@ int SetControlLAKESHORE340(pEVDriver self, int iSensor) { pLAKESHORE340Driv pMe = NULL; - + assert(self); pMe = (pLAKESHORE340Driv )self->pPrivate; assert(pMe); - /* For the LAKESHORE340 allow selection of internal or external control - where iControl==1 to 4 for A,B,C,D respectively. */ + /* For the LAKESHORE340 allow selection of internal or external control + where iControl==1 to 4 for A,B,C,D respectively. */ if( (iSensor < 1) || (iSensor > 4) ) { return 0; - } + } pMe->iControl = iSensor; pMe->pData->iControl = iSensor; return 1; @@ -383,7 +386,7 @@ int SetTMOLAKESHORE340(pEVDriver self, int iSensor) { pLAKESHORE340Driv pMe = NULL; - + assert(self); pMe = (pLAKESHORE340Driv )self->pPrivate; assert(pMe); @@ -391,7 +394,7 @@ if(iSensor < 10) { return 0; - } + } pMe->iTmo = iSensor; return 1; } @@ -399,7 +402,7 @@ int GetControlLAKESHORE340(pEVDriver self) { pLAKESHORE340Driv pMe = NULL; - + assert(self); pMe = (pLAKESHORE340Driv )self->pPrivate; assert(pMe); @@ -410,7 +413,7 @@ int GetSensorLAKESHORE340(pEVDriver self) { pLAKESHORE340Driv pMe = NULL; - + assert(self); pMe = (pLAKESHORE340Driv )self->pPrivate; assert(pMe); @@ -421,7 +424,7 @@ int GetTMOLAKESHORE340(pEVDriver self) { pLAKESHORE340Driv pMe = NULL; - + assert(self); pMe = (pLAKESHORE340Driv )self->pPrivate; assert(pMe); @@ -432,7 +435,7 @@ float GetDivisorLAKESHORE340(pEVDriver self) { pLAKESHORE340Driv pMe = NULL; - + assert(self); pMe = (pLAKESHORE340Driv )self->pPrivate; assert(pMe); @@ -443,12 +446,12 @@ int SetDivisorLAKESHORE340(pEVDriver self, float fDiv) { pLAKESHORE340Driv pMe = NULL; - + assert(self); pMe = (pLAKESHORE340Driv )self->pPrivate; assert(pMe); - /* The LAKESHORE340 doesn't need divisor, force to 1.0 */ + /* The LAKESHORE340 doesn't need divisor, force to 1.0 */ pMe->fDiv = 1.0; /* fDiv */; return 1; } @@ -456,7 +459,7 @@ float GetMultLAKESHORE340(pEVDriver self) { pLAKESHORE340Driv pMe = NULL; - + assert(self); pMe = (pLAKESHORE340Driv )self->pPrivate; assert(pMe); @@ -467,13 +470,13 @@ int SetMultLAKESHORE340(pEVDriver self, float fDiv) { pLAKESHORE340Driv pMe = NULL; - + assert(self); pMe = (pLAKESHORE340Driv )self->pPrivate; assert(pMe); - - /* The LAKESHORE340 doesn't need multiplier, force to 1.0 */ + + /* The LAKESHORE340 doesn't need multiplier, force to 1.0 */ pMe->fMult = 1.0; /* fDiv */; return 1; } - + diff --git a/site_ansto/motor_dmc2280.c b/site_ansto/motor_dmc2280.c index 20628b9f..0b505f41 100644 --- a/site_ansto/motor_dmc2280.c +++ b/site_ansto/motor_dmc2280.c @@ -46,7 +46,7 @@ extern double DoubleTime(void); * with valid values. * \see getDMCSetting */ -enum dmcsetting {dmcspeed, dmcacceleration, dmcdeceleration}; +typedef enum report_type {eReportMotion, eReportIdle, eReportFinal} ReportType; enum commandtype {CMD_RUN=1, CMD_HALT=2}; typedef struct __MoDriv DMC2280Driv, *pDMC2280Driv; @@ -196,6 +196,9 @@ struct __MoDriv { double lastPosition; /**< Position at last position check */ int lastSteps; int lastCounts; + double lastReportTime; + int lastReportedCounts; + int lastReportedSteps; double origPosition; /**< Position at motor start */ double origTime; /**< Time at motor start */ int origSteps; @@ -271,6 +274,14 @@ struct __MoDriv { double S_r; bool doTracking; TrackEntryBuffer *trackHead, *trackTail; + bool doReportMotion; /**< flag for reporting motion when not driving */ + bool doOscillate; /**< flag for motor oscillation */ + bool oscillate_up; /**< next oscillation move is to high position */ + bool oscillate_init; /**< initial move is not counted */ + int oscillate_count; /**< number of moves to make or -1 for continuous */ + int oscillate_counter; /**< number of moves made - half-oscillations */ + double oscillate_low; /**< soft position at low end */ + double oscillate_high; /**< soft position at high end */ }; int DMC2280MotionControl = 1; /* defaults to enabled */ @@ -361,6 +372,64 @@ static double getMotorParam(pDMC2280Driv self, char *param) { return fParam; } +static bool parseNumber(const char *str, double *pNumber) { + char *endPtr; + double fNumber; + if (!pNumber) + return false; + fNumber = strtod(str, &endPtr); + if (endPtr == str || errno == ERANGE) + return false; + /* Reject Infinity and Not a Number (NaN) */ + switch (fpclassify(fNumber)) { + case FP_ZERO: + case FP_NORMAL: + break; + default: + return false; + } + *pNumber = fNumber; + return true; +} + +static bool getHardFromSoft(pDMC2280Driv self, SConnection *pCon, double fSoft, double *pHard) { + float fLower, fUpper, fZero, fSign, fLim; + double fHard; + + MotorGetPar(self->pMot, "softlowerlim", &fLower); + MotorGetPar(self->pMot, "softupperlim", &fUpper); + MotorGetPar(self->pMot, "softzero", &fZero); + MotorGetPar(self->pMot, "sign", &fSign); + if (fSoft > fUpper) { + if (pCon) + SCPrintf(pCon, eWarning, "%g violates upper software limit %g on %s", + fSoft, fUpper, self->name); + return false; + } + if (fSoft < fLower) { + if (pCon) + SCPrintf(pCon, eWarning, "%g violates lower software limit %g on %s", + fSoft, fLower, self->name); + return false; + } + fHard = fSoft; + fHard += fZero; + fHard *= fSign; + if (fHard > self->fUpper) { + if (pCon) + SCPrintf(pCon, eWarning, "%g violates upper hardware limit %g (%g) on %s", + fSoft, self->fUpper * fSign + fZero, self->fUpper, self->name); + return false; + } else if (fHard < self->fLower) { + if (pCon) + SCPrintf(pCon, eWarning, "%g violates lower hardware limit %g (%g) on %s", + fSoft, self->fLower * fSign + fZero, self->fLower, self->name); + return false; + } + *pHard = fHard; + return true; +} + static void TrackingRelease(pDMC2280Driv self) { while (self->trackHead) { TrackEntryBuffer *victim; @@ -1084,18 +1153,60 @@ static void set_lastMotion(pDMC2280Driv self, int steps, int counts) { gettimeofday(&(self->time_lastPos_set), NULL); } -static void report_motion(pDMC2280Driv self) { - SConnection *pDumCon; - MotCallback sCall; +/* + * TODO: idle and final reporting + * when final, always report MOTDRIVE and MOTEND + * when idle, if time and motion > threshold, report MOTDRIVE and MOTEND + * when neither, if time and motion > threshold, report MOTDRIVE but not MOTEND + */ +static bool report_motion(pDMC2280Driv self, ReportType reportType) { + double current_time; + bool doMotDrive = false; + bool doMotEnd = false; + if (self->pMot == NULL) self->pMot = FindMotor(pServ->pSics, self->name); assert(self->pMot); - pDumCon = SCCreateDummyConnection(pServ->pSics); - MotorGetSoftPosition(self->pMot,pDumCon,&sCall.fVal); - SCDeleteConnection(pDumCon); - sCall.pName = self->pMot->name; - InvokeCallBack(self->pMot->pCall, MOTDRIVE, &sCall); - InvokeCallBack(self->pMot->pCall, MOTEND, &sCall); + current_time = DoubleTime(); + if (reportType == eReportFinal) { + doMotDrive = true; + doMotEnd = true; + } else { + double skip_time; + skip_time = 0.001 * getMotorParam(self, "movecount"); + if (self->lastReportTime + skip_time <= current_time) { + long lDelta; + if (self->abs_encoder) + lDelta = fabs(self->currCounts - self->lastReportedCounts); + else + lDelta = fabs(self->currSteps - self->lastReportedSteps); + if (reportType == eReportIdle) { + if (lDelta > 10) { + doMotDrive = true; + doMotEnd = true; + } + } else + doMotDrive = true; + } + } + if (doMotDrive || doMotEnd) { + SConnection *pDumCon; + MotCallback sCall; + pDumCon = SCCreateDummyConnection(pServ->pSics); + MotorGetSoftPosition(self->pMot, pDumCon, &sCall.fVal); + SCDeleteConnection(pDumCon); + sCall.pName = self->pMot->name; + if (doMotDrive) { + InvokeCallBack(self->pMot->pCall, MOTDRIVE, &sCall); + if (doMotEnd) + InvokeCallBack(self->pMot->pCall, MOTEND, &sCall); + self->lastReportedCounts = self->currCounts; + self->lastReportedSteps = self->currSteps; + self->lastReportTime = current_time; + return true; + } + } + return false; } /** \brief Reads absolute encoder. @@ -1553,6 +1664,8 @@ static int rspStatus(pDMC2280Driv self, const char* text) { int iRet, iFlags; int iSteps, iCounts; int iTIzero, iTIone, iIOByte, iStopCode, iXQ0, iBG; + char cmd[CMDLEN]; + iRet = sscanf(text, "%d %d %d %d %d %d %d %d", &iSteps, &iCounts, &iFlags, &iBG, &iStopCode, &iTIzero, &iTIone, &iXQ0); @@ -1634,8 +1747,13 @@ static int rspStatus(pDMC2280Driv self, const char* text) { self->ampError = !(1 & (iIOByte >> (self->axisLabel - 'E'))); #endif self->runError = iBG < 0 ? iBG : 0; - if (iBG < 0) + if (iBG < 0) { snprintf(self->dmc2280Error, CMDLEN, "MOTOR CONTROLLER RUN ERROR: %d", iBG); + if (self->protocol == 3) { + snprintf(cmd, CMDLEN, "RUN%cAK=1", self->axisLabel); + DMC_Send(self, cmd); + } + } self->threadError = self->thread0 < 0; self->moving = iBG > 0; if (self->protocol == 3 && !(self->variables & VAR_STP)) { @@ -1685,9 +1803,14 @@ static int rspVars(pDMC2280Driv self, const char* text) { static int rspPoll(pDMC2280Driv self, const char* text) { int iReply = atoi(text); - if (iReply < 0) + char cmd[CMDLEN]; + + if (iReply < 0) { snprintf(self->dmc2280Error, CMDLEN, "MOTOR CONTROLLER REQ ERROR: %d", iReply); + snprintf(cmd, CMDLEN, "RSP%cAK=1", self->axisLabel); + DMC_Send(self, cmd); + } return iReply; } @@ -1733,6 +1856,7 @@ static void DMCState_MotorOn(pDMC2280Driv self, pEvtEvent event); static void DMCState_Moving(pDMC2280Driv self, pEvtEvent event); static void DMCState_StepMove(pDMC2280Driv self, pEvtEvent event); static void DMCState_SimpleMove(pDMC2280Driv self, pEvtEvent event); +static void DMCState_Oscillate(pDMC2280Driv self, pEvtEvent event); static void DMCState_BacklashStart(pDMC2280Driv self, pEvtEvent event); static void DMCState_BacklashCont(pDMC2280Driv self, pEvtEvent event); static void DMCState_CreepStart(pDMC2280Driv self, pEvtEvent event); @@ -1751,6 +1875,7 @@ static char* state_name(StateFunc func) { if (func == DMCState_Moving) return "DMCState_Moving"; if (func == DMCState_StepMove) return "DMCState_StepMove"; if (func == DMCState_SimpleMove) return "DMCState_SimpleMove"; + if (func == DMCState_Oscillate) return "DMCState_Oscillate"; if (func == DMCState_BacklashStart) return "DMCState_BacklashStart"; if (func == DMCState_BacklashCont) return "DMCState_BacklashCont"; if (func == DMCState_CreepStart) return "DMCState_CreepStart"; @@ -2250,7 +2375,6 @@ static void DMCState_Idle(pDMC2280Driv self, pEvtEvent event) { pAsyncTxn pCmd = event->event.msg.cmd; if (self->subState == 1) { /* Status Response */ int iRet; - long lDelta; iRet = rspStatus(self, pCmd->inp_buf); if (iRet == 0) break; @@ -2261,13 +2385,11 @@ static void DMCState_Idle(pDMC2280Driv self, pEvtEvent event) { return; } /* if the motor moved, update any observers */ - if (self->abs_encoder) - lDelta = fabs(self->currCounts - self->lastCounts); - else - lDelta = fabs(self->currSteps - self->lastSteps); - if (lDelta > 10) { - set_lastMotion(self, self->currSteps, self->currCounts); - report_motion(self); + if (self->doReportMotion) { + (void) report_motion(self, eReportFinal); + self->doReportMotion = false; + } else { + (void) report_motion(self, eReportIdle); } if (trace_switches || self->debug) DMC_SetTimer(self, self->motorPollFast); @@ -2511,6 +2633,10 @@ static void DMCState_MotorOn(pDMC2280Driv self, pEvtEvent event) { if (self->trackHead) TrackingRelease(self); self->myNextState = NULL; + if (self->doOscillate) { + change_state(self, DMCState_Oscillate); + return; + } if (self->backlash_offset != 0) { change_state(self, DMCState_BacklashStart); return; @@ -3060,6 +3186,88 @@ static void DMCState_CreepCont(pDMC2280Driv self, pEvtEvent event) { return; } +/* + * This state oscillates the motor between two positions + */ +static void DMCState_Oscillate(pDMC2280Driv self, pEvtEvent event) { + double target; + int absolute; + + switch (event->event_type) { + case eStateEvent: + self->myNextState = NULL; + /* handle termination conditions (e.g. count) */ + if (self->oscillate_count > 0 && self->oscillate_counter >= self->oscillate_count) + self->doOscillate = false; + if (!self->doOscillate) { + (void) report_motion(self, eReportFinal); + change_state(self, DMCState_OffTimer); /* TODO: check this is OK */ + return; + } + if (self->oscillate_up) { + double fHard; + if (getHardFromSoft(self, NULL, self->oscillate_high, &fHard)) + self->fTarget = fHard; + self->oscillate_up = false; + } else { + double fHard; + if (getHardFromSoft(self, NULL, self->oscillate_low, &fHard)) + self->fTarget = fHard; + self->oscillate_up = true; + } + /* TODO: set timer for optional pause */ + /* Note: fallthrough is intentional */ + case eTimerEvent: + target = self->fTarget; + self->preseek = 0; + absolute = motCreep(self, target); + self->doSettle = false; + cmdPosition(self, absolute); + return; + case eMessageEvent: + if (self->run_flag != 0) { + change_state(self, DMCState_MotorHalt); + return; + } + /* set the next state after this move */ + self->myNextState = DMCState_Oscillate; + if (!self->oscillate_init) + self->oscillate_counter++; + self->oscillate_init = false; + change_state(self, DMCState_StepMove); + return; + case eCommandEvent: + switch (event->event.cmd.cmd_type) { + case CMD_RUN: + /* TODO: FIXME RUN command while running */ + if (self->driver_status == HWIdle) + self->driver_status = HWBusy; + self->run_flag = 1; + if (self->waitResponse == false) { + change_state(self, DMCState_MotorHalt); + } + return; + case CMD_HALT: + /* handle halt command, send message */ + self->run_flag = -1; + if (self->waitResponse == false) { + change_state(self, DMCState_MotorHalt); + } + return; + } + break; + case eTimeoutEvent: + strncpy(self->lastCmd, event->event.msg.cmd->out_buf, CMDLEN); + self->errorCode = MOTCMDTMO; + self->driver_status = HWFault; + change_state(self, DMCState_MotorHalt); + return; + } + unhandled_event(self, event); + self->errorCode = STATEERROR; + change_state(self, DMCState_Error); + return; +} /* * This state moves the motor from its current position to the current destination * set by PA (or PR) by the caller in myNextState. @@ -3145,6 +3353,8 @@ static void DMCState_StepMove(pDMC2280Driv self, pEvtEvent event) { ent->Counts = self->currCounts; } } + if (self->doReportMotion) + (void) report_motion(self, eReportMotion); /* if the status response can be handled here, return */ if (motorHandleStatus(self)) return; @@ -3807,6 +4017,8 @@ static int DMC2280Run(void *pData,float fValue){ /* Only do it if it is within our hard limits */ if (fValue >= self->fLower && fValue <= self->fUpper) { self->fTarget = fValue; + self->doOscillate = false; + self->doReportMotion = false; state_cmd_execute(self, CMD_RUN); return 1; } @@ -4133,6 +4345,14 @@ static int DMC2280GetPar(void *pData, char *name, *fValue = self->airPollTimer; return 1; } + if(strcasecmp(name,"posit_count") == 0) { + *fValue = self->posit_count; + return 1; + } + if(strcasecmp(name,"motorhome") == 0) { + *fValue = self->motorHome; + return 1; + } if (self->posit_count > 0) { if (strncasecmp(name, "posit_", 6) == 0 && isdigit(name[6])) { int index; @@ -4562,6 +4782,23 @@ static int DMC2280SetPar(void *pData, SConnection *pCon, return 1; } } + if(strcasecmp(name, "motorhome") == 0) { + /* Debug Managers only */ + if(!SCMatchRights(pCon,usInternal)) + return 1; + else { + if ( (self->fLower - newValue) > FLT_EPSILON) { + snprintf(pError, ERRLEN,"WARNING:'%s %s' is lower than the lower limit %f", self->name, HOME, self->fLower); + SCWrite(pCon, pError, eWarning); + } + if ( (newValue - self->fUpper) > FLT_EPSILON) { + snprintf(pError, ERRLEN,"WARNING:'%s %s' is greater than the upper limit %f", self->name, HOME, self->fUpper); + SCWrite(pCon, pError, eWarning); + } + self->motorHome = newValue; + return 1; + } + } if (self->posit_count > 0) { int index; @@ -4587,6 +4824,7 @@ static void DMC2280StrList(pDMC2280Driv self, char *name, SConnection *pCon){ SCPrintf(pCon, eStatus, "%s.part = %s\n", name, self->part); SCPrintf(pCon, eStatus, "%s.long_name = %s\n", name, self->long_name); SCPrintf(pCon, eStatus, "%s.axis = %c\n", name, self->axisLabel); + SCPrintf(pCon, eStatus, "%s.legacy_fsm = %s\n", name, self->legacy_fsm ? "ON" : "OFF"); if (self->encoderAxis) { SCPrintf(pCon, eStatus, "%s.encoderAxis = %c\n", name, self->encoderAxis); } @@ -4637,7 +4875,6 @@ static void DMC2280List(void *pData, char *name, SConnection *pCon){ SCPrintf(pCon, eStatus, "%s.Blockage_Fail = %d\n", name, self->blockage_fail); SCPrintf(pCon, eStatus, "%s.Backlash_offset = %f\n", name, self->backlash_offset); SCPrintf(pCon, eStatus, "%s.Protocol = %d\n", name, self->protocol); - SCPrintf(pCon, eStatus, "%s.Legacy_FSM = %s\n", name, self->legacy_fsm ? "ON" : "OFF"); SCPrintf(pCon, eStatus, "%s.absEncoder = %d\n", name, self->abs_encoder); if (self->abs_encoder) { SCPrintf(pCon, eStatus, "%s.absEncHome = %d\n", name, self->absEncHome); @@ -5262,86 +5499,204 @@ int DMC2280Action(SConnection *pCon, SicsInterp *pSics, void *pData, } return 1; } - else if(strcasecmp("run", argv[1]) == 0) { + else if(strcasecmp("oscillate_count", argv[1]) == 0) { + if (argc > 2) + self->oscillate_count = atoi(argv[2]); + else + SCPrintf(pCon, eValue, "%s.oscillate_count = %d", self->name, self->oscillate_count); + return 1; + } + else if (strcasecmp("oscillate_high", argv[1]) == 0) { + double fSoft = 0.0; + double fHard = 0.0; if (argc > 2) { - float fLower, fUpper, fZero, fSign, fFixed, fLim; - double fSoft; - char *endPtr; - errno = 0; - fSoft = strtod(argv[2], &endPtr); - if (endPtr == argv[2] || errno == ERANGE) { - self->errorCode = BADPAR; - SCPrintf(pCon, eWarning, "Motor %s bad run parameter %s", self->name, argv[2]); + if (parseNumber(argv[2], &fSoft) && + getHardFromSoft(self, pCon, fSoft, &fHard)) + self->oscillate_high = fSoft; + } + else + SCPrintf(pCon, eValue, "%s.oscillate_high = %g", self->name, self->oscillate_high); + return 1; + } + else if (strcasecmp("oscillate_low", argv[1]) == 0) { + double fSoft = 0.0; + double fHard = 0.0; + if (argc > 2) { + if (parseNumber(argv[2], &fSoft) && + getHardFromSoft(self, pCon, fSoft, &fHard)) + self->oscillate_low = fSoft; + } + else + SCPrintf(pCon, eValue, "%s.oscillate_low = %g", self->name, self->oscillate_low); + return 1; + } + else if (strcasecmp("oscillate_counter", argv[1]) == 0) { + SCPrintf(pCon, eValue, "%s.oscillate_counter = %d", self->name, self->oscillate_counter); + } + else if(strcasecmp("osc", argv[1]) == 0 || strcasecmp("oscillate", argv[1]) == 0) { + if (argc > 2) { + if (strcasecmp("list", argv[2]) == 0) { + /* TODO: list the osc params */ + SCPrintf(pCon, eValue, "%s.oscillate_count = %d", self->name, self->oscillate_count); + SCPrintf(pCon, eValue, "%s.oscillate_counter = %d", self->name, self->oscillate_counter); + SCPrintf(pCon, eValue, "%s.oscillate_low = %g", self->name, self->oscillate_low); + SCPrintf(pCon, eValue, "%s.oscillate_high = %g", self->name, self->oscillate_high); return 1; } - /* Reject Infinity and Not a Number (NaN) */ - switch (fpclassify(fSoft)) { - case FP_ZERO: - case FP_NORMAL: - break; - default: - self->errorCode = BADPAR; - SCPrintf(pCon, eWarning, "Motor %s bad run parameter %s", self->name, argv[2]); + if (strcasecmp("start", argv[2]) == 0) { + float fFixed; + double fHard; + MotorGetPar(self->pMot, "fixed", &fFixed); + if (fFixed >= 0) { + SCPrintf(pCon, eWarning, "Motor %s is Fixed", self->name); return 1; + } + if (!getHardFromSoft(self, pCon, self->oscillate_low, &fHard)) { + SCPrintf(pCon, eWarning, "Oscillate low point is in error"); + return 1; + } + if (!getHardFromSoft(self, pCon, self->oscillate_high, &fHard)) { + SCPrintf(pCon, eWarning, "Oscillate high point is in error"); + return 1; + } + if (fabs(self->oscillate_high - motPosit(self)) < fabs(self->oscillate_low - motPosit(self))) + self->oscillate_up = true; + else + self->oscillate_up = false; + self->doOscillate = true; + self->doReportMotion = true; + self->oscillate_init = true; + self->oscillate_counter = 0; + state_cmd_execute(self, CMD_RUN); + return 1; } - MotorGetPar(self->pMot, "softlowerlim", &fLower); - MotorGetPar(self->pMot, "softupperlim", &fUpper); - MotorGetPar(self->pMot, "softzero", &fZero); - MotorGetPar(self->pMot, "sign", &fSign); - MotorGetPar(self->pMot, "fixed", &fFixed); - if (fFixed >= 0) { - SCPrintf(pCon, eWarning, "Motor %s is Fixed", self->name); - } else if (fSoft > fUpper) { - SCPrintf(pCon, eWarning, "%g violates upper software limit %g on %s", - fSoft, fUpper, self->name); - } else if (fSoft < fLower) { - SCPrintf(pCon, eWarning, "%g violates lower software limit %g on %s", - fSoft, fLower, self->name); - } else { - double fHard = fSoft; - fHard += fZero; - fHard *= fSign; - if (fHard > self->fUpper) { - SCPrintf(pCon, eWarning, "%g violates upper hardware limit %g (%g) on %s", - fSoft, self->fUpper * fSign + fZero, self->fUpper, self->name); - } else if (fHard < self->fLower) { - SCPrintf(pCon, eWarning, "%g violates lower hardware limit %g (%g) on %s", - fSoft, self->fLower * fSign + fZero, self->fLower, self->name); + if (strcasecmp("stop", argv[2]) == 0) { + self->doOscillate = false; + return 1; + } + if (strcasecmp("halt", argv[2]) == 0) { + self->doOscillate = false; + state_cmd_execute(self, CMD_HALT); + return 1; + } + } else { + SCPrintf(pCon, eStatus, "%s.oscillation = %s", self->name, self->doOscillate ? "on" : "off"); + return 1; + } + } + else if(strcasecmp("driver", argv[1]) == 0) { + if(strcasecmp("run", argv[2]) == 0) { + if (argc > 2) { + float fLower, fUpper, fZero, fSign, fFixed, fLim; + double fSoft; + char *endPtr; + errno = 0; + fSoft = strtod(argv[3], &endPtr); + if (endPtr == argv[3] || errno == ERANGE) { + self->errorCode = BADPAR; + SCPrintf(pCon, eWarning, "Motor %s bad run parameter %s", self->name, argv[3]); + return 1; + } + /* Reject Infinity and Not a Number (NaN) */ + switch (fpclassify(fSoft)) { + case FP_ZERO: + case FP_NORMAL: + break; + default: + self->errorCode = BADPAR; + SCPrintf(pCon, eWarning, "Motor %s bad run parameter %s", self->name, argv[3]); + return 1; + } + MotorGetPar(self->pMot, "softlowerlim", &fLower); + MotorGetPar(self->pMot, "softupperlim", &fUpper); + MotorGetPar(self->pMot, "softzero", &fZero); + MotorGetPar(self->pMot, "sign", &fSign); + MotorGetPar(self->pMot, "fixed", &fFixed); + if (fFixed >= 0) { + SCPrintf(pCon, eWarning, "Motor %s is Fixed", self->name); + } else if (fSoft > fUpper) { + SCPrintf(pCon, eWarning, "%g violates upper software limit %g on %s", + fSoft, fUpper, self->name); + } else if (fSoft < fLower) { + SCPrintf(pCon, eWarning, "%g violates lower software limit %g on %s", + fSoft, fLower, self->name); } else { - self->fTarget = fHard; - SCPrintf(pCon, eLog, "Running %s to soft=%g, hard=%g", self->name, fSoft, fHard); - state_cmd_execute(self, CMD_RUN); + double fHard = fSoft; + fHard += fZero; + fHard *= fSign; + if (fHard > self->fUpper) { + SCPrintf(pCon, eWarning, "%g violates upper hardware limit %g (%g) on %s", + fSoft, self->fUpper * fSign + fZero, self->fUpper, self->name); + } else if (fHard < self->fLower) { + SCPrintf(pCon, eWarning, "%g violates lower hardware limit %g (%g) on %s", + fSoft, self->fLower * fSign + fZero, self->fLower, self->name); + } else { + self->fTarget = fHard; + SCPrintf(pCon, eLog, "Running %s to soft=%g, hard=%g", self->name, fSoft, fHard); + self->doOscillate = false; + self->doReportMotion = true; + state_cmd_execute(self, CMD_RUN); + } } } + else { + char *txt = NULL; + if (OKOK == self->driver_status) + txt = "OKOK"; + else if (HWIdle == self->driver_status) + txt = "HWIdle"; + else if (HWBusy == self->driver_status) + txt = "HWBusy"; + else if (HWFault == self->driver_status) + txt = "HWFault"; + else if (HWPosFault == self->driver_status) + txt = "HWPosFault"; + else if (HWCrash == self->driver_status) + txt = "HWCrash"; + else if (NOMEMORY == self->driver_status) + txt = "NOMEMORY"; + else if (HWNoBeam == self->driver_status) + txt = "HWNoBeam"; + else if (HWPause == self->driver_status) + txt = "HWPause"; + else if (HWWarn == self->driver_status) + txt = "HWWarn"; + else if (HWRedo == self->driver_status) + txt = "HWRedo"; + else + txt = "HWUnknown"; + SCPrintf(pCon, eValue, "%s.run = %s", self->name, txt); + } + return 1; } - else { - char *txt = NULL; - if (OKOK == self->driver_status) - txt = "OKOK"; - else if (HWIdle == self->driver_status) - txt = "HWIdle"; - else if (HWBusy == self->driver_status) - txt = "HWBusy"; - else if (HWFault == self->driver_status) - txt = "HWFault"; - else if (HWPosFault == self->driver_status) - txt = "HWPosFault"; - else if (HWCrash == self->driver_status) - txt = "HWCrash"; - else if (NOMEMORY == self->driver_status) - txt = "NOMEMORY"; - else if (HWNoBeam == self->driver_status) - txt = "HWNoBeam"; - else if (HWPause == self->driver_status) - txt = "HWPause"; - else if (HWWarn == self->driver_status) - txt = "HWWarn"; - else if (HWRedo == self->driver_status) - txt = "HWRedo"; - else - txt = "HWUnknown"; - SCPrintf(pCon, eValue, "%s.run = %s", self->name, txt); - } + } + else if(strcasecmp("status", argv[1]) == 0) { + char *txt = NULL; + if (OKOK == self->driver_status) + txt = "OKOK"; + else if (HWIdle == self->driver_status) + txt = "HWIdle"; + else if (HWBusy == self->driver_status) + txt = "HWBusy"; + else if (HWFault == self->driver_status) + txt = "HWFault"; + else if (HWPosFault == self->driver_status) + txt = "HWPosFault"; + else if (HWCrash == self->driver_status) + txt = "HWCrash"; + else if (NOMEMORY == self->driver_status) + txt = "NOMEMORY"; + else if (HWNoBeam == self->driver_status) + txt = "HWNoBeam"; + else if (HWPause == self->driver_status) + txt = "HWPause"; + else if (HWWarn == self->driver_status) + txt = "HWWarn"; + else if (HWRedo == self->driver_status) + txt = "HWRedo"; + else + txt = "HWUnknown"; + SCPrintf(pCon, eValue, "%s.status = %s", self->name, txt); return 1; } else if(strcasecmp("halt", argv[1]) == 0) { @@ -5433,8 +5788,7 @@ int DMC2280Action(SConnection *pCon, SicsInterp *pSics, void *pData, } return 1; } else if(self->abs_encoder && strcasecmp("stats", argv[1]) == 0) { - char line[132]; - snprintf(line, CMDLEN, "%s.stats=%s samples=%.0f, slope=%f, intercept=%f, r=%f, stepsPerX=%f", + SCPrintf(pCon, eValue, "%s.stats=%s samples=%.0f, slope=%f, intercept=%f, r=%f, stepsPerX=%f", self->name, self->doStats ? "ON" : "OFF", self->S_n, @@ -5442,7 +5796,6 @@ int DMC2280Action(SConnection *pCon, SicsInterp *pSics, void *pData, self->S_b, self->S_r, self->cntsPerX * self->S_m); - SCWrite(pCon, line, eValue); if (argc > 2) { if (strcasecmp(argv[2], "reset") == 0) { /* reset the stats */ @@ -5565,6 +5918,14 @@ int DMC2280Action(SConnection *pCon, SicsInterp *pSics, void *pData, SCWrite(pCon, line, eValue); return 1; } + else if(strcasecmp("legacy_fsm", argv[1]) == 0) { + SCPrintf(pCon, eValue, "%s.legacy_fsm = %d", self->name, self->posit_count); + return 1; + } + else if(strcasecmp("posit_count", argv[1]) == 0) { + SCPrintf(pCon, eValue, "%s.posit_count = %d", self->name, self->posit_count); + return 1; + } else if(strcasecmp("positions", argv[1]) == 0) { if (argc == 2) { int i, k = 0; diff --git a/site_ansto/site_ansto.c b/site_ansto/site_ansto.c index c161252b..0ec14b47 100644 --- a/site_ansto/site_ansto.c +++ b/site_ansto/site_ansto.c @@ -23,7 +23,10 @@ #include #include #include + +#ifdef SICS_VALGRIND #include +#endif #include "protocol.h" #include "sicslist.h" @@ -290,9 +293,33 @@ static int MacroFileEvalGlob(SConnection * pCon, SicsInterp * pInter, void *pDat SCSendOK(pCon); return rv; } + +/* Test of the logging facilities */ +int testLogCmd(SConnection *pCon, SicsInterp *pInter, void *pData, + int argc, char *argv[]) { + char lbuf[2048]; + char sbuf[1000]; + int i; + SICSLogWrite("Multiline:\nLine 1\r\nLine 2\r\nLine 3\r\n", eStatus); + memset(lbuf, 0, sizeof(lbuf)); + memset(sbuf, ' ', sizeof(sbuf)); + SICSLogPrintf(eStatus, "Hexlog %d all zero bytes", sizeof(lbuf)); + SICSLogWriteHex(lbuf, sizeof(lbuf), eStatus); + for (i = 0; i <= 128; ++i) + sbuf[i] = sbuf[sizeof(sbuf) - 1 - i] = i; + sbuf[sizeof(sbuf) / 2] = '!'; + SICSLogPrintf(eStatus, "Hexlog %d mid space bytes", sizeof(sbuf)); + SICSLogWriteHex(sbuf, sizeof(sbuf), eStatus); + for (i = 0; i < 1000; ++i) + sbuf[i] = ' ' + (i % 96); + sbuf[sizeof(sbuf) - 1] = '\0'; + SICSLogWrite("Very long line 1000 bytes", eStatus); + SICSLogWrite(sbuf, eStatus); + SCSendOK(pCon); + return OKOK; +} + void SiteInit(void) { - int NetWatchInit(void); - NetWatchInit(); #define INIT(F) { void F(void); F(); } /* insert here initialization routines ... */ INIT(SctEmonInit); diff --git a/site_ansto/west4100driv.c b/site_ansto/west4100driv.c index 00e2c026..a4830ef1 100644 --- a/site_ansto/west4100driv.c +++ b/site_ansto/west4100driv.c @@ -297,13 +297,16 @@ return NULL; } - pNew = CreateEVDriver(argc,argv); pSim = (pWEST4100Driv)malloc(sizeof(WEST4100Driv)); - memset(pSim,0,sizeof(WEST4100Driv)); - if(!pNew || !pSim) - { + if(!pSim) { return NULL; } + pNew = CreateEVDriver(argc,argv); + if(!pNew) { + free(pSim); + return NULL; + } + memset(pSim,0,sizeof(WEST4100Driv)); pNew->pPrivate = pSim; pNew->KillPrivate = KillWEST4100; diff --git a/statistics.c b/statistics.c index 406be5a4..da2a622d 100644 --- a/statistics.c +++ b/statistics.c @@ -58,7 +58,7 @@ int StatisticsCommand(SConnection * con, SicsInterp * pSics, void *pData, gettimeofday(&now, 0); dif = timeFloat(timeDif(lastStat, now)); - SCPrintf(con, eLog, "calls/s time[%] full[%] mean[ms] command"); + SCPrintf(con, eLog, "calls/s time[%%] full[%%] mean[ms] command"); SCPrintf(con, eLog, "----------------------------------------------"); for (p = list; p != NULL; p = p->next) { if (dif > 0) { diff --git a/tasdrive.c b/tasdrive.c index d4d6b96b..2f64fffa 100644 --- a/tasdrive.c +++ b/tasdrive.c @@ -39,9 +39,9 @@ static long TASSetValue(void *pData, SConnection * pCon, float value) { ptasMot self = (ptasMot) pData; - assert(self); int qcodes[] = {3,4,5,8}; /* qh,qk,ql, en */ int i; + assert(self); if (self->code > 5 && self->math->tasMode == ELASTIC) { SCWrite(pCon, "ERROR: cannot drive this motor in elastic mode", @@ -328,9 +328,9 @@ static int startMotors(ptasMot self, tasAngles angles, self->math->busy[A2] = 1; } - if (self->math->motors[MCV] != NULL) { + if (self->math->motors[MCV] != NULL && self->math->autofocus) { curve = maCalcVerticalCurvature(self->math->machine.monochromator, - angles.monochromator_two_theta); + angles.monochromator_two_theta, getTasPar(self->math->target, EI), self->math->focusfn); status = startTASMotor(self->math->motors[MCV], pCon, self->math->motname[MCV], curve, silent,stopFixed); if (status != OKOK) { @@ -341,9 +341,9 @@ static int startMotors(ptasMot self, tasAngles angles, } } - if (self->math->motors[MCH] != NULL) { + if (self->math->motors[MCH] != NULL && self->math->autofocus) { curve = maCalcHorizontalCurvature(self->math->machine.monochromator, - angles.monochromator_two_theta); + angles.monochromator_two_theta, getTasPar(self->math->target, EI), self->math->focusfn); status = startTASMotor(self->math->motors[MCH], pCon, self->math->motname[MCH], curve, silent,stopFixed); if (status != OKOK) { @@ -374,9 +374,9 @@ static int startMotors(ptasMot self, tasAngles angles, self->math->busy[A6] = 1; } - if (self->math->motors[ACV] != NULL) { + if (self->math->motors[ACV] != NULL && self->math->autofocus) { curve = maCalcVerticalCurvature(self->math->machine.analyzer, - angles.analyzer_two_theta); + angles.analyzer_two_theta, getTasPar(self->math->target, EF), self->math->focusfn); status = startTASMotor(self->math->motors[ACV], pCon, self->math->motname[ACV], curve, silent,stopFixed); if (status != OKOK) { @@ -386,9 +386,9 @@ static int startMotors(ptasMot self, tasAngles angles, self->math->busy[ACV] = 1; } } - if (self->math->motors[ACH] != NULL) { + if (self->math->motors[ACH] != NULL && self->math->autofocus) { curve = maCalcHorizontalCurvature(self->math->machine.analyzer, - angles.analyzer_two_theta); + angles.analyzer_two_theta, getTasPar(self->math->target, EF), self->math->focusfn); status = startTASMotor(self->math->motors[ACH], pCon, self->math->motname[ACH], curve, silent,stopFixed); if (status != OKOK) { @@ -666,9 +666,9 @@ static int startQMMotors(ptasMot self, tasAngles angles, self->math->busy[A2] = 1; } - if (self->math->motors[MCV] != NULL) { + if (self->math->motors[MCV] != NULL && self->math->autofocus) { curve = maCalcVerticalCurvature(self->math->machine.monochromator, - angles.monochromator_two_theta); + angles.monochromator_two_theta, getTasPar(self->math->target, EI), self->math->focusfn); status = startTASMotor(self->math->motors[MCV], pCon, self->math->motname[MCV], curve, silent,stopFixed); if (status != OKOK) { @@ -678,9 +678,9 @@ static int startQMMotors(ptasMot self, tasAngles angles, } } - if (self->math->motors[MCH] != NULL) { + if (self->math->motors[MCH] != NULL && self->math->autofocus) { curve = maCalcHorizontalCurvature(self->math->machine.monochromator, - angles.monochromator_two_theta); + angles.monochromator_two_theta, getTasPar(self->math->target, EI), self->math->focusfn); status = startTASMotor(self->math->motors[MCH], pCon, self->math->motname[MCH], curve, silent,stopFixed); if (status != OKOK) { @@ -709,9 +709,9 @@ static int startQMMotors(ptasMot self, tasAngles angles, self->math->busy[A6] = 1; } - if (self->math->motors[ACV] != NULL) { + if (self->math->motors[ACV] != NULL && self->math->autofocus) { curve = maCalcVerticalCurvature(self->math->machine.analyzer, - angles.analyzer_two_theta); + angles.analyzer_two_theta, getTasPar(self->math->target, EF), self->math->focusfn); status = startTASMotor(self->math->motors[ACV], pCon, self->math->motname[ACV], curve, silent,stopFixed); if (status != OKOK) { @@ -720,9 +720,9 @@ static int startQMMotors(ptasMot self, tasAngles angles, self->math->busy[ACV] = 1; } } - if (self->math->motors[ACH] != NULL) { + if (self->math->motors[ACH] != NULL && self->math->autofocus) { curve = maCalcHorizontalCurvature(self->math->machine.analyzer, - angles.analyzer_two_theta); + angles.analyzer_two_theta, getTasPar(self->math->target, EF), self->math->focusfn); status = startTASMotor(self->math->motors[ACH], pCon, self->math->motname[ACH], curve, silent,stopFixed); if (status != OKOK) { diff --git a/tasub.c b/tasub.c index 32b4c7d1..45992104 100644 --- a/tasub.c +++ b/tasub.c @@ -173,6 +173,8 @@ static ptasUB MakeTasUB() pNew->actualEn = .0; pNew->outOfPlaneAllowed = 1; pNew->mustRecalculate = 1; + pNew->autofocus = 0; + pNew->focusfn = THETA_FN; return pNew; } @@ -381,6 +383,10 @@ int TasUBFactory(SConnection * pCon, SicsInterp * pSics, void *pData, eError); return 0; } + if (pNew->motors[MCV] != NULL && pNew->motors[MCH] != NULL && + pNew->motors[ACV] != NULL && pNew->motors[ACH] != NULL) { + pNew->autofocus = 1; + } status = AddCommand(pSics, argv[1], TasUBWrapper, KillTasUB, pNew); if (status != 1) { @@ -453,6 +459,11 @@ static int setCrystalParameters(pmaCrystal crystal, SConnection * pCon, SCSendOK(pCon); SCparChange(pCon); return 1; + } else if (strcmp(argv[2], "hb3") == 0) { + crystal->HB3 = d; + SCSendOK(pCon); + SCparChange(pCon); + return 1; } else if (strcmp(argv[2], "vb1") == 0) { crystal->VB1 = d; SCSendOK(pCon); @@ -493,6 +504,11 @@ static int getCrystalParameters(pmaCrystal crystal, SConnection * pCon, crystal->HB2); SCWrite(pCon, pBueffel, eValue); return 1; + } else if (strcmp(argv[2], "hb3") == 0) { + snprintf(pBueffel, 131, "%s.%s.hb3 = %f", argv[0], argv[1], + crystal->HB3); + SCWrite(pCon, pBueffel, eValue); + return 1; } else if (strcmp(argv[2], "vb1") == 0) { snprintf(pBueffel, 131, "%s.%s.vb1 = %f", argv[0], argv[1], crystal->VB1); @@ -2200,9 +2216,44 @@ int TasUBWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, SCWrite(pCon, pBueffel, eValue); return 1; } - } else { + } else if (strcmp(argv[1], "autofocus") == 0) { + if (argc > 2) { + status = Tcl_GetInt(InterpGetTcl(pSics), argv[2], &(self->autofocus)); + if (status != TCL_OK) { + SCWrite(pCon, "ERROR: failed to convert argument to number", + eError); + return 0; + } + } else { + snprintf(pBueffel, 131, "%s.autofocus = %d", argv[0], self->autofocus); + SCWrite(pCon, pBueffel, eValue); + return 1; + } + } else if (strcmp(argv[1], "focusfn") == 0) { + if (argc > 2) { + strtolower(argv[2]); + if (strcmp(argv[2], "theta") == 0) { + self->focusfn = THETA_FN; + } else if (strcmp(argv[2], "energy") == 0) { + self->focusfn = ENERGY_FN; + } else { + SCWrite(pCon, "ERROR: Arguments should be theta or energy", eError); + } + } else { + switch (self->focusfn) { + case ENERGY_FN: + snprintf(pBueffel, 131, "%s.focusfn = %s", argv[0], "energy"); + break; + case THETA_FN: + snprintf(pBueffel, 131, "%s.focusfn = %s", argv[0], "theta"); + break; + } + SCWrite(pCon, pBueffel, eValue); + return 1; + } + } else { snprintf(pBueffel, 131, "ERROR: subcommand %s to %s not defined", - argv[1], argv[0]); + argv[1], argv[0]); SCWrite(pCon, pBueffel, eError); return 0; } diff --git a/tasub.h b/tasub.h index 0d4ba3e5..bd226423 100644 --- a/tasub.h +++ b/tasub.h @@ -24,6 +24,8 @@ tasQEPosition current; int tasMode; int outOfPlaneAllowed; + int autofocus; + int focusfn; double targetEn, actualEn; int mustRecalculate; int mustDrive; @@ -34,7 +36,7 @@ tasReflection r1, r2; int ubValid; int silent; - int stopFixed; /* flag to stop multiple fixed messages in scans*/ + int stopFixed; /* flag to stop multiple fixed messages in scans*/ char *updater; }tasUB, *ptasUB; diff --git a/tasublib.c b/tasublib.c index 4b38bfee..04dec63e 100644 --- a/tasublib.c +++ b/tasublib.c @@ -40,13 +40,21 @@ double KtoEnergy(double k) } /*-------------------------------------------------------------------*/ -static double calcCurvature(double B1, double B2, double theta, int ori) +static double calcCurvature(double B1, double B2, double B3, double theta, double energy, int ori, int focusfn) { assert(ori == VERT || ori == HOR); - if (ori == VERT) { - return B1 + B2 / Sind(ABS(theta)); + if (focusfn == ENERGY_FN) { + if (ori == VERT) { + return B1 + B2 * energy; + } else { + return B1 + B2 * pow(B3, energy); + } } else { - return B1 + B2 * Sind(ABS(theta)); + if (ori == VERT) { + return B1 + B2 / Sind(ABS(theta)); + } else { + return B1 + B2 * Sind(ABS(theta)); + } } } @@ -66,15 +74,15 @@ int maCalcTwoTheta(maCrystal data, double k, double *two_theta) } /*--------------------------------------------------------------------*/ -double maCalcVerticalCurvature(maCrystal data, double two_theta) +double maCalcVerticalCurvature(maCrystal data, double two_theta, double energy, int focusfn) { - return calcCurvature(data.VB1, data.VB2, two_theta / 2., VERT); + return calcCurvature(data.VB1, data.VB2, 1, two_theta / 2., energy, VERT, focusfn); } /*-------------------------------------------------------------------*/ -double maCalcHorizontalCurvature(maCrystal data, double two_theta) +double maCalcHorizontalCurvature(maCrystal data, double two_theta, double energy, int focusfn) { - return calcCurvature(data.HB1, data.HB2, two_theta / 2., HOR); + return calcCurvature(data.HB1, data.HB2, data.HB3, two_theta / 2., energy, HOR, focusfn); } /*--------------------------------------------------------------------*/ diff --git a/tasublib.h b/tasublib.h index 15ef992f..53a1b0d8 100644 --- a/tasublib.h +++ b/tasublib.h @@ -22,6 +22,9 @@ #define KICONST 1 #define KFCONST 2 #define ELASTIC 3 +/*========================== defines for focusfn ====================*/ +#define ENERGY_FN 1 +#define THETA_FN 2 /* * in elastic mode A5, A5 will be disregarded and ki = kf at all times */ @@ -42,8 +45,8 @@ typedef struct { double dd; /* lattice spacing */ int ss; /* scattering sense */ - double HB1, HB2; /* horizontal curvature parameters */ - double VB1, VB2; /* vertical curvature parameters */ + double HB1, HB2, HB3; /* horizontal curvature parameters */ + double VB1, VB2; /* vertical curvature parameters */ } maCrystal, *pmaCrystal; /** * the machine parameters of a triple axis spectrometer @@ -109,14 +112,14 @@ int maCalcTwoTheta(maCrystal data, double k, double *two_theta); * @param two_theta The tow theta value for which to calculate the curvature. * @return A new value for the curvature. */ -double maCalcVerticalCurvature(maCrystal data, double two_theta); +double maCalcVerticalCurvature(maCrystal data, double two_theta, double energy, int focusfn); /** * calculate the value for the horizontal curvature * @param data The input crystal parameters * @param two_theta The tow theta value for which to calculate the curvature. * @return A new value for the curvature. */ -double maCalcHorizontalCurvature(maCrystal data, double two_theta); +double maCalcHorizontalCurvature(maCrystal data, double two_theta, double energy, int focusfn); /** * calculate the value of the K vector from the angle * @param data The crystals constants diff --git a/trace.h b/trace.h index afd6d71b..24a266d5 100644 --- a/trace.h +++ b/trace.h @@ -18,17 +18,24 @@ * the socket number, a host:port or something appropriate * which tells us where the stuff is going to or coming from. */ -void traceIO(char *id, char *format, ...); -void traceDevice(char *id, char *format, ...); -void traceCommand(char *id, char *format, ...); -void tracePar(char *id, char *format, ...); -void traceSys(char *id, char *format, ...); +#if __GNUC__ > 2 +#define G_GNUC_PRINTF( format_idx, arg_idx ) \ + __attribute__((__format__ (__printf__, format_idx, arg_idx))) +#else +#define G_GNUC_PRINTF( format_idx, arg_idx ) +#endif +void traceIO(char *id, char *format, ...) G_GNUC_PRINTF (2, 3); +void traceDevice(char *id, char *format, ...) G_GNUC_PRINTF (2, 3); +void traceCommand(char *id, char *format, ...) G_GNUC_PRINTF (2, 3); +void tracePar(char *id, char *format, ...) G_GNUC_PRINTF (2, 3); +void traceSys(char *id, char *format, ...) G_GNUC_PRINTF (2, 3); void traceprint(char *sub, char *id,char *data); /** * A debugging trace. This has to be switched on separately */ -void traceDebug(char *id, char *format, ...); +void traceDebug(char *id, char *format, ...) G_GNUC_PRINTF (2, 3); +#undef G_GNUC_PRINTF /* * 1 when tracing active, 0 else