SuperKEKB XRM system  Not logged in ELOG logo
Entry  Tue Jan 22 07:56:56 2019, M. Andrew, documentation, instructions for setup, compiling and data acquisition XRM.instructions.txt
    Reply  Fri Oct 4 08:55:23 2019, M. Andrew, documentation, instructions for pdu control 
    Reply  Fri Oct 4 10:04:12 2019, M. Andrew, documentation, instructions for programming boardstack 
    Reply  Fri Oct 4 10:18:44 2019, M. Andrew, documentation, instructions for checking boardstack status and temperature 
    Reply  Fri Oct 4 10:33:53 2019, M. Andrew, documentation, instructions for boardstack configuration 
    Reply  Tue Oct 29 09:27:14 2019, M. Andrew, documentation, instructions on taking a full revolution of waveforms 2019-10-30.062954.s17a.SCROD004.xrm.log2019-10-30.063506.waveforms.425events.png
       Reply  Wed Oct 30 15:23:57 2019, M. Andrew, documentation, sample waveform files 8x
          Reply  Mon Nov 18 13:30:44 2019, M. Andrew, documentation, first light! 
          Reply  Wed Nov 6 13:35:45 2024, M. Andrew, documentation, sample waveform files 2024-04-17.135507.zip2024-04-17.135507.waveforms.32windows.pngxrm.py
    Reply  Tue Nov 5 11:47:36 2019, M. Andrew, documentation, instructions on taking data around a desired RF bucket 2019-11-05.121045.waveforms.0099.png
Message ID: 26     Entry time: Wed Oct 30 15:23:57 2019     In reply to: 25     Reply to this: 28   30
Author: M. Andrew 
Type: documentation 
Subject: sample waveform files 
A sample waveform file from the reference boardstack at UH and the boardstack in the HER at KEK are attached (in tar bzip2 file).

The format of the files is as in the attached spreadsheet (start from cell C29 for the waveform data).

A parser for the data (raw datafiles as well as waveform files) is committed to the UH svn repo (in scripts_dev/) and also attached here.  See the functions events_from_waveformfile() and waveforms_from_waveformfile() for details.
Attachment 1: data_format_v2_6.with-raw-waveform-details.ods  42 kB
Attachment 2: 2019-11-04.140943.waveforms.422events.png  350 kB  Uploaded Mon Nov 4 14:15:24 2019  | Show | Hide all
Attachment 3: 2019-11-04.140943.datafile.bz2  1.437 MB  Uploaded Mon Nov 4 14:15:47 2019
Attachment 4: 2019-11-04.140943.waveforms.bz2  969 kB  Uploaded Mon Nov 4 14:16:15 2019
Attachment 5: 2019-11-05.064104.waveforms.424events.png  535 kB  Uploaded Mon Nov 4 14:17:08 2019  | Show | Hide all
Attachment 6: 2019-11-05.064104.datafile.bz2  1.656 MB  Uploaded Mon Nov 4 14:17:21 2019
Attachment 7: 2019-11-05.064104.waveforms.bz2  1.129 MB  Uploaded Mon Nov 4 14:17:32 2019
Attachment 8: xrm.py  58 kB  Uploaded Mon Nov 4 14:19:21 2019  | Hide | Hide all
#!/bin/env python

# written 2019-01-28 by mza
# last updated 2019-11-04 by mza

import threading # Thread()
from B2L_common import *
from B2L_defs import *
from get_status import get_status
import ethudp
from DebugInfoWarningError24 import debug, info, warning, error, debug2, debug3, set_verbosity
import time # sleep()

BS = 0
set_verbosity(3)
frame_mask_shift = 16
frame_mask_all = 0b111111111 << frame_mask_shift
bunch_marker_first_valid = 4
initial_bunch_marker_of_interest = 1701
bunch_marker_last_valid = 5120 - 1
#number_of_64_sample_windows_per_beam_orbit = 427

def set_trigger_mask(s, c0, c1, c2, c3):
	write_register(SCROD_AxiCommon_trigMask, s, BS)
	write_register(CARRIER_AxiCommon_trigMask, c0, BS, 0)
	write_register(CARRIER_AxiCommon_trigMask, c1, BS, 1)
	write_register(CARRIER_AxiCommon_trigMask, c2, BS, 2)
	write_register(CARRIER_AxiCommon_trigMask, c3, BS, 3)

def mask_triggers(s=0xf, c0=0xf, c1=0xf, c2=0xf, c3=0xf):
	set_trigger_mask(s, c0, c1, c2, c3)

def unmask_triggers(s=0, c0=0, c1=0, c2=0, c3=0):
	set_trigger_mask(s, c0, c1, c2, c3)

