Files
sics/site_ansto/camera.c
Ferdi Franceschini f2befda1a2 Dingo camera driver
2013-02-11 19:14:03 +11:00

198 lines
5.8 KiB
C

#include <stdio.h>
#include <string.h>
#include "camera.h"
#define TR(a,b) #a,
#define TE(a,b) #a
char *event_names[] = { "0", CAMERA_CMDS_TABLE, CAMERA_MSGS_TABLE, CAM_MOD_EVENT_TABLE, DRIVER_EVENT_TABLE, CMD_EVENT_TABLE };
#undef TR
#undef TE
/* The signature array defines the identifying characters at the start of a reply. */
#define TR(a,b) b,
#define TE(a,b) b
char *event_signatures[] = { "0", CAMERA_CMDS_TABLE, CAMERA_MSGS_TABLE, CAM_MOD_EVENT_TABLE, DRIVER_EVENT_TABLE, CMD_EVENT_TABLE };
#undef TR
#undef TE
#define TR(a,b) #a,
#define TE(a,b) #a
char *SCL_NAMES[] = {"0", COMMAND_LATCH_STATE_TABLE};
char *SCM_NAMES[] = {"0", CAMERA_MODEL_STATE_TABLE};
char *SDR_NAMES[] = {"0", DRIVER_STATE_TABLE};
#undef TR
#undef TE
#define TR(a,b) b,
#define TE(a,b) b
char *COMMAND_LATCH_STATE_DESCRIPTION[] = {"0", COMMAND_LATCH_STATE_TABLE};
char *CAMERA_MODEL_STATE_DESCRIPTION[] = {"0", CAMERA_MODEL_STATE_TABLE};
char *DRIVER_STATE_DESCRIPTION[] = {"0", DRIVER_STATE_TABLE};
#undef TR
#undef TE
char state_str[SSLEN+1];
char event_str[ESLEN+1];
/* Clear event channel */
void EVclr(event_t *E) {
E->ca=0;
E->cm=0;
E->cd=0;
E->dr=0;
}
/* Set event channel */
void EVset(event_t *E, event_t Ev) {
if (Ev.ca) E->ca = Ev.ca;
if (Ev.cm) E->cm = Ev.cm;
if (Ev.cd) E->cd = Ev.cd;
if (Ev.dr) E->dr = Ev.dr;
}
/* 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;
}
enum event_codes camera_model(enum event_codes event) {
switch (event) {
case ECA_START:
case ECA_OPEN_SHUTR:
case ECA_ACQ_IMAGE:
return ECM_ACQ;
case ECA_CLOSE_SHUTR:
case ECA_READ_IMAGE:
case ECA_SEND_IMAGE:
return ECM_PROC;
case ECA_STOP:
return ECM_STOP;
case ECA_IDLE:
return ECM_IDLE;
case ECA_FAIL:
return ECM_FAIL;
default:
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=" ,";
char str[100], *tok;
int ret = 1;
strcpy(str,msg);
tok=strtok(str,delim);
ret = cam_rep2sym(tok);
if (ret != -1) {
*ca_sym = ret;
if (ECA_IDLE == *ca_sym) {
*time_rem = *time_tot = -1;
} else {
tok=strstr(msg, "Remaining");
sscanf(tok, " Remaining= %d ms, Total Time= %d ms, ", time_rem, time_tot);
}
}
return ret;
}
/* return -1 if message is unknown
* NOTE: 0 has meaning in the transition table
*/
enum event_codes cam_rep2sym(char *msg) {
int i;
for (i = ECA_START; i <= ECA_STOP; i++) {
if (0 == strcmp(msg, event_signatures[i])) {
return i;
}
}
return -1;
}
/* return 0 = no transition,
* return 1 = transition
*/
int cam_trans_fn(state_t Sc, enum event_codes Ein, state_t *Sn, event_t *Eo) {
trans_t tt;
int i, ret=0;
STset(Sn, Sc);
EVclr(Eo);
for (i=0; tt=TRANS_TABLE[i], tt.Sc.dr != END_TABLE; i++) {
if ( Ein == tt.Ei && INSYS(Sc,tt.Sc)) {
STset(Sn, tt.Sn);
EVset(Eo, tt.Eo);
ret = 1;
}
}
return ret;
}
void camdriv_input(void *caller, camdriv_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);
self->Sc = Sn;
}
char *strstate(state_t s) {
char *cl, *cm, *dr;
cm = SCM_NAMES[s.cm];
cl = SCL_NAMES[s.cl];
dr = SDR_NAMES[s.dr];
snprintf(state_str, SSLEN, "%s,%s,%s", cm, cl, dr);
return state_str;
}
char *strevent(event_t E) {
char *ca, *cm, *cd, *dr;
ca = event_names[E.ca];
cm = event_names[E.cm];
cd = event_names[E.cd];
dr = event_names[E.dr];
snprintf(event_str, ESLEN, "%s,%s,%s,%s", ca, cm, cd, dr);
return event_str;
}
/* 0 = wildcard for states.
* 0 = no output for the output events.
*/
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}},*/
{{.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}}
};