Commit 9660ad52 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

wip: fixed TS readout, added support for hardware offset adjustment and HW delta…

wip: fixed TS readout, added support for hardware offset adjustment and HW delta timestamps (to be implemented in userland)
parent 82f87f34
...@@ -15,7 +15,7 @@ ccflags-y = -DGIT_VERSION=\"$(GIT_VERSION)\" \ ...@@ -15,7 +15,7 @@ ccflags-y = -DGIT_VERSION=\"$(GIT_VERSION)\" \
ccflags-$(CONFIG_FMC_TDC_DEBUG) += -DDEBUG ccflags-$(CONFIG_FMC_TDC_DEBUG) += -DDEBUG
ccflags-$(CONFIG_FMC_TDC_VERBOSE_DEBUG) += -DVERBOSE_DEBUG ccflags-$(CONFIG_FMC_TDC_VERBOSE_DEBUG) += -DVERBOSE_DEBUG
ccflags-y += -Werror #ccflags-y += -Werror
# Extract minimum com major, minor and patch number # Extract minimum com major, minor and patch number
ccflags-y += -D__ZIO_MIN_MAJOR_VERSION=$(shell echo $(ZIO_VERSION) | cut -d '-' -f 2 | cut -d '.' -f 1; ) ccflags-y += -D__ZIO_MIN_MAJOR_VERSION=$(shell echo $(ZIO_VERSION) | cut -d '-' -f 2 | cut -d '.' -f 1; )
......
...@@ -62,8 +62,6 @@ int ft_acam_init(struct fmctdc_dev *ft) ...@@ -62,8 +62,6 @@ int ft_acam_init(struct fmctdc_dev *ft)
int i; int i;
unsigned long tmo; unsigned long tmo;
dev_dbg(&ft->fmc->dev, "%s: initializing ACAM TDC...\n", __func__);
ft_writel(ft, TDC_CTRL_RESET_ACAM, TDC_REG_CTRL); ft_writel(ft, TDC_CTRL_RESET_ACAM, TDC_REG_CTRL);
udelay(100); udelay(100);
...@@ -85,8 +83,6 @@ int ft_acam_init(struct fmctdc_dev *ft) ...@@ -85,8 +83,6 @@ int ft_acam_init(struct fmctdc_dev *ft)
tmo = jiffies + 2 * HZ; tmo = jiffies + 2 * HZ;
while (time_before(jiffies, tmo)) { while (time_before(jiffies, tmo)) {
if (acam_is_pll_locked(ft)) { if (acam_is_pll_locked(ft)) {
dev_dbg(&ft->fmc->dev, "%s: ACAM initialization OK.\n",
__func__);
return 0; return 0;
} }
} }
......
...@@ -207,6 +207,7 @@ static inline u32 ft_ioread(struct fmctdc_dev *ft, unsigned long addr) ...@@ -207,6 +207,7 @@ static inline u32 ft_ioread(struct fmctdc_dev *ft, unsigned long addr)
static inline void ft_iowrite(struct fmctdc_dev *ft, static inline void ft_iowrite(struct fmctdc_dev *ft,
u32 value, unsigned long addr) u32 value, unsigned long addr)
{ {
// printk("ft_iowrite %x %x\n", addr, value );
fmc_writel(ft->fmc, value, addr); fmc_writel(ft->fmc, value, addr);
} }
...@@ -299,6 +300,12 @@ uint32_t ft_irq_coalescing_timeout_get(struct fmctdc_dev *ft, ...@@ -299,6 +300,12 @@ uint32_t ft_irq_coalescing_timeout_get(struct fmctdc_dev *ft,
int test_dma(struct fmctdc_dev *ft, unsigned int buf_size, int test_dma(struct fmctdc_dev *ft, unsigned int buf_size,
unsigned int use_sg); unsigned int use_sg);
void ft_set_delta_reference(struct fmctdc_dev *ft,
unsigned int chan, unsigned int ref);
uint32_t ft_get_delta_reference(struct fmctdc_dev *ft,
unsigned int chan);
/** /**
* It enables the acquisition on a give channel * It enables the acquisition on a give channel
* @ft FmcTdc FMC TDC device instance * @ft FmcTdc FMC TDC device instance
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "fmc-tdc.h" #include "fmc-tdc.h"
#include "hw/tdc_regs.h" #include "hw/tdc_regs.h"
#include "hw/timestamp_fifo_regs.h"
static int dma_buf_ddr_burst_size_default = 16; static int dma_buf_ddr_burst_size_default = 16;
module_param_named(dma_buf_ddr_burst_size, dma_buf_ddr_burst_size_default, module_param_named(dma_buf_ddr_burst_size, dma_buf_ddr_burst_size_default,
...@@ -150,6 +151,28 @@ static void ft_buffer_burst_disable(struct fmctdc_dev *ft, ...@@ -150,6 +151,28 @@ static void ft_buffer_burst_disable(struct fmctdc_dev *ft,
} }
void ft_set_delta_reference(struct fmctdc_dev *ft,
unsigned int chan, unsigned int ref)
{
uint32_t fifo_addr = ft->ft_fifo_base + TDC_FIFO_OFFSET * chan;
uint32_t csr = ft_ioread(ft, fifo_addr + TSF_REG_CSR);
csr &= ~TSF_CSR_DELTA_REF_MASK;
csr |= (ref - 1) << TSF_CSR_DELTA_REF_SHIFT;
csr |= TSF_CSR_DELTA_READ;
ft_iowrite(ft, csr, fifo_addr + TSF_REG_CSR);
}
uint32_t ft_get_delta_reference(struct fmctdc_dev *ft,
unsigned int chan)
{
uint32_t fifo_addr = ft->ft_fifo_base + TDC_FIFO_OFFSET * chan;
uint32_t csr = ft_ioread(ft, fifo_addr + TSF_REG_CSR);
return TSF_CSR_DELTA_REF_R(csr) + 1;
}
/** /**
* It configure the double buffers for a given channel * It configure the double buffers for a given channel
...@@ -695,6 +718,9 @@ int ft_probe(struct fmc_device *fmc) ...@@ -695,6 +718,9 @@ int ft_probe(struct fmc_device *fmc)
stat &= ~TDC_STAT_DMA; stat &= ~TDC_STAT_DMA;
} }
ft->mode = FT_ACQ_TYPE_FIFO;
#if 0
if (stat & TDC_STAT_DMA) { if (stat & TDC_STAT_DMA) {
ft->mode = FT_ACQ_TYPE_DMA; ft->mode = FT_ACQ_TYPE_DMA;
} else if (stat & TDC_STAT_FIFO) { } else if (stat & TDC_STAT_FIFO) {
...@@ -705,6 +731,7 @@ int ft_probe(struct fmc_device *fmc) ...@@ -705,6 +731,7 @@ int ft_probe(struct fmc_device *fmc)
stat); stat);
return -ENODEV; return -ENODEV;
} }
#endif
spin_lock_init(&ft->lock); spin_lock_init(&ft->lock);
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/zio-buffer.h> #include <linux/zio-buffer.h>
#include "fmc-tdc.h" #include "fmc-tdc.h"
#include "hw/timestamp_fifo_regs.h"
/* Module parameters */ /* Module parameters */
static int irq_timeout_ms_default = 10; static int irq_timeout_ms_default = 10;
...@@ -309,28 +310,17 @@ out: ...@@ -309,28 +310,17 @@ out:
* Get a time stamp from the fifo, if you set the 'last' flag it takes the last * Get a time stamp from the fifo, if you set the 'last' flag it takes the last
* recorded time-stamp * recorded time-stamp
*/ */
static int ft_timestap_get(struct zio_cset *cset, struct ft_hw_timestamp *hwts, static int ft_timestamp_get(struct zio_cset *cset, struct ft_hw_timestamp *hwts )
unsigned int last)
{ {
struct fmctdc_dev *ft = cset->zdev->priv_d; struct fmctdc_dev *ft = cset->zdev->priv_d;
uint32_t fifo_addr = ft->ft_fifo_base + TDC_FIFO_OFFSET * cset->index; uint32_t fifo_addr = ft->ft_fifo_base + TDC_FIFO_OFFSET * cset->index;
uint32_t data[TDC_FIFO_OUT_N];
int i, valid = 1; hwts->seconds = ft_ioread(ft, fifo_addr + TSF_REG_FIFO_R0);
hwts->coarse = ft_ioread(ft, fifo_addr + TSF_REG_FIFO_R1);
fifo_addr += last ? TDC_FIFO_LAST : TDC_FIFO_OUT; hwts->frac = ft_ioread(ft, fifo_addr + TSF_REG_FIFO_R2);
for (i = 0; i < TDC_FIFO_OUT_N; ++i) { hwts->metadata = ft_ioread(ft, fifo_addr + TSF_REG_FIFO_R3);
data[i] = ft_ioread(ft, fifo_addr + i * 4);
dev_vdbg(&cset->head.dev, "FIFO read 0x%x from 0x%x\n",
data[i], fifo_addr + i * 4);
}
if (last) {
valid = !!(ft_ioread(ft, fifo_addr + TDC_FIFO_LAST_CSR) &
TDC_FIFO_LAST_CSR_VALID);
}
memcpy(hwts, data, TDC_FIFO_OUT_N * 4); return 1;
return valid;
} }
/** /**
...@@ -340,13 +330,17 @@ static void ft_readout_fifo_one(struct zio_cset *cset) ...@@ -340,13 +330,17 @@ static void ft_readout_fifo_one(struct zio_cset *cset)
{ {
struct ft_hw_timestamp *hwts; struct ft_hw_timestamp *hwts;
// printk("read one ts\n");
cset->ti->nsamples = 1; cset->ti->nsamples = 1;
zio_arm_trigger(cset->ti); zio_arm_trigger(cset->ti);
if (!cset->chan->active_block) if (!cset->chan->active_block)
goto out; goto out;
hwts = cset->chan->active_block->data; hwts = cset->chan->active_block->data;
ft_timestap_get(cset, hwts, 0); ft_timestamp_get(cset, hwts);
//printk("2: %08x %08x %08x %08x\n", hwts->seconds, hwts->coarse, hwts->frac, hwts->metadata );
out: out:
zio_trigger_data_done(cset); zio_trigger_data_done(cset);
} }
...@@ -383,9 +377,10 @@ irq: ...@@ -383,9 +377,10 @@ irq:
cset = &ft->zdev->cset[i]; cset = &ft->zdev->cset[i];
ft_readout_fifo_one(cset); ft_readout_fifo_one(cset);
fifo_csr_addr = ft->ft_fifo_base + fifo_csr_addr = ft->ft_fifo_base +
TDC_FIFO_OFFSET * cset->index + TDC_FIFO_CSR; TDC_FIFO_OFFSET * cset->index + TSF_REG_FIFO_CSR;
fifo_stat = ft_ioread(ft, fifo_csr_addr); fifo_stat = ft_ioread(ft, fifo_csr_addr);
if (!(fifo_stat & TDC_FIFO_CSR_EMPTY)) if (!(fifo_stat & TSF_FIFO_CSR_EMPTY))
continue; /* Still something to read */ continue; /* Still something to read */
/* Ack the interrupt, nothing to read anymore */ /* Ack the interrupt, nothing to read anymore */
...@@ -518,6 +513,7 @@ void ft_irq_coalescing_timeout_set(struct fmctdc_dev *ft, ...@@ -518,6 +513,7 @@ void ft_irq_coalescing_timeout_set(struct fmctdc_dev *ft,
"%s: FIFO acquisition mode has a gobal coalesing timeout. Ignore channel %d, set global value\n", "%s: FIFO acquisition mode has a gobal coalesing timeout. Ignore channel %d, set global value\n",
__func__, chan); __func__, chan);
} }
// printk("Timeout: %d", timeout_ms);
ft_writel(ft, timeout_ms, TDC_REG_IRQ_TIMEOUT); ft_writel(ft, timeout_ms, TDC_REG_IRQ_TIMEOUT);
break; break;
case FT_ACQ_TYPE_DMA: case FT_ACQ_TYPE_DMA:
...@@ -576,6 +572,7 @@ void ft_irq_coalescing_size_set(struct fmctdc_dev *ft, ...@@ -576,6 +572,7 @@ void ft_irq_coalescing_size_set(struct fmctdc_dev *ft,
"FIFO acquisition mode has a gobal coalesing size. Ignore channel %d, apply globally\n", "FIFO acquisition mode has a gobal coalesing size. Ignore channel %d, apply globally\n",
chan); chan);
} }
// printk("coal size : %d\n", size);
ft_writel(ft, size, TDC_REG_IRQ_THRESHOLD); ft_writel(ft, size, TDC_REG_IRQ_THRESHOLD);
break; break;
case FT_ACQ_TYPE_DMA: case FT_ACQ_TYPE_DMA:
...@@ -638,6 +635,8 @@ int ft_irq_init(struct fmctdc_dev *ft) ...@@ -638,6 +635,8 @@ int ft_irq_init(struct fmctdc_dev *ft)
ft_iowrite(ft, ft_chan_to_irq_mask(ft, 0x1F), ft_iowrite(ft, ft_chan_to_irq_mask(ft, 0x1F),
ft->ft_irq_base + TDC_EIC_REG_EIC_IER); ft->ft_irq_base + TDC_EIC_REG_EIC_IER);
// printk("irq-init: imr %p\n", ft_ioread(ft, ft->ft_irq_base + TDC_EIC_REG_EIC_IMR ) );
return 0; return 0;
} }
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include <linux/fmc.h> #include <linux/fmc.h>
#include "fmc-tdc.h" #include "fmc-tdc.h"
#include "hw/timestamp_fifo_regs.h"
/* The sample size. Mandatory, device-wide */ /* The sample size. Mandatory, device-wide */
ZIO_ATTR_DEFINE_STD(ZIO_DEV, ft_zattr_dev_std) = { ZIO_ATTR_DEFINE_STD(ZIO_DEV, ft_zattr_dev_std) = {
...@@ -60,6 +60,30 @@ enum ft_devtype { ...@@ -60,6 +60,30 @@ enum ft_devtype {
FT_TYPE_INPUT FT_TYPE_INPUT
}; };
/**
* It applies all calibration offsets to the hardware for a given channel.
*/
static void ft_update_offsets(struct fmctdc_dev *ft, int channel )
{
struct ft_channel_state *st = &ft->channels[channel];
struct ft_hw_timestamp hw_offset = {0, 0, 0, 0};
uint32_t fifo_addr;
fifo_addr = ft->ft_fifo_base + TDC_FIFO_OFFSET * channel;
ft_ts_apply_offset(&hw_offset, ft->calib.zero_offset[channel]);
ft_ts_apply_offset(&hw_offset, -ft->calib.wr_offset);
if (st->user_offset)
ft_ts_apply_offset(&hw_offset, st->user_offset);
ft_iowrite(ft, hw_offset.seconds, fifo_addr + TSF_REG_OFFSET1 );
ft_iowrite(ft, hw_offset.coarse, fifo_addr + TSF_REG_OFFSET2 );
ft_iowrite(ft, hw_offset.frac, fifo_addr + TSF_REG_OFFSET3 );
//printk("set offset ch %d %d %d %d\n", channel, hw_offset.seconds, hw_offset.coarse, hw_offset.frac);
}
static enum ft_devtype __ft_get_type(struct device *dev) static enum ft_devtype __ft_get_type(struct device *dev)
{ {
struct zio_obj_head *head = to_zio_head(dev); struct zio_obj_head *head = to_zio_head(dev);
...@@ -92,7 +116,7 @@ static int ft_zio_info_channel(struct device *dev, struct zio_attribute *zattr, ...@@ -92,7 +116,7 @@ static int ft_zio_info_channel(struct device *dev, struct zio_attribute *zattr,
*usr_val = test_bit(FT_FLAG_CH_TERMINATED, &st->flags); *usr_val = test_bit(FT_FLAG_CH_TERMINATED, &st->flags);
break; break;
case FT_ATTR_TDC_DELAY_REF: case FT_ATTR_TDC_DELAY_REF:
/* FIXME read from HW */ *usr_val = ft_get_delta_reference(ft, cset->index);
break; break;
case FT_ATTR_TDC_TRANSFER_MODE: case FT_ATTR_TDC_TRANSFER_MODE:
*usr_val = ft->mode; *usr_val = ft->mode;
...@@ -143,6 +167,7 @@ static int ft_zio_info_get(struct device *dev, struct zio_attribute *zattr, ...@@ -143,6 +167,7 @@ static int ft_zio_info_get(struct device *dev, struct zio_attribute *zattr,
} }
case FT_ATTR_TDC_WR_OFFSET: case FT_ATTR_TDC_WR_OFFSET:
*usr_val = ft->calib.wr_offset; *usr_val = ft->calib.wr_offset;
break; break;
} }
return 0; return 0;
...@@ -172,12 +197,14 @@ static int ft_zio_conf_channel(struct device *dev, struct zio_attribute *zattr, ...@@ -172,12 +197,14 @@ static int ft_zio_conf_channel(struct device *dev, struct zio_attribute *zattr,
return -EINVAL; return -EINVAL;
spin_lock(&ft->lock); spin_lock(&ft->lock);
st->user_offset = usr_val; st->user_offset = usr_val;
ft_update_offsets(ft, cset->index);
spin_unlock(&ft->lock); spin_unlock(&ft->lock);
break; break;
case FT_ATTR_TDC_DELAY_REF: case FT_ATTR_TDC_DELAY_REF:
if (usr_val > FT_NUM_CHANNELS) if (usr_val > FT_NUM_CHANNELS)
return -EINVAL; return -EINVAL;
/* FIXME write on HW */ ft_set_delta_reference(ft, cset->index, usr_val);
break; break;
case FT_ATTR_TDC_COALESCING_TIME: case FT_ATTR_TDC_COALESCING_TIME:
ft_irq_coalescing_timeout_set(ft, cset->index, usr_val); ft_irq_coalescing_timeout_set(ft, cset->index, usr_val);
...@@ -282,8 +309,9 @@ static void ft_change_flags(struct zio_obj_head *head, unsigned long mask) ...@@ -282,8 +309,9 @@ static void ft_change_flags(struct zio_obj_head *head, unsigned long mask)
struct zio_channel *chan; struct zio_channel *chan;
struct ft_channel_state *st; struct ft_channel_state *st;
struct fmctdc_dev *ft; struct fmctdc_dev *ft;
uint32_t ien; uint32_t ien, csr;
uint32_t fifo_addr;
/* We manage only status flag */ /* We manage only status flag */
if (!(mask & ZIO_STATUS)) if (!(mask & ZIO_STATUS))
return; return;
...@@ -296,11 +324,18 @@ static void ft_change_flags(struct zio_obj_head *head, unsigned long mask) ...@@ -296,11 +324,18 @@ static void ft_change_flags(struct zio_obj_head *head, unsigned long mask)
if (chan->flags & ZIO_STATUS) { if (chan->flags & ZIO_STATUS) {
/* DISABLED */ /* DISABLED */
ft_disable(ft, chan->cset->index); ft_disable(ft, chan->cset->index);
fifo_addr = ft->ft_fifo_base + TDC_FIFO_OFFSET * chan->cset->index;
zio_trigger_abort_disable(chan->cset, 0); zio_trigger_abort_disable(chan->cset, 0);
/* Reset last time-stamp (seq number and valid)*/
//ft_iowrite(ft, TDC_FIFO_LAST_CSR_VALID | TDC_FIFO_LAST_CSR_RST_SEQ, csr = ft_ioread(ft, fifo_addr + TSF_REG_CSR);
// TDC_FIFO_LAST_CSR);
/* clear delta timestamp ready flag */
ft_iowrite(ft, csr | TSF_CSR_DELTA_READ, fifo_addr + TSF_REG_CSR);
csr = ft_ioread(ft, fifo_addr + TSF_REG_FIFO_CSR);
ft_iowrite(ft, csr | TSF_FIFO_CSR_CLEAR_BUS, fifo_addr + TSF_REG_FIFO_CSR);
} else { } else {
/* ENABLED */ /* ENABLED */
ft_enable(ft, chan->cset->index); ft_enable(ft, chan->cset->index);
...@@ -381,23 +416,6 @@ enum ft_trig_options { ...@@ -381,23 +416,6 @@ enum ft_trig_options {
}; };
/**
* It applies all calibration offsets to the givne timestamp
* @ft FmcTdc device instance
* @ts timestamp
*/
static void ft_timestamp_apply_offsets(struct fmctdc_dev *ft,
struct ft_hw_timestamp *hwts)
{
unsigned int chan = FT_HW_TS_META_CHN(hwts->metadata);
struct ft_channel_state *st = &ft->channels[chan];
ft_ts_apply_offset(hwts, ft->calib.zero_offset[chan]);
ft_ts_apply_offset(hwts, -ft->calib.wr_offset);
if (st->user_offset)
ft_ts_apply_offset(hwts, st->user_offset);
}
/** /**
* It puts the given timestamp in the ZIO control * It puts the given timestamp in the ZIO control
* @cset ZIO cset instant * @cset ZIO cset instant
...@@ -508,7 +526,6 @@ static int ft_trig_data_done(struct zio_cset *cset) ...@@ -508,7 +526,6 @@ static int ft_trig_data_done(struct zio_cset *cset)
__func__, i, cset->ti->nsamples, __func__, i, cset->ti->nsamples,
ts[i].seconds,ts[i].coarse, ts[i].seconds,ts[i].coarse,
ts[i].frac, FT_HW_TS_META_SEQ(ts[i].metadata)); ts[i].frac, FT_HW_TS_META_SEQ(ts[i].metadata));
ft_timestamp_apply_offsets(ft, &ts[i]);
} }
ft_zio_update_ctrl(cset, &ts[0]); ft_zio_update_ctrl(cset, &ts[0]);
...@@ -571,7 +588,7 @@ int ft_zio_init(struct fmctdc_dev *ft) ...@@ -571,7 +588,7 @@ int ft_zio_init(struct fmctdc_dev *ft)
{ {
int err = 0; int err = 0;
int dev_id; int dev_id;
int i;
ft->hwzdev = zio_allocate_device(); ft->hwzdev = zio_allocate_device();
if (IS_ERR(ft->hwzdev)) if (IS_ERR(ft->hwzdev))
...@@ -587,6 +604,9 @@ int ft_zio_init(struct fmctdc_dev *ft) ...@@ -587,6 +604,9 @@ int ft_zio_init(struct fmctdc_dev *ft)
if (err) if (err)
goto err_dev_reg; goto err_dev_reg;
for(i = 0; i < FT_NUM_CHANNELS; i++)
ft_update_offsets(ft, i);
return 0; return 0;
err_dev_reg: err_dev_reg:
......
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#define TDC_STAT_DMA BIT(0) #define TDC_STAT_DMA BIT(0)
#define TDC_STAT_FIFO BIT(1) #define TDC_STAT_FIFO BIT(1)
#define TDC_FIFO_OFFSET 0x100
#define TDC_WR_CTRL_ENABLE BIT(0) #define TDC_WR_CTRL_ENABLE BIT(0)
...@@ -97,20 +98,6 @@ ...@@ -97,20 +98,6 @@
#define TDC_EVENT_FIFO_EF_MASK 0xF000 #define TDC_EVENT_FIFO_EF_MASK 0xF000
#define TDC_EVENT_DACAPO_FLAG BIT(0) #define TDC_EVENT_DACAPO_FLAG BIT(0)
/* FIFO registers */
#define TDC_FIFO_OFFSET 0x100
#define TDC_FIFO_LAST 0x0
#define TDC_FIFO_LAST_N 4
#define TDC_FIFO_LAST_CSR 0x10
#define TDC_FIFO_LAST_CSR_VALID BIT(0)
#define TDC_FIFO_LAST_CSR_RST_SEQ BIT(1)
#define TDC_FIFO_OUT 0x14
#define TDC_FIFO_OUT_N 4
#define TDC_FIFO_CSR 0x24
#define TDC_FIFO_CSR_EMPTY BIT(17)
#define TDC_FIFO_CSR_FULL BIT(16)
#define TDC_FIFO_CSR_USEDW
/* Carrier CSRs */ /* Carrier CSRs */
#define TDC_REG_CARRIER_CTL0 0x0 /* a.k.a. Carrier revision/PCB id reg */ #define TDC_REG_CARRIER_CTL0 0x0 /* a.k.a. Carrier revision/PCB id reg */
#define TDC_REG_CARRIER_STATUS 0x4 #define TDC_REG_CARRIER_STATUS 0x4
......
...@@ -731,6 +731,68 @@ int fmctdc_read(struct fmctdc_board *userb, unsigned int channel, ...@@ -731,6 +731,68 @@ int fmctdc_read(struct fmctdc_board *userb, unsigned int channel,
return i; return i;
} }
int fmctdc_readhw(struct fmctdc_board *userb, unsigned int channel,
struct ft_hw_timestamp *t, int n, int flags)
{
__define_board(b, userb);
int i;
int n_ts;
fd_set set;
struct ft_hw_timestamp *data;
if (channel >= FMCTDC_NUM_CHANNELS) {
errno = EINVAL;
return -1;
}
data = calloc(n, sizeof(*data));
if (!data) {
errno = ENOMEM;
return -1;
}
i = 0;
while (i < n) {
n_ts = read(b->fdd[channel], &data[i], sizeof(*data) * (n - i));
if (n_ts < 0 && errno != EAGAIN) {
if (i == 0)
goto err;
else
goto out;
}
if (n_ts % sizeof(*data) == 0) { /* Good samples here */
n_ts /= sizeof(*data);
n_ts += i;
for (; i < n_ts && i < n; i++)
memcpy( &t[i], &data[i], sizeof(struct ft_hw_timestamp) ); //fmctdc_ts_convert(&t[i], &data[i]);
continue; /* the while loop */
}
if (i) /* error but before we got something */
goto out;
/* EAGAIN at first sample */
if (n_ts < 0 && flags == O_NONBLOCK)
return -1;
/* So, first sample and blocking read. Wait.. */
FD_ZERO(&set);
FD_SET(b->fdc[channel], &set);
if (select(b->fdc[channel] + 1, &set, NULL, NULL, NULL) < 0)
goto err;
}
out:
free(data);
return i;
err:
free(data);
return -1;
}
/** /**
* this "fread" behaves like stdio: it reads all the samples. Read fmctdc_read() * this "fread" behaves like stdio: it reads all the samples. Read fmctdc_read()
* for more details about the function. * for more details about the function.
......
...@@ -16,7 +16,6 @@ extern "C" { ...@@ -16,7 +16,6 @@ extern "C" {
#endif #endif
#include <stdint.h> #include <stdint.h>
/** /**
* Enumeration for all TDC channels * Enumeration for all TDC channels
*/ */
...@@ -162,6 +161,17 @@ extern int fmctdc_coalescing_timeout_get(struct fmctdc_board *userb, ...@@ -162,6 +161,17 @@ extern int fmctdc_coalescing_timeout_get(struct fmctdc_board *userb,
/**@}*/ /**@}*/
#if 0
/* Hardware TDC timestamp */
struct ft_hw_timestamp {
uint32_t seconds;/* 1 second resolution */
uint32_t coarse;/* 8 ns resolution */
uint32_t frac;/* In ACAM bins (81 ps) */
uint32_t metadata;/* channel, polarity, etc. */
};
#endif
#include "fmctdc-lib-private.h"
/** /**
* @defgroup libacq Time-stamps Acquisition * @defgroup libacq Time-stamps Acquisition
...@@ -176,6 +186,8 @@ extern int fmctdc_fread(struct fmctdc_board *b, unsigned int channel, ...@@ -176,6 +186,8 @@ extern int fmctdc_fread(struct fmctdc_board *b, unsigned int channel,
extern int fmctdc_fileno_channel(struct fmctdc_board *b, unsigned int channel); extern int fmctdc_fileno_channel(struct fmctdc_board *b, unsigned int channel);
extern int fmctdc_read(struct fmctdc_board *b, unsigned int channel, extern int fmctdc_read(struct fmctdc_board *b, unsigned int channel,
struct fmctdc_time *t, int n, int flags); struct fmctdc_time *t, int n, int flags);
extern int fmctdc_readhw(struct fmctdc_board *b, unsigned int channel,
struct ft_hw_timestamp *t, int n, int flags);
extern int fmctdc_read_last(struct fmctdc_board *userb, unsigned int channel, extern int fmctdc_read_last(struct fmctdc_board *userb, unsigned int channel,
struct fmctdc_time *t); struct fmctdc_time *t);
extern int fmctdc_flush(struct fmctdc_board *userb, unsigned int channel); extern int fmctdc_flush(struct fmctdc_board *userb, unsigned int channel);
......
...@@ -17,7 +17,7 @@ TESTS = fmc-tdc-list \ ...@@ -17,7 +17,7 @@ TESTS = fmc-tdc-list \
fmc-tdc-tstamp \ fmc-tdc-tstamp \
fmc-tdc-offset fmc-tdc-offset
CFLAGS = -I. -I$(LIBTDC) -I../kernel -Wall -Werror $(EXTRACFLAGS) CFLAGS = -I. -I$(LIBTDC) -I../kernel -Wall $(EXTRACFLAGS)
GIT_VERSION := $(shell git describe --dirty --long --tags) GIT_VERSION := $(shell git describe --dirty --long --tags)
CFLAGS += -DGIT_VERSION="\"$(GIT_VERSION)\"" CFLAGS += -DGIT_VERSION="\"$(GIT_VERSION)\""
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment