Skip to content

Commit

Permalink
failure to set output trigger (#77)
Browse files Browse the repository at this point in the history
closes #76 

When setting up output triggering, DCAM_IDPROP_OUTPUTTRIGGER_SOURCE was
being set for all trigger kinds but it's not always writable. The
"trigger source" is only really for when using
DCAMPROP_OUTPUTTRIGGER_KIND__PROGRAMABLE.

Adds a test that runs through setting up an output trigger on line 1
configured to output when exposure starts.
  • Loading branch information
nclack authored Aug 10, 2023
1 parent 25e848e commit 01da744
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 26 deletions.
46 changes: 25 additions & 21 deletions src/dcam.camera.c
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ set_input_triggering(HDCAM h, struct CameraProperties* settings)
return 0;
}

// Sets used_lines[i] to true if line i is used.
static int
set_output_trigger__handler(HDCAM h,
const struct Trigger* trigger,
Expand All @@ -257,12 +258,15 @@ set_output_trigger__handler(HDCAM h,
? DCAMPROP_OUTPUTTRIGGER_POLARITY__NEGATIVE
: DCAMPROP_OUTPUTTRIGGER_POLARITY__POSITIVE;
used_lines[line] = 1;
array_prop_write(i32, h, DCAM_IDPROP_OUTPUTTRIGGER_KIND, line, kind);
CHECK(
array_prop_write(i32, h, DCAM_IDPROP_OUTPUTTRIGGER_KIND, line, kind));

array_prop_write(
i32, h, DCAM_IDPROP_OUTPUTTRIGGER_SOURCE, line, source);
if (kind == DCAMPROP_OUTPUTTRIGGER_KIND__PROGRAMABLE) {
CHECK(array_prop_write(
i32, h, DCAM_IDPROP_OUTPUTTRIGGER_SOURCE, line, source));
}

DCAM(array_prop_write(
CHECK(array_prop_write(
i32, h, DCAM_IDPROP_OUTPUTTRIGGER_POLARITY, line, edge));
}
return 1;
Expand All @@ -276,12 +280,11 @@ set_output_triggering(HDCAM h, struct CameraProperties* settings)
int used_lines[3] = { 0 };

if (settings->output_triggers.exposure.enable) {
CHECK(
set_output_trigger__handler(h,
&settings->output_triggers.exposure,
used_lines,
DCAMPROP_OUTPUTTRIGGER_KIND__EXPOSURE,
DCAMPROP_OUTPUTTRIGGER_SOURCE__EXPOSURE));
CHECK(set_output_trigger__handler(h,
&settings->output_triggers.exposure,
used_lines,
DCAMPROP_OUTPUTTRIGGER_KIND__EXPOSURE,
0 /*NA*/));
}

if (settings->output_triggers.frame_start.enable) {
Expand All @@ -294,21 +297,22 @@ set_output_triggering(HDCAM h, struct CameraProperties* settings)
}

if (settings->output_triggers.trigger_wait.enable) {
CHECK(set_output_trigger__handler(
h,
&settings->output_triggers.trigger_wait,
used_lines,
DCAMPROP_OUTPUTTRIGGER_KIND__TRIGGERREADY,
DCAMPROP_OUTPUTTRIGGER_SOURCE__READOUTEND));
CHECK(
set_output_trigger__handler(h,
&settings->output_triggers.trigger_wait,
used_lines,
DCAMPROP_OUTPUTTRIGGER_KIND__TRIGGERREADY,
0 /*NA*/));
}

// set unused lines low
for (int i = 0; i < countof(used_lines); ++i) {
array_prop_write(i32,
h,
DCAM_IDPROP_OUTPUTTRIGGER_KIND,
i,
DCAMPROP_OUTPUTTRIGGER_KIND__LOW);
if (!used_lines[i])
CHECK(array_prop_write(i32,
h,
DCAM_IDPROP_OUTPUTTRIGGER_KIND,
i,
DCAMPROP_OUTPUTTRIGGER_KIND__LOW));
}

return 1;
Expand Down
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ else()
dcam-list-triggers
dcam-reset-on-fail
one-video-stream
set-output-trigger
)

foreach(name ${tests})
Expand Down
51 changes: 46 additions & 5 deletions tests/dcam-list-triggers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,14 @@ main()

acquire_get_configuration_metadata(runtime, &metadata);

printf("Digital Lines\n");
{
const auto* info = &metadata.video[0].camera.digital_lines;
for (int i = 0; i < info->line_count; ++i)
printf("\t[%2d] %18s\n", i, info->names[i]);
}

printf("Input Events\n");
{
const int n_triggers =
sizeof(props.video[0].camera.settings.input_triggers) /
Expand All @@ -128,14 +136,47 @@ main()
((const struct Trigger*)&props.video[stream_id]
.camera.settings.input_triggers) +
i_trigger;
printf("\t[%2d] %18s %8s %2d %10s %10s %10s\n",
printf("\t[%2d] %18s %8s %2d %20s %20s\n",
i_trigger,
t->enable ? metadata.video[stream_id]
.camera.digital_lines.names[t->line]
: "",
t->enable ? "enabled" : "",
t->line,
event_names[i_trigger],
t->enable ? trigger_edge_to_string(t->edge) : "");
}
}
}
}

