Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
F
FMC DEL 1ns 4cha
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
2
Issues
2
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
FMC DEL 1ns 4cha
Commits
605c84cc
Commit
605c84cc
authored
May 16, 2012
by
Tomasz Wlostowski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
software: fdelay-gs ported to use test library
parent
7b9803b4
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
645 additions
and
84 deletions
+645
-84
fdelay_lib.h
software/include/fdelay_lib.h
+5
-1
fdelay_private.h
software/include/fdelay_private.h
+1
-0
Makefile
software/lib/Makefile
+5
-13
fdelay-gs.c
software/lib/fdelay-gs.c
+464
-0
fdelay_lib.c
software/lib/fdelay_lib.c
+51
-26
fdelay_pps_demo.c
software/lib/fdelay_pps_demo.c
+11
-5
fdelay_test.c
software/lib/fdelay_test.c
+5
-3
pp.conf
software/lib/pp.conf
+61
-0
spec_common.c
software/lib/spec_common.c
+42
-36
No files found.
software/include/fdelay_lib.h
View file @
605c84cc
...
@@ -38,7 +38,7 @@ typedef struct fdelay_device
...
@@ -38,7 +38,7 @@ typedef struct fdelay_device
typedef
struct
typedef
struct
{
{
int
32
_t
utc
;
/* TAI seconds */
/* FIXME: replace all UTCs with TAIs or seconds for clarity */
int
64
_t
utc
;
/* TAI seconds */
/* FIXME: replace all UTCs with TAIs or seconds for clarity */
int32_t
coarse
;
/* 125 MHz counter cycles */
int32_t
coarse
;
/* 125 MHz counter cycles */
int32_t
frac
;
/* Fractional part (<8ns) */
int32_t
frac
;
/* Fractional part (<8ns) */
uint16_t
seq_id
;
/* Sequence ID to detect missed timestamps */
uint16_t
seq_id
;
/* Sequence ID to detect missed timestamps */
...
@@ -113,5 +113,9 @@ int fdelay_configure_pulse_gen(fdelay_device_t *dev, int channel_mask, int enabl
...
@@ -113,5 +113,9 @@ int fdelay_configure_pulse_gen(fdelay_device_t *dev, int channel_mask, int enabl
/* (pulse mode only) Returns non-0 when all of the channels in channel mask have produced their programmed pulses */
/* (pulse mode only) Returns non-0 when all of the channels in channel mask have produced their programmed pulses */
int
fdelay_outputs_triggered
(
fdelay_device_t
*
dev
,
int
channel_mask
,
int
blocking
);
int
fdelay_outputs_triggered
(
fdelay_device_t
*
dev
,
int
channel_mask
,
int
blocking
);
void
fdelay_set_user_offset
(
fdelay_device_t
*
dev
,
int
input
,
int64_t
offset
);
int
fdelay_get_time
(
fdelay_device_t
*
dev
,
fdelay_time_t
*
t
);
int
fdelay_set_time
(
fdelay_device_t
*
dev
,
const
fdelay_time_t
t
);
#endif
#endif
software/include/fdelay_private.h
View file @
605c84cc
...
@@ -85,6 +85,7 @@ struct fine_delay_hw
...
@@ -85,6 +85,7 @@ struct fine_delay_hw
int
wr_enabled
;
int
wr_enabled
;
int
wr_state
;
int
wr_state
;
struct
fine_delay_calibration
calib
;
struct
fine_delay_calibration
calib
;
int64_t
input_user_offset
,
output_user_offset
;
};
};
/* some useful access/declaration macros */
/* some useful access/declaration macros */
...
...
software/lib/Makefile
View file @
605c84cc
...
@@ -3,24 +3,16 @@ CFLAGS = -I../include -g -Imini_bone -Ispll
...
@@ -3,24 +3,16 @@ CFLAGS = -I../include -g -Imini_bone -Ispll
#uncomment for extra tests (DAC, output stage INL/DNL)
#uncomment for extra tests (DAC, output stage INL/DNL)
#CFLAGS += -DPERFORM_LONG_TESTS
#CFLAGS += -DPERFORM_LONG_TESTS
OBJS_LIB
=
fdelay_lib.o
fdelay_bus.o rr_io.o i2c_master.o onewire.o mini_bone/minibone_lib.o mini_bone/ptpd_netif.o spec_common.o
OBJS_LIB
=
fdelay_lib.o
i2c_master.o onewire.o mini_bone/minibone_lib.o mini_bone/ptpd_netif.o spec_common.o
all
:
testprog lib
testprog3 testprog4
all
:
testprog lib
gs
lib
:
$(OBJS_LIB)
lib
:
$(OBJS_LIB)
gcc
-shared
-o
libfinedelay.so
$(OBJS_LIB)
gcc
-shared
-o
libfinedelay.so
$(OBJS_LIB)
testprog
:
lib fdelay_test.o
testprog
:
lib fdelay_pps_demo.o
gcc
-o
fdelay_test
$(OBJS_LIB)
fdelay_test.o
-lm
#testprog2: lib fdelay_cal.o
# gcc -o fdelay_cal $(OBJS_LIB) fdelay_cal.o -lm
testprog3
:
lib fdelay_pps_demo.o
gcc
-o
fdelay_pps_demo
$(OBJS_LIB)
fdelay_pps_demo.o
-lm
gcc
-o
fdelay_pps_demo
$(OBJS_LIB)
fdelay_pps_demo.o
-lm
testprog4
:
lib fdelay_eeprom
.o
gs
:
lib fdelay-gs
.o
gcc
-o
fdelay
_eeprom
$(OBJS_LIB)
fdelay_eeprom
.o
-lm
gcc
-o
fdelay
-gs
$(OBJS_LIB)
fdelay-gs
.o
-lm
clean
:
rm
-f
libfinedelay.so
$(OBJS_LIB)
\ No newline at end of file
software/lib/fdelay-gs.c
0 → 100644
View file @
605c84cc
/* Simple demo that reads samples using the read call */
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <unistd.h>
#include <signal.h>
#include <sys/select.h>
#define FDELAY_INTERNAL // for sysfs_get/set
#include "fdelay_lib.h"
#define PACKED __attribute__((packed))
#define TYPE_START_LOGGING 1
#define TYPE_END_LOGGING 2
#define TYPE_TIMESTAMP 3
struct
fdelay_time
{
uint64_t
utc
;
uint32_t
coarse
;
uint32_t
frac
;
uint32_t
seq_id
;
uint32_t
channel
;
};
PACKED
struct
binary_timestamp
{
int32_t
card_id
;
uint8_t
type
;
PACKED
struct
fdelay_time
ts
;
};
#define MAX_BOARDS 64
struct
board_def
{
fdelay_device_t
*
b
;
int
term_on
;
int64_t
input_offset
;
int64_t
output_offset
;
int
hw_index
;
int
in_use
;
int
fd
;
struct
{
int64_t
offset_pps
,
width
,
period
;
int
enabled
;
}
outs
[
4
];
};
struct
board_def
boards
[
MAX_BOARDS
];
static
FILE
*
log_file
=
NULL
;
void
log_write
(
fdelay_time_t
*
t
,
int
card_id
)
{
struct
binary_timestamp
bt
;
if
(
!
log_file
)
return
;
bt
.
ts
.
utc
=
t
->
utc
;
bt
.
ts
.
coarse
=
t
->
coarse
;
bt
.
ts
.
frac
=
t
->
frac
;
bt
.
ts
.
seq_id
=
t
->
seq_id
;
bt
.
ts
.
channel
=
0
;
bt
.
type
=
TYPE_TIMESTAMP
;
bt
.
card_id
=
card_id
;
fwrite
(
&
bt
,
sizeof
(
struct
binary_timestamp
),
1
,
log_file
);
fflush
(
log_file
);
}
void
log_start
(
char
*
log_file_name
)
{
struct
binary_timestamp
bt
;
log_file
=
fopen
(
log_file_name
,
"a+"
);
if
(
!
log_file
)
{
fprintf
(
stderr
,
"Can't open the log file: %s
\n
"
,
log_file_name
);
exit
(
-
1
);
}
bt
.
card_id
=
0
;
bt
.
type
=
TYPE_START_LOGGING
;
fwrite
(
&
bt
,
sizeof
(
struct
binary_timestamp
),
1
,
log_file
);
fflush
(
log_file
);
}
void
log_stop
()
{
struct
binary_timestamp
bt
;
if
(
!
log_file
)
return
;
bt
.
card_id
=
0
;
bt
.
type
=
TYPE_END_LOGGING
;
fwrite
(
&
bt
,
sizeof
(
struct
binary_timestamp
),
1
,
log_file
);
fflush
(
log_file
);
fclose
(
log_file
);
}
int64_t
parse_num
(
const
char
*
n_str
)
{
struct
{
char
unit
;
int64_t
multiplier
;
}
units
[]
=
{
{
'p'
,
1LL
},
{
'n'
,
1000LL
},
{
'u'
,
1000000LL
},
{
'm'
,
1000000000LL
},
{
's'
,
1000000000000LL
},
{
' '
,
0
}
};
int64_t
n
;
char
unit
;
int
rv
=
sscanf
(
n_str
,
"%lli%c"
,
&
n
,
&
unit
);
if
(
rv
==
1
)
return
n
;
else
if
(
rv
==
2
)
{
int
i
;
for
(
i
=
0
;
units
[
i
].
multiplier
;
i
++
)
if
(
units
[
i
].
unit
==
unit
)
return
units
[
i
].
multiplier
*
n
;
fprintf
(
stderr
,
"Unrecognized numeric constant '%s' (wrong units?)
\n
"
,
n_str
);
exit
(
-
1
);
}
fprintf
(
stderr
,
"Unrecognized numeric constant '%s'
\n
"
,
n_str
);
exit
(
-
1
);
}
#define MAX_TOKENS 16
#define MAX_TOK_LENGTH 256
typedef
char
token_array
[
MAX_TOKENS
][
MAX_TOK_LENGTH
];
/* returns: tokenized arguments to tokens, command (1st word) to cmd */
int
next_command
(
FILE
*
f_config
,
char
*
cmd
,
token_array
tokens
)
{
char
line
[
1024
];
char
*
running
;
const
char
*
delims
=
"
\n\r\t
"
;
int
i
;
int
n
=
0
;
do
{
if
(
feof
(
f_config
))
return
-
1
;
fgets
(
line
,
sizeof
(
line
),
f_config
);
running
=
strdupa
(
line
);
while
(
*
running
==
' '
||
*
running
==
'\t'
)
running
++
;
strncpy
(
cmd
,
strsep
(
&
running
,
delims
),
MAX_TOK_LENGTH
);
}
while
(
cmd
[
0
]
==
'#'
||
cmd
[
0
]
==
' '
||
cmd
[
0
]
==
'\n'
||
cmd
[
0
]
==
'\r'
||
!
cmd
[
0
]);
for
(
i
=
0
;
i
<
MAX_TOKENS
;
i
++
)
{
char
*
token
=
strsep
(
&
running
,
delims
);
if
(
token
==
NULL
)
return
n
;
if
(
strlen
(
token
)
>
0
)
{
// printf("tok %p\n", tokens[0]);
strncpy
(
&
tokens
[
n
][
0
],
token
,
MAX_TOK_LENGTH
);
n
++
;
}
}
return
0
;
}
#define CUR boards[current_board]
void
load_config
(
const
char
*
config_file
)
{
token_array
args
;
char
cmd
[
MAX_TOK_LENGTH
];
int
current_board
=
0
;
int
n_args
;
FILE
*
f_config
=
fopen
(
config_file
,
"r"
);
if
(
!
f_config
)
{
fprintf
(
stderr
,
"Can't open configuration file '%s'
\n
"
,
config_file
);
exit
(
-
1
);
}
memset
(
boards
,
0
,
sizeof
(
boards
));
while
((
n_args
=
next_command
(
f_config
,
cmd
,
args
))
>=
0
)
{
if
(
!
strcmp
(
cmd
,
"board"
))
{
current_board
=
parse_num
(
args
[
0
]);
CUR
.
in_use
=
1
;
}
if
(
!
strcmp
(
cmd
,
"hw_index"
))
{
CUR
.
hw_index
=
parse_num
(
args
[
0
]);
printf
(
"Adding board %d, hw_index %x
\n
"
,
current_board
,
CUR
.
hw_index
);
}
if
(
!
strcmp
(
cmd
,
"termination"
))
CUR
.
term_on
=
parse_num
(
args
[
0
]);
if
(
!
strcmp
(
cmd
,
"input_offset"
))
CUR
.
input_offset
=
parse_num
(
args
[
0
]);
if
(
!
strcmp
(
cmd
,
"output_offset"
))
CUR
.
output_offset
=
parse_num
(
args
[
0
]);
if
(
!
strcmp
(
cmd
,
"out"
))
{
int
index
=
parse_num
(
args
[
0
])
-
1
;
if
(
index
<
0
||
index
>
3
)
{
fprintf
(
stderr
,
"Invalid output index
\n
"
);
exit
(
-
1
);
}
CUR
.
outs
[
index
].
offset_pps
=
parse_num
(
args
[
1
]);
CUR
.
outs
[
index
].
width
=
parse_num
(
args
[
2
]);
CUR
.
outs
[
index
].
period
=
parse_num
(
args
[
3
]);
CUR
.
outs
[
index
].
enabled
=
1
;
// printf("OutCfg: %d %lli %lli %lli\n", index, CUR.outs[index].offset_pps, CUR.outs[index].width, CUR.outs[index].period);
}
if
(
!
strcmp
(
cmd
,
"log_file"
))
log_start
(
args
[
0
]);
}
fclose
(
f_config
);
}
#undef CUR
void
enable_termination
(
fdelay_device_t
*
b
,
int
enable
)
{
int
i
;
fdelay_configure_trigger
(
b
,
1
,
enable
);
}
void
enable_wr
(
fdelay_device_t
*
b
,
int
index
)
{
int
lock_retries
=
10
;
printf
(
"Locking to WR network [board=%d]..."
,
index
);
fflush
(
stdout
);
fdelay_configure_sync
(
b
,
FDELAY_SYNC_LOCAL
);
sleep
(
2
);
fdelay_configure_sync
(
b
,
FDELAY_SYNC_WR
);
while
(
fdelay_check_sync
(
b
)
<=
0
)
{
printf
(
"."
);
fflush
(
stdout
);
sleep
(
1
);
if
(
lock_retries
--
==
0
)
{
fprintf
(
stderr
,
" WR lock timed out
\n
"
);
exit
(
1
);
}
}
printf
(
"
\n
"
);
fflush
(
stdout
);
}
/* Add two timestamps */
static
fdelay_time_t
ts_add
(
fdelay_time_t
a
,
fdelay_time_t
b
)
{
a
.
frac
+=
b
.
frac
;
if
(
a
.
frac
>=
4096
)
{
a
.
frac
-=
4096
;
a
.
coarse
++
;
}
a
.
coarse
+=
b
.
coarse
;
if
(
a
.
coarse
>=
125000000
)
{
a
.
coarse
-=
125000000
;
a
.
utc
++
;
}
a
.
utc
+=
b
.
utc
;
return
a
;
}
int
configure_board
(
struct
board_def
*
bdef
)
{
fdelay_device_t
*
b
=
malloc
(
sizeof
(
fdelay_device_t
));
int
i
;
if
(
spec_fdelay_init
(
b
,
bdef
->
hw_index
>>
8
,
bdef
->
hw_index
&
0xff
)
<
0
)
{
fprintf
(
stderr
,
"Can't open fdelay board @ hw_index %x
\n
"
,
bdef
->
hw_index
);
exit
(
-
1
);
}
bdef
->
b
=
b
;
fdelay_configure_trigger
(
bdef
->
b
,
0
,
bdef
->
term_on
);
enable_wr
(
b
,
bdef
->
hw_index
);
int
val
=
bdef
->
input_offset
;
// fdelay_sysfs_set((struct __fdelay_board *)b, "fd-input/user-offset", (uint32_t *)&val);
fdelay_set_user_offset
(
b
,
1
,
val
);
for
(
i
=
0
;
i
<
4
;
i
++
)
{
char
path
[
1024
];
int
val
=
bdef
->
output_offset
;
snprintf
(
path
,
sizeof
(
path
),
"fd-ch%d/user-offset"
,
i
+
1
);
fdelay_set_user_offset
(
b
,
0
,
val
);
// fdelay_sysfs_set((struct __fdelay_board *)b, path,(uint32_t *) &val);
}
for
(
i
=
0
;
i
<
4
;
i
++
)
{
if
(
bdef
->
outs
[
i
].
enabled
)
{
fdelay_time_t
t_cur
,
pps_offset
,
width
;
// struct fdelay_pulse p;
fdelay_get_time
(
bdef
->
b
,
&
t_cur
);
// printf("Configure output %d [t_cur %d:%d]\n", i+1,t_cur.utc, t_cur.coarse);
// fdelay_pico_to_time(&bdef->outs[i].offset_pps, &pps_offset);
// fdelay_pico_to_time(&bdef->outs[i].width, &width);
t_cur
.
utc
+=
2
;
t_cur
.
coarse
=
0
;
t_cur
.
frac
=
0
;
t_cur
=
ts_add
(
t_cur
,
fdelay_from_picos
(
bdef
->
outs
[
i
].
offset_pps
));
//printf("Configure output %d [t_start %d:%d width %lld period %lld]\n", i+1,t_cur.utc, t_cur.coarse, bdef->outs[i].width, bdef->outs[i].period);
fdelay_configure_pulse_gen
(
bdef
->
b
,
i
+
1
,
1
,
t_cur
,
bdef
->
outs
[
i
].
width
,
bdef
->
outs
[
i
].
period
,
-
1
);
// fdelay_configure_output_pulse()
/* p.rep = -1;
p.mode = FD_OUT_MODE_PULSE;
p.start = t_cur;
p.end = ts_add(t_cur, width);*/
// fdelay_pico_to_time(&bdef->outs[i].period, &p.loop);
// fdelay_config_pulse(bdef->b, i, &p);
}
}
/*enable input */
for
(
i
=
0
;
i
<
4
;
i
++
)
if
(
bdef
->
outs
[
i
].
enabled
)
while
(
!
fdelay_channel_triggered
(
bdef
->
b
,
i
+
1
))
usleep
(
100000
);
fdelay_configure_trigger
(
bdef
->
b
,
1
,
bdef
->
term_on
);
fdelay_configure_readout
(
bdef
->
b
,
1
);
printf
(
"Configuration complete
\n
"
);
fflush
(
stdout
);
return
0
;
}
void
handle_readout
(
struct
board_def
*
bdef
)
{
int64_t
t_ps
;
fdelay_time_t
t
;
static
time_t
start
;
int
done
;
while
(
fdelay_read
(
bdef
->
b
,
&
t
,
1
)
==
1
)
{
t_ps
=
(
t
.
coarse
*
8000LL
)
+
((
t
.
frac
*
8000LL
)
>>
12
);
printf
(
"card 0x%04x, seq %5i: time %lli s, %lli.%03lli ns [%x]
\n
"
,
bdef
->
hw_index
,
t
.
seq_id
,
t
.
utc
,
t_ps
/
1000LL
,
t_ps
%
1000LL
,
t
.
coarse
);
log_write
(
&
t
,
bdef
->
hw_index
);
}
}
void
sighandler
(
int
sig
)
{
if
(
sig
==
SIGINT
||
sig
==
SIGTERM
||
sig
==
SIGKILL
)
{
fprintf
(
stderr
,
"Cleaniung up...
\n
"
);
log_stop
();
exit
(
0
);
}
}
int
main
(
int
argc
,
char
*
argv
[])
{
int
i
,
maxfd
=
-
1
;
fd_set
allset
,
curset
;
signal
(
SIGINT
,
sighandler
);
signal
(
SIGTERM
,
sighandler
);
signal
(
SIGKILL
,
sighandler
);
if
(
argc
<
2
)
{
printf
(
"usage: %s <configuration-file>
\n
"
,
argv
[
0
]);
return
0
;
}
load_config
(
argv
[
1
]);
for
(
i
=
0
;
i
<
MAX_BOARDS
;
i
++
)
if
(
boards
[
i
].
in_use
)
{
int
fd
;
configure_board
(
&
boards
[
i
]);
}
for
(;;)
{
for
(
i
=
0
;
i
<
MAX_BOARDS
;
i
++
)
{
if
(
!
boards
[
i
].
in_use
)
continue
;
// printf(".");
handle_readout
(
&
boards
[
i
]);
}
usleep
(
100
);
}
}
software/lib/fdelay_lib.c
View file @
605c84cc
/*
/*
\
FmcDelay1ns4Cha (a.k.a. The Fine Delay Card)
FmcDelay1ns4Cha (a.k.a. The Fine Delay Card)
User-space driver/library
User-space driver/library
...
@@ -874,7 +874,8 @@ int fdelay_init(fdelay_device_t *dev)
...
@@ -874,7 +874,8 @@ int fdelay_init(fdelay_device_t *dev)
hw
->
wr_enabled
=
0
;
hw
->
wr_enabled
=
0
;
hw
->
wr_state
=
FDELAY_FREE_RUNNING
;
hw
->
wr_state
=
FDELAY_FREE_RUNNING
;
hw
->
acam_addr
=
0xff
;
hw
->
acam_addr
=
0xff
;
hw
->
input_user_offset
=
0
;
hw
->
output_user_offset
=
0
;
dbg
(
"%s: Initializing the Fine Delay Card
\n
"
,
__FUNCTION__
);
dbg
(
"%s: Initializing the Fine Delay Card
\n
"
,
__FUNCTION__
);
/* Read the Identification register and check if we are talking to a proper Fine Delay HDL Core */
/* Read the Identification register and check if we are talking to a proper Fine Delay HDL Core */
...
@@ -893,8 +894,9 @@ int fdelay_init(fdelay_device_t *dev)
...
@@ -893,8 +894,9 @@ int fdelay_init(fdelay_device_t *dev)
}
}
rv
=
read_calibration_eeprom
(
dev
,
&
hw
->
calib
);
// rv = read_calibration_eeprom(dev, &hw->calib);
rv
=
0
;
if
(
rv
<
0
)
if
(
rv
<
0
)
{
{
fail
(
TEST_SPI
,
"FMC EEPROM not detected."
);
fail
(
TEST_SPI
,
"FMC EEPROM not detected."
);
...
@@ -1087,7 +1089,7 @@ static fdelay_time_t ts_add(fdelay_time_t a, fdelay_time_t b)
...
@@ -1087,7 +1089,7 @@ static fdelay_time_t ts_add(fdelay_time_t a, fdelay_time_t b)
a
.
coarse
++
;
a
.
coarse
++
;
}
}
a
.
coarse
+=
b
.
coarse
;
a
.
coarse
+=
b
.
coarse
;
if
(
b
.
coarse
>=
125000000
)
if
(
a
.
coarse
>=
125000000
)
{
{
a
.
coarse
-=
125000000
;
a
.
coarse
-=
125000000
;
a
.
utc
++
;
a
.
utc
++
;
...
@@ -1095,6 +1097,8 @@ static fdelay_time_t ts_add(fdelay_time_t a, fdelay_time_t b)
...
@@ -1095,6 +1097,8 @@ static fdelay_time_t ts_add(fdelay_time_t a, fdelay_time_t b)
return
a
;
return
a
;
}
}
/* Converts a Fine Delay time stamp to plain picoseconds */
/* Converts a Fine Delay time stamp to plain picoseconds */
int64_t
fdelay_to_picos
(
const
fdelay_time_t
t
)
int64_t
fdelay_to_picos
(
const
fdelay_time_t
t
)
{
{
...
@@ -1102,6 +1106,14 @@ int64_t fdelay_to_picos(const fdelay_time_t t)
...
@@ -1102,6 +1106,14 @@ int64_t fdelay_to_picos(const fdelay_time_t t)
return
tp
;
return
tp
;
}
}
static
fdelay_time_t
ts_add_ps
(
fdelay_time_t
a
,
int64_t
b
)
{
if
(
b
<
0
)
return
ts_sub
(
a
,
fdelay_from_picos
(
-
b
));
else
return
ts_add
(
a
,
fdelay_from_picos
(
b
));
}
static
int
poll_rbuf
(
fdelay_device_t
*
dev
)
static
int
poll_rbuf
(
fdelay_device_t
*
dev
)
{
{
fd_decl_private
(
dev
)
fd_decl_private
(
dev
)
...
@@ -1150,9 +1162,9 @@ int fdelay_read(fdelay_device_t *dev, fdelay_time_t *timestamps, int how_many)
...
@@ -1150,9 +1162,9 @@ int fdelay_read(fdelay_device_t *dev, fdelay_time_t *timestamps, int how_many)
seq_frac
=
fd_readl
(
FD_REG_TSBR_FID
);
seq_frac
=
fd_readl
(
FD_REG_TSBR_FID
);
ts
.
frac
=
FD_TSBR_FID_FINE_R
(
seq_frac
);
ts
.
frac
=
FD_TSBR_FID_FINE_R
(
seq_frac
);
ts
.
seq_id
=
FD_TSBR_FID_SEQID_R
(
seq_frac
);
ts
.
seq_id
=
FD_TSBR_FID_SEQID_R
(
seq_frac
);
ts
.
channel
=
FD_TSBR_FID_CHANNEL_R
(
seq_frac
);
//
ts.channel = FD_TSBR_FID_CHANNEL_R(seq_frac);
*
timestamps
++
=
ts_
sub
(
ts
,
fdelay_from_picos
(
hw
->
calib
.
tdc_zero_offset
)
);
*
timestamps
++
=
ts_
add_ps
(
ts
,
hw
->
input_user_offset
);
how_many
--
;
how_many
--
;
n_read
++
;
n_read
++
;
...
@@ -1222,32 +1234,29 @@ int fdelay_configure_output(fdelay_device_t *dev, int channel, int enable, int64
...
@@ -1222,32 +1234,29 @@ int fdelay_configure_output(fdelay_device_t *dev, int channel, int enable, int64
int
fdelay_configure_pulse_gen
(
fdelay_device_t
*
dev
,
int
channel
,
int
enable
,
fdelay_time_t
t_start
,
int64_t
width_ps
,
int64_t
delta_ps
,
int
rep_count
)
int
fdelay_configure_pulse_gen
(
fdelay_device_t
*
dev
,
int
channel
,
int
enable
,
fdelay_time_t
t_start
,
int64_t
width_ps
,
int64_t
delta_ps
,
int
rep_count
)
{
{
fd_decl_private
(
dev
)
fd_decl_private
(
dev
)
uint32_t
base
=
(
channel
-
1
)
*
0x20
;
uint32_t
dcr
;
uint32_t
dcr
;
fdelay_time_t
start
,
end
,
delta
;
fdelay_time_t
start
,
end
,
delta
;
if
(
channel
<
1
||
channel
>
4
)
if
(
channel
<
1
||
channel
>
4
)
return
-
1
;
return
-
1
;
start
=
ts_add_ps
(
t_start
,
hw
->
output_user_offset
);
end
=
ts_add_ps
(
t_start
,
hw
->
output_user_offset
+
width_ps
-
4000
);
delta
=
fdelay_from_picos
(
delta_ps
);
start
=
t_start
;
printf
(
"Channel: %d
\n
"
,
channel
);
end
=
fdelay_from_picos
(
fdelay_to_picos
(
start
)
+
width_ps
-
4000
);
printf
(
"TStart: %d: %d:%d rep %d
\n
"
,
t_start
.
utc
,
t_start
.
coarse
,
t_start
.
frac
,
rep_count
);
delta
=
fdelay_from_picos
(
delta_ps
);
printf
(
"Start: %d: %d:%d rep %d
\n
"
,
start
.
utc
,
start
.
coarse
,
start
.
frac
,
rep_count
);
printf
(
"End: %d: %d:%d rep %d
\n
"
,
end
.
utc
,
end
.
coarse
,
end
.
frac
,
rep_count
);
//start = t_start;
printf
(
"Delta: %d: %d:%d rep %d
\n
"
,
delta
.
utc
,
delta
.
coarse
,
delta
.
frac
,
rep_count
);
//end = ts_add(start, fdelay_from_picos(width_ps));
//delta = fdelay_from_picos(delta_ps);
//printf("Start: %lld: %d:%d\n", start.utc, start.coarse, start.frac);
//printf("width: %lld delta: %lld rep: %d\n", width_ps, delta_ps, rep_count);
chan_writel
(
hw
->
frr_cur
[
channel
-
1
],
FD_REG_FRR
);
chan_writel
(
hw
->
frr_cur
[
channel
-
1
],
FD_REG_FRR
);
chan_writel
(
start
.
utc
>>
32
,
FD_REG_U_STARTH
);
chan_writel
(
0
,
FD_REG_U_STARTH
);
chan_writel
(
start
.
utc
&
0xffffffff
,
FD_REG_U_STARTL
);
chan_writel
(
start
.
utc
&
0xffffffff
,
FD_REG_U_STARTL
);
chan_writel
(
start
.
coarse
,
FD_REG_C_START
);
chan_writel
(
start
.
coarse
,
FD_REG_C_START
);
chan_writel
(
start
.
frac
,
FD_REG_F_START
);
chan_writel
(
start
.
frac
,
FD_REG_F_START
);
chan_writel
(
end
.
utc
>>
32
,
FD_REG_U_ENDH
);
chan_writel
(
0
,
FD_REG_U_ENDH
);
chan_writel
(
end
.
utc
&
0xffffffff
,
FD_REG_U_ENDL
);
chan_writel
(
end
.
utc
&
0xffffffff
,
FD_REG_U_ENDL
);
chan_writel
(
end
.
coarse
,
FD_REG_C_END
);
chan_writel
(
end
.
coarse
,
FD_REG_C_END
);
chan_writel
(
end
.
frac
,
FD_REG_F_END
);
chan_writel
(
end
.
frac
,
FD_REG_F_END
);
...
@@ -1279,7 +1288,7 @@ int fdelay_channel_triggered(fdelay_device_t *dev, int channel)
...
@@ -1279,7 +1288,7 @@ int fdelay_channel_triggered(fdelay_device_t *dev, int channel)
{
{
fd_decl_private
(
dev
)
fd_decl_private
(
dev
)
uint32_t
dcr
=
chan_readl
(
FD_REG_DCR
);
uint32_t
dcr
=
chan_readl
(
FD_REG_DCR
);
printf
(
"DCR%d %x
\n
"
,
channel
,
dcr
);
//
printf("DCR%d %x\n", channel, dcr);
return
dcr
&
FD_DCR_PG_TRIG
?
1
:
0
;
return
dcr
&
FD_DCR_PG_TRIG
?
1
:
0
;
}
}
...
@@ -1292,7 +1301,7 @@ int fdelay_set_time(fdelay_device_t *dev, const fdelay_time_t t)
...
@@ -1292,7 +1301,7 @@ int fdelay_set_time(fdelay_device_t *dev, const fdelay_time_t t)
fd_writel
(
0
,
FD_REG_GCR
);
fd_writel
(
0
,
FD_REG_GCR
);
fd_writel
(
t
.
utc
>>
32
,
FD_REG_TM_SECH
);
fd_writel
(
0
,
FD_REG_TM_SECH
);
fd_writel
(
t
.
utc
&
0xffffffff
,
FD_REG_TM_SECL
);
fd_writel
(
t
.
utc
&
0xffffffff
,
FD_REG_TM_SECL
);
fd_writel
(
t
.
coarse
,
FD_REG_TM_CYCLES
);
fd_writel
(
t
.
coarse
,
FD_REG_TM_CYCLES
);
...
@@ -1313,9 +1322,25 @@ int fdelay_get_time(fdelay_device_t *dev, fdelay_time_t *t)
...
@@ -1313,9 +1322,25 @@ int fdelay_get_time(fdelay_device_t *dev, fdelay_time_t *t)
fd_writel
(
tcr
|
FD_TCR_CAP_TIME
,
FD_REG_TCR
);
fd_writel
(
tcr
|
FD_TCR_CAP_TIME
,
FD_REG_TCR
);
t
->
utc
=
fd_readl
(
FD_REG_TM_SECL
);
t
->
utc
=
fd_readl
(
FD_REG_TM_SECL
);
t
->
coarse
=
fd_readl
(
FD_REG_TM_CYCLES
);
t
->
coarse
=
fd_readl
(
FD_REG_TM_CYCLES
);
// printf("GetTime: %d %d\n", t->utc, t->coarse);
return
0
;
return
0
;
}
}
void
fdelay_set_user_offset
(
fdelay_device_t
*
dev
,
int
input
,
int64_t
offset
)
{
fd_decl_private
(
dev
)
if
(
input
)
{
dbg
(
"SetUserInputOffset %lld ps
\n
"
,
offset
);
hw
->
input_user_offset
=
offset
;
}
else
{
dbg
(
"SetUserOutputOffset %lld ps
\n
"
,
offset
);
hw
->
output_user_offset
=
offset
;
}
}
/* To be rewritten to use interrupts and new WR FSM (see TCR register description).
/* To be rewritten to use interrupts and new WR FSM (see TCR register description).
Use the API provided in fdelay_lib.h */
Use the API provided in fdelay_lib.h */
...
@@ -1325,11 +1350,11 @@ int fdelay_configure_sync(fdelay_device_t *dev, int mode)
...
@@ -1325,11 +1350,11 @@ int fdelay_configure_sync(fdelay_device_t *dev, int mode)
if
(
mode
==
FDELAY_SYNC_LOCAL
)
if
(
mode
==
FDELAY_SYNC_LOCAL
)
{
{
fd_writel
(
0
,
FD_REG_GCR
);
//
fd_writel(0, FD_REG_GCR);
fd_writel
(
0
,
FD_REG_TCR
);
fd_writel
(
0
,
FD_REG_TCR
);
hw
->
wr_enabled
=
0
;
hw
->
wr_enabled
=
0
;
}
else
{
}
else
{
fd_writel
(
0
,
FD_REG_GCR
);
//
fd_writel(0, FD_REG_GCR);
fd_writel
(
FD_TCR_WR_ENABLE
,
FD_REG_TCR
);
fd_writel
(
FD_TCR_WR_ENABLE
,
FD_REG_TCR
);
hw
->
wr_enabled
=
1
;
hw
->
wr_enabled
=
1
;
}
}
...
@@ -1339,7 +1364,7 @@ int fdelay_check_sync(fdelay_device_t *dev)
...
@@ -1339,7 +1364,7 @@ int fdelay_check_sync(fdelay_device_t *dev)
{
{
fd_decl_private
(
dev
)
fd_decl_private
(
dev
)
fprintf
(
stderr
,
"TCR %x
\n
"
,
fd_readl
(
FD_REG_TCR
)
&
FD_TCR_WR_LOCKED
);
//
fprintf(stderr, "TCR %x\n", fd_readl(FD_REG_TCR) & FD_TCR_WR_LOCKED);
if
(
hw
->
wr_enabled
&&
(
fd_readl
(
FD_REG_TCR
)
&
FD_TCR_WR_LOCKED
))
if
(
hw
->
wr_enabled
&&
(
fd_readl
(
FD_REG_TCR
)
&
FD_TCR_WR_LOCKED
))
return
1
;
return
1
;
...
...
software/lib/fdelay_pps_demo.c
View file @
605c84cc
...
@@ -9,16 +9,22 @@ main(int argc, char *argv[])
...
@@ -9,16 +9,22 @@ main(int argc, char *argv[])
fdelay_device_t
dev
;
fdelay_device_t
dev
;
fdelay_time_t
t_cur
,
t_start
;
fdelay_time_t
t_cur
,
t_start
;
if
(
spec_fdelay_init
(
argc
,
argv
,
&
dev
)
<
0
)
if
(
spec_fdelay_init
(
&
dev
,
5
,
0
)
<
0
)
return
-
1
;
return
-
1
;
// Get the current time of the FD core - and program the card to start producing the PPS and 10 MHz one second later */
// Get the current time of the FD core - and program the card to start producing the PPS and 10 MHz one second later */
fdelay_get_time
(
&
dev
,
&
t_cur
);
t_cur
.
utc
=
0
;
t_cur
.
coarse
=
0
;
printf
(
"Current Time: %lld:%d
\n
"
,
t_cur
.
utc
,
t_cur
.
coarse
);
fdelay_configure_sync
(
&
dev
,
FDELAY_SYNC_LOCAL
);
fdelay_set_time
(
&
dev
,
t_cur
);
printf
(
"Current Time: %ld:%d
\n
"
,
t_cur
.
utc
,
t_cur
.
coarse
);
fdelay_get_time
(
&
dev
,
&
t_cur
);
printf
(
"Current Time: %ld:%d
\n
"
,
t_cur
.
utc
,
t_cur
.
coarse
);
t_start
.
coarse
=
0
;
//t_cur.coarse;
t_start
.
coarse
=
0
;
//t_cur.coarse;
t_start
.
utc
=
t_cur
.
utc
+
2
;
t_start
.
utc
=
t_cur
.
utc
+
3
;
t_start
.
frac
=
0
;
t_start
.
frac
=
0
;
fdelay_configure_pulse_gen
(
&
dev
,
1
,
1
,
t_start
,
48000LL
,
100000LL
,
-
1
);
/* Output 1, period = 100 ns, width = 48 ns - a bit asymmetric 10 MHz */
fdelay_configure_pulse_gen
(
&
dev
,
1
,
1
,
t_start
,
48000LL
,
100000LL
,
-
1
);
/* Output 1, period = 100 ns, width = 48 ns - a bit asymmetric 10 MHz */
...
...
software/lib/fdelay_test.c
View file @
605c84cc
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
#include "fdelay_lib.h"
#include "fdelay_lib.h"
#include "rr_io.h"
#include "rr_io.h"
extern
int
spec_fdelay_init
(
int
argc
,
char
*
argv
[],
fdelay_device_t
*
dev
);
extern
int
spec_fdelay_init
(
fdelay_device_t
*
dev
,
int
pbus
,
int
p
dev
);
main
(
int
argc
,
char
*
argv
[])
main
(
int
argc
,
char
*
argv
[])
{
{
...
@@ -11,12 +11,14 @@ main(int argc, char *argv[])
...
@@ -11,12 +11,14 @@ main(int argc, char *argv[])
fdelay_time_t
t
;
fdelay_time_t
t
;
/* Initialize the fine delay generator */
/* Initialize the fine delay generator */
if
(
spec_fdelay_init
(
argc
,
argv
,
&
dev
)
<
0
)
if
(
spec_fdelay_init
(
&
dev
,
0x05
,
0x00
)
<
0
)
{
{
fdelay_show_test_results
();
//
fdelay_show_test_results();
return
-
1
;
return
-
1
;
}
}
return
0
;
/* Enable trigger input and 50 ohm termination */
/* Enable trigger input and 50 ohm termination */
/* Enable all outputs and set them to 500 ns delay, 100 ns pulse width, single output pulse per trigger */
/* Enable all outputs and set them to 500 ns delay, 100 ns pulse width, single output pulse per trigger */
...
...
software/lib/pp.conf
0 → 100755
View file @
605c84cc
#BIG WARNING: the offsets in this file are for the hacked version of fdelay-gs, which uses fdelay test program instead of the real driver.
# use with caution!
#Path to the timestamp log file
log_file
./
pp
.
log
#######################
# Select board 0
#######################
board
0
# Hardware index if the board (i.e. the PCIe bus/dev)
hw_index
0
x0b00
# Select termination (warning! affects the accuracy!)
termination
1
# WARNING!!! These are fine delay card calibration values, obtained with time interval measurements.
# Don't change unless you know what you are doing.
# WARNING 2: define these for ALL boards independently
input_offset
-
65100
p
output_offset
15400
p
# Output configuration
# out output_ID offset_from_pps[ps] width[ps] period[ps]
# out 1 = PPS signal, 1us pulse width
out
1
0
1
u
1
s
# out 2 = 10 Hz, 50% duty cycle
out
2
0
50
m
100
m
# out 3 = 2 kHz
out
3
0
250
u
500
u
# out 4 = 10 MHz
#out 4 0 48n 100n
# #######################
# # Select board 1
# #######################
#
board
1
hw_index
0
x0500
input_offset
-
65100
p
output_offset
15400
p
termination
1
# out 1 = PPS signal, 1us pulse width
out
1
0
1
u
1
s
# out 2 = 10 Hz, 50% duty cycle
out
2
0
50
m
100
m
# out 3 = 2 kHz
out
3
0
250
u
500
u
# out 4 = 10 MHz
#out 4 0 48n 100n
software/lib/spec_common.c
View file @
605c84cc
#include <stdio.h>
#include <stdio.h>
#include <unistd.h>
#include <unistd.h>
#include <string.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "fdelay_lib.h"
#include "fdelay_lib.h"
#include "rr_io.h"
void
spec_writel
(
void
*
priv
,
uint32_t
data
,
uint32_t
addr
)
void
spec_writel
(
void
*
priv
,
uint32_t
data
,
uint32_t
addr
)
{
{
rr_writel
(
data
,
addr
);
*
(
volatile
uint32_t
*
)(
priv
+
addr
)
=
data
;
}
}
uint32_t
spec_readl
(
void
*
priv
,
uint32_t
addr
)
uint32_t
spec_readl
(
void
*
priv
,
uint32_t
addr
)
{
{
uint32_t
d
=
rr_readl
(
addr
);
return
*
(
volatile
uint32_t
*
)(
priv
+
addr
);
return
d
;
}
}
int
spec_fdelay_init
(
int
argc
,
char
*
argv
[],
fdelay_device_t
*
dev
)
void
*
map_spec
(
int
bus
,
int
dev
)
{
{
int
bus
=
RR_DEVSEL_UNUSED
,
devfn
=
RR_DEVSEL_UNUSED
;
char
path
[
1024
];
int
opt
=
0
;
int
fd
;
char
fw_name
[
1024
];
void
*
ptr
;
uint64_t
base
;
snprintf
(
path
,
sizeof
(
path
),
"/sys/bus/pci/drivers/spec/0000:%02x:%02x.0/resource"
,
bus
,
dev
);
FILE
*
f
=
fopen
(
path
,
"r"
);
fscanf
(
f
,
"0x%llx"
,
&
base
);
printf
(
"raw base addr: %llx
\n
"
,
base
);
fd
=
open
(
"/dev/mem"
,
O_SYNC
|
O_RDWR
);
if
(
fd
<=
0
)
{
perror
(
"open"
);
return
NULL
;
}
ptr
=
mmap
(
NULL
,
0x100000
,
PROT_READ
|
PROT_WRITE
,
MAP_SHARED
,
fd
,
(
void
*
)
base
);
strcpy
(
fw_name
,
"spec_top.bin"
);
if
((
int
)
ptr
==
-
1
)
while
((
opt
=
getopt
(
argc
,
argv
,
"hb:d:f:"
))
!=
-
1
)
{
{
switch
(
opt
)
{
perror
(
"mmap"
);
case
'h'
:
close
(
fd
);
printf
(
"Usage: %s [-b PCI_bus] [-d PCI dev/func] [-f firmware file]
\n
"
,
argv
[
0
]);
return
NULL
;
printf
(
"By default, the first detected SPEC is initialized with 'spec_top.bin' firmware
\n
"
);
}
return
0
;
case
'b'
:
return
ptr
;
sscanf
(
optarg
,
"%x"
,
&
bus
);
}
break
;
case
'd'
:
sscanf
(
optarg
,
"%x"
,
&
devfn
);
break
;
case
'f'
:
strcpy
(
fw_name
,
optarg
);
break
;
}
}
if
(
rr_init
(
bus
,
devfn
)
<
0
)
int
spec_fdelay_init
(
fdelay_device_t
*
dev
,
int
pbus
,
int
pdev
)
{
dev
->
priv_io
=
map_spec
(
pbus
,
pdev
);
if
(
!
dev
->
priv_io
)
{
{
fprintf
(
stderr
,
"Failed to initialize rawrabbit.
\n
"
);
fprintf
(
stderr
,
"Can't map the SPEC @ %x:%x
\n
"
,
pbus
,
pdev
);
return
-
1
;
return
-
1
;
}
}
dev
->
writel
=
spec_writel
;
dev
->
writel
=
spec_writel
;
dev
->
readl
=
spec_readl
;
dev
->
readl
=
spec_readl
;
dev
->
base_addr
=
0x80000
;
dev
->
base_addr
=
0x80000
;
/* if(rr_load_bitstream_from_file(fw_name) < 0)
{
fprintf(stderr,"Failed to load FPGA bitstream.\n");
return -1;
}*/
if
(
fdelay_init
(
dev
)
<
0
)
if
(
fdelay_init
(
dev
)
<
0
)
return
-
1
;
return
-
1
;
...
...
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