From 87559bf411d2c79a68b53634b9a0abef279cd5b3 Mon Sep 17 00:00:00 2001 From: Ferdi Franceschini Date: Tue, 26 Feb 2013 01:02:25 +1100 Subject: [PATCH] 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. --- site_ansto/TESTS/dingo_camera/Makefile | 2 +- .../camdriver_event_io_expect.txt | 2 + site_ansto/TESTS/dingo_camera/camera_test | Bin 20496 -> 0 bytes site_ansto/TESTS/dingo_camera/camera_test.c | 57 +++- .../TESTS/dingo_camera/camrep2sym_expect.txt | 8 + .../{expect.txt => trans_fn_expect.txt} | 12 +- site_ansto/hardsup/camera.c | 85 +++-- site_ansto/hardsup/camera.h | 104 ++++-- site_ansto/hardsup/cameradriver.c | 313 ++++++++++++------ 9 files changed, 394 insertions(+), 189 deletions(-) create mode 100644 site_ansto/TESTS/dingo_camera/camdriver_event_io_expect.txt delete mode 100755 site_ansto/TESTS/dingo_camera/camera_test create mode 100644 site_ansto/TESTS/dingo_camera/camrep2sym_expect.txt rename site_ansto/TESTS/dingo_camera/{expect.txt => trans_fn_expect.txt} (51%) diff --git a/site_ansto/TESTS/dingo_camera/Makefile b/site_ansto/TESTS/dingo_camera/Makefile index c59f4709..cb7a53b8 100644 --- a/site_ansto/TESTS/dingo_camera/Makefile +++ b/site_ansto/TESTS/dingo_camera/Makefile @@ -1,7 +1,7 @@ # vim: ft=make: ts=8: sw=8: noet: cindent: 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: rm camera_test diff --git a/site_ansto/TESTS/dingo_camera/camdriver_event_io_expect.txt b/site_ansto/TESTS/dingo_camera/camdriver_event_io_expect.txt new file mode 100644 index 00000000..6b0f7ffd --- /dev/null +++ b/site_ansto/TESTS/dingo_camera/camdriver_event_io_expect.txt @@ -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 diff --git a/site_ansto/TESTS/dingo_camera/camera_test b/site_ansto/TESTS/dingo_camera/camera_test deleted file mode 100755 index 9ce9f044a88874f7a6326fcd61027ebc0c8df5d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20496 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 diff --git a/site_ansto/TESTS/dingo_camera/camera_test.c b/site_ansto/TESTS/dingo_camera/camera_test.c index 9b0cf856..ae7ffc64 100644 --- a/site_ansto/TESTS/dingo_camera/camera_test.c +++ b/site_ansto/TESTS/dingo_camera/camera_test.c @@ -1,4 +1,9 @@ - +/** + * \file camera_test.c + * \brief Test camera.[ch] state machine. + * + * \Author Ferdi Franceschini February 2013 + */ #include #include #include @@ -50,17 +55,24 @@ int test_camrep2sym(void) { 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++) { if ( cam_parse_status(camrep[i], &ca_sym, &time_rem, &time_tot) == -1) exit(1); else { cm_sym = camera_model(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 - 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; } @@ -76,6 +88,10 @@ int test_trans_fn(void) { 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"); for (i=0; input[i]; i++) { EVclr(&Eo); @@ -86,39 +102,52 @@ int test_trans_fn(void) { print_event(Eo); printf("\n"); } + fprintf(stderr, "TEST_TRANS_FN:OUTPUT:END\n"); return 1; } int camdriv_out(void *me, event_t Eo) { - int *self = me; - *self=0; /* shudduppa your warnings */ + int *self = me; *self=0; /* shudduppa your warnings */ if (Eo.ca) { - /* send command to camera */ - printf("camdriv_out: ev=%s, output=%s\n", event_names[Eo.ca], event_signatures[Eo.ca]); + printf("camdriv_out: symbol=%s, output=%s\n", event_names[Eo.ca], event_signatures[Eo.ca]); } 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) { - 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) { - /* send msg to SICS */ - printf("camdriv_out: ev=%s, output=%s\n", event_names[Eo.dr], event_signatures[Eo.dr]); + printf("camdriv_out: symbol=%s, output=%s\n", event_names[Eo.dr], event_signatures[Eo.dr]); } return 1; } -int test_camdriv_input(void) { + +int test_camdriv_event_io(void) { int Ein=ECD_TK_SHOT; int self; - camdriv_t cdinfo = { + camsm_t cdinfo = { .Sc = {.cl=SCL_RDY, .cm=SCM_IDLE, .dr=SDR_IDLE}, .Eo = {.ca=0}, .multi = 0, .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); + + 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; } @@ -156,7 +185,7 @@ int main(int argc, char *argv[]) { if (test & 2) ret = test_trans_fn(); if (test & 4) - ret = test_camdriv_input(); + ret = test_camdriv_event_io(); if (ret) return 0; diff --git a/site_ansto/TESTS/dingo_camera/camrep2sym_expect.txt b/site_ansto/TESTS/dingo_camera/camrep2sym_expect.txt new file mode 100644 index 00000000..4361863f --- /dev/null +++ b/site_ansto/TESTS/dingo_camera/camrep2sym_expect.txt @@ -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 diff --git a/site_ansto/TESTS/dingo_camera/expect.txt b/site_ansto/TESTS/dingo_camera/trans_fn_expect.txt similarity index 51% rename from site_ansto/TESTS/dingo_camera/expect.txt rename to site_ansto/TESTS/dingo_camera/trans_fn_expect.txt index fd902120..efc5294d 100644 --- a/site_ansto/TESTS/dingo_camera/expect.txt +++ b/site_ansto/TESTS/dingo_camera/trans_fn_expect.txt @@ -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 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 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 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 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_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_IDLE, SCM_PROC,SCL_RDY,SDR_IDLE, 0,0,0,0 diff --git a/site_ansto/hardsup/camera.c b/site_ansto/hardsup/camera.c index 06148d61..95bcedba 100644 --- a/site_ansto/hardsup/camera.c +++ b/site_ansto/hardsup/camera.c @@ -51,12 +51,9 @@ void EVset(event_t *E, event_t Ev) { /* Set system state */ void STset(state_t *Sc, state_t St) { - if (St.cl) - Sc->cl = St.cl; - if (St.cm) - Sc->cm = St.cm; - if (St.dr) - Sc->dr = St.dr; + if (St.cl) Sc->cl = St.cl; + if (St.cm) Sc->cm = St.cm; + if (St.dr) Sc->dr = St.dr; } 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; } } -/* 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) { 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 -1 if message is unknown * 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; } -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; cam_trans_fn(self->Sc, event_sym, &Sn, &self->Eo); self->output_fn(caller, self->Eo); @@ -163,35 +159,52 @@ char *strevent(event_t E) { 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 change for components of next state. */ -int START_STATE = SCL_RDY|SCM_IDLE|SDR_IDLE; 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_MLTI,{.dr=0}, {.cl=SCL_TK_MLTI}}, -{{.cl=SCL_TK_SHOT}, ECM_IDLE, {.ca=ECA_TK_SHOT}, {.cl=SCL_WT_ACQ}}, -{{.cl=SCL_TK_MLTI}, ECM_IDLE, {.ca=ECA_MLTI_ON}, {.cl=SCL_WT_ACQ}}, -{{.cl=SCL_TK_SHOT}, ECD_CLEAR, {.dr=0}, {.cl=SCL_RDY}}, -{{.cl=SCL_TK_MLTI}, ECD_CLEAR, {.dr=0}, {.cl=SCL_RDY}}, -{{.cl=SCL_WT_ACQ}, ECM_ACQ, {.dr=0}, {.cl=SCL_RDY}}, -{{.cl=SCL_WT_ACQ}, ECM_PROC, {.dr=0}, {.cl=SCL_RDY}}, -{{.cl=SCL_WT_ACQ}, 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_ACQ}, ECM_IDLE, {.dr=0}, {.cl=SCL_RDY}},*/ + {{.cl=SCL_RDY, .dr=SDR_IDLE}, ECD_TK_SHOT, {.dr=0}, {.cl=SCL_TK_SHOT}}, + {{.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}}, + {{.cl=SCL_TK_MLTI}, ECD_MLTI_OFF,{.dr=0}, {.cl=SCL_RDY}}, + {{.cl=SCL_TK_MLTI}, ECM_IDLE, {.ca=ECA_MLTI_ON}, {.cl=SCL_MLTI_ON}}, + {{.cl=SCL_MLTI_ON}, ECD_MLTI_OFF,{.ca=ECA_MLTI_OFF},{.cl=SCL_WT}}, + {{.cl=SCL_WT}, ECM_ACQ, {.dr=0}, {.cl=SCL_RDY}}, + {{.cl=SCL_WT}, ECM_PROC, {.dr=0}, {.cl=SCL_RDY}}, + {{.cl=SCL_WT}, ECM_STOP, {.dr=0}, {.cl=SCL_RDY}}, + {{.cl=SCL_WT}, ECM_IDLE, {.dr=0}, {.cl=SCL_RDY}}, -{{.cm=SCM_IDLE}, ECM_ACQ, {.dr=0}, {.cm=SCM_ACQ}}, -{{.cm=SCM_IDLE}, 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_PROC}, ECM_STOP, {.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_IDLE}, ECM_ACQ, {.dr=0}, {.cm=SCM_ACQ}}, + {{.cm=SCM_IDLE}, 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_PROC}, ECM_STOP, {.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}}, -{{.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_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_IDLE, {.dr=EDR_IDLE}, {.dr=SDR_IDLE}}, -{{.dr=END_TABLE}, END_TABLE, {.dr=END_TABLE}, {.dr=END_TABLE}} + {{.dr=SDR_IDLE}, ECD_TK_SHOT, {.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_STOP, {.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}} }; diff --git a/site_ansto/hardsup/camera.h b/site_ansto/hardsup/camera.h index 2cbdde2a..a715e7db 100644 --- a/site_ansto/hardsup/camera.h +++ b/site_ansto/hardsup/camera.h @@ -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 * 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. * The sets of states are, * 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, * EDR:Driver events. * + * The system state machine for the camera driver is defined as follows. * In the following, '<' means subset * Q < SCL X SCM X SCDR * Ein = ECA U ECM U ECD U EDR * Eo < ECA X ECM X ECD X EDR * trans fn: QXEin -> Q - * out fn : QXEin -> Eo + * out fn : QXEin -> Eo * * In the implementation the transition and output functions are combined in * TRANS_TABLE. */ #ifndef 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 */ #define END_TABLE -1 @@ -39,17 +47,18 @@ * EDR_ : Driver events */ #define CAMERA_CMDS_TABLE \ - TR(ECA_TK_SHOT, "take shot") \ - TR(ECA_MLTI_ON, "take multi on") \ - TR(ECA_MLTI_OFF, "take multi off") \ - TR(ECA_GET_STATUS, "get status") \ + TR(ECA_SET_CAM, "set camera") \ + TR(ECA_TK_SHOT, "take shot") \ + TR(ECA_MLTI_ON, "take multi on") \ + TR(ECA_MLTI_OFF, "take multi off") \ + TR(ECA_GET_STATUS, "get status") \ TE(ECA_GET_STATE, "get state") -#define CAMERA_MSGS_TABLE \ - TR(ECA_START, "StartTime") \ - TR(ECA_OK, "OK") \ - TR(ECA_FAIL, "Fail") \ - TR(ECA_IDLE, "Idle") \ +#define CAMERA_MSGS_TABLE \ + TR(ECA_START, "StartTime") \ + TR(ECA_OK, "OK") \ + TR(ECA_FAIL, "Fail") \ + TR(ECA_IDLE, "Idle") \ TR(ECA_OPEN_SHUTR, "Open") \ TR(ECA_CLOSE_SHUTR, "Close") \ TR(ECA_ACQ_IMAGE, "Acq") \ @@ -57,12 +66,12 @@ TR(ECA_SEND_IMAGE, "Send") \ TE(ECA_STOP, "Stop") -#define CAM_MOD_EVENT_TABLE \ +#define CAM_MOD_EVENT_TABLE \ TR(ECM_UNKNOWN, "Stop message received from camera") \ TR(ECM_STOP, "Stop message received from camera") \ TR(ECM_IDLE, "Camera in idle state") \ 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") /* COMMAND EVENTS @@ -71,14 +80,15 @@ * indirect via the scan command through the counter interface. */ #define CMD_EVENT_TABLE \ - TR(ECD_CMD_INPUT, "received a command") \ TR(ECD_CLEAR, "Clear latched command") \ - TR(ECD_TK_SHOT, "take shot") \ - TR(ECD_TK_MLTI, "take multi on") \ + TR(ECD_TK_SHOT, "take shot") \ + TR(ECD_MLTI_ON, "take multi on") \ + TR(ECD_MLTI_OFF, "take multi off") \ TR(ECD_GET_STATE, "get state") \ TE(ECD_GET_STATUS, "get status") /* DRIVER EVENT TABLE + * These events are of interest to SICS. */ #define DRIVER_EVENT_TABLE \ TR(EDR_IDLE, "HWIDLE") \ @@ -88,17 +98,17 @@ #define ESLEN 32 /* STATE CODES - * NOTE: Every state will respond to a timer event and * SXX_ State code enum constants, XX identifies a component of the system. * SCL_ Command latch states * SCM_ Camera model states * SDR_ Driver states */ #define COMMAND_LATCH_STATE_TABLE \ - TR(SCL_RDY, "command latch ready to accept") \ - TR(SCL_TK_SHOT, "latched a take shot command") \ + TR(SCL_RDY, "command latch ready to accept") \ + TR(SCL_TK_SHOT, "latched a take 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 \ TR(SCM_IDLE, "Camera is idle") \ @@ -112,7 +122,7 @@ #define SSLEN 32 -/* Generate event and state symbols */ +/* Enumerate event and state symbols */ #define TR(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}; @@ -130,10 +140,12 @@ enum driver_states {DR_Z,DRIVER_STATE_TABLE}; extern char *SCL_NAMES[]; extern char *SCM_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[]; -/* 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[]; @@ -148,12 +160,15 @@ typedef struct { enum event_codes cd; enum event_codes dr; } event_t; + /* A tuple (Scl,Scm,Sdr) in SCL X SCM X SDR */ typedef struct { int cl; int cm; int dr; } state_t; + +/* Defines a row in the transition table */ typedef struct { state_t Sc; enum event_codes Ei; @@ -161,25 +176,36 @@ typedef struct { state_t Sn; } 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 { state_t Sc; event_t Eo; int multi; + int debug; int (*output_fn)(void *caller, event_t Eo); -} camdriv_t; +} camsm_t; -/* 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. +/* Are we in the SCL_XX, SCM_ or SDR_ state? + * NOTE: 0 is a wildcard so any Sc.cl value matches St.cl==0 */ #define INCL(Sc,St) (!St.cl || Sc.cl==St.cl) #define INCM(Sc,St) (!St.cm || Sc.cm==St.cm) #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) ) +/* Clear the given event */ void EVclr(event_t *E); +/* Set E to Ev */ void EVset(event_t *E, event_t Ev); +/* Set Sc to St */ void STset(state_t *Sc, state_t St); /* \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); -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 *strevent(event_t E); + +/* The transition table */ extern trans_t TRANS_TABLE[]; #endif diff --git a/site_ansto/hardsup/cameradriver.c b/site_ansto/hardsup/cameradriver.c index 2fe9322e..0d137c00 100644 --- a/site_ansto/hardsup/cameradriver.c +++ b/site_ansto/hardsup/cameradriver.c @@ -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 #include #include #include @@ -31,18 +40,25 @@ static char *errmsg[] = {CAMDRIV_ERRTABLE}; #undef TE #define CAMDRIV_PARTABLE \ - TR(MULTI, "multi") \ - TR(CLOCK, "clock") \ - TR(BIN, "bin") \ - TR(SIZE, "size") \ - TR(GAIN, "gain") \ - TR(FLIP, "flip") \ - TR(XPOS, "xpos") \ - TR(YPOS, "ypos") \ - TR(TEMP, "temperature") \ - TR(THRESH, "threshold") \ - TR(SHOPT, "shutteropentime") \ - TE(SHCLT, "shutterclosetime") + TR(CLOCK, "clock") \ + TR(BIN, "bin") \ + TR(SIZE, "size") \ + TR(GAIN, "gain") \ + TR(FLIP, "flip") \ + TR(XSTART, "xstart") \ + TR(YSTART, "ystart") \ + TR(XEND, "xend") \ + TR(YEND, "yend") \ + TR(EXPOSURE, "exposure") \ + TR(TEMP, "temperature") \ + 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 \ TR(NORMAL, "normal") \ @@ -56,14 +72,14 @@ static char *errmsg[] = {CAMDRIV_ERRTABLE}; #define TR(a,b) a, #define TE(a,b) a -enum campar {CAMDRIV_PARTABLE}; +enum campar {CAMDRIV_PARTABLE, MULTI}; enum flipval {FLIP_TABLE}; #undef TR #undef TE #define TR(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}; #undef TR #undef TE @@ -78,8 +94,11 @@ typedef struct { float size; float gain; enum flipval flip; - float xpos; - float ypos; + float xstart; + float ystart; + float xend; + float yend; + float exposure; float temp; float thresh; float shopt; @@ -89,7 +108,8 @@ typedef struct { typedef struct { int debug; - camdriv_t state_machine; + char *asynq; + camsm_t state_machine; pNWTimer state_timer; int status; enum errcodes camError; @@ -100,22 +120,39 @@ typedef struct { /* Camera communications and protocol handlers */ 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) { - int ret = 1; - if (txn) { - txn->txn_status = ATX_ACTIVE; - if (AsyncUnitWrite(txn->unit, txn->out_buf, txn->out_len) < 0) { - if (AsyncUnitReconnect(txn->unit) < 0) - ret = 0; - } - ret = 1; - } else { - ret = 0; + if (txn == NULL) { + return 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); static int CAM_Rx(pAsyncProtocol p, pAsyncTxn txn, int ch) { int ret = 1; @@ -131,10 +168,13 @@ static int CAM_Rx(pAsyncProtocol p, pAsyncTxn txn, int ch) { return ret; } -/* TODO -static int CAM_Ev(pAsyncProtocol p, pAsyncTxn txn, int event) { +static int CAM_Ev(pAsyncProtocol p, pAsyncTxn pTxn, int event) { + if (event == AQU_TIMEOUT) { + pTxn->txn_status = ATX_TIMEOUT; + return AQU_POP_CMD; + } + return AQU_POP_CMD; } -*/ void CameraInitProtocol(SicsInterp *pSics) { if (CAM_Protocol == NULL) { @@ -143,8 +183,8 @@ void CameraInitProtocol(SicsInterp *pSics) { CAM_Protocol->handleInput = CAM_Rx; CAM_Protocol->prepareTxn = NULL; CAM_Protocol->killPrivate = NULL; - #if 0 CAM_Protocol->handleEvent = CAM_Ev; + #if 0 CAM_Protocol->sendTerminator = strdup("\r\n"); CAM_Protocol->replyTerminator[0] = strdup("\r\n"); #endif @@ -158,7 +198,11 @@ static int CamGetStatus(CounterDriver *cntrData, float *fControl) { 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]; if (self->debug) @@ -169,44 +213,75 @@ static void crank_state_machine(CamObj *self, enum event_codes ev_sym) { if (self->debug) { strncpy(ssnext, strstate(self->state_machine.Sc), SSLEN); strncpy(esout, strevent(self->state_machine.Eo), ESLEN); - snprintf(message, MSGLEN, - "DEBUG:(%s:%d) Scurr:%s Ein:%s|Snext:%s Eout:%s",__FILE__,__LINE__, - sscur,event_names[ev_sym],ssnext,esout); + snprintf(message, MSGLEN, "DEBUG:(run_sm) Scurr:%s Ei:%s", + sscur,event_names[ev_sym]); + SICSLogWrite(message, eLog); + snprintf(message, MSGLEN, "DEBUG:(run_sm) Snext:%s Eo:%s", ssnext,esout); SICSLogWrite(message, eLog); } } +/* \brief sendcfg, Send the camera configuration to the camera server + */ int sendcfg(CamObj *self) { int status, replen=MSGLEN; - char reply[MSGLEN+1]; - char *cfgCmd = "set camera,clock=1MHz"; + char reply[MSGLEN+1], logmsg[MSGLEN+1]; + 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); - 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) { CamObj *self = NULL; enum event_codes cd_sym; + char logmsg[MSGLEN+1]; 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 (sendcfg(self) == 0) { - /* ERROR failed to update configuration */ + snprintf(logmsg, MSGLEN, "CAM:(CamStart) Failed to upload configuration"); + SICSLogWrite(logmsg, eLogError); return 0; } + self->camera.updatecfg = 0; } if (self->state_machine.multi) { - cd_sym = ECD_TK_MLTI; + cd_sym = ECD_MLTI_ON; } else { cd_sym = ECD_TK_SHOT; } - crank_state_machine(self, cd_sym); + run_sm(self, cd_sym); return 1; } + static int CamPause(CounterDriver *cntrData) { return 1; } @@ -214,19 +289,25 @@ static int CamContinue(CounterDriver *cntrData) { return 1; } static int CamHalt(CounterDriver *cntrData) { + CamObj *self = cntrData->pData; + + if (self->state_machine.multi) { + run_sm(self, ECD_MLTI_OFF); + } return 1; } +/* TODO what should the counter data be set to? Total intensity? */ static int CamReadValues(CounterDriver *cntrData) { int status, iReplyLen=MSGLEN; - char *cmd="get imsz", pReply[MSGLEN]; + char *cmd="TODO ", pReply[MSGLEN]; CamObj *self = NULL; return 1; self = cntrData->pData; - // fTime = [get shtime] status = AsyncUnitTransact(self->asyncUnit, cmd, strlen(cmd), pReply, &iReplyLen); return 1; } + static int CamGetError(CounterDriver *cntrData, int *iCode, char *error, int iErrLen) { CamObj *camdrv=NULL; camdrv = (CamObj *) cntrData->pData; @@ -235,26 +316,32 @@ static int CamGetError(CounterDriver *cntrData, int *iCode, char *error, int iEr camdrv->camError = ENONE; switch (*iCode) { 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; 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; 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; 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; case EFAIL: - snprintf(error, (size_t) iErrLen, "CAMERR: %s", errmsg[EFAIL]); + snprintf(error, (size_t) iErrLen, "CAM: %s", errmsg[EFAIL]); break; } return 1; } + static int CamTryAndFixIt(CounterDriver *cntrData, int iCode) { return COTERM; } + static int CamSet(CounterDriver *cntrData, char *name, int iCter, float fVal) { CamObj *camdriv= (CamObj *)cntrData->pData; @@ -264,7 +351,7 @@ static int CamSet(CounterDriver *cntrData, char *name, int iCter, float fVal) { enum flipval flip; for (id=0; (cmd = cacmdstr[id]) != NULL; id++) { - if (strcmp(cmd,cacmdstr[id]) == 0) { + if (strcmp(cmd,name) == 0) { found=1; break; } @@ -319,40 +406,62 @@ static int CamSet(CounterDriver *cntrData, char *name, int iCter, float fVal) { case NORMAL: case INVINT: case NORMFH: + case NORMFV: case NORMFHV: case INVFH: case INVFV: case INVFHV: camdriv->camera.flip = flip; + camdriv->camera.updatecfg = 1; break; default: return 0; break; } break; - case XPOS: + case XSTART: if (fVal > 0) { - camdriv->camera.xpos = fVal; + camdriv->camera.xstart = fVal; camdriv->camera.updatecfg = 1; } else { return 0; } break; - case YPOS: + case YSTART: 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; } else { return 0; } break; case TEMP: - if (fVal > 0) { camdriv->camera.temp = fVal; camdriv->camera.updatecfg = 1; - } else { - return 0; - } break; case THRESH: if (fVal > 0) { @@ -383,6 +492,7 @@ static int CamSet(CounterDriver *cntrData, char *name, int iCter, float fVal) { } return 1; } + static int CamGet(CounterDriver *cntrData, char *name, int iCter, float *fVal) { CamObj *camdriv= (CamObj *)cntrData->pData; @@ -391,7 +501,7 @@ static int CamGet(CounterDriver *cntrData, char *name, int iCter, float *fVal) { enum campar id; for (id=0; (cmd = cacmdstr[id]) != NULL; id++) { - if (strcmp(cmd,cacmdstr[id]) == 0) { + if (strcmp(cmd,name) == 0) { found=1; break; } @@ -419,11 +529,20 @@ static int CamGet(CounterDriver *cntrData, char *name, int iCter, float *fVal) { case FLIP: *fVal = camdriv->camera.flip; break; - case XPOS: - *fVal = camdriv->camera.xpos; + case XSTART: + *fVal = camdriv->camera.xstart; break; - case YPOS: - *fVal = camdriv->camera.ypos; + case YSTART: + *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; case TEMP: *fVal = camdriv->camera.temp; @@ -442,6 +561,7 @@ static int CamGet(CounterDriver *cntrData, char *name, int iCter, float *fVal) { } return 1; } + static int CamSend(CounterDriver *cntrData, char *pText, char *pReply, int iReplyLen) { int status; CamObj *self = NULL; @@ -449,7 +569,10 @@ static int CamSend(CounterDriver *cntrData, char *pText, char *pReply, int iRepl self = cntrData->pData; 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) { @@ -466,7 +589,7 @@ static int cb_shotcmd(pAsyncTxn txn) { int camdriv_out(void *me, event_t Eo) { int len; - char cmd[MSGLEN], logmsg[MSGLEN]; + char cmd[MSGLEN]="", logmsg[MSGLEN+1]=""; CamObj *self = (CamObj *)me; if (Eo.ca) { @@ -480,21 +603,30 @@ int camdriv_out(void *me, event_t Eo) { len = strlen(event_signatures[ECA_MLTI_ON]); strncpy(cmd, event_signatures[ECA_MLTI_ON], len); break; - default: + case ECA_MLTI_OFF: + len = strlen(event_signatures[ECA_MLTI_OFF]); + strncpy(cmd, event_signatures[ECA_MLTI_OFF], len); 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); 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); } } 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); } 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); } if (Eo.dr) { @@ -510,16 +642,18 @@ int camdriv_out(void *me, event_t Eo) { self->status = HWFault; break; default: - break; + snprintf(logmsg, MSGLEN, "CAM:(camdriv_out) Unhandled event %s", event_names[Eo.dr]); + SICSLogWrite(logmsg, eLogError); + return 0; } 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); } } return 1; } -static int cb_getstate(pAsyncTxn txn); static int cb_state_timer(void *ctx, int mode) { CamObj *self = (CamObj *) ctx; char errmsg[32]=""; @@ -533,7 +667,7 @@ static int cb_state_timer(void *ctx, int mode) { if (status==1) { return 1; } else { - snprintf(errmsg, 31, "ERROR:(%s) AsyncUnitTransact failed",__FILE__); + snprintf(errmsg, 31, "CAM:(cb_getstate) AsyncUnitSendTxn failed"); SICSLogWrite(errmsg, eLogError); return 0; } @@ -547,19 +681,23 @@ static int cb_getstate(pAsyncTxn txn) { enum event_codes ca_sym, cm_sym; - if ( cam_parse_status(resp, &ca_sym, &time_rem, &time_tot) == -1) { - snprintf(message, MSGLEN, "ERROR:(%s:%d) cam_parse_status failed on '%s'",__FILE__,__LINE__,resp); + if (txn->txn_status == ATX_TIMEOUT) { + 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); ret = 0; } else { cm_sym = camera_model(ca_sym); - crank_state_machine(self, cm_sym); + run_sm(self, cm_sym); } if (self->state_timer) { NetWatchRemoveTimer(self->state_timer); self->state_timer=0; } NetWatchRegisterTimer(&self->state_timer, 500, cb_state_timer, self); + return ret; } @@ -581,13 +719,16 @@ pCounterDriver CreateCam(SConnection *pCon, char *name, char *asynq) { pNewCam->status = HWIdle; pNewCam->camError = ENONE; pNewCam->debug = 1; - pNewCam->camera.updatecfg = 0; + pNewCam->camera.updatecfg = 1; + pNewCam->asynq = strdup(asynq); 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); return NULL; } + AsyncUnitSetTimeout(pNewCam->asyncUnit, 1000); + AsyncUnitSetNotify(pNewCam->asyncUnit, pNewCam, CAM_Notify); pCntDriv = CreateCounterDriver(name, "anstocamera"); if (pCntDriv == NULL) @@ -614,17 +755,3 @@ pCounterDriver CreateCam(SConnection *pCon, char *name, char *asynq) { AsyncUnitSendTxn(pNewCam->asyncUnit, cmd, len, cb_getstate, pNewCam, MSGLEN); 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