The camera driver can now send meta data such as the motor positions to the camera server.

An auxiliary command has been added so we can set string values on the camera driver for the meta data.
This commit is contained in:
Ferdi Franceschini
2014-07-31 15:45:03 +10:00
parent 9b965e6313
commit fdbb0456ad
2 changed files with 328 additions and 56 deletions

View File

@ -62,7 +62,7 @@
TR(ECA_MLTI_OFF, "take multi off") \ TR(ECA_MLTI_OFF, "take multi off") \
TR(ECA_GET_STATUS, "get status") \ TR(ECA_GET_STATUS, "get status") \
TR(ECA_GET_STATE, "get state") \ TR(ECA_GET_STATE, "get state") \
TE(ECA_CFG, "send configuration") TE(ECA_CFG, "update camera settings, file configuration and meta data")
#define CAMERA_MSGS_TABLE \ #define CAMERA_MSGS_TABLE \
TR(ECA_START, "StartTime") \ TR(ECA_START, "StartTime") \

View File

@ -8,6 +8,8 @@
* *
* Copyright: see file Copyright.txt * Copyright: see file Copyright.txt
*/ */
#include <limits.h>
#include <errno.h>
#include <string.h> #include <string.h>
#include <sics.h> #include <sics.h>
#include <obdes.h> #include <obdes.h>
@ -17,8 +19,12 @@
#include <math.h> #include <math.h>
#include "camera.h" #include "camera.h"
#define NAMELEN 32
#define IFMTLEN 4
#define ERRLEN 256 #define ERRLEN 256
#define MSGLEN 512 #define MSGLEN 512
#define MAX_META_COUNT 32
#define MAX_SCANVAR_COUNT 16
enum camstates {idle, acquiring, processing, saving}; enum camstates {idle, acquiring, processing, saving};
#define CAMDRIV_ERRTABLE \ #define CAMDRIV_ERRTABLE \
@ -85,10 +91,20 @@ static char *flipcmdstr[] = {FLIP_TABLE, NULL};
#undef TR #undef TR
#undef TE #undef TE
// Camera get/set commands: ['status', 'info', 'state', 'camera', 'meta', 'file'] #define UPDATE_SETTINGS_CFG 1
#define ECMDSTART 0 #define CLEAR_META_CFG 2
#define EGETSTART 100 #define UPDATE_META_CFG 4
#define ESETSTART 200 #define UPDATE_SCANVAR_CFG 8
#define UPDATE_FILE_CFG 16
typedef struct {
char path[MSGLEN];
char basename[MSGLEN];
long startnumber;
char imageformat[IFMTLEN];
char experimentdetail[MSGLEN];
} filecfg_t;
typedef struct { typedef struct {
float clockMHz; float clockMHz;
float bin; float bin;
@ -105,18 +121,17 @@ typedef struct {
float shopt; float shopt;
float shclt; float shclt;
int updatecfg; int updatecfg;
filecfg_t file;
char meta_list[MAX_META_COUNT][MSGLEN];
char scanvar_list[MAX_SCANVAR_COUNT][NAMELEN];
pDummy scanvar_dummy[MAX_SCANVAR_COUNT];
pIDrivable pscanvar[MAX_SCANVAR_COUNT];
int meta_count;
int scanvar_count;
} camcfg_t; } camcfg_t;
typedef struct { typedef struct {
char path[MSGLEN]; pObjectDescriptor pDes;
char basename[MSGLEN];
int startnumber;
char imageformat[MSGLEN];
char experimentdetail[MSGLEN];
int updatecfg;
} filecfg_t;
typedef struct {
int debug; int debug;
char *asynq; char *asynq;
camsm_t state_machine; camsm_t state_machine;
@ -124,8 +139,8 @@ typedef struct {
int status; int status;
enum errcodes camError; enum errcodes camError;
camcfg_t camera; camcfg_t camera;
/* filecfg_t file;*/
pAsyncUnit asyncUnit; pAsyncUnit asyncUnit;
SicsInterp *pSics;
} CamObj; } CamObj;
/* Camera communications and protocol handlers */ /* Camera communications and protocol handlers */
@ -134,6 +149,21 @@ static int cb_state_timer(void *ctx, int mode);
static int cb_getstate(pAsyncTxn txn); static int cb_getstate(pAsyncTxn txn);
static int CamSet(CounterDriver *cntrData, char *name, int iCter, float fVal); static int CamSet(CounterDriver *cntrData, char *name, int iCter, float fVal);
/* if emsg == NULL conversion OK else if emsg == num not an integer else emsg == error message */
long getlong(char *num, char *emsg) {
long val = 0;
char *endptr;
errno = 0;
emsg = NULL;
val = strtol(num, &endptr, 10);
if ( (errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || (errno != 0 && val == 0) )
emsg = strerror(errno);
if (endptr == num)
emsg = num;
return val;
}
static void CAM_Notify(void* context, int event) { static void CAM_Notify(void* context, int event) {
CamObj *self = (CamObj *) context; CamObj *self = (CamObj *) context;
@ -215,10 +245,10 @@ static int CamGetStatus(CounterDriver *cntrData, float *fControl) {
* \param ev_sym, input event * \param ev_sym, input event
*/ */
static void run_sm(CamObj *self, enum event_codes ev_sym) { static void run_sm(CamObj *self, enum event_codes ev_sym) {
char sscur[SSLEN+1], ssnext[SSLEN+1], esout[ESLEN+1], message[MSGLEN+1]; char *sscur, *ssnext, *esout, message[MSGLEN+1];
if (self->debug) { if (self->debug) {
strncpy(sscur, strstate(self->state_machine.Sc), SSLEN); sscur = strstate(self->state_machine.Sc);
snprintf(message, MSGLEN, "DEBUG:(run_sm) Scurr:%s Ei:%s", snprintf(message, MSGLEN, "DEBUG:(run_sm) Scurr:%s Ei:%s",
sscur,event_names[ev_sym]); sscur,event_names[ev_sym]);
SICSLogWrite(message, eLog); SICSLogWrite(message, eLog);
@ -227,9 +257,9 @@ static void run_sm(CamObj *self, enum event_codes ev_sym) {
camdriv_input(self, &self->state_machine, ev_sym); camdriv_input(self, &self->state_machine, ev_sym);
if (self->debug) { if (self->debug) {
strncpy(ssnext, strstate(self->state_machine.Sc), SSLEN); ssnext = strstate(self->state_machine.Sc), SSLEN;
strncpy(esout, strevent(self->state_machine.Eo), ESLEN); esout = strevent(self->state_machine.Eo), ESLEN;
snprintf(message, MSGLEN, "DEBUG:(run_sm) Snext:%s Eo:%s", ssnext,esout); snprintf(message, MSGLEN, "DEBUG:(run_sm) Snext:%s Eo:%s", ssnext, esout);
SICSLogWrite(message, eLog); SICSLogWrite(message, eLog);
} }
} }
@ -277,7 +307,7 @@ static int CamHalt(CounterDriver *cntrData) {
} }
return 1; return 1;
} }
/* TODO what should the counter data be set to? Total intensity? */ /* FIXME what should the counter data be set to? Total intensity? */
static int CamReadValues(CounterDriver *cntrData) { static int CamReadValues(CounterDriver *cntrData) {
int status, iReplyLen=MSGLEN; int status, iReplyLen=MSGLEN;
char *cmd="TODO ", pReply[MSGLEN]; char *cmd="TODO ", pReply[MSGLEN];
@ -358,7 +388,7 @@ static int CamSet(CounterDriver *cntrData, char *name, int iCter, float fVal) {
case CLOCK: case CLOCK:
if (fVal > 0) { if (fVal > 0) {
camdriv->camera.clockMHz = fVal; camdriv->camera.clockMHz = fVal;
camdriv->camera.updatecfg = 1; camdriv->camera.updatecfg |= UPDATE_SETTINGS_CFG;
} else { } else {
return 0; return 0;
} }
@ -366,7 +396,7 @@ static int CamSet(CounterDriver *cntrData, char *name, int iCter, float fVal) {
case BIN: case BIN:
if (fVal > 0) { if (fVal > 0) {
camdriv->camera.bin = fVal; camdriv->camera.bin = fVal;
camdriv->camera.updatecfg = 1; camdriv->camera.updatecfg |= UPDATE_SETTINGS_CFG;
} else { } else {
return 0; return 0;
} }
@ -374,7 +404,7 @@ static int CamSet(CounterDriver *cntrData, char *name, int iCter, float fVal) {
case SIZE: case SIZE:
if (fVal > 0) { if (fVal > 0) {
camdriv->camera.size = fVal; camdriv->camera.size = fVal;
camdriv->camera.updatecfg = 1; camdriv->camera.updatecfg |= UPDATE_SETTINGS_CFG;
} else { } else {
return 0; return 0;
} }
@ -382,7 +412,7 @@ static int CamSet(CounterDriver *cntrData, char *name, int iCter, float fVal) {
case GAIN: case GAIN:
if (fVal > 0) { if (fVal > 0) {
camdriv->camera.gain = fVal; camdriv->camera.gain = fVal;
camdriv->camera.updatecfg = 1; camdriv->camera.updatecfg |= UPDATE_SETTINGS_CFG;
} else { } else {
return 0; return 0;
} }
@ -399,7 +429,7 @@ static int CamSet(CounterDriver *cntrData, char *name, int iCter, float fVal) {
case INVFV: case INVFV:
case INVFHV: case INVFHV:
camdriv->camera.flip = flip; camdriv->camera.flip = flip;
camdriv->camera.updatecfg = 1; camdriv->camera.updatecfg |= UPDATE_SETTINGS_CFG;
break; break;
default: default:
return 0; return 0;
@ -409,7 +439,7 @@ static int CamSet(CounterDriver *cntrData, char *name, int iCter, float fVal) {
case XSTART: case XSTART:
if (fVal > 0) { if (fVal > 0) {
camdriv->camera.xstart = fVal; camdriv->camera.xstart = fVal;
camdriv->camera.updatecfg = 1; camdriv->camera.updatecfg |= UPDATE_SETTINGS_CFG;
} else { } else {
return 0; return 0;
} }
@ -417,7 +447,7 @@ static int CamSet(CounterDriver *cntrData, char *name, int iCter, float fVal) {
case YSTART: case YSTART:
if (fVal > 0) { if (fVal > 0) {
camdriv->camera.ystart = fVal; camdriv->camera.ystart = fVal;
camdriv->camera.updatecfg = 1; camdriv->camera.updatecfg |= UPDATE_SETTINGS_CFG;
} else { } else {
return 0; return 0;
} }
@ -425,7 +455,7 @@ static int CamSet(CounterDriver *cntrData, char *name, int iCter, float fVal) {
case XEND: case XEND:
if (fVal > 0) { if (fVal > 0) {
camdriv->camera.xend = fVal; camdriv->camera.xend = fVal;
camdriv->camera.updatecfg = 1; camdriv->camera.updatecfg |= UPDATE_SETTINGS_CFG;
} else { } else {
return 0; return 0;
} }
@ -433,7 +463,7 @@ static int CamSet(CounterDriver *cntrData, char *name, int iCter, float fVal) {
case YEND: case YEND:
if (fVal > 0) { if (fVal > 0) {
camdriv->camera.yend = fVal; camdriv->camera.yend = fVal;
camdriv->camera.updatecfg = 1; camdriv->camera.updatecfg |= UPDATE_SETTINGS_CFG;
} else { } else {
return 0; return 0;
} }
@ -441,19 +471,19 @@ static int CamSet(CounterDriver *cntrData, char *name, int iCter, float fVal) {
case EXPOSURE: case EXPOSURE:
if (fVal > 0) { if (fVal > 0) {
camdriv->camera.exposure = fVal; camdriv->camera.exposure = fVal;
camdriv->camera.updatecfg = 1; camdriv->camera.updatecfg |= UPDATE_SETTINGS_CFG;
} else { } else {
return 0; return 0;
} }
break; break;
case TEMP: case TEMP:
camdriv->camera.temp = fVal; camdriv->camera.temp = fVal;
camdriv->camera.updatecfg = 1; camdriv->camera.updatecfg |= UPDATE_SETTINGS_CFG;
break; break;
case THRESH: case THRESH:
if (fVal > 0) { if (fVal > 0) {
camdriv->camera.thresh = fVal; camdriv->camera.thresh = fVal;
camdriv->camera.updatecfg = 1; camdriv->camera.updatecfg |= UPDATE_SETTINGS_CFG;
} else { } else {
return 0; return 0;
} }
@ -461,7 +491,7 @@ static int CamSet(CounterDriver *cntrData, char *name, int iCter, float fVal) {
case SHOPT: case SHOPT:
if (fVal > 0) { if (fVal > 0) {
camdriv->camera.shopt = fVal; camdriv->camera.shopt = fVal;
camdriv->camera.updatecfg = 1; camdriv->camera.updatecfg |= UPDATE_SETTINGS_CFG;
} else { } else {
return 0; return 0;
} }
@ -469,7 +499,7 @@ static int CamSet(CounterDriver *cntrData, char *name, int iCter, float fVal) {
case SHCLT: case SHCLT:
if (fVal > 0) { if (fVal > 0) {
camdriv->camera.shclt = fVal; camdriv->camera.shclt = fVal;
camdriv->camera.updatecfg = 1; camdriv->camera.updatecfg |= UPDATE_SETTINGS_CFG;
} else { } else {
return 0; return 0;
} }
@ -569,7 +599,6 @@ static int CamSend(CounterDriver *cntrData, char *pText, char *pReply, int iRepl
static int cb_shotcmd(pAsyncTxn txn) { static int cb_shotcmd(pAsyncTxn txn) {
CamObj *self = (CamObj *) txn->cntx; CamObj *self = (CamObj *) txn->cntx;
char *resp = txn->inp_buf, message[MSGLEN+1]; char *resp = txn->inp_buf, message[MSGLEN+1];
enum event_codes cd_sym;
if (self->debug) { if (self->debug) {
snprintf(message, MSGLEN, "DEBUG:(cb_shotcmd) Camera reply: %s", resp); snprintf(message, MSGLEN, "DEBUG:(cb_shotcmd) Camera reply: %s", resp);
@ -587,30 +616,44 @@ static int cb_shotcmd(pAsyncTxn txn) {
* it should be fed back into the state transition function. * it should be fed back into the state transition function.
*/ */
int camdriv_out(void *me, event_t Eo) { int camdriv_out(void *me, event_t Eo) {
int len, feedback = 0; int i, len, pend=0;
char cmd[MSGLEN]="", logmsg[MSGLEN+1]=""; char cmd[MSGLEN]="", logmsg[MSGLEN+1]="";
float clock; float clock, fVal;
CamObj *self = (CamObj *)me; CamObj *self = (CamObj *)me;
if (Eo.ca) { if (Eo.ca) {
/* send command to camera */ /* send command to camera */
if (self->debug) {
snprintf(logmsg, MSGLEN, "DEBUG:(camdriv_out:Eo.ca): ev=%s, output=%s\n",
event_names[Eo.ca], event_signatures[Eo.ca]);
SICSLogWrite(logmsg, eLog);
}
switch (Eo.ca) { switch (Eo.ca) {
case ECA_TK_SHOT: case ECA_TK_SHOT:
len = strlen(event_signatures[ECA_TK_SHOT]); len = strlen(event_signatures[ECA_TK_SHOT]);
strncpy(cmd, event_signatures[ECA_TK_SHOT], len); strncpy(cmd, event_signatures[ECA_TK_SHOT], len);
len = strlen(cmd);
AsyncUnitSendTxn(self->asyncUnit, cmd, len, cb_shotcmd, self, MSGLEN);
break; break;
case ECA_MLTI_ON: case ECA_MLTI_ON:
len = strlen(event_signatures[ECA_MLTI_ON]); len = strlen(event_signatures[ECA_MLTI_ON]);
strncpy(cmd, event_signatures[ECA_MLTI_ON], len); strncpy(cmd, event_signatures[ECA_MLTI_ON], len);
len = strlen(cmd);
AsyncUnitSendTxn(self->asyncUnit, cmd, len, cb_shotcmd, self, MSGLEN);
break; break;
case ECA_MLTI_OFF: case ECA_MLTI_OFF:
len = strlen(event_signatures[ECA_MLTI_OFF]); len = strlen(event_signatures[ECA_MLTI_OFF]);
strncpy(cmd, event_signatures[ECA_MLTI_OFF], len); strncpy(cmd, event_signatures[ECA_MLTI_OFF], len);
len = strlen(cmd);
AsyncUnitSendTxn(self->asyncUnit, cmd, len, cb_shotcmd, self, MSGLEN);
break; break;
case ECA_CFG: case ECA_CFG:
if(self->camera.updatecfg) { /* TODO Should we retry sending a command if AsyncUnitSendTxn fails?
* The driver should abort the shot and then try to send the
* configuration the next time a shot is taken. */
if( (self->camera.updatecfg & UPDATE_SETTINGS_CFG) == UPDATE_SETTINGS_CFG) {
clock = self->camera.clockMHz; clock = self->camera.clockMHz;
sprintf(cmd, snprintf(cmd, MSGLEN,
"set camera,clock=%.*fmhz,bin=%dx,size=%d,gain=%dxhs,flip=%s,xstart=%d,ystart=%d,xend=%d,yend=%d,exposure=%f,temperature=%f,threshold=%d,shutteropentime=%d,shutterclosetime=%d", "set camera,clock=%.*fmhz,bin=%dx,size=%d,gain=%dxhs,flip=%s,xstart=%d,ystart=%d,xend=%d,yend=%d,exposure=%f,temperature=%f,threshold=%d,shutteropentime=%d,shutterclosetime=%d",
clock>=1 ? 0 : 1, clock, (int)self->camera.bin, (int)self->camera.size, clock>=1 ? 0 : 1, clock, (int)self->camera.bin, (int)self->camera.size,
(int)self->camera.gain, flipcmdstr[self->camera.flip], (int)self->camera.gain, flipcmdstr[self->camera.flip],
@ -620,7 +663,59 @@ int camdriv_out(void *me, event_t Eo) {
(int)self->camera.shclt (int)self->camera.shclt
); );
len = strlen(cmd); len = strlen(cmd);
self->camera.updatecfg = 0; self->camera.updatecfg &= ~UPDATE_SETTINGS_CFG;
if (self->debug) {
snprintf(logmsg, MSGLEN, "DEBUG:(camdriv_out:UPDATE_SETTINGS_CFG): cmd=%s\n", cmd);
SICSLogWrite(logmsg, eLog);
}
AsyncUnitSendTxn(self->asyncUnit, cmd, len, cb_shotcmd, self, MSGLEN);
}
if( (self->camera.updatecfg & CLEAR_META_CFG) == CLEAR_META_CFG) {
snprintf(cmd, MSGLEN, "clear meta");
len = strlen(cmd);
if (self->debug) {
snprintf(logmsg, MSGLEN, "DEBUG:(camdriv_out:CLEAR_META_CFG): cmd=%s\n", cmd);
SICSLogWrite(logmsg, eLog);
}
AsyncUnitSendTxn(self->asyncUnit, cmd, len, cb_shotcmd, self, MSGLEN);
}
if( (self->camera.updatecfg & UPDATE_META_CFG) == UPDATE_META_CFG) {
//TODO concatenate the meta_list into a comma separated string and send it in MSGLEN chunks.
for (i=0; i < self->camera.meta_count && pend < MSGLEN; i++) {
pend = sprintf(cmd, "set meta,");
pend += snprintf(&cmd[pend], MSGLEN, "%s", self->camera.meta_list[i]);
len = strlen(cmd);
if (self->debug) {
snprintf(logmsg, MSGLEN, "DEBUG:(camdriv_out:UPDATE_META_CFG): cmd=%s\n", cmd);
SICSLogWrite(logmsg, eLog);
}
AsyncUnitSendTxn(self->asyncUnit, cmd, len, cb_shotcmd, self, MSGLEN);
}
}
if( (self->camera.updatecfg & UPDATE_SCANVAR_CFG) == UPDATE_SCANVAR_CFG) {
pend = sprintf(cmd, "set meta");
//TODO Send in MSGLEN chunks even though the string may never exceed MSGLEN
for (i=0; i < self->camera.scanvar_count && pend < MSGLEN; i++) {
fVal = self->camera.pscanvar[i]->GetValue(self->camera.scanvar_dummy[i], pServ->dummyCon);
pend += snprintf(&cmd[pend], MSGLEN, ",%s=%f", self->camera.scanvar_list[i], fVal);
}
len = strlen(cmd);
if (self->debug) {
snprintf(logmsg, MSGLEN, "DEBUG:(camdriv_out:UPDATE_SCANVAR_CFG): cmd=%s\n", cmd);
SICSLogWrite(logmsg, eLog);
}
AsyncUnitSendTxn(self->asyncUnit, cmd, len, cb_shotcmd, self, MSGLEN);
}
if( (self->camera.updatecfg & UPDATE_FILE_CFG) == UPDATE_FILE_CFG) {
snprintf(cmd, MSGLEN, "set file,path=%s,basename=%s,startnumber=%ld,imageformat=%s,experimentdetail=%s",
self->camera.file.path, self->camera.file.basename, self->camera.file.startnumber, self->camera.file.imageformat,self->camera.file.experimentdetail);
len = strlen(cmd);
if (self->debug) {
snprintf(logmsg, MSGLEN, "DEBUG:(camdriv_out:UPDATE_FILE_CFG): cmd=%s\n", cmd);
SICSLogWrite(logmsg, eLog);
}
AsyncUnitSendTxn(self->asyncUnit, cmd, len, cb_shotcmd, self, MSGLEN);
self->camera.updatecfg &= ~UPDATE_FILE_CFG;
} }
break; break;
default: default:
@ -628,12 +723,6 @@ int camdriv_out(void *me, event_t Eo) {
SICSLogWrite(logmsg, eLogError); SICSLogWrite(logmsg, eLogError);
return -1; return -1;
} }
AsyncUnitSendTxn(self->asyncUnit, cmd, len, cb_shotcmd, self, MSGLEN);
if (self->debug) {
snprintf(logmsg, MSGLEN, "DEBUG:(camdriv_out:Eo.ca): ev=%s, output=%s\n",
event_names[Eo.ca], event_signatures[Eo.ca]);
SICSLogWrite(logmsg, eLog);
}
return -1; return -1;
} }
if (Eo.cm) { if (Eo.cm) {
@ -650,6 +739,11 @@ int camdriv_out(void *me, event_t Eo) {
} }
if (Eo.dr) { if (Eo.dr) {
/* send msg to SICS */ /* send msg to SICS */
if (self->debug) {
snprintf(logmsg, MSGLEN, "DEBUG:(camdriv_out): ev=%s, output=%s\n",
event_names[Eo.dr], event_signatures[Eo.dr]);
SICSLogWrite(logmsg, eLog);
}
switch (Eo.dr) { switch (Eo.dr) {
case EDR_IDLE: case EDR_IDLE:
self->status = HWIdle; self->status = HWIdle;
@ -665,11 +759,6 @@ int camdriv_out(void *me, event_t Eo) {
SICSLogWrite(logmsg, eLogError); SICSLogWrite(logmsg, eLogError);
return -1; return -1;
} }
if (self->debug) {
snprintf(logmsg, MSGLEN, "DEBUG:(camdriv_out): ev=%s, output=%s\n",
event_names[Eo.dr], event_signatures[Eo.dr]);
SICSLogWrite(logmsg, eLog);
}
return -1; return -1;
} }
if (Eo.cl) { if (Eo.cl) {
@ -709,7 +798,7 @@ static int cb_state_timer(void *ctx, int mode) {
static int cb_getstate(pAsyncTxn txn) { static int cb_getstate(pAsyncTxn txn) {
CamObj *self = (CamObj *) txn->cntx; CamObj *self = (CamObj *) txn->cntx;
char *resp = txn->inp_buf, message[MSGLEN+1]; char *resp = txn->inp_buf, message[MSGLEN+1];
int len = txn->inp_idx, ret=1, time_rem, time_tot; int ret=1, time_rem, time_tot;
enum event_codes ca_sym, cm_sym; enum event_codes ca_sym, cm_sym;
@ -731,9 +820,182 @@ static int cb_getstate(pAsyncTxn txn) {
return ret; return ret;
} }
/* Auxiliary Camera Driver commands */
int cmd_code(char **cmd_list, char *cmd) {
int i;
for (i=0; cmd_list[i] != NULL; i++)
if (strcasecmp(cmd_list[i], cmd) == 0)
return i;
return -1;
}
int file_cmd(CamObj *camdriv, SConnection *pCon, char *subcmd, char *data) {
int i, subcmd_code, retval = 1;
long numval;
enum file_subcmd_codes {PATH, BASENAME, IMAGEFMT, STARTNUM, EXPDETAIL};
char *file_subcmd_names[] = {"path", "name", "format", "startnumber", "detail", NULL};
char *glemsg = NULL, emsg[MSGLEN];
if ( (subcmd_code = cmd_code(file_subcmd_names, subcmd)) == -1) {
return 0;
}
switch (subcmd_code) {
case PATH:
snprintf(camdriv->camera.file.path, MSGLEN, "%s", data);
break;
case BASENAME:
snprintf(camdriv->camera.file.basename, MSGLEN, "%s", data);
break;
case STARTNUM:
numval = getlong(data, glemsg);
if (glemsg == NULL) {
camdriv->camera.file.startnumber = numval;
} else if (glemsg == data) {
snprintf(emsg, MSGLEN, "CAM:(file_cmd) %s is not an integer", data);
SCWrite(pCon, emsg, eError);
retval = 0;
} else {
snprintf(emsg, MSGLEN, "CAM:(file_cmd) %s", glemsg);
SCWrite(pCon, emsg, eError);
retval = 0;
}
break;
case IMAGEFMT:
if (strcasecmp(data, "tif") == 0) {
for (i=0; data[i]; i++) {
data[i] = tolower(data[i]);
}
snprintf(camdriv->camera.file.imageformat, IFMTLEN, "%s", data);
} else {
retval = 0;
}
break;
case EXPDETAIL:
snprintf(camdriv->camera.file.experimentdetail, MSGLEN, "%s", data);
break;
default:
retval = 0;
}
return retval;
}
/**
* \brief Auxiliary command interface which gets around type and string length
* limitations of the CountAction command.
*/
int CamAuxCmd(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) {
char *cmd = NULL;
char message[MSGLEN];
enum auxcmd_codes {CLEAR_META, META, FILECMD, SCANVAR, MOTOR};
char *auxcmd_names[] = {"clearmeta", "meta", "file", "scanvar", "motor", NULL};
int i, code, retval = 1, pend=0;
CamObj *camdriv = (CamObj *)pData;
CommandList *pCom = NULL;
pIDrivable pDriv = NULL;
pDummy pDumData = NULL;
if (argc < 2) {
snprintf(message, MSGLEN, "CAM: You must specify a command");
SCWrite(pCon, message, eError);
return 0;
}
if ( (code = cmd_code(auxcmd_names, argv[1])) == -1 ) {
snprintf(message, MSGLEN, "CAM: %s is not a valid command", argv[1]);
SCWrite(pCon, message, eError);
retval = 0;
goto END;
}
switch (code) {
case CLEAR_META:
camdriv->camera.meta_count = 0;
camdriv->camera.scanvar_count = 0;
camdriv->camera.updatecfg |= CLEAR_META_CFG;
camdriv->camera.updatecfg &= ~UPDATE_META_CFG;
camdriv->camera.updatecfg &= ~UPDATE_SCANVAR_CFG;
break;
case META:
if (argc < 3) {
snprintf(message, MSGLEN, "CAM: Insufficient arguments, the META command requires name=val data");
SCWrite(pCon, message, eError);
retval = 0;
goto END;
}
if (camdriv->camera.meta_count < MAX_META_COUNT) {
for (i=2; i < argc; i++) {
pend += snprintf(&(camdriv->camera.meta_list[camdriv->camera.meta_count][pend]), MSGLEN, "%s ", argv[i]);
}
camdriv->camera.meta_count++;
camdriv->camera.updatecfg |= UPDATE_META_CFG;
} else {
goto END;
}
break;
case SCANVAR:
case MOTOR:
if (argc < 3) {
snprintf(message, MSGLEN, "CAM: Insufficient arguments, the MOTOR/SCANVAR command requires the name of something you can drive like a motor or environment control");
SCWrite(pCon, message, eError);
retval = 0;
goto END;
}
if (camdriv->camera.scanvar_count < MAX_SCANVAR_COUNT) {
pCom = FindCommand(pSics, argv[2]);
if (!pCom) {
snprintf(message, MSGLEN, "CAM: There is no command object for a driveable with this name %s", argv[2]);
SCWrite(pCon, message, eError);
retval = 0;
goto END;
}
pDumData = (pDummy) pCom->pData;
if (!pDumData) {
snprintf(message, MSGLEN, "CAM: There is no data for the command object of a driveable with this name %s", argv[2]);
SCWrite(pCon, message, eError);
retval = 0;
goto END;
}
pDriv = (pIDrivable) pDumData->pDescriptor->GetInterface(pDumData, DRIVEID);
if (!pDriv) {
snprintf(message, MSGLEN, "CAM: %s is not a driveable object", argv[2]);
SCWrite(pCon, message, eError);
retval = 0;
goto END;
}
camdriv->camera.scanvar_dummy[camdriv->camera.scanvar_count] = pDumData;
camdriv->camera.pscanvar[camdriv->camera.scanvar_count] = pDriv;
snprintf(camdriv->camera.scanvar_list[camdriv->camera.scanvar_count++], NAMELEN, "%s", argv[2]);
camdriv->camera.updatecfg |= UPDATE_SCANVAR_CFG;
} else {
snprintf(message, MSGLEN, "CAM: Exceeded maximum number (%d) of driveable objects", MAX_SCANVAR_COUNT);
SCWrite(pCon, message, eError);
retval = 0;
goto END;
}
break;
case FILECMD:
if (argc < 4) {
snprintf(message, MSGLEN, "CAM: Insufficient arguments for the FILE command");
SCWrite(pCon, message, eError);
retval = 0;
goto END;
}
if (file_cmd(camdriv, pCon, argv[2], argv[3]))
camdriv->camera.updatecfg |= UPDATE_FILE_CFG;
else {
snprintf(message, MSGLEN, "CAM: Failed to create camera file configuration");
SCWrite(pCon, message, eError);
retval = 0;
goto END;
}
break;
}
END:
if (cmd != NULL)
free(cmd);
return retval;
}
pCounterDriver CreateCam(SConnection *pCon, char *name, char *asynq) { pCounterDriver CreateCam(SConnection *pCon, char *name, char *asynq) {
char msg[ERRLEN], cmd[MSGLEN], reply[MSGLEN]; char msg[ERRLEN], cmd[MSGLEN], auxcmd[NAMELEN];
int len, reply_len; int len;
state_t start_state = {.cl=SCL_RDY, .cm=SCM_IDLE, .dr=SDR_IDLE}; state_t start_state = {.cl=SCL_RDY, .cm=SCM_IDLE, .dr=SDR_IDLE};
pCounterDriver pCntDriv = NULL; pCounterDriver pCntDriv = NULL;
@ -741,6 +1003,7 @@ pCounterDriver CreateCam(SConnection *pCon, char *name, char *asynq) {
pNewCam = (CamObj *) malloc(sizeof(CamObj)); pNewCam = (CamObj *) malloc(sizeof(CamObj));
memset(pNewCam, 0, sizeof(CamObj)); memset(pNewCam, 0, sizeof(CamObj));
pNewCam->pDes = CreateDescriptor("CameraCommandObject");
STset(&pNewCam->state_machine.Sc, start_state); STset(&pNewCam->state_machine.Sc, start_state);
EVclr(&pNewCam->state_machine.Eo); EVclr(&pNewCam->state_machine.Eo);
pNewCam->state_machine.output_fn = camdriv_out; pNewCam->state_machine.output_fn = camdriv_out;
@ -749,8 +1012,14 @@ pCounterDriver CreateCam(SConnection *pCon, char *name, char *asynq) {
pNewCam->status = HWIdle; pNewCam->status = HWIdle;
pNewCam->camError = ENONE; pNewCam->camError = ENONE;
pNewCam->debug = 1; pNewCam->debug = 1;
pNewCam->camera.updatecfg = 1; pNewCam->camera.updatecfg = 0;
pNewCam->camera.meta_count = 0;
pNewCam->camera.scanvar_count = 0;
pNewCam->camera.file.startnumber = 1;
snprintf(pNewCam->camera.file.imageformat, IFMTLEN, "tif");
pNewCam->camera.file.experimentdetail[0] = '\0';
pNewCam->asynq = strdup(asynq); pNewCam->asynq = strdup(asynq);
pNewCam->pSics = pServ->pSics;
if (!AsyncUnitCreate(asynq, &pNewCam->asyncUnit)) { if (!AsyncUnitCreate(asynq, &pNewCam->asyncUnit)) {
snprintf(msg, ERRLEN, "CAM:AsyncQueue %s has not been defined", asynq); snprintf(msg, ERRLEN, "CAM:AsyncQueue %s has not been defined", asynq);
@ -783,5 +1052,8 @@ pCounterDriver CreateCam(SConnection *pCon, char *name, char *asynq) {
len = strlen(event_signatures[ECA_GET_STATE]); len = strlen(event_signatures[ECA_GET_STATE]);
strncpy(cmd, event_signatures[ECA_GET_STATE], len); strncpy(cmd, event_signatures[ECA_GET_STATE], len);
NetWatchRegisterTimerPeriodic(&pNewCam->state_timer, 2000, 500, cb_state_timer, pNewCam); NetWatchRegisterTimerPeriodic(&pNewCam->state_timer, 2000, 500, cb_state_timer, pNewCam);
snprintf(auxcmd, NAMELEN, "%s_cmd", name);
AddCommand(pNewCam->pSics, auxcmd, CamAuxCmd, NULL, pNewCam);
return pCntDriv; return pCntDriv;
} }