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
f99f8986
Commit
f99f8986
authored
Dec 13, 2018
by
Tristan Gingold
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fw/adc: renaming.
parent
2a853764
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
223 additions
and
218 deletions
+223
-218
out_queue.h
software/firmware/adc/out_queue.h
+1
-0
wrtd-adcin.c
software/firmware/adc/wrtd-adcin.c
+62
-156
wrtd-adcout.c
software/firmware/adc/wrtd-adcout.c
+159
-61
wrtd-common.h
software/include/wrtd-common.h
+1
-1
No files found.
software/firmware/adc/out_queue.h
View file @
f99f8986
...
...
@@ -126,3 +126,4 @@ static int OUT_QUEUE_NAME(out_queue_check_timeout) (struct OUT_QUEUE_STRUCT *q)
#undef OUT_QUEUE_STRUCT
#undef OUT_QUEUE_NAME
#undef OUT_QUEUE_CONCAT
#undef OUT_QUEUE_CONCAT2
software/firmware/adc/wrtd-adcin.c
View file @
f99f8986
/*
* Copyright (C) 2013-2018 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* Copyright (C) 2018 CERN (www.cern.ch)
* Author: Dimitris Lampridis <dimitris.lampridis@cern.ch>
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#include <errno.h>
#include <string.h>
/* ADCIN: trigger coming from the ADC mezzanine. */
#include "mockturtle-rt.h"
#include <mockturtle-framework.h>
#include "wrtd-common.h"
#include "fmc_adc_alt_trigin.h"
#define OUT_QUEUE_MAXTIME 10
#define OUT_QUEUE_PREFIX adcin_
#define OUT_QUEUE_SIZE 4
#include "out_queue.h"
#define ADCIN_NUM_CHANNELS 5
struct
wrtd_adcin_dev
{
uint32_t
io_addr
;
int
idle
;
struct
adcin_out_queue
queue
;
/* FIXME: base channel (to create the event id). */
};
static
inline
int
adcin_wr_present
(
struct
wrtd_adcin_dev
*
fd
)
static
inline
void
adcin_writel
(
const
struct
wrtd_adcin_dev
*
dev
,
uint32_t
value
,
uint32_t
reg
)
{
return
1
;
dp_writel
(
value
,
dev
->
io_addr
+
reg
)
;
}
static
inline
int
adcin_wr_link_up
(
struct
wrtd_adcin_dev
*
fd
)
static
inline
uint32_t
adcin_readl
(
const
struct
wrtd_adcin_dev
*
dev
,
uint32_t
reg
)
{
return
1
;
return
dp_readl
(
dev
->
io_addr
+
reg
)
;
}
static
in
line
int
adcin_wr_time_locked
(
struct
wrtd_adcin_dev
*
fd
)
static
in
t
adcin_init
(
struct
wrtd_adcin_dev
*
adcin
)
{
return
1
;
}
pr_debug
(
"%s: Adcin initialization complete
\n\r
"
,
__func__
);
static
inline
int
adcin_wr_time_ready
(
struct
wrtd_adcin_dev
*
fd
)
{
return
1
;
}
/* Disable all channels. */
adcin_writel
(
adcin
,
0
,
ALT_TRIGOUT_CTRL
);
static
inline
int
adcin_wr_sync_timeout
(
void
)
{
return
0
;
}
static
void
adcin_wr_enable_lock
(
struct
wrtd_adcin_dev
*
fd
,
int
enable
)
{
return
;
}
static
inline
void
adcin_writel
(
struct
wrtd_adcin_dev
*
dev
,
uint32_t
value
,
uint32_t
reg
)
static
inline
int
adcin_wr_link_up
(
struct
wrtd_adcin_dev
*
adcin
)
{
dp_writel
(
value
,
dev
->
io_addr
+
reg
)
;
return
adcin_readl
(
adcin
,
ALT_TRIGOUT_STATUS
)
&
ALT_TRIGOUT_WR_LINK
;
}
static
inline
uint32_t
adcin_readl
(
struct
wrtd_adcin_dev
*
dev
,
uint32_t
reg
)
static
inline
int
adcin_wr_time_locked
(
struct
wrtd_adcin_dev
*
adcin
)
{
return
dp_readl
(
dev
->
io_addr
+
reg
)
;
return
1
;
}
/**
* Drop the given enqueued trigger
*/
static
void
adcin_drop_trigger
(
struct
wrtd_adcin_dev
*
dev
,
struct
wrtd_event
*
ev
,
unsigned
reason
)
static
void
adcin_wr_enable_lock
(
struct
wrtd_adcin_dev
*
dev
,
int
enable
)
{
struct
adcin_out_queue
*
q
=
&
dev
->
queue
;
dev
->
idle
=
1
;
if
(
adcin_out_queue_empty
(
q
))
return
;
/* Drop the pulse */
adcin_out_queue_pop
(
q
);
/* Disarm the FD output */
adcin_writel
(
dev
,
0
,
ALT_TRIGIN_CTRL
);
wrtd_log
(
WRTD_LOG_MSG_EV_DISCARDED
,
reason
,
ev
,
NULL
);
return
;
}
/**
* Output driving function. Reads pulses from the output queue,
* programs the output and updates the output statistics.
*/
static
void
adcin_output
(
struct
wrtd_adcin_dev
*
dev
)
static
inline
int
adcin_wr_time_ready
(
struct
wrtd_adcin_dev
*
adcin
)
{
struct
adcin_out_queue
*
q
=
&
dev
->
queue
;
struct
wrtd_event
*
ev
=
adcin_out_queue_front
(
q
);
uint32_t
ctrl
=
adcin_readl
(
dev
,
ALT_TRIGIN_CTRL
);
struct
wrtd_tstamp
*
ts
;
/* Check if the output has triggered */
if
(
!
dev
->
idle
)
{
#if 0
if (!wr_is_timing_ok()) {
/* Timing has been lost. */
drop_trigger(out, ev, q, WRTD_LOG_DISCARD_NO_SYNC);
return;
}
#endif
if
(
ctrl
&
ALT_TRIGIN_CTRL_ENABLE
)
{
/* Armed but still waiting for trigger */
if
(
adcin_out_queue_check_timeout
(
q
))
{
/* Will never trigger. Missed. */
adcin_drop_trigger
(
dev
,
ev
,
WRTD_LOG_DISCARD_TIMEOUT
);
}
}
else
{
/* Has been triggered. */
wrtd_log
(
WRTD_LOG_MSG_EV_CONSUMED
,
WRTD_LOG_CONSUMED_DONE
,
ev
,
NULL
);
adcin_out_queue_pop
(
q
);
dev
->
idle
=
1
;
}
return
;
}
/* Output is idle: check if there's something in the queue to execute */
if
(
adcin_out_queue_empty
(
q
))
return
;
ev
=
adcin_out_queue_front
(
q
);
ts
=
&
ev
->
ts
;
if
(
!
wr_is_timing_ok
())
{
adcin_drop_trigger
(
dev
,
ev
,
WRTD_LOG_DISCARD_NO_SYNC
);
return
;
}
/* Program the output start time */
adcin_writel
(
dev
,
ts
->
seconds
,
ALT_TRIGIN_SECONDS
+
0
);
adcin_writel
(
dev
,
ts
->
ns
/
8
,
ALT_TRIGIN_CYCLES
);
adcin_writel
(
dev
,
ALT_TRIGIN_CTRL_ENABLE
,
ALT_TRIGIN_CTRL
);
wrtd_log
(
WRTD_LOG_MSG_EV_CONSUMED
,
WRTD_LOG_CONSUMED_START
,
ev
,
NULL
);
ts_add2_ns
(
ts
,
8000
);
/*
* Store the last programmed timestamp (+ some margin) and mark
* the output as busy
*/
q
->
last_programmed_sec
=
ts
->
seconds
;
q
->
last_programmed_ns
=
ts
->
ns
;
dev
->
idle
=
0
;
return
adcin_readl
(
adcin
,
ALT_TRIGOUT_STATUS
)
&
ALT_TRIGOUT_WR_VALID
;
}
static
void
adcin_local_output
(
struct
wrtd_adcin_dev
*
dev
,
struct
wrtd_event
*
ev
,
unsigned
ch
)
static
inline
int
adcin_wr_sync_timeout
(
void
)
{
struct
wrtd_event
*
pq_ev
;
pq_ev
=
adcin_out_queue_push
(
&
dev
->
queue
);
if
(
!
pq_ev
)
{
/* overflow.
FIXME: stats ? */
wrtd_log
(
WRTD_LOG_MSG_EV_DISCARDED
,
WRTD_LOG_DISCARD_OVERFLOW
,
ev
,
NULL
);
return
;
}
*
pq_ev
=
*
ev
;
return
0
;
}
#if 0
/**
* It disable the given channel and clear its internal queue
* Handles input timestamps from all TDC channels.
*
* TODO: tdc config: base address
* first channel number (for sid)
* time offset
*/
static int wrtd_out_disable(struct trtl_fw_msg *msg_i,
struct trtl_fw_msg *msg_o)
{
uint32_t ch = ((uint32_t *)msg_i->payload)[0];
pulse_queue_init(&wrtd_out_channels[ch].queue);
fd_ch_writel(&wrtd_out_channels[ch], FD_DCR_MODE, FD_REG_DCR);
msg_o->header->msg_id = msg_i->header->msg_id;
return 0;
}
#endif
static
void
adcin_data_init
(
struct
wrtd_adcin_dev
*
dev
)
static
void
adcin_input
(
struct
wrtd_adcin_dev
*
adcin
)
{
adcin_out_queue_init
(
&
dev
->
queue
);
dev
->
idle
=
1
;
uint32_t
status
=
adcin_readl
(
adcin
,
ALT_TRIGOUT_STATUS
);
uint32_t
mask
;
struct
wrtd_event
ev
;
int
i
;
/* Poll the FIFO and read the timestamp */
if
(
!
(
status
&
ALT_TRIGOUT_TS_PRESENT
))
return
;
/* FIXME: MSB word ? */
ev
.
ts
.
seconds
=
adcin_readl
(
adcin
,
ALT_TRIGOUT_TS_MASK_SEC
+
0
);
mask
=
adcin_readl
(
adcin
,
ALT_TRIGOUT_TS_MASK_SEC
+
4
);
ev
.
ts
.
ns
=
adcin_readl
(
adcin
,
ALT_TRIGOUT_TS_CYCLES
)
*
8
;
ev
.
ts
.
frac
=
0
;
for
(
i
=
0
;
i
<
ADCIN_NUM_CHANNELS
;
i
++
)
{
if
(
!
(
mask
&
((
ALT_TRIGOUT_CH1_MASK
>>
32
)
<<
i
)))
continue
;
memset
(
ev
.
id
,
0
,
WRTD_ID_LEN
);
ev
.
id
[
0
]
=
'A'
;
ev
.
id
[
1
]
=
'D'
;
ev
.
id
[
2
]
=
'C'
;
ev
.
id
[
3
]
=
'I'
;
ev
.
id
[
4
]
=
'1'
+
i
;
ev
.
flags
=
0
;
wrtd_log
(
WRTD_LOG_MSG_EV_GENERATED
,
WRTD_LOG_GENERATED_DEVICE
+
i
,
&
ev
,
NULL
);
/* Pass to wrtd. */
wrtd_route_in
(
&
ev
);
}
}
software/firmware/adc/wrtd-adcout.c
View file @
f99f8986
/*
* Copyright (C) 2018 CERN (www.cern.ch)
* Author: Dimitris Lampridis <dimitris.lampridis@cern.ch>
* Copyright (C) 2013-2018 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
/* ADCout: trigger ADC sampling. Output from the WRTD pov. */
#include <errno.h>
#include <string.h>
#include "mockturtle-rt.h"
#include <mockturtle-framework.h>
#include "wrtd-common.h"
#include "fmc_adc_alt_trigin.h"
#define ADCOUT_NUM_CHANNELS 5
#define OUT_QUEUE_MAXTIME 10
#define OUT_QUEUE_PREFIX adcout_
#define OUT_QUEUE_SIZE 4
#include "out_queue.h"
struct
wrtd_adcout_dev
{
uint32_t
io_addr
;
/* FIXME: base channel (to create the event id). */
int
idle
;
struct
adcout_out_queue
queue
;
};
static
inline
void
adcout_writel
(
const
struct
wrtd_adcout_dev
*
dev
,
uint32_t
value
,
uint32_t
reg
)
static
inline
int
adcout_wr_present
(
struct
wrtd_adcout_dev
*
fd
)
{
dp_writel
(
value
,
dev
->
io_addr
+
reg
)
;
return
1
;
}
static
inline
uint32_t
adcout_readl
(
const
struct
wrtd_adcout_dev
*
dev
,
uint32_t
reg
)
static
inline
int
adcout_wr_link_up
(
struct
wrtd_adcout_dev
*
fd
)
{
return
dp_readl
(
dev
->
io_addr
+
reg
)
;
return
1
;
}
static
in
t
adcout_init
(
struct
wrtd_adcout_dev
*
adcout
)
static
in
line
int
adcout_wr_time_locked
(
struct
wrtd_adcout_dev
*
fd
)
{
pr_debug
(
"%s: ADCout initialization complete
\n\r
"
,
__func__
);
return
1
;
}
/* Disable all channels. */
adcout_writel
(
adcout
,
0
,
ALT_TRIGOUT_CTRL
);
static
inline
int
adcout_wr_time_ready
(
struct
wrtd_adcout_dev
*
fd
)
{
return
1
;
}
static
inline
int
adcout_wr_sync_timeout
(
void
)
{
return
0
;
}
static
inline
int
adcout_wr_link_up
(
struct
wrtd_adcout_dev
*
adcout
)
static
void
adcout_wr_enable_lock
(
struct
wrtd_adcout_dev
*
fd
,
int
enable
)
{
return
adcout_readl
(
adcout
,
ALT_TRIGOUT_STATUS
)
&
ALT_TRIGOUT_WR_LINK
;
return
;
}
static
inline
int
adcout_wr_time_locked
(
struct
wrtd_adcout_dev
*
adcout
)
static
inline
void
adcout_writel
(
struct
wrtd_adcout_dev
*
dev
,
uint32_t
value
,
uint32_t
reg
)
{
return
1
;
dp_writel
(
value
,
dev
->
io_addr
+
reg
)
;
}
static
void
adcout_wr_enable_lock
(
struct
wrtd_adcout_dev
*
dev
,
int
enable
)
static
inline
uint32_t
adcout_readl
(
struct
wrtd_adcout_dev
*
dev
,
uint32_t
reg
)
{
return
;
return
dp_readl
(
dev
->
io_addr
+
reg
);
}
/**
* Drop the given enqueued trigger
*/
static
void
adcout_drop_trigger
(
struct
wrtd_adcout_dev
*
dev
,
struct
wrtd_event
*
ev
,
unsigned
reason
)
{
struct
adcout_out_queue
*
q
=
&
dev
->
queue
;
dev
->
idle
=
1
;
if
(
adcout_out_queue_empty
(
q
))
return
;
/* Drop the pulse */
adcout_out_queue_pop
(
q
);
/* Disarm the FD output */
adcout_writel
(
dev
,
0
,
ALT_TRIGIN_CTRL
);
wrtd_log
(
WRTD_LOG_MSG_EV_DISCARDED
,
reason
,
ev
,
NULL
);
}
static
inline
int
adcout_wr_time_ready
(
struct
wrtd_adcout_dev
*
adcout
)
/**
* Output driving function. Reads pulses from the output queue,
* programs the output and updates the output statistics.
*/
static
void
adcout_output
(
struct
wrtd_adcout_dev
*
dev
)
{
return
adcout_readl
(
adcout
,
ALT_TRIGOUT_STATUS
)
&
ALT_TRIGOUT_WR_VALID
;
struct
adcout_out_queue
*
q
=
&
dev
->
queue
;
struct
wrtd_event
*
ev
=
adcout_out_queue_front
(
q
);
uint32_t
ctrl
=
adcout_readl
(
dev
,
ALT_TRIGIN_CTRL
);
struct
wrtd_tstamp
*
ts
;
/* Check if the output has triggered */
if
(
!
dev
->
idle
)
{
#if 0
if (!wr_is_timing_ok()) {
/* Timing has been lost. */
drop_trigger(out, ev, q, WRTD_LOG_DISCARD_NO_SYNC);
return;
}
#endif
if
(
ctrl
&
ALT_TRIGIN_CTRL_ENABLE
)
{
/* Armed but still waiting for trigger */
if
(
adcout_out_queue_check_timeout
(
q
))
{
/* Will never trigger. Missed. */
adcout_drop_trigger
(
dev
,
ev
,
WRTD_LOG_DISCARD_TIMEOUT
);
}
}
else
{
/* Has been triggered. */
wrtd_log
(
WRTD_LOG_MSG_EV_CONSUMED
,
WRTD_LOG_CONSUMED_DONE
,
ev
,
NULL
);
adcout_out_queue_pop
(
q
);
dev
->
idle
=
1
;
}
return
;
}
/* Output is idle: check if there's something in the queue to execute */
if
(
adcout_out_queue_empty
(
q
))
return
;
ev
=
adcout_out_queue_front
(
q
);
ts
=
&
ev
->
ts
;
if
(
!
wr_is_timing_ok
())
{
adcout_drop_trigger
(
dev
,
ev
,
WRTD_LOG_DISCARD_NO_SYNC
);
return
;
}
/* Program the output start time */
adcout_writel
(
dev
,
ts
->
seconds
,
ALT_TRIGIN_SECONDS
+
0
);
adcout_writel
(
dev
,
ts
->
ns
/
8
,
ALT_TRIGIN_CYCLES
);
adcout_writel
(
dev
,
ALT_TRIGIN_CTRL_ENABLE
,
ALT_TRIGIN_CTRL
);
wrtd_log
(
WRTD_LOG_MSG_EV_CONSUMED
,
WRTD_LOG_CONSUMED_START
,
ev
,
NULL
);
ts_add2_ns
(
ts
,
8000
);
/*
* Store the last programmed timestamp (+ some margin) and mark
* the output as busy
*/
q
->
last_programmed_sec
=
ts
->
seconds
;
q
->
last_programmed_ns
=
ts
->
ns
;
dev
->
idle
=
0
;
}
static
inline
int
adcout_wr_sync_timeout
(
void
)
static
void
adcout_local_output
(
struct
wrtd_adcout_dev
*
dev
,
struct
wrtd_event
*
ev
,
unsigned
ch
)
{
return
0
;
struct
wrtd_event
*
pq_ev
;
pq_ev
=
adcout_out_queue_push
(
&
dev
->
queue
);
if
(
!
pq_ev
)
{
/* overflow.
FIXME: stats ? */
wrtd_log
(
WRTD_LOG_MSG_EV_DISCARDED
,
WRTD_LOG_DISCARD_OVERFLOW
,
ev
,
NULL
);
return
;
}
*
pq_ev
=
*
ev
;
}
#if 0
/**
* Handles input timestamps from all TDC channels.
*
* TODO: tdc config: base address
* first channel number (for sid)
* time offset
* It disable the given channel and clear its internal queue
*/
static
void
adcout_input
(
struct
wrtd_adcout_dev
*
adcout
)
static int wrtd_out_disable(struct trtl_fw_msg *msg_i,
struct trtl_fw_msg *msg_o)
{
uint32_t
status
=
adcout_readl
(
adcout
,
ALT_TRIGOUT_STATUS
);
uint32_t
mask
;
struct
wrtd_event
ev
;
int
i
;
/* Poll the FIFO and read the timestamp */
if
(
!
(
status
&
ALT_TRIGOUT_TS_PRESENT
))
return
;
/* FIXME: MSB word ? */
ev
.
ts
.
seconds
=
adcout_readl
(
adcout
,
ALT_TRIGOUT_TS_MASK_SEC
+
0
);
mask
=
adcout_readl
(
adcout
,
ALT_TRIGOUT_TS_MASK_SEC
+
4
);
ev
.
ts
.
ns
=
adcout_readl
(
adcout
,
ALT_TRIGOUT_TS_CYCLES
)
*
8
;
ev
.
ts
.
frac
=
0
;
for
(
i
=
0
;
i
<
ADCOUT_NUM_CHANNELS
;
i
++
)
{
if
(
!
(
mask
&
((
ALT_TRIGOUT_CH1_MASK
>>
32
)
<<
i
)))
continue
;
memset
(
ev
.
id
,
0
,
WRTD_ID_LEN
);
ev
.
id
[
0
]
=
'A'
;
ev
.
id
[
1
]
=
'D'
;
ev
.
id
[
2
]
=
'C'
;
ev
.
id
[
3
]
=
'O'
;
ev
.
id
[
4
]
=
'1'
+
i
;
ev
.
flags
=
0
;
wrtd_log
(
WRTD_LOG_MSG_EV_GENERATED
,
WRTD_LOG_GENERATED_DEVICE
+
i
,
&
ev
,
NULL
);
/* Pass to wrtd. */
wrtd_route_in
(
&
ev
);
}
uint32_t ch = ((uint32_t *)msg_i->payload)[0];
pulse_queue_init(&wrtd_out_channels[ch].queue);
fd_ch_writel(&wrtd_out_channels[ch], FD_DCR_MODE, FD_REG_DCR);
msg_o->header->msg_id = msg_i->header->msg_id;
return 0;
}
#endif
static
void
adcout_init
(
struct
wrtd_adcout_dev
*
dev
)
{
adcout_out_queue_init
(
&
dev
->
queue
);
dev
->
idle
=
1
;
}
software/include/wrtd-common.h
View file @
f99f8986
...
...
@@ -202,7 +202,7 @@ struct wrtd_io_msg {
#define WRTD_APP_TDC_5CH 0x35D0
#define WRTD_APP_FD_4CH 0x35E0
#define WRTD_APP_ADCI
N
_5CH 0x35B0
#define WRTD_APP_ADCI
O
_5CH 0x35B0
enum
wrtd_trtl_actions
{
/* Always the first one, to get root and version. */
...
...
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