Upload camera configuration if it has changed before sending

a "take shot" or "take multi on" command.  Incorporate Vijay's changes
to the "set camera," parameters.
This commit is contained in:
Ferdi Franceschini
2013-02-26 01:02:25 +11:00
parent 743c52d905
commit 87559bf411
9 changed files with 394 additions and 189 deletions

View File

@@ -1,7 +1,7 @@
# vim: ft=make: ts=8: sw=8: noet: cindent: # vim: ft=make: ts=8: sw=8: noet: cindent:
all: camera_test.c ../../hardsup/camera.c ../../hardsup/camera.h all: camera_test.c ../../hardsup/camera.c ../../hardsup/camera.h
gcc -g -Wall -Wextra -std=c99 -pedantic -I../../ -o camera_test camera_test.c ../../camera.c gcc -g -Wall -Wextra -std=c99 -pedantic -I../../hardsup -o camera_test camera_test.c ../../hardsup/camera.c
clean: clean:
rm camera_test rm camera_test

View File

@@ -0,0 +1,2 @@
input: ECD_TK_SHOT :SCM_IDLE,SCL_RDY,SDR_IDLEcamdriv_out: symbol=EDR_BUSY, output=HWBUSY
input: ECM_IDLE :SCM_IDLE,SCL_TK_SHOT,SDR_BUSYcamdriv_out: symbol=ECA_TK_SHOT, output=take shot

View File

@@ -1,4 +1,9 @@
/**
* \file camera_test.c
* \brief Test camera.[ch] state machine.
*
* \Author Ferdi Franceschini February 2013
*/
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@@ -50,17 +55,24 @@ int test_camrep2sym(void) {
NULL NULL
}; };
fprintf(stderr, "TEST_CAMREP2SYM:DESCRIPTION: Parse camera status messages and convert them to camera events and camera model events\n");
fprintf(stderr, "TEST_CAMREP2SYM:DESCRIPTION: Output format = 'status message' => camera_symbol => camera_model_symbol\n");
fprintf(stderr, "TEST_CAMREP2SYM:OUTPUT:START\n");
for (i=0; camrep[i] != NULL; i++) { for (i=0; camrep[i] != NULL; i++) {
if ( cam_parse_status(camrep[i], &ca_sym, &time_rem, &time_tot) == -1) if ( cam_parse_status(camrep[i], &ca_sym, &time_rem, &time_tot) == -1)
exit(1); exit(1);
else { else {
cm_sym = camera_model(ca_sym); cm_sym = camera_model(ca_sym);
if (ECA_IDLE==ca_sym) if (ECA_IDLE==ca_sym)
printf("%s(%s) <- %s\n", event_names[cm_sym], event_names[ca_sym], camrep[i] ); printf("'%s' => %s => %s\n",
camrep[i], event_names[ca_sym], event_names[cm_sym]);
else else
printf("%s(%s): time remaining = %d, total time = %d\n",event_names[cm_sym], event_names[ca_sym], time_rem, time_tot); printf("'%s' => %s => %s: time remaining = %d, total time = %d\n",
camrep[i], event_names[ca_sym], event_names[cm_sym],
time_rem, time_tot);
} }
} }
fprintf(stderr, "TEST_CAMREP2SYM:OUTPUT:END\n\n");
return 1; return 1;
} }
@@ -76,6 +88,10 @@ int test_trans_fn(void) {
ECM_PROC, ECM_IDLE, 0 ECM_PROC, ECM_IDLE, 0
}; };
fprintf(stderr, "TEST_TRANS_FN:DESCRIPTION: Test the state transitions. Each line of ouput has three fields.\n");
fprintf(stderr, "TEST_TRANS_FN:DESCRIPTION: Output pattern ~= Ein Scurr Eout\n");
fprintf(stderr, "TEST_TRANS_FN:DESCRIPTION: You can follow the transitions by reading down the Scurr column\n");
fprintf(stderr, "TEST_TRANS_FN:OUTPUT:START\n");
printf("INPUT,\tCURR SCM,CURR SCL,CURR SDR,\tCA OUT,CM OUT,CD OUT,DR OUT\n"); printf("INPUT,\tCURR SCM,CURR SCL,CURR SDR,\tCA OUT,CM OUT,CD OUT,DR OUT\n");
for (i=0; input[i]; i++) { for (i=0; input[i]; i++) {
EVclr(&Eo); EVclr(&Eo);
@@ -86,39 +102,52 @@ int test_trans_fn(void) {
print_event(Eo); print_event(Eo);
printf("\n"); printf("\n");
} }
fprintf(stderr, "TEST_TRANS_FN:OUTPUT:END\n");
return 1; return 1;
} }
int camdriv_out(void *me, event_t Eo) { int camdriv_out(void *me, event_t Eo) {
int *self = me; int *self = me; *self=0; /* shudduppa your warnings */
*self=0; /* shudduppa your warnings */
if (Eo.ca) { if (Eo.ca) {
/* send command to camera */ printf("camdriv_out: symbol=%s, output=%s\n", event_names[Eo.ca], event_signatures[Eo.ca]);
printf("camdriv_out: ev=%s, output=%s\n", event_names[Eo.ca], event_signatures[Eo.ca]);
} }
if (Eo.cm) { if (Eo.cm) {
printf("camdriv_out: ev=%s, output=%s\n", event_names[Eo.cm], event_signatures[Eo.cm]); printf("camdriv_out: symbol=%s, output=%s\n", event_names[Eo.cm], event_signatures[Eo.cm]);
} }
if (Eo.cd) { if (Eo.cd) {
printf("camdriv_out: ev=%s, output=%s\n", event_names[Eo.cd], event_signatures[Eo.cd]); printf("camdriv_out: symbol=%s, output=%s\n", event_names[Eo.cd], event_signatures[Eo.cd]);
} }
if (Eo.dr) { if (Eo.dr) {
/* send msg to SICS */ printf("camdriv_out: symbol=%s, output=%s\n", event_names[Eo.dr], event_signatures[Eo.dr]);
printf("camdriv_out: ev=%s, output=%s\n", event_names[Eo.dr], event_signatures[Eo.dr]);
} }
return 1; return 1;
} }
int test_camdriv_input(void) {
int test_camdriv_event_io(void) {
int Ein=ECD_TK_SHOT; int Ein=ECD_TK_SHOT;
int self; int self;
camdriv_t cdinfo = { camsm_t cdinfo = {
.Sc = {.cl=SCL_RDY, .cm=SCM_IDLE, .dr=SDR_IDLE}, .Sc = {.cl=SCL_RDY, .cm=SCM_IDLE, .dr=SDR_IDLE},
.Eo = {.ca=0}, .Eo = {.ca=0},
.multi = 0, .multi = 0,
.output_fn = camdriv_out, .output_fn = camdriv_out,
}; };
fprintf(stderr, "TEST_CAMDRIVER_EVENT_IO:DESCRIPTION: Test State machine output_fn callback\n");
fprintf(stderr, "TEST_CAMDRIVER_EVENT_IO:DESCRIPTION: Output pattern ~= Ein:Scurr:Eo:output message\n");
fprintf(stderr, "TEST_CAMDRIVER_EVENT_IO:OUPUT:START\n");
printf("input: %s :", event_names[Ein]);
print_state(cdinfo.Sc);
camdriv_input(&self, &cdinfo, Ein); camdriv_input(&self, &cdinfo, Ein);
Ein = ECM_IDLE;
printf("input: %s :", event_names[Ein]);
cdinfo.Sc.cl=SCL_TK_SHOT;
print_state(cdinfo.Sc);
camdriv_input(&self, &cdinfo, Ein);
fprintf(stderr, "TEST_CAMDRIVER_EVENT_IO:OUPUT:END\n");
return 1; return 1;
} }
@@ -156,7 +185,7 @@ int main(int argc, char *argv[]) {
if (test & 2) if (test & 2)
ret = test_trans_fn(); ret = test_trans_fn();
if (test & 4) if (test & 4)
ret = test_camdriv_input(); ret = test_camdriv_event_io();
if (ret) if (ret)
return 0; return 0;

View File

@@ -0,0 +1,8 @@
'StartTime Remaining= 3907 ms, Total Time=3686 ms,' => ECA_START => ECM_ACQ: time remaining = 3907, total time = 3686
'Open ShutrTime Remaining= 539454 ms, Total Time=3686 ms,' => ECA_OPEN_SHUTR => ECM_ACQ: time remaining = 539454, total time = 3686
'Acq ImageTime Remaining= 109 ms, Total Time=3686 ms,' => ECA_ACQ_IMAGE => ECM_ACQ: time remaining = 109, total time = 3686
'Close ShutrTime Remaining= 218 ms, Total Time=3686 ms,' => ECA_CLOSE_SHUTR => ECM_PROC: time remaining = 218, total time = 3686
'Read ImageTime Remaining= 328 ms, Total Time=3686 ms,' => ECA_READ_IMAGE => ECM_PROC: time remaining = 328, total time = 3686
'Read ImageTime Remaining= 328 ms, Total Time=3686 ms,' => ECA_READ_IMAGE => ECM_PROC: time remaining = 328, total time = 3686
'Read ImageTime Remaining= 328 ms, Total Time=3686 ms,' => ECA_READ_IMAGE => ECM_PROC: time remaining = 328, total time = 3686
'Idle' => ECA_IDLE => ECM_IDLE

View File

@@ -1,22 +1,14 @@
ECM_ACQ(ECA_START): time remaining = 3907, total time = 3686
ECM_ACQ(ECA_OPEN_SHUTR): time remaining = 539454, total time = 3686
ECM_ACQ(ECA_ACQ_IMAGE): time remaining = 109, total time = 3686
ECM_PROC(ECA_CLOSE_SHUTR): time remaining = 218, total time = 3686
ECM_PROC(ECA_READ_IMAGE): time remaining = 328, total time = 3686
ECM_PROC(ECA_READ_IMAGE): time remaining = 328, total time = 3686
ECM_PROC(ECA_READ_IMAGE): time remaining = 328, total time = 3686
ECM_IDLE(ECA_IDLE) <- Idle
INPUT, CURR SCM,CURR SCL,CURR SDR, CA OUT,CM OUT,CD OUT,DR OUT INPUT, CURR SCM,CURR SCL,CURR SDR, CA OUT,CM OUT,CD OUT,DR OUT
ECM_IDLE, SCM_IDLE,SCL_RDY,SDR_IDLE, 0,0,0,0 ECM_IDLE, SCM_IDLE,SCL_RDY,SDR_IDLE, 0,0,0,0
ECD_TK_SHOT, SCM_IDLE,SCL_RDY,SDR_IDLE, 0,0,0,EDR_BUSY ECD_TK_SHOT, SCM_IDLE,SCL_RDY,SDR_IDLE, 0,0,0,EDR_BUSY
ECM_IDLE, SCM_IDLE,SCL_TK_SHOT,SDR_BUSY, ECA_TK_SHOT,0,0,0 ECM_IDLE, SCM_IDLE,SCL_TK_SHOT,SDR_BUSY, ECA_TK_SHOT,0,0,0
ECM_IDLE, SCM_IDLE,SCL_WT_ACQ,SDR_BUSY, 0,0,0,0 ECM_IDLE, SCM_IDLE,SCL_WT,SDR_BUSY, 0,0,0,0
ECM_ACQ, SCM_IDLE,SCL_RDY,SDR_BUSY, 0,0,0,0 ECM_ACQ, SCM_IDLE,SCL_RDY,SDR_BUSY, 0,0,0,0
ECD_TK_SHOT, SCM_ACQ,SCL_RDY,SDR_BUSY, 0,0,0,0 ECD_TK_SHOT, SCM_ACQ,SCL_RDY,SDR_BUSY, 0,0,0,0
ECM_PROC, SCM_ACQ,SCL_RDY,SDR_BUSY, 0,0,0,EDR_IDLE ECM_PROC, SCM_ACQ,SCL_RDY,SDR_BUSY, 0,0,0,EDR_IDLE
ECD_TK_SHOT, SCM_PROC,SCL_RDY,SDR_IDLE, 0,0,0,EDR_BUSY ECD_TK_SHOT, SCM_PROC,SCL_RDY,SDR_IDLE, 0,0,0,EDR_BUSY
ECM_PROC, SCM_PROC,SCL_TK_SHOT,SDR_BUSY, 0,0,0,0 ECM_PROC, SCM_PROC,SCL_TK_SHOT,SDR_BUSY, 0,0,0,0
ECM_IDLE, SCM_PROC,SCL_TK_SHOT,SDR_BUSY, ECA_TK_SHOT,0,0,0 ECM_IDLE, SCM_PROC,SCL_TK_SHOT,SDR_BUSY, ECA_TK_SHOT,0,0,0
ECM_ACQ, SCM_IDLE,SCL_WT_ACQ,SDR_BUSY, 0,0,0,0 ECM_ACQ, SCM_IDLE,SCL_WT,SDR_BUSY, 0,0,0,0
ECM_PROC, SCM_ACQ,SCL_RDY,SDR_BUSY, 0,0,0,EDR_IDLE ECM_PROC, SCM_ACQ,SCL_RDY,SDR_BUSY, 0,0,0,EDR_IDLE
ECM_IDLE, SCM_PROC,SCL_RDY,SDR_IDLE, 0,0,0,0 ECM_IDLE, SCM_PROC,SCL_RDY,SDR_IDLE, 0,0,0,0

View File

@@ -51,12 +51,9 @@ void EVset(event_t *E, event_t Ev) {
/* Set system state */ /* Set system state */
void STset(state_t *Sc, state_t St) { void STset(state_t *Sc, state_t St) {
if (St.cl) if (St.cl) Sc->cl = St.cl;
Sc->cl = St.cl; if (St.cm) Sc->cm = St.cm;
if (St.cm) if (St.dr) Sc->dr = St.dr;
Sc->cm = St.cm;
if (St.dr)
Sc->dr = St.dr;
} }
enum event_codes camera_model(enum event_codes event) { enum event_codes camera_model(enum event_codes event) {
@@ -81,9 +78,6 @@ enum event_codes camera_model(enum event_codes event) {
return ECM_UNKNOWN; return ECM_UNKNOWN;
} }
} }
/* NOTE the state is actually of the form (SCL_X,SCM_X,SDR_X)
* the table only shows the part of the state tuple which must match.
*/
int cam_parse_status(char *msg, enum event_codes *ca_sym, int *time_rem, int *time_tot) { int cam_parse_status(char *msg, enum event_codes *ca_sym, int *time_rem, int *time_tot) {
char *delim=" ,"; char *delim=" ,";
@@ -104,6 +98,7 @@ int cam_parse_status(char *msg, enum event_codes *ca_sym, int *time_rem, int *ti
} }
return ret; return ret;
} }
/* return -1 if message is unknown /* return -1 if message is unknown
* NOTE: 0 has meaning in the transition table * NOTE: 0 has meaning in the transition table
*/ */
@@ -137,7 +132,8 @@ int cam_trans_fn(state_t Sc, enum event_codes Ein, state_t *Sn, event_t *Eo) {
return ret; return ret;
} }
void camdriv_input(void *caller, camdriv_t *self, enum event_codes event_sym) { /* TODO Do we need Eo in self, should camsm_t be refactored to remove it? */
void camdriv_input(void *caller, camsm_t *self, enum event_codes event_sym) {
state_t Sn; state_t Sn;
cam_trans_fn(self->Sc, event_sym, &Sn, &self->Eo); cam_trans_fn(self->Sc, event_sym, &Sn, &self->Eo);
self->output_fn(caller, self->Eo); self->output_fn(caller, self->Eo);
@@ -163,35 +159,52 @@ char *strevent(event_t E) {
return event_str; return event_str;
} }
/* 0 = wildcard for states. /* The transition table has four columns,
* {current state}, input_event, {output events}, {next state}
*
* Each state is actually a 3-tuple (cl,cm,dr) where
* cl = command latch state
* cm = camera model state
* dr = driver state
*
* There is only one stream in the input event channel.
*
* The output event channel is a 4-tuple (ca,cm,cd,dr) where
* ca = camera event stream
* cm = cameram model event stream
* cd = command event stream
* dr = driver event stream
*
* The next state is a 3-tuple as above.
*
* 0 = wildcard for components of current state.
* 0 = no output for the output events. * 0 = no output for the output events.
* 0 = no change for components of next state.
*/ */
int START_STATE = SCL_RDY|SCM_IDLE|SDR_IDLE;
trans_t TRANS_TABLE[] = { trans_t TRANS_TABLE[] = {
{{.cl=SCL_RDY, .dr=SDR_IDLE}, ECD_TK_SHOT,{.dr=0}, {.cl=SCL_TK_SHOT}}, {{.cl=SCL_RDY, .dr=SDR_IDLE}, ECD_TK_SHOT, {.dr=0}, {.cl=SCL_TK_SHOT}},
{{.cl=SCL_RDY, .dr=SDR_IDLE}, ECD_TK_MLTI,{.dr=0}, {.cl=SCL_TK_MLTI}}, {{.cl=SCL_RDY, .dr=SDR_IDLE}, ECD_MLTI_ON, {.dr=0}, {.cl=SCL_TK_MLTI}},
{{.cl=SCL_TK_SHOT}, ECM_IDLE, {.ca=ECA_TK_SHOT}, {.cl=SCL_WT_ACQ}}, {{.cl=SCL_TK_SHOT}, ECM_IDLE, {.ca=ECA_TK_SHOT}, {.cl=SCL_WT}},
{{.cl=SCL_TK_MLTI}, ECM_IDLE, {.ca=ECA_MLTI_ON}, {.cl=SCL_WT_ACQ}}, {{.cl=SCL_TK_MLTI}, ECD_MLTI_OFF,{.dr=0}, {.cl=SCL_RDY}},
{{.cl=SCL_TK_SHOT}, ECD_CLEAR, {.dr=0}, {.cl=SCL_RDY}}, {{.cl=SCL_TK_MLTI}, ECM_IDLE, {.ca=ECA_MLTI_ON}, {.cl=SCL_MLTI_ON}},
{{.cl=SCL_TK_MLTI}, ECD_CLEAR, {.dr=0}, {.cl=SCL_RDY}}, {{.cl=SCL_MLTI_ON}, ECD_MLTI_OFF,{.ca=ECA_MLTI_OFF},{.cl=SCL_WT}},
{{.cl=SCL_WT_ACQ}, ECM_ACQ, {.dr=0}, {.cl=SCL_RDY}}, {{.cl=SCL_WT}, ECM_ACQ, {.dr=0}, {.cl=SCL_RDY}},
{{.cl=SCL_WT_ACQ}, ECM_PROC, {.dr=0}, {.cl=SCL_RDY}}, {{.cl=SCL_WT}, ECM_PROC, {.dr=0}, {.cl=SCL_RDY}},
{{.cl=SCL_WT_ACQ}, ECM_STOP, {.dr=0}, {.cl=SCL_RDY}}, {{.cl=SCL_WT}, ECM_STOP, {.dr=0}, {.cl=SCL_RDY}},
/* ffr: Uncomment when we're sure that we don't receive "Idle" after "take shot" {{.cl=SCL_WT}, ECM_IDLE, {.dr=0}, {.cl=SCL_RDY}},
* {{.cl=SCL_WT_ACQ}, ECM_IDLE, {.dr=0}, {.cl=SCL_RDY}},*/
{{.cm=SCM_IDLE}, ECM_ACQ, {.dr=0}, {.cm=SCM_ACQ}}, {{.cm=SCM_IDLE}, ECM_ACQ, {.dr=0}, {.cm=SCM_ACQ}},
{{.cm=SCM_IDLE}, ECM_PROC, {.dr=0}, {.cm=SCM_PROC}}, {{.cm=SCM_IDLE}, ECM_PROC, {.dr=0}, {.cm=SCM_PROC}},
{{.cm=SCM_ACQ}, ECM_PROC, {.dr=0}, {.cm=SCM_PROC}}, {{.cm=SCM_ACQ}, ECM_PROC, {.dr=0}, {.cm=SCM_PROC}},
{{.cm=SCM_ACQ}, ECM_STOP, {.dr=0}, {.cm=SCM_IDLE}}, {{.cm=SCM_ACQ}, ECM_STOP, {.dr=0}, {.cm=SCM_IDLE}},
{{.cm=SCM_PROC}, ECM_STOP, {.dr=0}, {.cm=SCM_IDLE}}, {{.cm=SCM_PROC}, ECM_STOP, {.dr=0}, {.cm=SCM_IDLE}},
{{.cm=SCM_ACQ}, ECM_IDLE, {.dr=0}, {.cm=SCM_IDLE}}, {{.cm=SCM_ACQ}, ECM_IDLE, {.dr=0}, {.cm=SCM_IDLE}},
{{.cm=SCM_PROC}, ECM_IDLE, {.dr=0}, {.cm=SCM_IDLE}}, {{.cm=SCM_PROC}, ECM_IDLE, {.dr=0}, {.cm=SCM_IDLE}},
{{.dr=SDR_IDLE}, ECD_TK_SHOT,{.dr=EDR_BUSY}, {.dr=SDR_BUSY}}, {{.dr=SDR_IDLE}, ECD_TK_SHOT, {.dr=EDR_BUSY}, {.dr=SDR_BUSY}},
{{.dr=SDR_IDLE}, ECD_TK_MLTI,{.dr=EDR_BUSY}, {.dr=SDR_BUSY}}, {{.dr=SDR_IDLE}, ECD_MLTI_ON, {.dr=EDR_BUSY}, {.dr=SDR_BUSY}},
{{.dr=SDR_BUSY, .cl=SCL_RDY}, ECM_PROC, {.dr=EDR_IDLE}, {.dr=SDR_IDLE}}, {{.dr=SDR_BUSY, .cl=SCL_RDY}, ECM_PROC, {.dr=EDR_IDLE}, {.dr=SDR_IDLE}},
{{.dr=SDR_BUSY, .cl=SCL_RDY}, ECM_STOP, {.dr=EDR_IDLE}, {.dr=SDR_IDLE}}, {{.dr=SDR_BUSY, .cl=SCL_RDY}, ECM_STOP, {.dr=EDR_IDLE}, {.dr=SDR_IDLE}},
{{.dr=SDR_BUSY, .cl=SCL_RDY}, ECM_IDLE, {.dr=EDR_IDLE}, {.dr=SDR_IDLE}}, {{.dr=SDR_BUSY, .cl=SCL_RDY}, ECM_IDLE, {.dr=EDR_IDLE}, {.dr=SDR_IDLE}},
{{.dr=END_TABLE}, END_TABLE, {.dr=END_TABLE}, {.dr=END_TABLE}} {{.dr=END_TABLE}, END_TABLE, {.dr=END_TABLE}, {.dr=END_TABLE}}
}; };

View File

@@ -1,8 +1,20 @@
/* Deterministic Finite State machine transducer (Mealy) /**
* The system is made up of three commponents, a command latch (CL), a camera * \file camera.h
* \brief Defines enumeration of event codes and states as well as the abstract
* types used in the state machine.
*
* \Author Ferdi Franceschini February 2013
*
* Copyright: see file Copyright.txt
*
* Deterministic Finite State machine transducer (Mealy)
* The idea is to synthesize a state machine which handles the union of input
* events for a given set state machines in a system.
*
* The system is made up of three components, a command latch (CL), a camera
* model (CM) and the driver (DR). The system state machine is considered to be * model (CM) and the driver (DR). The system state machine is considered to be
* made up of the component state machines running in parallel and with some of * made up of the component state machines running in parallel and with some of
* the component stae machine transitions being restricted by system state * the component state machine transitions being restricted by system state
* transition rules. * transition rules.
* The sets of states are, * The sets of states are,
* SCL:Command Latch states, SCM:Camera Model states, SCDR:Driver states. * SCL:Command Latch states, SCM:Camera Model states, SCDR:Driver states.
@@ -11,23 +23,19 @@
* ECA:Camera events, ECM:Camera model events, ECD:User command events, * ECA:Camera events, ECM:Camera model events, ECD:User command events,
* EDR:Driver events. * EDR:Driver events.
* *
* The system state machine for the camera driver is defined as follows.
* In the following, '<' means subset * In the following, '<' means subset
* Q < SCL X SCM X SCDR * Q < SCL X SCM X SCDR
* Ein = ECA U ECM U ECD U EDR * Ein = ECA U ECM U ECD U EDR
* Eo < ECA X ECM X ECD X EDR * Eo < ECA X ECM X ECD X EDR
* trans fn: QXEin -> Q * trans fn: QXEin -> Q
* out fn : QXEin -> Eo * out fn : QXEin -> Eo
* *
* In the implementation the transition and output functions are combined in * In the implementation the transition and output functions are combined in
* TRANS_TABLE. * TRANS_TABLE.
*/ */
#ifndef CAMERA_H #ifndef CAMERA_H
#define CAMERA_H #define CAMERA_H
/* TODO
* int output(state, event) return output event code
* int transition(state,event) return next state
*
*/
/* END_TABLE marks the last row in the transition table */ /* END_TABLE marks the last row in the transition table */
#define END_TABLE -1 #define END_TABLE -1
@@ -39,17 +47,18 @@
* EDR_ : Driver events * EDR_ : Driver events
*/ */
#define CAMERA_CMDS_TABLE \ #define CAMERA_CMDS_TABLE \
TR(ECA_TK_SHOT, "take shot") \ TR(ECA_SET_CAM, "set camera") \
TR(ECA_MLTI_ON, "take multi on") \ TR(ECA_TK_SHOT, "take shot") \
TR(ECA_MLTI_OFF, "take multi off") \ TR(ECA_MLTI_ON, "take multi on") \
TR(ECA_GET_STATUS, "get status") \ TR(ECA_MLTI_OFF, "take multi off") \
TR(ECA_GET_STATUS, "get status") \
TE(ECA_GET_STATE, "get state") TE(ECA_GET_STATE, "get state")
#define CAMERA_MSGS_TABLE \ #define CAMERA_MSGS_TABLE \
TR(ECA_START, "StartTime") \ TR(ECA_START, "StartTime") \
TR(ECA_OK, "OK") \ TR(ECA_OK, "OK") \
TR(ECA_FAIL, "Fail") \ TR(ECA_FAIL, "Fail") \
TR(ECA_IDLE, "Idle") \ TR(ECA_IDLE, "Idle") \
TR(ECA_OPEN_SHUTR, "Open") \ TR(ECA_OPEN_SHUTR, "Open") \
TR(ECA_CLOSE_SHUTR, "Close") \ TR(ECA_CLOSE_SHUTR, "Close") \
TR(ECA_ACQ_IMAGE, "Acq") \ TR(ECA_ACQ_IMAGE, "Acq") \
@@ -57,12 +66,12 @@
TR(ECA_SEND_IMAGE, "Send") \ TR(ECA_SEND_IMAGE, "Send") \
TE(ECA_STOP, "Stop") TE(ECA_STOP, "Stop")
#define CAM_MOD_EVENT_TABLE \ #define CAM_MOD_EVENT_TABLE \
TR(ECM_UNKNOWN, "Stop message received from camera") \ TR(ECM_UNKNOWN, "Stop message received from camera") \
TR(ECM_STOP, "Stop message received from camera") \ TR(ECM_STOP, "Stop message received from camera") \
TR(ECM_IDLE, "Camera in idle state") \ TR(ECM_IDLE, "Camera in idle state") \
TR(ECM_FAIL, "Command rejected") \ TR(ECM_FAIL, "Command rejected") \
TR(ECM_ACQ, "catch-all for start of acq phase") \ TR(ECM_ACQ, "catch-all for start of acq phase") \
TE(ECM_PROC, "catch-all for end of acq phase") TE(ECM_PROC, "catch-all for end of acq phase")
/* COMMAND EVENTS /* COMMAND EVENTS
@@ -71,14 +80,15 @@
* indirect via the scan command through the counter interface. * indirect via the scan command through the counter interface.
*/ */
#define CMD_EVENT_TABLE \ #define CMD_EVENT_TABLE \
TR(ECD_CMD_INPUT, "received a command") \
TR(ECD_CLEAR, "Clear latched command") \ TR(ECD_CLEAR, "Clear latched command") \
TR(ECD_TK_SHOT, "take shot") \ TR(ECD_TK_SHOT, "take shot") \
TR(ECD_TK_MLTI, "take multi on") \ TR(ECD_MLTI_ON, "take multi on") \
TR(ECD_MLTI_OFF, "take multi off") \
TR(ECD_GET_STATE, "get state") \ TR(ECD_GET_STATE, "get state") \
TE(ECD_GET_STATUS, "get status") TE(ECD_GET_STATUS, "get status")
/* DRIVER EVENT TABLE /* DRIVER EVENT TABLE
* These events are of interest to SICS.
*/ */
#define DRIVER_EVENT_TABLE \ #define DRIVER_EVENT_TABLE \
TR(EDR_IDLE, "HWIDLE") \ TR(EDR_IDLE, "HWIDLE") \
@@ -88,17 +98,17 @@
#define ESLEN 32 #define ESLEN 32
/* STATE CODES /* STATE CODES
* NOTE: Every state will respond to a timer event and
* SXX_ State code enum constants, XX identifies a component of the system. * SXX_ State code enum constants, XX identifies a component of the system.
* SCL_ Command latch states * SCL_ Command latch states
* SCM_ Camera model states * SCM_ Camera model states
* SDR_ Driver states * SDR_ Driver states
*/ */
#define COMMAND_LATCH_STATE_TABLE \ #define COMMAND_LATCH_STATE_TABLE \
TR(SCL_RDY, "command latch ready to accept") \ TR(SCL_RDY, "command latch ready to accept") \
TR(SCL_TK_SHOT, "latched a take shot command") \ TR(SCL_TK_SHOT, "latched a take shot command") \
TR(SCL_TK_MLTI, "latched a multi-shot command") \ TR(SCL_TK_MLTI, "latched a multi-shot command") \
TE(SCL_WT_ACQ, "waiting for camera to start acquisition") TR(SCL_MLTI_ON, "multi-shot is running") \
TE(SCL_WT, "waiting for camera to start acquisition")
#define CAMERA_MODEL_STATE_TABLE \ #define CAMERA_MODEL_STATE_TABLE \
TR(SCM_IDLE, "Camera is idle") \ TR(SCM_IDLE, "Camera is idle") \
@@ -112,7 +122,7 @@
#define SSLEN 32 #define SSLEN 32
/* Generate event and state symbols */ /* Enumerate event and state symbols */
#define TR(a,b) a, #define TR(a,b) a,
#define TE(a,b) a #define TE(a,b) a
enum event_codes {ECA_UNKNOWN, CAMERA_CMDS_TABLE, CAMERA_MSGS_TABLE, CAM_MOD_EVENT_TABLE, DRIVER_EVENT_TABLE, CMD_EVENT_TABLE}; enum event_codes {ECA_UNKNOWN, CAMERA_CMDS_TABLE, CAMERA_MSGS_TABLE, CAM_MOD_EVENT_TABLE, DRIVER_EVENT_TABLE, CMD_EVENT_TABLE};
@@ -130,10 +140,12 @@ enum driver_states {DR_Z,DRIVER_STATE_TABLE};
extern char *SCL_NAMES[]; extern char *SCL_NAMES[];
extern char *SCM_NAMES[]; extern char *SCM_NAMES[];
extern char *SDR_NAMES[]; extern char *SDR_NAMES[];
/* List of names generated from the event_codes. Defined in camera.c. */ /* List of names generated from the event_codes. */
extern char *event_names[]; extern char *event_names[];
/* The signature array defines the identifying characters at the start of a reply. */ /* The signature array includes the identifying characters at the start of a reply.
* as well as camera commands or just describes the corresponding symbols.
*/
extern char *event_signatures[]; extern char *event_signatures[];
@@ -148,12 +160,15 @@ typedef struct {
enum event_codes cd; enum event_codes cd;
enum event_codes dr; enum event_codes dr;
} event_t; } event_t;
/* A tuple (Scl,Scm,Sdr) in SCL X SCM X SDR */ /* A tuple (Scl,Scm,Sdr) in SCL X SCM X SDR */
typedef struct { typedef struct {
int cl; int cl;
int cm; int cm;
int dr; int dr;
} state_t; } state_t;
/* Defines a row in the transition table */
typedef struct { typedef struct {
state_t Sc; state_t Sc;
enum event_codes Ei; enum event_codes Ei;
@@ -161,25 +176,36 @@ typedef struct {
state_t Sn; state_t Sn;
} trans_t; } trans_t;
/* Transfer object for state machine IO and transitions
* output_fn: This is the output function callback. It must be defined by the
* IO layer (ie cameradriver.c).
*/
typedef struct { typedef struct {
state_t Sc; state_t Sc;
event_t Eo; event_t Eo;
int multi; int multi;
int debug;
int (*output_fn)(void *caller, event_t Eo); int (*output_fn)(void *caller, event_t Eo);
} camdriv_t; } camsm_t;
/* True if system state Sc is in St. /* Are we in the SCL_XX, SCM_ or SDR_ state?
* St is normally the current state in the transition table * NOTE: 0 is a wildcard so any Sc.cl value matches St.cl==0
* and describes a range of possible states.
*/ */
#define INCL(Sc,St) (!St.cl || Sc.cl==St.cl) #define INCL(Sc,St) (!St.cl || Sc.cl==St.cl)
#define INCM(Sc,St) (!St.cm || Sc.cm==St.cm) #define INCM(Sc,St) (!St.cm || Sc.cm==St.cm)
#define INDR(Sc,St) (!St.dr || Sc.dr==St.dr) #define INDR(Sc,St) (!St.dr || Sc.dr==St.dr)
/* INSYS is True if system state Sc is in St.
* St is normally the current state in the transition table
* and describes a range of possible states.
*/
#define INSYS(Sc,St) ( INCL(Sc,St) && INCM(Sc,St) && INDR(Sc,St) ) #define INSYS(Sc,St) ( INCL(Sc,St) && INCM(Sc,St) && INDR(Sc,St) )
/* Clear the given event */
void EVclr(event_t *E); void EVclr(event_t *E);
/* Set E to Ev */
void EVset(event_t *E, event_t Ev); void EVset(event_t *E, event_t Ev);
/* Set Sc to St */
void STset(state_t *Sc, state_t St); void STset(state_t *Sc, state_t St);
/* \brief Translates a camera status message to a camera (ECA_) event */ /* \brief Translates a camera status message to a camera (ECA_) event */
@@ -205,9 +231,17 @@ int cam_parse_status(char *msg, enum event_codes *ca_sym, int *time_rem, int *ti
*/ */
int cam_trans_fn(state_t Sc, enum event_codes Ein, state_t *Sn, event_t *Eo); int cam_trans_fn(state_t Sc, enum event_codes Ein, state_t *Sn, event_t *Eo);
void camdriv_input(void *caller, camdriv_t *self, enum event_codes event_sym); /* \brief This is the state machine input function called by the IO layer (ie cameradriver.c)
*
* \param caller, Provides context info for the ouput function callback.
* \param self, Provides current state on input and next state and output event on return.
*/
void camdriv_input(void *caller, camsm_t *self, enum event_codes event_sym);
/* Convenience functions to convert a state or event to a descriptive string */
char *strstate(state_t s); char *strstate(state_t s);
char *strevent(event_t E); char *strevent(event_t E);
/* The transition table */
extern trans_t TRANS_TABLE[]; extern trans_t TRANS_TABLE[];
#endif #endif

View File

@@ -1,5 +1,14 @@
/* MGS_ :Message from camera Get Status command /**
* \file cameradriver.c
* \brief This provides the IO layer which which feeds inputs from a user or
* the camera server to the state machine, and then sends any state machine
* output back to SICS or the camera.
*
* \Author Ferdi Franceschini February 2013
*
* Copyright: see file Copyright.txt
*/ */
#include <string.h>
#include <sics.h> #include <sics.h>
#include <obdes.h> #include <obdes.h>
#include <countdriv.h> #include <countdriv.h>
@@ -31,18 +40,25 @@ static char *errmsg[] = {CAMDRIV_ERRTABLE};
#undef TE #undef TE
#define CAMDRIV_PARTABLE \ #define CAMDRIV_PARTABLE \
TR(MULTI, "multi") \ TR(CLOCK, "clock") \
TR(CLOCK, "clock") \ TR(BIN, "bin") \
TR(BIN, "bin") \ TR(SIZE, "size") \
TR(SIZE, "size") \ TR(GAIN, "gain") \
TR(GAIN, "gain") \ TR(FLIP, "flip") \
TR(FLIP, "flip") \ TR(XSTART, "xstart") \
TR(XPOS, "xpos") \ TR(YSTART, "ystart") \
TR(YPOS, "ypos") \ TR(XEND, "xend") \
TR(TEMP, "temperature") \ TR(YEND, "yend") \
TR(THRESH, "threshold") \ TR(EXPOSURE, "exposure") \
TR(SHOPT, "shutteropentime") \ TR(TEMP, "temperature") \
TE(SHCLT, "shutterclosetime") TR(THRESH, "threshold") \
TR(SHOPT, "shutteropentime") \
TE(SHCLT, "shutterclosetime")
#define TR(a,b) 1+
#define TE(a,b) 1
static int NUMCAMPAR = CAMDRIV_PARTABLE;
#undef TR
#undef TE
#define FLIP_TABLE \ #define FLIP_TABLE \
TR(NORMAL, "normal") \ TR(NORMAL, "normal") \
@@ -56,14 +72,14 @@ static char *errmsg[] = {CAMDRIV_ERRTABLE};
#define TR(a,b) a, #define TR(a,b) a,
#define TE(a,b) a #define TE(a,b) a
enum campar {CAMDRIV_PARTABLE}; enum campar {CAMDRIV_PARTABLE, MULTI};
enum flipval {FLIP_TABLE}; enum flipval {FLIP_TABLE};
#undef TR #undef TR
#undef TE #undef TE
#define TR(a,b) b, #define TR(a,b) b,
#define TE(a,b) b #define TE(a,b) b
static char *cacmdstr[] = {CAMDRIV_PARTABLE, NULL}; static char *cacmdstr[] = {CAMDRIV_PARTABLE, "multi", NULL};
static char *flipcmdstr[] = {FLIP_TABLE, NULL}; static char *flipcmdstr[] = {FLIP_TABLE, NULL};
#undef TR #undef TR
#undef TE #undef TE
@@ -78,8 +94,11 @@ typedef struct {
float size; float size;
float gain; float gain;
enum flipval flip; enum flipval flip;
float xpos; float xstart;
float ypos; float ystart;
float xend;
float yend;
float exposure;
float temp; float temp;
float thresh; float thresh;
float shopt; float shopt;
@@ -89,7 +108,8 @@ typedef struct {
typedef struct { typedef struct {
int debug; int debug;
camdriv_t state_machine; char *asynq;
camsm_t state_machine;
pNWTimer state_timer; pNWTimer state_timer;
int status; int status;
enum errcodes camError; enum errcodes camError;
@@ -100,22 +120,39 @@ typedef struct {
/* Camera communications and protocol handlers */ /* Camera communications and protocol handlers */
static pAsyncProtocol CAM_Protocol = NULL; static pAsyncProtocol CAM_Protocol = NULL;
static int cb_state_timer(void *ctx, int mode);
static int cb_getstate(pAsyncTxn txn);
static void CAM_Notify(void* context, int event) {
CamObj *self = (CamObj *) context;
switch (event) {
case AQU_DISCONNECT:
SICSLogWrite("CAM:(AQU_DISCONNECT)", eLogError);
break;
case AQU_RECONNECT:
SICSLogWrite("CAM:(AQU_RECONNECT)", eLogError);
if (self->state_timer) {
NetWatchRemoveTimer(self->state_timer);
self->state_timer=0;
}
break;
}
return;
}
static int CAM_Tx(pAsyncProtocol p, pAsyncTxn txn) { static int CAM_Tx(pAsyncProtocol p, pAsyncTxn txn) {
int ret = 1;
if (txn) { if (txn == NULL) {
txn->txn_status = ATX_ACTIVE; return 0;
if (AsyncUnitWrite(txn->unit, txn->out_buf, txn->out_len) < 0) {
if (AsyncUnitReconnect(txn->unit) < 0)
ret = 0;
}
ret = 1;
} else {
ret = 0;
} }
return ret; txn->txn_status = ATX_ACTIVE;
if (AsyncUnitWrite(txn->unit, txn->out_buf, txn->out_len) < 0) {
return 0;
}
return 1;
} }
int defaultHandleInput(pAsyncProtocol p, pAsyncTxn txn, int ch); int defaultHandleInput(pAsyncProtocol p, pAsyncTxn txn, int ch);
static int CAM_Rx(pAsyncProtocol p, pAsyncTxn txn, int ch) { static int CAM_Rx(pAsyncProtocol p, pAsyncTxn txn, int ch) {
int ret = 1; int ret = 1;
@@ -131,10 +168,13 @@ static int CAM_Rx(pAsyncProtocol p, pAsyncTxn txn, int ch) {
return ret; return ret;
} }
/* TODO static int CAM_Ev(pAsyncProtocol p, pAsyncTxn pTxn, int event) {
static int CAM_Ev(pAsyncProtocol p, pAsyncTxn txn, int event) { if (event == AQU_TIMEOUT) {
pTxn->txn_status = ATX_TIMEOUT;
return AQU_POP_CMD;
}
return AQU_POP_CMD;
} }
*/
void CameraInitProtocol(SicsInterp *pSics) { void CameraInitProtocol(SicsInterp *pSics) {
if (CAM_Protocol == NULL) { if (CAM_Protocol == NULL) {
@@ -143,8 +183,8 @@ void CameraInitProtocol(SicsInterp *pSics) {
CAM_Protocol->handleInput = CAM_Rx; CAM_Protocol->handleInput = CAM_Rx;
CAM_Protocol->prepareTxn = NULL; CAM_Protocol->prepareTxn = NULL;
CAM_Protocol->killPrivate = NULL; CAM_Protocol->killPrivate = NULL;
#if 0
CAM_Protocol->handleEvent = CAM_Ev; CAM_Protocol->handleEvent = CAM_Ev;
#if 0
CAM_Protocol->sendTerminator = strdup("\r\n"); CAM_Protocol->sendTerminator = strdup("\r\n");
CAM_Protocol->replyTerminator[0] = strdup("\r\n"); CAM_Protocol->replyTerminator[0] = strdup("\r\n");
#endif #endif
@@ -158,7 +198,11 @@ static int CamGetStatus(CounterDriver *cntrData, float *fControl) {
return camdrv->status; return camdrv->status;
} }
static void crank_state_machine(CamObj *self, enum event_codes ev_sym) { /* \brief run_sm, call the state machine with the given input.
* \param self, driver context including current state
* \param ev_sym, input event
*/
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[SSLEN+1], ssnext[SSLEN+1], esout[ESLEN+1], message[MSGLEN+1];
if (self->debug) if (self->debug)
@@ -169,44 +213,75 @@ static void crank_state_machine(CamObj *self, enum event_codes ev_sym) {
if (self->debug) { if (self->debug) {
strncpy(ssnext, strstate(self->state_machine.Sc), SSLEN); strncpy(ssnext, strstate(self->state_machine.Sc), SSLEN);
strncpy(esout, strevent(self->state_machine.Eo), ESLEN); strncpy(esout, strevent(self->state_machine.Eo), ESLEN);
snprintf(message, MSGLEN, snprintf(message, MSGLEN, "DEBUG:(run_sm) Scurr:%s Ei:%s",
"DEBUG:(%s:%d) Scurr:%s Ein:%s|Snext:%s Eout:%s",__FILE__,__LINE__, sscur,event_names[ev_sym]);
sscur,event_names[ev_sym],ssnext,esout); SICSLogWrite(message, eLog);
snprintf(message, MSGLEN, "DEBUG:(run_sm) Snext:%s Eo:%s", ssnext,esout);
SICSLogWrite(message, eLog); SICSLogWrite(message, eLog);
} }
} }
/* \brief sendcfg, Send the camera configuration to the camera server
*/
int sendcfg(CamObj *self) { int sendcfg(CamObj *self) {
int status, replen=MSGLEN; int status, replen=MSGLEN;
char reply[MSGLEN+1]; char reply[MSGLEN+1], logmsg[MSGLEN+1];
char *cfgCmd = "set camera,clock=1MHz"; char cfgCmd[MSGLEN+1];
float clock = self->camera.clockMHz;
sprintf(cfgCmd,
"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,
(int)self->camera.gain, flipcmdstr[self->camera.flip],
(int)self->camera.xstart, (int)self->camera.ystart,
(int)self->camera.xend, (int)self->camera.yend, self->camera.exposure,
self->camera.temp, (int)self->camera.thresh, (int)self->camera.shopt,
(int)self->camera.shclt
);
status = AsyncUnitTransact(self->asyncUnit, cfgCmd, strlen(cfgCmd), reply, &replen); status = AsyncUnitTransact(self->asyncUnit, cfgCmd, strlen(cfgCmd), reply, &replen);
return 1; if (status <= 0)
return 0;
else
if (strncmp("OK", reply, 2) == 0)
return 1;
else {
snprintf(logmsg, MSGLEN, "CAM:(sendcfg) reply=%s", reply);
SICSLogWrite(logmsg, eLogError);
return 0;
}
} }
/* Called by the scan command and via the count and countnb subcommands of a
* counter object. Will update the configuration if necessary.
*/
static int CamStart(CounterDriver *cntrData) { static int CamStart(CounterDriver *cntrData) {
CamObj *self = NULL; CamObj *self = NULL;
enum event_codes cd_sym; enum event_codes cd_sym;
char logmsg[MSGLEN+1];
self = cntrData->pData; self = cntrData->pData;
/* Send the updated configuration to the camera server if it has been changed
* on SICS since the last shot was taken. */
if (self->camera.updatecfg) { if (self->camera.updatecfg) {
if (sendcfg(self) == 0) { if (sendcfg(self) == 0) {
/* ERROR failed to update configuration */ snprintf(logmsg, MSGLEN, "CAM:(CamStart) Failed to upload configuration");
SICSLogWrite(logmsg, eLogError);
return 0; return 0;
} }
self->camera.updatecfg = 0;
} }
if (self->state_machine.multi) { if (self->state_machine.multi) {
cd_sym = ECD_TK_MLTI; cd_sym = ECD_MLTI_ON;
} else { } else {
cd_sym = ECD_TK_SHOT; cd_sym = ECD_TK_SHOT;
} }
crank_state_machine(self, cd_sym); run_sm(self, cd_sym);
return 1; return 1;
} }
static int CamPause(CounterDriver *cntrData) { static int CamPause(CounterDriver *cntrData) {
return 1; return 1;
} }
@@ -214,19 +289,25 @@ static int CamContinue(CounterDriver *cntrData) {
return 1; return 1;
} }
static int CamHalt(CounterDriver *cntrData) { static int CamHalt(CounterDriver *cntrData) {
CamObj *self = cntrData->pData;
if (self->state_machine.multi) {
run_sm(self, ECD_MLTI_OFF);
}
return 1; return 1;
} }
/* TODO 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="get imsz", pReply[MSGLEN]; char *cmd="TODO ", pReply[MSGLEN];
CamObj *self = NULL; CamObj *self = NULL;
return 1; return 1;
self = cntrData->pData; self = cntrData->pData;
// fTime = [get shtime]
status = AsyncUnitTransact(self->asyncUnit, cmd, strlen(cmd), pReply, &iReplyLen); status = AsyncUnitTransact(self->asyncUnit, cmd, strlen(cmd), pReply, &iReplyLen);
return 1; return 1;
} }
static int CamGetError(CounterDriver *cntrData, int *iCode, char *error, int iErrLen) { static int CamGetError(CounterDriver *cntrData, int *iCode, char *error, int iErrLen) {
CamObj *camdrv=NULL; CamObj *camdrv=NULL;
camdrv = (CamObj *) cntrData->pData; camdrv = (CamObj *) cntrData->pData;
@@ -235,26 +316,32 @@ static int CamGetError(CounterDriver *cntrData, int *iCode, char *error, int iEr
camdrv->camError = ENONE; camdrv->camError = ENONE;
switch (*iCode) { switch (*iCode) {
case EBUSYACQ: case EBUSYACQ:
snprintf(error, (size_t) iErrLen, "CAMERR: Can't complete operation, %s", errmsg[EBUSYACQ]); snprintf(error, (size_t) iErrLen,
"CAM: Can't complete operation, %s", errmsg[EBUSYACQ]);
break; break;
case EBUSYSAVE: case EBUSYSAVE:
snprintf(error, (size_t) iErrLen, "CAMERR: Can't complete operation, %s", errmsg[EBUSYSAVE]); snprintf(error, (size_t) iErrLen,
"CAM: Can't complete operation, %s", errmsg[EBUSYSAVE]);
break; break;
case EBUSYPROC: case EBUSYPROC:
snprintf(error, (size_t) iErrLen, "CAMERR: Can't complete operation, %s", errmsg[EBUSYPROC]); snprintf(error, (size_t) iErrLen,
"CAM: Can't complete operation, %s", errmsg[EBUSYPROC]);
break; break;
case ENONE: case ENONE:
snprintf(error, (size_t) iErrLen, "CAMERR: Can't complete operation, %s", errmsg[ENONE]); snprintf(error, (size_t) iErrLen,
"CAM: Can't complete operation, %s", errmsg[ENONE]);
break; break;
case EFAIL: case EFAIL:
snprintf(error, (size_t) iErrLen, "CAMERR: %s", errmsg[EFAIL]); snprintf(error, (size_t) iErrLen, "CAM: %s", errmsg[EFAIL]);
break; break;
} }
return 1; return 1;
} }
static int CamTryAndFixIt(CounterDriver *cntrData, int iCode) { static int CamTryAndFixIt(CounterDriver *cntrData, int iCode) {
return COTERM; return COTERM;
} }
static int CamSet(CounterDriver *cntrData, char *name, int iCter, float fVal) { static int CamSet(CounterDriver *cntrData, char *name, int iCter, float fVal) {
CamObj *camdriv= (CamObj *)cntrData->pData; CamObj *camdriv= (CamObj *)cntrData->pData;
@@ -264,7 +351,7 @@ static int CamSet(CounterDriver *cntrData, char *name, int iCter, float fVal) {
enum flipval flip; enum flipval flip;
for (id=0; (cmd = cacmdstr[id]) != NULL; id++) { for (id=0; (cmd = cacmdstr[id]) != NULL; id++) {
if (strcmp(cmd,cacmdstr[id]) == 0) { if (strcmp(cmd,name) == 0) {
found=1; found=1;
break; break;
} }
@@ -319,40 +406,62 @@ static int CamSet(CounterDriver *cntrData, char *name, int iCter, float fVal) {
case NORMAL: case NORMAL:
case INVINT: case INVINT:
case NORMFH: case NORMFH:
case NORMFV:
case NORMFHV: case NORMFHV:
case INVFH: case INVFH:
case INVFV: case INVFV:
case INVFHV: case INVFHV:
camdriv->camera.flip = flip; camdriv->camera.flip = flip;
camdriv->camera.updatecfg = 1;
break; break;
default: default:
return 0; return 0;
break; break;
} }
break; break;
case XPOS: case XSTART:
if (fVal > 0) { if (fVal > 0) {
camdriv->camera.xpos = fVal; camdriv->camera.xstart = fVal;
camdriv->camera.updatecfg = 1; camdriv->camera.updatecfg = 1;
} else { } else {
return 0; return 0;
} }
break; break;
case YPOS: case YSTART:
if (fVal > 0) { if (fVal > 0) {
camdriv->camera.ypos = fVal; camdriv->camera.ystart = fVal;
camdriv->camera.updatecfg = 1;
} else {
return 0;
}
break;
case XEND:
if (fVal > 0) {
camdriv->camera.xend = fVal;
camdriv->camera.updatecfg = 1;
} else {
return 0;
}
break;
case YEND:
if (fVal > 0) {
camdriv->camera.yend = fVal;
camdriv->camera.updatecfg = 1;
} else {
return 0;
}
break;
case EXPOSURE:
if (fVal > 0) {
camdriv->camera.exposure = fVal;
camdriv->camera.updatecfg = 1; camdriv->camera.updatecfg = 1;
} else { } else {
return 0; return 0;
} }
break; break;
case TEMP: case TEMP:
if (fVal > 0) {
camdriv->camera.temp = fVal; camdriv->camera.temp = fVal;
camdriv->camera.updatecfg = 1; camdriv->camera.updatecfg = 1;
} else {
return 0;
}
break; break;
case THRESH: case THRESH:
if (fVal > 0) { if (fVal > 0) {
@@ -383,6 +492,7 @@ static int CamSet(CounterDriver *cntrData, char *name, int iCter, float fVal) {
} }
return 1; return 1;
} }
static int CamGet(CounterDriver *cntrData, char *name, int iCter, float *fVal) { static int CamGet(CounterDriver *cntrData, char *name, int iCter, float *fVal) {
CamObj *camdriv= (CamObj *)cntrData->pData; CamObj *camdriv= (CamObj *)cntrData->pData;
@@ -391,7 +501,7 @@ static int CamGet(CounterDriver *cntrData, char *name, int iCter, float *fVal) {
enum campar id; enum campar id;
for (id=0; (cmd = cacmdstr[id]) != NULL; id++) { for (id=0; (cmd = cacmdstr[id]) != NULL; id++) {
if (strcmp(cmd,cacmdstr[id]) == 0) { if (strcmp(cmd,name) == 0) {
found=1; found=1;
break; break;
} }
@@ -419,11 +529,20 @@ static int CamGet(CounterDriver *cntrData, char *name, int iCter, float *fVal) {
case FLIP: case FLIP:
*fVal = camdriv->camera.flip; *fVal = camdriv->camera.flip;
break; break;
case XPOS: case XSTART:
*fVal = camdriv->camera.xpos; *fVal = camdriv->camera.xstart;
break; break;
case YPOS: case YSTART:
*fVal = camdriv->camera.ypos; *fVal = camdriv->camera.ystart;
break;
case XEND:
*fVal = camdriv->camera.xend;
break;
case YEND:
*fVal = camdriv->camera.yend;
break;
case EXPOSURE:
*fVal = camdriv->camera.exposure;
break; break;
case TEMP: case TEMP:
*fVal = camdriv->camera.temp; *fVal = camdriv->camera.temp;
@@ -442,6 +561,7 @@ static int CamGet(CounterDriver *cntrData, char *name, int iCter, float *fVal) {
} }
return 1; return 1;
} }
static int CamSend(CounterDriver *cntrData, char *pText, char *pReply, int iReplyLen) { static int CamSend(CounterDriver *cntrData, char *pText, char *pReply, int iReplyLen) {
int status; int status;
CamObj *self = NULL; CamObj *self = NULL;
@@ -449,7 +569,10 @@ static int CamSend(CounterDriver *cntrData, char *pText, char *pReply, int iRepl
self = cntrData->pData; self = cntrData->pData;
status = AsyncUnitTransact(self->asyncUnit, pText, strlen(pText), pReply, &iReplyLen); status = AsyncUnitTransact(self->asyncUnit, pText, strlen(pText), pReply, &iReplyLen);
return 1; if (status <= 0)
return 0;
else
return 1;
} }
static int cb_shotcmd(pAsyncTxn txn) { static int cb_shotcmd(pAsyncTxn txn) {
@@ -466,7 +589,7 @@ static int cb_shotcmd(pAsyncTxn txn) {
int camdriv_out(void *me, event_t Eo) { int camdriv_out(void *me, event_t Eo) {
int len; int len;
char cmd[MSGLEN], logmsg[MSGLEN]; char cmd[MSGLEN]="", logmsg[MSGLEN+1]="";
CamObj *self = (CamObj *)me; CamObj *self = (CamObj *)me;
if (Eo.ca) { if (Eo.ca) {
@@ -480,21 +603,30 @@ int camdriv_out(void *me, event_t Eo) {
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);
break; break;
default: case ECA_MLTI_OFF:
len = strlen(event_signatures[ECA_MLTI_OFF]);
strncpy(cmd, event_signatures[ECA_MLTI_OFF], len);
break; break;
default:
snprintf(logmsg, MSGLEN, "CAM:(camdriv_out) Unhandled event %s", event_names[Eo.ca]);
SICSLogWrite(logmsg, eLogError);
return 0;
} }
AsyncUnitSendTxn(self->asyncUnit, cmd, len, cb_shotcmd, self, MSGLEN); AsyncUnitSendTxn(self->asyncUnit, cmd, len, cb_shotcmd, self, MSGLEN);
if (self->debug) { if (self->debug) {
snprintf(logmsg, MSGLEN, "DEBUG: camdriv_out: ev=%s, output=%s\n", event_names[Eo.ca], event_signatures[Eo.ca]); snprintf(logmsg, MSGLEN, "DEBUG:(camdriv_out:Eo.ca): ev=%s, output=%s\n",
event_names[Eo.ca], event_signatures[Eo.ca]);
SICSLogWrite(logmsg, eLog); SICSLogWrite(logmsg, eLog);
} }
} }
if (Eo.cm) { if (Eo.cm) {
snprintf(logmsg, MSGLEN, "ERROR: NOT IMPLEMENTED, camdriv_out: ev=%s, output=%s\n", event_names[Eo.cm], event_signatures[Eo.cm]); snprintf(logmsg, MSGLEN, "TODO:(camdriv_out:Eo.cm): ev=%s, output=%s\n",
event_names[Eo.cm], event_signatures[Eo.cm]);
SICSLogWrite(logmsg, eLogError); SICSLogWrite(logmsg, eLogError);
} }
if (Eo.cd) { if (Eo.cd) {
snprintf(logmsg, MSGLEN, "ERROR: NOT IMPLEMENTED, camdriv_out: ev=%s, output=%s\n", event_names[Eo.cd], event_signatures[Eo.cd]); snprintf(logmsg, MSGLEN, "TODO:(camdriv_out:Eo.cm): ev=%s, output=%s\n",
event_names[Eo.cd], event_signatures[Eo.cd]);
SICSLogWrite(logmsg, eLogError); SICSLogWrite(logmsg, eLogError);
} }
if (Eo.dr) { if (Eo.dr) {
@@ -510,16 +642,18 @@ int camdriv_out(void *me, event_t Eo) {
self->status = HWFault; self->status = HWFault;
break; break;
default: default:
break; snprintf(logmsg, MSGLEN, "CAM:(camdriv_out) Unhandled event %s", event_names[Eo.dr]);
SICSLogWrite(logmsg, eLogError);
return 0;
} }
if (self->debug) { if (self->debug) {
snprintf(logmsg, MSGLEN, "DEBUG: camdriv_out: ev=%s, output=%s\n", event_names[Eo.dr], event_signatures[Eo.dr]); snprintf(logmsg, MSGLEN, "DEBUG:(camdriv_out): ev=%s, output=%s\n",
event_names[Eo.dr], event_signatures[Eo.dr]);
SICSLogWrite(logmsg, eLog); SICSLogWrite(logmsg, eLog);
} }
} }
return 1; return 1;
} }
static int cb_getstate(pAsyncTxn txn);
static int cb_state_timer(void *ctx, int mode) { static int cb_state_timer(void *ctx, int mode) {
CamObj *self = (CamObj *) ctx; CamObj *self = (CamObj *) ctx;
char errmsg[32]=""; char errmsg[32]="";
@@ -533,7 +667,7 @@ static int cb_state_timer(void *ctx, int mode) {
if (status==1) { if (status==1) {
return 1; return 1;
} else { } else {
snprintf(errmsg, 31, "ERROR:(%s) AsyncUnitTransact failed",__FILE__); snprintf(errmsg, 31, "CAM:(cb_getstate) AsyncUnitSendTxn failed");
SICSLogWrite(errmsg, eLogError); SICSLogWrite(errmsg, eLogError);
return 0; return 0;
} }
@@ -547,19 +681,23 @@ static int cb_getstate(pAsyncTxn txn) {
enum event_codes ca_sym, cm_sym; enum event_codes ca_sym, cm_sym;
if ( cam_parse_status(resp, &ca_sym, &time_rem, &time_tot) == -1) { if (txn->txn_status == ATX_TIMEOUT) {
snprintf(message, MSGLEN, "ERROR:(%s:%d) cam_parse_status failed on '%s'",__FILE__,__LINE__,resp); ret = 0;
} else if ( cam_parse_status(resp, &ca_sym, &time_rem, &time_tot) == -1) {
snprintf(message, MSGLEN,
"CAM:(cb_getstate) cam_parse_status failed to parse '%s'",resp);
SICSLogWrite(message, eLogError); SICSLogWrite(message, eLogError);
ret = 0; ret = 0;
} else { } else {
cm_sym = camera_model(ca_sym); cm_sym = camera_model(ca_sym);
crank_state_machine(self, cm_sym); run_sm(self, cm_sym);
} }
if (self->state_timer) { if (self->state_timer) {
NetWatchRemoveTimer(self->state_timer); NetWatchRemoveTimer(self->state_timer);
self->state_timer=0; self->state_timer=0;
} }
NetWatchRegisterTimer(&self->state_timer, 500, cb_state_timer, self); NetWatchRegisterTimer(&self->state_timer, 500, cb_state_timer, self);
return ret; return ret;
} }
@@ -581,13 +719,16 @@ 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 = 0; pNewCam->camera.updatecfg = 1;
pNewCam->asynq = strdup(asynq);
if (!AsyncUnitCreate(asynq, &pNewCam->asyncUnit)) { if (!AsyncUnitCreate(asynq, &pNewCam->asyncUnit)) {
snprintf(msg, ERRLEN, "CAMERR:AsyncQueue %s has not been defined", asynq); snprintf(msg, ERRLEN, "CAM:AsyncQueue %s has not been defined", asynq);
SCWrite(pCon, msg, eError); SCWrite(pCon, msg, eError);
return NULL; return NULL;
} }
AsyncUnitSetTimeout(pNewCam->asyncUnit, 1000);
AsyncUnitSetNotify(pNewCam->asyncUnit, pNewCam, CAM_Notify);
pCntDriv = CreateCounterDriver(name, "anstocamera"); pCntDriv = CreateCounterDriver(name, "anstocamera");
if (pCntDriv == NULL) if (pCntDriv == NULL)
@@ -614,17 +755,3 @@ pCounterDriver CreateCam(SConnection *pCon, char *name, char *asynq) {
AsyncUnitSendTxn(pNewCam->asyncUnit, cmd, len, cb_getstate, pNewCam, MSGLEN); AsyncUnitSendTxn(pNewCam->asyncUnit, cmd, len, cb_getstate, pNewCam, MSGLEN);
return pCntDriv; return pCntDriv;
} }
#if 0
int CameraAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) {
CamObj *pCam = (CamObj *) pData;
}
int CamMakeCmd(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) {
CamObj *pNew = NULL;
pNew = CreateCam(argv[1], argv[2]);
if (pNew == NULL)
return 0;
AddCommand(pSics, argv[1], CameraAction, NULL, pNew);
return 1;
}
#endif