The camera driver will now upload the exposure time when it's called from a scan object. The output function now returns events which are not targeted at the camera or SICS so that they can be fed back into the state transition function. The input event handler (camera.c:camdriv_input) now feeds output events back into the transition function.
210 lines
5.9 KiB
C
210 lines
5.9 KiB
C
/**
|
|
* \file camera_test.c
|
|
* \brief Test camera.[ch] state machine.
|
|
*
|
|
* \Author Ferdi Franceschini February 2013
|
|
*/
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "camera.h"
|
|
|
|
|
|
void print_state(state_t s) {
|
|
char *cl, *cm, *dr;
|
|
cm = SCM_NAMES[s.cm];
|
|
cl = SCL_NAMES[s.cl];
|
|
dr = SDR_NAMES[s.dr];
|
|
printf("%s,%s,%s", cm, cl, dr);
|
|
}
|
|
|
|
void print_event(event_t E) {
|
|
char *ca, *cm, *cd, *dr, *cl;
|
|
ca = event_names[E.ca];
|
|
cm = event_names[E.cm];
|
|
cd = event_names[E.cd];
|
|
dr = event_names[E.dr];
|
|
cl = event_names[E.cl];
|
|
printf("%s,%s,%s,%s,%s", ca, cm, cd, dr, cl);
|
|
}
|
|
|
|
event_t output(state_t Sc, enum event_codes Ei) {
|
|
int i;
|
|
trans_t tr;
|
|
event_t Eo;
|
|
|
|
for (i=0; tr=TRANS_TABLE[i], tr.Sc.dr!= END_TABLE; i++) {
|
|
if (Ei==tr.Ei && INSYS(Sc,tr.Sc)) {
|
|
EVset(&Eo,tr.Eo);
|
|
}
|
|
}
|
|
return Eo;
|
|
}
|
|
|
|
int test_camrep2sym(void) {
|
|
int i, cm_sym, time_rem, time_tot;
|
|
enum event_codes ca_sym;
|
|
char *camrep[] = {
|
|
"StartTime Remaining= 3907 ms, Total Time=3686 ms,",
|
|
"Open ShutrTime Remaining= 539454 ms, Total Time=3686 ms,",
|
|
"Acq ImageTime Remaining= 109 ms, Total Time=3686 ms,",
|
|
"Close ShutrTime Remaining= 218 ms, Total Time=3686 ms,",
|
|
"Read ImageTime Remaining= 328 ms, Total Time=3686 ms,",
|
|
"Read ImageTime Remaining= 328 ms, Total Time=3686 ms,",
|
|
"Read ImageTime Remaining= 328 ms, Total Time=3686 ms,",
|
|
"Idle",
|
|
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",
|
|
camrep[i], event_names[ca_sym], event_names[cm_sym]);
|
|
else
|
|
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;
|
|
}
|
|
|
|
int test_trans_fn(void) {
|
|
int i;
|
|
event_t Eo={0,0,0,0,0};
|
|
|
|
|
|
state_t Sc = {.cl=SCL_RDY, .cm=SCM_IDLE, .dr=SDR_IDLE};
|
|
int input[] = {
|
|
ECM_IDLE, ECD_TK_SHOT, ECM_IDLE, ECM_IDLE, ECM_ACQ, ECD_TK_SHOT,
|
|
ECM_PROC, ECD_TK_SHOT, ECM_PROC, ECM_IDLE, ECM_ACQ,
|
|
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);
|
|
printf("%s,\t",event_names[input[i]]);
|
|
print_state(Sc);
|
|
cam_trans_fn(Sc, input[i], &Sc, &Eo);
|
|
printf(",\t");
|
|
print_event(Eo);
|
|
printf("\n");
|
|
if (Eo.cl) {
|
|
/* TODO Handle feedback in the general case where there may be multiple events in Eo to feed back into the transition function */
|
|
printf("%s,\t",event_names[Eo.cl]);
|
|
print_state(Sc);
|
|
cam_trans_fn(Sc, Eo.cl, &Sc, &Eo);
|
|
printf(",\t");
|
|
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 */
|
|
if (Eo.ca) {
|
|
printf("camdriv_out: symbol=%s, output=%s\n", event_names[Eo.ca], event_signatures[Eo.ca]);
|
|
}
|
|
if (Eo.cm) {
|
|
printf("camdriv_out: symbol=%s, output=%s\n", event_names[Eo.cm], event_signatures[Eo.cm]);
|
|
}
|
|
if (Eo.cd) {
|
|
printf("camdriv_out: symbol=%s, output=%s\n", event_names[Eo.cd], event_signatures[Eo.cd]);
|
|
}
|
|
if (Eo.dr) {
|
|
printf("camdriv_out: symbol=%s, output=%s\n", event_names[Eo.dr], event_signatures[Eo.dr]);
|
|
}
|
|
if (Eo.cl) {
|
|
printf("camdriv_out: symbol=%s, output=%s\n", event_names[Eo.cl], event_signatures[Eo.cl]);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int test_camdriv_event_io(void) {
|
|
int Ein=ECD_TK_SHOT;
|
|
int self;
|
|
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);
|
|
printf("\n");
|
|
camdriv_input(&self, &cdinfo, Ein);
|
|
|
|
Ein = ECM_IDLE;
|
|
printf("input: %s :", event_names[Ein]);
|
|
cdinfo.Sc.cl=SCL_TK_SHOT;
|
|
print_state(cdinfo.Sc);
|
|
printf("\n");
|
|
camdriv_input(&self, &cdinfo, Ein);
|
|
|
|
fprintf(stderr, "TEST_CAMDRIVER_EVENT_IO:OUPUT:END\n");
|
|
return 1;
|
|
}
|
|
|
|
char *tests[] = {"camrep2sym", "trans_fn", "camdriv_input"};
|
|
void usage(char *name) {
|
|
int i;
|
|
printf("Usage: %s [n]\n",name);
|
|
printf("default: run all tests\n");
|
|
printf("n is an int whose bits indicate which tests will be executed as follows\n");
|
|
for (i=0; i<3; i++)
|
|
printf("n=%d; %s\n",1 << i, tests[i]);
|
|
printf("\n");
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
int ret, test=0, tflag=7;
|
|
|
|
if (argc == 1)
|
|
test = tflag;
|
|
else if (strstr(argv[1], "help")) {
|
|
usage(argv[0]);
|
|
return 0;
|
|
} else
|
|
test = atoi(argv[1]);
|
|
|
|
if ((test < 1) || (test > tflag)) {
|
|
printf("ERROR: Argument must be a positive integer between 1 and %d inclusive\n", tflag);
|
|
usage(argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
|
|
if (test & 1)
|
|
ret = test_camrep2sym();
|
|
if (test & 2)
|
|
ret = test_trans_fn();
|
|
if (test & 4)
|
|
ret = test_camdriv_event_io();
|
|
|
|
if (ret)
|
|
return 0;
|
|
else
|
|
return 1;
|
|
}
|