Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
P
Production Test Suite - base
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
1
Merge Requests
1
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
Production Test Suite - base
Commits
557f9512
Commit
557f9512
authored
Jun 03, 2013
by
Evangelia Gousiou
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fmctdc1ns5cha folders restructure
parent
2f5f41b7
Hide whitespace changes
Inline
Side-by-side
Showing
36 changed files
with
5579 additions
and
0 deletions
+5579
-0
acam_gpx.h
common/fmc_delay/include/acam_gpx.h
+83
-0
fd_channel_regs.h
common/fmc_delay/include/fd_channel_regs.h
+122
-0
fd_main_regs.h
common/fmc_delay/include/fd_main_regs.h
+456
-0
fdelay_lib.h
common/fmc_delay/include/fdelay_lib.h
+74
-0
fdelay_private.h
common/fmc_delay/include/fdelay_private.h
+97
-0
i2c_master.h
common/fmc_delay/include/i2c_master.h
+12
-0
onewire.h
common/fmc_delay/include/onewire.h
+10
-0
pll_config.h
common/fmc_delay/include/pll_config.h
+70
-0
rawrabbit.h
common/fmc_delay/include/rawrabbit.h
+173
-0
rr_io.h
common/fmc_delay/include/rr_io.h
+15
-0
Makefile
common/fmc_delay/lib/Makefile
+26
-0
fdelay_bus.c
common/fmc_delay/lib/fdelay_bus.c
+70
-0
fdelay_cal.c
common/fmc_delay/lib/fdelay_cal.c
+104
-0
fdelay_eeprom.c
common/fmc_delay/lib/fdelay_eeprom.c
+53
-0
fdelay_lib.c
common/fmc_delay/lib/fdelay_lib.c
+1400
-0
fdelay_pps_demo.c
common/fmc_delay/lib/fdelay_pps_demo.c
+30
-0
fdelay_temp_calibration.c
common/fmc_delay/lib/fdelay_temp_calibration.c
+60
-0
fdelay_test.c
common/fmc_delay/lib/fdelay_test.c
+56
-0
i2c_master.c
common/fmc_delay/lib/i2c_master.c
+177
-0
Makefile
common/fmc_delay/lib/mini_bone/Makefile
+4
-0
minibone_lib.c
common/fmc_delay/lib/mini_bone/minibone_lib.c
+207
-0
minibone_lib.h
common/fmc_delay/lib/mini_bone/minibone_lib.h
+14
-0
ptpd_netif.c
common/fmc_delay/lib/mini_bone/ptpd_netif.c
+241
-0
ptpd_netif.h
common/fmc_delay/lib/mini_bone/ptpd_netif.h
+239
-0
onewire.c
common/fmc_delay/lib/onewire.c
+183
-0
rr_io.c
common/fmc_delay/lib/rr_io.c
+257
-0
spec_common.c
common/fmc_delay/lib/spec_common.c
+65
-0
softpll_ng.c
common/fmc_delay/lib/spll/softpll_ng.c
+68
-0
spll_common.h
common/fmc_delay/lib/spll/spll_common.h
+95
-0
spll_defs.h
common/fmc_delay/lib/spll/spll_defs.h
+21
-0
spll_helper.h
common/fmc_delay/lib/spll/spll_helper.h
+206
-0
demo.py
common/fmc_delay/python/demo.py
+117
-0
fd_demo.ui
common/fmc_delay/python/fd_demo.ui
+657
-0
fdelay_lib.py
common/fmc_delay/python/fdelay_lib.py
+107
-0
gn4124.py
common/gn4124.py
+4
-0
pts.py
pts.py
+6
-0
No files found.
common/fmc_delay/include/acam_gpx.h
0 → 100644
View file @
557f9512
#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 AR3_RaSpeed(num,val) (val << (num*2 + 21))
#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
common/fmc_delay/include/fd_channel_regs.h
0 → 100644
View file @
557f9512
/*
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 : Wed Apr 11 11:05:22 2012
* 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 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
common/fmc_delay/include/fd_main_regs.h
0 → 100644
View file @
557f9512
/*
Register definitions for slave core: Fine Delay Main WB Slave
* File : fd_main_regs.h
* Author : auto-generated by wbgen2 from fd_main_wishbone_slave.wb
* Created : Wed Apr 11 11:05:22 2012
* Standard : ANSI C
THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE fd_main_wishbone_slave.wb
DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
*/
#ifndef __WBGEN2_REGDEFS_FD_MAIN_WISHBONE_SLAVE_WB
#define __WBGEN2_REGDEFS_FD_MAIN_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: Reset Register */
/* definitions for field: State of the reset Line of the FMC Card in reg: Reset Register */
#define FD_RSTR_RST_FMC_MASK WBGEN2_GEN_MASK(0, 1)
#define FD_RSTR_RST_FMC_SHIFT 0
#define FD_RSTR_RST_FMC_W(value) WBGEN2_GEN_WRITE(value, 0, 1)
#define FD_RSTR_RST_FMC_R(reg) WBGEN2_GEN_READ(reg, 0, 1)
/* definitions for field: State of the reset of the Fine Delay HDL Core in reg: Reset Register */
#define FD_RSTR_RST_CORE_MASK WBGEN2_GEN_MASK(1, 1)
#define FD_RSTR_RST_CORE_SHIFT 1
#define FD_RSTR_RST_CORE_W(value) WBGEN2_GEN_WRITE(value, 1, 1)
#define FD_RSTR_RST_CORE_R(reg) WBGEN2_GEN_READ(reg, 1, 1)
/* definitions for field: Reset magic value in reg: Reset Register */
#define FD_RSTR_LOCK_MASK WBGEN2_GEN_MASK(16, 16)
#define FD_RSTR_LOCK_SHIFT 16
#define FD_RSTR_LOCK_W(value) WBGEN2_GEN_WRITE(value, 16, 16)
#define FD_RSTR_LOCK_R(reg) WBGEN2_GEN_READ(reg, 16, 16)
/* definitions for register: ID Register */
/* definitions for register: Global Control Register */
/* definitions for field: Bypass Hardware TDC/Delay Controller in reg: Global Control Register */
#define FD_GCR_BYPASS WBGEN2_GEN_MASK(0, 1)
/* definitions for field: Enable trigger input in reg: Global Control Register */
#define FD_GCR_INPUT_EN WBGEN2_GEN_MASK(1, 1)
/* definitions for field: PLL Locked in reg: Global Control Register */
#define FD_GCR_DDR_LOCKED WBGEN2_GEN_MASK(2, 1)
/* definitions for field: Mezzanice Present in reg: Global Control Register */
#define FD_GCR_FMC_PRESENT WBGEN2_GEN_MASK(3, 1)
/* definitions for register: Timing Control Register */
/* definitions for field: DMTD Clock Status in reg: Timing Control Register */
#define FD_TCR_DMTD_STAT WBGEN2_GEN_MASK(0, 1)
/* definitions for field: WR Timing Enable in reg: Timing Control Register */
#define FD_TCR_WR_ENABLE WBGEN2_GEN_MASK(1, 1)
/* definitions for field: WR Timing Locked in reg: Timing Control Register */
#define FD_TCR_WR_LOCKED WBGEN2_GEN_MASK(2, 1)
/* definitions for field: WR Core Present in reg: Timing Control Register */
#define FD_TCR_WR_PRESENT WBGEN2_GEN_MASK(3, 1)
/* definitions for field: WR Core Time Ready in reg: Timing Control Register */
#define FD_TCR_WR_READY WBGEN2_GEN_MASK(4, 1)
/* definitions for field: WR Core Link Up in reg: Timing Control Register */
#define FD_TCR_WR_LINK WBGEN2_GEN_MASK(5, 1)
/* definitions for field: Capture Current Time in reg: Timing Control Register */
#define FD_TCR_CAP_TIME WBGEN2_GEN_MASK(6, 1)
/* definitions for field: Set Current Time in reg: Timing Control Register */
#define FD_TCR_SET_TIME WBGEN2_GEN_MASK(7, 1)
/* definitions for register: Time Register - TAI seconds (MSB) */
/* definitions for register: Time Register - TAI seconds (LSB) */
/* definitions for register: Time Register - sub-second 125 MHz clock cycles */
/* definitions for register: TDC Data Register */
/* definitions for register: TDC control/status reg */
/* definitions for field: Start TDC write in reg: TDC control/status reg */
#define FD_TDCSR_WRITE WBGEN2_GEN_MASK(0, 1)
/* definitions for field: Start TDC read in reg: TDC control/status reg */
#define FD_TDCSR_READ WBGEN2_GEN_MASK(1, 1)
/* definitions for field: Empty flag in reg: TDC control/status reg */
#define FD_TDCSR_EMPTY WBGEN2_GEN_MASK(2, 1)
/* definitions for field: Start enable in reg: TDC control/status reg */
#define FD_TDCSR_STOP_EN WBGEN2_GEN_MASK(3, 1)
/* definitions for field: Start disable in reg: TDC control/status reg */
#define FD_TDCSR_START_DIS WBGEN2_GEN_MASK(4, 1)
/* definitions for field: Stop enable in reg: TDC control/status reg */
#define FD_TDCSR_START_EN WBGEN2_GEN_MASK(5, 1)
/* definitions for field: Stop disable in reg: TDC control/status reg */
#define FD_TDCSR_STOP_DIS WBGEN2_GEN_MASK(6, 1)
/* definitions for field: write 1: Pulse the Alutrigger line in reg: TDC control/status reg */
#define FD_TDCSR_ALUTRIG WBGEN2_GEN_MASK(7, 1)
/* definitions for register: Calibration register */
/* definitions for field: Triggers calibration pulses in reg: Calibration register */
#define FD_CALR_CAL_PULSE WBGEN2_GEN_MASK(0, 1)
/* definitions for field: PPS Calibration output enable in reg: Calibration register */
#define FD_CALR_CAL_PPS WBGEN2_GEN_MASK(1, 1)
/* definitions for field: Triggers calibration pulses in reg: Calibration register */
#define FD_CALR_CAL_DMTD WBGEN2_GEN_MASK(2, 1)
/* definitions for field: Enable pulse generation in reg: Calibration register */
#define FD_CALR_PSEL_MASK WBGEN2_GEN_MASK(3, 4)
#define FD_CALR_PSEL_SHIFT 3
#define FD_CALR_PSEL_W(value) WBGEN2_GEN_WRITE(value, 3, 4)
#define FD_CALR_PSEL_R(reg) WBGEN2_GEN_READ(reg, 3, 4)
/* definitions for field: DMTD Feedback Channel Select in reg: Calibration register */
#define FD_CALR_DMTD_FBSEL WBGEN2_GEN_MASK(7, 1)
/* definitions for field: DMTD Tag in reg: Calibration register */
#define FD_CALR_DMTD_TAG_MASK WBGEN2_GEN_MASK(8, 23)
#define FD_CALR_DMTD_TAG_SHIFT 8
#define FD_CALR_DMTD_TAG_W(value) WBGEN2_GEN_WRITE(value, 8, 23)
#define FD_CALR_DMTD_TAG_R(reg) WBGEN2_GEN_READ(reg, 8, 23)
/* definitions for field: DMTD Tag Ready in reg: Calibration register */
#define FD_CALR_DMTD_TAG_RDY WBGEN2_GEN_MASK(31, 1)
/* definitions for register: Softpll Register */
/* definitions for field: Frequency/Phase tag in reg: Softpll Register */
#define FD_SPLLR_TAG_MASK WBGEN2_GEN_MASK(0, 20)
#define FD_SPLLR_TAG_SHIFT 0
#define FD_SPLLR_TAG_W(value) WBGEN2_GEN_WRITE(value, 0, 20)
#define FD_SPLLR_TAG_R(reg) WBGEN2_GEN_READ(reg, 0, 20)
/* definitions for field: Tag Ready in reg: Softpll Register */
#define FD_SPLLR_TAG_RDY WBGEN2_GEN_MASK(20, 1)
/* definitions for field: Freq/Phase mode select in reg: Softpll Register */
#define FD_SPLLR_MODE WBGEN2_GEN_MASK(21, 1)
/* definitions for register: Softpll DAC Register */
/* definitions for field: DAC Value in reg: Softpll DAC Register */
#define FD_SDACR_DAC_VAL_MASK WBGEN2_GEN_MASK(0, 16)
#define FD_SDACR_DAC_VAL_SHIFT 0
#define FD_SDACR_DAC_VAL_W(value) WBGEN2_GEN_WRITE(value, 0, 16)
#define FD_SDACR_DAC_VAL_R(reg) WBGEN2_GEN_READ(reg, 0, 16)
/* definitions for register: Acam to Delay line fractional part Scale Factor Register */
/* definitions for register: Acam Timestamp Merging Control Register */
/* definitions for field: Wraparound Coarse Threshold in reg: Acam Timestamp Merging Control Register */
#define FD_ATMCR_C_THR_MASK WBGEN2_GEN_MASK(0, 4)
#define FD_ATMCR_C_THR_SHIFT 0
#define FD_ATMCR_C_THR_W(value) WBGEN2_GEN_WRITE(value, 0, 4)
#define FD_ATMCR_C_THR_R(reg) WBGEN2_GEN_READ(reg, 0, 4)
/* definitions for field: Wraparound Fine Threshold in reg: Acam Timestamp Merging Control Register */
#define FD_ATMCR_F_THR_MASK WBGEN2_GEN_MASK(4, 23)
#define FD_ATMCR_F_THR_SHIFT 4
#define FD_ATMCR_F_THR_W(value) WBGEN2_GEN_WRITE(value, 4, 23)
#define FD_ATMCR_F_THR_R(reg) WBGEN2_GEN_READ(reg, 4, 23)
/* definitions for register: Acam Start Offset Register */
/* definitions for field: Start Offset in reg: Acam Start Offset Register */
#define FD_ASOR_OFFSET_MASK WBGEN2_GEN_MASK(0, 23)
#define FD_ASOR_OFFSET_SHIFT 0
#define FD_ASOR_OFFSET_W(value) WBGEN2_GEN_WRITE(value, 0, 23)
#define FD_ASOR_OFFSET_R(reg) WBGEN2_GEN_READ(reg, 0, 23)
/* definitions for register: Raw Input Events Counter Register */
/* definitions for register: Tagged Input Events Counter Register */
/* definitions for register: Input Event Processing Delay Register */
/* definitions for field: Reset stats in reg: Input Event Processing Delay Register */
#define FD_IEPD_RST_STAT WBGEN2_GEN_MASK(0, 1)
/* definitions for field: Processing delay in reg: Input Event Processing Delay Register */
#define FD_IEPD_PDELAY_MASK WBGEN2_GEN_MASK(1, 8)
#define FD_IEPD_PDELAY_SHIFT 1
#define FD_IEPD_PDELAY_W(value) WBGEN2_GEN_WRITE(value, 1, 8)
#define FD_IEPD_PDELAY_R(reg) WBGEN2_GEN_READ(reg, 1, 8)
/* definitions for register: SPI Control Register */
/* definitions for field: Data in reg: SPI Control Register */
#define FD_SCR_DATA_MASK WBGEN2_GEN_MASK(0, 24)
#define FD_SCR_DATA_SHIFT 0
#define FD_SCR_DATA_W(value) WBGEN2_GEN_WRITE(value, 0, 24)
#define FD_SCR_DATA_R(reg) WBGEN2_GEN_READ(reg, 0, 24)
/* definitions for field: Select DAC in reg: SPI Control Register */
#define FD_SCR_SEL_DAC WBGEN2_GEN_MASK(24, 1)
/* definitions for field: Select PLL in reg: SPI Control Register */
#define FD_SCR_SEL_PLL WBGEN2_GEN_MASK(25, 1)
/* definitions for field: Select GPIO in reg: SPI Control Register */
#define FD_SCR_SEL_GPIO WBGEN2_GEN_MASK(26, 1)
/* definitions for field: Ready flag in reg: SPI Control Register */
#define FD_SCR_READY WBGEN2_GEN_MASK(27, 1)
/* definitions for field: Clock Polarity in reg: SPI Control Register */
#define FD_SCR_CPOL WBGEN2_GEN_MASK(28, 1)
/* definitions for field: Transfer Start in reg: SPI Control Register */
#define FD_SCR_START WBGEN2_GEN_MASK(29, 1)
/* definitions for register: Reference Clock Rate Register */
/* definitions for register: Timestamp Buffer Control Register */
/* definitions for field: Channel Mask in reg: Timestamp Buffer Control Register */
#define FD_TSBCR_CHAN_MASK_MASK WBGEN2_GEN_MASK(0, 5)
#define FD_TSBCR_CHAN_MASK_SHIFT 0
#define FD_TSBCR_CHAN_MASK_W(value) WBGEN2_GEN_WRITE(value, 0, 5)
#define FD_TSBCR_CHAN_MASK_R(reg) WBGEN2_GEN_READ(reg, 0, 5)
/* definitions for field: Buffer enable in reg: Timestamp Buffer Control Register */
#define FD_TSBCR_ENABLE WBGEN2_GEN_MASK(5, 1)
/* definitions for field: Buffer purge in reg: Timestamp Buffer Control Register */
#define FD_TSBCR_PURGE WBGEN2_GEN_MASK(6, 1)
/* definitions for field: Reset TS Sequence Numbers in reg: Timestamp Buffer Control Register */
#define FD_TSBCR_RST_SEQ WBGEN2_GEN_MASK(7, 1)
/* definitions for field: Buffer full in reg: Timestamp Buffer Control Register */
#define FD_TSBCR_FULL WBGEN2_GEN_MASK(8, 1)
/* definitions for field: Buffer empty in reg: Timestamp Buffer Control Register */
#define FD_TSBCR_EMPTY WBGEN2_GEN_MASK(9, 1)
/* definitions for field: Buffer entries count in reg: Timestamp Buffer Control Register */
#define FD_TSBCR_COUNT_MASK WBGEN2_GEN_MASK(10, 12)
#define FD_TSBCR_COUNT_SHIFT 10
#define FD_TSBCR_COUNT_W(value) WBGEN2_GEN_WRITE(value, 10, 12)
#define FD_TSBCR_COUNT_R(reg) WBGEN2_GEN_READ(reg, 10, 12)
/* definitions for register: Timestamp Buffer Interrupt Register */
/* definitions for field: IRQ timeout [milliseconds] in reg: Timestamp Buffer Interrupt Register */
#define FD_TSBIR_TIMEOUT_MASK WBGEN2_GEN_MASK(0, 10)
#define FD_TSBIR_TIMEOUT_SHIFT 0
#define FD_TSBIR_TIMEOUT_W(value) WBGEN2_GEN_WRITE(value, 0, 10)
#define FD_TSBIR_TIMEOUT_R(reg) WBGEN2_GEN_READ(reg, 0, 10)
/* definitions for field: Interrupt threshold in reg: Timestamp Buffer Interrupt Register */
#define FD_TSBIR_THRESHOLD_MASK WBGEN2_GEN_MASK(10, 12)
#define FD_TSBIR_THRESHOLD_SHIFT 10
#define FD_TSBIR_THRESHOLD_W(value) WBGEN2_GEN_WRITE(value, 10, 12)
#define FD_TSBIR_THRESHOLD_R(reg) WBGEN2_GEN_READ(reg, 10, 12)
/* definitions for register: Timestamp Buffer Readout Seconds Register (MSB) */
/* definitions for register: Timestamp Buffer Readout Seconds Register (LSB) */
/* definitions for register: Timestamp Buffer Readout Cycles Register */
/* definitions for register: Timestamp Buffer Readout Fine / Channel / Seq ID Register */
/* definitions for field: Channel ID in reg: Timestamp Buffer Readout Fine / Channel / Seq ID Register */
#define FD_TSBR_FID_CHANNEL_MASK WBGEN2_GEN_MASK(0, 4)
#define FD_TSBR_FID_CHANNEL_SHIFT 0
#define FD_TSBR_FID_CHANNEL_W(value) WBGEN2_GEN_WRITE(value, 0, 4)
#define FD_TSBR_FID_CHANNEL_R(reg) WBGEN2_GEN_READ(reg, 0, 4)
/* definitions for field: Fine Value [in phase units] in reg: Timestamp Buffer Readout Fine / Channel / Seq ID Register */
#define FD_TSBR_FID_FINE_MASK WBGEN2_GEN_MASK(4, 12)
#define FD_TSBR_FID_FINE_SHIFT 4
#define FD_TSBR_FID_FINE_W(value) WBGEN2_GEN_WRITE(value, 4, 12)
#define FD_TSBR_FID_FINE_R(reg) WBGEN2_GEN_READ(reg, 4, 12)
/* definitions for field: Timestamp Sequence ID in reg: Timestamp Buffer Readout Fine / Channel / Seq ID Register */
#define FD_TSBR_FID_SEQID_MASK WBGEN2_GEN_MASK(16, 16)
#define FD_TSBR_FID_SEQID_SHIFT 16
#define FD_TSBR_FID_SEQID_W(value) WBGEN2_GEN_WRITE(value, 16, 16)
#define FD_TSBR_FID_SEQID_R(reg) WBGEN2_GEN_READ(reg, 16, 16)
/* definitions for register: I2C bitbanged IO register */
/* definitions for field: SCL Line out in reg: I2C bitbanged IO register */
#define FD_I2CR_SCL_OUT WBGEN2_GEN_MASK(0, 1)
/* definitions for field: SDA Line out in reg: I2C bitbanged IO register */
#define FD_I2CR_SDA_OUT WBGEN2_GEN_MASK(1, 1)
/* definitions for field: SCL Line in in reg: I2C bitbanged IO register */
#define FD_I2CR_SCL_IN WBGEN2_GEN_MASK(2, 1)
/* definitions for field: SDA Line in in reg: I2C bitbanged IO register */
#define FD_I2CR_SDA_IN WBGEN2_GEN_MASK(3, 1)
/* definitions for register: Test/Debug register 1 */
/* definitions for field: VCXO Frequency in reg: Test/Debug register 1 */
#define FD_TDER1_VCXO_FREQ_MASK WBGEN2_GEN_MASK(0, 32)
#define FD_TDER1_VCXO_FREQ_SHIFT 0
#define FD_TDER1_VCXO_FREQ_W(value) WBGEN2_GEN_WRITE(value, 0, 32)
#define FD_TDER1_VCXO_FREQ_R(reg) WBGEN2_GEN_READ(reg, 0, 32)
/* definitions for register: Test/Debug register 1 */
/* definitions for field: Peltier PWM drive in reg: Test/Debug register 1 */
#define FD_TDER2_PELT_DRIVE_MASK WBGEN2_GEN_MASK(0, 32)
#define FD_TDER2_PELT_DRIVE_SHIFT 0
#define FD_TDER2_PELT_DRIVE_W(value) WBGEN2_GEN_WRITE(value, 0, 32)
#define FD_TDER2_PELT_DRIVE_R(reg) WBGEN2_GEN_READ(reg, 0, 32)
/* definitions for register: Interrupt disable register */
/* definitions for field: TS Buffer not empty. in reg: Interrupt disable register */
#define FD_EIC_IDR_TS_BUF_NOTEMPTY WBGEN2_GEN_MASK(0, 1)
/* definitions for field: DMTD Softpll interrupt in reg: Interrupt disable register */
#define FD_EIC_IDR_DMTD_SPLL WBGEN2_GEN_MASK(1, 1)
/* definitions for field: Sync Status Changed in reg: Interrupt disable register */
#define FD_EIC_IDR_SYNC_STATUS WBGEN2_GEN_MASK(2, 1)
/* definitions for register: Interrupt enable register */
/* definitions for field: TS Buffer not empty. in reg: Interrupt enable register */
#define FD_EIC_IER_TS_BUF_NOTEMPTY WBGEN2_GEN_MASK(0, 1)
/* definitions for field: DMTD Softpll interrupt in reg: Interrupt enable register */
#define FD_EIC_IER_DMTD_SPLL WBGEN2_GEN_MASK(1, 1)
/* definitions for field: Sync Status Changed in reg: Interrupt enable register */
#define FD_EIC_IER_SYNC_STATUS WBGEN2_GEN_MASK(2, 1)
/* definitions for register: Interrupt mask register */
/* definitions for field: TS Buffer not empty. in reg: Interrupt mask register */
#define FD_EIC_IMR_TS_BUF_NOTEMPTY WBGEN2_GEN_MASK(0, 1)
/* definitions for field: DMTD Softpll interrupt in reg: Interrupt mask register */
#define FD_EIC_IMR_DMTD_SPLL WBGEN2_GEN_MASK(1, 1)
/* definitions for field: Sync Status Changed in reg: Interrupt mask register */
#define FD_EIC_IMR_SYNC_STATUS WBGEN2_GEN_MASK(2, 1)
/* definitions for register: Interrupt status register */
/* definitions for field: TS Buffer not empty. in reg: Interrupt status register */
#define FD_EIC_ISR_TS_BUF_NOTEMPTY WBGEN2_GEN_MASK(0, 1)
/* definitions for field: DMTD Softpll interrupt in reg: Interrupt status register */
#define FD_EIC_ISR_DMTD_SPLL WBGEN2_GEN_MASK(1, 1)
/* definitions for field: Sync Status Changed in reg: Interrupt status register */
#define FD_EIC_ISR_SYNC_STATUS WBGEN2_GEN_MASK(2, 1)
/* [0x0]: REG Reset Register */
#define FD_REG_RSTR 0x00000000
/* [0x4]: REG ID Register */
#define FD_REG_IDR 0x00000004
/* [0x8]: REG Global Control Register */
#define FD_REG_GCR 0x00000008
/* [0xc]: REG Timing Control Register */
#define FD_REG_TCR 0x0000000c
/* [0x10]: REG Time Register - TAI seconds (MSB) */
#define FD_REG_TM_SECH 0x00000010
/* [0x14]: REG Time Register - TAI seconds (LSB) */
#define FD_REG_TM_SECL 0x00000014
/* [0x18]: REG Time Register - sub-second 125 MHz clock cycles */
#define FD_REG_TM_CYCLES 0x00000018
/* [0x1c]: REG TDC Data Register */
#define FD_REG_TDR 0x0000001c
/* [0x20]: REG TDC control/status reg */
#define FD_REG_TDCSR 0x00000020
/* [0x24]: REG Calibration register */
#define FD_REG_CALR 0x00000024
/* [0x28]: REG Softpll Register */
#define FD_REG_SPLLR 0x00000028
/* [0x2c]: REG Softpll DAC Register */
#define FD_REG_SDACR 0x0000002c
/* [0x30]: REG Acam to Delay line fractional part Scale Factor Register */
#define FD_REG_ADSFR 0x00000030
/* [0x34]: REG Acam Timestamp Merging Control Register */
#define FD_REG_ATMCR 0x00000034
/* [0x38]: REG Acam Start Offset Register */
#define FD_REG_ASOR 0x00000038
/* [0x3c]: REG Raw Input Events Counter Register */
#define FD_REG_IECRAW 0x0000003c
/* [0x40]: REG Tagged Input Events Counter Register */
#define FD_REG_IECTAG 0x00000040
/* [0x44]: REG Input Event Processing Delay Register */
#define FD_REG_IEPD 0x00000044
/* [0x48]: REG SPI Control Register */
#define FD_REG_SCR 0x00000048
/* [0x4c]: REG Reference Clock Rate Register */
#define FD_REG_RCRR 0x0000004c
/* [0x50]: REG Timestamp Buffer Control Register */
#define FD_REG_TSBCR 0x00000050
/* [0x54]: REG Timestamp Buffer Interrupt Register */
#define FD_REG_TSBIR 0x00000054
/* [0x58]: REG Timestamp Buffer Readout Seconds Register (MSB) */
#define FD_REG_TSBR_SECH 0x00000058
/* [0x5c]: REG Timestamp Buffer Readout Seconds Register (LSB) */
#define FD_REG_TSBR_SECL 0x0000005c
/* [0x60]: REG Timestamp Buffer Readout Cycles Register */
#define FD_REG_TSBR_CYCLES 0x00000060
/* [0x64]: REG Timestamp Buffer Readout Fine / Channel / Seq ID Register */
#define FD_REG_TSBR_FID 0x00000064
/* [0x68]: REG I2C bitbanged IO register */
#define FD_REG_I2CR 0x00000068
/* [0x6c]: REG Test/Debug register 1 */
#define FD_REG_TDER1 0x0000006c
/* [0x70]: REG Test/Debug register 1 */
#define FD_REG_TDER2 0x00000070
/* [0x80]: REG Interrupt disable register */
#define FD_REG_EIC_IDR 0x00000080
/* [0x84]: REG Interrupt enable register */
#define FD_REG_EIC_IER 0x00000084
/* [0x88]: REG Interrupt mask register */
#define FD_REG_EIC_IMR 0x00000088
/* [0x8c]: REG Interrupt status register */
#define FD_REG_EIC_ISR 0x0000008c
#endif
common/fmc_delay/include/fdelay_lib.h
0 → 100644
View file @
557f9512
#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
/* attached WR core is offline */
#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. */
/* fdelay_configure_sync() flags */
#define FDELAY_SYNC_LOCAL 0x1
/* use local oscillator */
#define FDELAY_SYNC_WR 0x2
/* use White Rabbit */
/* Hardware "handle" structure */
typedef
struct
fdelay_device
{
/* Base address of the FD core */
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
;
int32_t
coarse
;
int32_t
frac
;
uint16_t
seq_id
;
int
channel
;
}
fdelay_time_t
;
/*
--------------------
PUBLIC API
--------------------
*/
fdelay_device_t
*
fdelay_create_rawrabbit
(
int
fd
,
uint32_t
base_addr
);
fdelay_device_t
*
fdelay_create_minibone
(
char
*
iface
,
char
*
mac_addr
,
uint32_t
base_addr
);
fdelay_time_t
fdelay_from_picos
(
const
uint64_t
ps
);
int64_t
fdelay_to_picos
(
const
fdelay_time_t
t
);
int
fdelay_init
(
fdelay_device_t
*
dev
);
int
fdelay_release
(
fdelay_device_t
*
dev
);
int
fdelay_read
(
fdelay_device_t
*
dev
,
fdelay_time_t
*
timestamps
,
int
how_many
);
int
fdelay_configure_trigger
(
fdelay_device_t
*
dev
,
int
enable
,
int
termination
);
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
);
int
fdelay_configure_sync
(
fdelay_device_t
*
dev
,
int
mode
);
int
fdelay_update_sync_status
(
fdelay_device_t
*
dev
);
int
fdelay_set_time
(
fdelay_device_t
*
dev
,
const
fdelay_time_t
t
);
int
fdelay_configure_pulse_gen
(
fdelay_device_t
*
dev
,
int
channel
,
int
enable
,
fdelay_time_t
t_start
,
int64_t
width_ps
,
int64_t
delta_ps
,
int
rep_count
);
int
fdelay_channel_triggered
(
fdelay_device_t
*
dev
,
int
channel
);
int
fdelay_get_time
(
fdelay_device_t
*
dev
,
fdelay_time_t
*
t
);
#endif
common/fmc_delay/include/fdelay_private.h
0 → 100644
View file @
557f9512
/*
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 */
/* 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
/* 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
;
struct
fine_delay_calibration
calib
;
};
/* 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
common/fmc_delay/include/i2c_master.h
0 → 100644
View file @
557f9512
#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
common/fmc_delay/include/onewire.h
0 → 100644
View file @
557f9512
#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
common/fmc_delay/include/pll_config.h
0 → 100644
View file @
557f9512
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
}};
common/fmc_delay/include/rawrabbit.h
0 → 100644
View file @
557f9512
/*
* 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__ */
common/fmc_delay/include/rr_io.h
0 → 100644
View file @
557f9512
#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
common/fmc_delay/lib/Makefile
0 → 100644
View file @
557f9512
CFLAGS
=
-I
../include
-g
-Imini_bone
-Ispll
#uncomment for extra tests (DAC, output stage INL/DNL)
#CFLAGS += -DPERFORM_LONG_TESTS
OBJS_LIB
=
fdelay_lib.o fdelay_bus.o rr_io.o i2c_master.o onewire.o mini_bone/minibone_lib.o mini_bone/ptpd_netif.o spec_common.o
all
:
testprog lib testprog2 testprog3 testprog4
lib
:
$(OBJS_LIB)
gcc
-shared
-o
libfinedelay.so
$(OBJS_LIB)
testprog
:
lib fdelay_test.o
gcc
-o
fdelay_test
$(OBJS_LIB)
fdelay_test.o
-lm
testprog2
:
lib fdelay_cal.o
gcc
-o
fdelay_cal
$(OBJS_LIB)
fdelay_cal.o
-lm
testprog3
:
lib fdelay_pps_demo.o
gcc
-o
fdelay_pps_demo
$(OBJS_LIB)
fdelay_pps_demo.o
-lm
testprog4
:
lib fdelay_eeprom.o
gcc
-o
fdelay_eeprom
$(OBJS_LIB)
fdelay_eeprom.o
-lm
clean
:
rm
-f
libfinedelay.so
$(OBJS_LIB)
\ No newline at end of file
common/fmc_delay/lib/fdelay_bus.c
0 → 100644
View file @
557f9512
/*
FmcDelay1ns4Cha (a.k.a. The Fine Delay Card)
User-space driver/library - bus API creation functions
Tomasz Włostowski/BE-CO-HT, 2011
(c) Copyright CERN 2011
Licensed under LGPL 2.1
*/
#include <stdio.h>
#include <stdlib.h>
#include "rr_io.h"
#include "minibone_lib.h"
#include "fdelay_lib.h"
static
void
my_rr_writel
(
void
*
priv
,
uint32_t
data
,
uint32_t
addr
)
{
rr_writel
(
data
,
addr
);
}
static
uint32_t
my_rr_readl
(
void
*
priv
,
uint32_t
addr
)
{
uint32_t
d
=
rr_readl
(
addr
);
return
d
;
}
static
void
my_mb_writel
(
void
*
priv
,
uint32_t
data
,
uint32_t
addr
)
{
mbn_writel
(
priv
,
data
,
addr
>>
2
);
}
static
uint32_t
my_mb_readl
(
void
*
priv
,
uint32_t
addr
)
{
uint32_t
d
=
mbn_readl
(
priv
,
addr
>>
2
);
return
d
;
}
fdelay_device_t
*
fdelay_create_rawrabbit
(
int
fd
,
uint32_t
base_addr
)
{
fdelay_device_t
*
dev
=
malloc
(
sizeof
(
fdelay_device_t
));
rr_bind
(
fd
);
dev
->
writel
=
my_rr_writel
;
dev
->
readl
=
my_rr_readl
;
dev
->
base_addr
=
base_addr
;
return
dev
;
}
fdelay_device_t
*
fdelay_create_minibone
(
char
*
iface
,
char
*
mac_addr
,
uint32_t
base_addr
)
{
void
*
handle
;
uint8_t
target_mac
[
6
];
fdelay_device_t
*
dev
=
malloc
(
sizeof
(
fdelay_device_t
));
sscanf
(
mac_addr
,
"%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx"
,
&
target_mac
[
0
],
&
target_mac
[
1
],
&
target_mac
[
2
],
&
target_mac
[
3
],
&
target_mac
[
4
],
&
target_mac
[
5
]);
handle
=
mbn_open
(
iface
,
target_mac
);
if
(
handle
==
NULL
)
return
NULL
;
// dbg("%s: remote @ %s [%02x:%02x:%02x:%02x:%02x:%02x], base 0x%08x\n",__FUNCTION__, iface,
// target_mac[0], target_mac[1], target_mac[2], target_mac[3], target_mac[4], target_mac[5], base_addr);
dev
->
writel
=
my_mb_writel
;
dev
->
readl
=
my_mb_readl
;
dev
->
base_addr
=
base_addr
;
dev
->
priv_io
=
handle
;
return
dev
;
}
common/fmc_delay/lib/fdelay_cal.c
0 → 100644
View file @
557f9512
#include <stdio.h>
#include <stdint.h>
#include "fdelay_lib.h"
#include "fdelay_private.h"
#include "fd_main_regs.h"
#include "onewire.h"
#include "rr_io.h"
typedef
struct
{
float
kp
,
ki
,
err
,
pwm
,
setpoint
,
i
,
bias
;
}
pi_t
;
pi_t
pi_state
=
{
15
.
0
,
5
.
0
,
0
,
0
,
20
,
0
,
2048
};
void
pi_update
(
fdelay_device_t
*
dev
,
float
temp
)
{
fd_decl_private
(
dev
);
pi_state
.
err
=
temp
-
pi_state
.
setpoint
;
pi_state
.
i
+=
pi_state
.
err
;
pi_state
.
pwm
=
pi_state
.
bias
+
pi_state
.
kp
*
pi_state
.
err
+
pi_state
.
ki
*
pi_state
.
i
;
dbg
(
"t %.1f err:%.1f DRIVE: %d
\n
"
,
temp
,
pi_state
.
err
,
(
int
)
pi_state
.
pwm
);
fd_writel
(
FD_I2CR_DBGOUT_W
((
int
)
pi_state
.
pwm
),
FD_REG_I2CR
);
}
extern
int64_t
get_tics
();
static
int64_t
last_tics
=
0
;
#define TEMP_REG_PERIOD 1000000LL
int
pi_set_temp
(
fdelay_device_t
*
dev
,
float
new_temp
)
{
int
temp
;
float
temp_f
;
if
(
get_tics
()
-
last_tics
<
TEMP_REG_PERIOD
)
return
0
;
last_tics
=
get_tics
();
if
(
ds18x_read_temp
(
dev
,
&
temp
)
<
0
)
return
0
;
temp_f
=
(
float
)
temp
/
16
.
0
;
pi_state
.
setpoint
=
new_temp
;
pi_update
(
dev
,
temp_f
);
dbg
(
"Temperature: %.1f degC err %.1f
\n
"
,
temp_f
,
pi_state
.
err
);
return
fabs
(
pi_state
.
err
)
<
0
.
1
?
1
:
0
;
}
void
my_writel
(
void
*
priv
,
uint32_t
data
,
uint32_t
addr
)
{
rr_writel
(
data
,
addr
);
}
uint32_t
my_readl
(
void
*
priv
,
uint32_t
addr
)
{
uint32_t
d
=
rr_readl
(
addr
);
return
d
;
}
main
()
{
fdelay_device_t
*
dev
=
malloc
(
sizeof
(
fdelay_device_t
));
rr_init
(
RR_DEVSEL_UNUSED
,
RR_DEVSEL_UNUSED
);
dev
->
writel
=
my_writel
;
dev
->
readl
=
my_readl
;
dev
->
base_addr
=
0x80000
;
if
(
fdelay_init
(
dev
)
<
0
)
return
-
1
;
float
t_min
=
40
.
0
,
t_max
=
80
.
0
,
t_cur
;
t_cur
=
t_min
;
for
(;;)
{
if
(
pi_set_temp
(
dev
,
t_cur
))
{
fd_decl_private
(
dev
);
calibrate_outputs
(
dev
);
fprintf
(
stderr
,
"> %.1f %d %d %d %d
\n
"
,
t_cur
,
hw
->
frr_cur
[
0
],
hw
->
frr_cur
[
1
],
hw
->
frr_cur
[
2
],
hw
->
frr_cur
[
3
]);
t_cur
+=
1
.
0
;
if
(
t_cur
>
t_max
)
break
;
}
usleep
(
10000
);
}
}
common/fmc_delay/lib/fdelay_eeprom.c
0 → 100644
View file @
557f9512
#include <stdio.h>
#include "fdelay_lib.h"
#include "fdelay_private.h"
#include "rr_io.h"
#include "i2c_master.h"
void
my_writel
(
void
*
priv
,
uint32_t
data
,
uint32_t
addr
)
{
rr_writel
(
data
,
addr
);
}
uint32_t
my_readl
(
void
*
priv
,
uint32_t
addr
)
{
uint32_t
d
=
rr_readl
(
addr
);
return
d
;
}
main
()
{
fdelay_device_t
dev
;
struct
fine_delay_calibration
cal
;
rr_init
(
RR_DEVSEL_UNUSED
,
RR_DEVSEL_UNUSED
);
dev
.
writel
=
my_writel
;
dev
.
readl
=
my_readl
;
dev
.
base_addr
=
0x84000
;
if
(
fdelay_init
(
&
dev
)
<
0
)
return
-
1
;
cal
.
magic
=
0xf19ede1a
;
cal
.
zero_offset
[
0
]
=
63000
;
cal
.
zero_offset
[
1
]
=
63000
;
cal
.
zero_offset
[
2
]
=
63000
;
cal
.
zero_offset
[
3
]
=
63000
;
cal
.
tdc_zero_offset
=
35600
;
cal
.
frr_poly
[
0
]
=
-
165202LL
;
cal
.
frr_poly
[
1
]
=
-
29825595LL
;
cal
.
frr_poly
[
2
]
=
3801939743082LL
;
cal
.
tdc_zero_offset
=
35600
;
cal
.
atmcr_val
=
2
|
(
1000
<<
4
);
cal
.
adsfr_val
=
56648
;
cal
.
acam_start_offset
=
10000
;
printf
(
"Writing EEPROM..."
);
eeprom_write
(
&
dev
,
EEPROM_ADDR
,
0
,
&
cal
,
sizeof
(
struct
fine_delay_calibration
));
printf
(
" done.
\n
"
);
}
common/fmc_delay/lib/fdelay_lib.c
0 → 100644
View file @
557f9512
/*
FmcDelay1ns4Cha (a.k.a. The Fine Delay Card)
User-space driver/library
Tomasz Włostowski/BE-CO-HT, 2011
(c) Copyright CERN 2011
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 "pll_config.h"
#include "acam_gpx.h"
#include "fdelay_lib.h"
#include "fdelay_private.h"
#include "spll_defs.h"
#include "spll_common.h"
#include "spll_helper.h"
#include "onewire.h"
static
int
acam_test_bus
(
fdelay_device_t
*
dev
);
#define TEST_PRESENCE 0
#define TEST_FIRMWARE 1
#define TEST_DELAY_LINE 2
#define TEST_SPI 3
#define TEST_SENSORS 4
#define TEST_ACAM_IF 5
/*
----------------------
Some utility functions
----------------------
*/
char
fail_test_msg
[
1024
];
int
fail_test_id
=
-
1
;
static
void
fail
(
int
test_id
,
const
char
*
fmt
,
...)
{
va_list
ap
;
fail_test_id
=
test_id
;
va_start
(
ap
,
fmt
);
vsprintf
(
fail_test_msg
,
fmt
,
ap
);
va_end
(
ap
);
}
static
int
extra_debug
=
1
;
void
fdelay_show_test_results
()
{
if
(
fail_test_id
>=
0
)
{
fprintf
(
stderr
,
"
\n\n\n
***** FAILED TEST: %d (%s) ******
\n
"
,
fail_test_id
,
fail_test_msg
);
}
}
void
dbg
(
const
char
*
fmt
,
...)
{
va_list
ap
;
va_start
(
ap
,
fmt
);
if
(
extra_debug
)
vfprintf
(
stderr
,
fmt
,
ap
);
va_end
(
ap
);
}
/* Returns the numer of microsecond timer ticks */
int64_t
get_tics
()
{
struct
timezone
tz
=
{
0
,
0
};
struct
timeval
tv
;
gettimeofday
(
&
tv
,
&
tz
);
return
(
int64_t
)
tv
.
tv_sec
*
1000000LL
+
(
int64_t
)
tv
.
tv_usec
;
}
/* Microsecond-accurate delay */
void
udelay
(
uint32_t
usecs
)
{
int64_t
ts
=
get_tics
();
while
(
get_tics
()
-
ts
<
(
int64_t
)
usecs
);
}
/* Card reset. When mode == RESET_HW, resets the FMC hardware by asserting the reset line in the FMC
connector, if mode == RESET_CORE, the FPGA Fine Delay core is reset. Since HW reset operation also
reinitializes the PLL, the HW reset must be followed by a reinitialization of the FD Core. */
#define FD_RESET_HW 1
#define FD_RESET_CORE 0
static
void
fd_do_reset
(
fdelay_device_t
*
dev
,
int
mode
)
{
fd_decl_private
(
dev
)
;
if
(
mode
==
FD_RESET_HW
)
{
fd_writel
(
FD_RSTR_LOCK_W
(
0xdead
)
|
FD_RSTR_RST_CORE_MASK
,
FD_REG_RSTR
);
udelay
(
10000
);
fd_writel
(
FD_RSTR_LOCK_W
(
0xdead
)
|
FD_RSTR_RST_CORE_MASK
|
FD_RSTR_RST_FMC_MASK
,
FD_REG_RSTR
);
udelay
(
600000
);
/* Leave the TPS3307 supervisor some time to de-assert the master reset line */
}
else
if
(
mode
==
FD_RESET_CORE
)
{
fd_writel
(
FD_RSTR_LOCK_W
(
0xdead
)
|
FD_RSTR_RST_FMC_MASK
,
FD_REG_RSTR
);
udelay
(
1000
);
fd_writel
(
FD_RSTR_LOCK_W
(
0xdead
)
|
FD_RSTR_RST_FMC_MASK
|
FD_RSTR_RST_CORE_MASK
,
FD_REG_RSTR
);
udelay
(
1000
);
}
}
/*
----------------------------------
Simple SPI Master driver
----------------------------------
*/
/* Initializes the SPI Controller */
static
void
oc_spi_init
(
fdelay_device_t
*
dev
)
{
fd_decl_private
(
dev
)
}
/* Sends (num_bits) from (in) to slave at CS line (ss), storint the readback data in (*out) */
static
void
oc_spi_txrx
(
fdelay_device_t
*
dev
,
int
ss
,
int
num_bits
,
uint32_t
in
,
uint32_t
*
out
)
{
fd_decl_private
(
dev
);
uint32_t
scr
=
0
,
r
;
scr
=
FD_SCR_DATA_W
(
in
)
|
FD_SCR_CPOL
;
if
(
ss
==
CS_PLL
)
scr
|=
FD_SCR_SEL_PLL
;
else
if
(
ss
==
CS_GPIO
)
scr
|=
FD_SCR_SEL_GPIO
;
else
if
(
ss
==
CS_DAC
)
scr
|=
FD_SCR_SEL_DAC
;
fd_writel
(
scr
,
FD_REG_SCR
);
fd_writel
(
scr
|
FD_SCR_START
,
FD_REG_SCR
);
while
(
!
(
fd_readl
(
FD_REG_SCR
)
&
FD_SCR_READY
));
scr
=
fd_readl
(
FD_REG_SCR
);
r
=
FD_SCR_DATA_R
(
scr
);
if
(
out
)
*
out
=
r
;
udelay
(
100
);
}
/*
-----------------
AD9516 PLL Driver
-----------------
*/
/* Writes an AD9516 register */
static
inline
void
ad9516_write_reg
(
fdelay_device_t
*
dev
,
uint16_t
reg
,
uint8_t
val
)
{
oc_spi_txrx
(
dev
,
CS_PLL
,
24
,
((
uint32_t
)(
reg
&
0xfff
)
<<
8
)
|
val
,
NULL
);
}
/* Reads a register from AD9516 */
static
inline
uint8_t
ad9516_read_reg
(
fdelay_device_t
*
dev
,
uint16_t
reg
)
{
uint32_t
rval
;
oc_spi_txrx
(
dev
,
CS_PLL
,
24
,
((
uint32_t
)(
reg
&
0xfff
)
<<
8
)
|
(
1
<<
23
),
&
rval
);
return
rval
&
0xff
;
}
/* Initializes the AD9516 PLL by loading a pre-defined register set and waiting until the PLL has locked */
static
int
ad9516_init
(
fdelay_device_t
*
dev
)
{
fd_decl_private
(
dev
)
int
i
;
const
int64_t
lock_timeout
=
10000000LL
;
int64_t
start_tics
;
dbg
(
"%s: Initializing AD9516 PLL...
\n
"
,
__FUNCTION__
);
ad9516_write_reg
(
dev
,
0
,
0x99
);
ad9516_write_reg
(
dev
,
0x232
,
1
);
/* Check if the chip is present by reading its ID register */
if
(
ad9516_read_reg
(
dev
,
0x3
)
!=
0xc3
)
{
dbg
(
"%s: AD9516 PLL not responding.
\n
"
,
__FUNCTION__
);
fail
(
TEST_SPI
,
"Broken SPI connection to AD9516 PLL"
);
return
-
1
;
}
/* Load the regs */
for
(
i
=
0
;
ad9516_regs
[
i
].
reg
>=
0
;
i
++
)
ad9516_write_reg
(
dev
,
ad9516_regs
[
i
].
reg
,
ad9516_regs
[
i
].
val
);
ad9516_write_reg
(
dev
,
0x232
,
1
);
/* Wait until the PLL has locked */
start_tics
=
get_tics
();
for
(;;)
{
if
(
ad9516_read_reg
(
dev
,
0x1f
)
&
1
)
break
;
if
(
get_tics
()
-
start_tics
>
lock_timeout
)
{
dbg
(
"%s: AD9516 PLL does not lock.
\n
"
,
__FUNCTION__
);
return
-
1
;
}
udelay
(
100
);
}
/* Synchronize the phase of all clock outputs (this is critical for the accuracy!) */
ad9516_write_reg
(
dev
,
0x230
,
1
);
ad9516_write_reg
(
dev
,
0x232
,
1
);
ad9516_write_reg
(
dev
,
0x230
,
0
);
ad9516_write_reg
(
dev
,
0x232
,
1
);
dbg
(
"%s: AD9516 locked.
\n
"
,
__FUNCTION__
);
return
0
;
}
static
int
test_pll_dac
(
fdelay_device_t
*
dev
)
{
fd_decl_private
(
dev
);
int
f_hi
,
f_lo
;
double
range
;
int
i
=
0
;
dbg
(
"Testing DAC/VCXO... "
);
oc_spi_txrx
(
dev
,
CS_DAC
,
24
,
0
,
NULL
);
/* Drive the DAC to 0 */
udelay
(
1000000
);
f_lo
=
fd_readl
(
FD_REG_TDER1
)
&
0x7fffffff
;
oc_spi_txrx
(
dev
,
CS_DAC
,
24
,
0xffff
,
NULL
);
/* Drive the DAC to +Vref */
udelay
(
1000000
);
f_hi
=
fd_readl
(
FD_REG_TDER1
)
&
0x7fffffff
;
range
=
(
double
)
abs
(
f_hi
-
f_lo
)
/
(
double
)
f_lo
*
1e6
;
dbg
(
"tuning range: %.1f ppm.
\n
"
,
range
);
if
(
range
<
10
.
1
)
{
fail
(
TEST_SPI
,
"Too little VCXO tuning range. Either a broken VCXO or (more likely) broken SPI connection to the DAC."
);
return
-
1
;
}
return
0
;
}
/*
----------------------------
MCP23S17 SPI I/O Port Driver
----------------------------
*/
/* Writes MCP23S17 register */
static
inline
void
mcp_write
(
fdelay_device_t
*
dev
,
uint8_t
reg
,
uint8_t
val
)
{
oc_spi_txrx
(
dev
,
CS_GPIO
,
24
,
0x4e0000
|
(((
uint32_t
)
reg
)
<<
8
)
|
(
uint32_t
)
val
,
NULL
);
}
/* Reads MCP23S17 register */
static
uint8_t
mcp_read
(
fdelay_device_t
*
dev
,
uint8_t
reg
)
{
uint32_t
rval
;
oc_spi_txrx
(
dev
,
CS_GPIO
,
24
,
0x4f0000
|
(((
uint32_t
)
reg
)
<<
8
),
&
rval
);
return
rval
&
0xff
;
}
static
int
sgpio_init
(
fdelay_device_t
*
dev
)
{
int
failed
=
0
;
mcp_write
(
dev
,
MCP_IOCON
,
0
);
/* try to read and write a register to test the SPI connection */
mcp_write
(
dev
,
MCP_IPOL
,
0xaa
);
if
(
mcp_read
(
dev
,
MCP_IPOL
)
!=
0xaa
)
failed
=
1
;
mcp_write
(
dev
,
MCP_IPOL
,
0
);
if
(
mcp_read
(
dev
,
MCP_IPOL
)
!=
0
)
failed
=
1
;
fail
(
TEST_SPI
,
"Failed to access MCP23S17. Broken SPI connection?"
);
return
failed
?
-
1
:
0
;
}
/* Sets the direction (0 = input, non-zero = output) of a particular MCP23S17 GPIO pin */
static
void
sgpio_set_dir
(
fdelay_device_t
*
dev
,
int
pin
,
int
dir
)
{
uint8_t
iodir
=
(
MCP_IODIR
)
+
(
pin
&
0x100
?
1
:
0
);
uint8_t
x
;
x
=
mcp_read
(
dev
,
iodir
);
if
(
dir
)
x
&=
~
(
pin
);
else
x
|=
(
pin
);
mcp_write
(
dev
,
iodir
,
x
);
}
/* Sets the value on a given MCP23S17 GPIO pin */
static
void
sgpio_set_pin
(
fdelay_device_t
*
dev
,
int
pin
,
int
val
)
{
uint8_t
gpio
=
(
MCP_OLAT
)
+
(
pin
&
0x100
?
1
:
0
);
uint8_t
x
;
x
=
mcp_read
(
dev
,
gpio
);
if
(
!
val
)
x
&=
~
(
pin
);
else
x
|=
(
pin
);
mcp_write
(
dev
,
gpio
,
x
);
}
/*
----------------------------------------
ACAM Time To Digital Converter functions
----------------------------------------
*/
/* Sets the address on ACAM's address bus to addr using the SPI GPIO expander */
static
inline
void
acam_set_address
(
fdelay_device_t
*
dev
,
uint8_t
addr
)
{
fd_decl_private
(
dev
);
/* A hack to speed up calibration - avoid setting the same address several times */
if
(
addr
!=
hw
->
acam_addr
)
{
mcp_write
(
dev
,
MCP_IODIR
+
1
,
0
);
mcp_write
(
dev
,
MCP_OLAT
+
1
,
addr
&
0xf
);
hw
->
acam_addr
=
addr
;
}
}
/* Reads a register from the ACAM TDC. As for the function above, GCR.BYPASS must be enabled */
static
uint32_t
acam_read_reg
(
fdelay_device_t
*
dev
,
uint8_t
reg
)
{
fd_decl_private
(
dev
)
acam_set_address
(
dev
,
reg
);
fd_writel
(
FD_TDCSR_READ
,
FD_REG_TDCSR
);
return
fd_readl
(
FD_REG_TDR
)
&
0xfffffff
;
}
/* Writes a particular ACAM register. Works only if (GCR.BYPASS == 1) - i.e. when
the ACAM is controlled from the host instead of the delay core. */
static
void
acam_write_reg
(
fdelay_device_t
*
dev
,
uint8_t
reg
,
uint32_t
data
)
{
fd_decl_private
(
dev
)
acam_set_address
(
dev
,
reg
);
fd_writel
(
data
&
0xfffffff
,
FD_REG_TDR
);
fd_writel
(
FD_TDCSR_WRITE
,
FD_REG_TDCSR
);
}
/* Calculates the parameters of the ACAM PLL (hsdiv and refdiv)
for a given bin size and reference clock frequency. Returns the closest
achievable bin size. */
static
double
acam_calc_pll
(
int
*
hsdiv
,
int
*
refdiv
,
double
bin
,
double
clock_freq
)
{
int
h
;
int
r
;
double
best_err
=
100000
;
double
best_bin
;
/* Try all possible divider settings */
for
(
h
=
1
;
h
<=
255
;
h
++
)
for
(
r
=
0
;
r
<=
7
;
r
++
)
{
double
b
=
((
1
.
0
/
clock_freq
)
*
1e12
)
*
pow
(
2
.
0
,
(
double
)
r
)
/
(
216
.
0
*
(
double
)
h
);
if
(
fabs
(
bin
-
b
)
<
best_err
)
{
best_err
=
fabs
(
bin
-
b
);
best_bin
=
b
;
*
hsdiv
=
h
;
*
refdiv
=
r
;
}
}
dbg
(
"%s: requested bin=%.02fps best=%.02fps error=%.02f%%
\n
"
,
__FUNCTION__
,
bin
,
best_bin
,
(
best_err
/
bin
)
*
100
.
0
);
dbg
(
"%s: hsdiv=%d refdiv=%d
\n
"
,
__FUNCTION__
,
*
hsdiv
,
*
refdiv
);
return
best_bin
;
}
/* Returns non-zero if the ACAM's internal PLL is locked */
static
inline
int
acam_pll_locked
(
fdelay_device_t
*
dev
)
{
uint32_t
r12
=
acam_read_reg
(
dev
,
12
);
return
!
(
r12
&
AR12_NotLocked
);
}
static
int
test_addr_bit
(
fdelay_device_t
*
dev
,
int
addr1
,
int
addr2
,
int
addr_bit
,
int
data_bit
)
{
int
failed
=
0
;
acam_write_reg
(
dev
,
addr1
,
acam_read_reg
(
dev
,
addr1
)
&
~
(
1
<<
data_bit
));
// set the data bit to 0
acam_write_reg
(
dev
,
addr2
,
acam_read_reg
(
dev
,
addr2
)
|
(
1
<<
data_bit
));
// set the data bit to 1
if
(
acam_read_reg
(
dev
,
addr1
)
&
(
1
<<
data_bit
)
||
!
(
acam_read_reg
(
dev
,
addr2
)
&
(
1
<<
data_bit
)))
failed
=
1
;
/* the other way around */
acam_write_reg
(
dev
,
addr1
,
acam_read_reg
(
dev
,
addr1
)
|
(
1
<<
data_bit
));
acam_write_reg
(
dev
,
addr2
,
acam_read_reg
(
dev
,
addr2
)
&
~
(
1
<<
data_bit
));
if
(
!
(
acam_read_reg
(
dev
,
addr1
)
&
(
1
<<
data_bit
))
||
acam_read_reg
(
dev
,
addr2
)
&
(
1
<<
data_bit
))
failed
=
1
;
if
(
failed
)
{
dbg
(
"Bit failure on ACAM_A[%d]
\n
"
,
addr_bit
);
fail
(
TEST_ACAM_IF
,
"Bit failure on ACAM_A[%d]"
,
addr_bit
);
return
-
1
;
}
return
0
;
}
static
int
acam_test_bus
(
fdelay_device_t
*
dev
)
{
int
i
,
failed
=
0
;
dbg
(
"Testing ACAM Bus...
\n
"
);
for
(
i
=
0
;
i
<
28
;
i
++
)
{
acam_write_reg
(
dev
,
5
,
(
1
<<
i
));
acam_read_reg
(
dev
,
0
);
uint32_t
rb
=
acam_read_reg
(
dev
,
5
);
acam_write_reg
(
dev
,
5
,
~
(
1
<<
i
));
acam_read_reg
(
dev
,
0
);
uint32_t
rb2
=
acam_read_reg
(
dev
,
5
);
if
(
rb
!=
(
1
<<
i
)
||
rb2
!=
(
~
(
1
<<
i
)
&
0xfffffff
))
{
dbg
(
"Bit failure on ACAM_D[%d]: %x shouldbe %x
\n
"
,
i
,
rb
,
(
1
<<
i
));
fail
(
TEST_ACAM_IF
,
"Bit failure on ACAM_D[%d]: %x shouldbe %x "
,
i
,
rb
,
(
1
<<
i
));
return
-
1
;
}
}
failed
|=
test_addr_bit
(
dev
,
0
,
1
,
0
,
1
);
failed
|=
test_addr_bit
(
dev
,
1
,
3
,
1
,
3
);
failed
|=
test_addr_bit
(
dev
,
0
,
4
,
2
,
1
);
failed
|=
test_addr_bit
(
dev
,
3
,
11
,
3
,
16
);
return
failed
;
}
/* Configures the ACAM TDC to work in a particular mode. Currently there are two modes
supported: R-Mode for the normal operation (delay/timestamper) and I-Mode for the purpose
of calibrating the fine delay lines. */
static
int
acam_configure
(
fdelay_device_t
*
dev
,
int
mode
)
{
fd_decl_private
(
dev
)
int
hsdiv
,
refdiv
;
int64_t
start_tics
;
const
int64_t
lock_timeout
=
2000000LL
;
hw
->
acam_bin
=
acam_calc_pll
(
&
hsdiv
,
&
refdiv
,
80
.
9553
,
31.25e6
)
/
3
.
0
;
/* Disable TDC inputs prior to configuring */
fd_writel
(
FD_TDCSR_STOP_DIS
|
FD_TDCSR_START_DIS
,
FD_REG_TDCSR
);
if
(
mode
==
ACAM_RMODE
)
{
acam_write_reg
(
dev
,
0
,
AR0_ROsc
|
AR0_RiseEn0
|
AR0_RiseEn1
|
AR0_HQSel
);
acam_write_reg
(
dev
,
1
,
AR1_Adj
(
0
,
0
)
|
AR1_Adj
(
1
,
2
)
|
AR1_Adj
(
2
,
6
)
|
AR1_Adj
(
3
,
0
)
|
AR1_Adj
(
4
,
2
)
|
AR1_Adj
(
5
,
6
)
|
AR1_Adj
(
6
,
0
));
acam_write_reg
(
dev
,
2
,
AR2_RMode
|
AR2_Adj
(
7
,
2
)
|
AR2_Adj
(
8
,
6
));
acam_write_reg
(
dev
,
3
,
0
);
acam_write_reg
(
dev
,
4
,
AR4_EFlagHiZN
);
acam_write_reg
(
dev
,
5
,
AR5_StartRetrig
|
AR5_StartOff1
(
hw
->
calib
.
acam_start_offset
)
|
AR5_MasterAluTrig
);
acam_write_reg
(
dev
,
6
,
AR6_Fill
(
200
)
|
AR6_PowerOnECL
);
acam_write_reg
(
dev
,
7
,
AR7_HSDiv
(
hsdiv
)
|
AR7_RefClkDiv
(
refdiv
)
|
AR7_ResAdj
|
AR7_NegPhase
);
acam_write_reg
(
dev
,
11
,
0x7ff0000
);
acam_write_reg
(
dev
,
12
,
0x0000000
);
acam_write_reg
(
dev
,
14
,
0
);
/* Reset the ACAM after the configuration */
acam_write_reg
(
dev
,
4
,
AR4_EFlagHiZN
|
AR4_MasterReset
|
AR4_StartTimer
(
0
));
}
else
if
(
mode
==
ACAM_IMODE
)
{
acam_write_reg
(
dev
,
0
,
AR0_TRiseEn
(
0
)
|
AR0_HQSel
|
AR0_ROsc
);
acam_write_reg
(
dev
,
2
,
AR2_IMode
);
acam_write_reg
(
dev
,
5
,
AR5_StartOff1
(
3000
)
|
AR5_MasterAluTrig
);
acam_write_reg
(
dev
,
6
,
0
);
acam_write_reg
(
dev
,
7
,
AR7_HSDiv
(
hsdiv
)
|
AR7_RefClkDiv
(
refdiv
)
|
AR7_ResAdj
|
AR7_NegPhase
);
acam_write_reg
(
dev
,
11
,
0x7ff0000
);
acam_write_reg
(
dev
,
12
,
0x0000000
);
acam_write_reg
(
dev
,
14
,
0
);
/* Reset the ACAM after the configuration */
acam_write_reg
(
dev
,
4
,
AR4_EFlagHiZN
|
AR4_MasterReset
|
AR4_StartTimer
(
0
));
}
else
return
-
1
;
/* Unsupported mode? */
int
i
;
dbg
(
"%s: Waiting for ACAM ring oscillator lock...
\n
"
,
__FUNCTION__
);
start_tics
=
get_tics
();
for
(;;)
{
if
(
acam_pll_locked
(
dev
))
break
;
if
(
get_tics
()
-
start_tics
>
lock_timeout
)
{
dbg
(
"%s: ACAM PLL does not lock.
\n
"
,
__FUNCTION__
);
fail
(
TEST_ACAM_IF
,
"ACAM PLL does not lock."
);
return
-
1
;
}
usleep
(
10000
);
}
acam_set_address
(
dev
,
8
);
/* Permamently select FIFO1 register for readout */
return
0
;
}
/*
---------------------
Calibration functions
---------------------
*/
#define chan_writel(data, addr) fd_writel((data), channel * 0x100 + (addr))
#define chan_readl(addr) fd_readl(channel * 0x100 + (addr))
/* Measures the the FPGA-generated TDC start and the output of one of the fine delay chips (channel)
at a pre-defined number of taps (fine). Retuns the delay in picoseconds. The measurement is repeated
and averaged (n_avgs) times. Also, the standard deviation of the result can be written to (sdev)
if it's not NULL. */
static
double
measure_output_delay
(
fdelay_device_t
*
dev
,
int
channel
,
int
fine
,
int
n_avgs
,
double
*
sdev
)
{
fd_decl_private
(
dev
)
double
acc
=
0
.
0
,
std
=
0
.
0
;
int
i
;
/* Mapping between the channel of the delay card and the stop inputs of the ACAM */
int
chan_to_acam
[
5
]
=
{
0
,
1
,
2
,
3
,
4
};
/* Mapping between the channel number and the time tag FIFOs of the ACAM */
int
chan_to_fifo
[
5
]
=
{
0
,
8
,
8
,
8
,
8
};
double
rec
[
1024
];
/* Disable the output for the channel being calibrated */
sgpio_set_pin
(
dev
,
SGPIO_OUTPUT_EN
(
channel
),
0
);
/* Enable the stop input in the ACAM corresponding to the channel being calibrated */
acam_write_reg
(
dev
,
0
,
AR0_TRiseEn
(
0
)
|
AR0_TRiseEn
(
chan_to_acam
[
channel
])
|
AR0_HQSel
|
AR0_ROsc
);
/* Program the output delay line setpoint */
chan_writel
(
fine
,
FD_REG_FRR
);
chan_writel
(
FD_DCR_ENABLE
|
FD_DCR_MODE
|
FD_DCR_UPDATE
,
FD_REG_DCR
);
chan_writel
(
FD_DCR_FORCE_DLY
|
FD_DCR_ENABLE
,
FD_REG_DCR
);
/* Set the calibration pulse mask to genrate calibration pulses only on one channel at a time.
This minimizes the crosstalk in the output buffer which can severely decrease the accuracy
of calibration measurements */
fd_writel
(
FD_CALR_PSEL_W
(
1
<<
(
channel
-
1
)),
FD_REG_CALR
);
udelay
(
1
);
/* Do n_avgs single measurements and average */
for
(
i
=
0
;
i
<
n_avgs
;
i
++
)
{
uint32_t
fr
;
/* Re-arm the ACAM (it's working in a single-shot mode) */
fd_writel
(
FD_TDCSR_ALUTRIG
,
FD_REG_TDCSR
);
udelay
(
1
);
/* Produce a calibration pulse on the TDC start and the appropriate output channel */
fd_writel
(
FD_CALR_CAL_PULSE
|
FD_CALR_PSEL_W
((
1
<<
(
channel
-
1
))),
FD_REG_CALR
);
udelay
(
1
);
/* read the tag, convert to picoseconds and average */
fr
=
acam_read_reg
(
dev
,
chan_to_fifo
[
channel
]);
double
tag
=
(
double
)((
fr
>>
0
)
&
0x1ffff
)
*
hw
->
acam_bin
*
3
.
0
;
// dbg("Tag %.1f\n", tag);
acc
+=
tag
;
rec
[
i
]
=
tag
;
}
/* Calculate standard dev and average value */
acc
/=
(
double
)
n_avgs
;
for
(
i
=
0
;
i
<
n_avgs
;
i
++
)
std
+=
(
rec
[
i
]
-
acc
)
*
(
rec
[
i
]
-
acc
);
if
(
sdev
)
*
sdev
=
sqrt
(
std
/
(
double
)
n_avgs
);
chan_writel
(
0
,
FD_REG_DCR
);
return
acc
;
}
static
void
measure_linearity
(
double
*
x
,
int
n
,
double
*
inl
,
double
*
dnl
)
{
double
slope
=
(
x
[
n
-
1
]
-
x
[
0
])
/
(
double
)(
n
-
1
);
int
i
;
*
inl
=
0
;
*
dnl
=
0
;
for
(
i
=
0
;
i
<
n
;
i
++
)
{
double
d
=
fabs
(
x
[
i
]
-
(((
double
)
i
)
*
slope
+
x
[
0
]));
if
(
*
inl
<
d
)
*
inl
=
d
;
if
(
i
>
0
)
{
d
=
fabs
(
x
[
i
]
-
x
[
i
-
1
]
-
slope
);
if
(
d
>*
dnl
)
*
dnl
=
d
;
}
}
}
/* Measures the transfer function of the fine delay line (i.e. delay vs number of taps) and checks
its linearity, performing an indirect check of the delay lines' and TDC signal connections. */
#define MAX_DNL 20
#define MAX_INL 60
static
int
test_delay_transfer_function
(
fdelay_device_t
*
dev
)
{
double
inl
,
dnl
;
int
lin_fail
=
0
;
fd_decl_private
(
dev
)
int
channel
,
i
;
double
bias
,
x
,
meas
[
4
][
FDELAY_NUM_TAPS
],
sdev
[
4
][
FDELAY_NUM_TAPS
];
fd_writel
(
FD_GCR_BYPASS
,
FD_REG_GCR
);
acam_configure
(
dev
,
ACAM_IMODE
);
fd_writel
(
FD_TDCSR_START_EN
|
FD_TDCSR_STOP_EN
,
FD_REG_TDCSR
);
for
(
channel
=
1
;
channel
<=
4
;
channel
++
)
{
dbg
(
"calibrating channel %d
\n
"
,
channel
);
bias
=
measure_output_delay
(
dev
,
channel
,
0
,
FDELAY_CAL_AVG_STEPS
,
&
sdev
[
0
][
channel
-
1
]);
meas
[
channel
-
1
][
0
]
=
0
.
0
;
for
(
i
=
FDELAY_NUM_TAPS
-
1
;
i
>=
0
;
i
--
)
{
x
=
measure_output_delay
(
dev
,
channel
,
i
,
FDELAY_CAL_AVG_STEPS
,
&
sdev
[
channel
-
1
][
i
]);
meas
[
channel
-
1
][
i
]
=
x
-
bias
;
}
measure_linearity
(
meas
[
channel
-
1
],
FDELAY_NUM_TAPS
-
1
,
&
inl
,
&
dnl
);
dbg
(
"Linearity: INL = %.1f ps, DNL = %.1f ps
\n
"
,
inl
,
dnl
);
if
(
inl
>
MAX_INL
||
dnl
>
MAX_DNL
)
lin_fail
=
1
;
}
if
(
lin_fail
)
{
dbg
(
"Linearity check failed.
\n
"
);
fail
(
TEST_DELAY_LINE
,
"Maximum INL/DNL exceeded, indicating a wrong connection of the delay chip and/or the TDC calibration signals"
);
return
-
1
;
}
return
0
;
/* FILE *f=fopen("t_func.dat","w");
for(i=0;i<FDELAY_NUM_TAPS;i++)
{
fprintf(f, "%d %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f\n", i,
meas[i][0], meas[i][1], meas[i][2], meas[i][3],
sdev[i][0], sdev[i][1], sdev[i][2], sdev[i][3]);
}
fclose(f);*/
}
/* Finds the preset (i.e. the numer of taps) of the output delay line in (channel)
at which it introduces exactly 8 ns more than when it's programmed to 0 taps.
Uses a binary search algorithm to speed up the calibration (assuming that the
line is monotonous). */
static
int
find_8ns_tap
(
fdelay_device_t
*
dev
,
int
channel
)
{
int
l
=
0
,
r
=
FDELAY_NUM_TAPS
-
1
;
dbg
(
"Calibrating: %d
\n
"
,
channel
);
/* Measure the delay at zero setting, so it can be further subtracted to get only the
delay part introduced by the delay line (ingoring the TDC, FPGA and routing delays). */
double
bias
=
measure_output_delay
(
dev
,
channel
,
0
,
FDELAY_CAL_AVG_STEPS
,
NULL
);
while
(
abs
(
l
-
r
)
>
1
)
{
int
mid
=
(
l
+
r
)
/
2
;
double
dly
=
measure_output_delay
(
dev
,
channel
,
mid
,
FDELAY_CAL_AVG_STEPS
,
NULL
)
-
bias
;
if
(
dly
<
8000
.
0
)
l
=
mid
;
else
r
=
mid
;
}
return
l
;
}
/* Evaluates 2nd order polynomial. Coefs have 32 fractional bits. */
static
int32_t
eval_poly
(
int64_t
*
coef
,
int32_t
x
)
{
int32_t
y
;
y
=
(
coef
[
0
]
*
(
int64_t
)
x
*
(
int64_t
)
x
+
coef
[
1
]
*
(
int64_t
)
x
+
coef
[
2
])
>>
32
;
return
(
int32_t
)
y
;
}
/* Performs the startup calibration of the output delay lines. */
int
calibrate_outputs
(
fdelay_device_t
*
dev
)
{
fd_decl_private
(
dev
)
int
i
,
channel
,
temp
;
#ifdef PERFORM_LONG_TESTS
if
(
test_delay_transfer_function
(
dev
)
<
0
)
return
-
1
;
#endif
fd_writel
(
FD_GCR_BYPASS
,
FD_REG_GCR
);
acam_configure
(
dev
,
ACAM_IMODE
);
fd_writel
(
FD_TDCSR_START_EN
|
FD_TDCSR_STOP_EN
,
FD_REG_TDCSR
);
for
(
channel
=
1
;
channel
<=
4
;
channel
++
)
{
while
(
ds18x_read_temp
(
dev
,
&
temp
)
<
0
)
usleep
(
100000
);
int
cal_measd
=
find_8ns_tap
(
dev
,
channel
);
int
cal_fitted
=
eval_poly
(
hw
->
calib
.
frr_poly
,
temp
);
dbg
(
"%s: CH%d: 8ns @ %d (fitted %d, offset %d, temperature %d.%1d)
\n
"
,
__FUNCTION__
,
channel
,
cal_measd
,
cal_fitted
,
cal_measd
-
cal_fitted
,
temp
);
hw
->
frr_cur
[
channel
-
1
]
=
cal_measd
;
hw
->
frr_offset
[
channel
-
1
]
=
cal_measd
-
cal_fitted
;
}
return
0
;
}
/* TODO: run in a timer context every few seconds instead of the main program loop */
void
fdelay_update_calibration
(
fdelay_device_t
*
dev
)
{
fd_decl_private
(
dev
);
int
channel
,
temp
;
ds18x_read_temp
(
dev
,
&
temp
);
for
(
channel
=
1
;
channel
<=
4
;
channel
++
)
{
int
cal_fitted
=
eval_poly
(
hw
->
calib
.
frr_poly
,
temp
)
+
hw
->
frr_offset
[
channel
-
1
];
dbg
(
"%s: CH%d: FRR = %d
\n
"
,
__FUNCTION__
,
channel
,
cal_fitted
);
hw
->
frr_cur
[
channel
-
1
]
=
cal_fitted
;
chan_writel
(
hw
->
frr_cur
[
channel
-
1
],
FD_REG_FRR
);
}
}
#if 0
void poll_stats()
{
int raw = fd_readl(FD_REG_IECRAW);
int tagged = fd_readl(FD_REG_IECTAG);
int pd = fd_readl(FD_REG_IEPD) & 0xff;
if(events_raw != raw || events_tagged != tagged || pd != tag_delay)
{
events_raw = raw;
events_tagged = tagged;
tag_delay = pd;
// if(events_raw != events_tagged) printf("ERROR: raw %d vs tagged %d\n", raw,tagged);
// printf("NewStats: raw %d tagged %d pdelay %d nsec\n", raw, tagged ,(pd+3)*8);
}
}
#endif
static
int
read_calibration_eeprom
(
fdelay_device_t
*
dev
,
struct
fine_delay_calibration
*
d_cal
)
{
struct
fine_delay_calibration
cal
;
mi2c_init
(
dev
);
if
(
eeprom_read
(
dev
,
EEPROM_ADDR
,
0
,
(
uint8_t
*
)
&
cal
,
sizeof
(
struct
fine_delay_calibration
))
!=
sizeof
(
struct
fine_delay_calibration
))
{
dbg
(
"Can't read calibration EEPROM.
\n
"
);
return
-
1
;
}
if
(
cal
.
magic
!=
FDELAY_MAGIC_ID
)
{
dbg
(
"EEPROM doesn't contain valid calibration block.
\n
"
);
return
0
;
}
memcpy
(
d_cal
,
&
cal
,
sizeof
(
cal
));
return
1
;
}
/*
-------------------------------------
Public API
-------------------------------------
*/
/* Initialize & self-calibrate the Fine Delay card */
int
fdelay_init
(
fdelay_device_t
*
dev
)
{
int
i
,
rv
;
struct
fine_delay_hw
*
hw
;
fdelay_time_t
t_zero
;
dbg
(
"Init: dev %x
\n
"
,
dev
);
hw
=
(
struct
fine_delay_hw
*
)
malloc
(
sizeof
(
struct
fine_delay_hw
));
if
(
!
hw
)
return
-
1
;
dev
->
priv_fd
=
(
void
*
)
hw
;
hw
->
base_addr
=
dev
->
base_addr
;
hw
->
base_i2c
=
0x100
;
hw
->
base_onewire
=
dev
->
base_addr
+
0x500
;
hw
->
wr_enabled
=
0
;
hw
->
wr_state
=
FDELAY_FREE_RUNNING
;
hw
->
acam_addr
=
0xff
;
dbg
(
"%s: Initializing the Fine Delay Card
\n
"
,
__FUNCTION__
);
/* Read the Identification register and check if we are talking to a proper Fine Delay HDL Core */
if
(
fd_readl
(
FD_REG_IDR
)
!=
FDELAY_MAGIC_ID
)
{
fail
(
TEST_FIRMWARE
,
"Core not responding. Firmware loaded incorrectly?"
);
dbg
(
"%s: invalid core signature. Are you sure you have loaded the FPGA with the Fine Delay firmware?
\n
"
,
__FUNCTION__
);
return
-
1
;
}
if
(
!
(
fd_readl
(
FD_REG_GCR
)
&
FD_GCR_FMC_PRESENT
))
{
fail
(
TEST_PRESENCE
,
"FMC Card not detected in the slot. Maybe a fault on PRSNT_L line?"
);
dbg
(
"%s: FMC Presence line not active. Is the FMC correctly inserted into the carrier?
\n
"
,
__FUNCTION__
);
return
-
1
;
}
rv
=
read_calibration_eeprom
(
dev
,
&
hw
->
calib
);
if
(
rv
<
0
)
{
fail
(
TEST_SPI
,
"FMC EEPROM not detected."
);
return
-
1
;
}
else
if
(
!
rv
)
{
int
i
;
dbg
(
"%s: Calibration EEPROM does not contain a valid calibration block. Using default calibration values
\n
"
,
__FUNCTION__
);
hw
->
calib
.
frr_poly
[
0
]
=
-
165202LL
;
hw
->
calib
.
frr_poly
[
1
]
=
-
29825595LL
;
hw
->
calib
.
frr_poly
[
2
]
=
3801939743082LL
;
hw
->
calib
.
tdc_zero_offset
=
35600
;
hw
->
calib
.
atmcr_val
=
2
|
(
1000
<<
4
);
hw
->
calib
.
adsfr_val
=
56648
;
hw
->
calib
.
acam_start_offset
=
10000
;
for
(
i
=
0
;
i
<
4
;
i
++
)
hw
->
calib
.
zero_offset
[
i
]
=
50000
;
}
/* Reset the FMC hardware. */
fd_do_reset
(
dev
,
FD_RESET_HW
);
/* Initialize the clock system - AD9516 PLL */
oc_spi_init
(
dev
);
if
(
sgpio_init
(
dev
)
<
0
)
return
-
1
;
if
(
ad9516_init
(
dev
)
<
0
)
return
-
1
;
if
(
ds18x_init
(
dev
)
<
0
)
{
fail
(
TEST_SPI
,
"DS18x sensor not detected."
);
dbg
(
"DS18x sensor not detected. Bah!
\n
"
);
return
-
1
;
}
int
temp
;
ds18x_read_temp
(
dev
,
&
temp
);
dbg
(
"Device temperature: %d
\n
"
,
temp
);
/* Configure default states of the SPI GPIO pins */
sgpio_set_dir
(
dev
,
SGPIO_TRIG_SEL
,
1
);
sgpio_set_pin
(
dev
,
SGPIO_TRIG_SEL
,
1
);
for
(
i
=
1
;
i
<=
4
;
i
++
)
{
sgpio_set_pin
(
dev
,
SGPIO_OUTPUT_EN
(
i
),
0
);
sgpio_set_dir
(
dev
,
SGPIO_OUTPUT_EN
(
i
),
1
);
}
sgpio_set_dir
(
dev
,
SGPIO_TERM_EN
,
1
);
sgpio_set_pin
(
dev
,
SGPIO_TERM_EN
,
0
);
/* Reset the FD core once we have proper reference/TDC clocks */
fd_do_reset
(
dev
,
FD_RESET_CORE
);
while
(
!
(
fd_readl
(
FD_REG_GCR
)
&
FD_GCR_DDR_LOCKED
))
udelay
(
1
);
fd_do_reset
(
dev
,
FD_RESET_CORE
);
/* Disable the delay generator core, so we can access the ACAM from the host, both for
initialization and calibration */
fd_writel
(
FD_GCR_BYPASS
,
FD_REG_GCR
);
#ifdef PERFORM_LONG_TESTS
if
(
test_pll_dac
(
dev
)
<
0
)
return
-
1
;
#endif
/* Test if ACAM addr/data lines are OK */
if
(
acam_test_bus
(
dev
)
<
0
)
return
-
1
;
/* Calibrate the output delay lines */
if
(
calibrate_outputs
(
dev
)
<
0
)
return
-
1
;
/* Switch to the R-MODE (more precise) */
acam_configure
(
dev
,
ACAM_RMODE
);
/* Switch the ACAM to be driven by the delay core instead of the host */
fd_writel
(
0
,
FD_REG_GCR
);
/* Clear and disable the timestamp readout buffer */
fd_writel
(
FD_TSBCR_PURGE
|
FD_TSBCR_RST_SEQ
,
FD_REG_TSBCR
);
/* Program the ACAM-specific timestamper registers using pre-defined calibration values:
- bin -> internal timebase scalefactor (ADSFR),
- Start offset (must be consistent with the value written to the ACAM reg 4)
- timestamp merging control register (ATMCR) */
fd_writel
(
hw
->
calib
.
adsfr_val
,
FD_REG_ADSFR
);
fd_writel
(
3
*
hw
->
calib
.
acam_start_offset
,
FD_REG_ASOR
);
fd_writel
(
hw
->
calib
.
atmcr_val
,
FD_REG_ATMCR
);
t_zero
.
utc
=
0
;
t_zero
.
coarse
=
0
;
fdelay_set_time
(
dev
,
t_zero
);
/* Enable input */
udelay
(
1
);
fd_writel
(
FD_GCR_INPUT_EN
,
FD_REG_GCR
);
/* Enable output driver */
// sgpio_set_pin(dev, SGPIO_DRV_OEN, 1);
dbg
(
"FD initialized
\n
"
);
return
0
;
}
/* Configures the trigger input. Enable enables the input, termination selects the impedance
of the trigger input (0 == 2kohm, 1 = 50 ohm) */
int
fdelay_configure_trigger
(
fdelay_device_t
*
dev
,
int
enable
,
int
termination
)
{
fd_decl_private
(
dev
)
if
(
termination
)
{
dbg
(
"%s: 50-ohm terminated mode
\n
"
,
__FUNCTION__
);
sgpio_set_pin
(
dev
,
SGPIO_TERM_EN
,
1
);
}
else
{
dbg
(
"%s: high impedance mode
\n
"
,
__FUNCTION__
);
sgpio_set_pin
(
dev
,
SGPIO_TERM_EN
,
0
);
};
if
(
enable
)
{
fd_writel
(
fd_readl
(
FD_REG_GCR
)
|
FD_GCR_INPUT_EN
,
FD_REG_GCR
);
}
else
fd_writel
(
fd_readl
(
FD_REG_GCR
)
&
(
~
FD_GCR_INPUT_EN
)
,
FD_REG_GCR
);
return
0
;
}
/* Converts a positive time interval expressed in picoseconds to the timestamp format used in the Fine Delay core */
fdelay_time_t
fdelay_from_picos
(
const
uint64_t
ps
)
{
fdelay_time_t
t
;
uint64_t
tmp
=
ps
;
t
.
frac
=
(
tmp
%
8000ULL
)
*
(
uint64_t
)(
1
<<
FDELAY_FRAC_BITS
)
/
8000ULL
;
tmp
-=
(
tmp
%
8000ULL
);
tmp
/=
8000ULL
;
t
.
coarse
=
tmp
%
125000000ULL
;
tmp
-=
(
tmp
%
125000000ULL
);
tmp
/=
125000000ULL
;
t
.
utc
=
tmp
;
return
t
;
}
/* Substract two timestamps */
static
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
--
;
}
return
a
;
}
/* Add two timestamps */
static
fdelay_time_t
ts_add
(
fdelay_time_t
a
,
fdelay_time_t
b
)
{
a
.
frac
+=
b
.
frac
;
if
(
a
.
frac
>=
(
1
<<
FDELAY_FRAC_BITS
))
{
a
.
frac
-=
(
1
<<
FDELAY_FRAC_BITS
);
a
.
coarse
++
;
}
a
.
coarse
+=
b
.
coarse
;
if
(
b
.
coarse
>=
125000000
)
{
a
.
coarse
-=
125000000
;
a
.
utc
++
;
}
return
a
;
}
/* Converts a Fine Delay time stamp to plain picoseconds */
int64_t
fdelay_to_picos
(
const
fdelay_time_t
t
)
{
int64_t
tp
=
(((
int64_t
)
t
.
frac
*
8000LL
)
>>
FDELAY_FRAC_BITS
)
+
((
int64_t
)
t
.
coarse
*
8000LL
)
+
((
int64_t
)
t
.
utc
*
1000000000000LL
);
return
tp
;
}
static
int
poll_rbuf
(
fdelay_device_t
*
dev
)
{
fd_decl_private
(
dev
)
if
((
fd_readl
(
FD_REG_TSBCR
)
&
FD_TSBCR_EMPTY
)
==
0
)
return
1
;
return
0
;
}
/* TODO: chan_mask */
int
fdelay_configure_readout
(
fdelay_device_t
*
dev
,
int
enable
)
{
fd_decl_private
(
dev
)
if
(
enable
)
{
fd_writel
(
FD_TSBCR_PURGE
|
FD_TSBCR_RST_SEQ
,
FD_REG_TSBCR
);
fd_writel
(
FD_TSBCR_CHAN_MASK_W
(
1
)
|
FD_TSBCR_ENABLE
,
FD_REG_TSBCR
);
}
else
fd_writel
(
FD_TSBCR_PURGE
|
FD_TSBCR_RST_SEQ
,
FD_REG_TSBCR
);
return
0
;
}
/* Reads up to (how_many) timestamps from the FD ring buffer and stores them in (timestamps).
Returns the number of read timestamps. */
int
fdelay_read
(
fdelay_device_t
*
dev
,
fdelay_time_t
*
timestamps
,
int
how_many
)
{
fd_decl_private
(
dev
)
int
n_read
=
0
;
// dbg("tsbcr %x\n", fd_readl(FD_REG_TSBCR));
while
(
poll_rbuf
(
dev
))
{
fdelay_time_t
ts
;
uint32_t
seq_frac
;
if
(
!
how_many
)
break
;
ts
.
utc
=
((
int64_t
)
(
fd_readl
(
FD_REG_TSBR_SECH
)
&
0xff
)
<<
32
)
|
fd_readl
(
FD_REG_TSBR_SECL
);
ts
.
coarse
=
fd_readl
(
FD_REG_TSBR_CYCLES
)
&
0xfffffff
;
// dbg("Coarse %d\n", ts.coarse);
seq_frac
=
fd_readl
(
FD_REG_TSBR_FID
);
ts
.
frac
=
FD_TSBR_FID_FINE_R
(
seq_frac
);
ts
.
seq_id
=
FD_TSBR_FID_SEQID_R
(
seq_frac
);
ts
.
channel
=
FD_TSBR_FID_CHANNEL_R
(
seq_frac
);
*
timestamps
++
=
ts_sub
(
ts
,
fdelay_from_picos
(
hw
->
calib
.
tdc_zero_offset
));
how_many
--
;
n_read
++
;
}
// printf("read %d\n", how_many, n_read);
return
n_read
;
}
/* Configures the output channel (channel) to produce pulses delayed from the trigger by (delay_ps).
The output pulse width is proviced in (width_ps) parameter. */
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
)
{
fd_decl_private
(
dev
)
uint32_t
base
=
(
channel
-
1
)
*
0x20
;
uint32_t
dcr
;
fdelay_time_t
start
,
end
,
delta
;
if
(
channel
<
1
||
channel
>
4
)
return
-
1
;
delay_ps
-=
hw
->
calib
.
zero_offset
[
channel
-
1
];
start
=
fdelay_from_picos
(
delay_ps
);
end
=
fdelay_from_picos
(
delay_ps
+
width_ps
);
delta
=
fdelay_from_picos
(
delta_ps
);
// printf("Start: %lld: %d:%d\n", start.utc, start.coarse, start.frac);
chan_writel
(
hw
->
frr_cur
[
channel
-
1
],
FD_REG_FRR
);
chan_writel
(
start
.
utc
>>
32
,
FD_REG_U_STARTH
);
chan_writel
(
start
.
utc
&
0xffffffff
,
FD_REG_U_STARTL
);
chan_writel
(
start
.
coarse
,
FD_REG_C_START
);
chan_writel
(
start
.
frac
,
FD_REG_F_START
);
chan_writel
(
end
.
utc
>>
32
,
FD_REG_U_ENDH
);
chan_writel
(
end
.
utc
&
0xffffffff
,
FD_REG_U_ENDL
);
chan_writel
(
end
.
coarse
,
FD_REG_C_END
);
chan_writel
(
end
.
frac
,
FD_REG_F_END
);
chan_writel
(
delta
.
utc
&
0xf
,
FD_REG_U_DELTA
);
chan_writel
(
delta
.
coarse
,
FD_REG_C_DELTA
);
chan_writel
(
delta
.
frac
,
FD_REG_F_DELTA
);
// chan_writel(0, FD_REG_RCR);
chan_writel
(
FD_RCR_REP_CNT_W
(
rep_count
)
|
(
rep_count
<
0
?
FD_RCR_CONT
:
0
),
FD_REG_RCR
);
dcr
=
0
;
/* For narrowly spaced pulses, we don't have enough time to reload the tap number into the corresponding
SY89295 - therefore, the width/spacing resolution is limited to 4 ns. */
if
((
delta_ps
-
width_ps
)
<
200000
||
(
width_ps
<
200000
))
dcr
=
FD_DCR_NO_FINE
;
chan_writel
(
dcr
|
FD_DCR_UPDATE
,
FD_REG_DCR
);
chan_writel
(
dcr
|
FD_DCR_ENABLE
,
FD_REG_DCR
);
sgpio_set_pin
(
dev
,
SGPIO_OUTPUT_EN
(
channel
),
enable
?
1
:
0
);
return
0
;
}
/* Configures the output channel (channel) to produce pulses delayed from the trigger by (delay_ps).
The output pulse width is proviced in (width_ps) parameter. */
int
fdelay_configure_pulse_gen
(
fdelay_device_t
*
dev
,
int
channel
,
int
enable
,
fdelay_time_t
t_start
,
int64_t
width_ps
,
int64_t
delta_ps
,
int
rep_count
)
{
fd_decl_private
(
dev
)
uint32_t
base
=
(
channel
-
1
)
*
0x20
;
uint32_t
dcr
;
fdelay_time_t
start
,
end
,
delta
;
if
(
channel
<
1
||
channel
>
4
)
return
-
1
;
start
=
t_start
;
end
=
fdelay_from_picos
(
fdelay_to_picos
(
start
)
+
width_ps
-
4000
);
delta
=
fdelay_from_picos
(
delta_ps
);
//start = t_start;
//end = ts_add(start, fdelay_from_picos(width_ps));
//delta = fdelay_from_picos(delta_ps);
//printf("Start: %lld: %d:%d\n", start.utc, start.coarse, start.frac);
//printf("width: %lld delta: %lld rep: %d\n", width_ps, delta_ps, rep_count);
chan_writel
(
hw
->
frr_cur
[
channel
-
1
],
FD_REG_FRR
);
chan_writel
(
start
.
utc
>>
32
,
FD_REG_U_STARTH
);
chan_writel
(
start
.
utc
&
0xffffffff
,
FD_REG_U_STARTL
);
chan_writel
(
start
.
coarse
,
FD_REG_C_START
);
chan_writel
(
start
.
frac
,
FD_REG_F_START
);
chan_writel
(
end
.
utc
>>
32
,
FD_REG_U_ENDH
);
chan_writel
(
end
.
utc
&
0xffffffff
,
FD_REG_U_ENDL
);
chan_writel
(
end
.
coarse
,
FD_REG_C_END
);
chan_writel
(
end
.
frac
,
FD_REG_F_END
);
chan_writel
(
delta
.
utc
&
0xf
,
FD_REG_U_DELTA
);
chan_writel
(
delta
.
coarse
,
FD_REG_C_DELTA
);
chan_writel
(
delta
.
frac
,
FD_REG_F_DELTA
);
// chan_writel(0, FD_REG_RCR);
chan_writel
(
FD_RCR_REP_CNT_W
(
rep_count
<
0
?
0
:
rep_count
-
1
)
|
(
rep_count
<
0
?
FD_RCR_CONT
:
0
),
FD_REG_RCR
);
dcr
=
FD_DCR_MODE
;
/* For narrowly spaced pulses, we don't have enough time to reload the tap number into the corresponding
SY89295 - therefore, the width/spacing resolution is limited to 4 ns. */
if
((
delta_ps
-
width_ps
)
<
200000
||
(
width_ps
<
200000
))
dcr
|=
FD_DCR_NO_FINE
;
chan_writel
(
dcr
|
FD_DCR_UPDATE
,
FD_REG_DCR
);
chan_writel
(
dcr
|
FD_DCR_ENABLE
,
FD_REG_DCR
);
chan_writel
(
dcr
|
FD_DCR_ENABLE
|
FD_DCR_PG_ARM
,
FD_REG_DCR
);
sgpio_set_pin
(
dev
,
SGPIO_OUTPUT_EN
(
channel
),
enable
?
1
:
0
);
return
0
;
}
int
fdelay_channel_triggered
(
fdelay_device_t
*
dev
,
int
channel
)
{
fd_decl_private
(
dev
)
return
chan_readl
(
FD_REG_DCR
)
&
FD_DCR_PG_TRIG
?
1
:
0
;
}
/* Todo: write get_time() */
int
fdelay_set_time
(
fdelay_device_t
*
dev
,
const
fdelay_time_t
t
)
{
fd_decl_private
(
dev
)
uint32_t
tcr
;
uint32_t
gcr
;
fd_writel
(
0
,
FD_REG_GCR
);
fd_writel
(
t
.
utc
>>
32
,
FD_REG_TM_SECH
);
fd_writel
(
t
.
utc
&
0xffffffff
,
FD_REG_TM_SECL
);
fd_writel
(
t
.
coarse
,
FD_REG_TM_CYCLES
);
tcr
=
fd_readl
(
FD_REG_TCR
);
fd_writel
(
tcr
|
FD_TCR_SET_TIME
,
FD_REG_TCR
);
return
0
;
}
/* Todo: write get_time() */
int
fdelay_get_time
(
fdelay_device_t
*
dev
,
fdelay_time_t
*
t
)
{
fd_decl_private
(
dev
)
uint32_t
tcr
;
tcr
=
fd_readl
(
FD_REG_TCR
);
fd_writel
(
tcr
|
FD_TCR_CAP_TIME
,
FD_REG_TCR
);
t
->
utc
=
fd_readl
(
FD_REG_TM_SECL
);
t
->
coarse
=
fd_readl
(
FD_REG_TM_CYCLES
);
return
0
;
}
#if 0
/* To be rewritten to use interrupts and new WR FSM (see TCR register description).
Use the API provided in fdelay_lib.h */
int fdelay_configure_sync(fdelay_device_t *dev, int mode)
{
fd_decl_private(dev)
if(mode == FDELAY_SYNC_LOCAL)
{
fd_writel(0, FD_REG_GCR);
// fd_writel(FD_GCR_CSYNC_INT, FD_REG_GCR);
hw->wr_enabled = 0;
} else {
fd_writel(0, FD_REG_GCR);
hw->wr_enabled = 1;
hw->wr_state = FDELAY_WR_OFFLINE;
}
}
int fdelay_get_sync_status(fdelay_device_t *dev)
{
fd_decl_private(dev)
if(!hw->wr_enabled) return FDELAY_FREE_RUNNING;
switch(hw->wr_state)
{
case FDELAY_WR_OFFLINE:
if(fd_readl(FD_REG_GCR) & FD_GCR_WR_READY)
{
dbg("-> WR Core synced\n");
hw->wr_state = FDELAY_WR_READY;
}
break;
case FDELAY_WR_READY:
fd_writel(FD_GCR_WR_LOCK_EN, FD_REG_GCR);
hw->wr_state = FDELAY_WR_SYNCING;
break;
case FDELAY_WR_SYNCING:
if(fd_readl(FD_REG_GCR) & FD_GCR_WR_LOCKED)
{
fd_writel(FD_GCR_WR_LOCK_EN | FD_GCR_CSYNC_WR, FD_REG_GCR);
fd_writel(FD_GCR_WR_LOCK_EN , FD_REG_GCR);
fd_writel(FD_GCR_WR_LOCK_EN | FD_GCR_INPUT_EN, FD_REG_GCR);
hw->wr_state = FDELAY_WR_SYNCED;
}
break;
case FDELAY_WR_SYNCED:
if((fd_readl(FD_REG_GCR) & FD_GCR_WR_LOCKED) == 0)
hw->wr_state = FDELAY_WR_OFFLINE;
break;
}
return hw->wr_state;
}
#endif
# if 0
/* We might implement SPLL-based DMTD calibration, but not now - don't include in the driver */
int
fd_update_spll
(
fdelay_device_t
*
dev
)
{
struct
spll_helper_state
pll
;
fd_decl_private
(
dev
)
int
i
=
0
;
helper_start
(
dev
,
&
pll
);
fd_writel
(
FD_CALR_CAL_DMTD
,
FD_REG_CALR
);
sgpio_set_pin
(
dev
,
SGPIO_TRIG_SEL
,
0
);
for
(;;)
{
helper_update
(
&
pll
);
//if(pll.prelock.ld.locked)
// dbg("LOCK!");
}
}
#endif
common/fmc_delay/lib/fdelay_pps_demo.c
0 → 100644
View file @
557f9512
#include <stdio.h>
#include "fdelay_lib.h"
int
spec_fdelay_init
(
int
argc
,
char
*
argv
[],
fdelay_device_t
*
dev
);
main
(
int
argc
,
char
*
argv
[])
{
fdelay_device_t
dev
;
fdelay_time_t
t_cur
,
t_start
;
if
(
spec_fdelay_init
(
argc
,
argv
,
&
dev
)
<
0
)
return
-
1
;
// Get the current time of the FD core - and program the card to start producing the PPS and 10 MHz one second later */
fdelay_get_time
(
&
dev
,
&
t_cur
);
printf
(
"Current Time: %lld:%d
\n
"
,
t_cur
.
utc
,
t_cur
.
coarse
);
t_start
.
coarse
=
t_cur
.
coarse
;
t_start
.
utc
=
t_cur
.
utc
+
1
;
t_start
.
frac
=
0
;
fdelay_configure_pulse_gen
(
&
dev
,
1
,
1
,
t_start
,
48000LL
,
100000LL
,
-
1
);
/* Output 1, period = 100 ns, width = 48 ns - a bit asymmetric 10 MHz */
fdelay_configure_pulse_gen
(
&
dev
,
2
,
1
,
t_start
,
48000LL
,
1000000000000LL
,
-
1
);
/* Output 2: period = 1 second, width = 48 ns - PPS signal */
while
(
!
fdelay_channel_triggered
(
&
dev
,
1
)
||
fdelay_channel_triggered
(
&
dev
,
2
))
usleep
(
10000
);
/* wait until both outputs have triggered*/
;
return
0
;
}
common/fmc_delay/lib/fdelay_temp_calibration.c
0 → 100644
View file @
557f9512
#include <stdio.h>
#include "fdelay_lib.h"
#include "rr_io.h"
void
my_writel
(
void
*
priv
,
uint32_t
data
,
uint32_t
addr
)
{
rr_writel
(
data
,
addr
);
}
uint32_t
my_readl
(
void
*
priv
,
uint32_t
addr
)
{
uint32_t
d
=
rr_readl
(
addr
);
return
d
;
}
main
()
{
fdelay_device_t
dev
;
rr_init
();
dev
.
writel
=
my_writel
;
dev
.
readl
=
my_readl
;
dev
.
base_addr
=
0x84000
;
if
(
fdelay_init
(
&
dev
)
<
0
)
return
-
1
;
fdelay_configure_trigger
(
&
dev
,
1
,
1
);
fdelay_configure_output
(
&
dev
,
1
,
1
,
500000
,
100000
,
100000
,
0
);
fdelay_configure_output
(
&
dev
,
2
,
1
,
500000
,
100000
,
100000
,
0
);
fdelay_configure_output
(
&
dev
,
3
,
1
,
500000
,
100000
,
100000
,
0
);
fdelay_configure_output
(
&
dev
,
4
,
1
,
500000
,
100000
,
100000
,
0
);
fdelay_configure_readout
(
&
dev
,
1
);
// fd_update_spll(&dev);
int64_t
prev
=
0
,
dp
,
pmin
=
10000000000LL
,
pmax
=
0
;
#if 0
for(;;)
{
fdelay_time_t ts;
if(fdelay_read(&dev, &ts, 1) == 1)
{
int64_t ts_p = fdelay_to_picos(ts), d;
d=ts_p - prev;
if(prev > 0)
{
if(d<pmin) pmin=d;
if(d>pmax) pmax=d;
fprintf(stderr,"Got it %lld:%d:%d delta %lld span %lld\n", ts.utc, ts.coarse, ts.frac, d, pmax-pmin);
}
prev = ts_p;
}
}
#endif
}
common/fmc_delay/lib/fdelay_test.c
0 → 100644
View file @
557f9512
#include <stdio.h>
#include "fdelay_lib.h"
#include "rr_io.h"
int
spec_fdelay_init
(
int
argc
,
char
*
argv
[],
fdelay_device_t
*
dev
);
main
(
int
argc
,
char
*
argv
[])
{
fdelay_device_t
dev
;
fdelay_time_t
t_cur
,
t_start
;
if
(
spec_fdelay_init
(
argc
,
argv
,
&
dev
)
<
0
)
{
fdelay_show_test_results
();
return
-
1
;
}
fdelay_configure_trigger
(
&
dev
,
1
,
1
);
fdelay_configure_output
(
&
dev
,
1
,
1
,
500000
,
100000
,
100000
,
0
);
fdelay_configure_output
(
&
dev
,
2
,
1
,
500000
,
100000
,
100000
,
0
);
fdelay_configure_output
(
&
dev
,
3
,
1
,
500000
,
100000
,
100000
,
0
);
fdelay_configure_output
(
&
dev
,
4
,
1
,
500000
,
100000
,
100000
,
0
);
fdelay_configure_readout
(
&
dev
,
1
);
// fd_update_spll(&dev);
int64_t
prev
=
0
,
dp
,
pmin
=
10000000000LL
,
pmax
=
0
;
#if 0
for(;;)
{
fdelay_time_t ts;
if(fdelay_read(&dev, &ts, 1) == 1)
{
int64_t ts_p = fdelay_to_picos(ts), d;
d=ts_p - prev;
if(prev > 0)
{
if(d<pmin) pmin=d;
if(d>pmax) pmax=d;
fprintf(stderr,"Got it %lld:%d:%d delta %lld span %lld\n", ts.utc, ts.coarse, ts.frac, d, pmax-pmin);
}
prev = ts_p;
}
}
#endif
for
(;;)
{
fdelay_update_calibration
(
&
dev
);
sleep
(
1
);
}
}
common/fmc_delay/lib/i2c_master.c
0 → 100644
View file @
557f9512
#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
;
}
common/fmc_delay/lib/mini_bone/Makefile
0 → 100644
View file @
557f9512
OBJS
=
minibone_lib.o ptpd_netif.o
all
:
$(OBJS)
gcc
-o
m
$(OBJS)
\ No newline at end of file
common/fmc_delay/lib/mini_bone/minibone_lib.c
0 → 100644
View file @
557f9512
/* MiniBone library. BUGGY CRAP CODE INTENDED FOR TESTING ONLY! */
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sys/socket.h>
#include <sys/time.h>
#include "ptpd_netif.h"
#define F_SEL(x) (x & 0xf)
#define F_ERROR (1<<1)
#define F_READBACK (1<<0)
#define F_WRITE (1<<4)
#define RX_TIMEOUT 10
#define MBN_ETHERTYPE 0xa0a0
struct
mbn_packet
{
uint16_t
flags
;
uint32_t
a_d
;
uint32_t
d
;
}
__attribute__
((
packed
));
struct
mb_device
{
mac_addr_t
dest
;
uint16_t
ethertype
;
wr_socket_t
*
sock
;
int
tx_packets
,
rx_packets
,
tx_retries
,
rx_retries
;
};
typedef
struct
{
uint64_t
start_tics
;
uint64_t
timeout
;
}
timeout_t
;
static
uint64_t
get_tics
()
{
struct
timezone
tz
=
{
0
,
0
};
struct
timeval
tv
;
gettimeofday
(
&
tv
,
&
tz
);
return
(
uint64_t
)
tv
.
tv_sec
*
1000000ULL
+
(
uint64_t
)
tv
.
tv_usec
;
}
static
inline
int
tmo_init
(
timeout_t
*
tmo
,
uint32_t
milliseconds
)
{
tmo
->
start_tics
=
get_tics
();
tmo
->
timeout
=
(
uint64_t
)
milliseconds
*
1000ULL
;
return
0
;
}
static
inline
int
tmo_restart
(
timeout_t
*
tmo
)
{
tmo
->
start_tics
=
get_tics
();
return
0
;
}
static
inline
int
tmo_expired
(
timeout_t
*
tmo
)
{
return
(
get_tics
()
-
tmo
->
start_tics
>
tmo
->
timeout
);
}
void
*
mbn_open
(
const
char
*
if_name
,
mac_addr_t
target
)
{
struct
mb_device
*
dev
=
malloc
(
sizeof
(
struct
mb_device
));
wr_sockaddr_t
saddr
;
if
(
!
dev
)
return
NULL
;
memset
(
dev
,
0
,
sizeof
(
struct
mb_device
));
memcpy
(
dev
->
dest
,
target
,
6
);
strcpy
(
saddr
.
if_name
,
if_name
);
memcpy
(
saddr
.
mac
,
target
,
6
);
saddr
.
ethertype
=
htons
(
MBN_ETHERTYPE
);
saddr
.
family
=
PTPD_SOCK_RAW_ETHERNET
;
dev
->
sock
=
ptpd_netif_create_socket
(
PTPD_SOCK_RAW_ETHERNET
,
0
,
&
saddr
);
if
(
!
dev
->
sock
)
{
free
(
dev
);
return
NULL
;
}
return
(
void
*
)
dev
;
}
static
int
mbn_send
(
void
*
priv
,
uint8_t
*
data
,
int
size
)
{
struct
mb_device
*
dev
=
(
struct
mb_device
*
)
priv
;
wr_sockaddr_t
to
;
memcpy
(
to
.
mac
,
dev
->
dest
,
6
);
to
.
ethertype
=
MBN_ETHERTYPE
;
return
ptpd_netif_sendto
(
dev
->
sock
,
&
to
,
(
void
*
)
data
,
size
,
NULL
);
}
static
int
mbn_recv
(
void
*
handle
,
uint8_t
*
data
,
int
size
,
int
timeout
)
{
struct
mb_device
*
dev
=
(
struct
mb_device
*
)
handle
;
wr_sockaddr_t
from
;
timeout_t
rx_tmo
;
tmo_init
(
&
rx_tmo
,
timeout
);
do
{
int
n
=
ptpd_netif_recvfrom
(
dev
->
sock
,
&
from
,
(
void
*
)
data
,
size
,
NULL
);
if
(
n
>
0
&&
from
.
ethertype
==
MBN_ETHERTYPE
&&
!
memcmp
(
from
.
mac
,
dev
->
dest
,
6
))
{
dev
->
rx_packets
++
;
return
n
;
}
// dev->rx_retries++;
}
while
(
!
tmo_expired
(
&
rx_tmo
));
return
0
;
}
void
mbn_writel
(
void
*
handle
,
uint32_t
d
,
uint32_t
a
)
{
struct
mb_device
*
dev
=
(
struct
mb_device
*
)
handle
;
int
n_retries
=
3
;
struct
mbn_packet
pkt
;
while
(
n_retries
--
)
{
pkt
.
flags
=
htons
(
F_SEL
(
0xf
)
|
F_WRITE
);
pkt
.
a_d
=
htonl
(
a
);
pkt
.
d
=
htonl
(
d
);
mbn_send
(
handle
,
(
uint8_t
*
)
&
pkt
,
sizeof
(
pkt
));
int
n
=
mbn_recv
(
handle
,
(
uint8_t
*
)
&
pkt
,
sizeof
(
pkt
),
RX_TIMEOUT
);
pkt
.
flags
=
ntohs
(
pkt
.
flags
);
if
(
n
==
sizeof
(
pkt
)
&&
!
(
!
(
pkt
.
flags
&&
F_READBACK
)
&&
!
(
pkt
.
flags
&
F_ERROR
)))
{
int
i
;
fprintf
(
stderr
,
"
\n
BadPacket: "
);
for
(
i
=
0
;
i
<
n
;
i
++
)
fprintf
(
stderr
,
"%02x "
,
*
(
uint8_t
*
)
(
&
pkt
+
i
));
fprintf
(
stderr
,
"
\n
"
);
}
if
(
n
==
sizeof
(
pkt
)
&&
!
(
pkt
.
flags
&&
F_READBACK
)
&&
!
(
pkt
.
flags
&
F_ERROR
))
{
int
i
;
// fprintf(stderr,"GoodFlags: %x\n", pkt.flags);
/*fprintf(stderr,"\nGoodPacket: ");
for(i=0;i<n; i++) fprintf(stderr,"%02x ", *(uint8_t*) (&pkt + i));
fprintf(stderr,"\n");*/
dev
->
tx_packets
++
;
return
;
}
dev
->
tx_retries
++
;
}
fprintf
(
stderr
,
"No ack.
\n
"
);
}
uint32_t
mbn_readl
(
void
*
handle
,
uint32_t
a
)
{
int
n_retries
=
3
;
struct
mb_device
*
dev
=
(
struct
mb_device
*
)
handle
;
struct
mbn_packet
pkt
;
pkt
.
flags
=
htons
(
F_SEL
(
0xf
));
pkt
.
a_d
=
htonl
(
a
);
while
(
n_retries
--
)
{
mbn_send
(
handle
,
(
uint8_t
*
)
&
pkt
,
sizeof
(
pkt
));
int
n
=
mbn_recv
(
handle
,
(
uint8_t
*
)
&
pkt
,
sizeof
(
pkt
),
RX_TIMEOUT
);
pkt
.
flags
=
ntohs
(
pkt
.
flags
);
if
(
n
==
sizeof
(
pkt
)
&&
(
pkt
.
flags
&
F_READBACK
)
&&
!
(
pkt
.
flags
&
F_ERROR
))
{
return
ntohl
(
pkt
.
a_d
);
}
dev
->
tx_retries
++
;
}
fprintf
(
stderr
,
"No ack.
\n
"
);
}
void
mbn_stats
(
void
*
handle
)
{
struct
mb_device
*
dev
=
(
struct
mb_device
*
)
handle
;
fprintf
(
stderr
,
"Sent: %d [retries: %d], rcvd: %d [retries: %d]
\n
"
,
dev
->
tx_packets
,
dev
->
tx_retries
,
dev
->
rx_packets
,
dev
->
rx_retries
);
}
void
mbn_close
(
void
*
handle
)
{
struct
mb_device
*
dev
=
(
struct
mb_device
*
)
handle
;
ptpd_netif_close_socket
(
dev
->
sock
);
}
\ No newline at end of file
common/fmc_delay/lib/mini_bone/minibone_lib.h
0 → 100644
View file @
557f9512
/* MiniBone library. BUGGY CRAP CODE INTENDED FOR TESTING ONLY! */
#ifndef __MINIBONE_LIB_H
#define __MINIBONE_LIB_H
#include <stdint.h>
void
*
mbn_open
(
const
char
*
if_name
,
uint8_t
target_mac
[]);
void
mbn_writel
(
void
*
handle
,
uint32_t
d
,
uint32_t
a
);
uint32_t
mbn_readl
(
void
*
handle
,
uint32_t
a
);
void
mbn_close
(
void
*
handle
);
#endif
common/fmc_delay/lib/mini_bone/ptpd_netif.c
0 → 100644
View file @
557f9512
// Supports only raw ethernet now.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <linux/errqueue.h>
#include <linux/sockios.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <asm/types.h>
#include <fcntl.h>
#include <errno.h>
#include <asm/socket.h>
#include "ptpd_netif.h"
#ifdef NETIF_VERBOSE
#define netif_dbg(...) printf(__VA_ARGS__)
#else
#define netif_dbg(...)
#endif
#define ETHER_MTU 1518
#define DMTD_UPDATE_INTERVAL 100
struct
scm_timestamping
{
struct
timespec
systime
;
struct
timespec
hwtimetrans
;
struct
timespec
hwtimeraw
;
};
PACKED
struct
etherpacket
{
struct
ethhdr
ether
;
char
data
[
ETHER_MTU
];
};
struct
tx_timestamp
{
int
valid
;
wr_timestamp_t
ts
;
uint32_t
tag
;
uint64_t
t_acq
;
};
struct
my_socket
{
int
fd
;
wr_sockaddr_t
bind_addr
;
mac_addr_t
local_mac
;
int
if_index
;
// parameters for linearization of RX timestamps
uint32_t
clock_period
;
uint32_t
phase_transition
;
uint32_t
dmtd_phase
;
};
struct
nasty_hack
{
char
if_name
[
20
];
int
clockedAsPrimary
;
};
#ifdef MACIEK_HACKs
struct
nasty_hack
locking_hack
;
#endif
wr_socket_t
*
ptpd_netif_create_socket
(
int
sock_type
,
int
flags
,
wr_sockaddr_t
*
bind_addr
)
{
struct
my_socket
*
s
;
struct
sockaddr_ll
sll
;
struct
ifreq
f
;
int
fd
;
// fprintf(stderr,"CreateSocket!\n");
if
(
sock_type
!=
PTPD_SOCK_RAW_ETHERNET
)
return
NULL
;
fd
=
socket
(
PF_PACKET
,
SOCK_RAW
,
htons
(
ETH_P_ALL
));
if
(
fd
<
0
)
{
perror
(
"socket()"
);
return
NULL
;
}
fcntl
(
fd
,
F_SETFL
,
O_NONBLOCK
);
// Put the controller in promiscious mode, so it receives everything
strcpy
(
f
.
ifr_name
,
bind_addr
->
if_name
);
if
(
ioctl
(
fd
,
SIOCGIFFLAGS
,
&
f
)
<
0
)
{
perror
(
"ioctl()"
);
return
NULL
;
}
f
.
ifr_flags
|=
IFF_PROMISC
;
if
(
ioctl
(
fd
,
SIOCSIFFLAGS
,
&
f
)
<
0
)
{
perror
(
"ioctl()"
);
return
NULL
;
}
// Find the inteface index
strcpy
(
f
.
ifr_name
,
bind_addr
->
if_name
);
ioctl
(
fd
,
SIOCGIFINDEX
,
&
f
);
sll
.
sll_ifindex
=
f
.
ifr_ifindex
;
sll
.
sll_family
=
AF_PACKET
;
sll
.
sll_protocol
=
htons
(
bind_addr
->
ethertype
);
sll
.
sll_halen
=
6
;
memcpy
(
sll
.
sll_addr
,
bind_addr
->
mac
,
6
);
if
(
bind
(
fd
,
(
struct
sockaddr
*
)
&
sll
,
sizeof
(
struct
sockaddr_ll
))
<
0
)
{
close
(
fd
);
perror
(
"bind()"
);
return
NULL
;
}
s
=
calloc
(
sizeof
(
struct
my_socket
),
1
);
s
->
if_index
=
f
.
ifr_ifindex
;
// get interface MAC address
if
(
ioctl
(
fd
,
SIOCGIFHWADDR
,
&
f
)
<
0
)
{
perror
(
"ioctl()"
);
return
NULL
;
}
memcpy
(
s
->
local_mac
,
f
.
ifr_hwaddr
.
sa_data
,
6
);
memcpy
(
&
s
->
bind_addr
,
bind_addr
,
sizeof
(
wr_sockaddr_t
));
s
->
fd
=
fd
;
return
(
wr_socket_t
*
)
s
;
}
int
ptpd_netif_close_socket
(
wr_socket_t
*
sock
)
{
struct
my_socket
*
s
=
(
struct
my_socket
*
)
sock
;
if
(
!
s
)
return
0
;
close
(
s
->
fd
);
return
0
;
}
int
ptpd_netif_sendto
(
wr_socket_t
*
sock
,
wr_sockaddr_t
*
to
,
void
*
data
,
size_t
data_length
,
wr_timestamp_t
*
tx_ts
)
{
struct
etherpacket
pkt
;
struct
my_socket
*
s
=
(
struct
my_socket
*
)
sock
;
struct
sockaddr_ll
sll
;
int
rval
;
wr_timestamp_t
ts
;
if
(
s
->
bind_addr
.
family
!=
PTPD_SOCK_RAW_ETHERNET
)
return
-
ENOTSUP
;
if
(
data_length
>
ETHER_MTU
-
8
)
return
-
EINVAL
;
memset
(
&
pkt
,
0
,
sizeof
(
struct
etherpacket
));
memcpy
(
pkt
.
ether
.
h_dest
,
to
->
mac
,
6
);
memcpy
(
pkt
.
ether
.
h_source
,
s
->
local_mac
,
6
);
pkt
.
ether
.
h_proto
=
htons
(
to
->
ethertype
);
memcpy
(
pkt
.
data
,
data
,
data_length
);
size_t
len
=
data_length
+
sizeof
(
struct
ethhdr
);
if
(
len
<
72
)
len
=
72
;
memset
(
&
sll
,
0
,
sizeof
(
struct
sockaddr_ll
));
sll
.
sll_ifindex
=
s
->
if_index
;
sll
.
sll_family
=
AF_PACKET
;
sll
.
sll_protocol
=
htons
(
to
->
ethertype
);
sll
.
sll_halen
=
6
;
// fprintf(stderr,"fd %d ifi %d ethertype %d\n", s->fd,
// s->if_index, to->ethertype);
rval
=
sendto
(
s
->
fd
,
&
pkt
,
len
,
0
,
(
struct
sockaddr
*
)
&
sll
,
sizeof
(
struct
sockaddr_ll
));
return
rval
;
}
int
ptpd_netif_recvfrom
(
wr_socket_t
*
sock
,
wr_sockaddr_t
*
from
,
void
*
data
,
size_t
data_length
,
wr_timestamp_t
*
rx_timestamp
)
{
struct
my_socket
*
s
=
(
struct
my_socket
*
)
sock
;
struct
etherpacket
pkt
;
struct
msghdr
msg
;
struct
iovec
entry
;
struct
sockaddr_ll
from_addr
;
struct
{
struct
cmsghdr
cm
;
char
control
[
1024
];
}
control
;
struct
cmsghdr
*
cmsg
;
struct
scm_timestamping
*
sts
=
NULL
;
size_t
len
=
data_length
+
sizeof
(
struct
ethhdr
);
memset
(
&
msg
,
0
,
sizeof
(
msg
));
msg
.
msg_iov
=
&
entry
;
msg
.
msg_iovlen
=
1
;
entry
.
iov_base
=
&
pkt
;
entry
.
iov_len
=
len
;
msg
.
msg_name
=
(
caddr_t
)
&
from_addr
;
msg
.
msg_namelen
=
sizeof
(
from_addr
);
msg
.
msg_control
=
&
control
;
msg
.
msg_controllen
=
sizeof
(
control
);
int
ret
=
recvmsg
(
s
->
fd
,
&
msg
,
MSG_DONTWAIT
);
if
(
ret
<
0
&&
errno
==
EAGAIN
)
return
0
;
// would be blocking
if
(
ret
==
-
EAGAIN
)
return
0
;
if
(
ret
<=
0
)
return
ret
;
memcpy
(
data
,
pkt
.
data
,
ret
-
sizeof
(
struct
ethhdr
));
from
->
ethertype
=
ntohs
(
pkt
.
ether
.
h_proto
);
memcpy
(
from
->
mac
,
pkt
.
ether
.
h_source
,
6
);
memcpy
(
from
->
mac_dest
,
pkt
.
ether
.
h_dest
,
6
);
return
ret
-
sizeof
(
struct
ethhdr
);
}
common/fmc_delay/lib/mini_bone/ptpd_netif.h
0 → 100644
View file @
557f9512
// Network API for WR-PTPd
#ifndef __PTPD_NETIF_H
#define __PTPD_NETIF_H
#include <stdio.h>
//#include <inttypes.h>
#define PTPD_SOCK_RAW_ETHERNET 1
#define PTPD_SOCK_UDP 2
#define PTPD_FLAGS_MULTICAST 0x1
// error codes (to be extended)
#define PTPD_NETIF_READY 1
#define PTPD_NETIF_OK 0
#define PTPD_NETIF_ERROR -1
#define PTPD_NETIF_NOT_READY -2
#define PTPD_NETIF_NOT_FOUND -3
// GCC-specific
#define PACKED __attribute__((packed))
#define PHYS_PORT_ANY (0xffff)
#define PTPD_NETIF_TX 1
#define PTPD_NETIF_RX 2
#define IFACE_NAME_LEN 16
#define SLAVE_PRIORITY_0 0
#define SLAVE_PRIORITY_1 1
#define SLAVE_PRIORITY_2 2
#define SLAVE_PRIORITY_3 3
#define SLAVE_PRIORITY_4 4
// Some system-independent definitions
typedef
uint8_t
mac_addr_t
[
6
];
typedef
uint32_t
ipv4_addr_t
;
// WhiteRabbit socket - it's void pointer as the real socket structure is private and probably platform-specific.
typedef
void
*
wr_socket_t
;
// Socket address for ptp_netif_ functions
typedef
struct
{
// Network interface name (eth0, ...)
char
if_name
[
IFACE_NAME_LEN
];
// Socket family (RAW ethernet/UDP)
int
family
;
// MAC address
mac_addr_t
mac
;
// Destination MASC address, filled by recvfrom() function on interfaces bound to multiple addresses
mac_addr_t
mac_dest
;
// IP address
ipv4_addr_t
ip
;
// UDP port
uint16_t
port
;
// RAW ethertype
uint16_t
ethertype
;
// physical port to bind socket to
uint16_t
physical_port
;
}
wr_sockaddr_t
;
typedef
struct
{
uint32_t
v
[
4
];
}
wr_picoseconds_t
;
// Precise WhiteRabbit timestamp
// TS[picoseconds] = utc * 1e12 + nsec * 1e3 + phase;
PACKED
struct
_wr_timestamp
{
// UTC time value (seconds)
int64_t
utc
;
// Nanoseconds
int32_t
nsec
;
// Phase (in picoseconds), linearized for receive timestamps, zero for send timestamps
int32_t
phase
;
// phase(picoseconds)
int32_t
raw_phase
;
int32_t
raw_nsec
;
int32_t
raw_ahead
;
//int cntr_ahead;
};
typedef
struct
_wr_timestamp
wr_timestamp_t
;
/* OK. These functions we'll develop along with network card driver. You can write your own UDP-based stubs for testing purposes. */
// Initialization of network interface:
// - opens devices
// - does necessary ioctls()
// - initializes connection with the mighty HAL daemon
int
ptpd_netif_init
();
// Creates UDP or Ethernet RAW socket (determined by sock_type) bound to bind_addr. If PTPD_FLAG_MULTICAST is set, the socket is
// automatically added to multicast group. User can specify physical_port field to bind the socket to specific switch port only.
wr_socket_t
*
ptpd_netif_create_socket
(
int
sock_type
,
int
flags
,
wr_sockaddr_t
*
bind_addr
);
// Sends a UDP/RAW packet (data, data_length) to address provided in wr_sockaddr_t.
// For raw frames, mac/ethertype needs to be provided, for UDP - ip/port.
// Every transmitted frame has assigned a tag value, stored at tag parameter. This value is later used
// for recovering the precise transmit timestamp. If user doesn't need it, tag parameter can be left NULL.
int
ptpd_netif_sendto
(
wr_socket_t
*
sock
,
wr_sockaddr_t
*
to
,
void
*
data
,
size_t
data_length
,
wr_timestamp_t
*
tx_ts
);
// Receives an UDP/RAW packet. Data is written to (data) and length is returned. Maximum buffer length can be specified
// by data_length parameter. Sender information is stored in structure specified in 'from'. All RXed packets are timestamped and the timestamp
// is stored in rx_timestamp (unless it's NULL).
int
ptpd_netif_recvfrom
(
wr_socket_t
*
sock
,
wr_sockaddr_t
*
from
,
void
*
data
,
size_t
data_length
,
wr_timestamp_t
*
rx_timestamp
);
// Closes the socket.
int
ptpd_netif_close_socket
(
wr_socket_t
*
sock
);
int
ptpd_netif_poll
(
wr_socket_t
*
);
int
ptpd_netif_get_hw_addr
(
wr_socket_t
*
sock
,
mac_addr_t
*
mac
);
/*
* Function start HW locking of freq on WR Slave
* return:
* PTPD_NETIF_ERROR - locking not started
* PTPD_NETIF_OK - locking started
*/
int
ptpd_netif_locking_enable
(
int
txrx
,
const
char
*
ifaceName
,
int
priority
);
/*
*
* return:
*
* PTPD_NETIF_OK - locking started
*/
int
ptpd_netif_locking_disable
(
int
txrx
,
const
char
*
ifaceName
,
int
priority
);
int
ptpd_netif_locking_poll
(
int
txrx
,
const
char
*
ifaceName
,
int
priority
);
/*
* Function turns on calibration (measurement of delay)
* Tx or Rx depending on the txrx param
* return:
* PTPD_NETIF_NOT_READY - if there is calibratin going on on another port
* PTPD_NETIF_OK - calibration started
*/
int
ptpd_netif_calibrating_enable
(
int
txrx
,
const
char
*
ifaceName
);
/*
* Function turns off calibration (measurement of delay)
* Tx or Rx depending on the txrx param
* return:
* PTPD_NETIF_ERROR - if there is calibratin going on on another port
* PTPD_NETIF_OK - calibration started
*/
int
ptpd_netif_calibrating_disable
(
int
txrx
,
const
char
*
ifaceName
);
/*
* Function checks if Rx/Tx (depending on the param) calibration is finished
* if finished, returns measured delay in delta
* return:
*
* PTPD_NETIF_OK - locking started
*/
int
ptpd_netif_calibrating_poll
(
int
txrx
,
const
char
*
ifaceName
,
uint64_t
*
delta
);
/*
* Function turns on calibration pattern.
* return:
* PTPD_NETIF_NOT_READY - if WRSW is busy with calibration on other switch or error occured
* PTPD_NETIF_OK - calibration started
*/
int
ptpd_netif_calibration_pattern_enable
(
const
char
*
ifaceName
,
unsigned
int
calibrationPeriod
,
unsigned
int
calibrationPattern
,
unsigned
int
calibrationPatternLen
);
/*
* Function turns off calibration pattern
* return:
* PTPD_NETIF_ERROR - turning off not successful
* PTPD_NETIF_OK - turning off successful
*/
int
ptpd_netif_calibration_pattern_disable
(
const
char
*
ifaceName
);
/*
* Function read calibration data if it's available, used at the beginning of PTPWRd to check if
* HW knows already the interface's deltax, and therefore no need for calibration
* return:
* PTPD_NETIF_NOT_FOUND - if deltas are not known
* PTPD_NETIF_OK - if deltas are known, in such case, deltaTx and deltaRx have valid data
*/
int
ptpd_netif_read_calibration_data
(
const
char
*
ifaceName
,
uint64_t
*
deltaTx
,
uint64_t
*
deltaRx
);
#define MACIEK_TMP
#ifdef MACIEK_TMP
int
ptpd_netif_select
(
wr_socket_t
*
);
int
ptpd_netif_get_hw_addr
(
wr_socket_t
*
sock
,
mac_addr_t
*
mac
);
#endif
/*
* Function reads state of the given port (interface in our case), if the port is up, everything is OK, otherwise ERROR
* return:
* PTPD_NETIF_ERROR - if the port is down
* PTPD_NETIF_OK - if the port is up
*/
int
ptpd_netif_get_port_state
(
const
char
*
ifaceName
);
/*
* Function looks for a port (interface) for the port number 'number'
* it will return in the argument ifname the port name
* return:
* PTPD_NETIF_ERROR - port not found
* PTPD_NETIF_OK - if the port found
*/
int
ptpd_netif_get_ifName
(
char
*
ifname
,
int
number
);
/* Returns the millisecond "tics" counter value */
uint64_t
ptpd_netif_get_msec_tics
();
/*
* Function detects external source lock,
*
* return:
* HEXP_EXTSRC_STATUS_LOCKED 0
* HEXP_LOCK_STATUS_BUSY 1
* HEXP_EXTSRC_STATUS_NOSRC 2
*/
int
ptpd_netif_extsrc_detection
();
#endif
common/fmc_delay/lib/onewire.c
0 → 100644
View file @
557f9512
#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
]);
return
ds18x_read_temp
(
dev
,
NULL
);
}
common/fmc_delay/lib/rr_io.c
0 → 100644
View file @
557f9512
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <rawrabbit.h>
#include "rr_io.h"
#define DEVNAME "/dev/rawrabbit"
static
int
fd
;
int
rr_bind
(
int
a_fd
)
{
fd
=
a_fd
;
return
0
;
}
int
rr_init
(
int
bus
,
int
devfn
)
{
struct
rr_devsel
devsel
;
int
ret
=
-
EINVAL
;
devsel
.
bus
=
bus
;
devsel
.
devfn
=
devfn
;
devsel
.
subvendor
=
RR_DEVSEL_UNUSED
;
devsel
.
vendor
=
0x10dc
;
//RR_DEVSEL_UNUSED;
devsel
.
device
=
0x18d
;
//RR_DEVSEL_UNUSED;
devsel
.
subdevice
=
RR_DEVSEL_UNUSED
;
fd
=
open
(
DEVNAME
,
O_RDWR
);
if
(
fd
<
0
)
{
return
-
1
;
}
if
(
ioctl
(
fd
,
RR_DEVSEL
,
&
devsel
)
<
0
)
{
return
-
EIO
;
}
return
0
;
}
int
rr_writel
(
uint32_t
data
,
uint32_t
addr
)
{
struct
rr_iocmd
iocmd
;
iocmd
.
datasize
=
4
;
iocmd
.
address
=
addr
;
iocmd
.
address
|=
__RR_SET_BAR
(
0
);
iocmd
.
data32
=
data
;
ioctl
(
fd
,
RR_WRITE
,
&
iocmd
);
}
uint32_t
rr_readl
(
uint32_t
addr
)
{
struct
rr_iocmd
iocmd
;
iocmd
.
datasize
=
4
;
iocmd
.
address
=
addr
;
iocmd
.
address
|=
__RR_SET_BAR
(
0
);
ioctl
(
fd
,
RR_READ
,
&
iocmd
);
return
iocmd
.
data32
;
}
static
void
gennum_writel
(
uint32_t
data
,
uint32_t
addr
)
{
struct
rr_iocmd
iocmd
;
iocmd
.
datasize
=
4
;
iocmd
.
address
=
addr
;
iocmd
.
address
|=
__RR_SET_BAR
(
4
);
iocmd
.
data32
=
data
;
ioctl
(
fd
,
RR_WRITE
,
&
iocmd
);
}
static
uint32_t
gennum_readl
(
uint32_t
addr
)
{
struct
rr_iocmd
iocmd
;
iocmd
.
datasize
=
4
;
iocmd
.
address
=
addr
;
iocmd
.
address
|=
__RR_SET_BAR
(
4
);
ioctl
(
fd
,
RR_READ
,
&
iocmd
);
return
iocmd
.
data32
;
}
static
inline
int64_t
get_tics
()
{
struct
timezone
tz
=
{
0
,
0
};
struct
timeval
tv
;
gettimeofday
(
&
tv
,
&
tz
);
return
(
int64_t
)
tv
.
tv_sec
*
1000000LL
+
(
int64_t
)
tv
.
tv_usec
;
}
/* These must be set to choose the FPGA configuration mode */
#define GPIO_BOOTSEL0 15
#define GPIO_BOOTSEL1 14
static
inline
uint8_t
reverse_bits8
(
uint8_t
x
)
{
x
=
((
x
>>
1
)
&
0x55
)
|
((
x
&
0x55
)
<<
1
);
x
=
((
x
>>
2
)
&
0x33
)
|
((
x
&
0x33
)
<<
2
);
x
=
((
x
>>
4
)
&
0x0f
)
|
((
x
&
0x0f
)
<<
4
);
return
x
;
}
static
uint32_t
unaligned_bitswap_le32
(
const
uint32_t
*
ptr32
)
{
static
uint32_t
tmp32
;
static
uint8_t
*
tmp8
=
(
uint8_t
*
)
&
tmp32
;
static
uint8_t
*
ptr8
;
ptr8
=
(
uint8_t
*
)
ptr32
;
*
(
tmp8
+
0
)
=
reverse_bits8
(
*
(
ptr8
+
0
));
*
(
tmp8
+
1
)
=
reverse_bits8
(
*
(
ptr8
+
1
));
*
(
tmp8
+
2
)
=
reverse_bits8
(
*
(
ptr8
+
2
));
*
(
tmp8
+
3
)
=
reverse_bits8
(
*
(
ptr8
+
3
));
return
tmp32
;
}
static
inline
void
gpio_out
(
int
fd
,
const
uint32_t
addr
,
const
int
bit
,
const
int
value
)
{
uint32_t
reg
;
reg
=
gennum_readl
(
addr
);
if
(
value
)
reg
|=
(
1
<<
bit
);
else
reg
&=
~
(
1
<<
bit
);
gennum_writel
(
reg
,
addr
);
}
/*
* Unfortunately, most of the following is from fcl_gn4124.cpp, for which
* the license terms are at best ambiguous.
*/
int
loader_low_level
(
int
fd
,
const
void
*
data
,
int
size8
)
{
int
size32
=
(
size8
+
3
)
>>
2
;
const
uint32_t
*
data32
=
data
;
int
ctrl
=
0
,
i
,
done
=
0
,
wrote
=
0
;
/* configure Gennum GPIO to select GN4124->FPGA configuration mode */
gpio_out
(
fd
,
GNGPIO_DIRECTION_MODE
,
GPIO_BOOTSEL0
,
0
);
gpio_out
(
fd
,
GNGPIO_DIRECTION_MODE
,
GPIO_BOOTSEL1
,
0
);
gpio_out
(
fd
,
GNGPIO_OUTPUT_ENABLE
,
GPIO_BOOTSEL0
,
1
);
gpio_out
(
fd
,
GNGPIO_OUTPUT_ENABLE
,
GPIO_BOOTSEL1
,
1
);
gpio_out
(
fd
,
GNGPIO_OUTPUT_VALUE
,
GPIO_BOOTSEL0
,
1
);
gpio_out
(
fd
,
GNGPIO_OUTPUT_VALUE
,
GPIO_BOOTSEL1
,
0
);
gennum_writel
(
0x00
,
FCL_CLK_DIV
);
gennum_writel
(
0x40
,
FCL_CTRL
);
/* Reset */
i
=
gennum_readl
(
FCL_CTRL
);
if
(
i
!=
0x40
)
{
printf
(
"%s: %i: error
\n
"
,
__func__
,
__LINE__
);
return
-
EIO
;
}
gennum_writel
(
0x00
,
FCL_CTRL
);
gennum_writel
(
0x00
,
FCL_IRQ
);
/* clear pending irq */
switch
(
size8
&
3
)
{
case
3
:
ctrl
=
0x116
;
break
;
case
2
:
ctrl
=
0x126
;
break
;
case
1
:
ctrl
=
0x136
;
break
;
case
0
:
ctrl
=
0x106
;
break
;
}
gennum_writel
(
ctrl
,
FCL_CTRL
);
gennum_writel
(
0x00
,
FCL_CLK_DIV
);
/* again? maybe 1 or 2? */
gennum_writel
(
0x00
,
FCL_TIMER_CTRL
);
/* "disable FCL timr fun" */
gennum_writel
(
0x10
,
FCL_TIMER_0
);
/* "pulse width" */
gennum_writel
(
0x00
,
FCL_TIMER_1
);
/*
* Set delay before data and clock is applied by FCL
* after SPRI_STATUS is detected being assert.
*/
gennum_writel
(
0x08
,
FCL_TIMER2_0
);
/* "delay before data/clk" */
gennum_writel
(
0x00
,
FCL_TIMER2_1
);
gennum_writel
(
0x17
,
FCL_EN
);
/* "output enable" */
ctrl
|=
0x01
;
/* "start FSM configuration" */
gennum_writel
(
ctrl
,
FCL_CTRL
);
while
(
size32
>
0
)
{
/* Check to see if FPGA configuation has error */
i
=
gennum_readl
(
FCL_IRQ
);
if
(
(
i
&
8
)
&&
wrote
)
{
done
=
1
;
printf
(
"%s: %i: done after %i
\n
"
,
__func__
,
__LINE__
,
wrote
);
}
else
if
(
(
i
&
0x4
)
&&
!
done
)
{
printf
(
"%s: %i: error after %i
\n
"
,
__func__
,
__LINE__
,
wrote
);
return
-
EIO
;
}
/* Wait until at least 1/2 of the fifo is empty */
while
(
gennum_readl
(
FCL_IRQ
)
&
(
1
<<
5
))
;
/* Write a few dwords into FIFO at a time. */
for
(
i
=
0
;
size32
&&
i
<
32
;
i
++
)
{
gennum_writel
(
unaligned_bitswap_le32
(
data32
),
FCL_FIFO
);
data32
++
;
size32
--
;
wrote
++
;
}
}
gennum_writel
(
0x186
,
FCL_CTRL
);
/* "last data written" */
/* Checking for the "interrupt" condition is left to the caller */
return
wrote
;
}
int
rr_load_bitstream_from_file
(
const
char
*
file_name
)
{
uint8_t
*
buf
;
FILE
*
f
;
uint32_t
size
;
f
=
fopen
(
file_name
,
"rb"
);
if
(
!
f
)
return
-
1
;
fseek
(
f
,
0
,
SEEK_END
);
size
=
ftell
(
f
);
buf
=
malloc
(
size
);
if
(
!
buf
)
{
fclose
(
f
);
return
-
1
;
}
fseek
(
f
,
0
,
SEEK_SET
);
fread
(
buf
,
1
,
size
,
f
);
fclose
(
f
);
int
rval
=
loader_low_level
(
0
,
buf
,
size
);
free
(
buf
);
return
rval
;
}
common/fmc_delay/lib/spec_common.c
0 → 100644
View file @
557f9512
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include "fdelay_lib.h"
#include "rr_io.h"
void
spec_writel
(
void
*
priv
,
uint32_t
data
,
uint32_t
addr
)
{
rr_writel
(
data
,
addr
);
}
uint32_t
spec_readl
(
void
*
priv
,
uint32_t
addr
)
{
uint32_t
d
=
rr_readl
(
addr
);
return
d
;
}
int
spec_fdelay_init
(
int
argc
,
char
*
argv
[],
fdelay_device_t
*
dev
)
{
int
bus
=
RR_DEVSEL_UNUSED
,
devfn
=
RR_DEVSEL_UNUSED
;
int
opt
=
0
;
char
fw_name
[
1024
];
strcpy
(
fw_name
,
"spec_top.bin"
);
while
((
opt
=
getopt
(
argc
,
argv
,
"hb:d:f:"
))
!=
-
1
)
{
switch
(
opt
)
{
case
'h'
:
printf
(
"Usage: %s [-b PCI_bus] [-d PCI dev/func] [-f firmware file]
\n
"
,
argv
[
0
]);
printf
(
"By default, the first detected SPEC is initialized with 'spec_top.bin' firmware
\n
"
);
return
0
;
case
'b'
:
sscanf
(
optarg
,
"%x"
,
&
bus
);
break
;
case
'd'
:
sscanf
(
optarg
,
"%x"
,
&
devfn
);
break
;
case
'f'
:
strcpy
(
fw_name
,
optarg
);
break
;
}
}
if
(
rr_init
(
bus
,
devfn
)
<
0
)
{
fprintf
(
stderr
,
"Failed to initialize rawrabbit.
\n
"
);
return
-
1
;
}
dev
->
writel
=
spec_writel
;
dev
->
readl
=
spec_readl
;
dev
->
base_addr
=
0x84000
;
if
(
rr_load_bitstream_from_file
(
fw_name
)
<
0
)
{
fprintf
(
stderr
,
"Failed to load FPGA bitstream.
\n
"
);
return
-
1
;
}
if
(
fdelay_init
(
dev
)
<
0
)
return
-
1
;
return
0
;
}
common/fmc_delay/lib/spll/softpll_ng.c
0 → 100644
View file @
557f9512
#include <stdio.h>
#include "board.h"
#include "hw/softpll_regs.h"
#include "irq.h"
static
volatile
struct
SPLL_WB
*
SPLL
=
(
volatile
struct
SPLL_WB
*
)
BASE_SOFTPLL
;
/* The includes below contain code (not only declarations) to enable the compiler
to inline functions where necessary and save some CPU cycles */
#include "spll_defs.h"
#include "spll_common.h"
#include "spll_helper.h"
volatile
int
irq_count
=
0
,
eee
,
yyy
;
struct
spll_helper_state
helper
;
void
_irq_entry
()
{
volatile
uint32_t
trr
;
int
src
=
-
1
,
tag
;
if
(
!
(
SPLL
->
CSR
&
SPLL_TRR_CSR_EMPTY
))
{
trr
=
SPLL
->
TRR_R0
;
src
=
SPLL_TRR_R0_CHAN_ID_R
(
trr
);
tag
=
SPLL_TRR_R0_VALUE_R
(
trr
);
eee
=
tag
;
}
helper_update
(
&
helper
,
tag
,
src
);
yyy
=
helper
.
phase
.
pi
.
y
;
irq_count
++
;
clear_irq
();
}
void
spll_init
()
{
volatile
int
dummy
;
disable_irq
();
SPLL
->
CSR
=
0
;
SPLL
->
OCER
=
0
;
SPLL
->
RCER
=
0
;
SPLL
->
DEGLITCH_THR
=
2000
;
while
(
!
(
SPLL
->
TRR_CSR
&
SPLL_TRR_CSR_EMPTY
))
dummy
=
SPLL
->
TRR_R0
;
dummy
=
SPLL
->
PER_HPLL
;
SPLL
->
EIC_IER
=
1
;
}
void
spll_test
()
{
int
i
=
0
;
volatile
int
dummy
;
spll_init
();
helper_start
(
&
helper
,
6
);
enable_irq
();
for
(;;)
{
mprintf
(
"cnt %d serr %d src %d y %d d %d
\n
"
,
irq_count
,
eee
,
serr
,
yyy
,
delta
);
}
}
\ No newline at end of file
common/fmc_delay/lib/spll/spll_common.h
0 → 100644
View file @
557f9512
/*
White Rabbit Softcore PLL (SoftPLL) - common definitions
*/
/* PI regulator state */
typedef
struct
{
int
ki
,
kp
;
/* integral and proportional gains (1<<PI_FRACBITS == 1.0f) */
int
integrator
;
/* current integrator value */
int
bias
;
/* DC offset always added to the output */
int
anti_windup
;
/* when non-zero, anti-windup is enabled */
int
y_min
;
/* min/max output range, used by claming and antiwindup algorithms */
int
y_max
;
int
x
,
y
;
/* Current input and output value */
}
spll_pi_t
;
/* Processes a single sample (x) using PI controller (pi). Returns the value (y) which should
be used to drive the actuator. */
static
inline
int
pi_update
(
spll_pi_t
*
pi
,
int
x
)
{
int
i_new
,
y
;
pi
->
x
=
x
;
i_new
=
pi
->
integrator
+
x
;
y
=
((
i_new
*
pi
->
ki
+
x
*
pi
->
kp
)
>>
PI_FRACBITS
)
+
pi
->
bias
;
/* clamping (output has to be in <y_min, y_max>) and anti-windup:
stop the integretor if the output is already out of range and the output
is going further away from y_min/y_max. */
if
(
y
<
pi
->
y_min
)
{
y
=
pi
->
y_min
;
if
((
pi
->
anti_windup
&&
(
i_new
>
pi
->
integrator
))
||
!
pi
->
anti_windup
)
pi
->
integrator
=
i_new
;
}
else
if
(
y
>
pi
->
y_max
)
{
y
=
pi
->
y_max
;
if
((
pi
->
anti_windup
&&
(
i_new
<
pi
->
integrator
))
||
!
pi
->
anti_windup
)
pi
->
integrator
=
i_new
;
}
else
pi
->
integrator
=
i_new
;
pi
->
y
=
y
;
return
y
;
}
/* initializes the PI controller state. Currently almost a stub. */
static
inline
void
pi_init
(
spll_pi_t
*
pi
)
{
pi
->
integrator
=
0
;
}
/* lock detector state */
typedef
struct
{
int
lock_cnt
;
int
lock_samples
;
int
delock_samples
;
int
threshold
;
int
locked
;
}
spll_lock_det_t
;
/* Lock detector state machine. Takes an error sample (y) and checks if it's withing an acceptable range
(i.e. <-ld.threshold, ld.threshold>. If it has been inside the range for (ld.lock_samples) cyckes, the
FSM assumes the PLL is locked. */
static
inline
int
ld_update
(
spll_lock_det_t
*
ld
,
int
y
)
{
if
(
abs
(
y
)
<=
ld
->
threshold
)
{
if
(
ld
->
lock_cnt
<
ld
->
lock_samples
)
ld
->
lock_cnt
++
;
if
(
ld
->
lock_cnt
==
ld
->
lock_samples
)
ld
->
locked
=
1
;
}
else
{
if
(
ld
->
lock_cnt
>
ld
->
delock_samples
)
ld
->
lock_cnt
--
;
if
(
ld
->
lock_cnt
==
ld
->
delock_samples
)
{
ld
->
lock_cnt
=
0
;
ld
->
locked
=
0
;
}
}
return
ld
->
locked
;
}
static
void
ld_init
(
spll_lock_det_t
*
ld
)
{
ld
->
locked
=
0
;
ld
->
lock_cnt
=
0
;
}
common/fmc_delay/lib/spll/spll_defs.h
0 → 100644
View file @
557f9512
/*
White Rabbit Softcore PLL (SoftPLL) - common definitions
*/
#include <stdio.h>
/* Reference clock frequency */
#define CLOCK_FREQ 125000000
/* Bit size of phase tags generated by the DMTDs. Used to sign-extend the tags. */
#define TAG_BITS 20
/* Helper PLL N divider (1/2**N is the frequency offset) */
#define HPLL_N 14
/* Fractional bits in PI controller coefficients */
#define PI_FRACBITS 12
common/fmc_delay/lib/spll/spll_helper.h
0 → 100644
View file @
557f9512
/* State of the Helper PLL producing a clock (clk_dmtd_i) which is
slightly offset in frequency from the recovered/reference clock (clk_rx_i or clk_ref_i), so the
Main PLL can use it to perform linear phase measurements. This structure keeps the state of the pre-locking
stage */
struct
spll_helper_prelock_state
{
spll_pi_t
pi
;
spll_lock_det_t
ld
;
int
f_setpoint
;
int
ref_select
;
fdelay_device_t
*
dev
;
};
volatile
int
serr
;
void
helper_prelock_init
(
struct
spll_helper_prelock_state
*
s
)
{
/* Frequency branch PI controller */
s
->
pi
.
y_min
=
5
;
s
->
pi
.
y_max
=
65530
;
s
->
pi
.
anti_windup
=
0
;
s
->
pi
.
kp
=
28
*
32
*
16
;
s
->
pi
.
ki
=
50
*
32
*
16
;
s
->
pi
.
bias
=
32000
;
/* Freqency branch lock detection */
s
->
ld
.
threshold
=
2
;
s
->
ld
.
lock_samples
=
1000
;
s
->
ld
.
delock_samples
=
990
;
s
->
f_setpoint
=
131072
/
(
1
<<
HPLL_N
);
pi_init
(
&
s
->
pi
);
ld_init
(
&
s
->
ld
);
}
void
helper_prelock_enable
(
struct
spll_helper_prelock_state
*
state
,
int
ref_channel
,
int
enable
)
{
fdelay_device_t
*
dev
=
state
->
dev
;
fd_decl_private
(
dev
);
fd_writel
(
0
,
FD_REG_SPLLR
);
}
#define SPLL_LOCKED 1
#define SPLL_LOCKING 0
int
helper_prelock_update
(
struct
spll_helper_prelock_state
*
s
,
int
tag
)
{
fdelay_device_t
*
dev
=
s
->
dev
;
fd_decl_private
(
dev
);
int
y
;
volatile
uint32_t
per
=
fd_readl
(
FD_REG_SPLLR
);
short
err
=
(
short
)
(
tag
&
0xffff
);
serr
=
(
int
)
err
;
err
-=
s
->
f_setpoint
;
y
=
pi_update
(
&
s
->
pi
,
err
);
fd_writel
(
y
,
FD_REG_SDACR
);
if
(
ld_update
(
&
s
->
ld
,
err
))
return
SPLL_LOCKED
;
return
SPLL_LOCKING
;
}
struct
spll_helper_phase_state
{
spll_pi_t
pi
;
spll_lock_det_t
ld
;
int
p_setpoint
,
tag_d0
;
int
ref_src
;
fdelay_device_t
*
dev
;
};
void
helper_phase_init
(
struct
spll_helper_phase_state
*
s
)
{
/* Phase branch PI controller */
s
->
pi
.
y_min
=
5
;
s
->
pi
.
y_max
=
65530
;
s
->
pi
.
kp
=
(
int
)(
2
.
0
*
32
.
0
*
16
.
0
);
s
->
pi
.
ki
=
(
int
)(
0
.
05
*
32
.
0
*
3
.
0
);
s
->
pi
.
anti_windup
=
0
;
s
->
pi
.
bias
=
32000
;
/* Phase branch lock detection */
s
->
ld
.
threshold
=
500
;
s
->
ld
.
lock_samples
=
10000
;
s
->
ld
.
delock_samples
=
9900
;
s
->
ref_src
=
6
;
s
->
p_setpoint
=
-
1
;
pi_init
(
&
s
->
pi
);
ld_init
(
&
s
->
ld
);
}
void
helper_phase_enable
(
struct
spll_helper_phase_state
*
state
,
int
ref_channel
,
int
enable
)
{
fdelay_device_t
*
dev
=
state
->
dev
;
fd_decl_private
(
dev
);
fd_writel
(
FD_SPLLR_MODE
,
FD_REG_SPLLR
);
}
volatile
int
delta
;
int
helper_phase_update
(
struct
spll_helper_phase_state
*
s
,
int
tag
,
int
source
)
{
fdelay_device_t
*
dev
=
s
->
dev
;
fd_decl_private
(
dev
);
int
err
,
y
;
serr
=
source
;
// if(source == s->ref_src)
{
if
(
s
->
p_setpoint
<
0
)
{
s
->
p_setpoint
=
tag
;
return
;
}
err
=
tag
-
s
->
p_setpoint
;
delta
=
tag
-
s
->
tag_d0
;
s
->
tag_d0
=
tag
;
s
->
p_setpoint
+=
(
1
<<
HPLL_N
);
if
(
s
->
p_setpoint
>
(
1
<<
TAG_BITS
))
s
->
p_setpoint
-=
(
1
<<
TAG_BITS
);
y
=
pi_update
(
&
s
->
pi
,
err
);
//printf("t %d sp %d\n", tag, s->p_setpoint);
fd_writel
(
y
,
FD_REG_SDACR
);
if
(
ld_update
(
&
s
->
ld
,
err
))
{
return
SPLL_LOCKED
;
};
}
return
SPLL_LOCKING
;
}
#define HELPER_PRELOCKING 1
#define HELPER_PHASE 2
#define HELPER_LOCKED 3
struct
spll_helper_state
{
struct
spll_helper_prelock_state
prelock
;
struct
spll_helper_phase_state
phase
;
int
state
;
int
ref_channel
;
};
void
helper_start
(
fdelay_device_t
*
dev
,
struct
spll_helper_state
*
s
)
{
s
->
state
=
HELPER_PRELOCKING
;
s
->
ref_channel
=
0
;
s
->
prelock
.
dev
=
dev
;
s
->
phase
.
dev
=
dev
;
helper_prelock_init
(
&
s
->
prelock
);
helper_phase_init
(
&
s
->
phase
);
helper_prelock_enable
(
&
s
->
prelock
,
0
,
1
);
}
void
helper_update
(
struct
spll_helper_state
*
s
)
{
fdelay_device_t
*
dev
=
s
->
prelock
.
dev
;
fd_decl_private
(
dev
);
uint32_t
spllr
=
fd_readl
(
FD_REG_SPLLR
);
if
(
!
(
spllr
&
FD_SPLLR_TAG_RDY
))
return
;
int
tag
=
FD_SPLLR_TAG_R
(
spllr
);
switch
(
s
->
state
)
{
case
HELPER_PRELOCKING
:
if
(
helper_prelock_update
(
&
s
->
prelock
,
tag
)
==
SPLL_LOCKED
)
{
s
->
state
=
HELPER_PHASE
;
helper_prelock_enable
(
&
s
->
prelock
,
0
,
0
);
s
->
phase
.
pi
.
bias
=
s
->
prelock
.
pi
.
y
;
helper_phase_enable
(
&
s
->
phase
,
0
,
1
);
}
break
;
case
HELPER_PHASE
:
helper_phase_update
(
&
s
->
phase
,
tag
,
0
);
break
;
}
}
common/fmc_delay/python/demo.py
0 → 100644
View file @
557f9512
#!/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
(
"
%.3
f"
%
ts
.
nsecs
()))
m
.
ts_table
.
setItem
(
row
,
3
,
QTableWidgetItem
(
"
%.3
f"
%
(
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__"
:
app
=
QApplication
(
sys
.
argv
)
location
=
"local/0x84000"
m
=
MainWindow
()
m
.
show
()
m
.
setWindowTitle
(
"Fine Delay Demo @
%
s"
%
location
)
card
=
FineDelay
(
location
)
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_
()
common/fmc_delay/python/fd_demo.ui
0 → 100644
View file @
557f9512
<?xml version="1.0" encoding="UTF-8"?>
<ui
version=
"4.0"
>
<class>
MyDialog
</class>
<widget
class=
"QDialog"
name=
"MyDialog"
>
<property
name=
"geometry"
>
<rect>
<x>
0
</x>
<y>
0
</y>
<width>
649
</width>
<height>
352
</height>
</rect>
</property>
<property
name=
"windowTitle"
>
<string>
Fine Delay Demo
</string>
</property>
<widget
class=
"QTabWidget"
name=
"tabWidget"
>
<property
name=
"geometry"
>
<rect>
<x>
10
</x>
<y>
10
</y>
<width>
631
</width>
<height>
331
</height>
</rect>
</property>
<property
name=
"currentIndex"
>
<number>
0
</number>
</property>
<widget
class=
"QWidget"
name=
"tab_delay"
>
<attribute
name=
"title"
>
<string>
Delay
</string>
</attribute>
<widget
class=
"QGroupBox"
name=
"groupBox"
>
<property
name=
"geometry"
>
<rect>
<x>
10
</x>
<y>
10
</y>
<width>
591
</width>
<height>
161
</height>
</rect>
</property>
<property
name=
"title"
>
<string>
Outputs
</string>
</property>
<widget
class=
"QLabel"
name=
"label_2"
>
<property
name=
"geometry"
>
<rect>
<x>
470
</x>
<y>
10
</y>
<width>
91
</width>
<height>
16
</height>
</rect>
</property>
<property
name=
"font"
>
<font>
<weight>
75
</weight>
<bold>
true
</bold>
</font>
</property>
<property
name=
"text"
>
<string>
Pulse width
</string>
</property>
</widget>
<widget
class=
"QWidget"
name=
"layoutWidget"
>
<property
name=
"geometry"
>
<rect>
<x>
10
</x>
<y>
30
</y>
<width>
581
</width>
<height>
128
</height>
</rect>
</property>
<layout
class=
"QVBoxLayout"
name=
"verticalLayout"
>
<item>
<layout
class=
"QHBoxLayout"
name=
"horizontalLayout"
>
<item>
<widget
class=
"QLabel"
name=
"label_3"
>
<property
name=
"font"
>
<font>
<weight>
75
</weight>
<bold>
true
</bold>
</font>
</property>
<property
name=
"text"
>
<string>
OUT1:
</string>
</property>
</widget>
</item>
<item>
<widget
class=
"QCheckBox"
name=
"en_ch1"
>
<property
name=
"text"
>
<string>
Enabled
</string>
</property>
</widget>
</item>
<item>
<widget
class=
"QDoubleSpinBox"
name=
"sec_ch1"
>
<property
name=
"prefix"
>
<string/>
</property>
<property
name=
"suffix"
>
<string>
s
</string>
</property>
<property
name=
"decimals"
>
<number>
0
</number>
</property>
<property
name=
"minimum"
>
<double>
0.000000000000000
</double>
</property>
<property
name=
"maximum"
>
<double>
120.000000000000000
</double>
</property>
<property
name=
"singleStep"
>
<double>
1.000000000000000
</double>
</property>
<property
name=
"value"
>
<double>
0.000000000000000
</double>
</property>
</widget>
</item>
<item>
<widget
class=
"QDoubleSpinBox"
name=
"nsec_ch1"
>
<property
name=
"prefix"
>
<string/>
</property>
<property
name=
"suffix"
>
<string>
ns
</string>
</property>
<property
name=
"decimals"
>
<number>
3
</number>
</property>
<property
name=
"minimum"
>
<double>
500.000000000000000
</double>
</property>
<property
name=
"maximum"
>
<double>
1000000000.000000000000000
</double>
</property>
<property
name=
"singleStep"
>
<double>
0.050000000000000
</double>
</property>
</widget>
</item>
<item>
<widget
class=
"QDoubleSpinBox"
name=
"width_ch1"
>
<property
name=
"prefix"
>
<string/>
</property>
<property
name=
"suffix"
>
<string>
ns
</string>
</property>
<property
name=
"decimals"
>
<number>
3
</number>
</property>
<property
name=
"minimum"
>
<double>
200.000000000000000
</double>
</property>
<property
name=
"maximum"
>
<double>
1000000000.000000000000000
</double>
</property>
<property
name=
"singleStep"
>
<double>
0.050000000000000
</double>
</property>
<property
name=
"value"
>
<double>
200.000000000000000
</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout
class=
"QHBoxLayout"
name=
"horizontalLayout_2"
>
<item>
<widget
class=
"QLabel"
name=
"label_4"
>
<property
name=
"font"
>
<font>
<weight>
75
</weight>
<bold>
true
</bold>
</font>
</property>
<property
name=
"text"
>
<string>
OUT2:
</string>
</property>
</widget>
</item>
<item>
<widget
class=
"QCheckBox"
name=
"en_ch2"
>
<property
name=
"text"
>
<string>
Enabled
</string>
</property>
</widget>
</item>
<item>
<widget
class=
"QDoubleSpinBox"
name=
"sec_ch2"
>
<property
name=
"prefix"
>
<string/>
</property>
<property
name=
"suffix"
>
<string>
s
</string>
</property>
<property
name=
"decimals"
>
<number>
0
</number>
</property>
<property
name=
"minimum"
>
<double>
0.000000000000000
</double>
</property>
<property
name=
"maximum"
>
<double>
120.000000000000000
</double>
</property>
<property
name=
"singleStep"
>
<double>
1.000000000000000
</double>
</property>
<property
name=
"value"
>
<double>
0.000000000000000
</double>
</property>
</widget>
</item>
<item>
<widget
class=
"QDoubleSpinBox"
name=
"nsec_ch2"
>
<property
name=
"prefix"
>
<string/>
</property>
<property
name=
"suffix"
>
<string>
ns
</string>
</property>
<property
name=
"decimals"
>
<number>
3
</number>
</property>
<property
name=
"minimum"
>
<double>
500.000000000000000
</double>
</property>
<property
name=
"maximum"
>
<double>
1000000000.000000000000000
</double>
</property>
<property
name=
"singleStep"
>
<double>
0.050000000000000
</double>
</property>
</widget>
</item>
<item>
<widget
class=
"QDoubleSpinBox"
name=
"width_ch2"
>
<property
name=
"prefix"
>
<string/>
</property>
<property
name=
"suffix"
>
<string>
ns
</string>
</property>
<property
name=
"decimals"
>
<number>
3
</number>
</property>
<property
name=
"minimum"
>
<double>
200.000000000000000
</double>
</property>
<property
name=
"maximum"
>
<double>
1000000000.000000000000000
</double>
</property>
<property
name=
"singleStep"
>
<double>
0.050000000000000
</double>
</property>
<property
name=
"value"
>
<double>
200.000000000000000
</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout
class=
"QHBoxLayout"
name=
"horizontalLayout_3"
>
<item>
<widget
class=
"QLabel"
name=
"label_5"
>
<property
name=
"font"
>
<font>
<weight>
75
</weight>
<bold>
true
</bold>
</font>
</property>
<property
name=
"text"
>
<string>
OUT3:
</string>
</property>
</widget>
</item>
<item>
<widget
class=
"QCheckBox"
name=
"en_ch3"
>
<property
name=
"text"
>
<string>
Enabled
</string>
</property>
</widget>
</item>
<item>
<widget
class=
"QDoubleSpinBox"
name=
"sec_ch3"
>
<property
name=
"prefix"
>
<string/>
</property>
<property
name=
"suffix"
>
<string>
s
</string>
</property>
<property
name=
"decimals"
>
<number>
0
</number>
</property>
<property
name=
"minimum"
>
<double>
0.000000000000000
</double>
</property>
<property
name=
"maximum"
>
<double>
120.000000000000000
</double>
</property>
<property
name=
"singleStep"
>
<double>
1.000000000000000
</double>
</property>
<property
name=
"value"
>
<double>
0.000000000000000
</double>
</property>
</widget>
</item>
<item>
<widget
class=
"QDoubleSpinBox"
name=
"nsec_ch3"
>
<property
name=
"prefix"
>
<string/>
</property>
<property
name=
"suffix"
>
<string>
ns
</string>
</property>
<property
name=
"decimals"
>
<number>
3
</number>
</property>
<property
name=
"minimum"
>
<double>
500.000000000000000
</double>
</property>
<property
name=
"maximum"
>
<double>
1000000000.000000000000000
</double>
</property>
<property
name=
"singleStep"
>
<double>
0.050000000000000
</double>
</property>
<property
name=
"value"
>
<double>
500.000000000000000
</double>
</property>
</widget>
</item>
<item>
<widget
class=
"QDoubleSpinBox"
name=
"width_ch3"
>
<property
name=
"prefix"
>
<string/>
</property>
<property
name=
"suffix"
>
<string>
ns
</string>
</property>
<property
name=
"decimals"
>
<number>
3
</number>
</property>
<property
name=
"minimum"
>
<double>
200.000000000000000
</double>
</property>
<property
name=
"maximum"
>
<double>
1000000000.000000000000000
</double>
</property>
<property
name=
"singleStep"
>
<double>
0.050000000000000
</double>
</property>
<property
name=
"value"
>
<double>
200.000000000000000
</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout
class=
"QHBoxLayout"
name=
"horizontalLayout_4"
>
<item>
<widget
class=
"QLabel"
name=
"label_6"
>
<property
name=
"font"
>
<font>
<weight>
75
</weight>
<bold>
true
</bold>
</font>
</property>
<property
name=
"text"
>
<string>
OUT4:
</string>
</property>
</widget>
</item>
<item>
<widget
class=
"QCheckBox"
name=
"en_ch4"
>
<property
name=
"text"
>
<string>
Enabled
</string>
</property>
</widget>
</item>
<item>
<widget
class=
"QDoubleSpinBox"
name=
"sec_ch4"
>
<property
name=
"prefix"
>
<string/>
</property>
<property
name=
"suffix"
>
<string>
s
</string>
</property>
<property
name=
"decimals"
>
<number>
0
</number>
</property>
<property
name=
"minimum"
>
<double>
0.000000000000000
</double>
</property>
<property
name=
"maximum"
>
<double>
120.000000000000000
</double>
</property>
<property
name=
"singleStep"
>
<double>
1.000000000000000
</double>
</property>
<property
name=
"value"
>
<double>
0.000000000000000
</double>
</property>
</widget>
</item>
<item>
<widget
class=
"QDoubleSpinBox"
name=
"nsec_ch4"
>
<property
name=
"prefix"
>
<string/>
</property>
<property
name=
"suffix"
>
<string>
ns
</string>
</property>
<property
name=
"decimals"
>
<number>
3
</number>
</property>
<property
name=
"minimum"
>
<double>
500.000000000000000
</double>
</property>
<property
name=
"maximum"
>
<double>
1000000000.000000000000000
</double>
</property>
<property
name=
"singleStep"
>
<double>
0.050000000000000
</double>
</property>
</widget>
</item>
<item>
<widget
class=
"QDoubleSpinBox"
name=
"width_ch4"
>
<property
name=
"prefix"
>
<string/>
</property>
<property
name=
"suffix"
>
<string>
ns
</string>
</property>
<property
name=
"decimals"
>
<number>
3
</number>
</property>
<property
name=
"minimum"
>
<double>
200.000000000000000
</double>
</property>
<property
name=
"maximum"
>
<double>
1000000000.000000000000000
</double>
</property>
<property
name=
"singleStep"
>
<double>
0.050000000000000
</double>
</property>
<property
name=
"value"
>
<double>
200.000000000000000
</double>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget
class=
"QLabel"
name=
"label"
>
<property
name=
"geometry"
>
<rect>
<x>
260
</x>
<y>
10
</y>
<width>
91
</width>
<height>
16
</height>
</rect>
</property>
<property
name=
"font"
>
<font>
<weight>
75
</weight>
<bold>
true
</bold>
</font>
</property>
<property
name=
"text"
>
<string>
Delay setting
</string>
</property>
</widget>
</widget>
<widget
class=
"QGroupBox"
name=
"groupBox_2"
>
<property
name=
"geometry"
>
<rect>
<x>
10
</x>
<y>
180
</y>
<width>
481
</width>
<height>
51
</height>
</rect>
</property>
<property
name=
"title"
>
<string>
Trigger
</string>
</property>
<widget
class=
"QCheckBox"
name=
"en_trigger"
>
<property
name=
"geometry"
>
<rect>
<x>
20
</x>
<y>
20
</y>
<width>
111
</width>
<height>
19
</height>
</rect>
</property>
<property
name=
"text"
>
<string>
Enabled
</string>
</property>
<property
name=
"checked"
>
<bool>
true
</bool>
</property>
</widget>
<widget
class=
"QCheckBox"
name=
"en_term"
>
<property
name=
"geometry"
>
<rect>
<x>
160
</x>
<y>
20
</y>
<width>
191
</width>
<height>
19
</height>
</rect>
</property>
<property
name=
"text"
>
<string>
50 Ohm termination
</string>
</property>
<property
name=
"checked"
>
<bool>
true
</bool>
</property>
</widget>
</widget>
<widget
class=
"QGroupBox"
name=
"groupBox_3"
>
<property
name=
"geometry"
>
<rect>
<x>
10
</x>
<y>
240
</y>
<width>
481
</width>
<height>
51
</height>
</rect>
</property>
<property
name=
"title"
>
<string>
Sync Status
</string>
</property>
<widget
class=
"QWidget"
name=
"layoutWidget"
>
<property
name=
"geometry"
>
<rect>
<x>
10
</x>
<y>
20
</y>
<width>
381
</width>
<height>
31
</height>
</rect>
</property>
<layout
class=
"QGridLayout"
name=
"gridLayout"
>
<item
row=
"0"
column=
"0"
>
<widget
class=
"QCheckBox"
name=
"wr_checkbox"
>
<property
name=
"text"
>
<string>
Use White Rabbit
</string>
</property>
</widget>
</item>
<item
row=
"0"
column=
"1"
>
<widget
class=
"QLabel"
name=
"label_13"
>
<property
name=
"layoutDirection"
>
<enum>
Qt::LeftToRight
</enum>
</property>
<property
name=
"text"
>
<string>
WR Status:
</string>
</property>
<property
name=
"alignment"
>
<set>
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
</set>
</property>
</widget>
</item>
<item
row=
"0"
column=
"2"
>
<widget
class=
"QLabel"
name=
"wr_status"
>
<property
name=
"font"
>
<font>
<weight>
75
</weight>
<bold>
true
</bold>
</font>
</property>
<property
name=
"text"
>
<string>
STATUS
</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</widget>
<widget
class=
"QWidget"
name=
"tab_ts"
>
<attribute
name=
"title"
>
<string>
Timestamper
</string>
</attribute>
<widget
class=
"QCheckBox"
name=
"en_ts"
>
<property
name=
"geometry"
>
<rect>
<x>
10
</x>
<y>
10
</y>
<width>
231
</width>
<height>
19
</height>
</rect>
</property>
<property
name=
"text"
>
<string>
Enable timestamping
</string>
</property>
</widget>
<widget
class=
"QPushButton"
name=
"btn_clear"
>
<property
name=
"geometry"
>
<rect>
<x>
520
</x>
<y>
10
</y>
<width>
80
</width>
<height>
24
</height>
</rect>
</property>
<property
name=
"text"
>
<string>
Clear
</string>
</property>
</widget>
<widget
class=
"QTableWidget"
name=
"ts_table"
>
<property
name=
"geometry"
>
<rect>
<x>
10
</x>
<y>
40
</y>
<width>
611
</width>
<height>
251
</height>
</rect>
</property>
<attribute
name=
"horizontalHeaderDefaultSectionSize"
>
<number>
150
</number>
</attribute>
<attribute
name=
"horizontalHeaderDefaultSectionSize"
>
<number>
150
</number>
</attribute>
<column>
<property
name=
"text"
>
<string>
ID
</string>
</property>
</column>
<column>
<property
name=
"text"
>
<string>
Seconds
</string>
</property>
</column>
<column>
<property
name=
"text"
>
<string>
Nanoseconds
</string>
</property>
</column>
<column>
<property
name=
"text"
>
<string>
Delta
</string>
</property>
</column>
</widget>
</widget>
</widget>
</widget>
<resources/>
<connections/>
</ui>
common/fmc_delay/python/fdelay_lib.py
0 → 100644
View file @
557f9512
#!/usr/bin/python
from
ctypes
import
*
import
sys
import
re
import
os
sys
.
path
.
append
(
'../../../common/'
)
from
ptsexcept
import
*
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
:
GNUM_CSR_ADDR
=
0x0
BASE_ADDR
=
0x84000
FREE_RUNNING
=
0x10
WR_OFFLINE
=
0x8
WR_READY
=
0x1
WR_SYNCING
=
0x2
WR_SYNCED
=
0x4
SYNC_LOCAL
=
0x1
SYNC_WR
=
0x2
def
__init__
(
self
,
fd
):
cwd
=
os
.
path
.
dirname
(
__file__
)
self
.
fdelay
=
CDLL
(
cwd
+
'/../lib/libfinedelay.so'
)
self
.
handle
=
c_voidp
(
self
.
fdelay
.
fdelay_create_rawrabbit
(
c_int
(
fd
),
c_ulong
(
self
.
BASE_ADDR
)));
"""
s = re.split("
\
/", dev_path)
self.fdelay = CDLL('../lib/libfinedelay.so')
if(s[0] == "local"):
print("Initializing local at
%
x"
%
int(s[1], 16))
self.handle = c_voidp(self.fdelay.fdelay_create_rawrabbit(int(s[1],16)));
elif(s[0] == "minibone"):
print("Initializing minibone at
%
s [
%
s]
\n
"
%
( s[1], s[2]))
self.handle = c_voidp(self.fdelay.fdelay_create_minibone(c_char_p(s[1]), c_char_p(s[2]), int(s[3], 16)));
"""
print
"Initialising Fine Delay board..."
print
self
.
handle
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
))
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
):
htab
=
{
self
.
FREE_RUNNING
:
"oscillator free-running"
,
self
.
WR_OFFLINE
:
"WR core offline"
,
self
.
WR_READY
:
"WR core ready"
,
self
.
WR_SYNCING
:
"Syncing local clock with WR"
,
self
.
WR_SYNCED
:
"Synced with WR"
}
# status = c_int(self.fdelay.fdelay_get_sync_status(self.handle));
# print("GetSyncStatus %x" % status.value);
return
"none"
;
#htab[status.value]
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
common/gn4124.py
View file @
557f9512
...
...
@@ -92,6 +92,10 @@ class CGN4124:
def
get_physical_addr
(
self
):
return
self
.
pages
# Enable interrupt handling in the driver
def
irq_en
(
self
):
self
.
bus
.
irqena
()
# Wait for interrupt
def
wait_irq
(
self
):
# Add here reading of the interrupt source (once the irq core will be present)
...
...
pts.py
View file @
557f9512
...
...
@@ -18,6 +18,11 @@ import warnings
import
zipfile
import
string
sys
.
path
.
append
(
'.'
)
sys
.
path
.
append
(
'gnurabbit/python/'
)
sys
.
path
.
append
(
'common/'
)
sys
.
path
.
append
(
'common/fmc_delay/software/python/'
)
from
ConfigParser
import
ConfigParser
,
NoOptionError
from
optparse
import
OptionParser
from
sha
import
sha
as
sha160
...
...
@@ -292,6 +297,7 @@ class Suite(object):
log
.
write
(
' OK
\n
'
)
print
'test '
+
shortname
+
' OK
\n
'
log
.
write
(
'
\n
'
)
log
.
write
(
'------------------------
\n
'
)
log
.
write
(
'Test suite finished.
\n
'
)
...
...
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