Commit bad11788 authored by Federico Vaga's avatar Federico Vaga

remove unused legacy software

Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent 1139d4a3
This subdirectory contains some legacy/retired code & designs, kept for historical or testing reasons.
WE DO NOT PROVIDE ANY SUPPORT FOR THE CONTENTS OF THIS DIRECTORY.
\ No newline at end of file
*.o
*.txt
*.log
*.pyc
spec_top.bin
spec_top_fd.bin
*.a
*.so
lib/spec
SPEC_SW ?= $(shell readlink -f ~/wr-repos/spec-sw)
ETHERBONE ?= $(shell readlink -f ~/wr-repos/etherbone-core/api)
all:
make -C lib SPEC_SW=$(SPEC_SW) ETHERBONE=$(ETHERBONE)
make -C tests SPEC_SW=$(SPEC_SW) ETHERBONE=$(ETHERBONE)
clean:
make -C lib clean SPEC_SW=$(SPEC_SW) ETHERBONE=$(ETHERBONE)
make -C tests clean SPEC_SW=$(SPEC_SW) ETHERBONE=$(ETHERBONE)
\ No newline at end of file
#ifndef __ACAM_GPX_H
#define __ACAM_GPX_H
#define AR0_ROsc (1<<0)
#define AR0_RiseEn0 (1<<1)
#define AR0_FallEn0 (1<<2)
#define AR0_RiseEn1 (1<<3)
#define AR0_FallEn1 (1<<4)
#define AR0_RiseEn2 (1<<5)
#define AR0_FallEn2 (1<<6)
#define AR0_HQSel (1<<7)
#define AR0_TRiseEn(port) (1<<(10+port))
#define AR0_TFallEn(port) (1<<(19+port))
#define AR1_Adj(chan, value) (((value) & 0xf) << (chan * 4))
#define AR2_GMode (1<<0)
#define AR2_IMode (1<<1)
#define AR2_RMode (1<<2)
#define AR2_Disable(chan) (1<<(3+chan))
#define AR2_Adj(chan, value) (((value)&0xf)<<(12+4*(chan-7)))
#define AR2_DelRise1(value) (((value)&0x3)<<(20))
#define AR2_DelFall1(value) (((value)&0x3)<<(22))
#define AR2_DelRise2(value) (((value)&0x3)<<(24))
#define AR2_DelFall2(value) (((value)&0x3)<<(26))
#define AR3_DelTx(chan, value) (((value)&0x3)<<(5 + (chan -1 ) * 2))
#define AR3_RaSpeed(chan, value) (((value)&0x3)<<(21 + (chan ) * 2))
#define AR4_RaSpeed(chan, value) (((value)&0x3)<<(10 + (chan-3) * 2))
#define AR3_Zero (0) // nothing interesting for the Fine Delay
#define AR4_StartTimer(value) ((value) & 0xff)
#define AR4_Quiet (1<<8)
#define AR4_MMode (1<<9)
#define AR4_MasterReset (1<<22)
#define AR4_PartialReset (1<<23)
#define AR4_AluTrigSoft (1<<24)
#define AR4_EFlagHiZN (1<<25)
#define AR4_MTimerStart (1<<26)
#define AR4_MTimerStop (1<<27)
#define AR5_StartOff1(value) ((value)&0x3ffff)
#define AR5_StopDisStart (1<<21)
#define AR5_StartDisStart (1<<22)
#define AR5_MasterAluTrig (1<<23)
#define AR5_PartialAluTrig (1<<24)
#define AR5_MasterOenTrig (1<<25)
#define AR5_PartialOenTrig (1<<26)
#define AR5_StartRetrig (1<<27)
#define AR6_Fill(value) ((value)&0xff)
#define AR6_StartOff2(value) (((value)&0x3ffff)<<8)
#define AR6_InSelECL (1<<26)
#define AR6_PowerOnECL (1<<27)
#define AR7_HSDiv(value) ((value)&0xff)
#define AR7_RefClkDiv(value) (((value)&0x7)<<8)
#define AR7_ResAdj (1<<11)
#define AR7_NegPhase (1<<12)
#define AR7_Track (1<<13)
#define AR7_MTimer(value) (((value) & 0x1ff)<<15)
#define AR14_16BitMode (1<<4)
#define AR8I_IFIFO1(reg) ((reg) & 0x1ffff)
#define AR8I_Slope1(reg) ((reg) & (1<<17) ? 1 : 0)
#define AR8I_StartN1(reg) (((reg) >> 18) & 0xff)
#define AR8I_ChaCode1(reg) (((reg) >> 26) & 0x3)
#define AR9I_IFIFO2(reg) ((reg) & 0x1ffff)
#define AR9I_Slope2(reg) ((reg) & (1<<17) ? 1 : 0)
#define AR9I_StartN2(reg) (((reg) >> 18) & 0xff)
#define AR9I_ChaCode2(reg) (((reg) >> 26) & 0x3)
#define AR8R_IFIFO1(reg) ((reg) & 0x3fffff)
#define AR9R_IFIFO2(reg) ((reg) & 0x3fffff)
#define AR11_StopCounter0(num) ((num) & 0xff)
#define AR11_StopCounter1(num) (((num) & 0xff) << 8)
#define AR11_HFifoErrU(num) (1 << (num+16))
#define AR11_IFifoErrU(num) (1 << (num+24))
#define AR11_NotLockErrU (1 << 26)
#define AR12_HFifoE (1<<11)
#define AR12_NotLocked (1<<10)
#endif
/*
Register definitions for slave core: Fine Delay Channel WB Slave
* File : fd_channel_regs.h
* Author : auto-generated by wbgen2 from fd_channel_wishbone_slave.wb
* Created : Fri Feb 15 12:07:17 2013
* Standard : ANSI C
THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE fd_channel_wishbone_slave.wb
DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
*/
#ifndef __WBGEN2_REGDEFS_FD_CHANNEL_WISHBONE_SLAVE_WB
#define __WBGEN2_REGDEFS_FD_CHANNEL_WISHBONE_SLAVE_WB
#include <inttypes.h>
#if defined( __GNUC__)
#define PACKED __attribute__ ((packed))
#else
#error "Unsupported compiler?"
#endif
#ifndef __WBGEN2_MACROS_DEFINED__
#define __WBGEN2_MACROS_DEFINED__
#define WBGEN2_GEN_MASK(offset, size) (((1<<(size))-1) << (offset))
#define WBGEN2_GEN_WRITE(value, offset, size) (((value) & ((1<<(size))-1)) << (offset))
#define WBGEN2_GEN_READ(reg, offset, size) (((reg) >> (offset)) & ((1<<(size))-1))
#define WBGEN2_SIGN_EXTEND(value, bits) (((value) & (1<<bits) ? ~((1<<(bits))-1): 0 ) | (value))
#endif
/* definitions for register: Delay Control Register */
/* definitions for field: Enable channel in reg: Delay Control Register */
#define FD_DCR_ENABLE WBGEN2_GEN_MASK(0, 1)
/* definitions for field: Delay mode select in reg: Delay Control Register */
#define FD_DCR_MODE WBGEN2_GEN_MASK(1, 1)
/* definitions for field: Pulse generator arm in reg: Delay Control Register */
#define FD_DCR_PG_ARM WBGEN2_GEN_MASK(2, 1)
/* definitions for field: Pulse generator triggered in reg: Delay Control Register */
#define FD_DCR_PG_TRIG WBGEN2_GEN_MASK(3, 1)
/* definitions for field: Start Delay Update in reg: Delay Control Register */
#define FD_DCR_UPDATE WBGEN2_GEN_MASK(4, 1)
/* definitions for field: Delay Update Done in reg: Delay Control Register */
#define FD_DCR_UPD_DONE WBGEN2_GEN_MASK(5, 1)
/* definitions for field: Force Calibration Delay in reg: Delay Control Register */
#define FD_DCR_FORCE_DLY WBGEN2_GEN_MASK(6, 1)
/* definitions for field: Disable Fine Part update in reg: Delay Control Register */
#define FD_DCR_NO_FINE WBGEN2_GEN_MASK(7, 1)
/* definitions for field: Force Output High in reg: Delay Control Register */
#define FD_DCR_FORCE_HI WBGEN2_GEN_MASK(8, 1)
/* definitions for register: Fine Range Register */
/* definitions for register: Pulse start time / offset (MSB TAI seconds) */
/* definitions for register: Pulse start time / offset (LSB TAI seconds) */
/* definitions for register: Pulse start time / offset (8 ns cycles) */
/* definitions for register: Pulse start time / offset (sub-cycle fine part) */
/* definitions for register: Pulse end time / offset (MSB TAI seconds) */
/* definitions for register: Pulse end time / offset (LSB TAI seconds) */
/* definitions for register: Pulse end time / offset (8 ns cycles) */
/* definitions for register: Pulse end time / offset (sub-cycle fine part) */
/* definitions for register: Pulse spacing (TAI seconds) */
/* definitions for register: Pulse spacing (8 ns cycles) */
/* definitions for register: Pulse spacing (sub-cycle fine part) */
/* definitions for register: Repeat Count Register */
/* definitions for field: Repeat Count in reg: Repeat Count Register */
#define FD_RCR_REP_CNT_MASK WBGEN2_GEN_MASK(0, 16)
#define FD_RCR_REP_CNT_SHIFT 0
#define FD_RCR_REP_CNT_W(value) WBGEN2_GEN_WRITE(value, 0, 16)
#define FD_RCR_REP_CNT_R(reg) WBGEN2_GEN_READ(reg, 0, 16)
/* definitions for field: Continuous Waveform Mode in reg: Repeat Count Register */
#define FD_RCR_CONT WBGEN2_GEN_MASK(16, 1)
/* [0x0]: REG Delay Control Register */
#define FD_REG_DCR 0x00000000
/* [0x4]: REG Fine Range Register */
#define FD_REG_FRR 0x00000004
/* [0x8]: REG Pulse start time / offset (MSB TAI seconds) */
#define FD_REG_U_STARTH 0x00000008
/* [0xc]: REG Pulse start time / offset (LSB TAI seconds) */
#define FD_REG_U_STARTL 0x0000000c
/* [0x10]: REG Pulse start time / offset (8 ns cycles) */
#define FD_REG_C_START 0x00000010
/* [0x14]: REG Pulse start time / offset (sub-cycle fine part) */
#define FD_REG_F_START 0x00000014
/* [0x18]: REG Pulse end time / offset (MSB TAI seconds) */
#define FD_REG_U_ENDH 0x00000018
/* [0x1c]: REG Pulse end time / offset (LSB TAI seconds) */
#define FD_REG_U_ENDL 0x0000001c
/* [0x20]: REG Pulse end time / offset (8 ns cycles) */
#define FD_REG_C_END 0x00000020
/* [0x24]: REG Pulse end time / offset (sub-cycle fine part) */
#define FD_REG_F_END 0x00000024
/* [0x28]: REG Pulse spacing (TAI seconds) */
#define FD_REG_U_DELTA 0x00000028
/* [0x2c]: REG Pulse spacing (8 ns cycles) */
#define FD_REG_C_DELTA 0x0000002c
/* [0x30]: REG Pulse spacing (sub-cycle fine part) */
#define FD_REG_F_DELTA 0x00000030
/* [0x34]: REG Repeat Count Register */
#define FD_REG_RCR 0x00000034
#endif
This diff is collapsed.
#ifndef __FD_LIB_H
#define __FD_LIB_H
#include <stdint.h>
/* Number of fractional bits in the timestamps/time definitions. Must be consistent with the HDL bitstream. */
#define FDELAY_FRAC_BITS 12
/* fdelay_get_timing_status() return values: */
#define FDELAY_FREE_RUNNING 0x10 /* local oscillator is free running */
#define FDELAY_WR_OFFLINE 0x8 /* attached WR core is offline */
#define FDELAY_WR_READY 0x1 /* attached WR core is synchronized, we can sync the fine delay core anytime */
#define FDELAY_WR_SYNCING 0x2 /* local oscillator is being synchronized with WR clock */
#define FDELAY_WR_SYNCED 0x4 /* we are synced. */
#define FDELAY_WR_NOT_PRESENT 0x20 /* No WR Core present */
/* fdelay_configure_sync() flags */
#define FDELAY_SYNC_LOCAL 0x1 /* use local oscillator */
#define FDELAY_SYNC_WR 0x2 /* use White Rabbit */
/* fdelay_init() flags */
#define FDELAY_RAW_READOUT 0x1
#define FDELAY_PERFORM_LONG_TESTS 0x2
/* Hardware "handle" structure */
typedef struct fdelay_device
{
/* Base address of the FD core (relative to the beginning of local writel/readl address spaces) */
uint32_t base_addr;
/* Bus-specific readl/writel functions - so the same library can be used both with
RawRabbit, VME and Etherbone backends */
void (*writel)(void *priv, uint32_t data, uint32_t addr);
uint32_t (*readl)(void *priv, uint32_t addr);
void *priv_fd; /* pointer to Fine Delay library private data */
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;
uint32_t tsbcr;
} fdelay_raw_time_t;
typedef struct
{
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 */
fdelay_raw_time_t raw;
} fdelay_time_t;
/*
--------------------
PUBLIC API
--------------------
*/
fdelay_device_t *fdelay_create();
/* Creates a local instance of Fine Delay Core at address base_addr on the SPEC at bus/devfn. Returns 0 on success, negative on error. */
int spec_fdelay_create_bd(fdelay_device_t *dev, int bus, int dev_fn, uint32_t base);
/* A shortcut for test program, parsing the card base/location from command line args */
int spec_fdelay_create(fdelay_device_t *dev, int argc, char *argv[]);
/* Helper functions - converting FD timestamp format from/to plain picoseconds */
fdelay_time_t fdelay_from_picos(const uint64_t ps);
int64_t fdelay_to_picos(const fdelay_time_t t);
/* Enables/disables raw timestamp readout mode (debugging only) */
int fdelay_raw_readout(fdelay_device_t *dev, int raw_moide);
/* Initializes and calibrates the device. 0 = success, negative = error */
int fdelay_init(fdelay_device_t *dev, int init_flags);
/* Disables and releases the resources for a given FD Card */
int fdelay_release(fdelay_device_t *dev);
/* Returns an explaination of the last error occured on device dev (TBI) */
char *fdelay_strerror(fdelay_device_t *dev);
/* Sets the timing reference for the card (ref source). Currently there are two choices:
- FDELAY_SYNC_LOCAL - use local oscillator
- FDELAY_SYNC_WR - use White Rabbit */
int fdelay_set_timing_reference(fdelay_device_t *dev, int ref_source);
/* Polls the current status of the timing source. Returns a combination of
.... SYNCED flags. wait_mask can enable/disable waiting for a change of
a particular flag or set of flags. For example, calling
fdelay_get_timing_status(dev, FDELAY_WR_SYNCED) will wait until a change of
FDELAY_WR_SYNCED bit. */
int fdelay_get_timing_status(fdelay_device_t *dev, int wait_mask);
/* Configures the trigger input (TDC/Delay modes). enable enables the input,
termination switches on/off the built-in 50 Ohm termination resistor */
int fdelay_configure_trigger(fdelay_device_t *dev, int enable, int termination);
/* Configures timestamp buffer capture: enable = TS buffer enabled, channel mask:
channels to time tag (bit 0 = TDC, bits 1..4 = outputs 1..4) */
int fdelay_configure_capture (fdelay_device_t *dev, int enable, int channel_mask);
/* Reads how_many timestamps from the buffer. Blocking */
/* TODO: non-blocking version? */
int fdelay_read (fdelay_device_t *dev, fdelay_time_t *timestamps, int how_many);
int fdelay_configure_output(fdelay_device_t *dev, int channel, int enable, int64_t delay_ps, int64_t width_ps, int64_t delta_ps, int rep_count) ;
/* (delay mode only) Configures output(s) selected in channel_mask to work in delay mode. Delta_ps = spacing between
the rising edges of subsequent pulses. */
int fdelay_configure_delay (fdelay_device_t *dev, int channel_mask, int enable, int64_t delay_ps, int64_t width_ps, int64_t delta_ps, int repeat_count);
/* (pulse mode only) Configures output(s) selected in channel_mask to produce pulse(s) starting at (start) with appropriate width/spacing/repeat_count */
int fdelay_configure_pulse_gen(fdelay_device_t *dev, int channel_mask, int enable, fdelay_time_t start, int64_t width_ps, int64_t delta_ps, int repeat_count);
/* (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);
int fdelay_dmtd_calibration(fdelay_device_t *dev, double *offsets);
float fdelay_get_board_temperature(fdelay_device_t *dev);
#endif
/*
FmcDelay1ns4Cha (a.k.a. The Fine Delay Card)
User-space driver/library
Private includes
Tomasz Włostowski/BE-CO-HT, 2011
(c) Copyright CERN 2011
Licensed under LGPL 2.1
*/
#ifndef __FDELAY_PRIVATE_H
#define __FDELAY_PRIVATE_H
#include <stdint.h>
/* SPI Bus chip selects */
#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) */
#define SGPIO_OUTPUT_EN(x) (1<<(6-x)) /* Output driver enable (1 = on) */
#define SGPIO_TRIG_SEL (1<<6) /* TDC trigger select (0 = trigger input, 1 = FPGA) */
#define SGPIO_CAL_EN (1<<7) /* Calibration mode enable (0 = on) */
/* ACAM TDC operation modes */
#define ACAM_RMODE 0
#define ACAM_IMODE 1
#define ACAM_GMODE 2
/* MCP23S17 register addresses (only ones which are used by the lib) */
#define MCP_IODIR 0x0
#define MCP_IPOL 0x1
#define MCP_OLAT 0x14
#define MCP_IOCON 0x0a
#define MCP_GPIO 0x12
/* Number of fractional bits in the timestamps/time definitions. Must be consistent with the HDL bitstream. */
#define FDELAY_FRAC_BITS 12
/* Fractional bits shifted away when converting the fine (< 8ns) part to fit the range of SY89295 delay line. */
#define FDELAY_SCALER_SHIFT 12
/* Number of delay line taps */
#define FDELAY_NUM_TAPS 1024
/* How many times each calibration measurement will be averaged */
#define FDELAY_CAL_AVG_STEPS 1024
/* Fine Delay Card Magic ID */
#define FDELAY_MAGIC_ID 0xf19ede1a
/* RSTR Register value which triggers a reset of the FD Core */
#define FDELAY_RSTR_TRIGGER 0xdeadbeef
/* Calibration eeprom I2C address */
#define EEPROM_ADDR 0x50
/* ACAM Calibration parameters */
struct fine_delay_calibration {
uint32_t magic; /* magic ID: 0xf19ede1a */
uint32_t zero_offset[4]; /* Output zero offset, in nsec << FDELAY_FRAC_BITS */
uint32_t adsfr_val; /* ADSFR register value */
uint32_t acam_start_offset; /* ACAM Start offset value */
uint32_t atmcr_val; /* ATMCR register value */
uint32_t tdc_zero_offset; /* Zero offset of the TDC, in picoseconds */
int64_t frr_poly[3]; /* SY89295 delay/temperature polynomial coefficients */
} __attribute__((packed));
/* Internal state of the fine delay card */
struct fine_delay_hw
{
uint32_t base_addr; /* Base address of the core */
uint32_t base_onewire; /* Base address of the core */
uint32_t base_i2c; /* SPI Controller offset */
uint32_t acam_addr; /* Current state of ACAM's address lines */
double acam_bin; /* bin size of the ACAM TDC - calculated for 31.25 MHz reference */
uint32_t frr_offset[4]; /* Offset between the FRR measured at a known temperature at startup and poly-fitted FRR */
uint32_t frr_cur[4]; /* Fine range register for each output, current value (after online temp. compensation) */
int32_t cal_temp; /* SY89295 calibration temperature in 1/16 degC units */
int32_t board_temp; /* Current temperature of the board, unit = 1/16 degC */
int wr_enabled;
int wr_state;
int raw_mode;
int do_long_tests;
struct fine_delay_calibration calib;
int64_t input_user_offset, output_user_offset;
};
/* some useful access/declaration macros */
#define fd_writel(data, addr) dev->writel(dev->priv_io, data, (hw->base_addr + (addr)))
#define fd_readl(addr) dev->readl(dev->priv_io, (hw->base_addr + (addr)))
#define fd_decl_private(dev) struct fine_delay_hw *hw = (struct fine_delay_hw *) dev->priv_fd;
#endif
#ifndef __I2C_MASTER_H
#define __I2C_MASTER_H
#include <stdint.h>
#include "fdelay_lib.h"
void mi2c_init(fdelay_device_t *dev);
int eeprom_read(fdelay_device_t *dev, uint8_t i2c_addr, uint32_t offset, uint8_t *buf, size_t size);
int eeprom_write(fdelay_device_t *dev, uint8_t i2c_addr, uint32_t offset, uint8_t *buf, size_t size);
#endif
#ifndef ONEWIRE_H_INCLUDED
#define ONEWIRE_H_INCLUDED
#include "fdelay_lib.h"
int ds18x_init(fdelay_device_t *dev);
int ds18x_read_temp(fdelay_device_t *dev, int *temp_r);
#endif // ONEWIRE_H_INCLUDED
const struct {int reg; uint8_t val; } ad9516_regs[] = {
{0x0000, 0x99},
{0x0001, 0x00},
{0x0002, 0x10},
{0x0003, 0xC3},
{0x0004, 0x00},
{0x0010, 0x7C},
{0x0011, 0x05},
{0x0012, 0x00},
{0x0013, 0x0C},
{0x0014, 0x12},
{0x0015, 0x00},
{0x0016, 0x05},
{0x0017, 0xb4}, /* PLL_STATUS = Lock Detect */
{0x0018, 0x07},
{0x0019, 0x00},
{0x001A, 0x00},
{0x001B, 0xE0},
{0x001C, 0x02},
{0x001D, 0x00},
{0x001E, 0x00},
{0x001F, 0x0E},
{0x00A0, 0x01},
{0x00A1, 0x00},
{0x00A2, 0x00},
{0x00A3, 0x01},
{0x00A4, 0x00},
{0x00A5, 0x00},
{0x00A6, 0x01},
{0x00A7, 0x00},
{0x00A8, 0x00},
{0x00A9, 0x01},
{0x00AA, 0x00},
{0x00AB, 0x00},
{0x00F0, 0x08},
{0x00F1, 0x08},
{0x00F2, 0x08},
{0x00F3, 0x18}, /* out3 inverted */
{0x00F4, 0x00},
{0x00F5, 0x08},
{0x0140, 0x5A},
{0x0141, 0x5A},
{0x0142, 0x5B},
{0x0143, 0x42},
{0x0190, 0x00},
{0x0191, 0x80},
{0x0192, 0x00},
{0x0193, 0x00},
{0x0194, 0x80},
{0x0195, 0x00},
{0x0196, 0xFF},
{0x0197, 0x00},
{0x0198, 0x00},
{0x0199, 0x33},
{0x019A, 0x00},
{0x019B, 0x11},
{0x019C, 0x20},
{0x019D, 0x00},
{0x019E, 0x00},
{0x019F, 0x00},
{0x01A0, 0x11},
{0x01A1, 0x20},
{0x01A2, 0x00},
{0x01A3, 0x00},
{0x01E0, 0x04}, /* VCODIV = 6 */
{0x01E1, 0x02},
{0x0230, 0x00},
{0x0231, 0x00},
{0x0232, 0x00},
{-1, 0}};
/*
* Public header for the raw I/O interface for PCI or PCI express interfaces
*
* Copyright (C) 2010 CERN (www.cern.ch)
* Author: Alessandro Rubini <rubini@gnudd.com>
*
* Released according to the GNU GPL, version 2 or any later version.
*
* This work is part of the White Rabbit project, a research effort led
* by CERN, the European Institute for Nuclear Research.
*/
#ifndef __RAWRABBIT_H__
#define __RAWRABBIT_H__
#include <linux/types.h>
#include <linux/ioctl.h>
#ifdef __KERNEL__ /* The initial part of the file is driver-internal stuff */
#include <linux/pci.h>
#include <linux/completion.h>
#include <linux/workqueue.h>
#include <linux/firmware.h>
#include <linux/wait.h>
#include <linux/completion.h>
struct rr_devsel;
struct rr_dev {
struct rr_devsel *devsel;
struct pci_driver *pci_driver;
struct pci_device_id *id_table;
struct pci_dev *pdev; /* non-null after pciprobe */
struct mutex mutex;
wait_queue_head_t q;
void *dmabuf;
char *fwname;
struct timespec irqtime;
unsigned long irqcount;
struct completion complete;
struct resource *area[3]; /* bar 0, 2, 4 */
void *remap[3]; /* ioremap of bar 0, 2, 4 */
unsigned long flags;
struct work_struct work;
const struct firmware *fw;
struct completion fw_load;
void (*load_program)(struct rr_dev *); /* lm32 */
int usecount;
#ifdef IS_SPEC_DEMO
struct miscdevice misc;
char miscname[32]; /* "spec-demo-<bus>-<slot> */
struct list_head list;
#endif
};
extern char *rr_fwname; /* module parameter. If "" then defaults apply */
#define RR_FLAG_REGISTERED 0x00000001
#define RR_FLAG_IRQDISABLE 0x00000002
#define RR_FLAG_IRQREQUEST 0x00000002
#define RR_PROBE_TIMEOUT (HZ) /* for pci_register_drv */
/* These two live in ./loader.c */
extern void rr_ask_firmware(struct rr_dev *dev);
extern void rr_load_firmware(struct work_struct *work);
/* And, for the spec only, this is in ./spec-loader.c */
extern void spec_ask_program(struct rr_dev *dev);
#endif /* __KERNEL__ */
/* By default, the driver registers for this vendor/devid */
#define RR_DEFAULT_VENDOR 0x1a39
#define RR_DEFAULT_DEVICE 0x0004
#define RR_DEFAULT_FWNAME "rrabbit-%P-%p@%b"
#define RR_MAX_FWNAME_SIZE 64
#define RR_DEFAULT_BUFSIZE (1<<20) /* 1MB */
#define RR_PLIST_SIZE 4096 /* no PAGE_SIZE in user space */
#define RR_PLIST_LEN (RR_PLIST_SIZE / sizeof(void *))
#define RR_MAX_BUFSIZE (RR_PLIST_SIZE * RR_PLIST_LEN)
/* This structure is used to select the device to be accessed, via ioctl */
struct rr_devsel {
__u16 vendor;
__u16 device;
__u16 subvendor; /* RR_DEVSEL_UNUSED to ignore subvendor/dev */
__u16 subdevice;
__u16 bus; /* RR_DEVSEL_UNUSED to ignore bus and devfn */
__u16 devfn;
};
#define RR_DEVSEL_UNUSED 0xffff
/* Offsets for BAR areas in llseek() and/or ioctl */
#define RR_BAR_0 0x00000000
#define RR_BAR_2 0x20000000
#define RR_BAR_4 0x40000000
#define RR_BAR_BUF 0xc0000000 /* The DMA buffer */
#define RR_IS_DMABUF(addr) ((addr) >= RR_BAR_BUF)
#define __RR_GET_BAR(x) ((x) >> 28)
#define __RR_SET_BAR(x) ((x) << 28)
#define __RR_GET_OFF(x) ((x) & 0x0fffffff)
static inline int rr_is_valid_bar(unsigned long address)
{
int bar = __RR_GET_BAR(address);
return bar == 0 || bar == 2 || bar == 4 || bar == 0x0c;
}
static inline int rr_is_dmabuf_bar(unsigned long address)
{
int bar = __RR_GET_BAR(address);
return bar == 0x0c;
}
struct rr_iocmd {
__u32 address; /* bar and offset */
__u32 datasize; /* 1 or 2 or 4 or 8 */
union {
__u8 data8;
__u16 data16;
__u32 data32;
__u64 data64;
};
};
/* ioctl commands */
#define __RR_IOC_MAGIC '4' /* random or so */
#define RR_DEVSEL _IOW(__RR_IOC_MAGIC, 0, struct rr_devsel)
#define RR_DEVGET _IOR(__RR_IOC_MAGIC, 1, struct rr_devsel)
#define RR_READ _IOWR(__RR_IOC_MAGIC, 2, struct rr_iocmd)
#define RR_WRITE _IOW(__RR_IOC_MAGIC, 3, struct rr_iocmd)
#define RR_IRQWAIT _IO(__RR_IOC_MAGIC, 4)
#define RR_IRQENA _IO(__RR_IOC_MAGIC, 5)
#define RR_GETDMASIZE _IO(__RR_IOC_MAGIC, 6)
/* #define RR_SETDMASIZE _IO(__RR_IOC_MAGIC, 7, unsigned long) */
#define RR_GETPLIST _IO(__RR_IOC_MAGIC, 8) /* returns a whole page */
#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2])
/* Registers from the gennum header files */
enum {
GNGPIO_BASE = 0xA00,
GNGPIO_DIRECTION_MODE = GNGPIO_BASE + 0x4,
GNGPIO_OUTPUT_ENABLE = GNGPIO_BASE + 0x8,
GNGPIO_OUTPUT_VALUE = GNGPIO_BASE + 0xC,
GNGPIO_INPUT_VALUE = GNGPIO_BASE + 0x10,
FCL_BASE = 0xB00,
FCL_CTRL = FCL_BASE,
FCL_STATUS = FCL_BASE + 0x4,
FCL_IODATA_IN = FCL_BASE + 0x8,
FCL_IODATA_OUT = FCL_BASE + 0xC,
FCL_EN = FCL_BASE + 0x10,
FCL_TIMER_0 = FCL_BASE + 0x14,
FCL_TIMER_1 = FCL_BASE + 0x18,
FCL_CLK_DIV = FCL_BASE + 0x1C,
FCL_IRQ = FCL_BASE + 0x20,
FCL_TIMER_CTRL = FCL_BASE + 0x24,
FCL_IM = FCL_BASE + 0x28,
FCL_TIMER2_0 = FCL_BASE + 0x2C,
FCL_TIMER2_1 = FCL_BASE + 0x30,
FCL_DBG_STS = FCL_BASE + 0x34,
FCL_FIFO = 0xE00,
PCI_SYS_CFG_SYSTEM = 0x800
};
#endif /* __RAWRABBIT_H__ */
#ifndef __RR_IO_H
#define __RR_IO_H
#include <stdint.h>
#include <rawrabbit.h>
int rr_bind(int a_fd);
int rr_init(int bus, int devfn);
int rr_writel(uint32_t data, uint32_t addr);
uint32_t rr_readl(uint32_t addr);
int rr_load_bitstream(const void *data, int size8);
int rr_load_bitstream_from_file(const char *file_name);
#endif
SPEC_SW ?= $(shell readlink -f ~/wr-repos/spec-sw)
ETHERBONE ?= $(shell readlink -f ~/wr-repos/etherbone-core/api)
OBJS = fdelay_lib.o i2c_master.o onewire.o fdelay_bus.o fdelay_dmtd_calibration.o sveclib/sveclib.o sveclib/libvmebus.o speclib/speclib.o
CFLAGS = -I../include -g -Imini_bone -Ispec/tools -Isveclib -I.
#ifeq ($(SPEC_SW),)
#throw_error:
# @echo "SPEC software package location environment variable is not set. Can't compile :("
#endif
all: lib
#spec:
# ln -s $(SPEC_SW) spec
# ln -s $(ETHERBONE) etherbone
lib: $(OBJS)
gcc -shared -o libfinedelay.so $(OBJS)
ar rc libfinedelay.a $(OBJS)
clean:
rm -f *.o libfinedelay.so
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <getopt.h>
#include "fdelay_lib.h"
#include "sveclib/sveclib.h"
#include "speclib/speclib.h"
#include "fdelay_lib.h"
void printk() {};
static void fd_svec_writel(void *priv, uint32_t data, uint32_t addr)
{
svec_writel(priv, data, addr);
}
static uint32_t fd_svec_readl(void *priv, uint32_t addr)
{
return svec_readl(priv, addr);
}
static void fd_spec_writel(void *priv, uint32_t data, uint32_t addr)
{
spec_writel(priv, data, addr);
}
static uint32_t fd_spec_readl(void *priv, uint32_t addr)
{
return spec_readl(priv, addr);
}
#if 0
#endif
#define VENDOR_CERN 0xce42
#define DEVICE_FD_CORE 0xf19ede1a
#define DEVICE_VUART 0xe2d13d04
static int probe_svec(fdelay_device_t *dev, const char *location)
{
uint32_t map_base;
int slot;
void *card;
uint32_t core_base;
if (!strncmp(location, "svec:"), 5) {
sscanf(location+5, "%d,%x,%x", &slot, &map_base, &core_base);
} else
return -1;
card = svec_open(slot);
svec_set_map_base(card, map_base);
if(!card)
{
fprintf(stderr,"SVEC probe failed.\n");
return -1;
}
dev->priv_io = card;
dev->writel = fd_svec_writel;
dev->readl = fd_svec_readl;
dev->base_addr = core_base;
dbg("svec: using slot %d, A32/D32 base: 0x%x, core base 0x%x\n", slot, map_base, core_base);
return 0;
}
void loader_low_level() {};
static int probe_spec(fdelay_device_t *dev, const char *location)
{
uint32_t core_base;
int slot;
if (!strncmp(location, "spec:"), 5) {
sscanf(location+5, "%d,%x", &slot, &core_base);
} else
return -1;
dev->priv_io = spec_open(slot, -1);
if(!dev->priv_io)
{
fprintf(stderr,"Can't map the SPEC @ slot %d\n", slot);
return -1;
}
dev->writel = fd_spec_writel;
dev->readl = fd_spec_readl;
dev->base_addr = core_base;
dbg("spec: using slot %d, core base 0x%x\n", slot, core_base);
return 0;
}
int fdelay_probe(fdelay_device_t *dev, const char *location)
{
if(!probe_svec(dev, location))
return 0;
if(!probe_spec(dev, location))
return 0;
}
fdelay_device_t *fdelay_create()
{
return (fdelay_device_t *) malloc(sizeof(fdelay_device_t));
}
/*
FmcDelay1ns4Cha (a.k.a. The Fine Delay Card)
DMTD insertion delay calibration stuff
Short explaination:
We feed the input of the card with a perioid sequence of pulses, of a frequency, say,
1 MHz. The card is programmed to introduce a delay of Td. Then, we sample both the input
and the output of the card with a clock that is slightly offset in frequency wrs to the one that
was used to generate the pulses - in our case it's (1 + 1/16384) * 1 MHz. The resulting waveforms
are of very low frequency, but keep the phase shift of the original signals, scaled by a factor of 16384.
This way we can easily measure the actual insertion delay of the FD and apply a correction factor
for fdelay_configure_output().
Tomasz Włostowski/BE-CO-HT, 2012
(c) Copyright CERN 2012
Licensed under LGPL 2.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include <math.h>
#include "fd_channel_regs.h"
#include "fd_main_regs.h"
#include "fdelay_lib.h"
#include "fdelay_private.h"
extern void dbg(const char *fmt, ...);
extern int64_t get_tics();
extern void udelay(uint32_t usecs);
/* WR core shell communication functions */
/* Waits for a WR Core and returns the output of the previous command in rv */
static void wait_prompt(fdelay_device_t *dev, char *rv)
{
char buf[16384],c;
int pos = 0;
memset(buf, 0, sizeof(buf));
while(pos < sizeof(buf))
{
if(spec_vuart_rx(dev->priv_io, &c, 1) == 1)
{
buf[pos++] = c;
if(pos >= 5 && !strcmp(buf + pos - 5, "wrc# "))
{
int old_pos;
if(!rv)
return;
while(pos>0) if(buf[pos]=='\n'||buf[pos]=='\r')
break;
else
pos--;
pos-=2;
old_pos = pos;
while(pos>0) if(buf[pos]=='\n'||buf[pos]=='\r')
break;
else
pos--;
strncpy(rv, buf+pos+1, old_pos - pos);
rv[old_pos-pos]=0;
return;
}
}
}
dbg("Failure: shell buffer overflow.\n");
exit(1);
}
/* executes a shell command on the associated WR core */
static int wrc_shell_exec(fdelay_device_t *dev, const char *cmd, char *retval)
{
char c;
while(spec_vuart_rx(dev->priv_io, &c, 1) == 1);
spec_vuart_tx(dev->priv_io, (char *)cmd, strlen(cmd));
spec_vuart_tx(dev->priv_io, "\r", 1);
wait_prompt(dev, retval);
if(retval)
dbg("wr_core exec '%s', retval: '%s'\n", cmd, retval);
return 0;
}
#define DMTD_N_AVGS 10 /* number of average samples */
#define DELAY_SETPOINT 500000 /* test delay value */
#define DMTD_PULSE_PERIOD 144
#define DMTD_OUTPUT_PERIOD (16384 * DMTD_PULSE_PERIOD / 2) /* period of the DDMTD output signal in 62.5 MHz clock cycles */
struct dmtd_channel {
int64_t base;
int64_t prev_tag, phase;
int64_t period;
};
#define TAG_BITS 23
static void init_dmtd(struct dmtd_channel *ch, int64_t period)
{
ch->period = period;
ch->prev_tag = -1;
ch->base = 0;
}
static int read_dmtd(fdelay_device_t *dev, struct dmtd_channel *ch, int is_out)
{
fd_decl_private(dev)
uint32_t addr = (is_out ? FD_REG_DMTR_IN : FD_REG_DMTR_OUT);
uint32_t value = fd_readl(addr);
if(value & FD_DMTR_IN_RDY)
{
int64_t tag = (int64_t) (value & ((1<<TAG_BITS) - 1)) + ch->base;
if(ch->prev_tag >= 0 && tag < ch->prev_tag) /* DMTD tag counter has 23 bits. We need to unwrap it */
{
ch->base += (1LL<<TAG_BITS);
tag += (1LL<<TAG_BITS);
}
int64_t epoch = (tag / DMTD_OUTPUT_PERIOD) * DMTD_OUTPUT_PERIOD; /* calculate the offset between the beginning of DDMTD cycle and the current tag */
ch->phase = tag - epoch;
ch->prev_tag = tag;
return 1;
}
return 0;
}
void calibrate_channel(fdelay_device_t *dev, int channel, double *mean, double *std)
{
int64_t samples_in[DMTD_N_AVGS], samples_out[DMTD_N_AVGS], delta[DMTD_N_AVGS];
struct dmtd_channel ch_in, ch_out;
int i, n_in = 0, n_out = 0;
fd_decl_private(dev)
fdelay_configure_trigger(dev, 0, 0);
fd_writel(FD_CALR_PSEL_W(0), FD_REG_CALR);
/* Configure the output to introduce DELAY_SETPOINT delay (but with fixed offset set to 0)*/\
hw->calib.zero_offset[channel-1] = 0;
fdelay_configure_output(dev, channel, 1, (int64_t)DELAY_SETPOINT, 200000LL, 0LL, 1);
/* Disable ALL outputs to prevent the calibration pulses from driving whatever
is connected to the board */
sgpio_set_pin(dev, SGPIO_OUTPUT_EN(0), 0);
sgpio_set_pin(dev, SGPIO_OUTPUT_EN(1), 0);
sgpio_set_pin(dev, SGPIO_OUTPUT_EN(2), 0);
sgpio_set_pin(dev, SGPIO_OUTPUT_EN(3), 0);
/* Select internal trigger */
sgpio_set_pin(dev, SGPIO_TRIG_SEL, 0);
for(i=1;i<=4;i++) /* disable all other channels */
if(channel != i)
fd_writel(0, i * 0x100 + FD_REG_DCR);
fd_readl(FD_REG_DMTR_IN);
fd_readl(FD_REG_DMTR_OUT);
fdelay_configure_trigger(dev, 1, 0);
fd_writel(FD_CALR_PSEL_W(0) | FD_CALR_CAL_DMTD, FD_REG_CALR);
init_dmtd(&ch_in, DMTD_OUTPUT_PERIOD);
init_dmtd(&ch_out, DMTD_OUTPUT_PERIOD);
n_in = n_out = 0;
while(n_in < DMTD_N_AVGS || n_out < DMTD_N_AVGS) /* Get DMTD_N_AVGS samples to reduce error */
{
if(read_dmtd(dev, &ch_in, 0))
if(n_in < DMTD_N_AVGS) samples_in[n_in++] = ch_in.phase;
if(read_dmtd(dev, &ch_out, 1))
if(n_out < DMTD_N_AVGS) samples_out[n_out++] = ch_out.phase;
}
for(i=0;i<DMTD_N_AVGS;i++)
{
delta[i] = samples_out[i] - samples_in[i];
if(delta[i] < 0) delta[i] += DMTD_OUTPUT_PERIOD;
// printf("in %lld out %lld delta %lld\n", samples_in[i], samples_out[i], delta[i]);
}
double avg = 0, s= 0;
for(i=0;i<DMTD_N_AVGS;i++)
avg+=(double) (delta[i]);
avg/=(double)DMTD_N_AVGS;
double scalefact = (double) (DMTD_PULSE_PERIOD * 16000 / 2) / (double)DMTD_OUTPUT_PERIOD;
*mean = avg * scalefact;
for(i=0;i<DMTD_N_AVGS;i++)
s+=((double)delta[i]-avg) * ((double)delta[i]-avg);
*std = sqrt(s / (double)(DMTD_N_AVGS-1)) * scalefact;
}
int fdelay_dmtd_calibration(fdelay_device_t *dev, double *offsets)
{
char resp[1024];
char c;
int i;
fd_decl_private(dev)
int64_t base = 0, prev_tag = -1;
if(spec_load_lm32(dev->priv_io, "wrc.bin", 0xc0000))
{
dbg("Failed to load LM32 firmware\n");
return -1;
}
// sleep(2);
/* Configure the WR core to produce a proper calibration clock: */
/* Disable PTP and enter free-running master mode */
wrc_shell_exec(dev, "ptp stop", resp);
wrc_shell_exec(dev, "mode master", resp);
/* And lock the DMTD oscillator to the FMC clock instead of the SPEC 125 MHz oscillator. Set the FMC VCO DAC to 0
to have some headroom */
wrc_shell_exec(dev, "pll sdac 1 0", resp);
wrc_shell_exec(dev, "pll init 2 1 1", resp);
/* Wait until the PLL locks... */
while(1)
{
wrc_shell_exec(dev, "pll cl 0", resp);
if(!strcmp(resp, "1"))
break;
sleep(1);
}
double mean_out[4], std_out[4];
usleep(500000);
dbg("\n\nPerforming DDMTD delay calibration: \n");
for(i=1;i<=4;i++)
{
calibrate_channel(dev, i, &mean_out[i-1], &std_out[i-1]);
dbg("Channel %d: delay %.0f ps, std %.0f ps.\n", i, mean_out[i-1], std_out[i-1]);
}
return 0;
}
This diff is collapsed.
#include <stdio.h>
#include "fdelay_lib.h"
#include "fdelay_private.h"
#include "fd_main_regs.h"
#define M_SDA_OUT(x) { \
if(x) \
fd_writel(fd_readl(FD_REG_I2CR) | FD_I2CR_SDA_OUT, FD_REG_I2CR); \
else \
fd_writel(fd_readl(FD_REG_I2CR) & (~FD_I2CR_SDA_OUT), FD_REG_I2CR); \
udelay(10);\
}
#define M_SCL_OUT(x) { \
if(x) \
fd_writel(fd_readl(FD_REG_I2CR) | FD_I2CR_SCL_OUT, FD_REG_I2CR); \
else \
fd_writel(fd_readl(FD_REG_I2CR) & (~FD_I2CR_SCL_OUT), FD_REG_I2CR); \
udelay(10); \
}
#define M_SDA_IN ((fd_readl(FD_REG_I2CR) & FD_I2CR_SDA_IN) ? 1 : 0)
static void mi2c_start(fdelay_device_t *dev)
{
fd_decl_private(dev);
M_SDA_OUT(0);
M_SCL_OUT(0);
}
static void mi2c_repeat_start(fdelay_device_t *dev)
{
fd_decl_private(dev);
M_SDA_OUT(1);
M_SCL_OUT(1);
M_SDA_OUT(0);
M_SCL_OUT(0);
}
static void mi2c_stop(fdelay_device_t *dev)
{
fd_decl_private(dev);
M_SDA_OUT(0);
M_SCL_OUT(1);
M_SDA_OUT(1);
}
int mi2c_put_byte(fdelay_device_t *dev, unsigned char data)
{
fd_decl_private(dev);
char i;
unsigned char ack;
for (i=0;i<8;i++, data<<=1)
{
M_SDA_OUT(data&0x80);
M_SCL_OUT(1);
M_SCL_OUT(0);
}
M_SDA_OUT(1);
M_SCL_OUT(1);
ack = M_SDA_IN; /* ack: sda is pulled low ->success. */
M_SCL_OUT(0);
M_SDA_OUT(0);
return ack!=0 ? -1 : 0;
}
void mi2c_get_byte(fdelay_device_t *dev, unsigned char *data, int ack)
{
fd_decl_private(dev)
int i;
unsigned char indata = 0;
/* assert: scl is low */
M_SCL_OUT(0);
M_SDA_OUT(1);
for (i=0;i<8;i++)
{
M_SCL_OUT(1);
indata <<= 1;
if ( M_SDA_IN ) indata |= 0x01;
M_SCL_OUT(0);
}
M_SDA_OUT((ack ? 0 : 1));
M_SCL_OUT(1);
M_SCL_OUT(0);
M_SDA_OUT(0);
*data= indata;
}
void mi2c_init(fdelay_device_t *dev)
{
fd_decl_private(dev);
M_SCL_OUT(1);
M_SDA_OUT(1);
}
void mi2c_scan(fdelay_device_t *dev)
{
int i;
for(i=0;i<256;i+=2)
{
mi2c_start(dev);
if(!mi2c_put_byte(dev,i))
printf("Found device at 0x%x\n", i>>1);
mi2c_stop(dev);
}
}
int eeprom_read(fdelay_device_t *dev, uint8_t i2c_addr, uint32_t offset, uint8_t *buf, size_t size)
{
int i;
unsigned char c;
for(i=0;i<size;i++)
{
mi2c_start(dev);
if(mi2c_put_byte(dev, i2c_addr << 1) < 0)
{
mi2c_stop(dev);
return -1;
}
mi2c_put_byte(dev, (offset >> 8) & 0xff);
mi2c_put_byte(dev, offset & 0xff);
offset++;
mi2c_stop(dev);
mi2c_start(dev);
mi2c_put_byte(dev, (i2c_addr << 1) | 1);
mi2c_get_byte(dev, &c, 0);
// printf("readback: %x\n", c);
*buf++ = c;
mi2c_stop(dev);
}
return size;
}
int eeprom_write(fdelay_device_t *dev, uint8_t i2c_addr, uint32_t offset, uint8_t *buf, size_t size)
{
int i, busy;
for(i=0;i<size;i++)
{
mi2c_start(dev);
if(mi2c_put_byte(dev, i2c_addr << 1) < 0)
{
mi2c_stop(dev);
return -1;
}
mi2c_put_byte(dev, (offset >> 8) & 0xff);
mi2c_put_byte(dev, offset & 0xff);
mi2c_put_byte(dev, *buf++);
offset++;
mi2c_stop(dev);
do /* wait until the chip becomes ready */
{
mi2c_start(dev);
busy = mi2c_put_byte(dev, i2c_addr << 1);
mi2c_stop(dev);
} while(busy);
}
return size;
}
#include <stdio.h>
#include <stdint.h>
#include "fdelay_lib.h"
#include "fdelay_private.h"
#define R_CSR 0x0
#define R_CDR 0x4
#define CSR_DAT_MSK (1<<0)
#define CSR_RST_MSK (1<<1)
#define CSR_OVD_MSK (1<<2)
#define CSR_CYC_MSK (1<<3)
#define CSR_PWR_MSK (1<<4)
#define CSR_IRQ_MSK (1<<6)
#define CSR_IEN_MSK (1<<7)
#define CSR_SEL_OFS 8
#define CSR_SEL_MSK (0xF<<8)
#define CSR_POWER_OFS 16
#define CSR_POWER_MSK (0xFFFF<<16)
#define CDR_NOR_MSK (0xFFFF<<0)
#define CDR_OVD_OFS 16
#define CDR_OVD_MSK (0xFFFF<<16)
#define ow_writel(data, addr) dev->writel(dev->priv_io, data, (hw->base_onewire + (addr)))
#define ow_readl(addr) dev->readl(dev->priv_io, (hw->base_onewire + (addr)))
#define CLK_DIV_NOR 624/2
#define CLK_DIV_OVD 124/2
static void ow_init(fdelay_device_t *dev)
{
fd_decl_private(dev);
ow_writel(((CLK_DIV_NOR & CDR_NOR_MSK) | (( CLK_DIV_OVD << CDR_OVD_OFS) & CDR_OVD_MSK)), R_CDR);
}
static int ow_reset(fdelay_device_t *dev, int port)
{
fd_decl_private(dev);
uint32_t data = ((port<<CSR_SEL_OFS) & CSR_SEL_MSK) | CSR_CYC_MSK | CSR_RST_MSK;
ow_writel(data, R_CSR);
while(ow_readl(R_CSR) & CSR_CYC_MSK);
uint32_t reg = ow_readl(R_CSR);
return ~reg & CSR_DAT_MSK;
}
static int slot(fdelay_device_t *dev, int port, int bit)
{
fd_decl_private(dev);
uint32_t data;
data = ((port<<CSR_SEL_OFS) & CSR_SEL_MSK) | CSR_CYC_MSK | (bit & CSR_DAT_MSK);
ow_writel(data, R_CSR);
while(ow_readl(R_CSR) & CSR_CYC_MSK);
uint32_t reg = ow_readl(R_CSR);
return reg & CSR_DAT_MSK;
}
static int read_bit(fdelay_device_t *dev, int port) { return slot(dev, port, 0x1); }
static int write_bit(fdelay_device_t *dev, int port, int bit) { return slot(dev, port, bit); }
int ow_read_byte(fdelay_device_t *dev, int port) {
int data = 0, i;
for(i=0;i<8;i++)
data |= read_bit(dev, port) << i;
return data;
}
int ow_write_byte(fdelay_device_t *dev, int port, int byte)
{
int data = 0;
int byte_old = byte, i;
for (i=0;i<8;i++){
data |= write_bit(dev, port, (byte & 0x1)) << i;
byte >>= 1;
}
return byte_old == data ? 0 : -1;
}
int ow_write_block(fdelay_device_t *dev, int port, uint8_t *block, int len)
{
int i;
for(i=0;i<len;i++)
{
*block++ = ow_write_byte(dev, port, *block);
}
return 0;
}
int ow_read_block(fdelay_device_t *dev, int port, uint8_t *block, int len)
{
int i;
for(i=0;i<len;i++)
{
*block++ = ow_read_byte(dev, port);
}
return 0;
}
#define ROM_SEARCH 0xF0
#define ROM_READ 0x33
#define ROM_MATCH 0x55
#define ROM_SKIP 0xCC
#define ROM_ALARM_SEARCH 0xEC
#define CONVERT_TEMP 0x44
#define WRITE_SCRATCHPAD 0x4E
#define READ_SCRATCHPAD 0xBE
#define COPY_SCRATCHPAD 0x48
#define RECALL_EEPROM 0xB8
#define READ_POWER_SUPPLY 0xB4
static uint8_t ds18x_id [8];
int ds18x_read_serial(fdelay_device_t *dev, uint8_t *id)
{
int i;
if(!ow_reset(dev, 0))
return -1;
ow_write_byte(dev, 0, ROM_READ);
for(i=0;i<8;i++)
{
*id = ow_read_byte(dev, 0);
id++;
}
return 0;
}
static int ds18x_access(fdelay_device_t *dev, uint8_t *id)
{
int i;
if(!ow_reset(dev, 0))
return -1;
if(ow_write_byte(dev, 0, ROM_MATCH) < 0)
return -1;
for(i=0;i<8;i++)
if(ow_write_byte(dev, 0, id[i]) < 0)
return -1;
}
int ds18x_read_temp(fdelay_device_t *dev, int *temp_r)
{
int i;
uint8_t data[9];
if(ds18x_access(dev, ds18x_id) < 0)
return -1;
ow_write_byte(dev, 0, READ_SCRATCHPAD);
for(i=0;i<9;i++) data[i] = ow_read_byte(dev, 0);
int temp = ((int)data[1] << 8) | ((int)data[0]);
if(temp & 0x1000)
temp = -0x10000 + temp;
ds18x_access(dev, ds18x_id);
ow_write_byte(dev, 0, CONVERT_TEMP);
if(temp_r) *temp_r = temp;
return 0;
}
int ds18x_init(fdelay_device_t *dev)
{
ow_init(dev);
if(ds18x_read_serial(dev, ds18x_id) < 0)
return -1;
dbg("Found DS18xx sensor: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
ds18x_id[0], ds18x_id[1], ds18x_id[2], ds18x_id[3],
ds18x_id[4], ds18x_id[5], ds18x_id[6], ds18x_id[7]);
ds18x_read_temp(dev, NULL);
sleep(1);
return 0;
}
/*
* main.c
*
* Created on: Aug 10, 2012
* Author: bbielawski
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/time.h>
#include <unistd.h>
#include "etherbone.h"
static eb_socket_t socket;
static inline void process_result(eb_status_t result)
{
if (result != EB_OK)
{
printf("Error: %s\n", eb_status(result));
// exit(1);
}
return;
}
eb_status_t ebs_block_write(eb_device_t device, eb_address_t address, eb_data_t* data, int count, int autoincrement_address)
{
int write_done = 0;
void wr_callback(eb_user_data_t data, eb_device_t device, eb_operation_t operation, eb_status_t status)
{
write_done = 1;
}
eb_cycle_t cycle;
eb_status_t status = eb_cycle_open(device, NULL, wr_callback, &cycle);
if (status != EB_OK)
return status;
int i;
for (i = 0; i < count; i++)
{
eb_cycle_write(cycle, address, EB_DATA32 | EB_LITTLE_ENDIAN, data[i]);
if (autoincrement_address)
address += 4;
}
eb_cycle_close(cycle);
status = eb_device_flush(device);
while (!write_done) eb_socket_run(socket, 10); //wait forever
return status;
}
eb_status_t ebs_block_read(eb_device_t device, eb_address_t read_address, eb_data_t *rdata, int count, int autoincrement_address)
{
int read_done = 0;
void rd_callback(eb_user_data_t data, eb_device_t device, eb_operation_t op, eb_status_t status)
{
static int c = 0;
if (status != EB_OK)
{
fprintf(stderr, "read failed: %s\n", eb_status(status));
exit(-1);
}
for(; op != EB_NULL; op = eb_operation_next(op)) {
/* We read low bits first */
*rdata++ = eb_operation_data(op);
}
read_done = 1;
}
eb_cycle_t cycle;
eb_status_t status = eb_cycle_open(device, NULL, rd_callback, &cycle);
if (status != EB_OK)
return status;
int i;
for (i = 0; i < count; i++)
{
eb_cycle_read(cycle, read_address, EB_DATA32 | EB_LITTLE_ENDIAN, NULL);
if(autoincrement_address)
read_address += 4;
}
eb_cycle_close(cycle);
status = eb_device_flush(device);
while (!read_done) eb_socket_run(socket, -1); //wait forever
return status;
}
uint32_t ebs_read(eb_device_t device, eb_address_t addr)
{
eb_data_t rdata;
ebs_block_read(device, addr, &rdata, 1, 0);
return rdata;
}
void ebs_write(eb_device_t device, eb_address_t addr, eb_data_t data)
{
ebs_block_write(device, addr, &data, 1, 0);
}
eb_status_t ebs_init()
{
eb_status_t status = EB_OK;
status = eb_socket_open(EB_ABI_CODE, 0, EB_DATA32 | EB_ADDR32, &socket);
process_result(status);
}
eb_status_t ebs_shutdown()
{
return eb_socket_close(socket);
}
eb_status_t ebs_open(eb_device_t *dev, const char *network_address)
{
eb_status_t status = EB_OK;
status = eb_device_open(socket, network_address, EB_DATA32 | EB_ADDR32, 5, dev);
process_result(status);
return status;
}
eb_status_t ebs_close(eb_device_t dev)
{
return eb_device_close(dev);
}
struct bus_record {
int i;
int stop;
eb_address_t addr_first, addr_last;
struct bus_record* parent;
};
int ebs_sdb_find_device(eb_device_t dev, uint32_t vendor, uint32_t device, int seq, uint32_t *base_addr)
{
struct bus_record br;
int done = 0, found = 0, n = 0;
void scan_cb(eb_user_data_t user, eb_device_t dev, sdb_t sdb, eb_status_t status) {
struct bus_record br;
int devices;
br.parent = (struct bus_record*)user;
br.parent->stop = 1;
if (status != EB_OK) {
fprintf(stderr, "failed to retrieve SDB: %s\n", eb_status(status));
exit(1);
}
devices = sdb->interconnect.sdb_records - 1;
for (br.i = 0; br.i < devices; ++br.i) {
sdb_record_t des;
des = &sdb->record[br.i];
if(des->empty.record_type == sdb_device)
{
if(des->device.sdb_component.product.vendor_id == vendor &&
des->device.sdb_component.product.device_id == device)
{
if(n == seq)
{
*base_addr = des->device.sdb_component.addr_first;
found = 1;
return;
}
n ++;
}
}
}
done = 1;
}
br.parent = 0;
br.i = -1;
br.stop = 0;
br.addr_first = 0;
br.addr_last = ~(eb_address_t)0;
br.addr_last >>= (sizeof(eb_address_t) - (eb_device_width(dev) >> 4))*8;
if(eb_sdb_scan_root(dev, &br, &scan_cb) != EB_OK)
return -1;
while(!done && !found) // fixme: crap code
eb_socket_run(eb_device_socket(dev), -1);
return found;
}
#if 0
main()
{
eb_device_t dev;
uint32_t base;
ebs_init();
ebs_open(&dev, "udp/192.168.10.11");
ebs_sdb_find_device(dev, 0xce42, 0xf19ede1a, 0, &base);
printf("base addr: %x\n", base);
}
#endif
#ifndef __SIMPLE_EB_H
#define __SIMPLE_EB_H
#include <stdint.h>
#include "etherbone.h"
eb_status_t ebs_block_write(eb_device_t device, eb_address_t address, eb_data_t* data, int count, int autoincrement_address);
eb_status_t ebs_block_read(eb_device_t device, eb_address_t read_address, eb_data_t *rdata, int count, int autoincrement_address);
uint32_t ebs_read(eb_device_t device, eb_address_t addr);
void ebs_write(eb_device_t device, eb_address_t addr, eb_data_t data);
eb_status_t ebs_init();
eb_status_t ebs_shutdown();
eb_status_t ebs_open(eb_device_t *dev, const char *network_address);
eb_status_t ebs_close(eb_device_t dev);
int ebs_sdb_find_device(eb_device_t dev, uint32_t vendor, uint32_t device, int seq, uint32_t *base_addr);
#endif
#!/usr/bin/python
import sys
import PyQt4
import PyQt4.QtGui
import PyQt4.QtCore
import PyQt4.uic
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from fdelay_lib import FineDelay
FormClass = PyQt4.uic.loadUiType('fd_demo.ui')[0]
class MainWindow(QMainWindow, FormClass):
def __init__(self):
super(MainWindow, self).__init__()
self.setupUi(self)
# self.setWindowTitle("ion")
def channel_update(channel):
print("UpdateCh: %d" % channel)
en = ch_enable[channel-1].checkState();
dly = int(ch_nsec[channel-1].value() * 1000 + (ch_sec[channel-1].value() * 1000000000000))
w = int(ch_width[channel-1].value() * 1000)
card.conf_output(channel, en, dly, w)
def trigger_update():
card.conf_trigger(m.en_trigger.checkState(), m.en_term.checkState())
def on_ts_enable_disable():
print("ontsen")
card.conf_readout(m.en_ts.checkState())
prev_ts = 0
def on_ts_clear():
print("ontabclear")
poll_timer.stop()
for i in range(0, m.ts_table.rowCount()):
m.ts_table.removeRow(i)
prev_ts = 0
poll_timer.start()
def poll_timer_cb():
buf = card.read_ts()
for ts in buf:
global prev_ts
row = m.ts_table.rowCount()
m.ts_table.insertRow(row)
m.ts_table.setItem(row, 0, QTableWidgetItem("%d"%ts.seq_id))
m.ts_table.setItem(row, 1, QTableWidgetItem("%d"%ts.utc))
m.ts_table.setItem(row, 2, QTableWidgetItem("%.3f"%ts.nsecs()))
m.ts_table.setItem(row, 3, QTableWidgetItem("%.3f"%(ts.nsecs_full()-prev_ts)))
prev_ts = ts.nsecs_full()
# i = QTableWidgetItem()
m.ts_table.scrollToBottom()
m.wr_status.setText(card.get_sync_status())
def on_chk_wr():
if(m.wr_checkbox.checkState()):
card.conf_sync(card.SYNC_WR)
else:
card.conf_sync(card.SYNC_LOCAL)
if __name__ == "__main__":
import os,sys
card = FineDelay(sys.argv[1])
app = QApplication(sys.argv)
m = MainWindow()
m.show()
import os
m.setWindowTitle("Fine Delay Demo")
m.wr_status.setText("")
ch_enable = [m.en_ch1, m.en_ch2, m.en_ch3, m.en_ch4];
ch_nsec = [m.nsec_ch1, m.nsec_ch2, m.nsec_ch3, m.nsec_ch4];
ch_sec = [m.sec_ch1, m.sec_ch2, m.sec_ch3, m.sec_ch4];
ch_width = [m.width_ch1, m.width_ch2, m.width_ch3, m.width_ch4];
for i in range(1,5):
channel_update(i)
ch_enable[0].stateChanged.connect(lambda :channel_update(1))
ch_enable[1].stateChanged.connect(lambda :channel_update(2))
ch_enable[2].stateChanged.connect(lambda :channel_update(3))
ch_enable[3].stateChanged.connect(lambda :channel_update(4))
ch_nsec[0].valueChanged.connect(lambda :channel_update(1))
ch_nsec[1].valueChanged.connect(lambda :channel_update(2))
ch_nsec[2].valueChanged.connect(lambda :channel_update(3))
ch_nsec[3].valueChanged.connect(lambda :channel_update(4))
ch_sec[0].valueChanged.connect(lambda :channel_update(1))
ch_sec[1].valueChanged.connect(lambda :channel_update(2))
ch_sec[2].valueChanged.connect(lambda :channel_update(3))
ch_sec[3].valueChanged.connect(lambda :channel_update(4))
ch_width[0].valueChanged.connect(lambda :channel_update(1))
ch_width[1].valueChanged.connect(lambda :channel_update(2))
ch_width[2].valueChanged.connect(lambda :channel_update(3))
ch_width[3].valueChanged.connect(lambda :channel_update(4))
m.en_trigger.stateChanged.connect(lambda :trigger_update())
m.en_term.stateChanged.connect(lambda :trigger_update())
m.en_ts.stateChanged.connect(on_ts_enable_disable)
m.wr_checkbox.stateChanged.connect(on_chk_wr)
m.btn_clear.clicked.connect(on_ts_clear)
trigger_update();
on_ts_enable_disable()
m.ts_table.clearContents()
# m.ts_table
poll_timer = QTimer()
poll_timer.setInterval(200)
poll_timer.timeout.connect(poll_timer_cb)
poll_timer.start()
app.exec_()
This diff is collapsed.
#!/usr/bin/python
from ctypes import *
import sys
import re
import os
class fd_timestamp(Structure):
_fields_ = [("utc", c_ulonglong),
("coarse", c_ulong),
("frac", c_ulong),
("seq_id", c_ushort),
("channel", c_int)]
def nsecs(self):
return (float(self.frac) * 8000.0 / 4096.0 + float(self.coarse) * 8000.0) / 1000.0;
def nsecs_full(self):
return (float(self.frac) * 8000.0 / 4096.0 + float(self.coarse) * 8000.0) / 1000.0 + float(self.utc) * 1000000000.0;
def __str__(self):
return "%d:%d" % (self.utc, self.nsecs())
class FineDelay:
SYNC_LOCAL = 1
SYNC_WR = 2
def __init__(self, location="udp/192.168.10.11"):
self.fdelay = CDLL('../lib/libfinedelay.so')
self.handle = self.fdelay.fdelay_create();
if(self.fdelay.fdelay_probe(self.handle, c_char_p(location)) < 0):
print ("FD enumeration failed")
sys.exit(-1)
print "Initializing Fine Delay board..."
if(self.fdelay.fdelay_init(self.handle) < 0):
print ("Init failed..");
sys.exit(-1)
def conf_trigger(self, enable, termination):
self.fdelay.fdelay_configure_trigger(self.handle, c_int(enable), c_int(termination))
def conf_output(self, channel, enable, delay, width):
self.fdelay.fdelay_configure_output(self.handle, c_int(channel), c_int(enable), c_ulonglong(delay), c_ulonglong(width), c_ulonglong(200000), c_int(1))
def conf_readout(self, enable):
self.fdelay.fdelay_configure_readout(self.handle, enable)
def conf_sync(self, mode):
self.fdelay.fdelay_configure_sync(self.handle, mode)
# def conf_pulsegen(self, channel, enable, t_start_utc, t_start_coarse, width, delta, count):
# t = fd_timestamp(utc=c_ulonglong(t_start_utc), coarse=c_ulong(t_start_coarse))
# #print "channel:%d enable:%d start_t:%d width:%d delta:%d count:%d"%(channel, enable, t.utc, width, delta, count)
# self.fdelay.fdelay_configure_pulse_gen(self.handle, c_int(channel), c_int(enable), t,
# c_ulonglong(width), c_ulonglong(delta), c_int(count))
# def set_time(self, utc, coarse):
# t = fd_timestamp(utc=c_ulonglong(utc), coarse=c_ulong(coarse))
# self.fdelay.fdelay_set_time(self.handle, t)
# def get_time(self):
# t = fd_timestamp()
# self.fdelay.fdelay_get_time(self.handle, byref(t))
# return t
def get_sync_status(self):
c = self.fdelay.fdelay_check_sync(self.handle)
if(c):
return "synced"
else:
return "not synced"
def read_ts(self):
buf = (fd_timestamp * 256)();
ptr = pointer(buf)
n = self.fdelay.fdelay_read(self.handle, ptr, 256)
arr = [];
for i in range(0,n):
arr.append(buf[i])
return arr
TESTS = gs_logger simple_delay random_pulse_gen
CFLAGS = -I../include
LDFLAGS = -L../lib ../lib/libfinedelay.a -lm
CC=gcc
.PHONY: all
all: $(TESTS)
define TEST_template =
$(1): $$($(1).o)
endef
$(foreach test,$(TESTS),$(eval $(call TEST_template,$(test))))
$(TESTS):
gcc $@.c -o $@ $(CFLAGS) $(LDFLAGS)
clean:
rm -f $(ALL_OBJS) $(TESTS)
\ No newline at end of file
#include <stdio.h>
#include "fdelay_lib.h"
main(int argc, char *argv[])
{
fdelay_device_t dev;
/* Initialize the fine delay generator */
if(spec_fdelay_create(&dev, argc, argv) < 0)
{
printf("Probe failed.\n");
return -1;
}
if(fdelay_init(&dev, 0) < 0)
{
printf("Init failed.\n");
return -1;
}
fdelay_dmtd_calibration(&dev, NULL);
return 0;
}
This diff is collapsed.
#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)
location eb:192.168.10.11
# 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 -63100p
output_offset 14400p
# Output configuration
# out output_ID offset_from_pps[ps] width[ps] period[ps]
# out 1 = PPS signal, 1us pulse width
out 1 0 100m 1s
out 2 0 500u 1000u
out 4 0 500u 1000u
out 4 0 10u 99999990p
# #######################
# # Select board 1
# #######################
#
#\board 1
#hw_index 0x0500
#input_offset -63100p
#output_offset 14400p
#termination 1
#out 1 0 500u 1000u
#out 2 0 500u 1000u
#out 4 0 500u 1000u
#out 3 0 100u 200u
#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"
/* 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;
}
fdelay_time_t ts_sub(fdelay_time_t a, fdelay_time_t b)
{
a.frac -= b.frac;
if(a.frac < 0)
{
a.frac += 4096;
a.coarse--;
}
a.coarse -= b.coarse;
if(a.coarse < 0)
{
a.coarse += 125000000;
a.utc --;
}
a.utc-=b.utc;
return a;
}
int64_t rrand64(int64_t min, int64_t max)
{
int i;
uint64_t tmp = 0;
for(i=0;i<32;i++)
tmp ^= ((uint64_t)random()) << i;
tmp %= (max-min+1);
return min+tmp;
}
int armed = 0;
static int64_t min_gap, max_gap;
static fdelay_time_t t;
void produce_pulses(fdelay_device_t *b)
{
int64_t delta;
fdelay_time_t td;
if(armed && !fdelay_channel_triggered(b, 1))
return ;
delta = rrand64(min_gap, max_gap);
fdelay_get_time(b, &t);
td = fdelay_from_picos(delta);
t = ts_add(t, td);
fdelay_configure_pulse_gen(b, 1, 1, t, min_gap/3, 0, 1);
armed = 1;
}
int main(int argc, char *argv[])
{
if(argc < 4)
{
fprintf(stderr, "usage: %s card_location min_period[us] max_period[us] count\n", argv[0]);
return 0;
}
fdelay_device_t *b = fdelay_create();
if(fdelay_probe(b, argv[1]) < 0)
{
fprintf(stderr, "Probing failed\n");
return 0;
}
fdelay_init(b, 0);
fdelay_configure_trigger(b, 0, 0);
int count = atoi(argv[4]);
min_gap =(int64_t) (atof(argv[2]) * 1000000.0);
max_gap =(int64_t) (atof(argv[3]) * 1000000.0);
int i = 0;
while(count < 0 || (i < count))
{
produce_pulses(b);
i++;
}
printf("generated %d pulses\n", i);
return 0;
}
This diff is collapsed.
/* 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"
int configure_board(fdelay_device_t *b, int argc, char *argv[])
{
fdelay_time_t t;
if(spec_fdelay_create(b, argc, argv) < 0)
{
printf("Probe failed\n");
exit(-1);
}
if(fdelay_init(b, 0) < 0)
{
printf("Init failed\n");
exit(-1);
}
fdelay_configure_sync(b, FDELAY_SYNC_LOCAL);
fdelay_get_time(b, &t);
t.frac = 0;
t.coarse = 0;
t.utc += 2;
sleep(1);
fdelay_configure_pulse_gen(b, 1, 1, t, 10 * 1000000, 99999990, -1);
fdelay_configure_trigger(b, 0, 1);
fdelay_raw_readout(b, 0);
fdelay_configure_readout(b, 0);
fdelay_configure_readout(b, 1);
fdelay_configure_trigger(b, 1, 0);
printf("Configuration complete\n");
fflush(stdout);
return 0;
}
void handle_readout(fdelay_device_t *b, int n_samples)
{
int64_t t_ps;
fdelay_time_t t;
static time_t start;
static int64_t t_prev;
static int prev_seq = -1;
int done;
for(;;)
while(fdelay_read(b, &t, 1) == 1)
{
t_ps = (t.coarse * 8000LL) + ((t.frac * 8000LL) >> 12);
int64_t delta = t_ps-t_prev;
if(delta < 0)
delta += 1000000000000LL;
if(prev_seq >= 0)
printf("Samp %lli.%03lli %lli\n", t_ps / 1000LL, t_ps % 1000LL, delta) ;
prev_seq = t.seq_id;
t_prev=t_ps;
n_samples--;
if(!n_samples) return;
}
}
int main(int argc, char *argv[])
{
fdelay_device_t b;
configure_board(&b, argc, argv);
handle_readout(&b, 40000);
}
This diff is collapsed.
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