def set_trig_prescale_N_log2(N_log2):
	write_register(SCROD_AxiCommon_trig_prescale_N_log2, N_log2, BS)

def get_xrm_trigger_enable_status():
	return read_register(SCROD_AxiCommon_xrm_trigger_enabled, BS)

def enable_xrm_triggers():
	write_register(SCROD_AxiCommon_xrm_trigger_enabled, 1, BS)

def disable_xrm_triggers():
	write_register(SCROD_AxiCommon_xrm_trigger_enabled, 0, BS)

def allow_xrm_triggers_for_a_while(duration=1.0):
	if be_verbose_when_collecting_data:
		info("allowing xrm triggers for " + str(int(1000.0*duration)/1000.0) + " seconds...")
	a = get_SCROD_eventCnt()
	enable_xrm_triggers()
	time.sleep(duration)
	disable_xrm_triggers()
	b = get_SCROD_eventCnt()
	diff = b - a
	return diff

def trigger_and_wait_for_xrm_triggers(duration=1.0):
#	if be_verbose_when_collecting_data:
#		info("allowing xrm triggers for " + str(int(1000.0*duration)/1000.0) + " seconds...")
	a = get_SCROD_eventCnt()
	if should_software_trigger:
		software_trigger(BS)
	else:
		write_register_without_readback_verification(SCROD_AxiCommon_clear_count_of_triggers_for_bunch_markers, 0xf, BS)
	wait_at_least_until_next_frame9()
	time.sleep(duration)
	b = get_SCROD_eventCnt()
	diff = b - a
	return diff

expected_trigger_rate = { 0:11150.0, 1:5560.0, 2:2780.0, 3:1390.0, 4:690.0, 5:350.0, 6:170.0, 7:90.0, 8:40.0, 9:20.0, 10:10.0, 11:5.0, 12:2.0, 13:1.0, 14:1.0, 15:1.0, 16:1.0, 17:1.0, 18:1.0 }
def generate_histogram_of_trigger_rate_versus_prescale_N_log2(start, end):
	global expected_trigger_rate
	old_desired_trigger_quantities = set_desired_trigger_quantities(0, 0, 0, 0)
	mask_triggers()
	#max_rate = 151000.0
	for i in range(start, end+1):
		set_trig_prescale_N_log2(i)
		#duration = 40.0 * (2.0**i) / max_rate
		duration = 0.1
		#info(duration)
		if i > 10:
			duration = 1.0
		diff = allow_xrm_triggers_for_a_while(duration)
		#info(str(diff))
		rate = diff / duration
		expected_trigger_rate[i] = rate
		info("[" + str(i) + "]: " + str(rate))
	set_desired_trigger_quantities(old_desired_trigger_quantities[0], old_desired_trigger_quantities[1], old_desired_trigger_quantities[2], old_desired_trigger_quantities[3])

def get_SCROD_eventCnt(should_show_it=0):
	SCROD_eventCnt = read_register(SCROD_AxiCommon_eventCnt, BS)
	if should_show_it:
		info("SCROD_eventCnt: " + str(SCROD_eventCnt))
	return SCROD_eventCnt

def get_carrier_eventCnts(should_show_them=0):
	if 5==number_of_carriers[BS] or 0==number_of_carriers[BS]:
		return
	eventCnt = []
	if 1 <= number_of_carriers[BS]:
		carrier0_eventCnt = read_register(CARRIER_AxiCommon_eventCnt, BS, 0)
		eventCnt.append(carrier0_eventCnt)
		if should_show_them:
			info("carrier0_eventCnt: " + str(carrier0_eventCnt))
	if 2 <= number_of_carriers[BS]:
		carrier1_eventCnt = read_register(CARRIER_AxiCommon_eventCnt, BS, 1)
		eventCnt.append(carrier1_eventCnt)
		if should_show_them:
			info("carrier1_eventCnt: " + str(carrier1_eventCnt))
	if 3 <= number_of_carriers[BS]:
		carrier2_eventCnt = read_register(CARRIER_AxiCommon_eventCnt, BS, 2)
		eventCnt.append(carrier2_eventCnt)
		if should_show_them:
			info("carrier2_eventCnt: " + str(carrier2_eventCnt))
	if 4 <= number_of_carriers[BS]:
		carrier3_eventCnt = read_register(CARRIER_AxiCommon_eventCnt, BS, 3)
		eventCnt.append(carrier3_eventCnt)
		if should_show_them:
			info("carrier3_eventCnt: " + str(carrier3_eventCnt))
	return eventCnt

def set_readout_window_to_match_bunch(bunch):
	write_register_for_each_asic(CARRIER_IRSX_readoutLookback, int(bunch/RF_buckets_per_read_window), BS)

