From ba13899644e2f209d119927337a4d279642cedb1 Mon Sep 17 00:00:00 2001 From: Carl Philipp Klemm Date: Tue, 7 Oct 2025 15:16:23 +0200 Subject: [PATCH] Add trigger functionality --- eismultiplexer.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++ eismultiplexer.h | 52 +++++++++++++++++++++++ main.c | 40 +++++++++++++++++- 3 files changed, 197 insertions(+), 2 deletions(-) diff --git a/eismultiplexer.c b/eismultiplexer.c index 925b344..08477fa 100644 --- a/eismultiplexer.c +++ b/eismultiplexer.c @@ -33,6 +33,39 @@ #include #include #include +#include + +#ifdef WIND32 +#include +#endif + +typedef enum +{ + COMMAND_LED_OFF = 0, + COMMAND_LED_ON, + COMMAND_SET_OUTPUTS, + COMMAND_GET_OUTPUTS, + COMMAND_EEPROM_READ, + COMMAND_EEPROM_WRITE, + COMMAND_GET_GITREV, + COMMAND_GET_CHANNEL_COUNT, + COMMAND_GET_PROTO_VERSION, + COMMAND_SET_TRIG, + COMMAND_GET_TRIG, + COMMAND_GET_TRIG_COUNT +} command_t; + +static void msleep(uint64_t milliseconds) +{ +#ifdef WIN32 + Sleep(milliseconds); +#else + struct timespec ts; + ts.tv_sec = milliseconds / 1000; + ts.tv_nsec = (milliseconds % 1000) * 1000000; + nanosleep(&ts, NULL); +#endif +} uint16_t* eismultiplexer_list_available_devices(size_t* count) { @@ -130,6 +163,80 @@ uint16_t eismultiplexer_read_eeprom(struct eismultiplexer* muliplexer, uint16_t return *((uint16_t*)buffer); } +int eismultiplexer_set_trigger_state(struct eismultiplexer* muliplexer, uint16_t index, trigger_state_t state) +{ + int ret; + ret = usbshm_write_control_transfer(muliplexer->priv, COMMAND_SET_TRIG, NULL, 0, state, index); + return ret; +} + +int eismultiplexer_get_trigger_state(struct eismultiplexer* muliplexer, uint16_t index, trigger_state_t* state, bool* level) +{ + uint8_t buffer[2] = {}; + int ret = usbshm_read_control_transfer(muliplexer->priv, COMMAND_GET_TRIG, 0, index, buffer, 2); + if(ret == 2) { + if(state) + *state = buffer[1]; + if(level) + *level = buffer[0]; + } + return ret; +} + +int eismultiplexer_wait_trigger(struct eismultiplexer* muliplexer, uint16_t index, trigger_wait_t wait, uint64_t timeout) +{ + bool level; + bool prevlevel; + int ret = eismultiplexer_get_trigger_state(muliplexer, index, NULL, &prevlevel); + if(ret != 2) + return ret; + + struct timeval start; + struct timeval current; + gettimeofday(&start, NULL); + gettimeofday(¤t, NULL); + while((current.tv_sec - start.tv_sec)*1000 + (current.tv_usec - start.tv_usec)/1000 < timeout) { + int ret = eismultiplexer_get_trigger_state(muliplexer, index, NULL, &level); + if(ret != 2) + return ret; + switch(wait) { + case TRIGGER_WAIT_HIGH_LEVEL: + if(level) + return 0; + break; + case TRIGGER_WAIT_LOW_LEVEL: + if(!level) + return 0; + break; + case TRIGGER_WAIT_EDGE: + if(prevlevel != level) + return 0; + break; + case TRIGGER_WAIT_HIGH: + if(!prevlevel && level) + return 0; + break; + case TRIGGER_WAIT_LOW: + if(prevlevel && !level) + return 0; + break; + } + msleep(100); + gettimeofday(¤t, NULL); + } + return 1; +} + +int eismultiplexer_get_trigger_count(struct eismultiplexer* muliplexer) +{ + uint8_t buffer[1] = {}; + int ret = usbshm_read_control_transfer(muliplexer->priv, COMMAND_GET_TRIG, 0, 0, buffer, 1); + if(ret >= 0) + return buffer[0]; + else + return 0; +} + void eismultiplexer_disconnect(struct eismultiplexer* muliplexer) { usbshm_close(muliplexer->priv); diff --git a/eismultiplexer.h b/eismultiplexer.h index 711a318..e5cb1ef 100644 --- a/eismultiplexer.h +++ b/eismultiplexer.h @@ -54,6 +54,23 @@ typedef enum { CHANNEL_NONE = 0, } channel_t; +typedef enum +{ + TRIGGER_INPUT = 0, /*** Trigger is high impedance and set as an input*/ + TRIGGER_LOW, /*** Trigger output is logic low*/ + TRIGGER_HIGH, /*** Trigger output is logic high*/ + TRIGGER_STATE_COUNT +} trigger_state_t; + +typedef enum +{ + TRIGGER_WAIT_LOW = 0, /*** Waits until the trigger falls from high to low*/ + TRIGGER_WAIT_HIGH, /*** Waits until the trigger rises from low to high*/ + TRIGGER_WAIT_EDGE, /*** Waits until the trigger changes from low to high or high to low*/ + TRIGGER_WAIT_LOW_LEVEL, /*** Waits until the trigger is low*/ + TRIGGER_WAIT_HIGH_LEVEL /*** Waits until the trigger is high*/ +} trigger_wait_t; + struct eismultiplexer { struct usbshm* priv; }; @@ -113,6 +130,41 @@ channel_t eismultiplexer_get_connected(struct eismultiplexer* muliplexer); */ int eismultiplexer_set_led(struct eismultiplexer* muliplexer, bool on); +/** + * @brief Sets the state of the trigger pin + * @param multiplexer pointer to a eismultiplexer struct + * @param state state to put the trigger in + * @param index the index of the trigger to set + * @return 0 on success and < 0 on failure + */ +int eismultiplexer_set_trigger_state(struct eismultiplexer* muliplexer, uint16_t index, trigger_state_t state); + +/** + * @brief Gets the logic level and state of the trigger pin + * @param multiplexer pointer to a eismultiplexer struct + * @param index the index of the trigger + * @param state a pointer where the current state of the trigger will be stored, can be NULL + * @param level a pointer where the current logic level of the trigger will be stored, only relevant if state is TRIGGER_INPUT, can be NULL + * @return 0 on success and < 0 on failure + */ +int eismultiplexer_get_trigger_state(struct eismultiplexer* muliplexer, uint16_t index, trigger_state_t* state, bool* level); + +/** + * @brief Sets the state of the trigger pin + * @param multiplexer pointer to a eismultiplexer struct + * @param index the index of the trigger + * @param wait wait type + * @param timeout maximum time in milliseconds to wait + * @return 0 on success and < 0 on failure + */ +int eismultiplexer_wait_trigger(struct eismultiplexer* muliplexer, uint16_t index, trigger_wait_t wait, uint64_t timeout); + +/** + * @brief gets the nummber of trigger pins available on the device + * @return the nummber of trigger pins on success and < 0 on failure + */ +int eismultiplexer_get_trigger_count(struct eismultiplexer* muliplexer); + /** * @brief Gets the number of channels on the device * @param multiplexer pointer to an eismultiplexer struct diff --git a/main.c b/main.c index 7f6f706..62fc29f 100644 --- a/main.c +++ b/main.c @@ -80,8 +80,9 @@ void print_commands(void) puts("get\t\t\t | get the state of all channels"); puts("read [ADDRESS] [LENGTH]\t | read from the device eeprom at address"); puts("write [ADDRESS] [LENGTH] | write to the device eeprom at address"); - puts("list | list the serial nummbers of the connected devices"); - puts("channels | get the channel of the device"); + puts("trigger [INDEX] [STATE]\t | set the trigger state input (0), output and low (1) or output and high(2)"); + puts("list\t\t\t | list the serial nummbers of the connected devices"); + puts("channels\t\t | get the number of channels the device has"); } static int process_commands(char** commands, size_t command_count, struct eismultiplexer* multiplexer, char* name) @@ -160,6 +161,14 @@ static int process_commands(char** commands, size_t command_count, struct eismul bool connected = channels & (1 << i); printf("Channel %c: %s\n", (char)('A'+i), connected ? "on" : "off"); } + int trigger_count = eismultiplexer_get_trigger_count(multiplexer); + for(int i = 0; i < trigger_count; ++i) + { + trigger_state_t state; + bool level; + eismultiplexer_get_trigger_state(multiplexer, i, &state, &level); + printf("Trigger %i: state: %i level: %i\n", i, state, level); + } } else if(strcmp(commands[0], "channels") == 0) { @@ -187,6 +196,33 @@ static int process_commands(char** commands, size_t command_count, struct eismul free(serials); } + else if(strcmp(commands[0], "trigger") == 0) + { + if(command_count < 2) + { + printf("Usage %s %s [INDEX] [STATE]\n", name, commands[0]); + return 2; + } + int trigger_count = eismultiplexer_get_trigger_count(multiplexer); + long index = strtol(commands[1], NULL, 10); + long state = strtol(commands[2], NULL, 10); + if(state >= TRIGGER_STATE_COUNT) + { + printf("%li is an invalid state\n", state); + return 2; + } + if(index >= trigger_count) + { + printf("%li is out of range as the device has only %i triggers\n", index, trigger_count); + return 2; + } + int ret = eismultiplexer_set_trigger_state(multiplexer, index, state); + if(ret < 0) + { + puts("Unable to set trigger state"); + return 3; + } + } else { if(command_count != 2)