diff --git a/software/.gitignore b/software/.gitignore index 63e4546316481eb57905540c56787de8403f7c71..25917e420a1d822080439ab4fc961dc85eee7401 100644 --- a/software/.gitignore +++ b/software/.gitignore @@ -1,2 +1,9 @@ *.o -fd_test \ No newline at end of file +*.txt +*.log +*.pyc +spec_top.bin +spec_top_fd.bin +*.a +*.so +lib/spec diff --git a/software/Makefile b/software/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..f0fd8a8e9050a2f206f70cbbc605031e44be2c8e --- /dev/null +++ b/software/Makefile @@ -0,0 +1,7 @@ +all: + make -C lib + make -C tests + +clean: + make -C lib clean + make -C tests clean \ No newline at end of file diff --git a/software/include/fdelay_lib.h b/software/include/fdelay_lib.h index f4ac36f40dc85672532d6a2ed79f43a64890e6a3..0a249c2e2a5c1a09df0ec00e569eebc110d9d2d8 100644 --- a/software/include/fdelay_lib.h +++ b/software/include/fdelay_lib.h @@ -21,6 +21,10 @@ #define FDELAY_SYNC_LOCAL 0x1 /* use local oscillator */ #define FDELAY_SYNC_WR 0x2 /* use White Rabbit */ +/* fdelay_init() flags */ +#define FDELAY_RAW_READOUT 0x1 +#define FDELAY_PERFORM_LONG_TESTS 0x2 + /* Hardware "handle" structure */ typedef struct fdelay_device { @@ -62,26 +66,22 @@ PUBLIC API */ -/* Creates a local instance of Fine Delay Core at address base_addr. Returns a non-null fdelay_device_t - card context on success or null if an error occured */ -fdelay_device_t *fdelay_create(const char *device); -/* Does the same as above, but for a card accessible via EtherBone/MiniBone. - iface = network interface to which the carrier is connected - mac_addr = MAC address of the EtherBone/MiniBone core - base_addr = base address of the FD core (relative to EB/MB address space) */ -fdelay_device_t *fdelay_create_minibone(char *iface, char *mac_addr, uint32_t base_addr); +/* Creates a local instance of Fine Delay Core at address base_addr on the SPEC at bus/devfn. Returns 0 on success, negative on error. */ +int spec_fdelay_create_bd(fdelay_device_t *dev, int bus, int dev_fn, uint32_t base); + +/* A shortcut for test program, parsing the card base/location from command line args */ +int spec_fdelay_create(fdelay_device_t *dev, int argc, char *argv[]); /* Helper functions - converting FD timestamp format from/to plain picoseconds */ fdelay_time_t fdelay_from_picos(const uint64_t ps); int64_t fdelay_to_picos(const fdelay_time_t t); - /* Enables/disables raw timestamp readout mode (debugging only) */ int fdelay_raw_readout(fdelay_device_t *dev, int raw_moide); /* Initializes and calibrates the device. 0 = success, negative = error */ -int fdelay_init(fdelay_device_t *dev); +int fdelay_init(fdelay_device_t *dev, int init_flags); /* Disables and releases the resources for a given FD Card */ int fdelay_release(fdelay_device_t *dev); @@ -133,6 +133,6 @@ void fdelay_set_user_offset(fdelay_device_t *dev,int input, int64_t offset); int fdelay_get_time(fdelay_device_t *dev, fdelay_time_t *t); int fdelay_set_time(fdelay_device_t *dev, const fdelay_time_t t); -int fdelay_dmtd_calibration(fdelay_device_t *dev); +int fdelay_dmtd_calibration(fdelay_device_t *dev, double *offsets); #endif diff --git a/software/include/fdelay_private.h b/software/include/fdelay_private.h index 1ef31174fcaeb4a96378657c1eb3bae1187c40e8..23fd90d5f62eca6be07eb1e8db76f0f981a8674d 100644 --- a/software/include/fdelay_private.h +++ b/software/include/fdelay_private.h @@ -86,6 +86,7 @@ struct fine_delay_hw int wr_enabled; int wr_state; int raw_mode; + int do_long_tests; struct fine_delay_calibration calib; int64_t input_user_offset, output_user_offset; }; diff --git a/software/lib/Makefile b/software/lib/Makefile index 983795d7879e85d6a2c79656138a974806783930..c5487948560ef182daf40d62b1c9a3d81a3481fd 100644 --- a/software/lib/Makefile +++ b/software/lib/Makefile @@ -1,27 +1,21 @@ -CFLAGS = -I../include -g -Imini_bone -Ispll -#uncomment for extra tests (DAC, output stage INL/DNL) -#CFLAGS += -DPERFORM_LONG_TESTS +OBJS = fdelay_lib.o i2c_master.o onewire.o spec_common.o spec/speclib.o fdelay_dmtd_calibration.o -OBJS_LIB = fdelay_lib.o i2c_master.o onewire.o mini_bone/minibone_lib.o mini_bone/ptpd_netif.o spec_common.o spec/speclib.o fdelay_dmtd_calibration.o +CFLAGS = -I../include -g -Imini_bone -all: testprog lib gs rp-test sweep-test +ifeq ($(SPEC_SW),) +throw_error: + @echo "SPEC software package location environment variable is not set. Can't compile :(" +endif -lib: $(OBJS_LIB) - gcc -shared -o libfinedelay.so $(OBJS_LIB) +all: spec lib -testprog: lib fdelay_test.o - gcc -o fdelay_test $(OBJS_LIB) fdelay_test.o -lm +spec: + ln -s $(SPEC_SW)/tools spec -gs: lib fdelay-gs.o - gcc -o fdelay-gs $(OBJS_LIB) fdelay-gs.o -lm - -rp-test: lib random_pulse_test.o - gcc -o fdelay-random-test $(OBJS_LIB) random_pulse_test.o -lm - - -sweep-test: lib sweep_test.o - gcc -o fdelay-sweep-test $(OBJS_LIB) sweep_test.o -lm +lib: $(OBJS) + gcc -shared -o libfinedelay.so $(OBJS) + ar rc libfinedelay.a $(OBJS) clean: - rm -f *.o fdelay-random-test fdelay-gs fdelay_pps_demo fdelay_test \ No newline at end of file + rm -f *.o libfinedelay.so diff --git a/software/lib/fdelay_bus.c b/software/lib/fdelay_bus.c deleted file mode 100644 index 30dd819ebd3aa93adc57d35299b2d2de229b9ff6..0000000000000000000000000000000000000000 --- a/software/lib/fdelay_bus.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - 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 -#include - -#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; - -} - -int fdelay_load_firmware(const char *path) -{ - fprintf(stderr,"Booting up the FPGA with %s.\n", path); - if(rr_load_bitstream_from_file(path) < 0) - { - fprintf(stderr,"Failed to load FPGA bitstream.\n"); - return -1; - } - return 0; -} \ No newline at end of file diff --git a/software/lib/fdelay_dmtd_calibration.c b/software/lib/fdelay_dmtd_calibration.c new file mode 100644 index 0000000000000000000000000000000000000000..d32622130972bfd80b626c7824a8dfec79a43153 --- /dev/null +++ b/software/lib/fdelay_dmtd_calibration.c @@ -0,0 +1,281 @@ +/* + FmcDelay1ns4Cha (a.k.a. The Fine Delay Card) + DMTD insertion delay calibration stuff + + Short explaination: + + We feed the input of the card with a perioid sequence of pulses, of a frequency, say, + 1 MHz. The card is programmed to introduce a delay of Td. Then, we sample both the input + and the output of the card with a clock that is slightly offset in frequency wrs to the one that + was used to generate the pulses - in our case it's (1 + 1/16384) * 1 MHz. The resulting waveforms + are of very low frequency, but keep the phase shift of the original signals, scaled by a factor of 16384. + This way we can easily measure the actual insertion delay of the FD and apply a correction factor + for fdelay_configure_output(). + + Tomasz Włostowski/BE-CO-HT, 2012 + + (c) Copyright CERN 2012 + Licensed under LGPL 2.1 +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fd_channel_regs.h" +#include "fd_main_regs.h" + +#include "fdelay_lib.h" +#include "fdelay_private.h" + +#include "spec/speclib.h" + + +extern void dbg(const char *fmt, ...); +extern int64_t get_tics(); +extern void udelay(uint32_t usecs); + +/* WR core shell communication functions */ + +/* Waits for a WR Core and returns the output of the previous command in rv */ +static void wait_prompt(fdelay_device_t *dev, char *rv) +{ + char buf[16384],c; + int pos = 0; + + + memset(buf, 0, sizeof(buf)); + + while(pos < sizeof(buf)) + { + if(spec_vuart_rx(dev->priv_io, &c, 1) == 1) + { + buf[pos++] = c; + + if(pos >= 5 && !strcmp(buf + pos - 5, "wrc# ")) + { + int old_pos; + if(!rv) + return; + + while(pos>0) if(buf[pos]=='\n'||buf[pos]=='\r') + break; + else + pos--; + + pos-=2; + old_pos = pos; + + while(pos>0) if(buf[pos]=='\n'||buf[pos]=='\r') + break; + else + pos--; + + strncpy(rv, buf+pos+1, old_pos - pos); + rv[old_pos-pos]=0; + return; + } + } + } + + dbg("Failure: shell buffer overflow.\n"); + exit(1); +} + +/* executes a shell command on the associated WR core */ +static int wrc_shell_exec(fdelay_device_t *dev, const char *cmd, char *retval) +{ + char c; + + while(spec_vuart_rx(dev->priv_io, &c, 1) == 1); + + spec_vuart_tx(dev->priv_io, (char *)cmd, strlen(cmd)); + spec_vuart_tx(dev->priv_io, "\r", 1); + + wait_prompt(dev, retval); + + if(retval) + dbg("wr_core exec '%s', retval: '%s'\n", cmd, retval); + + return 0; +} + +#define DMTD_N_AVGS 10 /* number of average samples */ +#define DELAY_SETPOINT 500000 /* test delay value */ + +#define DMTD_PULSE_PERIOD 144 +#define DMTD_OUTPUT_PERIOD (16384 * DMTD_PULSE_PERIOD / 2) /* period of the DDMTD output signal in 62.5 MHz clock cycles */ + +struct dmtd_channel { + int64_t base; + int64_t prev_tag, phase; + int64_t period; + +}; + +#define TAG_BITS 23 + +static void init_dmtd(struct dmtd_channel *ch, int64_t period) +{ + ch->period = period; + ch->prev_tag = -1; + ch->base = 0; +} + +static int read_dmtd(fdelay_device_t *dev, struct dmtd_channel *ch, int is_out) +{ + fd_decl_private(dev) + + uint32_t addr = (is_out ? FD_REG_DMTR_IN : FD_REG_DMTR_OUT); + uint32_t value = fd_readl(addr); + + if(value & FD_DMTR_IN_RDY) + { + int64_t tag = (int64_t) (value & ((1<base; + + if(ch->prev_tag >= 0 && tag < ch->prev_tag) /* DMTD tag counter has 23 bits. We need to unwrap it */ + { + ch->base += (1LL<phase = tag - epoch; + ch->prev_tag = tag; + + return 1; + } + return 0; +} + +void calibrate_channel(fdelay_device_t *dev, int channel, double *mean, double *std) +{ + int64_t samples_in[DMTD_N_AVGS], samples_out[DMTD_N_AVGS], delta[DMTD_N_AVGS]; + struct dmtd_channel ch_in, ch_out; + + int i, n_in = 0, n_out = 0; + + fd_decl_private(dev) + + fdelay_configure_trigger(dev, 0, 0); + fd_writel(FD_CALR_PSEL_W(0), FD_REG_CALR); + + /* Configure the output to introduce DELAY_SETPOINT delay (but with fixed offset set to 0)*/\ + hw->calib.zero_offset[channel-1] = 0; + + fdelay_configure_output(dev, channel, 1, (int64_t)DELAY_SETPOINT, 200000LL, 0LL, 1); + + /* Disable ALL outputs to prevent the calibration pulses from driving whatever + is connected to the board */ + sgpio_set_pin(dev, SGPIO_OUTPUT_EN(0), 0); + sgpio_set_pin(dev, SGPIO_OUTPUT_EN(1), 0); + sgpio_set_pin(dev, SGPIO_OUTPUT_EN(2), 0); + sgpio_set_pin(dev, SGPIO_OUTPUT_EN(3), 0); + + /* Select internal trigger */ + sgpio_set_pin(dev, SGPIO_TRIG_SEL, 0); + + + for(i=1;i<=4;i++) /* disable all other channels */ + if(channel != i) + fd_writel(0, i * 0x100 + FD_REG_DCR); + + fd_readl(FD_REG_DMTR_IN); + fd_readl(FD_REG_DMTR_OUT); + + fdelay_configure_trigger(dev, 1, 0); + + fd_writel(FD_CALR_PSEL_W(0) | FD_CALR_CAL_DMTD, FD_REG_CALR); + + init_dmtd(&ch_in, DMTD_OUTPUT_PERIOD); + init_dmtd(&ch_out, DMTD_OUTPUT_PERIOD); + + n_in = n_out = 0; + + while(n_in < DMTD_N_AVGS || n_out < DMTD_N_AVGS) /* Get DMTD_N_AVGS samples to reduce error */ + { + if(read_dmtd(dev, &ch_in, 0)) + if(n_in < DMTD_N_AVGS) samples_in[n_in++] = ch_in.phase; + if(read_dmtd(dev, &ch_out, 1)) + if(n_out < DMTD_N_AVGS) samples_out[n_out++] = ch_out.phase; + } + + for(i=0;ipriv_io, "wrc.bin", 0xc0000)) + { + dbg("Failed to load LM32 firmware\n"); + return -1; + } + +// sleep(2); + + /* Configure the WR core to produce a proper calibration clock: */ + + /* Disable PTP and enter free-running master mode */ + wrc_shell_exec(dev, "ptp stop", resp); + wrc_shell_exec(dev, "mode master", resp); + + /* And lock the DMTD oscillator to the FMC clock instead of the SPEC 125 MHz oscillator. Set the FMC VCO DAC to 0 + to have some headroom */ + wrc_shell_exec(dev, "pll sdac 1 0", resp); + wrc_shell_exec(dev, "pll init 2 1 1", resp); + + /* Wait until the PLL locks... */ + while(1) + { + wrc_shell_exec(dev, "pll cl 0", resp); + if(!strcmp(resp, "1")) + break; + sleep(1); + } + + double mean_out[4], std_out[4]; + + usleep(500000); + + dbg("\n\nPerforming DDMTD delay calibration: \n"); + + for(i=1;i<=4;i++) + { + calibrate_channel(dev, i, &mean_out[i-1], &std_out[i-1]); + dbg("Channel %d: delay %.0f ps, std %.0f ps.\n", i, mean_out[i-1], std_out[i-1]); + } + + return 0; +} + diff --git a/software/lib/fdelay_eeprom.c b/software/lib/fdelay_eeprom.c deleted file mode 100644 index 357a8215105070703effe9f7da1528fe1a9d8ebe..0000000000000000000000000000000000000000 --- a/software/lib/fdelay_eeprom.c +++ /dev/null @@ -1,53 +0,0 @@ -#include - -#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"); - -} diff --git a/software/lib/fdelay_lib.c b/software/lib/fdelay_lib.c index 27c7777da294daf725b6254844ff0a44b106a866..c29106a5dba0a1c0bd5b193f3b6e405477fb7b0d 100644 --- a/software/lib/fdelay_lib.c +++ b/software/lib/fdelay_lib.c @@ -763,10 +763,8 @@ 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) + if(hw->do_long_tests && test_delay_transfer_function(dev) < 0) return -1; -#endif fd_writel( FD_GCR_BYPASS, FD_REG_GCR); acam_configure(dev, ACAM_IMODE); @@ -856,7 +854,7 @@ static int read_calibration_eeprom(fdelay_device_t *dev, struct fine_delay_calib */ /* Initialize & self-calibrate the Fine Delay card */ -int fdelay_init(fdelay_device_t *dev) +int fdelay_init(fdelay_device_t *dev, int init_flags) { int i, rv; struct fine_delay_hw *hw; @@ -869,7 +867,8 @@ int fdelay_init(fdelay_device_t *dev) dev->priv_fd = (void *) hw; - hw->raw_mode = 0; + hw->raw_mode = init_flags & FDELAY_RAW_READOUT ? 1 : 0; + hw->do_long_tests = init_flags & FDELAY_PERFORM_LONG_TESTS ? 1 : 0; hw->base_addr = dev->base_addr; hw->base_i2c = 0x100; hw->base_onewire = dev->base_addr + 0x500; @@ -970,10 +969,8 @@ int fdelay_init(fdelay_device_t *dev) fd_writel( FD_GCR_BYPASS, FD_REG_GCR); -#ifdef PERFORM_LONG_TESTS - if(test_pll_dac(dev) < 0) + if(hw->do_long_tests && test_pll_dac(dev) < 0) return -1; -#endif /* Test if ACAM addr/data lines are OK */ if(acam_test_bus(dev) < 0) @@ -1026,10 +1023,10 @@ int fdelay_configure_trigger(fdelay_device_t *dev, int enable, int termination) if(termination) { - dbg("%s: 50-ohm terminated mode\n", __FUNCTION__); +// dbg("%s: 50-ohm terminated mode\n", __FUNCTION__); sgpio_set_pin(dev,SGPIO_TERM_EN,1); } else { - dbg("%s: high impedance mode\n", __FUNCTION__); +// dbg("%s: high impedance mode\n", __FUNCTION__); sgpio_set_pin(dev,SGPIO_TERM_EN,0); }; diff --git a/software/lib/fdelay_pps_demo.c b/software/lib/fdelay_pps_demo.c deleted file mode 100644 index f290a08324d631e35d49fd96338d3b40f4e1c1a0..0000000000000000000000000000000000000000 --- a/software/lib/fdelay_pps_demo.c +++ /dev/null @@ -1,36 +0,0 @@ -#include - -#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(&dev, 5, 0) < 0) - return -1; - - // Get the current time of the FD core - and program the card to start producing the PPS and 10 MHz one second later */ - t_cur.utc = 0; - t_cur.coarse = 0; - - fdelay_configure_sync(&dev, FDELAY_SYNC_LOCAL); - - fdelay_set_time(&dev, t_cur); - printf("Current Time: %ld:%d\n", t_cur.utc, t_cur.coarse); - fdelay_get_time(&dev, &t_cur); - printf("Current Time: %ld:%d\n", t_cur.utc, t_cur.coarse); - - t_start.coarse = 0;//t_cur.coarse; - t_start.utc = t_cur.utc + 3; - t_start.frac = 0; - - fdelay_configure_pulse_gen(&dev, 1, 1, t_start, 48000LL, 100000LL, -1); /* Output 1, period = 100 ns, width = 48 ns - a bit asymmetric 10 MHz */ - fdelay_configure_pulse_gen(&dev, 2, 1, t_start, 1000000000000LL/2LL, 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; -} diff --git a/software/lib/fdelay_temp_calibration.c b/software/lib/fdelay_temp_calibration.c deleted file mode 100644 index b17e1e5c85860103627b249aedc70267344f89aa..0000000000000000000000000000000000000000 --- a/software/lib/fdelay_temp_calibration.c +++ /dev/null @@ -1,60 +0,0 @@ -#include - -#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(dpmax) 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 - - -} diff --git a/software/lib/fdelay_test.c b/software/lib/fdelay_test.c deleted file mode 100644 index 1d609ff7002f6351d95a02d67b15fb98cf5fe9fa..0000000000000000000000000000000000000000 --- a/software/lib/fdelay_test.c +++ /dev/null @@ -1,72 +0,0 @@ -#include - -#include "fdelay_lib.h" -#include "rr_io.h" - -extern int spec_fdelay_init(fdelay_device_t *dev, int pbus, int pdev); - -main(int argc, char *argv[]) -{ - fdelay_device_t dev; - fdelay_time_t t; - - /* Initialize the fine delay generator */ - if(spec_fdelay_init(&dev, 0x05, 0x00) < 0) - { -// fdelay_show_test_results(); - return -1; - } - - - return 0; - /* Enable trigger input and 50 ohm termination */ - - /* Enable all outputs and set them to 500 ns delay, 100 ns pulse width, single output pulse per trigger */ - -/* fdelay_configure_output(&dev,1,1,500000, 100000, 100000, 1); - fdelay_configure_output(&dev,2,1,500000, 100000, 100000, 1); - fdelay_configure_output(&dev,3,1,500000, 100000, 100000, 1); - fdelay_configure_output(&dev,4,1,500000, 100000, 100000, 1);*/ - - t.utc = 0; - t.coarse = 0; - - fdelay_set_time(&dev, t); - - fdelay_configure_sync(&dev, FDELAY_SYNC_WR); - fprintf(stderr, "Syncing with WR Timebase...\n"); - while(!fdelay_check_sync(&dev)) - fprintf(stderr, "."); - fprintf(stderr, " locked!\n"); - - fdelay_configure_trigger(&dev, 1, 0); - fdelay_configure_readout(&dev, 1);//int enable) - - int seq_prev = 0; - int64_t t_prev = 0; - - #if 1 - for(;;) - { - fdelay_time_t ts; - int64_t ts_i; - - if(fdelay_read(&dev, &ts, 1) == 1) - { - ts_i = fdelay_to_picos(ts); - fprintf(stderr,"ts = %-20lld ps, delta = %-20lld, seq = %-6d seq_delta=%-6d\n", - ts_i, ts_i-t_prev, ts.seq_id, ts.seq_id-seq_prev); - seq_prev = ts.seq_id; - t_prev= ts_i; - } - } - #endif - -// fdelay_ - - for(;;) - { - } - - -} diff --git a/software/lib/mini_bone/Makefile b/software/lib/mini_bone/Makefile deleted file mode 100644 index 58eb3c127562c83d5de4d2f4a124288eaf5d86bd..0000000000000000000000000000000000000000 --- a/software/lib/mini_bone/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -OBJS = minibone_lib.o ptpd_netif.o - -all: $(OBJS) - gcc -o m $(OBJS) \ No newline at end of file diff --git a/software/lib/mini_bone/minibone_lib.c b/software/lib/mini_bone/minibone_lib.c deleted file mode 100644 index fae93ff3c68a0425c1cc78cb00d7ba8d1abc8ab8..0000000000000000000000000000000000000000 --- a/software/lib/mini_bone/minibone_lib.c +++ /dev/null @@ -1,207 +0,0 @@ -/* MiniBone library. BUGGY CRAP CODE INTENDED FOR TESTING ONLY! */ - -#include -#include -#include -#include -#include -#include -#include - -#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,"\nBadPacket: "); - for(i=0;itx_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 diff --git a/software/lib/mini_bone/minibone_lib.h b/software/lib/mini_bone/minibone_lib.h deleted file mode 100644 index 0cc4a1445189286869b782a5479abad8261a25a0..0000000000000000000000000000000000000000 --- a/software/lib/mini_bone/minibone_lib.h +++ /dev/null @@ -1,14 +0,0 @@ -/* MiniBone library. BUGGY CRAP CODE INTENDED FOR TESTING ONLY! */ - -#ifndef __MINIBONE_LIB_H -#define __MINIBONE_LIB_H - -#include - -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 diff --git a/software/lib/mini_bone/ptpd_netif.c b/software/lib/mini_bone/ptpd_netif.c deleted file mode 100644 index 7b765dc78334bcb1082717320579797704def4e1..0000000000000000000000000000000000000000 --- a/software/lib/mini_bone/ptpd_netif.c +++ /dev/null @@ -1,241 +0,0 @@ -// Supports only raw ethernet now. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#include - -#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); -} - diff --git a/software/lib/mini_bone/ptpd_netif.h b/software/lib/mini_bone/ptpd_netif.h deleted file mode 100644 index 982c92f77d1da331fabd3171f6679e4bd3a39a35..0000000000000000000000000000000000000000 --- a/software/lib/mini_bone/ptpd_netif.h +++ /dev/null @@ -1,239 +0,0 @@ -// Network API for WR-PTPd - -#ifndef __PTPD_NETIF_H -#define __PTPD_NETIF_H - -#include -//#include - -#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 diff --git a/software/lib/rr_io.c b/software/lib/rr_io.c deleted file mode 100644 index 75be14eb241ce31ca46476ac07e04d65e04dcfd2..0000000000000000000000000000000000000000 --- a/software/lib/rr_io.c +++ /dev/null @@ -1,257 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#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<> 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; -} - diff --git a/software/lib/spec_common.c b/software/lib/spec_common.c index ba3defefe21ee39d186e2d341a98bd333710895d..8ea03a6ca110716bc9e1f7fc65961b8e3643b06c 100644 --- a/software/lib/spec_common.c +++ b/software/lib/spec_common.c @@ -17,7 +17,7 @@ static uint32_t fd_spec_readl(void *priv, uint32_t addr) return spec_readl(priv, addr); } -int spec_fdelay_init_bd(fdelay_device_t *dev, int bus, int dev_fn, uint32_t base) +int spec_fdelay_create_bd(fdelay_device_t *dev, int bus, int dev_fn, uint32_t base) { dev->priv_io = spec_open(bus, dev_fn); @@ -33,13 +33,10 @@ int spec_fdelay_init_bd(fdelay_device_t *dev, int bus, int dev_fn, uint32_t base spec_vuart_init(dev->priv_io, 0xe0500); /* for communication with WRCore during DMTD calibration */ - if(fdelay_init(dev) < 0) - return -1; - return 0; } -int spec_fdelay_init(fdelay_device_t *dev, int argc, char *argv[]) +int spec_fdelay_create(fdelay_device_t *dev, int argc, char *argv[]) { int bus = -1, dev_fn = -1, c; uint32_t base = 0x80000; @@ -66,7 +63,7 @@ int spec_fdelay_init(fdelay_device_t *dev, int argc, char *argv[]) } } - return spec_fdelay_init_bd(dev, bus, dev_fn, base); + return spec_fdelay_create_bd(dev, bus, dev_fn, base); } diff --git a/software/tests/Makefile b/software/tests/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..eef29f36241c5edc07adc107859d8606f4271f5c --- /dev/null +++ b/software/tests/Makefile @@ -0,0 +1,21 @@ +TESTS = dmtd_calibration gs_logger random_pulse_test sweep_test temperature_calibration + +CFLAGS = -I../include +LDFLAGS = -L../lib -static -lfinedelay -lm +CC=gcc + +.PHONY: all + +all: $(TESTS) + +define TEST_template = + $(1): $$($(1).o) +endef + +$(foreach test,$(TESTS),$(eval $(call TEST_template,$(test)))) + +$(TESTS): + gcc $@.c -o $@ $(CFLAGS) $(LDFLAGS) + +clean: + rm -f $(ALL_OBJS) $(TESTS) \ No newline at end of file diff --git a/software/tests/dmtd_calibration.c b/software/tests/dmtd_calibration.c new file mode 100644 index 0000000000000000000000000000000000000000..5f3b23a0fe204a19e1d92bf7daee0f228691f480 --- /dev/null +++ b/software/tests/dmtd_calibration.c @@ -0,0 +1,25 @@ +#include + +#include "fdelay_lib.h" + +main(int argc, char *argv[]) +{ + fdelay_device_t dev; + + /* Initialize the fine delay generator */ + if(spec_fdelay_create(&dev, argc, argv) < 0) + { + printf("Probe failed.\n"); + return -1; + } + + if(fdelay_init(&dev, 0) < 0) + { + printf("Init failed.\n"); + return -1; + } + + fdelay_dmtd_calibration(&dev, NULL); + + return 0; +} diff --git a/software/lib/fdelay-gs.c b/software/tests/gs_logger.c similarity index 86% rename from software/lib/fdelay-gs.c rename to software/tests/gs_logger.c index 00a70b97d364b2e3d633fb128981ef5ae90299a8..a0b7dd53375d20769311a7243c4d9b84254b3cd4 100644 --- a/software/lib/fdelay-gs.c +++ b/software/tests/gs_logger.c @@ -1,4 +1,5 @@ -/* Simple demo that reads samples using the read call */ +/* Fine Delay Logger/Pulse Generator program as used in Gran Sasso. + Treat as an example */ #define _GNU_SOURCE @@ -46,6 +47,7 @@ struct board_def { int hw_index; int in_use; int fd; + int prev_seq; struct { int64_t offset_pps, width, period; @@ -265,7 +267,7 @@ void enable_wr(fdelay_device_t *b, int index) printf("Locking to WR network [board=%d]...", index); fflush(stdout); fdelay_configure_sync(b, FDELAY_SYNC_LOCAL); - sleep(2); +/* sleep(2); fdelay_configure_sync(b, FDELAY_SYNC_WR); while(fdelay_check_sync(b) <= 0) @@ -281,7 +283,7 @@ void enable_wr(fdelay_device_t *b, int index) } printf("\n"); - fflush(stdout); + fflush(stdout);*/ } /* Add two timestamps */ @@ -311,11 +313,17 @@ int configure_board(struct board_def *bdef) - if(spec_fdelay_init(b, bdef->hw_index >>8, bdef->hw_index & 0xff) < 0) + if(spec_fdelay_create_bd(b, bdef->hw_index >>8, bdef->hw_index & 0xff, 0x80000) < 0) { fprintf(stderr,"Can't open fdelay board @ hw_index %x\n", bdef->hw_index); exit(-1); } + + if(fdelay_init(b, 0) < 0) + { + fprintf(stderr,"Can't initialize fdelay board @ hw_index %x\n", bdef->hw_index); + exit(-1); + } bdef->b = b; @@ -390,20 +398,52 @@ int configure_board(struct board_def *bdef) return 0; } +/* 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 --; + } + a.utc -= b.utc; + return a; +} + + void handle_readout(struct board_def *bdef) { int64_t t_ps; fdelay_time_t t; + static fdelay_time_t t_prev; static time_t start; + int done; while(fdelay_read(bdef->b, &t, 1) == 1) { t_ps = (t.coarse * 8000LL) + ((t.frac * 8000LL) >> 12); - printf("card 0x%04x, seq %5i: time %lli s, %lli.%03lli ns [%x] ", bdef->hw_index, t.seq_id, t.utc, t_ps / 1000LL, t_ps % 1000LL, t.coarse); - printf("raw utc=%lld coarse=%d startoffs=%d suboffs=%d frac=%d [%x]\n", t.raw.utc, t.raw.coarse, t.raw.start_offset, t.raw.subcycle_offset, t.raw.frac- 30000, t.raw.frac); + printf("card 0x%04x, seq %5i: time %lli s, %lli.%03lli ns [count %d] ", bdef->hw_index, t.seq_id, t.utc, t_ps / 1000LL, t_ps % 1000LL, (t.raw.tsbcr >> 10) & 0x3ff); + // printf("raw utc=%lld coarse=%d startoffs=%d suboffs=%d frac=%d [%x]\n", t.raw.utc, t.raw.coarse, t.raw.start_offset, t.raw.subcycle_offset, t.raw.frac- 30000, t.raw.frac); log_write(&t, bdef->hw_index); + + if(((bdef->prev_seq + 1) & 0xffff) != (t.seq_id & 0xffff)) + { + printf("MISMATCH\n"); + } else printf("\n"); + +// printf("raw %d %d\n", t.raw.start_offset, t.raw.frac-30000); +// printf("delta %lld\n", fdelay_to_picos(ts_sub(t,t_prev))); + bdef->prev_seq = t.seq_id; + t_prev = t; } } @@ -453,6 +493,7 @@ int main(int argc, char *argv[]) fdelay_configure_readout(boards[i].b, 1); fdelay_configure_trigger(boards[i].b, 1, boards[i].term_on); + boards[i].prev_seq = -1; } @@ -469,7 +510,7 @@ int main(int argc, char *argv[]) if(fdelay_dbg_sync_lost(boards[i].b)) { - printf("Weird, sync lost @ board %x. Reconfiguring...\n", boards[i].b); + printf("Weird, sync lost @ board %p. Reconfiguring...\n", boards[i].b); configure_board(&boards[i]); } @@ -482,4 +523,3 @@ int main(int argc, char *argv[]) } - diff --git a/software/lib/pp.conf b/software/tests/gs_logger.conf old mode 100755 new mode 100644 similarity index 77% rename from software/lib/pp.conf rename to software/tests/gs_logger.conf index 31bf6da4875c90a5ccdb4083db1fc7473ffb352f..9b65e1a4ad0834b7f36057e2a39bc355c068813d --- a/software/lib/pp.conf +++ b/software/tests/gs_logger.conf @@ -19,30 +19,30 @@ termination 0 # WARNING 2: define these for ALL boards independently -input_offset -69100p -output_offset 20400p +input_offset -63100p +output_offset 14400p # Output configuration # out output_ID offset_from_pps[ps] width[ps] period[ps] # out 1 = PPS signal, 1us pulse width -out 1 0 500u 1000u +out 1 0 100m 1s out 2 0 500u 1000u out 4 0 500u 1000u -out 3 0 250u 499999990p +out 4 0 10u 99999990p # ####################### # # Select board 1 # ####################### # -board 1 -hw_index 0x0500 +#\board 1 +#hw_index 0x0500 -input_offset -69100p -output_offset 20400p -termination 0 +#input_offset -63100p +#output_offset 14400p +#termination 1 -out 1 0 500u 1000u -out 2 0 500u 1000u -out 4 0 500u 1000u -out 3 0 250u 499999990p +#out 1 0 500u 1000u +#out 2 0 500u 1000u +#out 4 0 500u 1000u +#out 3 0 100u 200u diff --git a/software/lib/random_pulse_test.c b/software/tests/random_pulse_test.c similarity index 96% rename from software/lib/random_pulse_test.c rename to software/tests/random_pulse_test.c index 9a03bb6111240f4aa3d684a60aa4f2d661b3358b..8b2f28755b85f449fbee3f40541963dd7a6a4d6f 100644 --- a/software/lib/random_pulse_test.c +++ b/software/tests/random_pulse_test.c @@ -173,10 +173,16 @@ void enable_wr(fdelay_device_t *b, int index) } -int configure_board(fdelay_device_t *b) +int configure_board(fdelay_device_t *b, int argc, char *argv[]) { - if(spec_fdelay_init(b,1,0) < 0) + if(spec_fdelay_create(b, 1, NULL) < 0) + { + printf("Probe failed\n"); + exit(-1); + } + + if(fdelay_init(b, 0) < 0) { printf("Init failed\n"); exit(-1); @@ -274,7 +280,7 @@ int main(int argc, char *argv[]) { fdelay_device_t b; - configure_board(&b); + configure_board(&b, argc, argv); pqueue_clear(&incoming); pqueue_clear(&outgoing); diff --git a/software/lib/sweep_test.c b/software/tests/sweep_test.c similarity index 93% rename from software/lib/sweep_test.c rename to software/tests/sweep_test.c index deb3aee090905158da618f96f782e90d1fa128e5..2d9b65717d35f80346a9c60d4f017b2ed627bd4b 100644 --- a/software/lib/sweep_test.c +++ b/software/tests/sweep_test.c @@ -19,7 +19,13 @@ int configure_board(fdelay_device_t *b, int argc, char *argv[]) { fdelay_time_t t; - if(spec_fdelay_init(b,argc,argv) < 0) + if(spec_fdelay_create(b, argc, argv) < 0) + { + printf("Probe failed\n"); + exit(-1); + } + + if(fdelay_init(b, 0) < 0) { printf("Init failed\n"); exit(-1); @@ -82,6 +88,5 @@ int main(int argc, char *argv[]) fdelay_device_t b; configure_board(&b, argc, argv); - handle_readout(&b, 40000); } diff --git a/software/lib/fdelay_cal.c b/software/tests/temperature_calibration.c similarity index 72% rename from software/lib/fdelay_cal.c rename to software/tests/temperature_calibration.c index afae401f6df367f1241a30df4408de2b097badc8..0ce7f77c9ec4f05f5d6f61c10791b661eb1c45c0 100644 --- a/software/lib/fdelay_cal.c +++ b/software/tests/temperature_calibration.c @@ -1,12 +1,16 @@ +/* Temperature calibration test program. + + Requires a PWM-driven peltier cooler placed over the delay line chips, PWM drive connected to MOSI pin */ + #include #include +#include #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; @@ -25,7 +29,7 @@ void pi_update(fdelay_device_t *dev, float temp) 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); + fd_writel((int)pi_state.pwm, FD_REG_TDER2); } extern int64_t get_tics(); @@ -56,41 +60,34 @@ int pi_set_temp(fdelay_device_t *dev, float new_temp) 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() +main(int argc, char *argv[]) { - fdelay_device_t *dev = malloc(sizeof(fdelay_device_t)); - - rr_init(RR_DEVSEL_UNUSED, RR_DEVSEL_UNUSED); + fdelay_device_t dev; - dev->writel = my_writel; - dev->readl = my_readl; - dev->base_addr = 0x80000; - - if(fdelay_init(dev) < 0) + if(spec_fdelay_create(&dev, argc, argv) < 0) + { + fprintf(stderr,"Card probe failed.\n"); return -1; - + } + + if(fdelay_init(&dev, 0) < 0) + { + fprintf(stderr,"Card init failed.\n"); + 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)) + if(pi_set_temp(&dev, t_cur)) { - fd_decl_private(dev); + fdelay_device_t *b = &dev; + fd_decl_private(b); - calibrate_outputs(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; diff --git a/software/tests/wrc.bin b/software/tests/wrc.bin new file mode 100755 index 0000000000000000000000000000000000000000..cd170b866e510323366afeac60c9a0e23fe60619 Binary files /dev/null and b/software/tests/wrc.bin differ