Add trigger functionality
This commit is contained in:
parent
5c42094b06
commit
ba13899644
107
eismultiplexer.c
107
eismultiplexer.c
|
@ -33,6 +33,39 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#ifdef WIND32
|
||||||
|
#include <synchapi.h>
|
||||||
|
#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)
|
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);
|
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)
|
void eismultiplexer_disconnect(struct eismultiplexer* muliplexer)
|
||||||
{
|
{
|
||||||
usbshm_close(muliplexer->priv);
|
usbshm_close(muliplexer->priv);
|
||||||
|
|
|
@ -54,6 +54,23 @@ typedef enum {
|
||||||
CHANNEL_NONE = 0,
|
CHANNEL_NONE = 0,
|
||||||
} channel_t;
|
} 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 eismultiplexer {
|
||||||
struct usbshm* priv;
|
struct usbshm* priv;
|
||||||
};
|
};
|
||||||
|
@ -113,6 +130,41 @@ channel_t eismultiplexer_get_connected(struct eismultiplexer* muliplexer);
|
||||||
*/
|
*/
|
||||||
int eismultiplexer_set_led(struct eismultiplexer* muliplexer, bool on);
|
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
|
* @brief Gets the number of channels on the device
|
||||||
* @param multiplexer pointer to an eismultiplexer struct
|
* @param multiplexer pointer to an eismultiplexer struct
|
||||||
|
|
40
main.c
40
main.c
|
@ -80,8 +80,9 @@ void print_commands(void)
|
||||||
puts("get\t\t\t | get the state of all channels");
|
puts("get\t\t\t | get the state of all channels");
|
||||||
puts("read [ADDRESS] [LENGTH]\t | read from the device eeprom at address");
|
puts("read [ADDRESS] [LENGTH]\t | read from the device eeprom at address");
|
||||||
puts("write [ADDRESS] [LENGTH] | write to 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("trigger [INDEX] [STATE]\t | set the trigger state input (0), output and low (1) or output and high(2)");
|
||||||
puts("channels | get the channel of the device");
|
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)
|
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);
|
bool connected = channels & (1 << i);
|
||||||
printf("Channel %c: %s\n", (char)('A'+i), connected ? "on" : "off");
|
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)
|
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);
|
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
|
else
|
||||||
{
|
{
|
||||||
if(command_count != 2)
|
if(command_count != 2)
|
||||||
|
|
Loading…
Reference in a new issue