def set_bunch_marker(bunch_marker_number, frame_mask, value):
	set_readout_window_to_match_bunch(value)
	value &= ~frame_mask_all
	value |= frame_mask << frame_mask_shift
	#info(hex(value))
	if 0==bunch_marker_number:
		write_register(SCROD_AxiCommon_bunch_marker_a, value, BS)
	if 1==bunch_marker_number:
		write_register(SCROD_AxiCommon_bunch_marker_b, value, BS)
	if 2==bunch_marker_number:
		write_register(SCROD_AxiCommon_bunch_marker_c, value, BS)
	if 3==bunch_marker_number:
		write_register(SCROD_AxiCommon_bunch_marker_d, value, BS)

#def set_bunch_markers(a, b, c, d):
#	a |= frame_mask_all
#	b |= frame_mask_all
#	c |= frame_mask_all
#	d |= frame_mask_all
#	#a &= ~frame_mask_all
#	#b &= ~frame_mask_all
#	#c &= ~frame_mask_all
#	#d &= ~frame_mask_all
#	#a |= (1<<0)<<frame_mask_shift
#	#b |= (1<<5)<<frame_mask_shift
#	#c |= (1<<6)<<frame_mask_shift
#	#d |= (1<<7)<<frame_mask_shift
#	write_register(SCROD_AxiCommon_bunch_marker_a, a, BS)
#	write_register(SCROD_AxiCommon_bunch_marker_b, b, BS)
#	write_register(SCROD_AxiCommon_bunch_marker_c, c, BS)
#	write_register(SCROD_AxiCommon_bunch_marker_d, d, BS)
#
#def set_quadbunch_markers(a, b, c, d):
#	set_bunch_markers(4*a, 4*b, 4*c, 4*d)
#
#def set_asic_write_window_bunch_markers(a, b, c, d):
#	#calculate_parameters(4)
#	#calculate_parameters(6)
#	#calculate_parameters(8)
#	#set_bunch_markers(16*a, 16*b, 16*c, 16*d)
#	set_bunch_markers(24*a, 24*b, 24*c, 24*d)
#	#set_bunch_markers(32*a, 32*b, 32*c, 32*d)

def set_desired_trigger_quantities(a, b, c, d):
	old_a = read_register(SCROD_AxiCommon_desired_trigger_quantity_for_bunch_marker_a, BS)
	old_b = read_register(SCROD_AxiCommon_desired_trigger_quantity_for_bunch_marker_b, BS)
	old_c = read_register(SCROD_AxiCommon_desired_trigger_quantity_for_bunch_marker_c, BS)
	old_d = read_register(SCROD_AxiCommon_desired_trigger_quantity_for_bunch_marker_d, BS)
	write_register(SCROD_AxiCommon_desired_trigger_quantity_for_bunch_marker_a, a, BS)
	write_register(SCROD_AxiCommon_desired_trigger_quantity_for_bunch_marker_b, b, BS)
	write_register(SCROD_AxiCommon_desired_trigger_quantity_for_bunch_marker_c, c, BS)
	write_register(SCROD_AxiCommon_desired_trigger_quantity_for_bunch_marker_d, d, BS)
	return old_a, old_b, old_c, old_d