printf("Output Events\n");
{
const int n_triggers =
sizeof(props.video[0].camera.settings.output_triggers) /
sizeof(Trigger);
const char* event_names[] = {
"Exposure",
"FrameStart",
"TriggerWait",
};
for (int stream_id = 0; stream_id < countof(props.video); ++stream_id) {
if (props.video[stream_id].camera.identifier.kind !=
DeviceKind_None) {
printf("Video %d\n", stream_id);
for (int i_trigger = 0; i_trigger < n_triggers; ++i_trigger) {
const Trigger* t =
((const struct Trigger*)&props.video[stream_id]
.camera.settings.output_triggers) +
i_trigger;
printf("\t[%2d] %18s %8s %2d %20s %20s\n",
i_trigger,
metadata.video[stream_id]
.camera.digital_lines.names[t->line],
t->enable ? metadata.video[stream_id]
.camera.digital_lines.names[t->line]
: "",
t->enable ? "enabled" : "",
t->line,
t->enable ? event_names[i_trigger] : "",
t->enable ? signal_io_kind_to_string(t->kind) : "",
event_names[i_trigger],
t->enable ? trigger_edge_to_string(t->edge) : "");
}
}
Expand Down
106 changes: 106 additions & 0 deletions tests/set-output-trigger.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
//! Test: Runs through setting up an output trigger on line 1 configured to
//! output when exposure starts.
#include "acquire.h"
#include "device/hal/device.manager.h"
#include "device/props/components.h"
#include "logger.h"
#include <stdio.h>
#include <string.h>

#define L (aq_logger)
#define LOG(...) L(0, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
#define ERR(...) L(1, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
#define CHECK(e) \
do { \
if (!(e)) { \
ERR("Expression evaluated as false: " #e); \
goto Error; \
} \
} while (0)
#define DEVOK(e) CHECK(Device_Ok == (e))
#define OK(e) CHECK(AcquireStatus_Ok == (e))

#define countof(e) (sizeof(e) / sizeof(*(e)))

void
reporter(int is_error,
const char* file,
int line,
const char* function,
const char* msg)
{
fprintf(is_error ? stderr : stdout,
"%s%s(%d) - %s: %s\n",
is_error ? "ERROR " : "",
file,
line,
function,
msg);
}

uint8_t
select_digital_line(const AcquireRuntime* runtime, const char* name)
{
AcquirePropertyMetadata meta = {};
OK(acquire_get_configuration_metadata(runtime, &meta));
{
const auto* info = &meta.video[0].camera.digital_lines;
for (int i = 0; i < info->line_count; ++i)
if (strcmp(info->names[i], name) == 0)
return i;
}
Error:
return -1;
}

int
setup(AcquireRuntime* runtime)
{
AcquireProperties props = {};

const DeviceManager* dm = 0;
CHECK(dm = acquire_device_manager(runtime));

#define SIZED(s) s, sizeof(s) - 1
DEVOK(device_manager_select(dm,
DeviceKind_Camera,
SIZED("Hamamatsu C15440-20UP.*"),
&props.video[0].camera.identifier));
DEVOK(device_manager_select(dm,
DeviceKind_Storage,
SIZED("Trash"),
&props.video[0].storage.identifier));
#undef SIZED

props.video[0].max_frame_count = 10;
props.video[0].camera.settings.output_triggers.exposure = {
.enable = 1,
.line = 1,
.kind = Signal_Output,
.edge = TriggerEdge_Rising
};
OK(acquire_configure(runtime, &props));
// Expect that "Timing 1" is line id 1.
// select_digital_line() must be called after setting the camera.
CHECK(select_digital_line(runtime, "Timing 1") == 1);
return 1;
Error:
return 0;
}

int
main()
{
int ecode = 0;
AcquireRuntime* runtime = 0;
CHECK(runtime = acquire_init(reporter));
CHECK(setup(runtime));
OK(acquire_start(runtime));
OK(acquire_stop(runtime));
Finalize:
acquire_shutdown(runtime);
return ecode;
Error:
ecode = 1;
goto Finalize;
}

0 comments on commit 01da744

Please sign in to comment.