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
ec8b2e68
Commit
ec8b2e68
authored
May 22, 2012
by
Tomasz Wlostowski
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of ohwr.org:fmc-projects/fmc-delay-1ns-8cha
parents
3bb91660
4b397849
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
777 additions
and
100 deletions
+777
-100
fd_main_regs.h
software/include/fd_main_regs.h
+15
-1
fdelay_lib.h
software/include/fdelay_lib.h
+15
-1
fdelay_private.h
software/include/fdelay_private.h
+3
-0
Makefile
software/lib/Makefile
+5
-13
fdelay-gs.c
software/lib/fdelay-gs.c
+485
-0
fdelay_lib.c
software/lib/fdelay_lib.c
+143
-36
fdelay_pps_demo.c
software/lib/fdelay_pps_demo.c
+14
-8
fdelay_test.c
software/lib/fdelay_test.c
+5
-3
pp.conf
software/lib/pp.conf
+48
-0
spec_common.c
software/lib/spec_common.c
+42
-36
fdelay_lib.py
software/python/fdelay_lib.py
+2
-2
No files found.
software/include/fd_main_regs.h
View file @
ec8b2e68
...
...
@@ -3,7 +3,7 @@
* File : fd_main_regs.h
* Author : auto-generated by wbgen2 from fd_main_wishbone_slave.wb
* Created :
Wed Apr 11 11:05:22
2012
* Created :
Mon May 21 20:09:50
2012
* Standard : ANSI C
THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE fd_main_wishbone_slave.wb
...
...
@@ -274,6 +274,9 @@
#define FD_TSBCR_COUNT_W(value) WBGEN2_GEN_WRITE(value, 10, 12)
#define FD_TSBCR_COUNT_R(reg) WBGEN2_GEN_READ(reg, 10, 12)
/* definitions for field: RAW readout mode enable in reg: Timestamp Buffer Control Register */
#define FD_TSBCR_RAW WBGEN2_GEN_MASK(22, 1)
/* definitions for register: Timestamp Buffer Interrupt Register */
/* definitions for field: IRQ timeout [milliseconds] in reg: Timestamp Buffer Interrupt Register */
...
...
@@ -344,6 +347,13 @@
#define FD_TDER2_PELT_DRIVE_W(value) WBGEN2_GEN_WRITE(value, 0, 32)
#define FD_TDER2_PELT_DRIVE_R(reg) WBGEN2_GEN_READ(reg, 0, 32)
/* definitions for register: Timestamp Buffer Debug Values Register */
/* definitions for register: Timestamp Buffer Advance Register */
/* definitions for field: Advance buffer readout in reg: Timestamp Buffer Advance Register */
#define FD_TSBR_ADVANCE_ADV WBGEN2_GEN_MASK(0, 1)
/* definitions for register: Interrupt disable register */
/* definitions for field: TS Buffer not empty. in reg: Interrupt disable register */
...
...
@@ -445,6 +455,10 @@
#define FD_REG_TDER1 0x0000006c
/* [0x70]: REG Test/Debug register 1 */
#define FD_REG_TDER2 0x00000070
/* [0x74]: REG Timestamp Buffer Debug Values Register */
#define FD_REG_TSBR_DEBUG 0x00000074
/* [0x78]: REG Timestamp Buffer Advance Register */
#define FD_REG_TSBR_ADVANCE 0x00000078
/* [0x80]: REG Interrupt disable register */
#define FD_REG_EIC_IDR 0x00000080
/* [0x84]: REG Interrupt enable register */
...
...
software/include/fdelay_lib.h
View file @
ec8b2e68
...
...
@@ -36,9 +36,19 @@ typedef struct fdelay_device
void
*
priv_io
;
/* pointer to the I/O routines private data */
}
fdelay_device_t
;
typedef
struct
{
int64_t
utc
,
utc_sh
;
int32_t
coarse
,
coarse_sh
;
int32_t
start_offset
;
int32_t
subcycle_offset
;
int32_t
frac
;
}
fdelay_raw_time_t
;
typedef
struct
{
int32_t
utc
;
/* TAI seconds */
/* FIXME: replace all UTCs with TAIs or seconds for clarity */
fdelay_raw_time_t
raw
;
int64_t
utc
;
/* TAI seconds */
/* FIXME: replace all UTCs with TAIs or seconds for clarity */
int32_t
coarse
;
/* 125 MHz counter cycles */
int32_t
frac
;
/* Fractional part (<8ns) */
uint16_t
seq_id
;
/* Sequence ID to detect missed timestamps */
...
...
@@ -113,5 +123,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 */
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
software/include/fdelay_private.h
View file @
ec8b2e68
...
...
@@ -20,6 +20,7 @@
#define CS_DAC 0
/* AD9516 PLL */
#define CS_PLL 1
/* AD9516 PLL */
#define CS_GPIO 2
/* MCP23S17 GPIO */
#define CS_NONE 3
/* MCP23S17 GPIO expander pin locations: bit 8 = select bank 2, bits 7..0 = mask of the pin in the selected bank */
#define SGPIO_TERM_EN (1<<0)
/* Input termination enable (1 = on) */
...
...
@@ -84,7 +85,9 @@ struct fine_delay_hw
int32_t
board_temp
;
/* Current temperature of the board, unit = 1/16 degC */
int
wr_enabled
;
int
wr_state
;
int
raw_mode
;
struct
fine_delay_calibration
calib
;
int64_t
input_user_offset
,
output_user_offset
;
};
/* some useful access/declaration macros */
...
...
software/lib/Makefile
View file @
ec8b2e68
...
...
@@ -3,24 +3,16 @@ CFLAGS = -I../include -g -Imini_bone -Ispll
#uncomment for extra tests (DAC, output stage INL/DNL)
#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)
gcc
-shared
-o
libfinedelay.so
$(OBJS_LIB)
testprog
:
lib fdelay_test.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
testprog
:
lib fdelay_pps_demo.o
gcc
-o
fdelay_pps_demo
$(OBJS_LIB)
fdelay_pps_demo.o
-lm
testprog4
:
lib fdelay_eeprom
.o
gcc
-o
fdelay
_eeprom
$(OBJS_LIB)
fdelay_eeprom
.o
-lm
gs
:
lib fdelay-gs
.o
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 @
ec8b2e68
/* 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_wr
(
fdelay_device_t
*
b
,
int
index
)
{
int
lock_retries
=
50
;
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
);
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] "
,
bdef
->
hw_index
,
t
.
seq_id
,
t
.
utc
,
t_ps
/
1000LL
,
t_ps
%
1000LL
,
t
.
coarse
);
printf
(
"raw utc=%lld coarse=%d startoffs=%d suboffs=%d frac=%d [%x]
\n
"
,
t
.
raw
.
utc
,
t
.
raw
.
coarse
,
t
.
raw
.
start_offset
,
t
.
raw
.
subcycle_offset
,
t
.
raw
.
frac
-
30000
,
t
.
raw
.
frac
);
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
fdelay_dbg_sync_lost
(
fdelay_device_t
*
dev
);
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
(
i
=
0
;
i
<
MAX_BOARDS
;
i
++
)
if
(
boards
[
i
].
in_use
)
{
int
fd
;
fdelay_configure_readout
(
boards
[
i
].
b
,
1
);
fdelay_configure_trigger
(
boards
[
i
].
b
,
1
,
boards
[
i
].
term_on
);
}
for
(;;)
{
for
(
i
=
0
;
i
<
MAX_BOARDS
;
i
++
)
{
if
(
!
boards
[
i
].
in_use
)
continue
;
// printf(".");
handle_readout
(
&
boards
[
i
]);
if
(
fdelay_dbg_sync_lost
(
boards
[
i
].
b
))
{
printf
(
"Weird, sync lost @ board %x. Reconfiguring...
\n
"
,
boards
[
i
].
b
);
configure_board
(
&
boards
[
i
]);
}
}
usleep
(
100
);
}
}
software/lib/fdelay_lib.c
View file @
ec8b2e68
This diff is collapsed.
Click to expand it.
software/lib/fdelay_pps_demo.c
View file @
ec8b2e68
...
...
@@ -9,22 +9,28 @@ main(int argc, char *argv[])
fdelay_device_t
dev
;
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
;
// 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
);
printf
(
"Current Time: %lld:%d
\n
"
,
t_cur
.
utc
,
t_cur
.
coarse
);
t_cur
.
utc
=
0
;
t_cur
.
coarse
=
0
;
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
=
t_cur
.
coarse
;
t_start
.
utc
=
t_cur
.
utc
+
1
;
t_start
.
coarse
=
0
;
//
t_cur.coarse;
t_start
.
utc
=
t_cur
.
utc
+
3
;
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
,
2
,
1
,
t_start
,
48000
LL
,
1000000000000LL
,
-
1
);
/* Output 2: period = 1 second, width = 48 ns - PPS signal */
fdelay_configure_pulse_gen
(
&
dev
,
2
,
1
,
t_start
,
1000000000000LL
/
2
LL
,
1000000000000LL
,
-
1
);
/* Output 2: period = 1 second, width = 48 ns - PPS signal */
while
(
!
fdelay_channel_triggered
(
&
dev
,
1
)
||
fdelay_channel_triggered
(
&
dev
,
2
))
while
(
!
fdelay_channel_triggered
(
&
dev
,
1
)
||
!
fdelay_channel_triggered
(
&
dev
,
2
))
usleep
(
10000
);
/* wait until both outputs have triggered*/
;
return
0
;
}
software/lib/fdelay_test.c
View file @
ec8b2e68
...
...
@@ -3,7 +3,7 @@
#include "fdelay_lib.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
[])
{
...
...
@@ -11,12 +11,14 @@ main(int argc, char *argv[])
fdelay_time_t
t
;
/* 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
0
;
/* 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 */
...
...
software/lib/pp.conf
0 → 100755
View file @
ec8b2e68
#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
0
# 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
-
69100
p
output_offset
20400
p
# Output configuration
# out output_ID offset_from_pps[ps] width[ps] period[ps]
# out 1 = PPS signal, 1us pulse width
out
1
0
500
u
1000
u
out
2
0
500
u
1000
u
out
4
0
500
u
1000
u
out
3
0
250
u
499999990
p
# #######################
# # Select board 1
# #######################
#
board
1
hw_index
0
x0500
input_offset
-
69100
p
output_offset
20400
p
termination
0
out
1
0
500
u
1000
u
out
2
0
500
u
1000
u
out
4
0
500
u
1000
u
out
3
0
250
u
499999990
p
software/lib/spec_common.c
View file @
ec8b2e68
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "fdelay_lib.h"
#include "rr_io.h"
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
d
=
rr_readl
(
addr
);
return
d
;
return
*
(
volatile
uint32_t
*
)(
priv
+
addr
);
}
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
;
int
opt
=
0
;
char
fw_name
[
1024
];
char
path
[
1024
];
int
fd
;
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"
);
while
((
opt
=
getopt
(
argc
,
argv
,
"hb:d:f:"
))
!=
-
1
)
{
switch
(
opt
)
{
case
'h'
:
printf
(
"Usage: %s [-b PCI_bus] [-d PCI dev/func] [-f firmware file]
\n
"
,
argv
[
0
]);
printf
(
"By default, the first detected SPEC is initialized with 'spec_top.bin' firmware
\n
"
);
return
0
;
case
'b'
:
sscanf
(
optarg
,
"%x"
,
&
bus
);
break
;
case
'd'
:
sscanf
(
optarg
,
"%x"
,
&
devfn
);
break
;
case
'f'
:
strcpy
(
fw_name
,
optarg
);
break
;
}
}
if
((
int
)
ptr
==
-
1
)
{
perror
(
"mmap"
);
close
(
fd
);
return
NULL
;
}
return
ptr
;
}
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
"
);
return
-
1
;
fprintf
(
stderr
,
"Can't map the SPEC @ %x:%x
\n
"
,
pbus
,
pdev
);
return
-
1
;
}
dev
->
writel
=
spec_writel
;
dev
->
readl
=
spec_readl
;
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
)
return
-
1
;
...
...
software/python/fdelay_lib.py
View file @
ec8b2e68
...
...
@@ -23,7 +23,7 @@ class fd_timestamp(Structure):
class
FineDelay
:
BASE_ADDR
=
0x8
4
000
BASE_ADDR
=
0x8
0
000
FREE_RUNNING
=
0x10
WR_OFFLINE
=
0x8
...
...
@@ -39,7 +39,7 @@ class FineDelay:
self
.
handle
=
c_voidp
(
self
.
fdelay
.
fdelay_create_rawrabbit
(
c_int
(
fd
),
c_ulong
(
self
.
BASE_ADDR
)));
if
(
c_int
(
self
.
fdelay
.
fdelay_load_firmware
(
"
spec_top
.bin"
))
<
0
):
if
(
c_int
(
self
.
fdelay
.
fdelay_load_firmware
(
"
../spec_top_wr
.bin"
))
<
0
):
print
(
"Firmware loader failed..."
);
sys
.
exit
(
-
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