def calculate_parameters(SST_clock_divide_ratio=6, should_print_info=0):
	# 5120 / 4 = 1280 FTSW clocks per frame
	# 5120 buckets / 508.8875 MHz = 10.0611628307 us per frame
	#
	# 127.221875 MHz / 6 = 21.203645833 MHz
	# 128 samples per write window * 21.203645833 MHz SST = 2714.066666 MHz sampling rate
	# 1/21.203645833 MHz = 47.1617007689 ns per write window
	# 10.0611628307 us / 47.1617007689 ns = 213.333333 write windows per revolution
	# 5120 / 213.333333 = 24.0 bunches per window
	# 6.0 FTSW bunches per window
	#
	# 127.221875 MHz / 8 = 15.902734375 MHz
	# 128 samples per write window * 15.902734375 MHz SST = 2035.55 MHz sampling rate
	# 1/15.902734375 MHz = 62.882268 ns per write window
	# 10.0611628307 us / 62.882268 ns = 160 write windows per revolution
	# 5120 / 160 = 32.0 bunches per window
	# 8.0 FTSW bunches per window
	global RF_clock_Hz
	RF_clock_Hz = 508.8875e6
	global period_of_RF_clock_ns
	period_of_RF_clock_ns = 1.0e9 / RF_clock_Hz
	global RF_buckets
	RF_buckets = 5120
	global asic_samples_per_write_window
	asic_samples_per_write_window = 128
	global FTSW_clock_divide_ratio
	FTSW_clock_divide_ratio = 4
	global revolution_duration_s
	revolution_duration_s = RF_buckets / RF_clock_Hz
	global SST_clock_Hz
	SST_clock_Hz = RF_clock_Hz / FTSW_clock_divide_ratio / SST_clock_divide_ratio
	global sampling_rate_Hz
	sampling_rate_Hz = SST_clock_Hz * asic_samples_per_write_window
	global write_window_duration_s
	write_window_duration_s = 1.0 / SST_clock_Hz
	global read_window_duration_s
	read_window_duration_s = write_window_duration_s / 2.0
	global write_windows_per_revolution
	write_windows_per_revolution = revolution_duration_s / write_window_duration_s
	global read_windows_per_revolution
	read_windows_per_revolution = revolution_duration_s / read_window_duration_s
	global RF_buckets_per_write_window
	RF_buckets_per_write_window = RF_buckets / write_windows_per_revolution
	global RF_buckets_per_read_window
	RF_buckets_per_read_window = RF_buckets / read_windows_per_revolution
	global FTSW_clocks_per_write_window
	FTSW_clocks_per_write_window = RF_buckets_per_write_window / FTSW_clock_divide_ratio
	global FTSW_clocks_per_read_window
	FTSW_clocks_per_read_window = RF_buckets_per_read_window / FTSW_clock_divide_ratio
	if should_print_info:
		info("revolution_duration_us: " + str(revolution_duration_s*1.0e6))
		info("SST_clock_MHz: " + str(SST_clock_Hz/1.0e6))
		info("sampling_rate_GHz: " + str(sampling_rate_Hz/1.0e9))
		info("write_window_duration_ns : " + str(write_window_duration_s*1.0e9))
		info("read_window_duration_ns : " + str(read_window_duration_s*1.0e9))
		info("write_windows_per_revolution: " + str(write_windows_per_revolution))
		info("read_windows_per_revolution: " + str(read_windows_per_revolution))
		info("RF_buckets_per_write_window: " + str(RF_buckets_per_write_window))
		info("RF_buckets_per_read_window: " + str(RF_buckets_per_read_window))
		info("FTSW_clocks_per_write_window: " + str(FTSW_clocks_per_write_window))
		info("FTSW_clocks_per_read_window: " + str(FTSW_clocks_per_read_window))

def decode_frame_mask(frame_mask):
	frame_mask &= frame_mask_all
	frame_mask >>= frame_mask_shift
	list = []
	if frame_mask & 0x100:
		list.append(0)
	if frame_mask & 0x080:
		list.append(1)
	if frame_mask & 0x040:
		list.append(2)
	if frame_mask & 0x020:
		list.append(3)
	if frame_mask & 0x010:
		list.append(4)
	if frame_mask & 0x008:
		list.append(5)
	if frame_mask & 0x004:
		list.append(6)
	if frame_mask & 0x002:
		list.append(7)
	if frame_mask & 0x001:
		list.append(8)
	return list

def show_frame_masks():
	a = read_register(SCROD_AxiCommon_bunch_marker_a, BS)
	af = decode_frame_mask(a)
	a &= ~frame_mask_all
	info("a: " + str(af) + " " + str(a))
	b = read_register(SCROD_AxiCommon_bunch_marker_b, BS)
	bf = decode_frame_mask(b)
	b &= ~frame_mask_all
	info("b: " + str(bf) + " " + str(b))
	c = read_register(SCROD_AxiCommon_bunch_marker_c, BS)
	cf = decode_frame_mask(c)
	c &= ~frame_mask_all
	info("c: " + str(cf) + " " + str(c))
	d = read_register(SCROD_AxiCommon_bunch_marker_d, BS)
	df = decode_frame_mask(d)
	d &= ~frame_mask_all
	info("d: " + str(df) + " " + str(d))
	info("total frame masks active: " + str(count_frame_masks()))

def count_frame_masks():
	a = read_register(SCROD_AxiCommon_bunch_marker_a, BS)
	ac = len(decode_frame_mask(a))
	b = read_register(SCROD_AxiCommon_bunch_marker_b, BS)
	bc = len(decode_frame_mask(b))
	c = read_register(SCROD_AxiCommon_bunch_marker_c, BS)
	cc = len(decode_frame_mask(c))
	d = read_register(SCROD_AxiCommon_bunch_marker_d, BS)
	dc = len(decode_frame_mask(d))
	total = ac + bc + cc + dc
	return total

def show_xrm_trigger_enable_status():
	en = read_register(SCROD_AxiCommon_xrm_trigger_enabled, BS)
... 1246 more lines ...
ELOG V3.1.5-3a5f2f0