Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
W
White Rabbit Trigger Distribution
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
White Rabbit Trigger Distribution
Commits
a9d7899e
Commit
a9d7899e
authored
Jan 25, 2019
by
Dimitris Lampridis
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
sw: remove deprecated lib-old
parent
407f25d7
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
0 additions
and
3144 deletions
+0
-3144
.gitignore
software/lib-old/.gitignore
+0
-3
Makefile
software/lib-old/Makefile
+0
-49
libwrtd-common.c
software/lib-old/libwrtd-common.c
+0
-298
libwrtd-input.c
software/lib-old/libwrtd-input.c
+0
-767
libwrtd-internal.c
software/lib-old/libwrtd-internal.c
+0
-102
libwrtd-internal.h
software/lib-old/libwrtd-internal.h
+0
-50
libwrtd-logging.c
software/lib-old/libwrtd-logging.c
+0
-296
libwrtd-output.c
software/lib-old/libwrtd-output.c
+0
-1164
libwrtd.h
software/lib-old/libwrtd.h
+0
-331
readme.md
software/lib-old/readme.md
+0
-84
No files found.
software/lib-old/.gitignore
deleted
100644 → 0
View file @
407f25d7
*.a
*.so
.depend
software/lib-old/Makefile
deleted
100644 → 0
View file @
407f25d7
# If it exists includes Makefile.specific. In this Makefile, you should put
# specific Makefile code that you want to run before this. For example,
# build a particular environment.
-include
Makefile.specific
# include parent_common.mk for buildsystem's defines
# It allows you to inherit an environment configuration from larger project
REPO_PARENT
?=
..
-include
$(REPO_PARENT)/parent_common.mk
TRTL
?=
../../dependencies/mock-turtle/software
LIBTDC
?=
../../fmc-tdc-sw/lib
LIBFD
?=
../../fine-delay-sw/lib
LIBS
=
libwrtd.so
LIB
=
libwrtd.a
LOBJ
:=
libwrtd-internal.o
LOBJ
+=
libwrtd-common.o
LOBJ
+=
libwrtd-logging.o
LOBJ
+=
libwrtd-input.o
LOBJ
+=
libwrtd-output.o
CFLAGS
+=
-Wall
-ggdb
-O2
-fPIC
-I
.
-I
../include
-I
$(TRTL)
/include
-I
$(TRTL)
/lib
-I
$(LIBFD)
-I
$(LIBTDC)
-I
$(LIBFD)
/../kernel
CFLAGS
+=
-Werror
CFLAGS
+=
$(EXTRACFLAGS)
LDLIBS
+=
-L
.
-lwrtd
ARFLAGS
=
rc
modules all
:
$(LIB) $(LIBS)
%
:
%.c $(LIB)
$(CC)
$(CFLAGS)
$(LDFLAGS)
$*
.c
$(LDLIBS)
-o
$@
$(LIB)
:
$(LOBJ)
$(AR)
$(ARFLAGS)
$@
$^
$(LIBS)
:
$(LIB)
$(CC)
-shared
-o
$@
-Wl
,--whole-archive,-soname,
$@
$^
-Wl
,--no-whole-archive
clean
:
rm
-f
$(LIB)
.depend
*
.o
*
~
.depend
:
Makefile $(wildcard *.c *.h)
$(CC)
$(CFLAGS)
-M
$
(
LOBJ:.o
=
.c
)
-o
$@
install modules_install
:
-include
.depend
software/lib-old/libwrtd-common.c
deleted
100644 → 0
View file @
407f25d7
/*
* Copyright (C) 2014-2016 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
* inspired by a draft of Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <stdint.h>
#include <libmockturtle.h>
#include <libwrtd-internal.h>
static
const
char
*
const
wrtd_errors
[]
=
{
"Received an invalid answer from white-rabbit-node-code CPU"
,
"Cannot read channel/trigger state"
,
"You are using an invalid binary"
,
"Invalid dead time value"
,
"Invalid delay value"
,
"Invalid trigger identifier"
,
"Invalid channel number"
,
"Function not yet implemented"
,
"Received an invalid trigger entry"
,
"Received an invalid hash entry"
,
"Received an invalid hash chain"
,
"Received an invalid trigger handle"
,
"Trigger not found"
,
"No trigger condition"
,
"Invalid pulse width"
,
"Invalid input real-time application version"
,
"Invalid output real-time application version"
};
/**
* It returns a string messages corresponding to a given error code. If
* it is not a libwrtd error code, it will run trtl_strerror()
* @param[in] err error code
* @return a message error
*/
const
char
*
wrtd_strerror
(
int
err
)
{
if
(
err
<
EWRTD_INVALID_ANSWER_ACK
||
err
>=
__EWRTD_MAX_ERROR_NUMBER
)
return
trtl_strerror
(
err
);
return
wrtd_errors
[
err
-
EWRTD_INVALID_ANSWER_ACK
];
}
/**
* It initializes the WRTD library. It must be called before doing
* anything else. If you are going to load/unload WRTD devices, then
* you have to un-load (wrtd_exit()) e reload (wrtd_init()) the library.
*
* This library is based on the libmockturtle, so internally, this function also
* run trtl_init() in order to initialize the WRNC library.
* @return 0 on success, otherwise -1 and errno is appropriately set
*/
int
wrtd_init
(
void
)
{
int
err
;
err
=
trtl_init
();
if
(
err
)
return
err
;
return
0
;
}
/**
* It releases the resources allocated by wrtd_init(). It must be called when
* you stop to use this library. Then, you cannot use functions from this
* library.
*/
void
wrtd_exit
(
void
)
{
trtl_exit
();
}
static
int
__wrtd_load
(
struct
wrtd_desc
*
wrtd
,
char
*
fw
,
unsigned
int
cpu
,
uint16_t
id
)
{
struct
trtl_fw_version
version
;
int
err
;
err
=
trtl_cpu_load_application_file
(
wrtd
->
trtl
,
cpu
,
fw
);
if
(
err
)
return
err
;
err
=
trtl_cpu_enable
(
wrtd
->
trtl
,
cpu
);
if
(
err
)
return
err
;
/* Do a ping, but wait for 5sec for the FW to be ready. */
err
=
trtl_fw_ping_timeout
(
wrtd
->
trtl
,
cpu
,
0
,
5000
);
if
(
err
)
return
err
;
err
=
trtl_fw_version
(
wrtd
->
trtl
,
cpu
,
0
,
&
version
);
if
(
err
)
return
err
;
if
(
version
.
rt_id
!=
id
)
{
errno
=
EWRTD_INVALID_IN_APP
;
return
-
1
;
}
return
0
;
}
/**
* It loads the input firmare (TDC)
* @param[in] dev device token
* @param[in] fw path to firmware
* @return 0 on success, otherwise -1 and errno is appropriately set
*/
int
wrtd_in_load
(
struct
wrtd_node
*
dev
,
char
*
fw
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
return
__wrtd_load
(
wrtd
,
fw
,
WRTD_CPU_TDC
,
WRTD_IN_RT_ID
);
}
/**
* It loads the output firmare (FD)
* @param[in] dev device token
* @param[in] fw path to firmware
* @return 0 on success, otherwise -1 and errno is appropriately set
*/
int
wrtd_out_load
(
struct
wrtd_node
*
dev
,
char
*
fw
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
return
__wrtd_load
(
wrtd
,
fw
,
WRTD_CPU_FD
,
WRTD_OUT_RT_ID
);
}
/**
* It opens and initialize the configuration for the given device
* @param[in] device_id device identifier
* @return It returns an anonymous wrtd_node structure on success.
* On error, NULL is returned, and errno is set appropriately.
*/
struct
wrtd_node
*
wrtd_open
(
uint32_t
device_id
)
{
struct
wrtd_desc
*
wrtd
;
wrtd
=
malloc
(
sizeof
(
struct
wrtd_desc
));
if
(
!
wrtd
)
return
NULL
;
wrtd
->
trtl
=
trtl_open_by_id
(
device_id
);
if
(
!
wrtd
->
trtl
)
goto
out
;
wrtd
->
dev_id
=
device_id
;
return
(
struct
wrtd_node
*
)
wrtd
;
out:
free
(
wrtd
);
return
NULL
;
}
/**
* It closes a WRTD device opened with one of the following function:
* wrtd_open_by_lun(), wrtd_open_by_fmc()
* @param[in] dev device token
*/
void
wrtd_close
(
struct
wrtd_node
*
dev
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
trtl_close
(
wrtd
->
trtl
);
free
(
wrtd
);
dev
=
NULL
;
}
/**
* It returns the WRNC token in order to allows users to run
* functions from the WRNC library
* @param[in] dev device token
* @return the WRNC token
*/
struct
trtl_dev
*
wrtd_get_trtl_dev
(
struct
wrtd_node
*
dev
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
return
(
struct
trtl_dev
*
)
wrtd
->
trtl
;
}
/**
* It converts the white rabbit time stamp to a pico seconds
* @param[in] ts time-stamp
* @param[out] pico pico-seconds
*/
void
wrtd_ts_to_pico
(
struct
wr_timestamp
*
ts
,
uint64_t
*
pico
)
{
uint64_t
p
;
p
=
ts
->
frac
*
8000
/
4096
;
p
+=
(
uint64_t
)
ts
->
ticks
*
8000LL
;
p
+=
ts
->
seconds
*
(
1000ULL
*
1000ULL
*
1000ULL
*
1000ULL
);
*
pico
=
p
;
}
/**
* It converts a pico seconds integer into a white rabbit time stamp
* @param[in] pico pico-seconds
* @param[out] ts time-stamp
*/
void
wrtd_pico_to_ts
(
uint64_t
*
pico
,
struct
wr_timestamp
*
ts
)
{
uint64_t
p
=
*
pico
;
ts
->
seconds
=
p
/
(
1000ULL
*
1000ULL
*
1000ULL
*
1000ULL
);
p
%=
(
1000ULL
*
1000ULL
*
1000ULL
*
1000ULL
);
ts
->
ticks
=
p
/
8000
;
p
%=
8000
;
ts
->
frac
=
p
*
4096
/
8000
;
}
/**
* It converts a white rabbit time stamp to seconds and pico-seconds
* @param[in] ts time-stamp
* @param[out] sec seconds
* @param[out] pico pico-seconds
*/
void
wrtd_ts_to_sec_pico
(
struct
wr_timestamp
*
ts
,
uint64_t
*
sec
,
uint64_t
*
pico
)
{
*
sec
=
ts
->
seconds
;
*
pico
=
ts
->
frac
*
8000
/
4096
;
*
pico
+=
(
uint64_t
)
ts
->
ticks
*
8000LL
;
}
/**
* It converts a white rabbit time stamp to seconds and pico-seconds
* @param[in] sec seconds
* @param[in] pico pico-seconds
* @param[out] ts time-stamp
*/
void
wrtd_sec_pico_to_ts
(
uint64_t
sec
,
uint64_t
pico
,
struct
wr_timestamp
*
ts
)
{
ts
->
seconds
=
sec
;
ts
->
ticks
=
pico
/
8000
;
ts
->
frac
=
(
pico
%
8000
)
*
4096
/
8000
;
}
/**
* Substract two timestamp. Returns -1 if the result would be negative.
* @param[in] l left operand
* @param[in] r right operand
* @param[out] res result
*/
int
wrtd_ts_sub
(
struct
wr_timestamp
*
res
,
struct
wr_timestamp
*
l
,
struct
wr_timestamp
*
r
)
{
int
carry
;
uint32_t
rticks
;
uint64_t
rsecs
;
carry
=
(
l
->
frac
<
r
->
frac
);
res
->
frac
=
(
carry
?
4096
:
0
)
+
l
->
frac
-
r
->
frac
;
rticks
=
r
->
ticks
+
(
carry
?
1
:
0
);
carry
=
l
->
ticks
<
rticks
;
res
->
ticks
=
(
carry
?
125000000
:
0
)
+
l
->
ticks
-
rticks
;
rsecs
=
r
->
seconds
+
(
carry
?
1
:
0
);
if
(
l
->
seconds
<
rsecs
)
return
-
1
;
res
->
seconds
=
l
->
seconds
-
rsecs
;
return
0
;
}
software/lib-old/libwrtd-input.c
deleted
100644 → 0
View file @
407f25d7
/*
* Copyright (C) 2014-2016 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
* inspired by a draft of Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <errno.h>
#include <libmockturtle.h>
#include "libwrtd-internal.h"
/**
* Internal helper to send and recevie synchronous messages to/from the TDC
*/
static
inline
int
wrtd_in_send_and_receive_sync
(
struct
wrtd_desc
*
wrtd
,
struct
trtl_msg
*
msg
)
{
int
err
;
/* Send the message and get answer */
err
=
trtl_msg_sync
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
msg
,
msg
,
WRTD_DEFAULT_TIMEOUT
);
return
err
<
0
?
err
:
0
;
/* Ignore timeout */
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * PROTOTYPEs IMPLEMENTATION * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* FIXME
* Most of the function's code below can be optimized by using memcpy()
* or similar operations. For the time being, I'm leaving it like this
* because data structures are shared with the real-time applications
*/
/**
* It retreives the current status of a given input channel
* @param[in] dev device token
* @param[in] input index (0-based) of the input channel
* @param[out] state the current status of a channel
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_in_state_get
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
struct
wrtd_input_state
*
state
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
int
err
;
struct
wrtd_in_channel
chan
;
struct
trtl_tlv
tlv
=
{
.
type
=
IN_STRUCT_CHAN_0
+
input
,
.
size
=
sizeof
(
struct
wrtd_in_channel
),
.
buf
=
&
chan
,
};
uint32_t
variables
[]
=
{
IN_VAR_DEVICE_SENT_PACK
,
0
,
IN_VAR_DEVICE_DEAD_TIME
,
0
};
if
(
input
>=
TDC_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
if
(
state
==
NULL
)
{
errno
=
ENOMEM
;
return
-
1
;
}
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
err
=
trtl_fw_variable_get
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
variables
,
2
);
if
(
err
)
return
err
;
/* Convert to state structure */
state
->
input
=
chan
.
n
;
state
->
assigned_id
=
chan
.
config
.
id
;
state
->
delay
=
chan
.
config
.
delay
;
state
->
tdc_timebase_offset
=
chan
.
config
.
timebase_offset
;
state
->
last_pulse
=
chan
.
stats
.
last_pulse
;
state
->
flags
=
chan
.
config
.
flags
;
state
->
log_level
=
chan
.
config
.
log_level
;
state
->
mode
=
chan
.
config
.
mode
;
state
->
total_pulses
=
chan
.
stats
.
total_pulses
;
state
->
sent_triggers
=
chan
.
stats
.
sent_pulses
;
state
->
last_sent
=
chan
.
stats
.
last_sent
;
state
->
miss_no_timing
=
chan
.
stats
.
miss_no_timing
;
state
->
dead_time
.
seconds
=
0
;
state
->
dead_time
.
frac
=
0
;
state
->
dead_time
.
ticks
=
variables
[
3
]
*
2
;
state
->
sent_packets
=
variables
[
1
];
return
0
;
}
/**
* Hardware enable/disable a WRTD input channel.
* @param[in] dev pointer to open node device.
* @param[in] input index (0-based) of the input channel
* @param[in] enable 1 to enable the input, 0 disables it.
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_in_enable
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
int
enable
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_in_channel
chan
;
struct
trtl_tlv
tlv
=
{
.
type
=
IN_STRUCT_CHAN_0
+
input
,
.
size
=
sizeof
(
struct
wrtd_in_channel
),
.
buf
=
&
chan
,
};
uint32_t
variables
[]
=
{
IN_VAR_DEVICE_CHAN_ENABLE
,
0
};
int
err
;
if
(
input
>=
TDC_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
err
=
trtl_fw_variable_get
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
variables
,
1
);
if
(
err
)
return
err
;
if
(
enable
)
{
variables
[
1
]
|=
(
1
<<
input
);
chan
.
config
.
flags
|=
WRTD_ENABLED
;
}
else
{
variables
[
1
]
&=
~
(
1
<<
input
);
chan
.
config
.
flags
&=
~
WRTD_ENABLED
;
}
err
=
trtl_fw_buffer_set
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
return
trtl_fw_variable_set
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
variables
,
1
);
}
/**
* Assign (unassign) a trigger ID to a given WRTD input. Passing a NULL trig_id
* un-assigns the current trigger (the input will be tagging pulses and
* logging them, but they will not be sent as triggers to the WR network).
* @param[in] dev device token
* @param[in] input index (0-based) of the input channel
* @param[in] trig_id the trigger to be sent upon reception of a pulse on the
* given input.
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_in_trigger_assign
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
struct
wrtd_trig_id
*
trig_id
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_in_channel
chan
;
struct
trtl_tlv
tlv
=
{
.
type
=
IN_STRUCT_CHAN_0
+
input
,
.
size
=
sizeof
(
struct
wrtd_in_channel
),
.
buf
=
&
chan
,
};
int
err
;
if
(
input
>=
TDC_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
if
(
trig_id
)
{
chan
.
config
.
id
=
*
trig_id
;
chan
.
config
.
flags
|=
WRTD_TRIGGER_ASSIGNED
;
chan
.
config
.
flags
&=
~
WRTD_LAST_VALID
;
}
else
{
memset
(
&
chan
.
config
.
id
,
0
,
sizeof
(
struct
wrtd_trig_id
));
chan
.
config
.
flags
&=
~
WRTD_TRIGGER_ASSIGNED
;
}
return
trtl_fw_buffer_set
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
&
tlv
,
1
);
}
/**
* It un-assign the trigger on an input channel. It is just an helper that
* internally use wrtd_in_trigger_unassign()
* @param[in] dev device token
* @param[in] input index (0-based) of the input channel
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_in_trigger_unassign
(
struct
wrtd_node
*
dev
,
unsigned
int
input
)
{
return
wrtd_in_trigger_assign
(
dev
,
input
,
NULL
);
}
/**
* Set trigger mode for a given WRTD input. Note that the input must be armed
* by calling wrtd_in_arm() at least once before it can send triggers.
*
* The mode can be single shot or continuous. Single shot means the input will
* trigger on the first incoming pulse and will ignore the subsequent pulses
* until re-armed.
*
* @param[in] dev device token
* @param[in] input (0-based) of the input channel
* @param[in] mode triggering mode.
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_in_trigger_mode_set
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
enum
wrtd_trigger_mode
mode
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_in_channel
chan
;
struct
trtl_tlv
tlv
=
{
.
type
=
IN_STRUCT_CHAN_0
+
input
,
.
size
=
sizeof
(
struct
wrtd_in_channel
),
.
buf
=
&
chan
,
};
int
err
;
if
(
input
>=
TDC_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
chan
.
config
.
mode
=
mode
;
return
trtl_fw_buffer_set
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
&
tlv
,
1
);
}
/**
* It generates a software trigger at a given TAI value. The TAI value that
* you provide to this function (trigger->ts) is considered as a delay
* from the current time. The current time means the time when the real-time
* application receive the software trigger command
* @param[in] dev device token
* @param[in] trigger trigger to enumlate
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_in_trigger_software
(
struct
wrtd_node
*
dev
,
struct
wrtd_trigger_entry
*
trigger
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
trtl_msg
msg
;
if
(
trigger
==
NULL
)
{
errno
=
EWRTD_INVALID_TRIG_ID
;
return
-
1
;
}
memset
(
&
msg
,
0
,
sizeof
(
struct
trtl_msg
));
msg
.
hdr
.
msg_id
=
WRTD_IN_ACTION_SW_TRIG
;
msg
.
hdr
.
flags
=
TRTL_HMQ_HEADER_FLAG_RPC
;
msg
.
hdr
.
len
=
sizeof
(
struct
wrtd_trigger_entry
)
/
4
;
memcpy
(
msg
.
data
,
trigger
,
sizeof
(
struct
wrtd_trigger_entry
));
/* Send the message and get answer */
return
wrtd_in_send_and_receive_sync
(
wrtd
,
&
msg
);
}
/**
* Arm (disarm) a WRTD input for triggering. By arming the input, you are making
* it ready to accept/send triggers
* @param[in] dev device token
* @param[in] input index (0-based) of input channel
* @param[in] armed 1 arms the input, 0 disarms the input.
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_in_arm
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
int
armed
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_in_channel
chan
;
struct
trtl_tlv
tlv
=
{
.
type
=
IN_STRUCT_CHAN_0
+
input
,
.
size
=
sizeof
(
struct
wrtd_in_channel
),
.
buf
=
&
chan
,
};
int
err
;
if
(
input
>=
TDC_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
if
(
armed
)
chan
.
config
.
flags
|=
WRTD_ARMED
;
else
chan
.
config
.
flags
&=
~
WRTD_ARMED
;
chan
.
config
.
flags
&=
~
WRTD_TRIGGERED
;
return
trtl_fw_buffer_set
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
&
tlv
,
1
);
}
/**
* Set the dead time (the minimum gap between input pulses, below which
* the TDC ignores the subsequent pulses; limits maximum input pulse rate,
* 16 ns granularity)
* @param[in] dev device token
* @param[in] input index (0-based) of input channel
* @param[in] dead_time_ps dead time in pico-seconds [80000000, 160000000000]
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_in_dead_time_set
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
uint64_t
dead_time_ps
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
uint32_t
variables
[]
=
{
IN_VAR_DEVICE_DEAD_TIME
,
0
};
uint32_t
dead_time_cycles
;
if
(
input
>=
TDC_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
/* Convert dead-times in cycles/ticks */
dead_time_cycles
=
dead_time_ps
/
16000
;
if
(
dead_time_cycles
<
5000
||
dead_time_cycles
>
10000000
)
{
errno
=
EWRTD_INVALID_DEAD_TIME
;
return
-
1
;
}
variables
[
1
]
=
dead_time_cycles
;
// FIXME wrong API
return
trtl_fw_variable_set
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
variables
,
1
);
}
/**
* Set the offset (for compensating cable delays), in 10 ps steps.
* @param[in] dev device token
* @param[in] input index (0-based) of input channel
* @param[in] delay_ps delay in pico-seconds
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_in_delay_set
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
uint64_t
delay_ps
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_in_channel
chan
;
struct
trtl_tlv
tlv
=
{
.
type
=
IN_STRUCT_CHAN_0
+
input
,
.
size
=
sizeof
(
struct
wrtd_in_channel
),
.
buf
=
&
chan
,
};
struct
wr_timestamp
t
;
int
err
;
if
(
input
>=
TDC_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
wrtd_pico_to_ts
(
&
delay_ps
,
&
t
);
memcpy
(
&
chan
.
config
.
delay
,
&
t
,
sizeof
(
struct
wr_timestamp
));
return
trtl_fw_buffer_set
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
&
tlv
,
1
);
}
/**
* Set the time offset on a given input channel. The time offset is between
* the White-Rabbit timescale and the ACAM TDC timescale. This information
* is only known by the TDC driver which has access the calibration data
* on the TDC eeprom. So, it is necessary to inform the RealTime application
* about this offset as soon as the RealTime application start to run.
* @param[in] dev device token
* @param[in] input index (0-based) of input channel
* @param[in] offset time offset in pico seconds
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_in_timebase_offset_set
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
uint64_t
offset
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_in_channel
chan
;
struct
trtl_tlv
tlv
=
{
.
type
=
IN_STRUCT_CHAN_0
+
input
,
.
size
=
sizeof
(
struct
wrtd_in_channel
),
.
buf
=
&
chan
,
};
struct
wr_timestamp
t
;
int
err
;
if
(
input
>=
TDC_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
wrtd_pico_to_ts
(
&
offset
,
&
t
);
memcpy
(
&
chan
.
config
.
timebase_offset
,
&
t
,
sizeof
(
struct
wr_timestamp
));
return
trtl_fw_buffer_set
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
&
tlv
,
1
);
}
/**
* Reset all counters on a given input channel
* @param[in] dev device token
* @param[in] input index (0-based) of input channel
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_in_counters_reset
(
struct
wrtd_node
*
dev
,
unsigned
int
input
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_in_channel
chan
;
struct
trtl_tlv
tlv
=
{
.
type
=
IN_STRUCT_CHAN_0
+
input
,
.
size
=
sizeof
(
struct
wrtd_in_channel
),
.
buf
=
&
chan
,
};
int
err
;
if
(
input
>=
TDC_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
chan
.
stats
.
total_pulses
=
0
;
chan
.
stats
.
sent_pulses
=
0
;
chan
.
stats
.
miss_no_timing
=
0
;
chan
.
config
.
flags
&=
~
WRTD_LAST_VALID
;
return
trtl_fw_buffer_set
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
&
tlv
,
1
);
}
/**
* Reset global counters
* @param[in] dev device token
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_in_global_counters_reset
(
struct
wrtd_node
*
dev
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
uint32_t
variables
[]
=
{
IN_VAR_DEVICE_SENT_PACK
,
0
};
return
trtl_fw_variable_set
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
variables
,
1
);
}
/**
* Check the enable status on a trigger input.
* @param[in] dev device token
* @param[in] input index (0-based) of input channel
* @param[out] enable 1 if it is enabled, 0 otherwise
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_in_is_enabled
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
unsigned
int
*
enable
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_in_channel
chan
;
struct
trtl_tlv
tlv
=
{
.
type
=
IN_STRUCT_CHAN_0
+
input
,
.
size
=
sizeof
(
struct
wrtd_in_channel
),
.
buf
=
&
chan
,
};
int
err
;
if
(
input
>=
TDC_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
*
enable
=
!!
(
chan
.
config
.
flags
&
WRTD_ENABLED
);
return
0
;
}
/**
* Check the armed status on a trigger input.
* @param[in] dev device token
* @param[in] input index (0-based) of input channel
* @param[out] armed 1 if it is enabled, 0 otherwise
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_in_is_armed
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
unsigned
int
*
armed
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_in_channel
chan
;
struct
trtl_tlv
tlv
=
{
.
type
=
IN_STRUCT_CHAN_0
+
input
,
.
size
=
sizeof
(
struct
wrtd_in_channel
),
.
buf
=
&
chan
,
};
int
err
;
if
(
input
>=
TDC_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
*
armed
=
!!
(
chan
.
config
.
flags
&
WRTD_ARMED
);
return
0
;
}
/**
* Check the trigger assigned status on a trigger input.
* @param[in] dev device token
* @param[in] input index (0-based) of input channel
* @param[out] armed 1 if it is enabled, 0 otherwise
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_in_has_trigger
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
unsigned
int
*
assigned
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_in_channel
chan
;
struct
trtl_tlv
tlv
=
{
.
type
=
IN_STRUCT_CHAN_0
+
input
,
.
size
=
sizeof
(
struct
wrtd_in_channel
),
.
buf
=
&
chan
,
};
int
err
;
if
(
input
>=
TDC_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
*
assigned
=
!!
(
chan
.
config
.
flags
&
WRTD_TRIGGER_ASSIGNED
);
return
0
;
}
/**
* Get the dead time (the minimum gap between input pulses, below which
* the TDC ignores the subsequent pulses; limits maximum input pulse rate,
* 16 ns granularity)
* @param[in] dev device token
* @param[in] input index (0-based) of input channel
* @param[out] dead_time_ps dead time in pico-seconds
* @return 0 on success, -1 on error and errno is set appropriately
*
* @todo to be implemented
*/
int
wrtd_in_dead_time_get
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
uint64_t
*
dead_time_ps
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
uint32_t
variables
[]
=
{
IN_VAR_DEVICE_DEAD_TIME
,
0
};
int
err
;
if
(
input
>=
TDC_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
err
=
trtl_fw_variable_get
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
variables
,
1
);
if
(
err
)
return
err
;
*
dead_time_ps
=
variables
[
1
]
*
16000
;
return
0
;
}
/**
* Get the offset (for compensating cable delays), in 10 ps steps.
* @param[in] dev device token
* @param[in] input index (0-based) of input channel
* @param[out] delay_ps delay in pico-seconds
* @return 0 on success, -1 on error and errno is set appropriately
*
* @todo to be implemented
*/
int
wrtd_in_delay_get
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
uint64_t
*
delay_ps
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_in_channel
chan
;
struct
trtl_tlv
tlv
=
{
.
type
=
IN_STRUCT_CHAN_0
+
input
,
.
size
=
sizeof
(
struct
wrtd_in_channel
),
.
buf
=
&
chan
,
};
int
err
;
if
(
input
>=
TDC_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
wrtd_ts_to_pico
(
&
chan
.
config
.
delay
,
delay_ps
);
return
0
;
}
/**
* Get/set the Sequence ID counter (counting up at every pulse)
* @param[in] dev device token
* @param[in] input index (0-based) of input channel
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_in_seq_counter_set
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
unsigned
int
value
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_in_channel
chan
;
struct
trtl_tlv
tlv
=
{
.
type
=
IN_STRUCT_CHAN_0
+
input
,
.
size
=
sizeof
(
struct
wrtd_in_channel
),
.
buf
=
&
chan
,
};
int
err
;
if
(
input
>=
TDC_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
chan
.
stats
.
seq
=
value
;
return
trtl_fw_buffer_set
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
&
tlv
,
1
);
}
/**
* It check if the input real-time application is alive
* @param[in] dev device token
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_in_ping
(
struct
wrtd_node
*
dev
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
return
trtl_fw_ping
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
);
}
/**
* It gets the input base time
* @param[in] dev device token
* @param[out] ts input device base time
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_in_base_time
(
struct
wrtd_node
*
dev
,
struct
wr_timestamp
*
ts
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
uint32_t
variables
[]
=
{
IN_VAR_DEVICE_TIME_S
,
0
,
IN_VAR_DEVICE_TIME_T
,
0
};
int
err
;
err
=
trtl_fw_variable_get
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
variables
,
2
);
if
(
err
)
return
err
;
ts
->
seconds
=
variables
[
1
];
ts
->
ticks
=
variables
[
3
];
return
0
;
}
/**
* It gets the output version
* @param[in] dev device token
* @param[out] version the RT application version
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_in_version
(
struct
wrtd_node
*
dev
,
struct
trtl_fw_version
*
version
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
return
trtl_fw_version
(
wrtd
->
trtl
,
WRTD_CPU_TDC
,
0
,
version
);
}
/**
* It tells if the input firmware is valid
* @param[in] dev device token
* @param[out] version the RT application version
* @return 1 when valid, 0 if invalid or error (and errno is set appropriately)
*/
int
wrtd_in_is_valid
(
struct
wrtd_node
*
dev
)
{
struct
trtl_fw_version
version
;
int
err
;
err
=
wrtd_in_version
(
dev
,
&
version
);
if
(
err
)
return
0
;
if
(
version
.
rt_id
!=
WRTD_IN_RT_ID
)
{
errno
=
EWRTD_INVALID_IN_APP
;
return
0
;
}
return
1
;
}
software/lib-old/libwrtd-internal.c
deleted
100644 → 0
View file @
407f25d7
/*
* Copyright (C) 2014-2016 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
* inspired by a draft of Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <libmockturtle.h>
#include "libwrtd-internal.h"
/**
* It validates the answer of a synchronous message
* @param[in] msg message to validate
* @return 0 if it is valid, -1 otherwise and errno is appropriately set
*/
int
wrtd_validate_acknowledge
(
struct
trtl_msg
*
msg
)
{
if
(
msg
->
hdr
.
len
!=
2
||
msg
->
data
[
0
]
!=
WRTD_REP_ACK_ID
)
{
errno
=
EWRTD_INVALID_ANSWER_ACK
;
return
-
1
;
}
return
0
;
}
/**
* It extracts a wr_timestamp from a given buffer (arriving from a real-time
* application)
* @param[in] buf answer of the real time application
* @param[in] offset offset of the timestamp inside the answer buffer
* @param[out] ts where write the wr_timestamp
*/
void
unbag_ts
(
uint32_t
*
buf
,
int
offset
,
struct
wr_timestamp
*
ts
)
{
ts
->
seconds
=
buf
[
offset
];
ts
->
ticks
=
buf
[
offset
+
1
];
ts
->
frac
=
buf
[
offset
+
2
];
}
/**
* It compares two triggers id. The output is the same of memcmp(2)
* @param[in] id1 first id to compare
* @param[in] id2 second id to compare
* @return like memcmp(2)
*/
int
wrtd_trig_id_cmp
(
struct
wrtd_trig_id
*
id1
,
struct
wrtd_trig_id
*
id2
)
{
return
memcmp
(
id1
,
id2
,
sizeof
(
struct
wrtd_trig_id
));
}
/*
* Internal helper to send and receive synchronous messages to/from the WRNC
*/
int
wrtd_send_and_receive_sync
(
struct
wrtd_desc
*
wrtd
,
struct
trtl_msg
*
msg
,
int
cpu
)
{
int
err
;
err
=
trtl_msg_sync
(
wrtd
->
trtl
,
cpu
,
0
,
msg
,
msg
,
WRTD_DEFAULT_TIMEOUT
);
return
err
<
0
?
err
:
0
;
/* ignore timeout */
}
/**
* It performs a simple request to a given core which will only answer
* with an ACK
*/
int
wrtd_trivial_request
(
struct
wrtd_node
*
dev
,
struct
trtl_msg
*
request_msg
,
int
cpu
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
int
err
;
err
=
wrtd_send_and_receive_sync
(
wrtd
,
request_msg
,
cpu
);
if
(
err
)
return
err
;
return
wrtd_validate_acknowledge
(
request_msg
);
}
software/lib-old/libwrtd-internal.h
deleted
100644 → 0
View file @
407f25d7
/*
* Copyright (C) 2014 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
* License: GPL v3
*/
#ifndef __LIBWRTD_INTERNAL__H__
#define __LIBWRTD_INTERNAL__H__
#include <stdlib.h>
#include <errno.h>
#include <libwrtd.h>
/* FIXME
* Statically defined but we must find a dynamic way to determinate
* these offsets
*/
#define WRTD_TDC_DEV_ID_OFFSET 0
#define WRTD_FD_DEV_ID_OFFSET 1
/**
* Description of a White-Rabbit Trigger-Distribution device
*/
struct
wrtd_desc
{
struct
trtl_dev
*
trtl
;
/**< WRNC device associated */
uint32_t
dev_id
;
/**< fmc device id */
uint32_t
app_id
;
/**< Application id */
uint32_t
n_cpu
;
/**< Number of CPUs */
};
#define WRTD_OUT_CHANNEL_PUBLIC_SIZE (sizeof(struct wrtd_out_channel) \
- sizeof(struct wrtd_out_channel_private))
/**
* @file libwrtd-interal.c
*/
void
unbag_ts
(
uint32_t
*
buf
,
int
offset
,
struct
wr_timestamp
*
ts
);
int
wrtd_validate_acknowledge
(
struct
trtl_msg
*
msg
);
int
wrtd_trig_id_cmp
(
struct
wrtd_trig_id
*
id1
,
struct
wrtd_trig_id
*
id2
);
extern
int
wrtd_trivial_request
(
struct
wrtd_node
*
dev
,
struct
trtl_msg
*
request_msg
,
int
cpu
);
extern
int
wrtd_send_and_receive_sync
(
struct
wrtd_desc
*
wrtd
,
struct
trtl_msg
*
msg
,
int
cpu
);
#endif
software/lib-old/libwrtd-logging.c
deleted
100644 → 0
View file @
407f25d7
/*
* Copyright (C) 2015-2016 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <poll.h>
#include <libmockturtle.h>
#include <libwrtd-internal.h>
/**
* It returns a human readable string that describe a given log level
* @param[in] lvl log level
* @return a string if the log level is mapped, otherwise an empty string
*/
const
char
*
wrtd_strlogging
(
enum
wrtd_log_level
lvl
)
{
switch
(
lvl
&
WRTD_LOG_LEVEL_MASK
)
{
case
WRTD_LOG_NOTHING
:
return
"off"
;
case
WRTD_LOG_RAW
:
return
"raw"
;
case
WRTD_LOG_SENT
:
return
"sent"
;
case
WRTD_LOG_PROMISC
:
return
"promiscuous"
;
case
WRTD_LOG_FILTERED
:
return
"filtered"
;
case
WRTD_LOG_EXECUTED
:
return
"executed"
;
case
WRTD_LOG_MISSED
:
return
"missed"
;
case
WRTD_LOG_ALL
:
return
"all"
;
}
return
"n/a"
;
}
/**
* It returns the full string describing the log_level in use
* @param[out] buf where write the string
* @param[in] log_level the log level to describe
*/
void
wrtd_strlogging_full
(
char
*
buf
,
uint32_t
log_level
)
{
enum
wrtd_log_level
lvl
;
if
(
!
log_level
)
{
/* No log level */
strcpy
(
buf
,
wrtd_strlogging
(
log_level
));
return
;
}
strcpy
(
buf
,
""
);
for
(
lvl
=
0x1
;
lvl
<=
WRTD_LOG_MISSED
;
lvl
<<=
1
)
{
if
(
lvl
&
log_level
)
{
strcat
(
buf
,
wrtd_strlogging
(
lvl
));
strcat
(
buf
,
" "
);
}
}
}
/**
* It converts a given logging string into a log_level
* @param[in] log string log level
* @return the correspondent log level enum
*/
enum
wrtd_log_level
wrtd_strlogging_to_level
(
char
*
log
)
{
if
(
!
strcmp
(
log
,
"all"
))
return
WRTD_LOG_ALL
;
if
(
!
strcmp
(
log
,
"promiscuous"
))
return
WRTD_LOG_PROMISC
;
if
(
!
strcmp
(
log
,
"raw"
))
return
WRTD_LOG_RAW
;
if
(
!
strcmp
(
log
,
"executed"
))
return
WRTD_LOG_EXECUTED
;
if
(
!
strcmp
(
log
,
"missed"
))
return
WRTD_LOG_MISSED
;
if
(
!
strcmp
(
log
,
"sent"
))
return
WRTD_LOG_SENT
;
if
(
!
strcmp
(
log
,
"filtered"
))
return
WRTD_LOG_FILTERED
;
return
WRTD_LOG_NOTHING
;
}
/**
* It reads one or more log entry from a given hmq_log. The user of this
* function must check that the hmq_log used correspond to a logging interface
* @param[in] hmq_log logging HMQ.
* @param[out] log log message
* @param[in] count number of messages to read
* @param[in] poll_timeout poll(2) timeout argument. Negative means infinite.
* @return number of read messages on success (check errno if it returns less
* messages than expected), -1 on error and errno is set appropriately
*/
int
wrtd_log_read
(
struct
wrtd_node
*
dev
,
struct
wrtd_log_entry
*
log
,
int
count
,
int
poll_timeout
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_log_entry
*
cur
=
log
;
struct
trtl_msg
msg
;
#define __WRTD_POLL_N 2
struct
polltrtl
p
[
__WRTD_POLL_N
];
int
remaining
=
count
;
int
n_read
=
0
,
ret
,
i
;
for
(
i
=
0
;
i
<
__WRTD_POLL_N
;
++
i
)
{
p
[
i
].
trtl
=
wrtd
->
trtl
;
p
[
i
].
idx_hmq
=
0
;
p
[
i
].
events
=
POLLIN
;
}
p
[
0
].
idx_cpu
=
WRTD_CPU_TDC
;
p
[
1
].
idx_cpu
=
WRTD_CPU_FD
;
/* Clean up errno to be able to distinguish between error cases and
normal behaviour when the function return less messages
than expected */
errno
=
0
;
while
(
remaining
>
0
)
{
ret
=
trtl_msg_poll
(
p
,
2
,
poll_timeout
);
if
(
ret
<=
0
)
break
;
for
(
i
=
0
;
i
<
__WRTD_POLL_N
;
++
i
)
{
if
(
!
(
p
[
i
].
revents
&
POLLIN
))
continue
;
ret
=
trtl_msg_async_recv
(
p
[
i
].
trtl
,
p
[
i
].
idx_cpu
,
p
[
i
].
idx_hmq
,
&
msg
,
1
);
if
(
ret
<=
0
)
break
;
memcpy
(
cur
,
msg
.
data
,
sizeof
(
struct
wrtd_log_entry
));
cur
->
type
|=
(
p
[
i
].
idx_cpu
<<
WRTD_LOG_CPU_SHIFT
);
remaining
--
;
n_read
++
;
cur
++
;
}
}
#undef __WRTD_POLL_N
return
(
n_read
>
0
||
errno
==
0
?
n_read
:
-
1
);
}
/**
* @param[in] dev device token
* @param[in] channel 0-based channel index
* @param[in] log_level log level to apply to the logging messages
* @return 0 on success, -1 on error and errno is set appropriately
*/
static
int
wrtd_log_level_set
(
struct
wrtd_node
*
dev
,
unsigned
int
channel
,
uint32_t
log_level
,
int
core
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
trtl_tlv
tlv
;
struct
wrtd_out_channel
ochan
;
struct
wrtd_in_channel
ichan
;
int
err
;
switch
(
core
)
{
case
WRTD_CPU_FD
:
if
(
channel
>=
FD_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
tlv
.
type
=
OUT_STRUCT_CHAN_0
+
channel
;
tlv
.
size
=
WRTD_OUT_CHANNEL_PUBLIC_SIZE
;
tlv
.
buf
=
&
ochan
;
break
;
case
WRTD_CPU_TDC
:
if
(
channel
>=
TDC_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
tlv
.
type
=
IN_STRUCT_CHAN_0
+
channel
;
tlv
.
size
=
sizeof
(
struct
wrtd_in_channel
);
tlv
.
buf
=
&
ichan
;
break
;
default:
abort
();
}
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
core
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
switch
(
core
)
{
case
WRTD_CPU_FD
:
ochan
.
config
.
log_level
=
log_level
;
break
;
case
WRTD_CPU_TDC
:
ichan
.
config
.
log_level
=
log_level
;
break
;
default:
abort
();
}
return
trtl_fw_buffer_set
(
wrtd
->
trtl
,
core
,
0
,
&
tlv
,
1
);
}
/**
* It sets the logging level for an output channel
* @param[in] dev device token
* @param[in] output index (0-based) of output channel
* @param[in] log_level log level to apply to the logging messages
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_out_log_level_set
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
uint32_t
log_level
)
{
return
wrtd_log_level_set
(
dev
,
output
,
log_level
,
WRTD_CPU_FD
);
}
/**
* It gets the logging level for an output channel
* @param[in] dev device token
* @param[in] output index (0-based) of output channel
* @param[out] log_level current log level used by the Real-Time application
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_out_log_level_get
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
uint32_t
*
log_level
)
{
struct
wrtd_output_state
state
;
int
err
;
err
=
wrtd_out_state_get
(
dev
,
input
,
&
state
);
if
(
err
)
return
err
;
*
log_level
=
state
.
log_level
;
return
0
;
}
/**
* It sets the logging level for an input channel
* @param[in] dev device token
* @param[in] input index (0-based) of input channel
* @param[in] log_level log level to apply to the logging messages
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_in_log_level_set
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
uint32_t
log_level
)
{
return
wrtd_log_level_set
(
dev
,
input
,
log_level
,
WRTD_CPU_TDC
);
}
/**
* It gets the logging level for an input channel
* @param[in] dev device token
* @param[in] input index (0-based) of input channel
* @param[out] log_level current log level used by the Real-Time application
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_in_log_level_get
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
uint32_t
*
log_level
)
{
struct
wrtd_input_state
state
;
int
err
;
err
=
wrtd_in_state_get
(
dev
,
input
,
&
state
);
if
(
err
)
return
err
;
*
log_level
=
state
.
log_level
;
return
0
;
}
software/lib-old/libwrtd-output.c
deleted
100644 → 0
View file @
407f25d7
/*
* Copyright (C) 2014-2016 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
* inspired by a draft of Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <libmockturtle.h>
#include <libwrtd-internal.h>
/*
* Internal helper to send and receive synchronous messages to/from the WRNC
*/
static
inline
int
wrtd_out_send_and_receive_sync
(
struct
wrtd_desc
*
wrtd
,
struct
trtl_msg
*
msg
)
{
int
err
;
/* Send the message and get answer */
err
=
trtl_msg_sync
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
msg
,
msg
,
WRTD_DEFAULT_TIMEOUT
);
return
err
<
0
?
err
:
0
;
/* Ignore timeout */
}
/**
* It retrieves the trigger index where you can write.
* If the trigger with ID 'tid' already exists it returns its index,
* otherwise it return the first free index.
*/
static
int
wrtd_out_trigger_index_get
(
struct
wrtd_desc
*
wrtd
,
struct
wrtd_trig_id
*
tid
)
{
struct
trtl_msg
msg
;
int
err
;
memset
(
&
msg
.
hdr
,
0
,
sizeof
(
struct
trtl_hmq_header
));
msg
.
hdr
.
flags
=
TRTL_HMQ_HEADER_FLAG_RPC
;
msg
.
hdr
.
msg_id
=
WRTD_OUT_ACTION_TRIG_IDX
;
msg
.
hdr
.
len
=
sizeof
(
struct
wrtd_trig_id
)
/
4
;
memcpy
(
msg
.
data
,
tid
,
sizeof
(
struct
wrtd_trig_id
));
err
=
wrtd_out_send_and_receive_sync
(
wrtd
,
&
msg
);
if
(
err
)
return
-
1
;
if
(
msg
.
hdr
.
msg_id
!=
WRTD_OUT_ACTION_TRIG_IDX
&&
msg
.
hdr
.
msg_id
!=
WRTD_OUT_ACTION_TRIG_FRE
)
{
errno
=
ETRTL_INVALID_MESSAGE
;
return
-
1
;
}
/* return the trigger index */
return
msg
.
data
[
0
];
}
int
wrtd_out_trigger_sw_now
(
struct
wrtd_node
*
dev
,
unsigned
int
output
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
trtl_msg
msg
;
struct
wrtd_out_trigger_sw
d
;
int
err
;
memset
(
&
msg
.
hdr
,
0
,
sizeof
(
struct
trtl_hmq_header
));
msg
.
hdr
.
flags
=
TRTL_HMQ_HEADER_FLAG_RPC
;
msg
.
hdr
.
msg_id
=
WRTD_OUT_ACTION_SW_TRIG
;
msg
.
hdr
.
len
=
sizeof
(
struct
wrtd_out_trigger_sw
)
/
4
;
d
.
chan
=
output
;
d
.
now
=
1
;
memset
(
&
d
.
tstamp
,
0
,
sizeof
(
d
.
tstamp
));
memcpy
(
msg
.
data
,
&
d
,
sizeof
(
d
));
err
=
wrtd_out_send_and_receive_sync
(
wrtd
,
&
msg
);
if
(
err
)
return
-
1
;
if
(
msg
.
hdr
.
msg_id
!=
WRTD_OUT_ACTION_SW_TRIG
)
{
errno
=
ETRTL_INVALID_MESSAGE
;
return
-
1
;
}
return
0
;
}
static
int
wrtd_out_action_one_word
(
struct
wrtd_desc
*
wrtd
,
uint8_t
msgid
,
uint32_t
word
)
{
struct
trtl_msg
msg
;
memset
(
&
msg
.
hdr
,
0
,
sizeof
(
struct
trtl_hmq_header
));
msg
.
hdr
.
flags
=
TRTL_HMQ_HEADER_FLAG_RPC
;
msg
.
hdr
.
msg_id
=
msgid
;
msg
.
hdr
.
len
=
1
;
msg
.
data
[
0
]
=
word
;
return
wrtd_out_send_and_receive_sync
(
wrtd
,
&
msg
);
}
static
inline
int
wrtd_out_trigger_insert
(
struct
wrtd_desc
*
wrtd
,
uint32_t
tid
)
{
return
wrtd_out_action_one_word
(
wrtd
,
WRTD_OUT_ACTION_TRIG_ADD
,
tid
);
}
static
inline
int
wrtd_out_trigger_remove
(
struct
wrtd_desc
*
wrtd
,
uint32_t
tid
)
{
return
wrtd_out_action_one_word
(
wrtd
,
WRTD_OUT_ACTION_TRIG_DEL
,
tid
);
}
static
inline
int
wrtd_out_rt_disable
(
struct
wrtd_desc
*
wrtd
,
unsigned
int
output
)
{
return
wrtd_out_action_one_word
(
wrtd
,
WRTD_OUT_ACTION_DISABLE
,
output
);
}
static
struct
trtl_tlv
wrtd_trigger_tlv
(
uint32_t
index
,
struct
wrtd_out_trigger
*
trig
)
{
struct
trtl_tlv
tlv
=
{
.
type
=
__WRTD_OUT_STRUCT_MAX
+
index
,
.
size
=
sizeof
(
struct
wrtd_out_trigger
),
.
buf
=
trig
,
};
return
tlv
;
}
static
struct
trtl_tlv
wrtd_channel_tlv
(
uint32_t
index
,
struct
wrtd_out_channel
*
chan
)
{
struct
trtl_tlv
tlv
=
{
.
type
=
OUT_STRUCT_CHAN_0
+
index
,
.
size
=
WRTD_OUT_CHANNEL_PUBLIC_SIZE
,
.
buf
=
chan
,
};
return
tlv
;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * PROTOTYPEs IMPLEMENTATION * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* It retreives the current output status of a given channel
* @param[in] dev device token
* @param[in] output index (0-based) of output channel
* @param[out] state channel status
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_out_state_get
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
struct
wrtd_output_state
*
state
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_out
out
;
struct
wrtd_out_channel
chan
;
struct
trtl_tlv
tlv
=
wrtd_channel_tlv
(
output
,
&
chan
);
int
err
;
if
(
output
>=
FD_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
if
(
state
==
NULL
)
{
errno
=
ENOMEM
;
return
-
1
;
}
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
/* Copy to state structure */
state
->
output
=
chan
.
n
;
state
->
executed_pulses
=
chan
.
stats
.
hits
;
state
->
missed_pulses_late
=
chan
.
stats
.
miss_timeout
;
state
->
missed_pulses_deadtime
=
chan
.
stats
.
miss_deadtime
;
state
->
missed_pulses_overflow
=
chan
.
stats
.
miss_overflow
;
state
->
missed_pulses_no_timing
=
chan
.
stats
.
miss_no_timing
;
state
->
last_executed
=
chan
.
stats
.
last_executed
;
state
->
last_enqueued
=
chan
.
stats
.
last_enqueued
;
state
->
last_lost
=
chan
.
stats
.
last_lost
;
state
->
mode
=
chan
.
config
.
mode
;
state
->
flags
=
chan
.
config
.
flags
;
state
->
log_level
=
chan
.
config
.
log_level
;
state
->
pulse_width
.
seconds
=
0
;
state
->
pulse_width
.
frac
=
0
;
state
->
pulse_width
.
ticks
=
chan
.
config
.
width_cycles
;
state
->
dead_time
.
seconds
=
0
;
state
->
dead_time
.
frac
=
0
;
state
->
dead_time
.
ticks
=
chan
.
config
.
dead_time
;
tlv
.
type
=
OUT_STRUCT_DEVICE
;
tlv
.
size
=
sizeof
(
struct
wrtd_out
);
tlv
.
buf
=
&
out
;
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
state
->
received_messages
=
out
.
counter_etherbone
;
state
->
received_loopback
=
out
.
counter_loopback
;
state
->
last_received
=
out
.
last_received
;
return
0
;
}
/**
* It enables/disables a trigger output line
* @param[in] dev device token
* @param[in] output index (0-based) of output channel
* @param[in] enable 1 to enable the output, 0 disables it.
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_out_enable
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
int
enable
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_out_channel
chan
;
struct
trtl_tlv
tlv
=
wrtd_channel_tlv
(
output
,
&
chan
);
int
err
;
if
(
output
>=
FD_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
if
(
enable
)
{
chan
.
config
.
flags
|=
WRTD_ENABLED
;
}
else
{
chan
.
config
.
flags
&=
~
(
WRTD_ENABLED
|
WRTD_ARMED
|
WRTD_TRIGGERED
|
WRTD_LAST_VALID
);
chan
.
config
.
state
=
OUT_ST_IDLE
;
err
=
wrtd_out_rt_disable
(
wrtd
,
output
);
if
(
err
)
return
-
1
;
}
return
trtl_fw_buffer_set
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
}
static
int
wrtd_out_trig_assign_condition_by_index
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
uint32_t
trig_idx
,
uint32_t
cond_idx
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_out_trigger
trig
;
struct
trtl_tlv
tlv
;
int
err
;
if
(
output
>=
FD_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
tlv
=
wrtd_trigger_tlv
(
trig_idx
,
&
trig
);
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
if
(
!
(
trig
.
flags
&
ENTRY_FLAG_VALID
))
{
/* If the given trigger is not valid, then skip */
errno
=
EINVAL
;
return
-
1
;
}
trig
.
ocfg
[
output
].
state
&=
~
HASH_ENT_DIRECT
;
trig
.
ocfg
[
output
].
state
|=
HASH_ENT_CONDITIONAL
;
trig
.
ocfg
[
output
].
cond_ptr
=
cond_idx
;
err
=
trtl_fw_buffer_set
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
tlv
=
wrtd_trigger_tlv
(
cond_idx
,
&
trig
);
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
if
(
!
(
trig
.
flags
&
ENTRY_FLAG_VALID
))
{
/* If the given trigger is not valid, then skip */
errno
=
EINVAL
;
return
-
1
;
}
trig
.
ocfg
[
output
].
state
&=
~
HASH_ENT_DIRECT
;
trig
.
ocfg
[
output
].
state
|=
HASH_ENT_CONDITION
;
trig
.
ocfg
[
output
].
cond_ptr
=
-
1
;
return
trtl_fw_buffer_set
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
}
/**
* It sets the given bitmaks (it means that it does OR with the current value)
*/
static
int
wrtd_out_flag_set
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
uint32_t
flags
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_out_channel
chan
;
struct
trtl_tlv
tlv
=
wrtd_channel_tlv
(
output
,
&
chan
);
int
err
;
if
(
output
>=
FD_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
chan
.
config
.
flags
|=
flags
;
return
trtl_fw_buffer_set
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
}
/**
* It sets the given bitmaks (it means that it does AND NOT with the current
* value)
*/
static
int
wrtd_out_flag_clr
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
uint32_t
flags
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_out_channel
chan
;
struct
trtl_tlv
tlv
=
wrtd_channel_tlv
(
output
,
&
chan
);
int
err
;
if
(
output
>=
FD_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
chan
.
config
.
flags
&=
~
flags
;
return
trtl_fw_buffer_set
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
}
static
int
wrtd_out_trig_assign_one
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
struct
wrtd_trigger_handle
*
handle
,
struct
wrtd_trig_id
*
tid
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_out_trigger
trig
;
struct
trtl_tlv
tlv
;
int
err
,
ret
;
handle
->
channel
=
output
;
if
(
handle
->
channel
>=
FD_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
ret
=
wrtd_out_trigger_index_get
(
wrtd
,
tid
);
if
(
ret
<
0
)
return
ret
;
handle
->
ptr_trig
=
ret
;
tlv
=
wrtd_trigger_tlv
(
handle
->
ptr_trig
,
&
trig
);
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
trig
.
flags
|=
ENTRY_FLAG_VALID
;
trig
.
id
=
*
tid
;
memset
(
&
trig
.
ocfg
[
handle
->
channel
],
0
,
sizeof
(
struct
lrt_output_rule
));
trig
.
ocfg
[
handle
->
channel
].
delay_cycles
=
100000000
/
8000
;
trig
.
ocfg
[
handle
->
channel
].
state
=
HASH_ENT_DISABLED
;
trig
.
ocfg
[
handle
->
channel
].
state
|=
HASH_ENT_DIRECT
;
trig
.
ocfg
[
handle
->
channel
].
cond_ptr
=
-
1
;
err
=
trtl_fw_buffer_set
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
err
=
wrtd_out_trigger_insert
(
wrtd
,
handle
->
ptr_trig
);
if
(
err
)
return
err
;
return
wrtd_out_flag_set
(
dev
,
handle
->
channel
,
WRTD_TRIGGER_ASSIGNED
);
}
/**
* It assign a trigger to an output channel
* @param[in] dev pointer to open node device.
* @param[in] output index (0-based) of output channel
* @param[out] handle
* @param[in] trig trigger id to assign
* @param[in] condition trigger id to assign to the condition
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_out_trig_assign
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
struct
wrtd_trigger_handle
*
handle
,
struct
wrtd_trig_id
*
tid
,
struct
wrtd_trig_id
*
condition
)
{
struct
wrtd_trigger_handle
tmp_handle
;
int
err
;
if
(
output
>=
FD_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
err
=
wrtd_out_trig_assign_one
(
dev
,
output
,
handle
,
tid
);
if
(
err
)
return
err
;
/* Return now for direct triggers. */
if
(
!
condition
)
return
0
;
/* Setup the condition trigger. */
err
=
wrtd_out_trig_assign_one
(
dev
,
output
,
&
tmp_handle
,
condition
);
if
(
err
)
return
err
;
handle
->
ptr_cond
=
tmp_handle
.
ptr_trig
;
return
wrtd_out_trig_assign_condition_by_index
(
dev
,
output
,
handle
->
ptr_trig
,
handle
->
ptr_cond
);
}
/**
* Un-assign a give trigger
* @param[in] dev pointer to open node device.
* @param[in] handle
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_out_trig_unassign
(
struct
wrtd_node
*
dev
,
struct
wrtd_trigger_handle
*
handle
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_output_trigger_state
triggers
[
256
];
struct
wrtd_out_trigger
trig
;
struct
trtl_tlv
tlv
=
wrtd_trigger_tlv
(
handle
->
ptr_trig
,
&
trig
);
struct
wrtd_output_trigger_state
state
;
int
err
,
cnt
=
0
,
i
;
volatile
int
cond
;
if
(
handle
->
channel
>=
FD_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
cond
=
trig
.
ocfg
[
handle
->
channel
].
cond_ptr
;
memset
(
&
trig
.
ocfg
[
handle
->
channel
],
0
,
sizeof
(
struct
lrt_output_rule
));
for
(
i
=
0
;
i
<
FD_NUM_CHANNELS
;
i
++
)
if
(
trig
.
ocfg
[
i
].
state
==
HASH_ENT_EMPTY
)
cnt
++
;
if
(
cnt
==
FD_NUM_CHANNELS
)
trig
.
flags
&=
~
ENTRY_FLAG_VALID
;
err
=
trtl_fw_buffer_set
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
err
=
wrtd_out_trigger_remove
(
wrtd
,
handle
->
ptr_trig
);
if
(
err
)
return
err
;
err
=
wrtd_out_trig_get_all
(
dev
,
handle
->
channel
,
triggers
,
256
);
if
(
err
<
0
)
return
-
1
;
if
(
err
==
0
){
err
=
wrtd_out_flag_clr
(
dev
,
handle
->
channel
,
WRTD_TRIGGER_ASSIGNED
);
}
else
{
err
=
0
;
}
if
(
cond
<
0
||
cond
>
FD_HASH_ENTRIES
)
return
err
;
/* Remove also its condition */
err
=
wrtd_out_trig_state_get_by_index
(
dev
,
cond
,
handle
->
channel
,
&
state
);
if
(
err
)
return
err
;
return
wrtd_out_trig_unassign
(
dev
,
&
state
.
handle
);
}
/**
* It retreive a given number of triggers from output device
* @param[in] dev device token
* @param[in] output index (0-based) of output channel
* @param[out] triggers list of assigned trigger
* @param[in] max_count maximum triggers to retreive
* @return number of triggers on success, -1 on error and
* errno is set appropriately
*/
int
wrtd_out_trig_get_all
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
struct
wrtd_output_trigger_state
*
triggers
,
int
max_count
)
{
struct
wrtd_output_trigger_state
tmp
;
int
err
=
0
,
i
,
count
=
0
;
if
(
output
>=
FD_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
for
(
i
=
0
;
count
<
max_count
&&
i
<
FD_HASH_ENTRIES
;
i
++
)
{
err
=
wrtd_out_trig_state_get_by_index
(
dev
,
i
,
output
,
&
tmp
);
if
(
err
)
{
if
(
errno
==
EWRTD_NOFOUND_TRIGGER
)
{
err
=
0
;
continue
;
}
else
{
break
;
}
}
else
{
memcpy
(
&
triggers
[
count
],
&
tmp
,
sizeof
(
struct
wrtd_output_trigger_state
));
count
++
;
}
}
/* Do not count trigger with error */
if
(
err
)
count
--
;
return
count
>
0
?
count
:
err
;
}
/**
* It returns a trigger state from a given handle.
* @param[in] dev pointer to open node device.
* @param[in] handle trigger where act on
* @param[out] trigger trigger status
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_out_trig_state_get_by_handle
(
struct
wrtd_node
*
dev
,
struct
wrtd_trigger_handle
*
handle
,
struct
wrtd_output_trigger_state
*
trigger
)
{
return
wrtd_out_trig_state_get_by_index
(
dev
,
handle
->
ptr_trig
,
handle
->
channel
,
trigger
);
}
/**
* It returns a trigget from a given identifier.
* Whenever is possible you should prefer wrtd_out_trig_state_get_by_handle()
* @param[in] dev device token
* @param[in] output index (0-based) of output channel
* @param[in] id identifier of the trigger to retrieve
* @param[out] trigger trigger status
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_out_trig_state_get_by_id
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
struct
wrtd_trig_id
*
tid
,
struct
wrtd_output_trigger_state
*
trigger
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
int
index
;
index
=
wrtd_out_trigger_index_get
(
wrtd
,
tid
);
if
(
index
<
0
)
{
errno
=
EWRTD_NOFOUND_TRIGGER
;
return
-
1
;
}
return
wrtd_out_trig_state_get_by_index
(
dev
,
index
,
output
,
trigger
);
}
/**
* It returns a trigget from a given index. The index may change due to trigger
* assing and un-assing. So, before use this function you have to check the
* current trigger's indexes. Note that this is not thread safe.
* Whenever is possible you should prefer wrtd_out_trig_state_get_by_handle()
* @param[in] dev device token
* @param[in] output index (0-based) of output channel
* @param[out] trigger trigger status
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_out_trig_state_get_by_index
(
struct
wrtd_node
*
dev
,
unsigned
int
index
,
unsigned
int
output
,
struct
wrtd_output_trigger_state
*
trigger
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_out_trigger
trig
;
struct
trtl_tlv
tlv
=
wrtd_trigger_tlv
(
index
,
&
trig
);
struct
wrtd_output_trigger_state
cond
;
int
err
;
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
if
(
!
(
trig
.
flags
&
ENTRY_FLAG_VALID
)
||
(
trig
.
ocfg
[
output
].
state
==
HASH_ENT_EMPTY
))
{
errno
=
EWRTD_NOFOUND_TRIGGER
;
return
-
1
;
}
memset
(
trigger
,
0
,
sizeof
(
struct
wrtd_output_trigger_state
));
trigger
->
handle
.
channel
=
output
;
trigger
->
handle
.
ptr_trig
=
index
;
trigger
->
handle
.
ptr_cond
=
(
uint32_t
)
trig
.
ocfg
[
output
].
cond_ptr
;
trigger
->
is_conditional
=
(
0
<=
trigger
->
handle
.
ptr_cond
&&
trigger
->
handle
.
ptr_cond
<=
FD_HASH_ENTRIES
);
trigger
->
enabled
=
!
(
trig
.
ocfg
[
output
].
state
&
HASH_ENT_DISABLED
);
trigger
->
trigger
=
trig
.
id
;
trigger
->
delay_trig
.
ticks
=
trig
.
ocfg
[
output
].
delay_cycles
;
trigger
->
delay_trig
.
frac
=
trig
.
ocfg
[
output
].
delay_frac
;
if
(
trig
.
ocfg
[
output
].
latency_avg_nsamples
)
{
trigger
->
latency_average_us
=
(
trig
.
ocfg
[
output
].
latency_avg_sum
/
trig
.
ocfg
[
output
].
latency_avg_nsamples
+
124
)
/
125
;
}
else
{
trigger
->
latency_average_us
=
0
;
}
trigger
->
latency_worst_us
=
(
trig
.
ocfg
[
output
].
latency_worst
+
124
)
/
125
;
trigger
->
executed_pulses
=
trig
.
ocfg
[
output
].
hits
;
trigger
->
missed_pulses
=
trig
.
ocfg
[
output
].
misses
;
if
(
!
trigger
->
is_conditional
)
return
0
;
/* Get conditional trigger */
err
=
wrtd_out_trig_state_get_by_index
(
dev
,
trigger
->
handle
.
ptr_cond
,
output
,
&
cond
);
if
(
err
)
return
err
;
memcpy
(
&
trigger
->
condition
,
&
cond
.
trigger
,
sizeof
(
struct
wrtd_trig_id
));
memcpy
(
&
trigger
->
delay_cond
,
&
cond
.
delay_trig
,
sizeof
(
struct
wr_timestamp
));
return
0
;
}
static
int
wrtd_out_rule_delay_set
(
struct
wrtd_node
*
dev
,
int
output
,
uint32_t
trig_idx
,
uint64_t
delay_ps
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_out_trigger
trig
;
struct
trtl_tlv
tlv
=
wrtd_trigger_tlv
(
trig_idx
,
&
trig
);
struct
wr_timestamp
t
;
int
err
;
if
(
output
>=
FD_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
if
(
delay_ps
>
(
1000
*
1000
*
1000
*
1000ULL
-
1000ULL
))
{
errno
=
EWRTD_INVALID_DELAY
;
return
-
1
;
}
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
if
(
!
(
trig
.
flags
&
ENTRY_FLAG_VALID
))
{
errno
=
EWRTD_NOFOUND_TRIGGER
;
return
-
1
;
}
wrtd_pico_to_ts
(
&
delay_ps
,
&
t
);
trig
.
ocfg
[
output
].
delay_cycles
=
t
.
ticks
;
trig
.
ocfg
[
output
].
delay_frac
=
t
.
frac
;
return
trtl_fw_buffer_set
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
}
/**
* It sets the delay to apply for a given trigger
* @param[in] dev pointer to open node device.
* @param[in] handle trigger where act on
* @param[in] delay_ps delay in pico-seconds in range [0, 999999999000]
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_out_trig_delay_set
(
struct
wrtd_node
*
dev
,
struct
wrtd_trigger_handle
*
handle
,
uint64_t
delay_ps
)
{
return
wrtd_out_rule_delay_set
(
dev
,
handle
->
channel
,
handle
->
ptr_trig
,
delay_ps
);
}
/**
* Sets the pulse width for a given output channel.
* @param[in] dev device token
* @param[in] output index (0-based) of output channel
* @param[in] width_ps pulse width in pico-seconds (from 250ns to 1s)
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_out_pulse_width_set
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
uint64_t
width_ps
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_out_channel
chan
;
struct
trtl_tlv
tlv
=
wrtd_channel_tlv
(
output
,
&
chan
);
int
err
;
if
(
output
>=
FD_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
if
(
width_ps
<
1000ULL
*
250
||
width_ps
>=
1000ULL
*
1000
*
1000
*
1000
)
{
errno
=
EWRTD_INVALID_PULSE_WIDTH
;
return
-
1
;
}
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
chan
.
config
.
width_cycles
=
width_ps
/
8000ULL
;
return
trtl_fw_buffer_set
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
}
/**
* It set the dead time for a given output channel. so, it applies on all
* triggers assigned to the given output channel.
*
* The function will round the value, so it may happen that you read back a
* different value. The reason is that the RT application measure the dead
* time in ticks, which are 8ns steps. So this function will internally
* convert the dead time in ticks. The function accept pico-seconds only to
* be consistent with the API.
* @param[in] dev device token
* @param[in] output index (0-based) of output channel
* @param[in] dead_time_ps dead time in pico-seconds
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_out_dead_time_set
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
uint64_t
dead_time_ps
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_out_channel
chan
;
struct
trtl_tlv
tlv
=
wrtd_channel_tlv
(
output
,
&
chan
);
int
err
;
if
(
output
>=
FD_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
chan
.
config
.
dead_time
=
dead_time_ps
/
8000
;
return
trtl_fw_buffer_set
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
}
/**
* @param[in] dev pointer to open node device.
* @param[in] handle trigger where act on
* @param[in] delay_ps delay in pico-seconds in range [0, 999999999000]
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_out_trig_condition_delay_set
(
struct
wrtd_node
*
dev
,
struct
wrtd_trigger_handle
*
handle
,
uint64_t
delay_ps
)
{
if
(
handle
->
ptr_cond
==
0
)
{
errno
=
EWRTD_NO_TRIGGER_CONDITION
;
return
-
1
;
}
return
wrtd_out_rule_delay_set
(
dev
,
handle
->
channel
,
handle
->
ptr_cond
,
delay_ps
);
}
/**
* @param[in] dev pointer to open node device.
* @param[in] handle trigger where act on
* @param[in] enable 1 to enable, 0 to disable
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_out_trig_enable
(
struct
wrtd_node
*
dev
,
struct
wrtd_trigger_handle
*
handle
,
int
enable
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_out_trigger
trig
;
struct
trtl_tlv
tlv
=
wrtd_trigger_tlv
(
handle
->
ptr_trig
,
&
trig
);
int
err
;
if
(
handle
->
channel
>=
FD_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
if
(
!
(
trig
.
flags
&
ENTRY_FLAG_VALID
))
{
errno
=
EWRTD_NOFOUND_TRIGGER
;
return
-
1
;
}
if
(
enable
)
trig
.
ocfg
[
handle
->
channel
].
state
&=
~
HASH_ENT_DISABLED
;
else
trig
.
ocfg
[
handle
->
channel
].
state
|=
HASH_ENT_DISABLED
;
return
trtl_fw_buffer_set
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
}
/**
* It sets the trigger mode of a given output channel
* @param[in] dev device token
* @param[in] output index (0-based) of output channel
* @param[in] mode output mode
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_out_trigger_mode_set
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
enum
wrtd_trigger_mode
mode
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_out_channel
chan
;
struct
trtl_tlv
tlv
=
wrtd_channel_tlv
(
output
,
&
chan
);
int
err
;
if
(
output
>=
FD_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
chan
.
config
.
mode
=
mode
;
chan
.
config
.
flags
&=
~
(
WRTD_TRIGGERED
|
WRTD_LAST_VALID
);
if
(
chan
.
config
.
mode
==
WRTD_TRIGGER_MODE_SINGLE
)
{
chan
.
config
.
flags
&=
~
WRTD_ARMED
;
chan
.
config
.
state
=
OUT_ST_IDLE
;
}
return
trtl_fw_buffer_set
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
}
/**
* It arms (un-arms) a given output channel
* @param[in] dev device token
* @param[in] output index (0-based) of output channel
* @param[in] armed 1 to arm, 0 to un-arm
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_out_arm
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
int
armed
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_out_channel
chan
;
struct
trtl_tlv
tlv
=
wrtd_channel_tlv
(
output
,
&
chan
);
int
err
;
if
(
output
>=
FD_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
chan
.
config
.
flags
&=
~
WRTD_TRIGGERED
;
if
(
armed
)
{
chan
.
config
.
flags
|=
WRTD_ARMED
;
chan
.
config
.
state
=
OUT_ST_ARMED
;
}
else
{
chan
.
config
.
flags
&=
~
WRTD_ARMED
;
chan
.
config
.
state
=
OUT_ST_IDLE
;
}
return
trtl_fw_buffer_set
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
}
/**
* @param[in] dev device token
* @param[in] output index (0-based) of output channel
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_out_counters_reset
(
struct
wrtd_node
*
dev
,
unsigned
int
output
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_out_channel
chan
;
struct
trtl_tlv
tlv
=
wrtd_channel_tlv
(
output
,
&
chan
);
int
err
;
if
(
output
>=
FD_NUM_CHANNELS
)
{
errno
=
EWRTD_INVALID_CHANNEL
;
return
-
1
;
}
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
chan
.
stats
.
hits
=
0
;
chan
.
stats
.
miss_timeout
=
0
;
chan
.
stats
.
miss_deadtime
=
0
;
chan
.
stats
.
miss_no_timing
=
0
;
chan
.
stats
.
miss_overflow
=
0
;
chan
.
config
.
flags
&=
~
WRTD_LAST_VALID
;
return
trtl_fw_buffer_set
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
}
/**
* Reset global counters
* @param[in] dev device token
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_out_global_counters_reset
(
struct
wrtd_node
*
dev
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
struct
wrtd_out
out
;
struct
trtl_tlv
tlv
;
int
err
;
tlv
.
type
=
OUT_STRUCT_DEVICE
;
tlv
.
size
=
sizeof
(
struct
wrtd_out
);
tlv
.
buf
=
&
out
;
err
=
trtl_fw_buffer_get
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
if
(
err
)
return
err
;
out
.
counter_etherbone
=
0
;
out
.
counter_loopback
=
0
;
return
trtl_fw_buffer_set
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
&
tlv
,
1
);
}
/**
* @param[in] dev device token
* @param[in] output index (0-based) of output channel
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_out_check_triggered
(
struct
wrtd_node
*
dev
,
unsigned
int
output
)
{
struct
wrtd_output_state
st
;
int
err
;
err
=
wrtd_out_state_get
(
dev
,
output
,
&
st
);
if
(
err
)
return
err
;
return
st
.
flags
&
WRTD_TRIGGERED
?
1
:
0
;
}
/**
* Check the enable status on a trigger output.
* @param[in] dev device token
* @param[in] output index (0-based) of output channel
* @param[out] enable 1 if it is enabled, 0 otherwise
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_out_is_enabled
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
unsigned
int
*
enable
)
{
struct
wrtd_output_state
state
;
int
err
;
err
=
wrtd_out_state_get
(
dev
,
output
,
&
state
);
if
(
err
)
return
-
1
;
*
enable
=
!!
(
state
.
flags
&
WRTD_ENABLED
);
return
0
;
}
/**
* Check the armed status on a trigger output.
* @param[in] dev device token
* @param[in] output index (0-based) of output channel
* @param[out] armed 1 if it is enabled, 0 otherwise
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_out_is_armed
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
unsigned
int
*
armed
)
{
struct
wrtd_output_state
state
;
int
err
;
err
=
wrtd_out_state_get
(
dev
,
output
,
&
state
);
if
(
err
)
return
-
1
;
*
armed
=
!!
(
state
.
flags
&
WRTD_ARMED
);
return
0
;
}
/**
* Check the trigger assigned status on a trigger output. If you provide
* a trigger identifier then the function checks that the given trigger
* is assigned to the given channel. Otherwise it will tell you if there
* is any trigger assigned to the channel.
* @param[in] dev device token
* @param[in] output index (0-based) of output channel
* @param[in] id trigger identifier (optional)
* @param[out] armed 1 if it is enabled, 0 otherwise
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_out_has_trigger
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
struct
wrtd_trig_id
*
id
,
unsigned
int
*
assigned
)
{
struct
wrtd_output_trigger_state
triggers
[
256
];
struct
wrtd_output_state
state
;
int
ret
,
i
;
/* Set default output */
*
assigned
=
0
;
ret
=
wrtd_out_state_get
(
dev
,
output
,
&
state
);
if
(
ret
)
return
-
1
;
if
(
!
id
)
{
/* Check only if there is at least one trigger */
*
assigned
=
!!
(
state
.
flags
&
WRTD_TRIGGER_ASSIGNED
);
return
0
;
}
/* Look for the id among all assigned trigger */
ret
=
wrtd_out_trig_get_all
(
dev
,
output
,
triggers
,
256
);
if
(
ret
<
0
)
return
-
1
;
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
if
(
wrtd_trig_id_cmp
(
id
,
&
triggers
[
i
].
trigger
)
==
0
)
{
*
assigned
=
1
;
return
0
;
}
}
return
0
;
}
/**
* It check if the output real-time application is alive
* @param[in] dev device token
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_out_ping
(
struct
wrtd_node
*
dev
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
return
trtl_fw_ping
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
);
}
/**
* It gets the output base time
* @param[in] dev device token
* @param[out] ts output device base time
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_out_base_time
(
struct
wrtd_node
*
dev
,
struct
wr_timestamp
*
ts
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
uint32_t
variables
[]
=
{
OUT_VAR_DEVICE_TIME_S
,
0
,
OUT_VAR_DEVICE_TIME_T
,
0
};
int
err
;
err
=
trtl_fw_variable_get
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
variables
,
2
);
if
(
err
)
return
err
;
ts
->
seconds
=
variables
[
1
];
ts
->
ticks
=
variables
[
3
];
return
0
;
}
/**
* It gets the output version
* @param[in] dev device token
* @param[out] version the RT application version
* @return 0 on success, -1 on error and errno is set appropriately
*/
int
wrtd_out_version
(
struct
wrtd_node
*
dev
,
struct
trtl_fw_version
*
version
)
{
struct
wrtd_desc
*
wrtd
=
(
struct
wrtd_desc
*
)
dev
;
return
trtl_fw_version
(
wrtd
->
trtl
,
WRTD_CPU_FD
,
0
,
version
);
}
/**
* It tells if the ouput firmware is valid
* @param[in] dev device token
* @param[out] version the RT application version
* @return 1 when valid, 0 if invalid or error (and errno is set appropriately)
*/
int
wrtd_out_is_valid
(
struct
wrtd_node
*
dev
)
{
struct
trtl_fw_version
version
;
int
err
;
err
=
wrtd_out_version
(
dev
,
&
version
);
if
(
err
)
return
0
;
if
(
version
.
rt_id
!=
WRTD_OUT_RT_ID
)
{
errno
=
EWRTD_INVALID_IN_APP
;
return
0
;
}
return
1
;
}
software/lib-old/libwrtd.h
deleted
100644 → 0
View file @
407f25d7
/*
* Copyright (C) 2014 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
* inspired by a draft of Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* License: GPL v3
*/
#ifndef __WRTD_LIB_H__
#define __WRTD_LIB_H__
/** @file libwrtd.h */
#ifdef __cplusplus
extern
"C"
{
#endif
#include <stdint.h>
#include <stdio.h>
#include "libmockturtle.h"
/**
* @file wrtd-common.h
*/
#include "wrtd-common.h"
struct
wrtd_node
;
#define WRTD_DEFAULT_TIMEOUT 1000
/**
* @enum wrtd_error_list
* White Rabbit Trigger Distribution errors
*/
enum
wrtd_error_list
{
EWRTD_INVALID_ANSWER_ACK
=
3276
,
EWRTD_INVALID_ANSWER_STATE
,
EWRTD_INVALID_BINARY
,
EWRTD_INVALID_DEAD_TIME
,
EWRTD_INVALID_DELAY
,
EWRTD_INVALID_TRIG_ID
,
EWRTD_INVALID_CHANNEL
,
EWRTD_NO_IMPLEMENTATION
,
EWRTD_INVALID_ANSWER_TRIG
,
EWRTD_INVALID_ANSWER_HASH
,
EWRTD_INVALID_ANSWER_HASH_CONT
,
EWRTD_INVALID_ANSWER_HANDLE
,
EWRTD_NOFOUND_TRIGGER
,
EWRTD_NO_TRIGGER_CONDITION
,
EWRTD_INVALID_PULSE_WIDTH
,
EWRTD_INVALID_IN_APP
,
EWRTD_INVALID_OUT_APP
,
__EWRTD_MAX_ERROR_NUMBER
,
};
/**
* Trigger token
*/
struct
wrtd_trigger_handle
{
uint32_t
ptr_cond
;
/**< trigger condition pointer */
uint32_t
ptr_trig
;
/**< trigger pointer */
int
channel
;
/**< channel assigned to the trigger */
};
/**
* Status description for an input channel
*/
struct
wrtd_input_state
{
int
input
;
/**< Input channel index */
uint32_t
flags
;
/**< enum list_io_flags */
uint32_t
log_level
;
/**< enum list_log_level */
enum
wrtd_trigger_mode
mode
;
/**< Trigger mode in use */
uint32_t
total_pulses
;
/**< Number of incoming pulses detected */
uint32_t
sent_triggers
;
/**< Number of triggers sent over the
white-rabbit network */
uint32_t
sent_packets
;
/**< Number of packets sent over the
white-rabbit network */
uint32_t
miss_no_timing
;
/**< Number of pulse missing due to no WR
timing */
struct
wrtd_trigger_entry
last_sent
;
/**< Description of the last
trigger sent */
struct
wrtd_trig_id
assigned_id
;
/**< trigger assigned to this channel */
struct
wr_timestamp
dead_time
;
/**< Configured dead time */
struct
wr_timestamp
delay
;
/**< Time delay assined */
struct
wr_timestamp
last_pulse
;
/** Time stamp of the last
detected pulse*/
struct
wr_timestamp
tdc_timebase_offset
;
/**< TDC time base offset */
};
/**
* Status description for a trigger on output
*/
struct
wrtd_output_trigger_state
{
int
is_conditional
;
/**< tell if the trigger is under condition or not */
int
enabled
;
/**< tell if the trigger is enable, so it may be
generater as output */
struct
wrtd_trig_id
trigger
;
/**< Trigger identifier */
struct
wrtd_trig_id
condition
;
/**< Trigger identifier for the trigger
condition */
struct
wr_timestamp
delay_trig
;
/**< Configured trigger delay */
struct
wr_timestamp
delay_cond
;
/**< Configured trigger condition delay */
struct
wrtd_trigger_handle
handle
;
int
latency_worst_us
;
/**< Worst latency in micro-seconds */
int
latency_average_us
;
/**< Average latency in micro-seconds */
uint32_t
executed_pulses
;
/**< Number of executed pulses */
uint32_t
missed_pulses
;
/**< Number of missed pulses */
void
*
private_data
;
/**< private pointer used by the library */
};
/**
* Status description for an output channel
*/
struct
wrtd_output_state
{
int
output
;
/**< Output channel index */
uint32_t
executed_pulses
;
/**< Number of generated pulses */
uint32_t
missed_pulses_late
;
/**< Number of missed pulses due to: */
uint32_t
missed_pulses_deadtime
;
/**< Number of missed pulses due to: */
uint32_t
missed_pulses_overflow
;
/**< Number of missed pulses due to: */
uint32_t
missed_pulses_no_timing
;
/**< Number of missed pulses due to: */
struct
wrtd_trigger_entry
last_executed
;
/**< Trigger description of the
last generated trigger */
struct
wrtd_trigger_entry
last_received
;
/**< Trigger description of the
last received trigger from
the white-rabbit network */
struct
wrtd_trigger_entry
last_enqueued
;
/**< Trigger description of
the last enqueued trigger
in the execution queue */
struct
wrtd_trigger_entry
last_lost
;
/**< Trigger description of the
last lost trigger */
uint32_t
flags
;
/**< enum list_io_flags */
uint32_t
log_level
;
/**< enum list_log_level */
enum
wrtd_trigger_mode
mode
;
/**< Trigger mode in use */
struct
wr_timestamp
dead_time
;
/**< Configured dead time */
struct
wr_timestamp
pulse_width
;
/**< Pulse width */
uint32_t
received_messages
;
/**< Number of received packets from
the network */
uint32_t
received_loopback
;
};
/**
* @file libwrtd-common.c
*/
/**
* @defgroup dev
* Set of functions to manage the basic device and library configuration.
* @{
*/
extern
int
wrtd_init
();
extern
void
wrtd_exit
();
extern
struct
wrtd_node
*
wrtd_open
(
uint32_t
device_id
);
extern
void
wrtd_close
(
struct
wrtd_node
*
dev
);
extern
struct
trtl_dev
*
wrtd_get_trtl_dev
(
struct
wrtd_node
*
dev
);
extern
int
wrtd_in_load
(
struct
wrtd_node
*
dev
,
char
*
fw
);
extern
int
wrtd_out_load
(
struct
wrtd_node
*
dev
,
char
*
fw
);
extern
int
wrtd_out_is_valid
(
struct
wrtd_node
*
dev
);
extern
int
wrtd_in_is_valid
(
struct
wrtd_node
*
dev
);
extern
int
wrtd_white_rabbit_sync
(
struct
wrtd_node
*
dev
,
unsigned
long
timeout_s
);
extern
int
wrtd_time_get
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
struct
wr_timestamp
*
current_time
);
/**@}*/
/**
* @defgroup util Utilities
* Set of utilities
* @{
*/
extern
const
char
*
wrtd_strerror
(
int
err
);
extern
void
wrtd_ts_to_pico
(
struct
wr_timestamp
*
ts
,
uint64_t
*
pico
);
extern
void
wrtd_pico_to_ts
(
uint64_t
*
pico
,
struct
wr_timestamp
*
ts
);
extern
void
wrtd_ts_to_sec_pico
(
struct
wr_timestamp
*
ts
,
uint64_t
*
sec
,
uint64_t
*
pico
);
extern
void
wrtd_sec_pico_to_ts
(
uint64_t
sec
,
uint64_t
pico
,
struct
wr_timestamp
*
ts
);
extern
int
wrtd_ts_sub
(
struct
wr_timestamp
*
res
,
struct
wr_timestamp
*
l
,
struct
wr_timestamp
*
r
);
/**@}*/
/**
* @defgroup log Logging
* Set of logging functions for input and output channels
* @{
*/
extern
const
char
*
wrtd_strlogging
(
enum
wrtd_log_level
lvl
);
enum
wrtd_log_level
wrtd_strlogging_to_level
(
char
*
log
);
extern
void
wrtd_strlogging_full
(
char
*
buf
,
uint32_t
log_level
);
extern
int
wrtd_log_read
(
struct
wrtd_node
*
dev
,
struct
wrtd_log_entry
*
log
,
int
count
,
int
poll_timeout
);
extern
int
wrtd_in_log_level_set
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
uint32_t
log_level
);
extern
int
wrtd_in_log_level_get
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
uint32_t
*
log_level
);
extern
int
wrtd_out_log_level_set
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
uint32_t
log_level
);
extern
int
wrtd_out_log_level_get
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
uint32_t
*
log_level
);
/**@}*/
/**
* @file libwrtd-input.c
*/
/**
* @defgroup input Input Management
* Set of functions to handle input channels
* @{
*/
extern
int
wrtd_in_state_get
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
struct
wrtd_input_state
*
state
);
extern
int
wrtd_in_enable
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
int
enable
);
extern
int
wrtd_in_trigger_assign
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
struct
wrtd_trig_id
*
trig_id
);
extern
int
wrtd_in_trigger_unassign
(
struct
wrtd_node
*
dev
,
unsigned
int
input
);
extern
int
wrtd_in_trigger_mode_set
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
enum
wrtd_trigger_mode
mode
);
extern
int
wrtd_in_trigger_software
(
struct
wrtd_node
*
dev
,
struct
wrtd_trigger_entry
*
trigger
);
extern
int
wrtd_in_arm
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
int
armed
);
extern
int
wrtd_in_dead_time_set
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
uint64_t
dead_time_ps
);
extern
int
wrtd_in_delay_set
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
uint64_t
delay_ps
);
extern
int
wrtd_in_timebase_offset_set
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
uint64_t
offset
);
extern
int
wrtd_in_counters_reset
(
struct
wrtd_node
*
dev
,
unsigned
int
input
);
extern
int
wrtd_in_global_counters_reset
(
struct
wrtd_node
*
dev
);
extern
int
wrtd_in_seq_counter_set
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
unsigned
int
value
);
extern
int
wrtd_in_is_enabled
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
unsigned
int
*
enable
);
extern
int
wrtd_in_is_armed
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
unsigned
int
*
armed
);
extern
int
wrtd_in_has_trigger
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
unsigned
int
*
assigned
);
extern
int
wrtd_in_ping
(
struct
wrtd_node
*
dev
);
extern
int
wrtd_in_base_time
(
struct
wrtd_node
*
dev
,
struct
wr_timestamp
*
ts
);
extern
int
wrtd_in_version
(
struct
wrtd_node
*
dev
,
struct
trtl_fw_version
*
version
);
extern
int
wrtd_in_dead_time_get
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
uint64_t
*
dead_time_ps
);
extern
int
wrtd_in_delay_get
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
uint64_t
*
delay_ps
);
/**@}*/
/**
* @file libwrtd-output.c
*/
/**
* @defgroup output Output Management
* Set of functions to handle output channels
* @{
*/
extern
int
wrtd_out_state_get
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
struct
wrtd_output_state
*
state
);
extern
int
wrtd_out_enable
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
int
enable
);
extern
int
wrtd_out_trig_assign
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
struct
wrtd_trigger_handle
*
handle
,
struct
wrtd_trig_id
*
trig
,
struct
wrtd_trig_id
*
condition
);
extern
int
wrtd_out_trig_unassign
(
struct
wrtd_node
*
dev
,
struct
wrtd_trigger_handle
*
handle
);
extern
int
wrtd_out_trig_get_all
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
struct
wrtd_output_trigger_state
*
triggers
,
int
max_count
);
extern
int
wrtd_out_trig_state_get_by_index
(
struct
wrtd_node
*
dev
,
unsigned
int
index
,
unsigned
int
output
,
struct
wrtd_output_trigger_state
*
trigger
);
extern
int
wrtd_out_trig_state_get_by_id
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
struct
wrtd_trig_id
*
id
,
struct
wrtd_output_trigger_state
*
trigger
);
extern
int
wrtd_out_trig_state_get_by_handle
(
struct
wrtd_node
*
dev
,
struct
wrtd_trigger_handle
*
handle
,
struct
wrtd_output_trigger_state
*
state
);
extern
int
wrtd_out_trig_delay_set
(
struct
wrtd_node
*
dev
,
struct
wrtd_trigger_handle
*
handle
,
uint64_t
delay_ps
);
extern
int
wrtd_out_dead_time_set
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
uint64_t
dead_time_ps
);
extern
int
wrtd_out_pulse_width_set
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
uint64_t
pulse_width_ps
);
extern
int
wrtd_out_trig_enable
(
struct
wrtd_node
*
dev
,
struct
wrtd_trigger_handle
*
handle
,
int
enable
);
extern
int
wrtd_out_ping
(
struct
wrtd_node
*
dev
);
extern
int
wrtd_out_base_time
(
struct
wrtd_node
*
dev
,
struct
wr_timestamp
*
ts
);
extern
int
wrtd_out_version
(
struct
wrtd_node
*
dev
,
struct
trtl_fw_version
*
version
);
extern
int
wrtd_out_trigger_mode_set
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
enum
wrtd_trigger_mode
mode
);
extern
int
wrtd_out_trig_condition_delay_set
(
struct
wrtd_node
*
dev
,
struct
wrtd_trigger_handle
*
handle
,
uint64_t
delay_ps
);
extern
int
wrtd_out_arm
(
struct
wrtd_node
*
dev
,
unsigned
int
input
,
int
armed
);
extern
int
wrtd_out_counters_reset
(
struct
wrtd_node
*
dev
,
unsigned
int
output
);
extern
int
wrtd_out_global_counters_reset
(
struct
wrtd_node
*
dev
);
extern
int
wrtd_out_check_triggered
(
struct
wrtd_node
*
dev
,
unsigned
int
output
);
extern
int
wrtd_out_is_enabled
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
unsigned
int
*
enable
);
extern
int
wrtd_out_is_armed
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
unsigned
int
*
armed
);
extern
int
wrtd_out_has_trigger
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
struct
wrtd_trig_id
*
id
,
unsigned
int
*
assigned
);
extern
int
wrtd_out_trigger_sw_now
(
struct
wrtd_node
*
dev
,
unsigned
int
output
);
extern
int
wrtd_out_trigger_sw
(
struct
wrtd_node
*
dev
,
unsigned
int
output
,
struct
wr_timestamp
*
ts
);
/**@}*/
#ifdef __cplusplus
};
#endif
#endif
software/lib-old/readme.md
deleted
100644 → 0
View file @
407f25d7
Library Overview {#mainpage}
================
This is the
**WRTD**
library documentation. Here you can find all
the information about the
*White-Rabbit Trigger-Distribution*
API and the main
library behavior that you need to be aware of.
If you are reading this from the doxygen documentation, then you can find
the API documentation in the usual Doxygen places. Otherwise, you can get
the API documentation directly from the source code that you can find in
the
*lib*
directory.
In this document we are going to provides you some clues to understand how
to use the library API.
This library is completely base on the
*White-Rabbit Node-Core*
library.
It uses all its features to establish the communication between the
Trigger Distribution Real Time applications. This library hides the knowledge
about the conventions (protocol) used between the Host and the Real Time
applications and it exposes a simple API for the interaction.
While reading any documentation we suggest you to read the dictionary to avoid
misinterpretation.
Overview
========
The White-Rabbit Trigger-Distribution is a system that allow its users to detect
a trigger (pulse), propagate it over the White-Rabbit network and reproduce it
on a remote machine. This library is in charge to ease the configuration of this
system. The system is based on the White-Rabbit Node-Core. There are two cores
running separately two Real Time applications: one to manage the input,
one to manage the output.
+--------------Trigger-Distribution-System-------------+
| RealTime App - - - - - - - - - RealTime App |
-\ | +-------+ ( ) +--------+ | /-
|--------|->| INPUT |--->( WhiteRabbit Network )--->| OUTPUT |--|------->|
-/ PULSE | +-------+ ( ) +--------+ | PULSE \-
| - - - - - - - - - |
+------------------------------------------------------+
Initialization
==============
To be able to use this library the first thing to do is to initialize a library
instance using wrtd_init(); form this point on you are able to use the
library API. Of course, when you finished to use the library you have to
remove this instance using wrtd_exit().
At the beginning, all communication channels are close, so before start to
communicate with the Real Time application you have to open your communication
channel. Then, close it when you have done.
Logging
=======
The WRTD Real Time applications are able to provide some logging information
about the things happening on the FPGA. This interface is read only, so
you can only read logging messages. There are only two configuration parameters:
one for the
*logging level*
; the other one to set the exclusivity access to the
logging interface. When the logging interface is shared, then also other users
are allowed to get the same messages.
Input
=====
The
*input*
Real Time application and the associated part of library manages
the detection of the incoming pulse and their correct propagation over the
white-rabbit network as trigger event.
The library allows the user to fully configure the input parameter and to get
the current status of Real Time application but also to get information about
the triggers associated to the input channels. Go directly to the API for the
list of parameters that you can set.
Output
======
The
*input*
Real Time application and the associated part of library manages
the pluse generation and their correct reception from the white-rabbit
network as trigger event.
The library allows the user to fully configure the output parameter and to get
the current status of Real Time application but also to get information about
the trigger associated to the output channesl. Go directly to the API for the
list of parameters that you can set.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment