Files
sics/hmcontrol.c
koennecke ce565b4d50 - Fixed a normalisation problem in diffscan when the first value
did not have enough counts
- Reduced polling frequency in emon
- Fixed a scriptcontext bug which would cause it to dump core in SctTransact
  on interrupts
- Fixed an issue with missing <nl> at the end of batch files
- Added a feature which does not call halt when counting stops in hmcontrol.c
  This is necessary for the BOA CCD
- Initalized doNotFree properly in hipadaba.c
- Added the travelling salesman reflection measurement algorithm
- Added another component to amorset
- Removed old SicsWait from nserver.c
- Added a means to nxscript to write 16 bit data for BOA
- Modified tasub to accept a drivabel as a motor and not only a motor.
  This became necessary to make EIGER work as A2 on EIGER is a virtual
  motor


SKIPPED:
	psi/amorcomp.h
	psi/amordrive.h
	psi/amorset.c
	psi/amorset.h
	psi/amorset.tex
	psi/amorset.w
	psi/el734hp.c
	psi/el737hpdriv.c
	psi/make_gen
	psi/pardef.c
	psi/polterwrite.c
	psi/psi.c
	psi/sinqhttpopt.c
2011-09-23 07:55:49 +00:00

423 lines
11 KiB
C

/*------------------------------------------------------------------------
H M C O N T R O L
A module for coordinating several counters and histogram
memories. One of the counters is the master counter and the rest are
slaves which have to be kept in sync with the master in their
operations.
copyright: see copyright.h
Mark Koennecke, June 2001
Added a flag which does not call halt after the counter
finished. This feauture is necessary to allow normal
counting on CCD camera. When they get interrupted, the
image is invalid. This is not what is wanted.
Mark Koennecke, July 2011
-------------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
#include <tcl.h>
#include <unistd.h>
#include "fortify.h"
#include "hmcontrol.h"
#include "HistMem.h"
#include "devexec.h"
/*-------------------------------------------------------------------------*/
static void *HMCGetInterface(void *pData, int ID)
{
pHMcontrol self = NULL;
self = (pHMcontrol) pData;
assert(self);
if (ID == COUNTID)
return self->pCount;
else
return NULL;
}
/*------------------------------------------------------------------------*/
static int HMCHalt(void *pData)
{
int i, retVal = OKOK, status;
pHMcontrol self = NULL;
self = (pHMcontrol) pData;
assert(self);
for (i = 0; i < self->nSlaves; i++) {
status = self->slaves[i]->Halt(self->slaveData[i]);
ReleaseCountLock(self->slaves[i]);
if (status != OKOK)
retVal = status;
}
ReleaseCountLock(self->pCount);
return retVal;
}
/*-----------------------------------------------------------------------*/
static int HMCStart(void *pData, SConnection * pCon)
{
int i, status;
pHMcontrol self = NULL;
self = (pHMcontrol) pData;
assert(self);
if (!GetCountLock(self->pCount, pCon)) {
return HWFault;
}
for (i = 1; i < self->nSlaves; i++) {
ReleaseCountLock(self->slaves[i]);
status = self->slaves[i]->StartCount(self->slaveData[i], pCon);
if (status != OKOK) {
HMCHalt(self);
return status;
}
}
/*
* This starts the counter: always 0, last.This should be the
* right thing as the HM do not start counting in earnest before
* the busy line from the counter box is set.
*/
ReleaseCountLock(self->slaves[0]);
status = self->slaves[0]->StartCount(self->slaveData[0], pCon);
if (status != OKOK) {
HMCHalt(self);
return status;
}
/*
Warning: this assumes that slaves 1 - MAXSLAVE are histogram memories.
If this assumption does not hold, change this code to check if this
is really a histogram memory.
*/
for (i = 1; i < MAXSLAVE; i++) {
if (self->slaves[i] != NULL) {
HistDirty((pHistMem) self->slaveData[i]);
}
}
self->checkSlaves = 0;
return OKOK;
}
/*----------------------------------------------------------------------*/
static int HMCStatus(void *pData, SConnection * pCon)
{
int status, i;
pHMcontrol self = NULL;
self = (pHMcontrol) pData;
assert(self);
if(self->checkSlaves == 0) {
status = self->slaves[0]->CheckCountStatus(self->slaveData[0], pCon);
/*
Warning: this assumes that slaves 1 - MAXSLAVE are histogram memories.
If this assumption does not hold, change this code to check if this
is really a histogram memory.
*/
for (i = 1; i < MAXSLAVE; i++) {
if (self->slaves[i] != NULL) {
HistDirty((pHistMem) self->slaveData[i]);
}
}
if (status == HWIdle || status == HWFault) {
/*
stop counting on slaves when finished or when an error
occurred.
*/
if(self->stopSlaves){
HMCHalt(self);
}
ReleaseCountLock(self->pCount);
self->checkSlaves = 1;
status = HWBusy;
}
} else {
/*
* wait for the detectors to report finish too. Otherwise, with the second
* generation HM data may not be fully transferred.
*/
for(i = 1; i < self->nSlaves; i++){
status = self->slaves[i]->CheckCountStatus(self->slaveData[i], pCon);
if(status != HWIdle || status != HWFault){
return status;
}
}
status = HWIdle;
InvokeCallBack(self->pCall, COUNTEND, pCon);
self->checkSlaves = 0;
}
return status;
}
/*-------------------------------------------------------------------------*/
static int HMCPause(void *pData, SConnection * pCon)
{
int i, status;
pHMcontrol self = NULL;
self = (pHMcontrol) pData;
assert(self);
for (i = 0; i < self->nSlaves; i++) {
status = self->slaves[i]->Pause(self->slaveData[i], pCon);
if (status != OKOK) {
HMCHalt(self);
return status;
}
}
return OKOK;
}
/*------------------------------------------------------------------------*/
static int HMCContinue(void *pData, SConnection * pCon)
{
int i, status;
pHMcontrol self = NULL;
self = (pHMcontrol) pData;
assert(self);
for (i = 0; i < self->nSlaves; i++) {
status = self->slaves[i]->Continue(self->slaveData[i], pCon);
if (status != OKOK) {
HMCHalt(self);
return status;
}
}
return OKOK;
}
/*----------------------------------------------------------------------*/
static int HMCTransfer(void *pData, SConnection * pCon)
{
int i, retVal = OKOK, status;
pHMcontrol self = NULL;
char pBueffel[132];
self = (pHMcontrol) pData;
assert(self);
for (i = 0; i < self->nSlaves; i++) {
status = self->slaves[i]->TransferData(self->slaveData[i], pCon);
if (status != OKOK) {
retVal = status;
snprintf(pBueffel,sizeof(pBueffel)-1,
"WARNING: slave histogram %d failed to transfer data", i);
SCWrite(pCon, pBueffel, eWarning);
}
}
return retVal;
}
/*-----------------------------------------------------------------------*/
static void HMCParameter(void *pData, float fPreset, CounterMode eMode)
{
int i;
pHMcontrol self = NULL;
self = (pHMcontrol) pData;
assert(self);
if(isRunning(self->pCount)){
return;
}
for (i = 0; i < self->nSlaves; i++) {
self->slaves[i]->SetCountParameters(self->slaveData[i], fPreset,
eMode);
}
}
/*----------------------------------------------------------------------*/
static void KillHMcontrol(void *pData)
{
pHMcontrol self;
self = (pHMcontrol) pData;
if (!self)
return;
if (self->pDes)
DeleteDescriptor(self->pDes);
if (self->pCount)
free(self->pCount);
free(self);
}
/*-----------------------------------------------------------------------*/
int MakeHMControl(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
int i, status;
pHMcontrol pNew = NULL;
char pBueffel[132];
CommandList *pCom;
pICountable pCount;
/*
need at least two parameters
*/
if (argc < 3) {
SCWrite(pCon,
"ERROR: insufficient number of arguments to MakeHMControl",
eError);
return 0;
}
/*
allocate our data structure
*/
pNew = (pHMcontrol) malloc(sizeof(HMcontrol));
if (!pNew) {
SCWrite(pCon, "ERROR: out of memory in MakeHMControl", eError);
return 0;
}
memset(pNew, 0, sizeof(HMcontrol));
pNew->pDes = CreateDescriptor("HMcontrol");
pNew->pCount = CreateCountableInterface();
pNew->pCall = CreateCallBackInterface();
if (!pNew->pDes || !pNew->pCount) {
SCWrite(pCon, "ERROR: out of memory in MakeHMControl", eError);
KillHMcontrol(pNew);
return 0;
}
/*
assign interface functions
*/
pNew->pDes->GetInterface = HMCGetInterface;
pNew->pCount->Halt = HMCHalt;
pNew->pCount->StartCount = HMCStart;
pNew->pCount->CheckCountStatus = HMCStatus;
pNew->pCount->Pause = HMCPause;
pNew->pCount->Continue = HMCContinue;
pNew->pCount->TransferData = HMCTransfer;
pNew->pCount->SetCountParameters = HMCParameter;
/*
now loop through the remaining arguments, thereby entering them into
the slave list.
*/
for (i = 2; i < argc; i++) {
pCom = FindCommand(pSics, argv[i]);
if (!pCom) {
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: object %s not found in MakeHMcontrol",
argv[i]);
SCWrite(pCon, pBueffel, eError);
continue;
}
pCount = GetCountableInterface(pCom->pData);
if (!pCount) {
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: object %s is NOT countable", argv[i]);
SCWrite(pCon, pBueffel, eError);
continue;
}
pNew->slaves[pNew->nSlaves] = pCount;
pNew->slaveData[pNew->nSlaves] = pCom->pData;
pNew->nSlaves++;
pNew->stopSlaves = 1;
}
/*
now install our action command and we are done
*/
status = AddCommand(pSics, argv[1], HMControlAction, KillHMcontrol,
pNew);
if (!status) {
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: duplicate command %s not created", argv[1]);
SCWrite(pCon, pBueffel, eError);
KillHMcontrol(pNew);
return 0;
}
return 1;
}
/*-----------------------------------------------------------------------
Syntax: whatever start preset mode
------------------------------------------------------------------------*/
int HMControlAction(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
pHMcontrol self;
char pBueffel[132];
double dPreset;
CounterMode eMode;
int status;
/*
checks
*/
self = (pHMcontrol) pData;
assert(self);
if (argc < 2) {
snprintf(pBueffel, 131, "ERROR: Usage %s start preset mode", argv[0]);
SCWrite(pCon, pBueffel, eError);
return 0;
}
strtolower(argv[1]);
if (strcmp(argv[1], "start") == 0) {
if (argc < 4) {
snprintf(pBueffel, 131, "ERROR: Usage %s start preset mode", argv[0]);
SCWrite(pCon, pBueffel, eError);
return 0;
}
/*
interpret count parameters
*/
status = Tcl_GetDouble(pSics->pTcl, argv[2], &dPreset);
if (status != TCL_OK) {
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: failed to convert %s to number", argv[2]);
SCWrite(pCon, pBueffel, eError);
return 0;
}
strtolower(argv[3]);
if (strcmp(argv[3], "timer") == 0)
eMode = eTimer;
else if (strcmp(argv[3], "monitor") == 0)
eMode = ePreset;
else {
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s is no recognized count mode", argv[3]);
SCWrite(pCon, pBueffel, eError);
return 0;
}
/*
set count parameters and go
*/
self->pCount->SetCountParameters(self, (float) dPreset, eMode);
status = StartDevice(pServ->pExecutor, "hmcontrol", self->pDes,
self, pCon, RUNRUN, 99);
if (!status) {
SCWrite(pCon, "ERROR: failed to start counting", eError);
return 0;
}
InvokeCallBack(self->pCall, COUNTSTART, pCon);
SCSendOK(pCon);
}else if(strcmp(argv[1],"stopslaves") == 0){
if(argc < 3){
SCPrintf(pCon,eValue,"hm.stopslaves = %d", self->stopSlaves);
return 1;
} else {
self->stopSlaves = atoi(argv[2]);
SCPrintf(pCon,eValue,"hm.stopslaves = %d", self->stopSlaves);
return 1;
}
} else {
SCWrite(pCon, "ERROR: subcommand not recognized", eError);
return 0;
}
return 1;
}