<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://daq00.triumf.ca/DaqWiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Bsmith</id>
	<title>DaqWiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://daq00.triumf.ca/DaqWiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Bsmith"/>
	<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php/Special:Contributions/Bsmith"/>
	<updated>2026-05-31T16:07:01Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.6</generator>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=Ubuntu&amp;diff=8788</id>
		<title>Ubuntu</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=Ubuntu&amp;diff=8788"/>
		<updated>2026-03-23T23:38:24Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: /* 32-bit intel cross-compiler */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Prerequisites =&lt;br /&gt;
&lt;br /&gt;
* before setting up new machine run memory test&lt;br /&gt;
* prepare flash drive with free version of memtest86: https://www.memtest86.com&lt;br /&gt;
* test boot from flash drive, test takes ~ few hours&lt;br /&gt;
* test will end with summary page, if passed continue with Ubuntu&lt;br /&gt;
* number that might be worth noting is memory latency&lt;br /&gt;
&lt;br /&gt;
= Ubuntu version =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lsb_release -a&lt;br /&gt;
uname -a&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Ubuntu installer =&lt;br /&gt;
&lt;br /&gt;
* updated for Ububtu LTS 20.04.01, 22.04.1, 24.04 (only minor differences)&lt;br /&gt;
&lt;br /&gt;
* download the latest Ubuntu LTS desktop installer iso image&lt;br /&gt;
* dd the image to a USB key&lt;br /&gt;
* power down, disconnect all disks (all HDDs, all SSDs, all M.2)&lt;br /&gt;
* connect the SSD to be used as system disk&lt;br /&gt;
* if system will use mirrored SSDs (using ZFS mirror), leave second SSD disconnected, we will activate it later&lt;br /&gt;
* power up&lt;br /&gt;
* boot from USB key in legacy mode or UEFI mode (select this in the BIOS boot menu - F2 or F8 for ASUS, F11 for Supermicro)&lt;br /&gt;
* follow the instruction:&lt;br /&gt;
* &amp;quot;try ubuntu or install ubuntu&amp;quot; - choose &amp;quot;install&amp;quot;&lt;br /&gt;
* select language - accept default&lt;br /&gt;
* &amp;quot;updates and other software&amp;quot; - accept default settings (&amp;quot;normal install&amp;quot;)&lt;br /&gt;
* &amp;quot;installation type&amp;quot; - select &amp;quot;advanced features&amp;quot; and &amp;quot;experimental: use ZFS&amp;quot;&lt;br /&gt;
* accept partition choice&lt;br /&gt;
* &amp;quot;where are you?&amp;quot; - select &amp;quot;Vancouver&amp;quot; (PST time zone)&lt;br /&gt;
* &amp;quot;who are you?&amp;quot; - leave all fields blank, except &amp;quot;username&amp;quot; set to &amp;quot;wheel&amp;quot;, &amp;quot;password&amp;quot; set to the root password. hostname will be set later after configuring the network&lt;br /&gt;
* don&#039;t install third party sw&lt;br /&gt;
* installation runs in a few minutes, when finished, reboot&lt;br /&gt;
* login as user wheel&lt;br /&gt;
* answer annouying questions:&lt;br /&gt;
* &amp;quot;livepatch&amp;quot; - say &amp;quot;next&amp;quot;&lt;br /&gt;
* &amp;quot;help improve&amp;quot; - select &amp;quot;do not send&amp;quot;, say &amp;quot;next&amp;quot;&lt;br /&gt;
* &amp;quot;privacy&amp;quot; - leave &amp;quot;location&amp;quot; as &amp;quot;off&amp;quot;, say &amp;quot;next&amp;quot;&lt;br /&gt;
* &amp;quot;ready to go&amp;quot;, say &amp;quot;done&amp;quot;&lt;br /&gt;
* right-click on the desktop, say &amp;quot;open in terminal&amp;quot;, a shell will open&lt;br /&gt;
* say &amp;quot;sudo /bin/bash&amp;quot;, enter the root password, you now have the root shell&lt;br /&gt;
* run nm-connection-editor to configure the network. use netmask 255.255.224.0, gateway 142.90.100.18, DNS 142.90.100.19, search path &amp;quot;triumf.ca&amp;quot;&lt;br /&gt;
* after network is up (can ping ladd00), continue with post-installation steps below&lt;br /&gt;
&lt;br /&gt;
= Install instructions =&lt;br /&gt;
&lt;br /&gt;
== prepare ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt update&lt;br /&gt;
apt upgrade&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install ssh ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install ssh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install git/scripts ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y install git&lt;br /&gt;
mkdir ~root/git&lt;br /&gt;
cd ~root/git&lt;br /&gt;
git clone https://daq00.triumf.ca/~olchansk/git/scripts.git&lt;br /&gt;
cd scripts&lt;br /&gt;
git pull&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* if needed, update git/scripts repository from ladd00 to daq00:&lt;br /&gt;
* git remote -v ### if it says daq00, we are good&lt;br /&gt;
* git remote set-url origin https://daq00.triumf.ca/~olchansk/git/scripts.git&lt;br /&gt;
* git pull ### check that it works&lt;br /&gt;
&lt;br /&gt;
== configure hostname ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vi /etc/hostname&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== disable swap ==&lt;br /&gt;
&lt;br /&gt;
ubuntu installer creates a 2 GB swap partition, not useful&lt;br /&gt;
on 32-64 GB machine, disable it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vi /etc/fstab ### comment out the &amp;quot;swap&amp;quot; line&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* on 64 GB RAM machines swap is not useful&lt;br /&gt;
* on machines booted from network (NFS-ROOT), swap does not work&lt;br /&gt;
* on machines running from flash (RPi, etc), flash is too slow for useful swap&lt;br /&gt;
* swap configured by linux installers invariably has wrong size and is not useful&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl disable dphys-swapfile&lt;br /&gt;
systemctl stop dphys-swapfile&lt;br /&gt;
dphys-swapfile uninstall&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== maybe reboot ==&lt;br /&gt;
&lt;br /&gt;
this is a good point to reboot the machine to boot&lt;br /&gt;
the latest kernel and to set the correct hostname&lt;br /&gt;
&lt;br /&gt;
== install etckeeper ==&lt;br /&gt;
&lt;br /&gt;
keep contents of /etc in a git repository:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y install etckeeper&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== set timezone ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
timedatectl list-timezones | grep -i vancouver&lt;br /&gt;
timedatectl set-timezone America/Vancouver&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install time synchronization ==&lt;br /&gt;
&lt;br /&gt;
check if chrony is installed correctly and is synched to TRIUMF time servers:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chronyc sources&lt;br /&gt;
chronyc tracking&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
if not, remove old chrony and&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y remove chrony&lt;br /&gt;
apt -y purge chrony&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and install it from scratch:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y install chrony&lt;br /&gt;
cd ~/git/scripts&lt;br /&gt;
git pull&lt;br /&gt;
cd ~&lt;br /&gt;
cp ~/git/scripts/etc/triumf.sources /etc/chrony/sources.d/&lt;br /&gt;
systemctl disable systemd-timesyncd.service&lt;br /&gt;
systemctl stop systemd-timesyncd.service&lt;br /&gt;
systemctl disable ntp&lt;br /&gt;
systemctl stop ntp&lt;br /&gt;
systemctl enable chrony&lt;br /&gt;
systemctl restart chrony&lt;br /&gt;
chronyc sources&lt;br /&gt;
chronyc tracking&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== reenable systemd-timesyncd ==&lt;br /&gt;
&lt;br /&gt;
ONLY IF CHRONY DOES NOT WORK&lt;br /&gt;
&lt;br /&gt;
To configure systemd-timesyncd, set &amp;quot;NTP=&amp;quot; in /etc/systemd/timesyncd.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt remove chrony&lt;br /&gt;
cat /etc/systemd/timesyncd.conf&lt;br /&gt;
systemctl enable systemd-timesyncd.service&lt;br /&gt;
systemctl restart systemd-timesyncd.service&lt;br /&gt;
systemctl status systemd-timesyncd.service&lt;br /&gt;
timedatectl status&lt;br /&gt;
timedatectl timesync-status&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== enable outgoing email (debian 11) ==&lt;br /&gt;
&lt;br /&gt;
this is different from ubuntu 20. it uses /etc/mailname and it hardwires the hostname into main.cf.&lt;br /&gt;
&lt;br /&gt;
== enable outgoing email ==&lt;br /&gt;
&lt;br /&gt;
we have an unusual email configuration. outgoing email should work to deliver error messages, notices, etc. incoming email is disabled, we do not receive email for local users.&lt;br /&gt;
&lt;br /&gt;
this causes problems with TRIUMF smtp server. if our message cannot be delivered (wrong email address or receipient computer is turned off), TRIUMF smtp server will generate a delivery failure notification email and try to send it to the &amp;quot;from&amp;quot; address of the failed message. but the &amp;quot;from&amp;quot; address does not receive any email, so another delivery failure  notification email is generated and an attempt to deliver it. which again fails, rinse and repeat.&lt;br /&gt;
&lt;br /&gt;
as solution, kray created a special rule, email from scrap.triumf.ca does not generate delivery failure notices. failed messages sit in the queue for 5 days, then they are deleted. (K.O. - confirmed with kray 3jan2024).&lt;br /&gt;
&lt;br /&gt;
to make this work we use the msmtp MTA package.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~&lt;br /&gt;
apt -y install mailutils msmtp msmtp-mta # say &amp;quot;no&amp;quot; to apparmor support&lt;br /&gt;
apt -y remove postfix&lt;br /&gt;
apt -y purge postfix # remove old config files&lt;br /&gt;
apt -y install bsd-mailx&lt;br /&gt;
cd ~/git/scripts/etc&lt;br /&gt;
git pull&lt;br /&gt;
/bin/cp -fv aliases /etc/aliases&lt;br /&gt;
/bin/cp -fv msmtprc /etc/msmtprc&lt;br /&gt;
/bin/rm -vf ~root/.forward&lt;br /&gt;
/bin/rm -vf /etc/mailname&lt;br /&gt;
Mail root&lt;br /&gt;
Subject: test&lt;br /&gt;
test&lt;br /&gt;
^D&lt;br /&gt;
CC: &amp;lt;CR&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== enable outgoing email (postfix) ==&lt;br /&gt;
&lt;br /&gt;
THIS IS OBSOLETE!!!&lt;br /&gt;
&lt;br /&gt;
* TRIUMF: use smtp.triumf.ca&lt;br /&gt;
* CERN: use cernmx.cern.ch&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install postfix ### select &amp;quot;satellite system&amp;quot;, enter full hostname &amp;quot;xxx.triumf.ca&amp;quot;, enter &amp;quot;smtp.triumf.ca&amp;quot;&lt;br /&gt;
apt install mailutils&lt;br /&gt;
dpkg-reconfigure postfix ### (if postfix already installed)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo olchansk@triumf.ca lindner@triumf.ca bsmith@triumf.ca dfujimoto@triumf.ca &amp;gt;&amp;gt; ~root/.forward&lt;br /&gt;
mailx root&lt;br /&gt;
test&lt;br /&gt;
^D&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== enable ping for all users (debian 11) ==&lt;br /&gt;
&lt;br /&gt;
Without this tweak, Debian will report &amp;quot;operation not permitted&amp;quot; if a user tries to ping somewhere.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &#039;net.ipv4.ping_group_range = 0 1000&#039; &amp;gt; /etc/sysctl.d/99-ping.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== disable apparmor ==&lt;br /&gt;
&lt;br /&gt;
On NFS-Root network booted machines!&lt;br /&gt;
&lt;br /&gt;
If &amp;quot;man man&amp;quot; returns &amp;quot;permission denied&amp;quot; and syslog reports apparmor &amp;quot;sendmsg DENIED&amp;quot; errors, disable apparmor. This is supposedly fixed in kernel 6.0 and later (to be confirmed), see https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/1784499&lt;br /&gt;
&lt;br /&gt;
Disable apparmor, see https://ubuntu.com/server/docs/security-apparmor&lt;br /&gt;
&lt;br /&gt;
This takes effect after a reboot.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl stop apparmor.service&lt;br /&gt;
systemctl disable apparmor.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If on boot apparmor appears to still be confining apps (for example, mysql), edit the file /etc/default/grub and change&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
GRUB_CMDLINE_LINUX=&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
to &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
GRUB_CMDLINE_LINUX=&amp;quot;apparmor=0&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Run sudo update-grub and reboot.&lt;br /&gt;
&lt;br /&gt;
== install missing packages ==&lt;br /&gt;
&lt;br /&gt;
(apt eats terminal input, even the &amp;quot;yes |&amp;quot; trick does not quite work,&lt;br /&gt;
repeat the following commands until they report that everything&lt;br /&gt;
is installed)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
yes | apt -y install ssh tcsh ethtool ncat rsync strace net-tools traceroute time minicom screen git lsof debsums tmux iptables telnet pax rpm mtools at gdisk tcpdump&lt;br /&gt;
yes | apt -y install sysstat smartmontools lm-sensors&lt;br /&gt;
yes | apt -y install lsb-release&lt;br /&gt;
apt -y install vim # in addition to default vim-tiny, requested by IRIS&lt;br /&gt;
apt -y install gedit # requested by TACTIC&lt;br /&gt;
apt -y install tcl&lt;br /&gt;
apt -y install mc # requested by sol&lt;br /&gt;
apt -y install pax rpm alien ### package converter tools&lt;br /&gt;
apt -y install flex bison&lt;br /&gt;
apt -y install neofetch&lt;br /&gt;
apt -y install snmp snmp-mibs-downloader&lt;br /&gt;
apt -y install git subversion g++ gfortran cmake doxygen&lt;br /&gt;
apt -y install curl libcurl4 libcurl4-openssl-dev&lt;br /&gt;
### conflits with mysql packages ### apt -y install mariadb-client libmariadb-dev ### mysql client for MIDAS&lt;br /&gt;
apt -y install mysql-client libmysqlclient-dev&lt;br /&gt;
apt -y install postgresql-common libpq-dev ### postgresql client for MIDAS&lt;br /&gt;
yes | apt -y install libz-dev libzstd-dev sqlite3 libsqlite3-dev unixodbc-dev&lt;br /&gt;
yes | apt -y install libssl-dev&lt;br /&gt;
yes | apt -y install emacs xemacs21 joe&lt;br /&gt;
yes | apt -y install gnuplot dos2unix&lt;br /&gt;
yes | apt -y install mutt bsd-mailx # email clients&lt;br /&gt;
yes | apt -y install liblz4-tool pbzip2 libbz2-dev&lt;br /&gt;
yes | apt -y install libc6-dev-i386 # otherwise no /usr/include/sys/types.h&lt;br /&gt;
yes | apt -y install libreadline-dev&lt;br /&gt;
yes | apt -y install ubuntu-mate-themes&lt;br /&gt;
yes | apt -y install libmotif-dev libxmu-dev&lt;br /&gt;
yes | apt -y install libusb-dev libusb-1.0-0-dev&lt;br /&gt;
yes | apt -y install i2c-tools libi2c-dev libi2c0&lt;br /&gt;
yes | apt -y install xfig gsfonts-x11 gsfonts-other # install fonts for xfig&lt;br /&gt;
yes | apt -y install libjson-perl&lt;br /&gt;
yes | apt -y install libgsl-dev # additional GNU Scientific Library&lt;br /&gt;
yes | apt -y install qt5-default # Qt development&lt;br /&gt;
yes | apt -y install python3-full python3-dev python3-dbg python3-pip ### for pyROOT&lt;br /&gt;
yes | apt -y install imagemagick imagemagick-common ckeditor # for elog&lt;br /&gt;
yes | apt -y install libjpeg-dev libjpeg-progs libjpeg-tools&lt;br /&gt;
yes | apt -y install linux-tools-common linux-tools-generic # cpupower frequency-info&lt;br /&gt;
yes | apt -y install rdesktop remmina remmina-plugin&amp;quot;*&amp;quot; # requested by POL&lt;br /&gt;
yes | apt -y install nlohmann-json3-dev # required to build MIDAS with ROOT 6.30 on Ubuntu-22&lt;br /&gt;
apt -y install dpkg-dev cmake g++ gcc binutils libx11-dev libxpm-dev libxft-dev libxext-dev python3 libssl-dev libafterimage0 # from https://root.cern/install/dependencies/&lt;br /&gt;
apt -y install gfortran libpcre3-dev xlibmesa-glu-dev libglew-dev libftgl-dev libmysqlclient-dev libfftw3-dev libcfitsio-dev graphviz-dev libldap2-dev python3-dev python3-numpy libxml2-dev libkrb5-dev libgsl0-dev qtwebengine5-dev nlohmann-json3-dev libtbb-dev libavahi-compat-libdnssd-dev # from https://root.cern/install/dependencies/&lt;br /&gt;
apt -y install libvdt-dev # for ROOT 6.32 on Ubuntu-24&lt;br /&gt;
apt -y install autoconf automake gperf # gnu package build tools&lt;br /&gt;
apt -y install u-boot-tools # for Xilinx petalinux&lt;br /&gt;
#apt -y install linux-headers-generic # to build linux kernel drivers&lt;br /&gt;
apt -y install htop&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ubuntu LTS 20.04:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
yes | apt -y install linux-image-generic-hwe-20.04 linux-tools-virtual-hwe-20.04 # enable linux 5.11 series kernel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ubuntu LTS 22.04:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y install linux-generic-hwe-22.04 # enable linux 6.8.0 series kernel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ubuntu LTS 24.04:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y install linux-generic-hwe-24.04 # enable linux 6.14.0 series kernel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== remove snap ==&lt;br /&gt;
&lt;br /&gt;
remove snap at this point.&lt;br /&gt;
&lt;br /&gt;
Do &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
snap list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
to see a list of installed snaps. Use &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
snap remove &amp;lt;item&amp;gt; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
to remove each. You will need to remove snapd last. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl stop snapd&lt;br /&gt;
systemctl disable snapd&lt;br /&gt;
apt purge snapd&lt;br /&gt;
rm -rf ~/snap&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install non-snap firefox ==&lt;br /&gt;
&lt;br /&gt;
delay this until the very end, download of firefox-esr deb package is very slow.&lt;br /&gt;
&lt;br /&gt;
See https://askubuntu.com/questions/1399383/how-to-install-firefox-as-a-traditional-deb-package-without-snap-in-ubuntu-22&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
add-apt-repository ppa:mozillateam/ppa&lt;br /&gt;
apt install firefox-esr&lt;br /&gt;
echo run firefox-esr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enable automatic updates:&lt;br /&gt;
&lt;br /&gt;
* rerun [[#Enable_automatic_updates]]&lt;br /&gt;
&lt;br /&gt;
== configure DNS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/git/scripts&lt;br /&gt;
git pull&lt;br /&gt;
mkdir /etc/systemd/resolved.conf.d&lt;br /&gt;
cp etc/resolved-triumf.conf /etc/systemd/resolved.conf.d/&lt;br /&gt;
systemctl restart systemd-resolved&lt;br /&gt;
resolvectl&lt;br /&gt;
#systemd-analyze cat-config systemd/resolved.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install ganglia ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y install ganglia-monitor&lt;br /&gt;
cd ~root/git/scripts/ganglia&lt;br /&gt;
git pull&lt;br /&gt;
make install&lt;br /&gt;
./ganglia-all.perl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
fix gmond start before network is ready:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /etc/systemd/system/ganglia-monitor.service.d&lt;br /&gt;
echo -e &amp;quot;[Unit]\nAfter=network-online.target\n&amp;quot; &amp;gt; /etc/systemd/system/ganglia-monitor.service.d/local.conf&lt;br /&gt;
systemctl daemon-reload&lt;br /&gt;
systemctl cat ganglia-monitor.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install ganglia server ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;On the main computer only! (daq00, dsdaqgw, etc)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* zfs create rpool/ganglia&lt;br /&gt;
* apt install gmetad php php-xml rrdtool&lt;br /&gt;
* mv /etc/ganglia/gmetad.conf /etc/ganglia/gmetad.conf-stock&lt;br /&gt;
* create /etc/ganglia/gmetad.conf with the following contents:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
data_source &amp;quot;my cluster&amp;quot; 15 localhost&lt;br /&gt;
RRAs &amp;quot;RRA:AVERAGE:0.5:1:244&amp;quot; &amp;quot;RRA:AVERAGE:0.5:24:244&amp;quot; &amp;quot;RRA:AVERAGE:0.5:168:244&amp;quot; &amp;quot;RRA:AVERAGE:0.5:672:244&amp;quot; &amp;quot;RRA:AVERAGE:0.5:5760:374&amp;quot;&lt;br /&gt;
setuid_username &amp;quot;ganglia&amp;quot;&lt;br /&gt;
rrd_rootdir &amp;quot;/ganglia/rrds&amp;quot;&lt;br /&gt;
case_sensitive_hostnames 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* mkdir /ganglia/rrds&lt;br /&gt;
* chown ganglia:ganglia /ganglia/rrds&lt;br /&gt;
* systemctl restart gmetad&lt;br /&gt;
* create /etc/ganglia/gmond-collect.conf&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
globals {&lt;br /&gt;
  daemonize = yes&lt;br /&gt;
  setuid = yes&lt;br /&gt;
  user = nobody&lt;br /&gt;
  debug_level = 0&lt;br /&gt;
  max_udp_msg_len = 1472&lt;br /&gt;
  mute = no&lt;br /&gt;
  #deaf = yes&lt;br /&gt;
  deaf = no&lt;br /&gt;
  allow_extra_data = yes&lt;br /&gt;
  host_dmax = 0 /* 86400 */ /*secs. Expires (removes from web interface) hosts in 1 day */&lt;br /&gt;
  host_tmax = 20 /*secs */&lt;br /&gt;
  cleanup_threshold = 300 /*secs */&lt;br /&gt;
  gexec = no&lt;br /&gt;
  send_metadata_interval = 600 /*secs */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The cluster attributes specified will be used as part of the &amp;lt;CLUSTER&amp;gt;&lt;br /&gt;
 * tag that will wrap all hosts collected by this instance.&lt;br /&gt;
 */&lt;br /&gt;
cluster {&lt;br /&gt;
  name = &amp;quot;DAQ&amp;quot;&lt;br /&gt;
  owner = &amp;quot;TRIUMF DAQ&amp;quot;&lt;br /&gt;
  latlong = &amp;quot;unspecified&amp;quot;&lt;br /&gt;
  url = &amp;quot;https://daq.triumf.ca&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* The host section describes attributes of the host, like the location */&lt;br /&gt;
host {&lt;br /&gt;
  location = &amp;quot;unspecified&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
udp_send_channel {&lt;br /&gt;
  host = daq00.triumf.ca&lt;br /&gt;
  bind_hostname = yes&lt;br /&gt;
  port = 8649&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
udp_recv_channel {&lt;br /&gt;
  #mcast_join = 239.2.11.71&lt;br /&gt;
  port = 8649&lt;br /&gt;
  #bind = 239.2.11.71&lt;br /&gt;
  retry_bind = true&lt;br /&gt;
  # Size of the UDP buffer. If you are handling lots of metrics you really&lt;br /&gt;
  # should bump it up to e.g. 10MB or even higher.&lt;br /&gt;
  #buffer = 10485760&lt;br /&gt;
  buffer = 200000&lt;br /&gt;
  family = ipv4&lt;br /&gt;
&lt;br /&gt;
  acl {&lt;br /&gt;
    default = &amp;quot;deny&amp;quot;&lt;br /&gt;
    access {&lt;br /&gt;
      # vlan1 daq00&lt;br /&gt;
      ip = 142.90.111.168&lt;br /&gt;
      mask = 19&lt;br /&gt;
      action = &amp;quot;allow&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
    access {&lt;br /&gt;
      # MUSR VLAN&lt;br /&gt;
      ip = 142.90.154.73&lt;br /&gt;
      mask = 8&lt;br /&gt;
      action = &amp;quot;allow&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
    access {&lt;br /&gt;
      # KVM network&lt;br /&gt;
      ip = 192.168.1.1&lt;br /&gt;
      mask = 8&lt;br /&gt;
      action = &amp;quot;allow&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
udp_recv_channel {&lt;br /&gt;
  #mcast_join = 239.2.11.71                                                                                                                                                                                                &lt;br /&gt;
  port = 8649&lt;br /&gt;
  #bind = 239.2.11.71                                                                                                                                                                                                      &lt;br /&gt;
  retry_bind = true&lt;br /&gt;
  # Size of the UDP buffer. If you are handling lots of metrics you really                                                                                                                                                 &lt;br /&gt;
  # should bump it up to e.g. 10MB or even higher.                                                                                                                                                                         &lt;br /&gt;
  #buffer = 10485760                                                                                                                                                                                                       &lt;br /&gt;
  buffer = 200000&lt;br /&gt;
  family = ipv6&lt;br /&gt;
&lt;br /&gt;
  acl {&lt;br /&gt;
    default = &amp;quot;deny&amp;quot;&lt;br /&gt;
    access {&lt;br /&gt;
      # ALPHA network                                                                                                                                                                                                      &lt;br /&gt;
      ip = 2001:1458:202:fd::100:aa&lt;br /&gt;
      mask = 8&lt;br /&gt;
      action = &amp;quot;allow&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
    #access {                                                                                                                                                                                                              &lt;br /&gt;
    #  # ALPHA-g network                                                                                                                                                                                                   &lt;br /&gt;
    #  ip = 192.168.1.1                                                                                                                                                                                                    &lt;br /&gt;
    #  mask = 8                                                                                                                                                                                                            &lt;br /&gt;
    #  action = &amp;quot;allow&amp;quot;                                                                                                                                                                                                    &lt;br /&gt;
    #}                                                                                                                                                                                                                     &lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
tcp_accept_channel {&lt;br /&gt;
  port = 8649&lt;br /&gt;
  bind = localhost&lt;br /&gt;
  # If you want to gzip XML output&lt;br /&gt;
  gzip_output = no&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* add to /etc/rc.local&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/usr/sbin/gmond -c /etc/ganglia/gmond-collect.conf &amp;amp;&lt;br /&gt;
systemctl restart gmetad &amp;amp;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* cd /ganglia&lt;br /&gt;
* git clone https://daq00.triumf.ca/~olchansk/git/ganglia-web.git&lt;br /&gt;
* cd ganglia-web&lt;br /&gt;
* git checkout KO1&lt;br /&gt;
* ln -s /ganglia/ganglia-web /var/www/html/ganglia&lt;br /&gt;
* make dwoo directories&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /var/lib/ganglia-web&lt;br /&gt;
chown www-data:www-data /var/lib/ganglia-web&lt;br /&gt;
mkdir /var/lib/ganglia-web/dwoo&lt;br /&gt;
chown www-data:www-data /var/lib/ganglia-web/dwoo&lt;br /&gt;
mkdir /var/lib/ganglia-web/dwoo/compiled&lt;br /&gt;
chown www-data:www-data /var/lib/ganglia-web/dwoo/compiled&lt;br /&gt;
mkdir /var/lib/ganglia-web/dwoo/cache&lt;br /&gt;
chown www-data:www-data /var/lib/ganglia-web/dwoo/cache&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* open https://alphacpc05.cern.ch/ganglia/&lt;br /&gt;
&lt;br /&gt;
== install gonodeinfo ==&lt;br /&gt;
&lt;br /&gt;
* go to https://bitbucket.org/dd1/gonodeinfo follow instructions:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y install golang&lt;br /&gt;
mkdir ~/git&lt;br /&gt;
cd ~/git&lt;br /&gt;
#git clone https://bitbucket.org/dd1/gonodeinfo.git&lt;br /&gt;
git clone https://daq00.triumf.ca/~olchansk/git/gonodeinfo.git&lt;br /&gt;
cd gonodeinfo&lt;br /&gt;
git remote set-url origin https://daq00.triumf.ca/~olchansk/git/gonodeinfo.git&lt;br /&gt;
git pull&lt;br /&gt;
make&lt;br /&gt;
make install # install gonodeinfo agent&lt;br /&gt;
cd ~ # this is important&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* edit /etc/gonodeinfo.conf&lt;br /&gt;
* change &amp;quot;Description&amp;quot;, &amp;quot;Location&amp;quot;, &amp;quot;User&amp;quot; and &amp;quot;Administrator&amp;quot; as appropriate (or delete them)&lt;br /&gt;
* change &amp;quot;Servers&amp;quot; to read: Servers: daq00.triumf.ca:8601&lt;br /&gt;
* run &amp;quot;gonodeinfo -v&amp;quot;&lt;br /&gt;
* if error is &amp;quot;connection refused&amp;quot;. go to the nodeinfo server to add this client to the access control list:&lt;br /&gt;
* on the gonodeinfo server: run /opt/gonodeinfo/gonodereceive.exe -a daq13&lt;br /&gt;
* try gonodeinfo again, there should be no error&lt;br /&gt;
* on the gonodeinfo server: run gonodereport, look at the web pages, the new machine should be listed now&lt;br /&gt;
&lt;br /&gt;
== install emailonreboot ==&lt;br /&gt;
&lt;br /&gt;
send an email if computer is rebooted&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ssh root&lt;br /&gt;
mkdir -p ~/git&lt;br /&gt;
cd ~/git&lt;br /&gt;
git clone https://daq00.triumf.ca/~olchansk/git/rpms.git&lt;br /&gt;
cd rpms/emailonreboot&lt;br /&gt;
git pull&lt;br /&gt;
make&lt;br /&gt;
make install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install monitor_nfs ==&lt;br /&gt;
&lt;br /&gt;
monitor NFS mounts and complain about dead, stale and hung mounts&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ssh root&lt;br /&gt;
mkdir -p ~/git&lt;br /&gt;
cd ~/git&lt;br /&gt;
git clone https://daq00.triumf.ca/~olchansk/git/rpms.git&lt;br /&gt;
cd rpms/monitor_nfs&lt;br /&gt;
git pull&lt;br /&gt;
make&lt;br /&gt;
make install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install fonts for EPICS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y install xfonts-100dpi xfonts-75dpi&lt;br /&gt;
killall Xorg # restart Xorg (i.e. &amp;quot;killall Xorg&amp;quot;, this will log you out from the console)&lt;br /&gt;
xlsfonts | grep -i helvetica ### should show fonts with different sizes, not just size 0 (scalable)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install libz.so.1 for CentOS compatibility ==&lt;br /&gt;
&lt;br /&gt;
KO - confirm which versions on quartus need this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
yes | apt-get -y install zlib1g&lt;br /&gt;
yes | apt-get -y install zlib1g:i386 libc6:i386 libgcc1:i386 gcc-6-base:i386&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install ld-ldb-x86-64.so.3 for Quartus compatibility ==&lt;br /&gt;
&lt;br /&gt;
Not clear from package this is supposed to come from. Copied from U-20.&lt;br /&gt;
&lt;br /&gt;
Without this, Quartus lmgrd does not run.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /lib64&lt;br /&gt;
ln -s  ld-linux-x86-64.so.2 ld-lsb-x86-64.so.2&lt;br /&gt;
ln -s  ld-linux-x86-64.so.2 ld-lsb-x86-64.so.3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
should look like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq13:/lib64# ls -l&lt;br /&gt;
total 3&lt;br /&gt;
lrwxrwxrwx 1 root root 44 Jan 28 09:07 ld-linux-x86-64.so.2 -&amp;gt; ../lib/x86_64-linux-gnu/ld-linux-x86-64.so.2&lt;br /&gt;
lrwxrwxrwx 1 root root 20 Feb 18 16:45 ld-lsb-x86-64.so.2 -&amp;gt; ld-linux-x86-64.so.2&lt;br /&gt;
lrwxrwxrwx 1 root root 20 Feb 18 16:45 ld-lsb-x86-64.so.3 -&amp;gt; ld-linux-x86-64.so.2&lt;br /&gt;
root@daq13:/lib64# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install libpng12.so.0 for Quartus 13.0sp1 and 13.1.4.182 ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget https://daq00.triumf.ca/~olchansk/linux/libpng12.so.0&lt;br /&gt;
wget https://daq00.triumf.ca/~olchansk/linux/libpng12.so.0.50.0&lt;br /&gt;
/bin/cp -pv libpng12.so.0 libpng12.so.0.50.0 /lib/x86_64-linux-gnu/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install packages for Xilinx ==&lt;br /&gt;
&lt;br /&gt;
ubuntu LTS 22.04 vivado 2020.1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install autoconf libtool&lt;br /&gt;
apt install libtinfo5&lt;br /&gt;
apt install texinfo&lt;br /&gt;
apt install zlib1g:i386&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install packages for building ROOT ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y install libx11-dev libxpm-dev libxft-dev libxext-dev libpng-dev libjpeg-dev xlibmesa-glu-dev libxml2-dev libgsl-dev cmake&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install wine ==&lt;br /&gt;
&lt;br /&gt;
As far as I know, only needed for BNMR/BNQR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install wine winetricks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install lightdm ==&lt;br /&gt;
&lt;br /&gt;
unlike the default gdm login manager, lightdm shows the machine hostname and does not require an extra mouse click to swicth from screen saver to login mode.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y install lightdm&lt;br /&gt;
# select lightdm&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install desktop environments ==&lt;br /&gt;
&lt;br /&gt;
note: default display manager and default desktop are deficient, please do not skip this step.&lt;br /&gt;
&lt;br /&gt;
note: if apt asks to choose the display manager, select &amp;quot;lightdm&amp;quot;&lt;br /&gt;
&lt;br /&gt;
note: KO - I recommend the &amp;quot;MATE&amp;quot; desktop.&lt;br /&gt;
&lt;br /&gt;
note: you will have to cut-and-paste this several times because &amp;quot;apt&amp;quot; eats commands, even with &amp;quot;-y&amp;quot; and even piped from &amp;quot;yes&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
note: DF - on U24 this may re-install snap&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# install MATE desktop&lt;br /&gt;
apt -y install ubuntu-mate-core ubuntu-mate-desktop ubuntu-mate-themes&lt;br /&gt;
# install Cinnamon desktop&lt;br /&gt;
apt -y install cinnamon&lt;br /&gt;
# install KDE desktop&lt;br /&gt;
apt -y install kde-standard kubuntu-settings-desktop&lt;br /&gt;
# install Lxqt desktop&lt;br /&gt;
# apt -y install lxqt # conflict over kubuntu-desktop, kubuntu-settings-desktop and desktop-base&lt;br /&gt;
# install Xfce4 desktop&lt;br /&gt;
apt -y install xfce4&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install ROOT ==&lt;br /&gt;
&lt;br /&gt;
Please install ROOT per instructions at https://root.cern.ch.&lt;br /&gt;
&lt;br /&gt;
NOTE1: The ROOT package available from Ubuntu repositories is severely out of date and cannot be used with MIDAS and ROOTANA. ### DO NOT DO THIS! apt-get install root-system&lt;br /&gt;
&lt;br /&gt;
NOTE2: as of 2017-Jan-09, ROOT binary kits for Ubuntu do not work (use GCC 5 instead of GCC6), build from source instead.&lt;br /&gt;
&lt;br /&gt;
== Install x2go ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt-get update&lt;br /&gt;
apt-get install x2goserver x2goserver-xsession&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== enable root login from ladd00/daq00 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ssh localhost&lt;br /&gt;
CTRL-C&lt;br /&gt;
/bin/cp ~root/git/scripts/etc/authorized_keys ~root/.ssh/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== disable ssh access from outside of TRIUMF ==&lt;br /&gt;
&lt;br /&gt;
to stop ssh login spam, disable ssh access from outside of TRIUMF. this can be done by requesting a firewall block through the helpdesk or by local firewall rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo iptables -I INPUT ! -s 142.90.0.0/255.255.0.0 -p tcp --dport 22 -j REJECT &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
/etc/rc.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install smart-status ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ln -s ~/git/scripts/smart-status/smart-status.perl ~root/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== enable boot menu and boot messages ==&lt;br /&gt;
&lt;br /&gt;
This will enable the grub menu (with a 10 sec timeout) and&lt;br /&gt;
replace black screen with exciting linux boot messages.&lt;br /&gt;
&lt;br /&gt;
* emacs -nw /etc/default/grub&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
GRUB_DEFAULT=0&lt;br /&gt;
GRUB_TIMEOUT_STYLE=menu&lt;br /&gt;
GRUB_TIMEOUT=10&lt;br /&gt;
GRUB_RECORDFAIL_TIMEOUT=10&lt;br /&gt;
GRUB_DISTRIBUTOR=`lsb_release -i -s 2&amp;gt; /dev/null || echo Debian`&lt;br /&gt;
#GRUB_CMDLINE_LINUX_DEFAULT=&amp;quot;vga=769 video=640x480&amp;quot;&lt;br /&gt;
GRUB_CMDLINE_LINUX_DEFAULT=&amp;quot;&amp;quot;&lt;br /&gt;
GRUB_CMDLINE_LINUX=&amp;quot;&amp;quot;&lt;br /&gt;
#GRUB_GFXMODE=640x480&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* update grub config:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
grub-mkconfig -o /boot/grub/grub.cfg&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Disable welcome message on ssh == &lt;br /&gt;
&lt;br /&gt;
On ssh, there is a lengthy welcome message. To disable: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vim /etc/ssh/sshd_config&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensure that the file reads &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PrintMod no&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vim /etc/pam.d/sshd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
comment out the lines: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
session    optional     pam_motd.so  motd=/run/motd.dynamic&lt;br /&gt;
session    optional     pam_motd.so noupdate&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Enable automatic updates =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install unattended-upgrades&lt;br /&gt;
cd ~/git/scripts&lt;br /&gt;
git pull&lt;br /&gt;
/bin/cp -v etc/99apt-conf-ko /etc/apt/apt.conf.d/&lt;br /&gt;
apt-config dump | grep Unattended&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Following is obsolete:&lt;br /&gt;
&lt;br /&gt;
* emacs -nw /etc/apt/apt.conf.d/50unattended-upgrades&lt;br /&gt;
** uncomment in Allowed-Origins &amp;quot;-security&amp;quot; and &amp;quot;-updates&amp;quot;&lt;br /&gt;
** add in Allowed-Origins: &amp;quot;Google LLC:stable&amp;quot;;&lt;br /&gt;
** uncomment/add: &amp;quot;Unattended-Upgrade::Mail &amp;quot;root&amp;quot;;&lt;br /&gt;
* emacs -nw /etc/apt/apt.conf.d/10periodic&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
APT::Periodic::Update-Package-Lists &amp;quot;1&amp;quot;;&lt;br /&gt;
APT::Periodic::Download-Upgradeable-Packages &amp;quot;1&amp;quot;;&lt;br /&gt;
APT::Periodic::AutocleanInterval &amp;quot;7&amp;quot;;&lt;br /&gt;
APT::Periodic::Unattended-Upgrade &amp;quot;1&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* test: unattended-upgrade --dry-run -v&lt;br /&gt;
&lt;br /&gt;
NOTE: update-on-shutdown is disabled.&lt;br /&gt;
&lt;br /&gt;
NOTE: there is no update-on-boot, but:&lt;br /&gt;
&lt;br /&gt;
NOTE: if machine was off for a long time, the systemd update timer would have expired and it will fire soon after reboot, causing an automatic update run. this is unwanted, and there is no fix or workaround for it. K.O. June-2023.&lt;br /&gt;
&lt;br /&gt;
= Fix bpool is full (obsolete) =&lt;br /&gt;
&lt;br /&gt;
THIS IS CAUSED BY OBSOLETE PACKAGE zsys. PLEASE: apt remove zsys&lt;br /&gt;
&lt;br /&gt;
= IPMI instructions =&lt;br /&gt;
&lt;br /&gt;
IPMI is the board management hardware on Supermicro and other server motherboards. This includes hardware sensors - fan rotation speed, temperatures and power supply voltages.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt-get install ipmitool&lt;br /&gt;
systemctl enable ipmievd&lt;br /&gt;
systemctl restart ipmievd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Run:&lt;br /&gt;
* ipmitool sel list ### event list&lt;br /&gt;
* ipmitool sel elist ### event list&lt;br /&gt;
* ipmitool sel clear ### clear event list (if it becomes full)&lt;br /&gt;
* ipmitool sensor ### report hardware sensors&lt;br /&gt;
&lt;br /&gt;
= move /home/wheel (U-24) =&lt;br /&gt;
&lt;br /&gt;
Ubuntu LTS 24 installed on ZFS has rpool/USERDATA/home_xxx mounted on /home,&lt;br /&gt;
has to be moved or autofs /home will not work.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs list | grep USERDATA | grep home | cut -f1 -d&amp;quot; &amp;quot;&lt;br /&gt;
zfs set -u mountpoint=/home1 `zfs list | grep USERDATA | grep home | cut -f1 -d&amp;quot; &amp;quot;`&lt;br /&gt;
emacs -nw /etc/passwd # change mount for wheel account to /home1/wheel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will not take effect until rebooting.  Please ensure that ssh from root@daq00 to this computer works before rebooting; if ssh from root@daq00 doesn&#039;t work and you mess this up you will be locked out of wheel account. Once you verify that this works, reboot and make sure that when you login as wheel that home directory is /home1/wheel.  &lt;br /&gt;
&lt;br /&gt;
= move /home/wheel =&lt;br /&gt;
&lt;br /&gt;
note: this MUST be done if ZFS root and NIS/autofs with /home.&lt;br /&gt;
&lt;br /&gt;
Default location of wheel&#039;s home directory will collide with autofs /home, it has to be moved,&lt;br /&gt;
for example to /wheel.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# logout from the wheel user&lt;br /&gt;
# go to another computer&lt;br /&gt;
ssh root@daqubuntuxxx&lt;br /&gt;
zfs list | grep wheel ### identify zfs name wheel_xxxxxx&lt;br /&gt;
#zfs set mountpoint=/wheel rpool/USERDATA/wheel_hm8fzh&lt;br /&gt;
zfs set mountpoint=/wheel `zfs list | grep wheel | cut -f1 -d&amp;quot; &amp;quot;`&lt;br /&gt;
zfs list | grep wheel&lt;br /&gt;
emacs -nw /etc/passwd ### change wheel&#039;s home directory from /home/wheel to /wheel&lt;br /&gt;
su - wheel ### check that user wheel still works&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will break wheel&#039;s ability to run snap programs, such as firefox, install chrome as listed below.&lt;br /&gt;
&lt;br /&gt;
= enable NIS (ubuntu 22.04, 24.04, debian 11, 12) =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y install rpcbind nis&lt;br /&gt;
echo DAQ-NIS &amp;gt;&amp;gt; /etc/defaultdomain&lt;br /&gt;
echo ypserver daq00.triumf.ca &amp;gt;&amp;gt; /etc/yp.conf&lt;br /&gt;
systemctl enable ypbind.service&lt;br /&gt;
systemctl restart ypbind.service&lt;br /&gt;
systemctl status ypbind.service&lt;br /&gt;
ypwhich -m&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
enable ypserv:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sed -i s/NISSERVER=false/NISSERVER=slave/ /etc/default/nis&lt;br /&gt;
/usr/lib/yp/ypinit -s daq00&lt;br /&gt;
echo ypserver localhost &amp;gt;&amp;gt; /etc/yp.conf&lt;br /&gt;
sed -i &amp;quot;s/ypserver .*/ypserver localhost/&amp;quot; /etc/yp.conf&lt;br /&gt;
systemctl enable ypserv&lt;br /&gt;
systemctl restart ypserv&lt;br /&gt;
systemctl restart ypbind&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
update /etc/nsswitch.conf and enable hourly update of NIS maps:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir ~root/git&lt;br /&gt;
cd ~root/git&lt;br /&gt;
git clone https://daq00.triumf.ca/~olchansk/git/scripts.git&lt;br /&gt;
cd ~/git/scripts/etc&lt;br /&gt;
git pull&lt;br /&gt;
cp -pv nsswitch.conf-U24 /etc/nsswitch.conf&lt;br /&gt;
ln -s $PWD/ypxfr-cron-hourly /etc/cron.hourly&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this is a new machine, then on the master NIS node (daq00), add this new node to /etc/netgroup, and update NIS maps (cd /var/yp; make)&lt;br /&gt;
&lt;br /&gt;
= enable NIS (ubuntu 20.04) =&lt;br /&gt;
&lt;br /&gt;
* apt-get -y install portmap nis ### will ask for NIS domain (DAQ-NIS)&lt;br /&gt;
* dpkg-reconfigure nis ### reconfigure if already installed&lt;br /&gt;
* ypwhich -m&lt;br /&gt;
* edit /etc/default/nis&lt;br /&gt;
** set &amp;quot;NISSERVER=slave&amp;quot;&lt;br /&gt;
** Ubuntu LTS 20.04, check that &amp;quot;YPBINDARGS=&amp;quot; is blank, remove &amp;quot;-no-dbus&amp;quot; if it is there&lt;br /&gt;
* #edit /etc/yp.conf, comment-out everything, add &amp;quot;domain DAQ-NIS server localhost&amp;quot;&lt;br /&gt;
* edit /etc/yp.conf, comment-out everything, add &amp;quot;ypserver localhost&amp;quot;&lt;br /&gt;
* /usr/lib/yp/ypinit -s daq00&lt;br /&gt;
* systemctl enable nis&lt;br /&gt;
* systemctl restart nis&lt;br /&gt;
* ypwhich&lt;br /&gt;
* ypwhich -m&lt;br /&gt;
* ypcat -k passwd&lt;br /&gt;
* vi /etc/nsswitch.conf ### add the automount line, modify the passwd, group and shadow lines to read this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# begin get data from nis&lt;br /&gt;
passwd: files nis&lt;br /&gt;
group: files nis&lt;br /&gt;
shadow: files nis&lt;br /&gt;
automount:  files nis&lt;br /&gt;
netgroup: files nis&lt;br /&gt;
# end get data from nis&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* enable hourly update of NIS maps&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir ~root/git&lt;br /&gt;
cd ~root/git&lt;br /&gt;
git clone https://daq00.triumf.ca/~olchansk/git/scripts.git&lt;br /&gt;
cd ~/git/scripts/etc&lt;br /&gt;
git pull&lt;br /&gt;
ln -s $PWD/ypxfr-cron-hourly /etc/cron.hourly&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ### NOT NEEDED sudo vi /etc/idmapd.conf ### add line: &amp;quot;Domain = triumf.ca&amp;quot;&lt;br /&gt;
&lt;br /&gt;
= enable autofs =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y install autofs&lt;br /&gt;
systemctl enable autofs&lt;br /&gt;
systemctl restart autofs&lt;br /&gt;
ls -l /home/olchansk ### test autofs, check file owner is correct&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= enable NFS server =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install nfs-kernel-server&lt;br /&gt;
#edit /etc/exports&lt;br /&gt;
systemctl enable nfs-server&lt;br /&gt;
systemctl restart nfs-server&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= NIS master =&lt;br /&gt;
&lt;br /&gt;
notes for setting up the NIS master&lt;br /&gt;
&lt;br /&gt;
== wheel user ==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;wheel&amp;quot; is the default administrative user. We do not want it&#039;s password exported to NIS (encrypted password hash is world visible) and we do not want it&#039;s home directory exported to NFS (~wheel/.ssh is world visible and potentially writable: anybody can change ~wheel/.ssh/authorized_keys).&lt;br /&gt;
&lt;br /&gt;
* move wheel&#039;s home directory from /home/wheel to /wheel (see special section about this)&lt;br /&gt;
* change wheel&#039;s UID and GID from 1000 to a value below MINUID in /var/yp/Makefile&lt;br /&gt;
&lt;br /&gt;
== coherent uids ==&lt;br /&gt;
&lt;br /&gt;
we do not want system accounts defined in /etc/passwd of the NIS master&lt;br /&gt;
to be included in the NIS map &amp;quot;passwd&amp;quot;. this causes trouble on NIS clients&lt;br /&gt;
where newly installed packages fail to create local system users because same&lt;br /&gt;
user already exists in NIS.&lt;br /&gt;
&lt;br /&gt;
This is controlled by MINUID in /var/yp/Makefile.&lt;br /&gt;
&lt;br /&gt;
Historical TRIUMF uids start from around 200, but several clusters do not have any historic TRIUMF uids below 500 and MINUID is set to:&lt;br /&gt;
* DAQ-NIS: MINUID=200&lt;br /&gt;
* ISAC-NIS: MINUID=500&lt;br /&gt;
* TITAN-NIS: MINUID=500&lt;br /&gt;
* MUSR-NIS: MINUID=500&lt;br /&gt;
* TIG-NIS: MINUID=500 (100 on SL6 mother8pi)&lt;br /&gt;
&lt;br /&gt;
Ubuntu 20 has two programs to create users:&lt;br /&gt;
* adduser - creates new users with UID 1000 and up as specified in /etc/adduser.conf. No problems here.&lt;br /&gt;
* adduser --system - creates new system users with UID 100 and up as specified in /etc/adduser.conf. No problems here.&lt;br /&gt;
* useradd - creates new users with UID 1000 and up as specified in /etc/login.defs. No problems here.&lt;br /&gt;
* useradd --system - creates new system users with UID 999 and down (read &amp;quot;man useradd&amp;quot;, section at the end about SYS_UID_MAX). This collides with NIS MINUID, these system users will be included in the NIS map and cause trouble.&lt;br /&gt;
&lt;br /&gt;
This problem cannot be fixed, SYS_UID_MIN, SYS_UID_MAX and UID_MIN in /etc/login.defs do not seem&lt;br /&gt;
to have any effect on UIDs chosen by &amp;quot;useradd --system&amp;quot;. (tested on Ubuntu LTS 20.04).&lt;br /&gt;
&lt;br /&gt;
So far only these system accounts seem to be affected by this:&lt;br /&gt;
* systemd-coredump&lt;br /&gt;
* ganglia&lt;br /&gt;
&lt;br /&gt;
To fix:&lt;br /&gt;
* run &amp;quot;sort -r -n -t: -k3 /etc/passwd&amp;quot; to identify the last unused system user uid (range 100..200)&lt;br /&gt;
* run &amp;quot;sort -r -n -t: -k3 /etc/group&amp;quot; to identify the last unused system user gid (range 100.200)&lt;br /&gt;
* systemd-coredump: manually change UID and GID (package systemd-coredump is usually not installed)&lt;br /&gt;
* ganglia: same thing, then change ownership on all ganglia files.&lt;br /&gt;
&lt;br /&gt;
Also read systemd author&#039;s opinion on system vs user UIDs:&lt;br /&gt;
https://github.com/systemd/systemd/issues/4850#issuecomment-265698275&lt;br /&gt;
&lt;br /&gt;
= Fix systemd-logind NIS breakage =&lt;br /&gt;
&lt;br /&gt;
!!! THIS IS NOT NEEDED FOR UBUNTU LTS 20.04 !!!&lt;br /&gt;
&lt;br /&gt;
there is a delay in ssh logins for normal users. &amp;quot;ssh -v&amp;quot; shows the delay is after &amp;quot;pledge...&amp;quot;. this&lt;br /&gt;
fix removes the delay.&lt;br /&gt;
&lt;br /&gt;
systemd developers think that we should not use NIS and made sure there are&lt;br /&gt;
problems if we do. To give them credit, they do offer a workaround. Read this:&lt;br /&gt;
https://github.com/poettering/systemd/commit/695fe4078f0df6564a1be1c4a6a9e8a640d23b67&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /etc/systemd/system/systemd-logind.service.d&lt;br /&gt;
echo -e &amp;quot;[Service]\nIPAddressDeny=\n&amp;quot; &amp;gt; /etc/systemd/system/systemd-logind.service.d/local.conf&lt;br /&gt;
systemctl daemon-reload&lt;br /&gt;
systemctl cat systemd-logind.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Fix systemd-udevd NIS breakage =&lt;br /&gt;
&lt;br /&gt;
see same problem as above with udev getting stuck. ubuntu lts 20.04.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /etc/systemd/system/systemd-udevd.service.d&lt;br /&gt;
echo -e &amp;quot;[Service]\nIPAddressDeny=\n&amp;quot; &amp;gt; /etc/systemd/system/systemd-udevd.service.d/local.conf&lt;br /&gt;
systemctl daemon-reload&lt;br /&gt;
systemctl cat systemd-udevd.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Configure USB device permissions =&lt;br /&gt;
&lt;br /&gt;
Configure USB device permissions for user access to USB-serial devices, Altera USB Blaster, etc.&lt;br /&gt;
&lt;br /&gt;
* create file /etc/udev/rules.d/99-usb-chmod.rules with this contents:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
emacs -nw /etc/udev/rules.d/99-usb-chmod.rules&lt;br /&gt;
ACTION==&amp;quot;add&amp;quot;, SUBSYSTEM==&amp;quot;usbmisc&amp;quot;, RUN+=&amp;quot;/bin/chmod a+wr $env{DEVNAME}&amp;quot; &lt;br /&gt;
ACTION==&amp;quot;add&amp;quot;, SUBSYSTEM==&amp;quot;usb_device&amp;quot;, RUN+=&amp;quot;/bin/chmod a+wr /dev/%c&amp;quot;&lt;br /&gt;
ACTION==&amp;quot;add&amp;quot;, SUBSYSTEM==&amp;quot;usb_device&amp;quot;, RUN+=&amp;quot;/bin/chmod a+wr /proc/%c&amp;quot;&lt;br /&gt;
ACTION==&amp;quot;add&amp;quot;, ENV{DEVTYPE}==&amp;quot;usb_device&amp;quot;, RUN+=&amp;quot;/bin/chmod a+wr $env{DEVNAME}&amp;quot;&lt;br /&gt;
ACTION==&amp;quot;add&amp;quot;, ENV{DEVTYPE}==&amp;quot;usb_device&amp;quot;, RUN+=&amp;quot;/bin/chmod a+wr $env{DEVICE}&amp;quot;&lt;br /&gt;
ACTION==&amp;quot;add&amp;quot;, ENV{PHYSDEVBUS}==&amp;quot;usb-serial&amp;quot;, RUN+=&amp;quot;/bin/chmod a+wr $env{DEVNAME}&amp;quot;&lt;br /&gt;
ACTION==&amp;quot;add&amp;quot;, ENV{DEVPATH}==&amp;quot;/class/tty/ttyS*&amp;quot;, RUN+=&amp;quot;/bin/chmod a+wr $env{DEVNAME}&amp;quot;&lt;br /&gt;
ACTION==&amp;quot;add&amp;quot;, SUBSYSTEM==&amp;quot;tty&amp;quot;, DEVPATH==&amp;quot;*ttyUSB*&amp;quot;, RUN+=&amp;quot;/bin/chmod a+rw $env{DEVNAME}&amp;quot;&lt;br /&gt;
ACTION==&amp;quot;add&amp;quot;, SUBSYSTEM==&amp;quot;tty&amp;quot;, DEVPATH==&amp;quot;*ttyACM*&amp;quot;, RUN+=&amp;quot;/bin/chmod a+rw $env{DEVNAME}&amp;quot;&lt;br /&gt;
ACTION==&amp;quot;add&amp;quot;, SUBSYSTEM==&amp;quot;tty&amp;quot;, DEVPATH==&amp;quot;*ttyS*&amp;quot;, RUN+=&amp;quot;/bin/chmod a+rw $env{DEVNAME}&amp;quot;&lt;br /&gt;
ACTION==&amp;quot;add&amp;quot;, DEVPATH==&amp;quot;*video*&amp;quot;, RUN+=&amp;quot;/bin/chmod a+rw $env{DEVNAME}&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* reload udev rules: udevadm control --reload-rules&lt;br /&gt;
* apply new permissions: udevadm trigger --action=add&lt;br /&gt;
* watch udev activity: udevadm monitor -p&lt;br /&gt;
&lt;br /&gt;
= Configure lightdm display manager =&lt;br /&gt;
&lt;br /&gt;
* enable it&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo lightdm | dpkg-reconfigure -fteletype lightdm&lt;br /&gt;
systemctl disable gdm&lt;br /&gt;
systemctl disable sddm&lt;br /&gt;
systemctl enable lightdm&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* make the MATE desktop as default&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~root/git/scripts/&lt;br /&gt;
git pull&lt;br /&gt;
/bin/cp -v etc/lightdm_default_mate.conf /etc/lightdm/lightdm.conf.d/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* enable login by NIS users&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/bin/cp -v etc/lightdm_enable_nis_login.conf /etc/lightdm/lightdm.conf.d/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* restart lightdm&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl stop gdm&lt;br /&gt;
systemctl restart lightdm&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Install libpng12.so.0 =&lt;br /&gt;
&lt;br /&gt;
Quartus 16 needs libpng12:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://mirrors.kernel.org/ubuntu/pool/main/libp/libpng/libpng12-0_1.2.54-1ubuntu1_amd64.deb&lt;br /&gt;
dpkg --install libpng12-0_1.2.54-1ubuntu1_amd64.deb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Install google-chrome =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb&lt;br /&gt;
dpkg -i google-chrome-stable_current_amd64.deb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
confirm autoupdate is enabled, observe dl.google.com is present in the list of repositories:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt update&lt;br /&gt;
...&lt;br /&gt;
Get:5 https://dl.google.com/linux/chrome/deb stable/main amd64 Packages [1,094 B]&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
FOLLOWING IS OBSOLETE:&lt;br /&gt;
&lt;br /&gt;
Instructions from here:&lt;br /&gt;
https://www.ubuntuupdates.org/ppa/google_chrome?dist=stable&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -&lt;br /&gt;
sh -c &#039;echo &amp;quot;deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main&amp;quot; &amp;gt;&amp;gt; /etc/apt/sources.list.d/google-tmp.list&#039;&lt;br /&gt;
apt update&lt;br /&gt;
apt install google-chrome-stable&lt;br /&gt;
/bin/rm -f /etc/apt/sources.list.d/google-tmp.list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Install amanda client =&lt;br /&gt;
&lt;br /&gt;
ONLY ON MACHINES THAT HOST HOME DIRECTORIES&lt;br /&gt;
&lt;br /&gt;
* apt install amanda-client&lt;br /&gt;
* edit /etc/amandahosts&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
amanda.triumf.ca amanda amdump&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* check permissions on /etc/amandahosts:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq00:/var/log/amanda# ls -l /etc/amandahosts&lt;br /&gt;
-rw------- 1 backup backup 49 Jan 27 10:48 /etc/amandahosts&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* fix if needed: chown backup.backup /etc/amandahosts; chmod a= /etc/amandahosts; chmod u=wr /etc/amandahosts&lt;br /&gt;
* edit /etc/amanda-security.conf, add this line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
runtar:gnutar_path=/usr/bin/tar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On the amanda machine:&lt;br /&gt;
&lt;br /&gt;
* in amanda disklist, use dump type &amp;quot;bsdtcp-comp-user-tar&amp;quot;&lt;br /&gt;
* su - amanda and run amcheck -c daily daq00&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-bash-4.1$ amcheck -c daily daq00&lt;br /&gt;
&lt;br /&gt;
Amanda Backup Client Hosts Check&lt;br /&gt;
--------------------------------&lt;br /&gt;
Client check: 1 host checked in 0.092 seconds.  0 problems found.&lt;br /&gt;
&lt;br /&gt;
(brought to you by Amanda 3.3.7p1.git.685ff76d)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Enable rc.local =&lt;br /&gt;
&lt;br /&gt;
For reasons unknown, Ubuntu LTS 20.04 does not enable /etc/rc.local. Do this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/git/scripts&lt;br /&gt;
git pull&lt;br /&gt;
cp -n -v etc/rc.local /etc/&lt;br /&gt;
chmod a+rx /etc/rc.local&lt;br /&gt;
cp etc/rc-local.service /etc/systemd/system/&lt;br /&gt;
systemctl daemon-reload&lt;br /&gt;
systemctl enable rc-local&lt;br /&gt;
systemctl start rc-local&lt;br /&gt;
systemctl status rc-local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Remove unwanted packages =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt purge  bash-completion # broken, adds unwanted &amp;quot;\&amp;quot; if &amp;quot;ls -l $ROOTSYS/&amp;lt;tab&amp;gt;&amp;quot;&lt;br /&gt;
apt purge  zsys # broken, do not use&lt;br /&gt;
apt purge  sddm # login manager&lt;br /&gt;
apt purge  avahi-daemon avahi-autoipd # not sure what it does, observed using 100% CPU&lt;br /&gt;
apt purge  modemmanager # probes all serial ports to see if it&#039;s a modem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Disable unwanted services =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl disable mpd&lt;br /&gt;
systemctl disable snapd&lt;br /&gt;
systemctl disable ModemManager&lt;br /&gt;
systemctl --global mask tracker-extract-3.service&lt;br /&gt;
systemctl --global mask tracker-miner-fs-3.service&lt;br /&gt;
systemctl daemon-reload&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Disable sleep and suspend =&lt;br /&gt;
&lt;br /&gt;
note: we see some computers randomly shutdown or go to sleep, log files indicates the &amp;quot;sleep&amp;quot; or &amp;quot;suspend&amp;quot; button was pushed by user, but no such buttons actually exist. this is the fix for this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target systemd-suspend.service systemd-hybrid-sleep.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Enable crontab @reboot for MIDAS =&lt;br /&gt;
&lt;br /&gt;
startup scripts have a bug - cron @reboot entries for normal users can run before autofs is ready, so if the home directory is on autofs/NFS, it cannot be accessed and the cron job fails. If MIDAS is supposed to be started by cron @reboot, it will not start (there *will* be an error message in /var/log/cron).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /etc/systemd/system/cron.service.d&lt;br /&gt;
echo -e &amp;quot;[Unit]\nAfter=ypbind.service autofs.service\n&amp;quot; &amp;gt; /etc/systemd/system/cron.service.d/local.conf&lt;br /&gt;
systemctl daemon-reload&lt;br /&gt;
systemctl cat cron.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explore the systemd dependency tree using &amp;quot;systemctl list-dependencies&amp;quot; maybe with &amp;quot;--all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Visualize the exact boot sequence from previous boot: &amp;quot;systemd-analyze plot &amp;gt; xxx.svg&amp;quot;, look at the svg file using a web browser.&lt;br /&gt;
&lt;br /&gt;
Crontab entry to start midas: (install in the midas user crontab, not root crontab)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
su - midasuser&lt;br /&gt;
crontab -l&lt;br /&gt;
#@reboot /bin/bash -l -c &amp;quot;/home/trinat/bin/start-daq-applications&amp;quot;&lt;br /&gt;
#@reboot /bin/tcsh -c &amp;quot;/home/trinat/bin/start-daq-applications&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Install apache httpd proxy for midas and elog =&lt;br /&gt;
&lt;br /&gt;
This will configure the HTTPS/SSL certificate using &amp;quot;certbot&amp;quot; and &amp;quot;letsencrypt&amp;quot; and configure an HTTPS web server using apache2.&lt;br /&gt;
&lt;br /&gt;
First, configure apache2:&lt;br /&gt;
&lt;br /&gt;
* execute these commands:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y install apache2&lt;br /&gt;
cd /etc/apache2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* create new file conf-available/ssl-daq14.conf # use actual hostname instead of daq14&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SSLSessionCache         shmcb:/run/httpd/sslcache(512000)&lt;br /&gt;
SSLSessionCacheTimeout  300&lt;br /&gt;
SSLRandomSeed startup file:/dev/urandom  256&lt;br /&gt;
SSLRandomSeed connect builtin&lt;br /&gt;
SSLCryptoDevice builtin&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* create new file sites-available/daq14-ssl.conf # use actual hostname instead of daq14&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;IfModule mod_ssl.c&amp;gt;&lt;br /&gt;
    &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
        ServerName daq14.triumf.ca&lt;br /&gt;
        DocumentRoot /var/www/html&lt;br /&gt;
        ErrorLog /var/log/apache2/daq14.log&lt;br /&gt;
        SSLEngine on&lt;br /&gt;
        # note SSLProtocol, SSLCipherSuite and some other settings are overwritten by /etc/letsencrypt/options-ssl-apache.conf&lt;br /&gt;
        SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1&lt;br /&gt;
        SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5:!SEED:!IDEA:!RC4&lt;br /&gt;
        ## use port specified in elogd.cfg&lt;br /&gt;
        #ProxyPass /elog/ http://localhost:8082/ retry=1 &lt;br /&gt;
        ## use mhttpd port&lt;br /&gt;
        #ProxyPass /      http://localhost:8080/ retry=1 &lt;br /&gt;
        Header always set Strict-Transport-Security &amp;quot;max-age=31536000; includeSubDomains&amp;quot;&lt;br /&gt;
        &amp;lt;Location /&amp;gt;&lt;br /&gt;
            SSLRequireSSL&lt;br /&gt;
            AuthType Basic&lt;br /&gt;
            AuthName &amp;quot;DAQ password protected site&amp;quot;&lt;br /&gt;
            Require valid-user&lt;br /&gt;
            # create password file: touch /etc/apache2/htpasswd&lt;br /&gt;
            # to add new user or change password: htpasswd /etc/apache2/htpasswd username&lt;br /&gt;
            AuthUserFile /etc/apache2/htpasswd&lt;br /&gt;
        &amp;lt;/Location&amp;gt;&lt;br /&gt;
        #SSLCertificateFile /root/server.cert &lt;br /&gt;
        #SSLCertificateKeyFile /root/server.key &lt;br /&gt;
    &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&amp;lt;/IfModule&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* stop apache2 from listening on port 80: edit /etc/apache2/ports.conf, comment-out the line &amp;quot;Listen 80&amp;quot;&lt;br /&gt;
* enable ssl module and new configurations:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a2enmod ssl&lt;br /&gt;
a2enmod headers&lt;br /&gt;
a2enmod proxy&lt;br /&gt;
a2enmod proxy_http&lt;br /&gt;
a2enconf ssl-daq14&lt;br /&gt;
a2ensite daq14-ssl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* disable default ssl sites&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a2dissite 000-default-le-ssl&lt;br /&gt;
a2dissite 000-default&lt;br /&gt;
ls -l /etc/apache2/sites-enabled/ ### should show only daq14-ssl.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* check that there are no syntax problems&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apache2ctl configtest&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* enable and start apache2:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl enable apache2&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
systemctl status apache2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* apache2 may fail to start, look in /var/log/apache2/error.log and /var/log/apache2/daq14.log&lt;br /&gt;
* if it says &amp;quot;Failed to configure ... certificate&amp;quot;, proceed to the step for setting certbot.&lt;br /&gt;
* try to access https://daq14.triumf.ca&lt;br /&gt;
** you should see a complaint about self-signed certificate&lt;br /&gt;
** you should see a request for password (do not login yet)&lt;br /&gt;
** if you get &amp;quot;connection refused&amp;quot;, HTTPS port 443 may need to be enabled in the local firewall, look at documentation for ufw.&lt;br /&gt;
Second, configure certbot:&lt;br /&gt;
&lt;br /&gt;
(Note: as of 2018-01-18 certbot requires use of http port 80 to get the initial https certificate,&lt;br /&gt;
renewal can continue to use the https port 443)&lt;br /&gt;
&lt;br /&gt;
(Note: as of 2019-01-?? certbot requires use of port 80 for renewals)&lt;br /&gt;
&lt;br /&gt;
(Note: unsurprisingly, this requires outside access to connect with letsencrypt, so won&#039;t work if PC is only accessible from on-site network)&lt;br /&gt;
&lt;br /&gt;
* check that port 80 is not used by anything:&lt;br /&gt;
* netstat -an | grep LISTEN | grep ^tcp | grep 80&lt;br /&gt;
* lsof -P | grep -i tcp | grep LISTEN | grep 80&lt;br /&gt;
* if lsof reports that apache2 is listening on port 80, follow the apache2 instructions above (remove &amp;quot;listen 80&amp;quot; from apache2.conf&lt;br /&gt;
&lt;br /&gt;
* install certbot (if necessary open tcp port 80 in the firewall, see documentation for ufw):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install certbot python3-certbot-apache&lt;br /&gt;
certbot certonly --standalone --installer apache&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* then answer questions:&lt;br /&gt;
* &amp;quot;activate HTTPS for daq14.triumf.ca&amp;quot; - say ok&lt;br /&gt;
* &amp;quot;enter email address&amp;quot; - enter your own email address&lt;br /&gt;
* &amp;quot;please read terms...&amp;quot; - read the terms and say &amp;quot;agree&amp;quot;&lt;br /&gt;
* it will take a few moments...&lt;br /&gt;
* &amp;quot;congratulations...&amp;quot; - say ok.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
certbot install --apache --cert-name daq14.triumf.ca&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* then answer questions:&lt;br /&gt;
* &amp;quot;choose redirect...&amp;quot; - say &amp;quot;1&amp;quot; (no redirect)&lt;br /&gt;
* look inside /etc/apache2/sites-enabled/daq14-ssl.conf to see that SSLCertificateFile &amp;amp; co point to certbot certificates in&lt;br /&gt;
/etc/letsencrypt/live/daq14.triumf.ca/&lt;br /&gt;
* to check current renewal and to update the certbot config file in /etc/letsencrypt/renewal, run this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
certbot renew --standalone --installer apache --force-renewal&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
NOTE: this certificate will expire in 3 months, automatic renewal should work with current version of certbot&lt;br /&gt;
&lt;br /&gt;
Third, activate password protection:&lt;br /&gt;
&lt;br /&gt;
* as shown in the config file above, create password file and initial user: (replace &amp;quot;midas&amp;quot; with specific username)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /etc/apache2/htpasswd&lt;br /&gt;
htpasswd /etc/apache2/htpasswd midas&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* restart apache2&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
systemctl status apache2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From here:&lt;br /&gt;
* enable proxy for MIDAS mhttpd - uncomment redirect in the config file above&lt;br /&gt;
* enable proxy for ELOG - ditto&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a2enmod proxy&lt;br /&gt;
a2enmod proxy_http&lt;br /&gt;
apache2ctl configtest&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* try accessing MIDAS https://daq14.triumf.ca/ (make sure mhttpd is running)&lt;br /&gt;
* if it&#039;s not working, check odb setting FIXME!&lt;br /&gt;
* try accessing ELog https://daq14.triumf.ca/elog/ (make sure elogd is running)&lt;br /&gt;
* if it&#039;s not working, check elogd.cfg file and make sure&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SSL                  = 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
NOTE: if certbot fails with errors about &#039;module&#039; object has no attribute &#039;pyopenssl&#039;,&lt;br /&gt;
try this: pip install requests==2.6.0&lt;br /&gt;
&lt;br /&gt;
== generate self-signed certificate ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# cd $HOME&lt;br /&gt;
# openssl req  -nodes -new -x509  -keyout server.key -out server.cert -days 1001&lt;br /&gt;
...+....+..+..........+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*....+..+...+.........+......+.+...+...+.....+...............+.........+...+.+......+...+...........+....+...+..+......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*....+......+.+...+..+.......+..+...+.......+......+...+..+...+......+....+...............+..+...+....+...........+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++&lt;br /&gt;
......+......+.+..+......+.+......+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.+.....+......+.+.........+......+.....+.+..+...+.......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.......+....+......+.....+...+...+.......+..+.+........+.+...+......+..+..........+..+.+...........+...+.......+......+.....+.......+...+.........+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++&lt;br /&gt;
-----&lt;br /&gt;
You are about to be asked to enter information that will be incorporated&lt;br /&gt;
into your certificate request.&lt;br /&gt;
What you are about to enter is what is called a Distinguished Name or a DN.&lt;br /&gt;
There are quite a few fields but you can leave some blank&lt;br /&gt;
For some fields there will be a default value,&lt;br /&gt;
If you enter &#039;.&#039;, the field will be left blank.&lt;br /&gt;
-----&lt;br /&gt;
Country Name (2 letter code) [AU]:CH&lt;br /&gt;
State or Province Name (full name) [Some-State]:Geneve&lt;br /&gt;
Locality Name (eg, city) []:CERN&lt;br /&gt;
Organization Name (eg, company) [Internet Widgits Pty Ltd]:CERN&lt;br /&gt;
Organizational Unit Name (eg, section) []:ALPHA experiment           &lt;br /&gt;
Common Name (e.g. server FQDN or YOUR name) []:alphacpc05.cern.ch&lt;br /&gt;
Email Address []:&lt;br /&gt;
root@alphacpc05:~# &lt;br /&gt;
root@alphacpc05:~# &lt;br /&gt;
root@alphacpc05:~# ls -l&lt;br /&gt;
-rw-r--r-- 1 root root 1375 juil. 10 21:43 server.cert&lt;br /&gt;
-rw------- 1 root root 1708 juil. 10 21:42 server.key&lt;br /&gt;
root@alphacpc05:~# systemctl restart apache2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Enable elog PDF preview =&lt;br /&gt;
&lt;br /&gt;
NOTE: looks like U-24 already has this correctly.&lt;br /&gt;
&lt;br /&gt;
see https://stackoverflow.com/questions/52998331/imagemagick-security-policy-pdf-blocking-conversion&lt;br /&gt;
&lt;br /&gt;
* xemacs -nw /etc/ImageMagick-6/policy.xml&lt;br /&gt;
* remove this section at the end:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;!-- disable ghostscript format types --&amp;gt;&lt;br /&gt;
&amp;lt;policy domain=&amp;quot;coder&amp;quot; rights=&amp;quot;none&amp;quot; pattern=&amp;quot;PS&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;policy domain=&amp;quot;coder&amp;quot; rights=&amp;quot;none&amp;quot; pattern=&amp;quot;PS2&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;policy domain=&amp;quot;coder&amp;quot; rights=&amp;quot;none&amp;quot; pattern=&amp;quot;PS3&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;policy domain=&amp;quot;coder&amp;quot; rights=&amp;quot;none&amp;quot; pattern=&amp;quot;EPS&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;policy domain=&amp;quot;coder&amp;quot; rights=&amp;quot;none&amp;quot; pattern=&amp;quot;PDF&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;policy domain=&amp;quot;coder&amp;quot; rights=&amp;quot;none&amp;quot; pattern=&amp;quot;XPS&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Install Jupyter notebook =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
From https://jupyter.org/install&lt;br /&gt;
apt install python3-pip&lt;br /&gt;
pip install jupyterlab&lt;br /&gt;
pip install notebook&lt;br /&gt;
~/.local/bin/jupyter notebook&lt;br /&gt;
watch the http://localhost:8888 URL that it printed&lt;br /&gt;
say &amp;quot;no&amp;quot; to offer to start firefox (it will not work!)&lt;br /&gt;
URL is: http://localhost:8888/tree?token=xxx&lt;br /&gt;
from the machine where you are running the web browser (i.e. google-chrome), run (replace trinat@trinatdaq with the username and machine name where you started jupyter)&lt;br /&gt;
open a new shell and run: ssh -v trinat@trinatdaq -L 8888:localhost:8888&lt;br /&gt;
in the web browser, open http://localhost:8888&lt;br /&gt;
this gives us the login page&lt;br /&gt;
in the password or token entry field, put the token from the &amp;quot;tree?token=xxx&amp;quot; above (printed by jupyter on startup)&lt;br /&gt;
push button &amp;quot;login&amp;quot;&lt;br /&gt;
jupyter page should open with the list of files in the trinat home directory&lt;br /&gt;
congratulate Brian with full success&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Install ZFS quota report =&lt;br /&gt;
&lt;br /&gt;
If there are any ZFS volumes, install script to report disk and quota usage&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/git/scripts/quotareport&lt;br /&gt;
git pull&lt;br /&gt;
mkdir /var/www/html/zfsquotareport&lt;br /&gt;
cp -pv ~/git/scripts/quotareport/sorttable.js /var/www/html/zfsquotareport/&lt;br /&gt;
ln -s $PWD/zfsquotareport.perl /etc/cron.daily/&lt;br /&gt;
touch /etc/crontab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If httpd is configured to redirect &amp;quot;/&amp;quot; to MIDAS mhttpd:&lt;br /&gt;
* add following to /etc/apache2/sites-enabled/xxx-ssl.conf in front of &amp;quot;ProxyPass / ...&amp;quot;&lt;br /&gt;
* run &amp;quot;systemctl reload apache2&amp;quot;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
## do not proxy zfs quota report directory &lt;br /&gt;
ProxyPass /zfsquotareport/ ! &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Install PHP =&lt;br /&gt;
&lt;br /&gt;
* apt install php libapache2-mod-php&lt;br /&gt;
* systemctl restart apache2&lt;br /&gt;
* create /var/www/html/info.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php &lt;br /&gt;
 &lt;br /&gt;
phpinfo(); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* open https://daq00.triumf.ca/info.php&lt;br /&gt;
&lt;br /&gt;
= Configure TRIUMF printers =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl stop cups&lt;br /&gt;
systemctl stop cups-browsed.service&lt;br /&gt;
systemctl disable cups&lt;br /&gt;
systemctl disable cups-browsed.service&lt;br /&gt;
systemctl stop snap.cups.cupsd.service&lt;br /&gt;
systemctl stop snap.cups.cups-browsed.service&lt;br /&gt;
systemctl disable snap.cups.cupsd.service&lt;br /&gt;
systemctl disable snap.cups.cups-browsed.service&lt;br /&gt;
echo &amp;quot;ServerName printers.triumf.ca&amp;quot; &amp;gt; /etc/cups/client.conf&lt;br /&gt;
lpstat -a&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Enable core dumps =&lt;br /&gt;
&lt;br /&gt;
By default, Ubuntu LTS 20.04 installs the apport package&lt;br /&gt;
which disabled core dumps from user applications. (google it up!).&lt;br /&gt;
It is not meant to do this and documentation claims that&lt;br /&gt;
it is not installed and not enabled by default. Oh, well...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt purge apport&lt;br /&gt;
apt autoremove ### will remove apport-symptoms and a few other packages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After this, core dumps are written to file &amp;quot;core&amp;quot; in the current directory.&lt;br /&gt;
See /proc/sys/kernel/core_pattern and /proc/sys/kernel/core_uses_pid.&lt;br /&gt;
&lt;br /&gt;
Enable core dump file names to include process id, add following to /etc/rc.local&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &amp;quot;echo 1 &amp;gt; /proc/sys/kernel/core_uses_pid&amp;quot; &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Enable debugger =&lt;br /&gt;
&lt;br /&gt;
By default, Ubuntu LTS 20.04 does not permit debugger to attach and debug&lt;br /&gt;
already running programs. To enable it, add following to /etc/rc.local&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &amp;quot;echo 0 &amp;gt; /proc/sys/kernel/yama/ptrace_scope&amp;quot; &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Disable Ubuntu Pro nag =&lt;br /&gt;
&lt;br /&gt;
best I can tell, impossible at this time.&lt;br /&gt;
&lt;br /&gt;
== do not do this ==&lt;br /&gt;
&lt;br /&gt;
!!! does nothing !!!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
pro config set apt_news=false&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== do not do this ==&lt;br /&gt;
&lt;br /&gt;
!!! breaks automatic updates because 20apt-esm-hook.conf is missing !!!&lt;br /&gt;
&lt;br /&gt;
If &amp;quot;apt upgrade&amp;quot; requests Ubuntu Pro or esm-apps, disable the nag:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/bin/rm /etc/apt/apt.conf.d/20apt-esm-hook.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== do not do this ==&lt;br /&gt;
&lt;br /&gt;
!!! likely same as above, breaks automatic updates !!!&lt;br /&gt;
&lt;br /&gt;
* comment out /etc/apt/apt.conf.d/20apt-esm-hook.conf&lt;br /&gt;
&lt;br /&gt;
== do not do this ==&lt;br /&gt;
&lt;br /&gt;
!!! removes too many packages !!!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt remove ubuntu-pro-client&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Update packages =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt update # update package list&lt;br /&gt;
apt upgrade # install updated packages and update &amp;quot;kept back&amp;quot; packages&lt;br /&gt;
apt autoremove # remove packages that apt thinks should be removed&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Remove obsolete packages =&lt;br /&gt;
&lt;br /&gt;
NOTE: do this only if booted into the latest linux kernel - compare &amp;quot;uname -a&amp;quot; with &amp;quot;ls -l /boot&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt list &#039;~o&#039;&lt;br /&gt;
apt purge &#039;~o&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Cleanup residual configs =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt list &#039;~c&#039;&lt;br /&gt;
apt purge &#039;~c&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Install firefox-esr =&lt;br /&gt;
&lt;br /&gt;
install firefox-esr here&lt;br /&gt;
&lt;br /&gt;
= Finish installation =&lt;br /&gt;
&lt;br /&gt;
Congratulations. There is nothing more to do!&lt;br /&gt;
&lt;br /&gt;
* reboot&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
shutdown -r now&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Update to new version of Ubuntu =&lt;br /&gt;
&lt;br /&gt;
* run &amp;quot;do-release-upgrade -c&amp;quot;&lt;br /&gt;
* if it does not report new release Ubuntu 24, check /etc/update-manager/release-upgrades has &amp;quot;Prompt=lts&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Update Ubuntu LTS 20.04 to LTS 22.04 ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt remove zsys&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== daqubuntu ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# reboot to clear out all updates&lt;br /&gt;
# vi /etc/update-manager/release-upgrades # set &amp;quot;Prompt=normal&amp;quot;&lt;br /&gt;
# do-release-upgrade -c&lt;br /&gt;
Checking for a new Ubuntu release&lt;br /&gt;
New release &#039;22.04 LTS&#039; available.&lt;br /&gt;
Run &#039;do-release-upgrade&#039; to upgrade to it.&lt;br /&gt;
# do-release-upgrade&lt;br /&gt;
...&lt;br /&gt;
say yes...&lt;br /&gt;
...&lt;br /&gt;
login.defs, say &amp;quot;Y&amp;quot; (erase local changes, use packaged version)&lt;br /&gt;
/etc/systemd/resolved.conf, say &amp;quot;Y&amp;quot; (same as above)&lt;br /&gt;
firefox snap, say yes&lt;br /&gt;
unable to reach snap store, say &amp;quot;skip&amp;quot;&lt;br /&gt;
/etc/gmond.conf, say &amp;quot;Y&amp;quot;&lt;br /&gt;
/var/yp/Makefile, say &amp;quot;install the package maintainer&#039;s version&amp;quot;&lt;br /&gt;
/etc/ypserv.conf, same thing&lt;br /&gt;
/etc/ypserv.securenets, same thing&lt;br /&gt;
/etc/default/nis, same thing&lt;br /&gt;
/etc/speech-dispatcher/modules/mary-generic.conf, same thing&lt;br /&gt;
/etc/apt/apt.conf.d/50unattended-upgrades, same thing&lt;br /&gt;
...&lt;br /&gt;
278 packages are going to be removed, say yes&lt;br /&gt;
...&lt;br /&gt;
restart required, say yes&lt;br /&gt;
...&lt;br /&gt;
no ping... yes ping...&lt;br /&gt;
...&lt;br /&gt;
ssh daqubuntu, ok&lt;br /&gt;
apt update, fail, DNS does not work, &amp;quot;host security.ubuntu.com&amp;quot; does not resolve.&lt;br /&gt;
fix resolver per https://daq00.triumf.ca/DaqWiki/index.php/Ubuntu#Disable_NetworkManager&lt;br /&gt;
apt update, apt upgrade now works, 0 packages to update&lt;br /&gt;
NIS does not work.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== midm9a ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
login.defs&lt;br /&gt;
firefox snap&lt;br /&gt;
gmond.conf&lt;br /&gt;
ypserv&lt;br /&gt;
/etc/default/nis&lt;br /&gt;
unattended-upgrades&lt;br /&gt;
amanda-security.conf&lt;br /&gt;
remove obsolete (no)&lt;br /&gt;
reboot&lt;br /&gt;
configure dns&lt;br /&gt;
reenable nis&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== daq17 ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
firefox snap&lt;br /&gt;
imagemagick policy.xml&lt;br /&gt;
gmond.conf&lt;br /&gt;
chrony.conf&lt;br /&gt;
/var/yp/Makefile&lt;br /&gt;
ypserv.conf&lt;br /&gt;
ypserv.securenets&lt;br /&gt;
/etc/default/nis&lt;br /&gt;
50unattended-upgrades&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== daq00 ===&lt;br /&gt;
&lt;br /&gt;
per https://serverpilot.io/docs/how-to-upgrade-ubuntu-20.04-to-22.04/&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
do-release-upgrade -f DistUpgradeViewNonInteractive&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
if it exists &amp;quot;too soon&amp;quot; without doing anything, run it without &amp;quot;-f xxx&amp;quot;, most likely it does not like something about this machine. in case of daq00 it did not like how the EFI partitions were mounted. after fixing it, non-interactive upgrade was successful.&lt;br /&gt;
&lt;br /&gt;
=== isdaq08 ===&lt;br /&gt;
&lt;br /&gt;
* prepare&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/git/scripts&lt;br /&gt;
git pull&lt;br /&gt;
cd ~&lt;br /&gt;
apt -y install debsums&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* check for modified config files that make upgrade unhappy, deal with all files reported by debsums.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@isdaq08:~# debsums -ce&lt;br /&gt;
/etc/ganglia/gmond.conf&lt;br /&gt;
/etc/yp.conf&lt;br /&gt;
/etc/apt/apt.conf.d/10periodic&lt;br /&gt;
root@isdaq08:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* restore original /etc/apt/apt.conf.d/10periodic&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
APT::Periodic::Update-Package-Lists &amp;quot;1&amp;quot;; &lt;br /&gt;
APT::Periodic::Download-Upgradeable-Packages &amp;quot;0&amp;quot;; &lt;br /&gt;
APT::Periodic::AutocleanInterval &amp;quot;0&amp;quot;; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* apt remove ganglia-monitor&lt;br /&gt;
* apt remove nis&lt;br /&gt;
* &amp;quot;debsums -ce&amp;quot; is now empty&lt;br /&gt;
&lt;br /&gt;
Run the upgrade:&lt;br /&gt;
&lt;br /&gt;
* do-release-upgrade -f DistUpgradeViewNonInteractive&lt;br /&gt;
&lt;br /&gt;
Post upgrade:&lt;br /&gt;
&lt;br /&gt;
* configure DNS&lt;br /&gt;
* apt -y install linux-generic-hwe-22.04&lt;br /&gt;
* /bin/cp -v ~/git/scripts/etc/99apt-conf-ko /etc/apt/apt.conf.d/ # restore nightly updates&lt;br /&gt;
* /bin/rm /etc/apt/apt.conf.d/20apt-esm-hook.conf # remove the ubuntu-pro nag&lt;br /&gt;
* install missing packages&lt;br /&gt;
* restore ganglia&lt;br /&gt;
* restore nis&lt;br /&gt;
* check zpool status, may need zpool upgrade&lt;br /&gt;
* reboot&lt;br /&gt;
&lt;br /&gt;
== upgrade U-22 to U-24 ==&lt;br /&gt;
&lt;br /&gt;
generic instructions. below are notes from upgrades of specific machines.&lt;br /&gt;
&lt;br /&gt;
NOTE: at CERN saw installation getting stuck on restart of autofs (automount, rsyslogd 100% CPU, huge /var/log/syslog), stop autofs before upgrade?&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl stop autofs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cleanup zsys&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
maybe: if snap is already removed, remove firefox to prevent snap from reinstalling.&lt;br /&gt;
install non-snap firefox-esr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
remove thunderbird to prevent installation of snap thunderbird in U-24&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mount EFI partition as /boot/efi, otherwise upgrade bombs&lt;br /&gt;
usually mount /dev/sda1 /boot/efi&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
debsums -ce&lt;br /&gt;
apt -y remove desktop-base # causes installer crash&lt;br /&gt;
apt -y remove thunderbird  # avoid forced conversion to snap&lt;br /&gt;
apt update&lt;br /&gt;
apt -y upgrade&lt;br /&gt;
apt -y autoremove&lt;br /&gt;
do-release-upgrade -c      # confirm upgrade will be to U-24&lt;br /&gt;
do-release-upgrade&lt;br /&gt;
# say &amp;quot;y&amp;quot; to all questions&lt;br /&gt;
# after installation starts, accept default answers to all questions&lt;br /&gt;
# should run for about 1 hour or so&lt;br /&gt;
# after upgrade finishes&lt;br /&gt;
apt update&lt;br /&gt;
apt -y upgrade&lt;br /&gt;
apt -y autoremove&lt;br /&gt;
shutdown -r now&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
post upgrade:&lt;br /&gt;
&lt;br /&gt;
* check zpool status, may need zpool upgrade&lt;br /&gt;
* cd /etc/apt/sources.list.d, reenable 3rd party repos (mozilla, google, etc)&lt;br /&gt;
&lt;br /&gt;
if installation bombs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt update&lt;br /&gt;
apt upgrade # will tell us to run &amp;quot;apt --fix-broken install&amp;quot;, do it&lt;br /&gt;
apt --fix-broken install&lt;br /&gt;
apt update&lt;br /&gt;
apt upgrade # should resume the upgrade, will run for a long time&lt;br /&gt;
apt update&lt;br /&gt;
apt upgrade # should do nothing&lt;br /&gt;
apt autoremove&lt;br /&gt;
shutdown -r now&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== daqubuntu, U-24 ===&lt;br /&gt;
&lt;br /&gt;
* prepare&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/git/scripts&lt;br /&gt;
git pull&lt;br /&gt;
cd ~&lt;br /&gt;
apt -y install debsums&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* check for modified config files that make upgrade unhappy, deal with all files reported by debsums.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daqubuntu:~# debsums -ce&lt;br /&gt;
/etc/ganglia/gmond.conf&lt;br /&gt;
debsums: missing file /etc/init.d/nis (from nis package)&lt;br /&gt;
/etc/default/nis&lt;br /&gt;
/etc/ypserv.conf&lt;br /&gt;
/etc/ypserv.securenets&lt;br /&gt;
/var/yp/Makefile&lt;br /&gt;
/etc/update-manager/release-upgrades&lt;br /&gt;
/etc/apt/apt.conf.d/10periodic&lt;br /&gt;
/etc/yp.conf&lt;br /&gt;
root@daqubuntu:~# &lt;br /&gt;
* restore original /etc/apt/apt.conf.d/10periodic&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
APT::Periodic::Update-Package-Lists &amp;quot;1&amp;quot;; &lt;br /&gt;
APT::Periodic::Download-Upgradeable-Packages &amp;quot;0&amp;quot;; &lt;br /&gt;
APT::Periodic::AutocleanInterval &amp;quot;0&amp;quot;; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* apt remove ganglia-monitor&lt;br /&gt;
* apt remove nis&lt;br /&gt;
* apt autoremove&lt;br /&gt;
* restore original release-upgrades: &amp;quot;Prompt: lts&amp;quot;&lt;br /&gt;
* &amp;quot;debsums -ce&amp;quot; is now empty&lt;br /&gt;
&lt;br /&gt;
Check for upgrade:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daqubuntu:~# do-release-upgrade -c&lt;br /&gt;
Checking for a new Ubuntu release&lt;br /&gt;
There is no development version of an LTS available.&lt;br /&gt;
To upgrade to the latest non-LTS development release &lt;br /&gt;
set Prompt=normal in /etc/update-manager/release-upgrades.&lt;br /&gt;
root@daqubuntu:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Run the upgrade:&lt;br /&gt;
&lt;br /&gt;
* do-release-upgrade -f DistUpgradeViewNonInteractive&lt;br /&gt;
&lt;br /&gt;
Post upgrade:&lt;br /&gt;
&lt;br /&gt;
* configure DNS&lt;br /&gt;
* apt -y install linux-generic-hwe-22.04&lt;br /&gt;
* /bin/cp -v ~/git/scripts/etc/99apt-conf-ko /etc/apt/apt.conf.d/ # restore nightly updates&lt;br /&gt;
* /bin/rm /etc/apt/apt.conf.d/20apt-esm-hook.conf # remove the ubuntu-pro nag&lt;br /&gt;
* install missing packages&lt;br /&gt;
* restore ganglia&lt;br /&gt;
* restore nis&lt;br /&gt;
* check zpool status, may need zpool upgrade&lt;br /&gt;
* cd /etc/apt/sources.list.d, reenable 3rd party repos (mozilla, google, etc)&lt;br /&gt;
* reboot&lt;br /&gt;
&lt;br /&gt;
=== daq14, U-20-22-24 ===&lt;br /&gt;
&lt;br /&gt;
* apt update, apt upgrade&lt;br /&gt;
* apt -y install linux-image-generic-hwe-20.04 linux-tools-virtual-hwe-20.04 ### install kernel 5.15&lt;br /&gt;
* shutdown -r now&lt;br /&gt;
* stuck waiting for daq14 to shutdown...&lt;br /&gt;
* reboot into kernel 5.15&lt;br /&gt;
* ???&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/git/scripts&lt;br /&gt;
git pull&lt;br /&gt;
cd ~&lt;br /&gt;
apt -y install debsums&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* debsums -ce&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/etc/apache2/ports.conf&lt;br /&gt;
/etc/dnsmasq.conf&lt;br /&gt;
/etc/ganglia/gmond.conf&lt;br /&gt;
/etc/yp.conf&lt;br /&gt;
/etc/sudoers&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* apache2 restore original ports.conf, uncomment &amp;quot;Listen 80&amp;quot;&lt;br /&gt;
* cp -pv /etc/dnsmasq.conf.dpkg-dist /etc/dnsmasq.conf&lt;br /&gt;
* apt remove ganglia-monitor&lt;br /&gt;
* edit /etc/yp.conf, remove everything after &amp;quot;# ypserver ypserver.network.com&amp;quot;&lt;br /&gt;
* &amp;quot;debsums -ce&amp;quot; is now empty&lt;br /&gt;
* do-release-upgrade -f DistUpgradeViewNonInteractive&lt;br /&gt;
* runs for a long time&lt;br /&gt;
* stuck on &amp;quot;/etc/default/nis&amp;quot;, type &amp;quot;Y&amp;quot;, press enter, nothing for a bit, then resumes running&lt;br /&gt;
* finished&lt;br /&gt;
* configure DNS&lt;br /&gt;
* reboot&lt;br /&gt;
* have kernel 6.8&lt;br /&gt;
* apt update; apt upgrade&lt;br /&gt;
* apt upgrade guile-2.2-libs ### would not auto-update, &amp;quot;kept back&amp;quot;, has to be done by hand&lt;br /&gt;
* apt autoremove&lt;br /&gt;
* debsums -ce&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
debsums: missing file /etc/init.d/nis (from nis package)&lt;br /&gt;
/etc/default/nis&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* diff /etc/default/nis.dpkg-dist  /etc/default/nis&lt;br /&gt;
* cp -pv /etc/default/nis.dpkg-dist  /etc/default/nis&lt;br /&gt;
* debsums -ce&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
debsums: missing file /etc/init.d/nis (from nis package)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* we ignore this and run the update&lt;br /&gt;
* do-release-upgrade -c&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Checking for a new Ubuntu release&lt;br /&gt;
New release &#039;24.04.1 LTS&#039; available.&lt;br /&gt;
Run &#039;do-release-upgrade&#039; to upgrade to it.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* do-release-upgrade -f DistUpgradeViewNonInteractive&lt;br /&gt;
* bombs out without any error messages&lt;br /&gt;
* in /var/log/dist-upgrade/main.log reports &amp;quot;Failed to find a replacement for xapp&amp;quot; and other packages&lt;br /&gt;
* apt remove xapp usrmerge ureadahead thunderbird-gnome-support&lt;br /&gt;
* no go, complains about even more packages.&lt;br /&gt;
* apt list | grep installed | grep -v jammy ### show packages installed from non-ubuntu sources&lt;br /&gt;
* remove all packages marked &amp;quot;install,local&amp;quot; ### ubuntu updater does not know where they came from and so cannot update them.&lt;br /&gt;
* apt remove desktop-base ### not happy about this package in /var/log/dist-upgrade/apt.log&lt;br /&gt;
* apt autoremove&lt;br /&gt;
* do-release-upgrade -f DistUpgradeViewNonInteractive&lt;br /&gt;
* running for a long time...&lt;br /&gt;
&lt;br /&gt;
=== alpha04 U-20-24 ===&lt;br /&gt;
&lt;br /&gt;
* apt update, apt upgrade, apt autoremove&lt;br /&gt;
* reboot into latest kernel (already done)&lt;br /&gt;
* debsums -ce&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@alpha04:~# debsums -ce&lt;br /&gt;
/etc/dnsmasq.conf&lt;br /&gt;
/etc/ganglia/gmond.conf&lt;br /&gt;
/etc/default/nis&lt;br /&gt;
/etc/yp.conf&lt;br /&gt;
root@alpha04:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* move /etc/dnsmasq.conf to /etc/dnsmasq.d/alpha04.conf&lt;br /&gt;
* apt remove dnsmasq&lt;br /&gt;
* apt remove ganglia-monitor&lt;br /&gt;
* apt remove nis&lt;br /&gt;
* apt autoremove&lt;br /&gt;
* debsums -ce ### is now empty&lt;br /&gt;
* do-release-upgrade -f DistUpgradeViewNonInteractive&lt;br /&gt;
* it runs for a long time...&lt;br /&gt;
* complained about /etc/fwupd config files, not sure why...&lt;br /&gt;
* finished&lt;br /&gt;
* apt update, apt upgrade, apt autoremove&lt;br /&gt;
* restore dnsmasq: apt install dnsmasq, systemctl status dnsmasq&lt;br /&gt;
* restore ganglia, per instructions&lt;br /&gt;
* restore NIS: apt -y install rpcbind nis, ypwhich, ypwhich -m&lt;br /&gt;
* zpool upgrade rpool ### also upgrade any other zfs pools, see zpool status&lt;br /&gt;
* remove unwanted packages, per instructions&lt;br /&gt;
* run gonodeinfo&lt;br /&gt;
* reboot&lt;br /&gt;
* done&lt;br /&gt;
&lt;br /&gt;
== vera00 U20-22-24 ==&lt;br /&gt;
&lt;br /&gt;
* everything same as daq14 for U20-22&lt;br /&gt;
* kernel is still 5.15&lt;br /&gt;
* U22-24 is going...&lt;br /&gt;
* stuck for a few minutes on /etc/fwupd config files&lt;br /&gt;
* have kernel 6.8.0-49&lt;br /&gt;
* same steps as daq14&lt;br /&gt;
* reboot&lt;br /&gt;
* same steps as daq14&lt;br /&gt;
* done&lt;br /&gt;
&lt;br /&gt;
== phaarmonster U22-24 ==&lt;br /&gt;
&lt;br /&gt;
* debsums -ce&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/etc/amandahosts&lt;br /&gt;
/etc/apache2/ports.conf&lt;br /&gt;
/etc/ganglia/gmond.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* do-release-upgrade -c ### reports U24.04.1&lt;br /&gt;
* do-release-upgrade -f DistUpgradeViewNonInteractive ### bombs&lt;br /&gt;
* apt remove desktop-base; apt autoremove&lt;br /&gt;
* do-release-upgrade ### (interactive) runs ok&lt;br /&gt;
* bombed !!!&lt;br /&gt;
* apt upgrade spews errors and tells us to run &amp;quot;apt --fix-broken install&amp;quot;&lt;br /&gt;
* apt --fix-broken install ### runs&lt;br /&gt;
* bombs with thunderbird snap errors&lt;br /&gt;
* again... no go&lt;br /&gt;
* thunderbird snap complains about mounting /home, but /home is a symlink&lt;br /&gt;
* rm /home, mkdir /home&lt;br /&gt;
* again, runs ok&lt;br /&gt;
* asks about /etc/fwupd/fwupd.conf - say &amp;quot;Y&amp;quot; to install updated package version&lt;br /&gt;
* apt install completes&lt;br /&gt;
* apt update; apt upgrade ### running for a long time...&lt;br /&gt;
* finished&lt;br /&gt;
* install missing packages, etc&lt;br /&gt;
* reboot&lt;br /&gt;
* long wait... came back&lt;br /&gt;
* DNS does now work, systemd-resolved missing, apt install systemd-resolved, &amp;quot;configure DNS&amp;quot;&lt;br /&gt;
* done.&lt;br /&gt;
&lt;br /&gt;
== isdaq10 U22-24 ==&lt;br /&gt;
&lt;br /&gt;
* do-release-upgrade -f DistUpgradeViewNonInteractive&lt;br /&gt;
* bombed on desktop-base, &amp;quot;apt remove desktop-base; apt autoremove&amp;quot;&lt;br /&gt;
* bombed with errors&lt;br /&gt;
* running &amp;quot;apt --fix-broken install&amp;quot;&lt;br /&gt;
* complained about thunderbird snap&lt;br /&gt;
* complained about /etc/fwupd/fwupd.conf (say Y)&lt;br /&gt;
* finished ok&lt;br /&gt;
* apt update&lt;br /&gt;
* apt upgrade ### reports &amp;quot;1382 upgraded, 140 newly installed, 0 to remove and 29 not upgraded&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== iris01 ==&lt;br /&gt;
&lt;br /&gt;
* debsums -ce&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/etc/ganglia/gmond.conf&lt;br /&gt;
/etc/default/nis&lt;br /&gt;
/etc/yp.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* apt remove desktop-base&lt;br /&gt;
* apt remove thunderbird&lt;br /&gt;
* apt autoremove&lt;br /&gt;
* do-release-upgrade -f DistUpgradeViewNonInteractive&lt;br /&gt;
* bombed with dpkg errors:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
hplip wants wrong python&lt;br /&gt;
ganglia-monitor wants wrong libapr1&lt;br /&gt;
sssd-ad wants bunch of wrong libraries&lt;br /&gt;
xemacs21-mule&lt;br /&gt;
libnfsidmap1 wants libldap2&lt;br /&gt;
adn so forth...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* apt --fix-broken install -y&lt;br /&gt;
* bombs on ganglia - ganglia group absent from /etc/groups&lt;br /&gt;
* fix group ganglia by hand, remove ganglia group from NIS on isdaq00&lt;br /&gt;
* apt --fix-broken install&lt;br /&gt;
* apt upgrade&lt;br /&gt;
&lt;br /&gt;
== iris00 ==&lt;br /&gt;
&lt;br /&gt;
* stuck on &amp;quot;autofs: restarting&amp;quot;, login as root, kill iris midas, kill automount, systemctl restart autofs, noble got unstuck, ctrl-c systemctl restart autofs&lt;br /&gt;
* noble running...&lt;br /&gt;
* bombed with dpkg errors&lt;br /&gt;
* check ganglia user, group - both ok&lt;br /&gt;
* apt --fix-broken install&lt;br /&gt;
* apt upgrade&lt;br /&gt;
&lt;br /&gt;
== tigstore01 ==&lt;br /&gt;
&lt;br /&gt;
* no bomb-out&lt;br /&gt;
&lt;br /&gt;
== midm9b ==&lt;br /&gt;
&lt;br /&gt;
* apt remove desktop-base thunderbird&lt;br /&gt;
* bombed&lt;br /&gt;
* apt --fix-broken-install&lt;br /&gt;
* apt upgrade&lt;br /&gt;
&lt;br /&gt;
= Upgrade to new version of Debian =&lt;br /&gt;
&lt;br /&gt;
https://www.debian.org/releases/bookworm/amd64/release-notes/ch-upgrading.en.html&lt;br /&gt;
&lt;br /&gt;
== 32-bit VME processor Debian 11 to 12 to 13 ==&lt;br /&gt;
&lt;br /&gt;
* cd git/scripts; git pull; cd ~&lt;br /&gt;
* apt update&lt;br /&gt;
* apt upgrade&lt;br /&gt;
* edit /etc/apt/sources.list&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
deb http://deb.debian.org/debian/ trixie main&lt;br /&gt;
#deb http://deb.debian.org/debian/ bookworm main&lt;br /&gt;
#deb http://deb.debian.org/debian/ bullseye main&lt;br /&gt;
#deb http://deb.debian.org/debian/ buster main&lt;br /&gt;
#deb-src http://deb.debian.org/debian/ bullseye main&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* apt update&lt;br /&gt;
* apt upgrade --without-new-pkgs&lt;br /&gt;
* apt full-upgrade&lt;br /&gt;
* apt list &#039;~c&#039;; apt purge &#039;~c&#039; # purge left-over config files [residual-config]&lt;br /&gt;
* reboot&lt;br /&gt;
&lt;br /&gt;
= Ubuntu package manager =&lt;br /&gt;
&lt;br /&gt;
* apt-get install xxx # install package xxx&lt;br /&gt;
* apt-get update&lt;br /&gt;
* apt-get upgrade&lt;br /&gt;
* apt-get dist-upgrade&lt;br /&gt;
* apt-get autoremove # remove automatically installed packages required by a removed package&lt;br /&gt;
* apt-get remove xxx # remove package xxx&lt;br /&gt;
* apt-cache search . # list all available packages&lt;br /&gt;
* apt-cache show &amp;quot;.&amp;quot; | grep ^Package # list al available packages&lt;br /&gt;
* apt-cache madison root-system # show all available versions of package root-system&lt;br /&gt;
* apt list # list all installed packages&lt;br /&gt;
* dpkg --listfiles libpng16-16 # list all files from this package&lt;br /&gt;
* apt list --installed # list all installed packages&lt;br /&gt;
* dpkg -S /bin/bash # what package provides this file?&lt;br /&gt;
* dpkg -L bash # what files provided by this package?&lt;br /&gt;
* debsums -ce # show modified config files&lt;br /&gt;
* apt-config dump # show apt configuration&lt;br /&gt;
* apt purge &#039;~c&#039; # purge all [residual-config] packages&lt;br /&gt;
* ls -l /var/lib/dpkg/info/ # show post-install scripts&lt;br /&gt;
&lt;br /&gt;
= Ubuntu zsys =&lt;br /&gt;
&lt;br /&gt;
NOTE: DO NOT USE ZSYS, see https://github.com/ubuntu/zsys/issues/218 and https://github.com/ubuntu/zsys/issues/230&lt;br /&gt;
&lt;br /&gt;
* scripted removal of old snapshots (replace &amp;quot;echo zfs destroy&amp;quot; with &amp;quot;zfs destroy&amp;quot;)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs list -t all | cut -f1 -d &amp;quot; &amp;quot; | grep autozsys | xargs -n1 echo zfs destroy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* manual removal of old snapshots&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zsysctl show&lt;br /&gt;
zsysctl state remove xy69ye -s&lt;br /&gt;
zsysctl state remove xy69ye&lt;br /&gt;
zsysctl state remove xy69ye -u wheel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* apt remove zsys&lt;br /&gt;
&lt;br /&gt;
NOTE: old zsys snapshots must be cleaned manually, &amp;quot;zsysctl state remove xxx --system&amp;quot; is broken and does not remove user data snapshots&lt;br /&gt;
&lt;br /&gt;
* manages system snapshots&lt;br /&gt;
* documentation: https://github.com/ubuntu/zsys&lt;br /&gt;
* documentation: (go to next article via link &amp;quot;newer&amp;quot; at the bottom) https://didrocks.fr/2020/05/21/zfs-focus-on-ubuntu-20.04-lts-whats-new/&lt;br /&gt;
* ubuntu 20.04 bug, too many snapshots cause /boot to become full and updates fail. https://github.com/ubuntu/zsys/issues/155&lt;br /&gt;
* solution: use custom /etc/zsys.conf, limit number of snapshots to 10, see trinatdaq:/etc/zsys.conf&lt;br /&gt;
* zsys commands:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
update-grub # list of all snapshots, errors if some snapshots are broken&lt;br /&gt;
zsysctl state remove lnc0k7 --system # remove snapshot&lt;br /&gt;
xemacs -nw /etc/zsys.conf; zsysctl service reload; zsysctl service gc # cause gc to run with new settings in zsys.conf&lt;br /&gt;
zfs list -r -t snapshot -o name,used,referenced,creation bpool/BOOT # list snapshots&lt;br /&gt;
zsysctl show # show snapshots&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Ubuntu cloning =&lt;br /&gt;
&lt;br /&gt;
to clone a ubuntu image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /nfsroot/lxcpet&lt;br /&gt;
emacs -nw etc/hostname ### change hostname&lt;br /&gt;
emacs -nw etc/mailname ### change hostname (debian 11)&lt;br /&gt;
emacs -nw etc/defaultdomain ### change the NIS domainname&lt;br /&gt;
emacs -nw etc/yp.conf ### change the NIS server&lt;br /&gt;
cp -pvf ../lxcpet-SL610/etc/ssh/*key* etc/ssh/ ### preserve the ssh keys&lt;br /&gt;
emacs -nw opt/gonodeinfo/gonodeinfo.conf ### update information&lt;br /&gt;
emacs -nw root/.ssh/authorized_keys ### update root ssh keys&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Ubuntu boot loader =&lt;br /&gt;
&lt;br /&gt;
== maintenance commands ==&lt;br /&gt;
&lt;br /&gt;
* update-initramfs -v -u&lt;br /&gt;
* grub-install /dev/sda&lt;br /&gt;
&lt;br /&gt;
= Convert from single to dual mirrored ZFS SSD =&lt;br /&gt;
&lt;br /&gt;
Assuming Ubuntu LTS 22.04 with &amp;quot;instal on ZFS&amp;quot; option, we will&lt;br /&gt;
add a second SSD, configure ZFS to use both SSDs in mirrored&lt;br /&gt;
configuration and setup grub to boot from either SSD. This&lt;br /&gt;
is intended to create a full redundant system where failure&lt;br /&gt;
of either SSD does not break the system.&lt;br /&gt;
&lt;br /&gt;
== partition ==&lt;br /&gt;
&lt;br /&gt;
* identify first SSD&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@midm9b:~# ./smart-status.perl &lt;br /&gt;
        Disk                    model               serial     temperature  realloc  pending   uncorr  CRC err     RRER Errors     Link&lt;br /&gt;
    /dev/sda  WD Blue SA510 2.5 250GB         22243Z803769              24        .        ?        ?        .        ?        .      6.0&lt;br /&gt;
root@midm9b:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* connect second SSD of identical size&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@midm9b:~# ./smart-status.perl &lt;br /&gt;
        Disk                    model               serial     temperature  realloc  pending   uncorr  CRC err     RRER   Errors     Link&lt;br /&gt;
    /dev/sda  WD Blue SA510 2.5 250GB         22243Z803769              24        .        ?        ?        .        ?        .      6.0&lt;br /&gt;
    /dev/sdb  WD Blue SA510 2.5 250GB         22243Z803852              25        .        ?        ?        .        ?        .      6.0&lt;br /&gt;
root@midm9b:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* if second SSD is not autodetected, reboot&lt;br /&gt;
* Clone partition table automatically&lt;br /&gt;
If both SSDs are identical size, use this simpler method of duplicating the partition table:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@midm9b:~# sfdisk -d /dev/sda &amp;gt; part_table&lt;br /&gt;
root@midm9b:~# grep -v ^label-id part_table | sed -e &#039;s/, *uuid=[0-9A-F-]*//&#039; | sfdisk /dev/sdb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The grep and sed in the second command are there to prevent disk ID and partition IDs from being cloned. Alternatively the part_table file can be edited manually to remove the label-id line and the uuid entries from the individual partitions.&lt;br /&gt;
&lt;br /&gt;
* Clone partition table manually (e.g. for different size disks)&lt;br /&gt;
* list partition table of first SSD:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@midm9b:~# fdisk -l /dev/sda&lt;br /&gt;
Disk /dev/sda: 232.89 GiB, 250059350016 bytes, 488397168 sectors&lt;br /&gt;
Disk model: WD Blue SA510 2.&lt;br /&gt;
Units: sectors of 1 * 512 = 512 bytes&lt;br /&gt;
Sector size (logical/physical): 512 bytes / 512 bytes&lt;br /&gt;
I/O size (minimum/optimal): 512 bytes / 512 bytes&lt;br /&gt;
Disklabel type: gpt&lt;br /&gt;
Disk identifier: 951A4174-B4C6-400D-99F5-BE9B5627FA8E&lt;br /&gt;
&lt;br /&gt;
Device       Start       End   Sectors   Size Type&lt;br /&gt;
/dev/sda1     2048   1050623   1048576   512M EFI System&lt;br /&gt;
/dev/sda2  1050624   5244927   4194304     2G Linux swap&lt;br /&gt;
/dev/sda3  5244928   9439231   4194304     2G Solaris boot&lt;br /&gt;
/dev/sda4  9439232 488397134 478957903 228.4G Solaris root&lt;br /&gt;
root@midm9b:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* create identical partitions on second SSD, use sector numbers from above.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@midm9b:~# gdisk /dev/sdb&lt;br /&gt;
GPT fdisk (gdisk) version 1.0.8&lt;br /&gt;
&lt;br /&gt;
Partition table scan:&lt;br /&gt;
  MBR: not present&lt;br /&gt;
  BSD: not present&lt;br /&gt;
  APM: not present&lt;br /&gt;
  GPT: not present&lt;br /&gt;
&lt;br /&gt;
Creating new GPT entries in memory.&lt;br /&gt;
&lt;br /&gt;
Command (? for help): n&lt;br /&gt;
Partition number (1-128, default 1): &lt;br /&gt;
First sector (34-488397134, default = 2048) or {+-}size{KMGTP}: &lt;br /&gt;
Last sector (2048-488397134, default = 488397134) or {+-}size{KMGTP}: 1050623&lt;br /&gt;
Current type is 8300 (Linux filesystem)&lt;br /&gt;
Hex code or GUID (L to show codes, Enter = 8300): ef00&lt;br /&gt;
Changed type of partition to &#039;EFI system partition&#039;&lt;br /&gt;
&lt;br /&gt;
Command (? for help): n&lt;br /&gt;
Partition number (2-128, default 2): &lt;br /&gt;
First sector (34-488397134, default = 1050624) or {+-}size{KMGTP}: &lt;br /&gt;
Last sector (1050624-488397134, default = 488397134) or {+-}size{KMGTP}: 5244927&lt;br /&gt;
Current type is 8300 (Linux filesystem)&lt;br /&gt;
Hex code or GUID (L to show codes, Enter = 8300): 8200&lt;br /&gt;
Changed type of partition to &#039;Linux swap&#039;&lt;br /&gt;
&lt;br /&gt;
Command (? for help): n&lt;br /&gt;
Partition number (3-128, default 3): &lt;br /&gt;
First sector (34-488397134, default = 5244928) or {+-}size{KMGTP}: &lt;br /&gt;
Last sector (5244928-488397134, default = 488397134) or {+-}size{KMGTP}: 9439231&lt;br /&gt;
Current type is 8300 (Linux filesystem)&lt;br /&gt;
Hex code or GUID (L to show codes, Enter = 8300): be00&lt;br /&gt;
Changed type of partition to &#039;Solaris boot&#039;&lt;br /&gt;
&lt;br /&gt;
Command (? for help): n&lt;br /&gt;
Partition number (4-128, default 4): &lt;br /&gt;
First sector (34-488397134, default = 9439232) or {+-}size{KMGTP}: &lt;br /&gt;
Last sector (9439232-488397134, default = 488397134) or {+-}size{KMGTP}: &lt;br /&gt;
Current type is 8300 (Linux filesystem)&lt;br /&gt;
Hex code or GUID (L to show codes, Enter = 8300): bf00&lt;br /&gt;
Changed type of partition to &#039;Solaris root&#039;&lt;br /&gt;
&lt;br /&gt;
Command (? for help): w&lt;br /&gt;
&lt;br /&gt;
Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING&lt;br /&gt;
PARTITIONS!!&lt;br /&gt;
&lt;br /&gt;
Do you want to proceed? (Y/N): y&lt;br /&gt;
OK; writing new GUID partition table (GPT) to /dev/sdb.&lt;br /&gt;
The operation has completed successfully.&lt;br /&gt;
root@midm9b:~# fdisk -l /dev/sda /dev/sdb&lt;br /&gt;
Disk /dev/sda: 232.89 GiB, 250059350016 bytes, 488397168 sectors&lt;br /&gt;
Disk model: WD Blue SA510 2.&lt;br /&gt;
Units: sectors of 1 * 512 = 512 bytes&lt;br /&gt;
Sector size (logical/physical): 512 bytes / 512 bytes&lt;br /&gt;
I/O size (minimum/optimal): 512 bytes / 512 bytes&lt;br /&gt;
Disklabel type: gpt&lt;br /&gt;
Disk identifier: 951A4174-B4C6-400D-99F5-BE9B5627FA8E&lt;br /&gt;
&lt;br /&gt;
Device       Start       End   Sectors   Size Type&lt;br /&gt;
/dev/sda1     2048   1050623   1048576   512M EFI System&lt;br /&gt;
/dev/sda2  1050624   5244927   4194304     2G Linux swap&lt;br /&gt;
/dev/sda3  5244928   9439231   4194304     2G Solaris boot&lt;br /&gt;
/dev/sda4  9439232 488397134 478957903 228.4G Solaris root&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Disk /dev/sdb: 232.89 GiB, 250059350016 bytes, 488397168 sectors&lt;br /&gt;
Disk model: WD Blue SA510 2.&lt;br /&gt;
Units: sectors of 1 * 512 = 512 bytes&lt;br /&gt;
Sector size (logical/physical): 512 bytes / 512 bytes&lt;br /&gt;
I/O size (minimum/optimal): 512 bytes / 512 bytes&lt;br /&gt;
Disklabel type: gpt&lt;br /&gt;
Disk identifier: EB251739-30C6-422F-A505-5887B5A0B603&lt;br /&gt;
&lt;br /&gt;
Device       Start       End   Sectors   Size Type&lt;br /&gt;
/dev/sdb1     2048   1050623   1048576   512M EFI System&lt;br /&gt;
/dev/sdb2  1050624   5244927   4194304     2G Linux swap&lt;br /&gt;
/dev/sdb3  5244928   9439231   4194304     2G Solaris boot&lt;br /&gt;
/dev/sdb4  9439232 488397134 478957903 228.4G Solaris root&lt;br /&gt;
root@midm9b:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== update ZFS pools ==&lt;br /&gt;
&lt;br /&gt;
* identify second SSD partitions&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@midm9b:~# ls -l /dev/disk/by-id/ata*part2&lt;br /&gt;
lrwxrwxrwx 1 root root 10 Jan 20 18:37 /dev/disk/by-id/ata-WD_Blue_SA510_2.5_250GB_22243Z803769-part2 -&amp;gt; ../../sda2&lt;br /&gt;
lrwxrwxrwx 1 root root 10 Jan 20 19:34 /dev/disk/by-id/ata-WD_Blue_SA510_2.5_250GB_22243Z803852-part2 -&amp;gt; ../../sdb2&lt;br /&gt;
root@midm9b:~# ls -l /dev/disk/by-id/ata*part4&lt;br /&gt;
lrwxrwxrwx 1 root root 10 Jan 20 18:37 /dev/disk/by-id/ata-WD_Blue_SA510_2.5_250GB_22243Z803769-part4 -&amp;gt; ../../sda4&lt;br /&gt;
lrwxrwxrwx 1 root root 10 Jan 20 19:34 /dev/disk/by-id/ata-WD_Blue_SA510_2.5_250GB_22243Z803852-part4 -&amp;gt; ../../sdb4&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* convert bpool from single disk to mirrored disk:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@midm9b:~# zpool status&lt;br /&gt;
  pool: bpool&lt;br /&gt;
 state: ONLINE&lt;br /&gt;
config:&lt;br /&gt;
&lt;br /&gt;
	NAME                                    STATE     READ WRITE CKSUM&lt;br /&gt;
	bpool                                   ONLINE       0     0     0&lt;br /&gt;
	  99e03dc0-7d4d-f24b-8fa1-f042b9f135db  ONLINE       0     0     0&lt;br /&gt;
&lt;br /&gt;
errors: No known data errors&lt;br /&gt;
&lt;br /&gt;
  pool: rpool&lt;br /&gt;
 state: ONLINE&lt;br /&gt;
config:&lt;br /&gt;
&lt;br /&gt;
	NAME                                    STATE     READ WRITE CKSUM&lt;br /&gt;
	rpool                                   ONLINE       0     0     0&lt;br /&gt;
	  f6fd54f8-3af7-b943-ae3d-a4e480537fb9  ONLINE       0     0     0&lt;br /&gt;
&lt;br /&gt;
errors: No known data errors&lt;br /&gt;
root@midm9b:~# zpool attach bpool 99e03dc0-7d4d-f24b-8fa1-f042b9f135db /dev/disk/by-id/ata-WD_Blue_SA510_2.5_250GB_22243Z803852-part3&lt;br /&gt;
root@midm9b:~# zpool status bpool&lt;br /&gt;
  pool: bpool&lt;br /&gt;
 state: ONLINE&lt;br /&gt;
  scan: resilvered 247M in 00:00:00 with 0 errors on Fri Jan 20 19:39:40 2023&lt;br /&gt;
config:&lt;br /&gt;
&lt;br /&gt;
	NAME                                                STATE     READ WRITE CKSUM&lt;br /&gt;
	bpool                                               ONLINE       0     0     0&lt;br /&gt;
	  mirror-0                                          ONLINE       0     0     0&lt;br /&gt;
	    99e03dc0-7d4d-f24b-8fa1-f042b9f135db            ONLINE       0     0     0&lt;br /&gt;
	    ata-WD_Blue_SA510_2.5_250GB_22243Z803852-part3  ONLINE       0     0     0&lt;br /&gt;
&lt;br /&gt;
errors: No known data errors&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* convert rpool&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@midm9b:~# ls -l /dev/disk/by-id/ata*part4&lt;br /&gt;
lrwxrwxrwx 1 root root 10 Jan 20 18:37 /dev/disk/by-id/ata-WD_Blue_SA510_2.5_250GB_22243Z803769-part4 -&amp;gt; ../../sda4&lt;br /&gt;
lrwxrwxrwx 1 root root 10 Jan 20 19:34 /dev/disk/by-id/ata-WD_Blue_SA510_2.5_250GB_22243Z803852-part4 -&amp;gt; ../../sdb4&lt;br /&gt;
root@midm9b:~# zpool attach rpool f6fd54f8-3af7-b943-ae3d-a4e480537fb9 /dev/disk/by-id/ata-WD_Blue_SA510_2.5_250GB_22243Z803852-part4&lt;br /&gt;
root@midm9b:~# zpool status rpool&lt;br /&gt;
  pool: rpool&lt;br /&gt;
 state: ONLINE&lt;br /&gt;
status: One or more devices is currently being resilvered.  The pool will&lt;br /&gt;
	continue to function, possibly in a degraded state.&lt;br /&gt;
action: Wait for the resilver to complete.&lt;br /&gt;
  scan: resilver in progress since Fri Jan 20 19:40:45 2023&lt;br /&gt;
	5.83G scanned at 664M/s, 2.92M issued at 332K/s, 9.11G total&lt;br /&gt;
	0B resilvered, 0.03% done, no estimated completion time&lt;br /&gt;
config:&lt;br /&gt;
&lt;br /&gt;
	NAME                                                STATE     READ WRITE CKSUM&lt;br /&gt;
	rpool                                               ONLINE       0     0     0&lt;br /&gt;
	  mirror-0                                          ONLINE       0     0     0&lt;br /&gt;
	    f6fd54f8-3af7-b943-ae3d-a4e480537fb9            ONLINE       0     0     0&lt;br /&gt;
	    ata-WD_Blue_SA510_2.5_250GB_22243Z803852-part4  ONLINE       0     0     0&lt;br /&gt;
&lt;br /&gt;
errors: No known data errors&lt;br /&gt;
root@midm9b:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* wait for resilver to complete&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@midm9b:~# zpool status&lt;br /&gt;
  pool: bpool&lt;br /&gt;
 state: ONLINE&lt;br /&gt;
  scan: resilvered 247M in 00:00:00 with 0 errors on Fri Jan 20 19:39:40 2023&lt;br /&gt;
config:&lt;br /&gt;
&lt;br /&gt;
	NAME                                                STATE     READ WRITE CKSUM&lt;br /&gt;
	bpool                                               ONLINE       0     0     0&lt;br /&gt;
	  mirror-0                                          ONLINE       0     0     0&lt;br /&gt;
	    99e03dc0-7d4d-f24b-8fa1-f042b9f135db            ONLINE       0     0     0&lt;br /&gt;
	    ata-WD_Blue_SA510_2.5_250GB_22243Z803852-part3  ONLINE       0     0     0&lt;br /&gt;
&lt;br /&gt;
errors: No known data errors&lt;br /&gt;
&lt;br /&gt;
  pool: rpool&lt;br /&gt;
 state: ONLINE&lt;br /&gt;
  scan: resilvered 9.65G in 00:00:36 with 0 errors on Fri Jan 20 19:41:21 2023&lt;br /&gt;
config:&lt;br /&gt;
&lt;br /&gt;
	NAME                                                STATE     READ WRITE CKSUM&lt;br /&gt;
	rpool                                               ONLINE       0     0     0&lt;br /&gt;
	  mirror-0                                          ONLINE       0     0     0&lt;br /&gt;
	    f6fd54f8-3af7-b943-ae3d-a4e480537fb9            ONLINE       0     0     0&lt;br /&gt;
	    ata-WD_Blue_SA510_2.5_250GB_22243Z803852-part4  ONLINE       0     0     0&lt;br /&gt;
&lt;br /&gt;
errors: No known data errors&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== update boot loader ==&lt;br /&gt;
&lt;br /&gt;
INSTALL SYSLINUX: https://daq00.triumf.ca/DaqWiki/index.php/Ubuntu#EFI_boot_using_syslinux&lt;br /&gt;
&lt;br /&gt;
DO *NOT* DO THE FOLOWING:&lt;br /&gt;
&lt;br /&gt;
* create and mount EFI partitions:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@midm9b:~# mkfs.msdos /dev/sdb1&lt;br /&gt;
root@midm9b:~# mkdir /boot/efi-sda&lt;br /&gt;
root@midm9b:~# mkdir /boot/efi-sdb&lt;br /&gt;
root@midm20c:~# blkid | grep vfat ### identify UUID&lt;br /&gt;
/dev/sdb1: UUID=&amp;quot;DD89-5081&amp;quot; BLOCK_SIZE=&amp;quot;512&amp;quot; TYPE=&amp;quot;vfat&amp;quot; PARTLABEL=&amp;quot;EFI System Partition&amp;quot; PARTUUID=&amp;quot;d0cb6be4-2f67-5b42-9b26-9e6905e9f774&amp;quot;&lt;br /&gt;
/dev/sdc1: UUID=&amp;quot;D970-86BA&amp;quot; BLOCK_SIZE=&amp;quot;512&amp;quot; TYPE=&amp;quot;vfat&amp;quot; PARTLABEL=&amp;quot;EFI System Partition&amp;quot; PARTUUID=&amp;quot;e6d3b5b9-a512-44a2-9205-1a4db06ed2a2&amp;quot;&lt;br /&gt;
/dev/sda1: UUID=&amp;quot;DDA1-044C&amp;quot; BLOCK_SIZE=&amp;quot;512&amp;quot; TYPE=&amp;quot;vfat&amp;quot; PARTLABEL=&amp;quot;EFI System Partition&amp;quot; PARTUUID=&amp;quot;6dc9dff0-1c13-8045-a906-7803d3074c70&amp;quot;&lt;br /&gt;
root@midm20c:~# cat /etc/fstab | grep vfat ### add mount points with correct UUID&lt;br /&gt;
#UUID=D970-86BA  /boot/efi       vfat    umask=0022,fmask=0022,dmask=0022      0       1&lt;br /&gt;
UUID=DDA1-044C  /boot/efi-sda       vfat    umask=0022,fmask=0022,dmask=0022      0       1&lt;br /&gt;
UUID=DD89-5081  /boot/efi-sdb       vfat    umask=0022,fmask=0022,dmask=0022      0       1&lt;br /&gt;
root@midm9b:~# mount -a&lt;br /&gt;
root@midm9b:~# df -kl&lt;br /&gt;
Filesystem                                       1K-blocks    Used Available Use% Mounted on&lt;br /&gt;
...&lt;br /&gt;
/dev/sda1                                           523244   13720    509524   3% /boot/efi&lt;br /&gt;
/dev/sdb1                                           523244       4    523240   1% /boot/efi-sdb&lt;br /&gt;
...&lt;br /&gt;
root@midm9b:~# rsync -av /boot/efi/ /boot/efi-sdb/&lt;br /&gt;
sending incremental file list&lt;br /&gt;
EFI/&lt;br /&gt;
...&lt;br /&gt;
root@midm9b:~# ls -l /boot/efi-sda&lt;br /&gt;
total 8&lt;br /&gt;
drwxr-xr-x 4 root root 4096 Jan 19 23:26 EFI&lt;br /&gt;
drwxr-xr-x 5 root root 4096 Jan 19 23:26 grub&lt;br /&gt;
root@midm9b:~# ls -l /boot/efi-sdb&lt;br /&gt;
total 8&lt;br /&gt;
drwxr-xr-x 4 root root 4096 Jan 19 23:26 EFI&lt;br /&gt;
drwxr-xr-x 5 root root 4096 Jan 19 23:26 grub&lt;br /&gt;
root@midm9b:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* add systemd &amp;quot;nofail&amp;quot; flag to /etc/fstab, without this, systemd will stop booting if one SSD is missing&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
daq00:~$ cat /etc/fstab | grep vfat&lt;br /&gt;
#UUID=31A7-24BE  /boot/efi       vfat    umask=0022,fmask=0022,dmask=0022      0       1&lt;br /&gt;
/dev/sda1 /boot/efi-sda       vfat    umask=0022,fmask=0022,dmask=0022,nofail      0       1&lt;br /&gt;
/dev/sdb1 /boot/efi-sdb       vfat    umask=0022,fmask=0022,dmask=0022,nofail      0       1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* setup script to update grub on second SSD, it must be run manually after every kernel update&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@midm9b:~# ln -s ~/git/scripts/etc/update_efi_grub.perl ~/&lt;br /&gt;
root@midm9b:~# ~/update_efi_grub.perl -u&lt;br /&gt;
EFI dir: /boot/efi-sda&lt;br /&gt;
/boot/efi-sda: update grub: rsync  -av --delete-after --modify-window=2 /boot/efi/grub/ /boot/efi-sda/grub&lt;br /&gt;
building file list ... done&lt;br /&gt;
&lt;br /&gt;
sent 5,313 bytes  received 11 bytes  10,648.00 bytes/sec&lt;br /&gt;
total size is 7,944,644  speedup is 1,492.23&lt;br /&gt;
/boot/efi-sda: update efi:  rsync  -av --delete-after --modify-window=2 /boot/efi/EFI/  /boot/efi-sda/EFI&lt;br /&gt;
building file list ... done&lt;br /&gt;
&lt;br /&gt;
sent 216 bytes  received 11 bytes  454.00 bytes/sec&lt;br /&gt;
total size is 5,452,378  speedup is 24,019.29&lt;br /&gt;
EFI dir: /boot/efi-sdb&lt;br /&gt;
/boot/efi-sdb: update grub: rsync  -av --delete-after --modify-window=2 /boot/efi/grub/ /boot/efi-sdb/grub&lt;br /&gt;
building file list ... done&lt;br /&gt;
&lt;br /&gt;
sent 5,313 bytes  received 11 bytes  10,648.00 bytes/sec&lt;br /&gt;
total size is 7,944,644  speedup is 1,492.23&lt;br /&gt;
/boot/efi-sdb: update efi:  rsync  -av --delete-after --modify-window=2 /boot/efi/EFI/  /boot/efi-sdb/EFI&lt;br /&gt;
building file list ... done&lt;br /&gt;
&lt;br /&gt;
sent 216 bytes  received 11 bytes  454.00 bytes/sec&lt;br /&gt;
total size is 5,452,378  speedup is 24,019.29&lt;br /&gt;
root@midm9b:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Disable NetworkManager =&lt;br /&gt;
&lt;br /&gt;
== Debian-12 ==&lt;br /&gt;
&lt;br /&gt;
* use netplan, https://www.debian.org/doc/manuals/debian-reference/ch05.en.html#_the_modern_network_configuration_for_cloud&lt;br /&gt;
* apt install netplan.io&lt;br /&gt;
* systemctl enable systemd-networkd&lt;br /&gt;
* systemctl restart systemd-networkd&lt;br /&gt;
* create /etc/netplan/50-dhcp.yaml&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
network:&lt;br /&gt;
  version: 2&lt;br /&gt;
  ethernets:&lt;br /&gt;
    all-en:&lt;br /&gt;
      match:&lt;br /&gt;
        name: &amp;quot;en*&amp;quot;&lt;br /&gt;
      dhcp4: true&lt;br /&gt;
      dhcp6: true&lt;br /&gt;
      ignore-carrier: true ### do not drop IP address if network link drops&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* netplan apply&lt;br /&gt;
* netplan try&lt;br /&gt;
* ifconfig -a ### to check IP address settings&lt;br /&gt;
* netstat -rn ### to check default route&lt;br /&gt;
* cat /etc/resolv.conf ### to check DNS&lt;br /&gt;
* ls -l /run/systemd/netif/leases ### systemd-networkd dhcp leases&lt;br /&gt;
* NOTE: without &amp;quot;ignore-carrier&amp;quot; it will drop the IP address if network link drops, re-do dhcp when links comes back&lt;br /&gt;
* NOTE: wait-network-online will wait for all interfaces to get an IP address&lt;br /&gt;
&lt;br /&gt;
== Ubuntu-20 ==&lt;br /&gt;
&lt;br /&gt;
NOTE: THIS IS BROKEN IN UBUNTU LTS 22.04&lt;br /&gt;
&lt;br /&gt;
NetworkManager is useful for configuring dynamic&lt;br /&gt;
network interfaces, i.e. laptops that often move&lt;br /&gt;
between networks, or connect to multiple choice&lt;br /&gt;
of wifi networks, etc.&lt;br /&gt;
&lt;br /&gt;
For machines with statically configured network interfaces,&lt;br /&gt;
NetworkManager is not necessary.&lt;br /&gt;
&lt;br /&gt;
As it has been observed to become confused and observed&lt;br /&gt;
to malfunction when network links go up and down (it keeps&lt;br /&gt;
unnecessarily reconfiguring the ip address, etc), it can&lt;br /&gt;
be usefuil to disable it.&lt;br /&gt;
&lt;br /&gt;
* list all network interfaces&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# /bin/ls -1 /sys/class/net/&lt;br /&gt;
enp0s31f6&lt;br /&gt;
lo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* edit /etc/network/interfaces:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rename enp0s31f6=eth0&lt;br /&gt;
auto eth0&lt;br /&gt;
iface eth0 inet static&lt;br /&gt;
   address 142.90.120.94/19&lt;br /&gt;
   gateway 142.90.100.18&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* statically configure systemd-resolved&lt;br /&gt;
** create /etc/systemd/resolved.conf.d/resolved.conf with this contents:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Resolve]&lt;br /&gt;
DNS=142.90.100.19&lt;br /&gt;
Domains=triumf.ca&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
** systemctl restart systemd-resolved&lt;br /&gt;
** resolvectl&lt;br /&gt;
** systemd-analyze cat-config systemd/resolved.conf&lt;br /&gt;
* disable NetworkManager&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl disable NetworkManager&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* reboot&lt;br /&gt;
&lt;br /&gt;
== U-22, U-24 ifup-ko ==&lt;br /&gt;
&lt;br /&gt;
Network configuration of modern linux is confused. There are at least 3 configuration methods, each with different shortcomings:&lt;br /&gt;
* the old ifup method is barely documented&lt;br /&gt;
* NetworkManager is well documented and tooled, but sometimes does strange things&lt;br /&gt;
* systemd-networkd is mysterious, and likely to do strange stuff, like all systemd stuff&lt;br /&gt;
* netplan is the latest method, configuration is simple but uses NetworkManager or systemd-networkd as backend.&lt;br /&gt;
&lt;br /&gt;
This is a solution for a specific situation of fixed computer with one fixed wired interface and maybe one or more additional interfaces for fixed wired private networks.&lt;br /&gt;
&lt;br /&gt;
Install /etc/ifup-ko, edit it with IP addresses of main and additional interfaces, let systemd run it in the right place in the boot sequence replacing NetworkManager and NetworkManager-wait-online .&lt;br /&gt;
&lt;br /&gt;
As bonus, /etc/ifup-ko waits up to 10 seconds for the main interface link to come up. If this is not needed, comment it out from the script.&lt;br /&gt;
&lt;br /&gt;
* prepare&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/git/scripts&lt;br /&gt;
git pull&lt;br /&gt;
cd ifup-ko&lt;br /&gt;
make install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* confirm interface names&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl start ifup-ko ### should finish immediately or after 10 seconds&lt;br /&gt;
systemctl status ifup-ko -n 1000 ### observe list of interfaces is correct, name of main interface is correct&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* edit /etc/ifup-ko&lt;br /&gt;
** add host IP address to the &amp;quot;ifconfig&amp;quot; line&lt;br /&gt;
** add gateway IP address to the &amp;quot;ip route add&amp;quot; line&lt;br /&gt;
* test&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl start ifup-ko ### should finish immediately&lt;br /&gt;
systemctl status ifup-ko -n 1000 ### observe everything is configured as expected&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* cut-over&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl disable networkd-dispatcher&lt;br /&gt;
systemctl disable NetworkManager&lt;br /&gt;
systemctl disable wpa_supplicant # if no Wifi or Wifi not in use&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* reboot&lt;br /&gt;
&lt;br /&gt;
= Disable systemd-networkd =&lt;br /&gt;
&lt;br /&gt;
On netbooted machines, systemd-networkd should be disabled - when &amp;quot;apt upgrade&amp;quot; runs&lt;br /&gt;
and needs to update and configure systemd, it will stop systemd-networkd, which&lt;br /&gt;
will stop the network, which will stop the NFS mounted root filesystem, which will stop&lt;br /&gt;
the machine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl disable systemd-networkd.service&lt;br /&gt;
systemctl disable systemd-networkd.socket&lt;br /&gt;
systemctl mask systemd-networkd.service&lt;br /&gt;
systemctl mask systemd-networkd.socket&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Configure ECC memory =&lt;br /&gt;
&lt;br /&gt;
== Configure EDAC ==&lt;br /&gt;
&lt;br /&gt;
* apt install edac-utils rasdaemon&lt;br /&gt;
&lt;br /&gt;
=== Intel i3-2120 ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@musr00:~# edac-ctl --mainboard&lt;br /&gt;
edac-ctl: mainboard: Supermicro X9SCL/X9SCM&lt;br /&gt;
root@musr00:~# edac-ctl --status&lt;br /&gt;
edac-ctl: drivers not loaded.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Intel E-2236 ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq00:~# edac-ctl --mainboard&lt;br /&gt;
edac-ctl: mainboard: Supermicro X11SCM-F&lt;br /&gt;
root@daq00:~# edac-ctl --status&lt;br /&gt;
edac-ctl: drivers are loaded.&lt;br /&gt;
root@daq00:~# edac-util &lt;br /&gt;
edac-util: No errors to report.&lt;br /&gt;
root@daq00:~# edac-util -s&lt;br /&gt;
edac-util: EDAC drivers are loaded. 1 MC detected&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* check edac sysfs files (Intel)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq00:~# ls -l /sys/devices/system/edac/mc/mc0&lt;br /&gt;
total 0&lt;br /&gt;
-r--r--r-- 1 root root 4096 Jan 25 15:10 ce_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Jan 25 15:10 ce_noinfo_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Jan 25 15:10 max_location&lt;br /&gt;
-r--r--r-- 1 root root 4096 Jan 25 15:10 mc_name&lt;br /&gt;
drwxr-xr-x 2 root root    0 Jan 25 15:10 power&lt;br /&gt;
drwxr-xr-x 3 root root    0 Jan 25 15:10 rank0&lt;br /&gt;
drwxr-xr-x 3 root root    0 Jan 25 15:10 rank1&lt;br /&gt;
drwxr-xr-x 3 root root    0 Jan 25 15:10 rank2&lt;br /&gt;
drwxr-xr-x 3 root root    0 Jan 25 15:10 rank3&lt;br /&gt;
drwxr-xr-x 3 root root    0 Jan 25 15:10 rank4&lt;br /&gt;
drwxr-xr-x 3 root root    0 Jan 25 15:10 rank5&lt;br /&gt;
drwxr-xr-x 3 root root    0 Jan 25 15:10 rank6&lt;br /&gt;
drwxr-xr-x 3 root root    0 Jan 25 15:10 rank7&lt;br /&gt;
--w------- 1 root root 4096 Jan 25 15:10 reset_counters&lt;br /&gt;
-r--r--r-- 1 root root 4096 Jan 25 15:10 seconds_since_reset&lt;br /&gt;
-r--r--r-- 1 root root 4096 Jan 25 15:10 size_mb&lt;br /&gt;
-r--r--r-- 1 root root 4096 Jan 25 15:10 ue_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Jan 25 15:10 ue_noinfo_count&lt;br /&gt;
-rw-r--r-- 1 root root 4096 Jan 25 15:10 uevent&lt;br /&gt;
root@daq00:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Intel E3-1270 v6 ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@wheel-SYS-5019S-M:~/git/scripts# edac-ctl --mainboard&lt;br /&gt;
edac-ctl: mainboard: Supermicro X11SSH-F&lt;br /&gt;
root@wheel-SYS-5019S-M:~/git/scripts# edac-ctl --status&lt;br /&gt;
edac-ctl: drivers are loaded.&lt;br /&gt;
root@grsnis01:~# edac-util&lt;br /&gt;
edac-util: No errors to report.&lt;br /&gt;
root@grsnis01:~# edac-util -s&lt;br /&gt;
edac-util: EDAC drivers are loaded. 1 MC detected&lt;br /&gt;
root@grsnis01:~# ls -l /sys/devices/system/edac/mc/mc0&lt;br /&gt;
total 0&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 19 12:35 ce_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 19 12:35 ce_noinfo_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 19 12:35 max_location&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 19 12:35 mc_name&lt;br /&gt;
drwxr-xr-x 2 root root    0 Feb 19 12:35 power&lt;br /&gt;
drwxr-xr-x 3 root root    0 Feb 19 12:35 rank0&lt;br /&gt;
drwxr-xr-x 3 root root    0 Feb 19 12:35 rank1&lt;br /&gt;
drwxr-xr-x 3 root root    0 Feb 19 12:35 rank2&lt;br /&gt;
drwxr-xr-x 3 root root    0 Feb 19 12:35 rank3&lt;br /&gt;
drwxr-xr-x 3 root root    0 Feb 19 12:35 rank4&lt;br /&gt;
drwxr-xr-x 3 root root    0 Feb 19 12:35 rank5&lt;br /&gt;
drwxr-xr-x 3 root root    0 Feb 19 12:35 rank6&lt;br /&gt;
drwxr-xr-x 3 root root    0 Feb 19 12:35 rank7&lt;br /&gt;
--w------- 1 root root 4096 Feb 19 12:35 reset_counters&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 19 12:35 seconds_since_reset&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 19 12:35 size_mb&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 19 12:35 ue_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 19 12:35 ue_noinfo_count&lt;br /&gt;
-rw-r--r-- 1 root root 4096 Feb 19 12:35 uevent&lt;br /&gt;
root@grsnis01:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Intel E3-1245 v6 ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[root@alphagdaq ~]# edac-ctl --mainboard&lt;br /&gt;
edac-ctl: mainboard: Supermicro X11SSH-F&lt;br /&gt;
[root@alphagdaq ~]# edac-ctl --mainboard&lt;br /&gt;
edac-ctl: mainboard: Supermicro X11SSH-F&lt;br /&gt;
[root@alphagdaq ~]# edac-ctl --status&lt;br /&gt;
edac-ctl: drivers are loaded.&lt;br /&gt;
[root@alphagdaq ~]# edac-util&lt;br /&gt;
edac-util: No errors to report.&lt;br /&gt;
[root@alphagdaq ~]# edac-util -s&lt;br /&gt;
edac-util: EDAC drivers are loaded. 1 MC detected&lt;br /&gt;
[root@alphagdaq ~]# ras-mc-ctl --layout&lt;br /&gt;
          +-----------------------------------------------+&lt;br /&gt;
          |                      mc0                      |&lt;br /&gt;
          |  csrow0   |  csrow1   |  csrow2   |  csrow3   |&lt;br /&gt;
----------+-----------------------------------------------+&lt;br /&gt;
channel1: |  8192 MB  |  8192 MB  |  8192 MB  |  8192 MB  |&lt;br /&gt;
channel0: |  8192 MB  |  8192 MB  |  8192 MB  |  8192 MB  |&lt;br /&gt;
----------+-----------------------------------------------+&lt;br /&gt;
[root@alphagdaq ~]# ras-mc-ctl --error-count&lt;br /&gt;
Label               	CE	UE&lt;br /&gt;
mc#0csrow#3channel#0	0	0&lt;br /&gt;
mc#0csrow#2channel#1	0	0&lt;br /&gt;
mc#0csrow#3channel#1	0	0&lt;br /&gt;
mc#0csrow#0channel#0	0	0&lt;br /&gt;
mc#0csrow#1channel#1	0	0&lt;br /&gt;
mc#0csrow#0channel#1	0	0&lt;br /&gt;
mc#0csrow#1channel#0	0	0&lt;br /&gt;
mc#0csrow#2channel#0	0	0&lt;br /&gt;
[root@alphagdaq ~]# ras-mc-ctl --mainboard&lt;br /&gt;
ras-mc-ctl: mainboard: Supermicro model X11SSH-F&lt;br /&gt;
[root@alphagdaq ~]# ras-mc-ctl --summary&lt;br /&gt;
DBD::SQLite::db prepare failed: no such table: mc_event at /usr/sbin/ras-mc-ctl line 1129.&lt;br /&gt;
Can&#039;t call method &amp;quot;execute&amp;quot; on an undefined value at /usr/sbin/ras-mc-ctl line 1130.&lt;br /&gt;
[root@alphagdaq ~]# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== AMD 3700X ===&lt;br /&gt;
&lt;br /&gt;
(memory is non-ECC)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq13:~# edac-ctl --mainboard&lt;br /&gt;
edac-ctl: mainboard: ASUSTeK COMPUTER INC. ROG STRIX B550-E GAMING&lt;br /&gt;
root@daq13:~# &lt;br /&gt;
root@daq13:~# &lt;br /&gt;
root@daq13:~# edac-ctl --status&lt;br /&gt;
edac-ctl: drivers not loaded.&lt;br /&gt;
root@daq13:~# edac-util &lt;br /&gt;
edac-util: Error: No memory controller data found.&lt;br /&gt;
root@daq13:~# edac-util -s&lt;br /&gt;
edac-util: EDAC drivers loaded. No memory controllers found&lt;br /&gt;
root@daq13:~# ls -l /sys/devices/system/edac/mc&lt;br /&gt;
total 0&lt;br /&gt;
drwxr-xr-x 2 root root    0 Jan 25 15:26 power&lt;br /&gt;
lrwxrwxrwx 1 root root    0 Jan 21 16:16 subsystem -&amp;gt; ../../../../bus/edac&lt;br /&gt;
-rw-r--r-- 1 root root 4096 Jan 21 16:16 uevent&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(memory is ECC)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@trinatdaq:~# edac-ctl --mainboard&lt;br /&gt;
edac-ctl: mainboard: ASUSTeK COMPUTER INC. ROG STRIX B550-E GAMING&lt;br /&gt;
root@trinatdaq:~# edac-ctl --status&lt;br /&gt;
edac-ctl: drivers are loaded.&lt;br /&gt;
root@trinatdaq:~# edac-util &lt;br /&gt;
edac-util: No errors to report.&lt;br /&gt;
root@trinatdaq:~# edac-util -s&lt;br /&gt;
edac-util: EDAC drivers are loaded. 1 MC detected&lt;br /&gt;
root@trinatdaq:~# ls -l /sys/devices/system/edac/mc&lt;br /&gt;
total 0&lt;br /&gt;
drwxr-xr-x 7 root root    0 Dec 15 13:04 mc0&lt;br /&gt;
drwxr-xr-x 2 root root    0 Dec 15 13:04 power&lt;br /&gt;
lrwxrwxrwx 1 root root    0 Dec 13 18:31 subsystem -&amp;gt; ../../../../bus/edac&lt;br /&gt;
-rw-r--r-- 1 root root 4096 Dec 13 18:31 uevent&lt;br /&gt;
root@trinatdaq:~# ls -l /sys/devices/system/edac/mc/mc0&lt;br /&gt;
total 0&lt;br /&gt;
-r--r--r-- 1 root root 4096 Dec 15 13:04 ce_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Dec 15 13:04 ce_noinfo_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Dec 15 13:04 max_location&lt;br /&gt;
-r--r--r-- 1 root root 4096 Dec 15 13:04 mc_name&lt;br /&gt;
drwxr-xr-x 2 root root    0 Dec 15 13:04 power&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dec 15 13:04 rank4&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dec 15 13:04 rank5&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dec 15 13:04 rank6&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dec 15 13:04 rank7&lt;br /&gt;
--w------- 1 root root 4096 Dec 15 13:04 reset_counters&lt;br /&gt;
-rw-r--r-- 1 root root 4096 Dec 15 13:04 sdram_scrub_rate&lt;br /&gt;
-r--r--r-- 1 root root 4096 Dec 15 13:04 seconds_since_reset&lt;br /&gt;
-r--r--r-- 1 root root 4096 Dec 15 13:04 size_mb&lt;br /&gt;
-r--r--r-- 1 root root 4096 Dec 15 13:04 ue_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Dec 15 13:04 ue_noinfo_count&lt;br /&gt;
-rw-r--r-- 1 root root 4096 Dec 15 13:04 uevent&lt;br /&gt;
root@trinatdaq:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== AMD 5000G ===&lt;br /&gt;
&lt;br /&gt;
* no linux driver for AMD 5000-series &amp;quot;G&amp;quot; CPU&lt;br /&gt;
* no mention of ECC in the BIOS settings&lt;br /&gt;
* unclear status of ECC support in AMD documentation (sais only &amp;quot;pro&amp;quot; &amp;quot;G&amp;quot; CPUs have ECC)&lt;br /&gt;
* unclear status of ECC support in ASUS documentation (web page out of date)&lt;br /&gt;
&lt;br /&gt;
=== AMD 5600X ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq17:~# edac-ctl --mainboard&lt;br /&gt;
edac-ctl: mainboard: ASUSTeK COMPUTER INC. ROG STRIX B550-XE GAMING WIFI&lt;br /&gt;
root@daq17:~# edac-ctl --status&lt;br /&gt;
edac-ctl: drivers are loaded.&lt;br /&gt;
root@daq17:~# edac-util&lt;br /&gt;
edac-util: No errors to report.&lt;br /&gt;
root@daq17:~# edac-util -s&lt;br /&gt;
edac-util: EDAC drivers are loaded. 1 MC detected&lt;br /&gt;
root@daq17:~# ls -l /sys/devices/system/edac/mc&lt;br /&gt;
total 0&lt;br /&gt;
drwxr-xr-x 7 root root    0 Aug 19 19:27 mc0&lt;br /&gt;
drwxr-xr-x 2 root root    0 Aug 19 19:27 power&lt;br /&gt;
lrwxrwxrwx 1 root root    0 May 10 10:11 subsystem -&amp;gt; ../../../../bus/edac&lt;br /&gt;
-rw-r--r-- 1 root root 4096 May 10 10:11 uevent&lt;br /&gt;
root@daq17:~# ls -l /sys/devices/system/edac/mc/mc0&lt;br /&gt;
total 0&lt;br /&gt;
-r--r--r-- 1 root root 4096 Aug 19 19:27 ce_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Aug 19 19:27 ce_noinfo_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Aug 19 19:27 max_location&lt;br /&gt;
-r--r--r-- 1 root root 4096 Aug 19 19:27 mc_name&lt;br /&gt;
drwxr-xr-x 2 root root    0 Aug 19 19:27 power&lt;br /&gt;
drwxr-xr-x 3 root root    0 Aug 19 19:27 rank4&lt;br /&gt;
drwxr-xr-x 3 root root    0 Aug 19 19:27 rank5&lt;br /&gt;
drwxr-xr-x 3 root root    0 Aug 19 19:27 rank6&lt;br /&gt;
drwxr-xr-x 3 root root    0 Aug 19 19:27 rank7&lt;br /&gt;
--w------- 1 root root 4096 Aug 19 19:27 reset_counters&lt;br /&gt;
-rw-r--r-- 1 root root 4096 Aug 19 19:27 sdram_scrub_rate&lt;br /&gt;
-r--r--r-- 1 root root 4096 Aug 19 19:27 seconds_since_reset&lt;br /&gt;
-r--r--r-- 1 root root 4096 Aug 19 19:27 size_mb&lt;br /&gt;
-r--r--r-- 1 root root 4096 Aug 19 19:27 ue_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Aug 19 19:27 ue_noinfo_count&lt;br /&gt;
-rw-r--r-- 1 root root 4096 Aug 19 19:27 uevent&lt;br /&gt;
root@daq17:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== AMD 3955WX ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@alphasuperdaq:~/git/scripts/quotareport# edac-ctl --mainboard&lt;br /&gt;
edac-ctl: mainboard: ASUSTeK COMPUTER INC. Pro WS WRX80E-SAGE SE WIFI&lt;br /&gt;
root@alphasuperdaq:~/git/scripts/quotareport# edac-ctl --status&lt;br /&gt;
edac-ctl: drivers are loaded.&lt;br /&gt;
root@alphasuperdaq:~/git/scripts/quotareport# edac-util &lt;br /&gt;
edac-util: No errors to report.&lt;br /&gt;
root@alphasuperdaq:~/git/scripts/quotareport# edac-util -s&lt;br /&gt;
edac-util: EDAC drivers are loaded. 1 MC detected&lt;br /&gt;
root@alphasuperdaq:~/git/scripts/quotareport# ls -l /sys/devices/system/edac/mc&lt;br /&gt;
total 0&lt;br /&gt;
drwxr-xr-x 19 root root    0 Dez 12 04:48 mc0&lt;br /&gt;
drwxr-xr-x  2 root root    0 Dez 12 04:48 power&lt;br /&gt;
lrwxrwxrwx  1 root root    0 Dez  9 05:31 subsystem -&amp;gt; ../../../../bus/edac&lt;br /&gt;
-rw-r--r--  1 root root 4096 Dez  9 05:31 uevent&lt;br /&gt;
root@alphasuperdaq:~/git/scripts/quotareport# &lt;br /&gt;
root@alphasuperdaq:~# ls -l /sys/devices/system/edac/mc/mc0&lt;br /&gt;
total 0&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 28 22:19 ce_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 28 22:19 ce_noinfo_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 28 22:19 max_location&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 28 22:19 mc_name&lt;br /&gt;
drwxr-xr-x 2 root root    0 Dez 12 04:48 power&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank0&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank1&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank10&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank11&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank12&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank13&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank14&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank15&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank2&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank3&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank4&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank5&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank6&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank7&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank8&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank9&lt;br /&gt;
--w------- 1 root root 4096 Feb 28 22:19 reset_counters&lt;br /&gt;
-rw-r--r-- 1 root root 4096 Feb 28 22:19 sdram_scrub_rate&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 28 22:19 seconds_since_reset&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 28 22:19 size_mb&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 28 22:19 ue_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 28 22:19 ue_noinfo_count&lt;br /&gt;
-rw-r--r-- 1 root root 4096 Feb 28 22:19 uevent&lt;br /&gt;
root@alphasuperdaq:~# &lt;br /&gt;
root@alphasuperdaq:~# ras-mc-ctl --layout&lt;br /&gt;
Use of uninitialized value $max_pos[3] in modulus (%) at /usr/sbin/ras-mc-ctl line 868.&lt;br /&gt;
Use of uninitialized value $d in numeric ge (&amp;gt;=) at /usr/sbin/ras-mc-ctl line 869.&lt;br /&gt;
Use of uninitialized value $d in sprintf at /usr/sbin/ras-mc-ctl line 872.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
    +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+&lt;br /&gt;
    |                                                                                              mc0                                                                                              |&lt;br /&gt;
    |                                            csrow0                                             |                                            csrow1                                             |&lt;br /&gt;
    | channel0  | channel1  | channel2  | channel3  | channel4  | channel5  | channel6  | channel7  | channel0  | channel1  | channel2  | channel3  | channel4  | channel5  | channel6  | channel7  |&lt;br /&gt;
----+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+&lt;br /&gt;
&lt;br /&gt;
0: |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |&lt;br /&gt;
----+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+&lt;br /&gt;
root@alphasuperdaq:~# ras-mc-ctl --error-count&lt;br /&gt;
Label               	CE	UE&lt;br /&gt;
mc#0csrow#0channel#2	0	0&lt;br /&gt;
mc#0csrow#1channel#7	0	0&lt;br /&gt;
mc#0csrow#0channel#3	0	0&lt;br /&gt;
mc#0csrow#1channel#4	0	0&lt;br /&gt;
mc#0csrow#1channel#2	0	0&lt;br /&gt;
mc#0csrow#0channel#7	0	0&lt;br /&gt;
mc#0csrow#1channel#3	0	0&lt;br /&gt;
mc#0csrow#0channel#4	0	0&lt;br /&gt;
mc#0csrow#1channel#1	0	0&lt;br /&gt;
mc#0csrow#1channel#0	0	0&lt;br /&gt;
mc#0csrow#1channel#5	0	0&lt;br /&gt;
mc#0csrow#0channel#6	0	0&lt;br /&gt;
mc#0csrow#0channel#1	0	0&lt;br /&gt;
mc#0csrow#0channel#5	0	0&lt;br /&gt;
mc#0csrow#0channel#0	0	0&lt;br /&gt;
mc#0csrow#1channel#6	0	0&lt;br /&gt;
root@alphasuperdaq:~# ras-mc-ctl --mainboard&lt;br /&gt;
ras-mc-ctl: mainboard: ASUSTeK COMPUTER INC. model Pro WS WRX80E-SAGE SE WIFI&lt;br /&gt;
root@alphasuperdaq:~# ras-mc-ctl --summary&lt;br /&gt;
No Memory errors.&lt;br /&gt;
&lt;br /&gt;
No PCIe AER errors.&lt;br /&gt;
&lt;br /&gt;
No Extlog errors.&lt;br /&gt;
&lt;br /&gt;
DBD::SQLite::db prepare failed: no such table: devlink_event at /usr/sbin/ras-mc-ctl line 1181.&lt;br /&gt;
Can&#039;t call method &amp;quot;execute&amp;quot; on an undefined value at /usr/sbin/ras-mc-ctl line 1182.&lt;br /&gt;
root@alphasuperdaq:~#&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== AMD 7700X ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@dsfe05:~# apt install edac-utils&lt;br /&gt;
root@dsfe05:~# edac-ctl --mainboard&lt;br /&gt;
edac-ctl: mainboard: Supermicro H13SAE-MF&lt;br /&gt;
root@dsfe05:~# edac-ctl --status&lt;br /&gt;
edac-ctl: drivers are loaded.&lt;br /&gt;
root@dsfe05:~# edac-util&lt;br /&gt;
edac-util: No errors to report.&lt;br /&gt;
root@dsfe05:~# edac-util -s&lt;br /&gt;
edac-util: EDAC drivers are loaded. 1 MC detected&lt;br /&gt;
root@dsfe05:~# ls -l /sys/devices/system/edac/mc/mc0&lt;br /&gt;
total 0&lt;br /&gt;
-r--r--r-- 1 root root 4096 May 14 09:33 ce_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 May 14 09:33 ce_noinfo_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 May 14 09:33 max_location&lt;br /&gt;
-r--r--r-- 1 root root 4096 May 14 09:33 mc_name&lt;br /&gt;
drwxr-xr-x 2 root root    0 May 14 09:33 power&lt;br /&gt;
drwxr-xr-x 3 root root    0 May 14 09:33 rank4&lt;br /&gt;
drwxr-xr-x 3 root root    0 May 14 09:33 rank5&lt;br /&gt;
--w------- 1 root root 4096 May 14 09:33 reset_counters&lt;br /&gt;
-r--r--r-- 1 root root 4096 May 14 09:33 seconds_since_reset&lt;br /&gt;
-r--r--r-- 1 root root 4096 May 14 09:33 size_mb&lt;br /&gt;
-r--r--r-- 1 root root 4096 May 14 09:33 ue_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 May 14 09:33 ue_noinfo_count&lt;br /&gt;
-rw-r--r-- 1 root root 4096 May 14 09:33 uevent&lt;br /&gt;
root@dsfe05:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configure rasdaemon ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install rasdaemon&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl enable rasdaemon&lt;br /&gt;
systemctl restart rasdaemon&lt;br /&gt;
systemctl status rasdaemon&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
● rasdaemon.service - RAS daemon to log the RAS events&lt;br /&gt;
     Loaded: loaded (/lib/systemd/system/rasdaemon.service; enabled; vendor preset: enabled)&lt;br /&gt;
     Active: active (running) since Mon 2021-01-25 15:16:37 PST; 3min 5s ago&lt;br /&gt;
   Main PID: 2477175 (rasdaemon)&lt;br /&gt;
      Tasks: 1 (limit: 76958)&lt;br /&gt;
     Memory: 17.1M&lt;br /&gt;
     CGroup: /system.slice/rasdaemon.service&lt;br /&gt;
             └─2477175 /usr/sbin/rasdaemon -f -r&lt;br /&gt;
&lt;br /&gt;
Jan 25 15:16:37 daq00.triumf.ca rasdaemon[2477175]: rasdaemon: ras:extlog_mem_event event enabled&lt;br /&gt;
Jan 25 15:16:37 daq00.triumf.ca rasdaemon[2477175]: rasdaemon: Enabled event ras:extlog_mem_event&lt;br /&gt;
Jan 25 15:16:37 daq00.triumf.ca rasdaemon[2477175]: ras:extlog_mem_event event enabled&lt;br /&gt;
Jan 25 15:16:37 daq00.triumf.ca rasdaemon[2477175]: rasdaemon: Listening to events for cpus 0 to 11&lt;br /&gt;
Jan 25 15:16:37 daq00.triumf.ca rasdaemon[2477175]: Enabled event ras:extlog_mem_event&lt;br /&gt;
Jan 25 15:16:37 daq00.triumf.ca rasdaemon[2477175]: rasdaemon: Recording mc_event events&lt;br /&gt;
Jan 25 15:16:37 daq00.triumf.ca rasdaemon[2477175]: rasdaemon: Recording aer_event events&lt;br /&gt;
Jan 25 15:16:37 daq00.triumf.ca rasdaemon[2477175]: rasdaemon: Recording extlog_event events&lt;br /&gt;
Jan 25 15:16:37 daq00.triumf.ca rasdaemon[2477175]: rasdaemon: Recording mce_record events&lt;br /&gt;
Jan 25 15:16:37 daq00.triumf.ca rasdaemon[2477175]: rasdaemon: Recording arm_event events&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get reports ==&lt;br /&gt;
&lt;br /&gt;
* Intel 2x32GB ECC DIMMs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq00:~# ras-mc-ctl --layout&lt;br /&gt;
          +-------------------------+&lt;br /&gt;
          |           mc0           |&lt;br /&gt;
          |   csrow0   |   csrow1   |&lt;br /&gt;
----------+-------------------------+&lt;br /&gt;
channel1: |  16384 MB  |  16384 MB  |&lt;br /&gt;
channel0: |  16384 MB  |  16384 MB  |&lt;br /&gt;
----------+-------------------------+&lt;br /&gt;
root@daq00:~# ras-mc-ctl --error-count&lt;br /&gt;
Label                   CE      UE&lt;br /&gt;
mc#0csrow#1channel#1    0       0&lt;br /&gt;
mc#0csrow#1channel#0    0       0&lt;br /&gt;
mc#0csrow#0channel#0    0       0&lt;br /&gt;
mc#0csrow#0channel#1    0       0&lt;br /&gt;
root@daq00:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Intel 4x16GB ECC DIMMs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq00:~# ras-mc-ctl --error-count&lt;br /&gt;
Label                   CE      UE&lt;br /&gt;
mc#0csrow#0channel#1    0       0&lt;br /&gt;
mc#0csrow#2channel#0    0       0&lt;br /&gt;
mc#0csrow#0channel#0    0       0&lt;br /&gt;
mc#0csrow#2channel#1    0       0&lt;br /&gt;
mc#0csrow#1channel#0    0       0&lt;br /&gt;
mc#0csrow#1channel#1    0       0&lt;br /&gt;
mc#0csrow#3channel#0    0       0&lt;br /&gt;
mc#0csrow#3channel#1    0       0&lt;br /&gt;
root@daq00:~# &lt;br /&gt;
root@daq00:~# ras-mc-ctl --layout&lt;br /&gt;
          +-----------------------+&lt;br /&gt;
          |          mc0          |&lt;br /&gt;
          |  csrow0   |  csrow1   |&lt;br /&gt;
----------+-----------------------+&lt;br /&gt;
channel1: |  8192 MB  |  8192 MB  |&lt;br /&gt;
channel0: |  8192 MB  |  8192 MB  |&lt;br /&gt;
----------+-----------------------+&lt;br /&gt;
root@daq00:~# &lt;br /&gt;
root@daq00:~# &lt;br /&gt;
root@daq00:~# &lt;br /&gt;
root@daq00:~# ras-mc-ctl --print-labels&lt;br /&gt;
ras-mc-ctl: Error: No dimm labels for Supermicro model X11SCM-F&lt;br /&gt;
root@daq00:~# ras-mc-ctl --mainboard&lt;br /&gt;
ras-mc-ctl: mainboard: Supermicro model X11SCM-F&lt;br /&gt;
root@daq00:~# ras-mc-ctl --summary&lt;br /&gt;
No Memory errors.&lt;br /&gt;
&lt;br /&gt;
No PCIe AER errors.&lt;br /&gt;
&lt;br /&gt;
No Extlog errors.&lt;br /&gt;
&lt;br /&gt;
DBD::SQLite::db prepare failed: no such table: devlink_event at /usr/sbin/ras-mc-ctl line 1181.&lt;br /&gt;
Can&#039;t call method &amp;quot;execute&amp;quot; on an undefined value at /usr/sbin/ras-mc-ctl line 1182.&lt;br /&gt;
root@daq00:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
note: ubuntu LTS 22.04 DBD::SQLite::db error is not there.&lt;br /&gt;
&lt;br /&gt;
* AMD 7700 2x32GB DDR5 ECC DIMMs&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@dsfe05:~# systemctl status rasdaemon&lt;br /&gt;
● rasdaemon.service - RAS daemon to log the RAS events&lt;br /&gt;
     Loaded: loaded (/lib/systemd/system/rasdaemon.service; enabled; vendor preset: enabled)&lt;br /&gt;
     Active: active (running) since Tue 2024-05-14 09:36:43 PDT; 33ms ago&lt;br /&gt;
    Process: 4088418 ExecStartPost=/usr/sbin/rasdaemon --enable (code=exited, status=0/SUCCESS)&lt;br /&gt;
   Main PID: 4088417 (rasdaemon)&lt;br /&gt;
      Tasks: 1 (limit: 37300)&lt;br /&gt;
     Memory: 788.0K&lt;br /&gt;
        CPU: 5ms&lt;br /&gt;
     CGroup: /system.slice/rasdaemon.service&lt;br /&gt;
             └─4088417 /usr/sbin/rasdaemon -f -r&lt;br /&gt;
&lt;br /&gt;
May 14 09:36:43 dsfe05 rasdaemon[4088417]: ras:aer_event event enabled&lt;br /&gt;
May 14 09:36:43 dsfe05 rasdaemon[4088417]: Enabled event ras:aer_event&lt;br /&gt;
May 14 09:36:43 dsfe05 rasdaemon[4088417]: mce:mce_record event enabled&lt;br /&gt;
May 14 09:36:43 dsfe05 rasdaemon[4088417]: Enabled event mce:mce_record&lt;br /&gt;
May 14 09:36:43 dsfe05 rasdaemon[4088417]: ras:extlog_mem_event event enabled&lt;br /&gt;
May 14 09:36:43 dsfe05 rasdaemon[4088417]: Enabled event ras:extlog_mem_event&lt;br /&gt;
May 14 09:36:43 dsfe05 rasdaemon[4088417]: rasdaemon: Recording mc_event events&lt;br /&gt;
May 14 09:36:43 dsfe05 rasdaemon[4088417]: rasdaemon: Recording aer_event events&lt;br /&gt;
May 14 09:36:43 dsfe05 rasdaemon[4088417]: rasdaemon: Recording extlog_event events&lt;br /&gt;
May 14 09:36:43 dsfe05 rasdaemon[4088417]: rasdaemon: Recording mce_record events&lt;br /&gt;
root@dsfe05:~# ras-mc-ctl --layout&lt;br /&gt;
Use of uninitialized value $max_pos[3] in modulus (%) at /usr/sbin/ras-mc-ctl line 907.&lt;br /&gt;
Use of uninitialized value $d in numeric ge (&amp;gt;=) at /usr/sbin/ras-mc-ctl line 908.&lt;br /&gt;
Use of uninitialized value $d in sprintf at /usr/sbin/ras-mc-ctl line 911.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 830.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 830.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 830.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 830.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 830.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 830.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 830.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 830.&lt;br /&gt;
    +-----------------------------------------------------------------------------------------------+&lt;br /&gt;
    |                                              mc0                                              |&lt;br /&gt;
    |        csrow0         |        csrow1         |        csrow2         |        csrow3         |&lt;br /&gt;
    | channel0  | channel1  | channel0  | channel1  | channel0  | channel1  | channel0  | channel1  |&lt;br /&gt;
----+-----------------------------------------------------------------------------------------------+&lt;br /&gt;
&lt;br /&gt;
0: |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |&lt;br /&gt;
----+-----------------------------------------------------------------------------------------------+&lt;br /&gt;
root@dsfe05:~# ras-mc-ctl --error-count&lt;br /&gt;
Label               	CE	UE&lt;br /&gt;
mc#0csrow#2channel#1	0	0&lt;br /&gt;
mc#0csrow#2channel#0	0	0&lt;br /&gt;
root@dsfe05:~# ras-mc-ctl --print-labels&lt;br /&gt;
ras-mc-ctl: Error: No dimm labels for Supermicro model H13SAE-MF&lt;br /&gt;
root@dsfe05:~# ras-mc-ctl --mainboard&lt;br /&gt;
ras-mc-ctl: mainboard: Supermicro model H13SAE-MF&lt;br /&gt;
root@dsfe05:~# ras-mc-ctl --summary&lt;br /&gt;
No Memory errors.&lt;br /&gt;
&lt;br /&gt;
No PCIe AER errors.&lt;br /&gt;
&lt;br /&gt;
No Extlog errors.&lt;br /&gt;
&lt;br /&gt;
No MCE errors.&lt;br /&gt;
root@dsfe05:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= sensors =&lt;br /&gt;
&lt;br /&gt;
== VME CPU V7865 ==&lt;br /&gt;
&lt;br /&gt;
add to /etc/rc.local&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
modprobe coretemp&lt;br /&gt;
modprobe lm75&lt;br /&gt;
modprobe lm90&lt;br /&gt;
modprobe max1668&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
available sensors:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@lxdaq23:~# sensors&lt;br /&gt;
max6657-i2c-0-4c&lt;br /&gt;
Adapter: SMBus I801 adapter at 0400&lt;br /&gt;
temp1:        +29.1°C  (low  = -55.0°C, high = +105.0°C)&lt;br /&gt;
                       (crit = +105.0°C, hyst = +95.0°C)&lt;br /&gt;
temp2:        +31.5°C  (low  = -55.0°C, high = +105.0°C)&lt;br /&gt;
                       (crit = +105.0°C, hyst = +95.0°C)&lt;br /&gt;
&lt;br /&gt;
coretemp-isa-0000&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
Core 0:       +25.0°C  (crit = +100.0°C)&lt;br /&gt;
Core 1:       +25.0°C  (crit = +100.0°C)&lt;br /&gt;
&lt;br /&gt;
max1805-i2c-0-18&lt;br /&gt;
Adapter: SMBus I801 adapter at 0400&lt;br /&gt;
temp1:        +35.0°C  (low  = -55.0°C, high = +127.0°C)&lt;br /&gt;
temp2:        +63.0°C  (low  = -55.0°C, high = +127.0°C)&lt;br /&gt;
temp3:          FAULT  (low  = -55.0°C, high = +127.0°C)  ALARM (HIGH)&lt;br /&gt;
&lt;br /&gt;
lm75-i2c-0-48&lt;br /&gt;
Adapter: SMBus I801 adapter at 0400&lt;br /&gt;
temp1:        +34.5°C  (high = +80.0°C, hyst = +75.0°C)&lt;br /&gt;
&lt;br /&gt;
root@lxdaq23:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ASUS P7P55D EVO ==&lt;br /&gt;
&lt;br /&gt;
* BIOS version 2101&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@iris01:~# sensors&lt;br /&gt;
coretemp-isa-0000&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
Core 0:       +34.0°C  (high = +83.0°C, crit = +99.0°C)&lt;br /&gt;
Core 1:       +37.0°C  (high = +83.0°C, crit = +99.0°C)&lt;br /&gt;
Core 2:       +38.0°C  (high = +83.0°C, crit = +99.0°C)&lt;br /&gt;
Core 3:       +35.0°C  (high = +83.0°C, crit = +99.0°C)&lt;br /&gt;
&lt;br /&gt;
nouveau-pci-0100&lt;br /&gt;
Adapter: PCI adapter&lt;br /&gt;
GPU core:    900.00 mV (min =  +0.85 V, max =  +1.05 V)&lt;br /&gt;
temp1:        +46.0°C  (high = +95.0°C, hyst =  +3.0°C)&lt;br /&gt;
                       (crit = +105.0°C, hyst =  +5.0°C)&lt;br /&gt;
                       (emerg = +135.0°C, hyst =  +5.0°C)&lt;br /&gt;
&lt;br /&gt;
atk0110-acpi-0&lt;br /&gt;
Adapter: ACPI interface&lt;br /&gt;
Vcore Voltage:      864.00 mV (min =  +0.80 V, max =  +1.60 V)&lt;br /&gt;
+3.3V Voltage:        3.38 V  (min =  +2.97 V, max =  +3.63 V)&lt;br /&gt;
+5V Voltage:          5.04 V  (min =  +4.50 V, max =  +5.50 V)&lt;br /&gt;
+12V Voltage:        12.15 V  (min = +10.20 V, max = +13.80 V)&lt;br /&gt;
CPU Fan Speed:       968 RPM  (min =  600 RPM, max = 7200 RPM)&lt;br /&gt;
Chassis1 Fan Speed: 1288 RPM  (min =  600 RPM, max = 7200 RPM)&lt;br /&gt;
Chassis2 Fan Speed: 1316 RPM  (min =  600 RPM, max = 7200 RPM)&lt;br /&gt;
Power Fan Speed:       0 RPM  (min =    0 RPM, max = 7200 RPM)&lt;br /&gt;
CPU Temperature:     +34.0°C  (high = +45.0°C, crit = +45.5°C)&lt;br /&gt;
MB Temperature:      +30.0°C  (high = +45.0°C, crit = +46.0°C)&lt;br /&gt;
&lt;br /&gt;
root@iris01:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ASUS Z97-WS ==&lt;br /&gt;
&lt;br /&gt;
* BIOS version 2704&lt;br /&gt;
* load sensors drivers&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo modprobe coretemp &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
echo modprobe nct6775 &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* in /boot/grub/grub.cfg, add: GRUB_CMDLINE_LINUX_DEFAULT=&amp;quot;acpi_enforce_resources=no&amp;quot;&lt;br /&gt;
* update grub and reboot: grub-mkconfig -o /boot/grub/grub.cfg&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@isdaq08:~# sensors&lt;br /&gt;
acpitz-acpi-0&lt;br /&gt;
Adapter: ACPI interface&lt;br /&gt;
temp1:        +27.8°C  &lt;br /&gt;
temp2:        +29.8°C  &lt;br /&gt;
&lt;br /&gt;
nct6791-isa-0290&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
Vcore:                 888.00 mV (min =  +0.00 V, max =  +1.74 V)&lt;br /&gt;
in1:                     1.01 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
AVCC:                    3.36 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
+3.3V:                   3.36 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in4:                     1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in5:                     1.99 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in6:                     0.00 V  (min =  +0.00 V, max =  +0.00 V)&lt;br /&gt;
3VSB:                    3.44 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
Vbat:                    3.33 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in9:                     1.01 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in10:                    0.00 V  (min =  +0.00 V, max =  +0.00 V)&lt;br /&gt;
in11:                  840.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in12:                    0.00 V  (min =  +0.00 V, max =  +0.00 V)&lt;br /&gt;
in13:                    0.00 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in14:                    0.00 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
fan1:                  1041 RPM  (min =    0 RPM)&lt;br /&gt;
fan2:                  1040 RPM  (min =    0 RPM)&lt;br /&gt;
fan3:                     0 RPM  (min =    0 RPM)&lt;br /&gt;
fan4:                     0 RPM  (min =    0 RPM)&lt;br /&gt;
fan5:                     0 RPM  (min =    0 RPM)&lt;br /&gt;
fan6:                     0 RPM  (min =    0 RPM)&lt;br /&gt;
SYSTIN:                 +34.0°C  (high =  +0.0°C, hyst =  +0.0°C)  ALARM  sensor = thermistor&lt;br /&gt;
CPUTIN:                 +41.0°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermistor&lt;br /&gt;
AUXTIN0:               -128.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN1:               -128.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN2:                +35.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN3:               +127.0°C    sensor = thermistor&lt;br /&gt;
PECI Agent 0:           +41.0°C  &lt;br /&gt;
PCH_CHIP_CPU_MAX_TEMP:   +0.0°C  &lt;br /&gt;
PCH_CHIP_TEMP:           +0.0°C  &lt;br /&gt;
PCH_CPU_TEMP:            +0.0°C  &lt;br /&gt;
PCH_MCH_TEMP:            +0.0°C  &lt;br /&gt;
PCH_DIM0_TEMP:           +0.0°C  &lt;br /&gt;
intrusion0:            ALARM&lt;br /&gt;
intrusion1:            ALARM&lt;br /&gt;
beep_enable:           disabled&lt;br /&gt;
&lt;br /&gt;
coretemp-isa-0000&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
Package id 0:  +42.0°C  (high = +80.0°C, crit = +100.0°C)&lt;br /&gt;
Core 0:        +42.0°C  (high = +80.0°C, crit = +100.0°C)&lt;br /&gt;
Core 1:        +40.0°C  (high = +80.0°C, crit = +100.0°C)&lt;br /&gt;
Core 2:        +39.0°C  (high = +80.0°C, crit = +100.0°C)&lt;br /&gt;
Core 3:        +39.0°C  (high = +80.0°C, crit = +100.0°C)&lt;br /&gt;
&lt;br /&gt;
root@isdaq08:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ASUS Z170-DELUXE ==&lt;br /&gt;
&lt;br /&gt;
* BIOS version 3801&lt;br /&gt;
* load sensors drivers&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo modprobe coretemp &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
echo modprobe jc42 &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
echo modprobe lm92 &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
echo modprobe nct6775 &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* in /etc/default/grub, add: GRUB_CMDLINE_LINUX_DEFAULT=&amp;quot;acpi_enforce_resources=no&amp;quot;&lt;br /&gt;
* update grub and reboot: grub-mkconfig -o /boot/grub/grub.cfg&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@iris00:~# sensors&lt;br /&gt;
nct6793-isa-0290&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
in0:                      600.00 mV (min =  +0.00 V, max =  +1.74 V)&lt;br /&gt;
in1:                        1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in2:                        3.39 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in3:                        3.38 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in4:                        1.03 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in5:                      144.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in6:                        0.00 V  (min =  +0.00 V, max =  +0.00 V)&lt;br /&gt;
in7:                        3.38 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in8:                        3.14 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in9:                      1000.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in10:                     600.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in11:                       1.06 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in12:                       1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in13:                     592.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in14:                     968.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
fan1:                     1370 RPM  (min =    0 RPM)&lt;br /&gt;
fan2:                     1437 RPM  (min =    0 RPM)&lt;br /&gt;
fan3:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
fan4:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
fan5:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
fan6:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
SYSTIN:                    +32.0°C  (high = +98.0°C, hyst = +95.0°C)  sensor = thermistor&lt;br /&gt;
CPUTIN:                    +42.0°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermistor&lt;br /&gt;
AUXTIN0:                  -128.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN1:                   +50.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN2:                   +22.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN3:                   +28.0°C    sensor = thermistor&lt;br /&gt;
PECI Agent 0:              +50.0°C  (high = +98.0°C, hyst = +95.0°C)&lt;br /&gt;
                                    (crit = +100.0°C)&lt;br /&gt;
PECI Agent 0 Calibration:  +42.5°C  &lt;br /&gt;
PCH_CHIP_CPU_MAX_TEMP:      +0.0°C  &lt;br /&gt;
PCH_CHIP_TEMP:              +0.0°C  &lt;br /&gt;
PCH_CPU_TEMP:               +0.0°C  &lt;br /&gt;
PCH_MCH_TEMP:               +0.0°C  &lt;br /&gt;
TSI2_TEMP:                +3892314.0°C  &lt;br /&gt;
TSI3_TEMP:                +3892314.0°C  &lt;br /&gt;
TSI4_TEMP:                +3892314.0°C  &lt;br /&gt;
TSI5_TEMP:                +3892314.0°C  &lt;br /&gt;
TSI6_TEMP:                +3892314.0°C  &lt;br /&gt;
TSI7_TEMP:                +3892314.0°C  &lt;br /&gt;
intrusion0:               ALARM&lt;br /&gt;
intrusion1:               ALARM&lt;br /&gt;
beep_enable:              disabled&lt;br /&gt;
&lt;br /&gt;
jc42-i2c-0-1a&lt;br /&gt;
Adapter: SMBus I801 adapter at f040&lt;br /&gt;
temp1:        +36.0°C  (low  =  +0.0°C)                  ALARM (HIGH, CRIT)&lt;br /&gt;
                       (high =  +0.0°C, hyst =  +0.0°C)&lt;br /&gt;
                       (crit =  +0.0°C, hyst =  +0.0°C)&lt;br /&gt;
&lt;br /&gt;
jc42-i2c-0-18&lt;br /&gt;
Adapter: SMBus I801 adapter at f040&lt;br /&gt;
temp1:        +34.8°C  (low  =  +0.0°C)                  ALARM (HIGH, CRIT)&lt;br /&gt;
                       (high =  +0.0°C, hyst =  +0.0°C)&lt;br /&gt;
                       (crit =  +0.0°C, hyst =  +0.0°C)&lt;br /&gt;
&lt;br /&gt;
jc42-i2c-0-1b&lt;br /&gt;
Adapter: SMBus I801 adapter at f040&lt;br /&gt;
temp1:        +35.0°C  (low  =  +0.0°C)                  ALARM (HIGH, CRIT)&lt;br /&gt;
                       (high =  +0.0°C, hyst =  +0.0°C)&lt;br /&gt;
                       (crit =  +0.0°C, hyst =  +0.0°C)&lt;br /&gt;
&lt;br /&gt;
jc42-i2c-0-19&lt;br /&gt;
Adapter: SMBus I801 adapter at f040&lt;br /&gt;
temp1:        +36.0°C  (low  =  +0.0°C)                  ALARM (HIGH, CRIT)&lt;br /&gt;
                       (high =  +0.0°C, hyst =  +0.0°C)&lt;br /&gt;
                       (crit =  +0.0°C, hyst =  +0.0°C)&lt;br /&gt;
&lt;br /&gt;
coretemp-isa-0000&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
Package id 0:  +52.0°C  (high = +84.0°C, crit = +100.0°C)&lt;br /&gt;
Core 0:        +52.0°C  (high = +84.0°C, crit = +100.0°C)&lt;br /&gt;
Core 1:        +51.0°C  (high = +84.0°C, crit = +100.0°C)&lt;br /&gt;
Core 2:        +48.0°C  (high = +84.0°C, crit = +100.0°C)&lt;br /&gt;
Core 3:        +47.0°C  (high = +84.0°C, crit = +100.0°C)&lt;br /&gt;
&lt;br /&gt;
root@iris00:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ASUS Z390M-PRO GAMING (WI-FI) ==&lt;br /&gt;
&lt;br /&gt;
* BIOS 3006&lt;br /&gt;
* load sensors drivers&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo modprobe coretemp &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
echo modprobe nct6775 &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq18:~# sensors&lt;br /&gt;
nct6798-isa-0290&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
in0:                      696.00 mV (min =  +0.00 V, max =  +1.74 V)&lt;br /&gt;
in1:                        1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in2:                        3.42 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in3:                        3.41 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in4:                        1.03 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in5:                      208.00 mV (min =  +0.00 V, max =  +0.00 V)&lt;br /&gt;
in6:                        1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in7:                        3.42 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in8:                        3.17 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in9:                        1.07 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in10:                       1.36 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in11:                       1.33 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in12:                       1.06 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in13:                       1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in14:                       1.03 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
fan1:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
fan2:                     1131 RPM  (min =    0 RPM)&lt;br /&gt;
fan3:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
fan4:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
fan5:                     1006 RPM  (min =    0 RPM)&lt;br /&gt;
fan6:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
fan7:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
SYSTIN:                    +32.0°C  (high = +80.0°C, hyst = +75.0°C)&lt;br /&gt;
                                    (crit = +100.0°C)  sensor = thermistor&lt;br /&gt;
CPUTIN:                    +29.0°C  (high = +80.0°C, hyst = +75.0°C)&lt;br /&gt;
                                    (crit = +100.0°C)  sensor = thermistor&lt;br /&gt;
AUXTIN0:                   +25.0°C  (high = +80.0°C, hyst = +75.0°C)&lt;br /&gt;
                                    (crit = +100.0°C)  sensor = thermistor&lt;br /&gt;
AUXTIN1:                    +7.0°C  (high = +80.0°C, hyst = +75.0°C)&lt;br /&gt;
                                    (crit = +100.0°C)  sensor = thermistor&lt;br /&gt;
AUXTIN2:                    +8.0°C  (high = +80.0°C, hyst = +75.0°C)&lt;br /&gt;
                                    (crit = +100.0°C)  sensor = thermistor&lt;br /&gt;
AUXTIN3:                   +24.0°C  (high = +80.0°C, hyst = +75.0°C)&lt;br /&gt;
                                    (crit = +100.0°C)  sensor = thermistor&lt;br /&gt;
AUXTIN4:                   +83.0°C  (high = +80.0°C, hyst = +75.0°C)  ALARM&lt;br /&gt;
                                    (crit = +100.0°C)&lt;br /&gt;
PECI Agent 0 Calibration:  +29.0°C  (high = +80.0°C, hyst = +75.0°C)&lt;br /&gt;
PCH_CHIP_CPU_MAX_TEMP:      +0.0°C  &lt;br /&gt;
PCH_CHIP_TEMP:              +0.0°C  &lt;br /&gt;
PCH_CPU_TEMP:               +0.0°C  &lt;br /&gt;
PCH_MCH_TEMP:               +0.0°C  &lt;br /&gt;
intrusion0:               ALARM&lt;br /&gt;
intrusion1:               ALARM&lt;br /&gt;
beep_enable:              disabled&lt;br /&gt;
&lt;br /&gt;
coretemp-isa-0000&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
Package id 0:  +39.0°C  (high = +82.0°C, crit = +100.0°C)&lt;br /&gt;
Core 0:        +39.0°C  (high = +82.0°C, crit = +100.0°C)&lt;br /&gt;
Core 1:        +33.0°C  (high = +82.0°C, crit = +100.0°C)&lt;br /&gt;
Core 2:        +32.0°C  (high = +82.0°C, crit = +100.0°C)&lt;br /&gt;
Core 3:        +31.0°C  (high = +82.0°C, crit = +100.0°C)&lt;br /&gt;
Core 4:        +31.0°C  (high = +82.0°C, crit = +100.0°C)&lt;br /&gt;
Core 5:        +30.0°C  (high = +82.0°C, crit = +100.0°C)&lt;br /&gt;
&lt;br /&gt;
acpitz-acpi-0&lt;br /&gt;
Adapter: ACPI interface&lt;br /&gt;
temp1:        +27.8°C  &lt;br /&gt;
&lt;br /&gt;
iwlwifi_1-virtual-0&lt;br /&gt;
Adapter: Virtual device&lt;br /&gt;
temp1:        +28.0°C  &lt;br /&gt;
&lt;br /&gt;
root@daq18:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ASUS H110M-A/M.2 ==&lt;br /&gt;
&lt;br /&gt;
* BIOS version 4202&lt;br /&gt;
* echo modprobe coretemp &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
* echo modprobe nct6775 &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@midpol:~# sensors&lt;br /&gt;
coretemp-isa-0000&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
Package id 0:  +33.0°C  (high = +80.0°C, crit = +100.0°C)&lt;br /&gt;
Core 0:        +33.0°C  (high = +80.0°C, crit = +100.0°C)&lt;br /&gt;
Core 1:        +30.0°C  (high = +80.0°C, crit = +100.0°C)&lt;br /&gt;
&lt;br /&gt;
acpitz-acpi-0&lt;br /&gt;
Adapter: ACPI interface&lt;br /&gt;
temp1:        +27.8°C  (crit = +119.0°C)&lt;br /&gt;
temp2:        +29.8°C  (crit = +119.0°C)&lt;br /&gt;
&lt;br /&gt;
nct6793-isa-0290&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
in0:                      368.00 mV (min =  +0.00 V, max =  +1.74 V)&lt;br /&gt;
in1:                        1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in2:                        3.39 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in3:                        3.36 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in4:                        1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in5:                      152.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in6:                      928.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in7:                        3.39 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in8:                        3.14 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in9:                      1000.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in10:                     152.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in11:                     128.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in12:                     136.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in13:                     120.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in14:                     136.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
fan1:                     1004 RPM  (min =    0 RPM)&lt;br /&gt;
fan2:                     1143 RPM  (min =    0 RPM)&lt;br /&gt;
fan5:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
fan6:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
SYSTIN:                   +118.0°C  (high = +98.0°C, hyst = +95.0°C)  sensor = thermistor&lt;br /&gt;
CPUTIN:                    +29.0°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermistor&lt;br /&gt;
AUXTIN0:                   +30.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN1:                  +112.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN2:                  +111.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN3:                  +110.0°C    sensor = thermistor&lt;br /&gt;
PECI Agent 0:              +31.0°C  (high = +98.0°C, hyst = +95.0°C)&lt;br /&gt;
                                    (crit = +100.0°C)&lt;br /&gt;
PECI Agent 0 Calibration:  +36.5°C  &lt;br /&gt;
PCH_CHIP_CPU_MAX_TEMP:      +0.0°C  &lt;br /&gt;
PCH_CHIP_TEMP:              +0.0°C  &lt;br /&gt;
TSI2_TEMP:                +3892314.0°C  &lt;br /&gt;
TSI3_TEMP:                +3892314.0°C  &lt;br /&gt;
TSI4_TEMP:                +3892314.0°C  &lt;br /&gt;
TSI5_TEMP:                +3892314.0°C  &lt;br /&gt;
TSI6_TEMP:                +3892314.0°C  &lt;br /&gt;
TSI7_TEMP:                +3892314.0°C  &lt;br /&gt;
intrusion0:               ALARM&lt;br /&gt;
intrusion1:               ALARM&lt;br /&gt;
beep_enable:              disabled&lt;br /&gt;
&lt;br /&gt;
root@midpol:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ASUS P9X79 WS ==&lt;br /&gt;
&lt;br /&gt;
* https://www.asus.com/supportonly/P9X79%20WS/HelpDesk_Manual/&lt;br /&gt;
* BIOS version 4802&lt;br /&gt;
* modprobe nct6775&lt;br /&gt;
* modprobe coretemp&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq14:~# sensors&lt;br /&gt;
coretemp-isa-0000&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
Package id 0:  +35.0°C  (high = +82.0°C, crit = +100.0°C)&lt;br /&gt;
Core 0:        +29.0°C  (high = +82.0°C, crit = +100.0°C)&lt;br /&gt;
Core 1:        +24.0°C  (high = +82.0°C, crit = +100.0°C)&lt;br /&gt;
Core 2:        +35.0°C  (high = +82.0°C, crit = +100.0°C)&lt;br /&gt;
Core 3:        +32.0°C  (high = +82.0°C, crit = +100.0°C)&lt;br /&gt;
&lt;br /&gt;
nouveau-pci-0200&lt;br /&gt;
Adapter: PCI adapter&lt;br /&gt;
GPU core:    900.00 mV (min =  +0.85 V, max =  +1.00 V)&lt;br /&gt;
temp1:        +39.0°C  (high = +95.0°C, hyst =  +3.0°C)&lt;br /&gt;
                       (crit = +105.0°C, hyst =  +5.0°C)&lt;br /&gt;
                       (emerg = +135.0°C, hyst =  +5.0°C)&lt;br /&gt;
&lt;br /&gt;
nct6776-isa-0290&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
Vcore:           1.04 V  (min =  +0.00 V, max =  +1.74 V)&lt;br /&gt;
in1:             1.01 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
AVCC:            3.33 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
+3.3V:           3.33 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in4:             1.01 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in5:             2.04 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in6:           904.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
3VSB:            3.41 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
Vbat:            3.30 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
fan1:          1265 RPM  (min =    0 RPM)&lt;br /&gt;
fan2:          1909 RPM  (min =    0 RPM)&lt;br /&gt;
fan3:             0 RPM  (min =    0 RPM)&lt;br /&gt;
fan4:             0 RPM  (min =    0 RPM)&lt;br /&gt;
fan5:             0 RPM  (min =    0 RPM)&lt;br /&gt;
SYSTIN:         +34.0°C  (high =  +0.0°C, hyst =  +0.0°C)  ALARM  sensor = thermistor&lt;br /&gt;
CPUTIN:         +58.0°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermal diode&lt;br /&gt;
AUXTIN:         +31.5°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermistor&lt;br /&gt;
PECI Agent 0:   +31.0°C  (high = +80.0°C, hyst = +75.0°C)&lt;br /&gt;
                         (crit = +96.0°C)&lt;br /&gt;
PCH_CHIP_TEMP:   +0.0°C  &lt;br /&gt;
PCH_CPU_TEMP:    +0.0°C  &lt;br /&gt;
PCH_MCH_TEMP:    +0.0°C  &lt;br /&gt;
intrusion0:    ALARM&lt;br /&gt;
intrusion1:    ALARM&lt;br /&gt;
beep_enable:   disabled&lt;br /&gt;
&lt;br /&gt;
root@daq14:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ASUS TUF GAMING B550M-PLUS WIFI II ==&lt;br /&gt;
&lt;br /&gt;
* BIOS 2803, 2806&lt;br /&gt;
* echo modprobe nct6775 &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@midm9a:~# sensors&lt;br /&gt;
nct6798-isa-0290&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
in0:                      488.00 mV (min =  +0.00 V, max =  +1.74 V)&lt;br /&gt;
in1:                        1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in2:                        3.41 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in3:                        3.38 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in4:                        1.01 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in5:                        1.01 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in6:                      208.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in7:                        3.41 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in8:                        3.33 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in9:                        1.82 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in10:                       1.01 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in11:                       1.01 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in12:                       1.03 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in13:                       1.01 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in14:                       1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
fan1:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
fan2:                      760 RPM  (min =    0 RPM)&lt;br /&gt;
fan3:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
fan7:                     1264 RPM  (min =    0 RPM)&lt;br /&gt;
SYSTIN:                    +25.0°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermistor&lt;br /&gt;
CPUTIN:                    +22.5°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermistor&lt;br /&gt;
AUXTIN0:                   +95.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN1:                   +25.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN2:                   +25.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN3:                   +25.0°C    sensor = thermistor&lt;br /&gt;
PECI Agent 0 Calibration:  +23.5°C  &lt;br /&gt;
PCH_CHIP_CPU_MAX_TEMP:      +0.0°C  &lt;br /&gt;
PCH_CHIP_TEMP:              +0.0°C  &lt;br /&gt;
PCH_CPU_TEMP:               +0.0°C  &lt;br /&gt;
TSI0_TEMP:                 +32.4°C  &lt;br /&gt;
intrusion0:               ALARM&lt;br /&gt;
intrusion1:               ALARM&lt;br /&gt;
beep_enable:              disabled&lt;br /&gt;
&lt;br /&gt;
amdgpu-pci-0800&lt;br /&gt;
Adapter: PCI adapter&lt;br /&gt;
vddgfx:        1.45 V  &lt;br /&gt;
vddnb:       993.00 mV &lt;br /&gt;
edge:         +28.0°C  &lt;br /&gt;
PPT:          20.00 W  &lt;br /&gt;
&lt;br /&gt;
k10temp-pci-00c3&lt;br /&gt;
Adapter: PCI adapter&lt;br /&gt;
Tctl:         +33.4°C  &lt;br /&gt;
&lt;br /&gt;
root@midm9a:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ASUS ASUS ROG STRIX B550-XE GAMING WIFI ==&lt;br /&gt;
&lt;br /&gt;
* BIOS 2423, 2604&lt;br /&gt;
* echo modprobe nct6775 &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq13:~# sensors&lt;br /&gt;
nct6798-isa-0290&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
in0:                      344.00 mV (min =  +0.00 V, max =  +1.74 V)&lt;br /&gt;
in1:                      992.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in2:                        3.41 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in3:                        3.39 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in4:                        1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in5:                      960.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in6:                      216.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in7:                        3.41 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in8:                        3.30 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in9:                        1.81 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in10:                     960.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in11:                     960.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in12:                       1.03 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in13:                     280.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in14:                     208.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
fan1:                      845 RPM  (min =    0 RPM)&lt;br /&gt;
fan2:                      998 RPM  (min =    0 RPM)&lt;br /&gt;
fan3:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
fan4:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
fan5:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
SYSTIN:                    +28.0°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermistor&lt;br /&gt;
CPUTIN:                    +27.5°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermistor&lt;br /&gt;
AUXTIN0:                   +94.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN1:                   +28.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN2:                   +28.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN3:                   +97.0°C    sensor = thermistor&lt;br /&gt;
PECI Agent 0 Calibration:  +27.5°C  &lt;br /&gt;
PCH_CHIP_CPU_MAX_TEMP:      +0.0°C  &lt;br /&gt;
PCH_CHIP_TEMP:              +0.0°C  &lt;br /&gt;
PCH_CPU_TEMP:               +0.0°C  &lt;br /&gt;
TSI0_TEMP:                 +33.6°C  &lt;br /&gt;
intrusion0:               ALARM&lt;br /&gt;
intrusion1:               ALARM&lt;br /&gt;
beep_enable:              disabled&lt;br /&gt;
&lt;br /&gt;
amdgpu-pci-0600&lt;br /&gt;
Adapter: PCI adapter&lt;br /&gt;
vddgfx:        1.45 V  &lt;br /&gt;
vddnb:       999.00 mV &lt;br /&gt;
edge:         +29.0°C  &lt;br /&gt;
PPT:          14.00 W  &lt;br /&gt;
&lt;br /&gt;
iwlwifi_1-virtual-0&lt;br /&gt;
Adapter: Virtual device&lt;br /&gt;
temp1:        +30.0°C  &lt;br /&gt;
&lt;br /&gt;
k10temp-pci-00c3&lt;br /&gt;
Adapter: PCI adapter&lt;br /&gt;
Tctl:         +33.9°C  &lt;br /&gt;
&lt;br /&gt;
root@daq13:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ASUS ASUS ROG STRIX B550-E GAMING ==&lt;br /&gt;
&lt;br /&gt;
* bios 2803&lt;br /&gt;
* echo modprobe jc42 &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
* echo modprobe nct6775 &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq17:~# sensors&lt;br /&gt;
jc42-i2c-1-1b&lt;br /&gt;
Adapter: SMBus PIIX4 adapter port 0 at 0b00&lt;br /&gt;
temp1:        +25.0°C  (low  =  +0.0°C)                  ALARM (HIGH, CRIT)&lt;br /&gt;
                       (high =  +0.0°C, hyst =  +0.0°C)&lt;br /&gt;
                       (crit =  +0.0°C, hyst =  +0.0°C)&lt;br /&gt;
&lt;br /&gt;
iwlwifi_1-virtual-0&lt;br /&gt;
Adapter: Virtual device&lt;br /&gt;
temp1:        +28.0°C  &lt;br /&gt;
&lt;br /&gt;
nouveau-pci-0800&lt;br /&gt;
Adapter: PCI adapter&lt;br /&gt;
GPU core:    900.00 mV (min =  +0.85 V, max =  +1.00 V)&lt;br /&gt;
temp1:        +34.0°C  (high = +95.0°C, hyst =  +3.0°C)&lt;br /&gt;
                       (crit = +105.0°C, hyst =  +5.0°C)&lt;br /&gt;
                       (emerg = +135.0°C, hyst =  +5.0°C)&lt;br /&gt;
&lt;br /&gt;
nct6798-isa-0290&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
in0:                      288.00 mV (min =  +0.00 V, max =  +1.74 V)&lt;br /&gt;
in1:                        1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in2:                        3.36 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in3:                        3.38 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in4:                        1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in5:                        1.06 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in6:                      224.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in7:                        3.36 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in8:                        3.31 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in9:                        1.79 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in10:                       1.06 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in11:                       1.06 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in12:                       1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in13:                     280.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in14:                     208.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
fan1:                      843 RPM  (min =    0 RPM)&lt;br /&gt;
fan2:                      629 RPM  (min =    0 RPM)&lt;br /&gt;
fan3:                      746 RPM  (min =    0 RPM)&lt;br /&gt;
fan4:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
fan5:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
SYSTIN:                    +22.0°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermistor&lt;br /&gt;
CPUTIN:                    +25.0°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermistor&lt;br /&gt;
AUXTIN0:                   +93.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN1:                   +22.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN2:                   +22.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN3:                   +96.0°C    sensor = thermistor&lt;br /&gt;
PECI Agent 0 Calibration:  +25.5°C  &lt;br /&gt;
PCH_CHIP_CPU_MAX_TEMP:      +0.0°C  &lt;br /&gt;
PCH_CHIP_TEMP:              +0.0°C  &lt;br /&gt;
PCH_CPU_TEMP:               +0.0°C  &lt;br /&gt;
TSI0_TEMP:                 +27.6°C  &lt;br /&gt;
intrusion0:               ALARM&lt;br /&gt;
intrusion1:               ALARM&lt;br /&gt;
beep_enable:              disabled&lt;br /&gt;
&lt;br /&gt;
jc42-i2c-1-1a&lt;br /&gt;
Adapter: SMBus PIIX4 adapter port 0 at 0b00&lt;br /&gt;
temp1:        +23.2°C  (low  =  +0.0°C)                  ALARM (HIGH, CRIT)&lt;br /&gt;
                       (high =  +0.0°C, hyst =  +0.0°C)&lt;br /&gt;
                       (crit =  +0.0°C, hyst =  +0.0°C)&lt;br /&gt;
&lt;br /&gt;
asusec-isa-0000&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
CPU_Opt:        0 RPM&lt;br /&gt;
Chipset:      +34.0°C  &lt;br /&gt;
CPU:          +25.0°C  &lt;br /&gt;
Motherboard:  +22.0°C  &lt;br /&gt;
T_Sensor:     -40.0°C  &lt;br /&gt;
VRM:          +31.0°C  &lt;br /&gt;
&lt;br /&gt;
k10temp-pci-00c3&lt;br /&gt;
Adapter: PCI adapter&lt;br /&gt;
Tctl:         +28.0°C  &lt;br /&gt;
Tccd1:        +27.5°C  &lt;br /&gt;
&lt;br /&gt;
root@daq17:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ASUS PRIME B650-PLUS ==&lt;br /&gt;
&lt;br /&gt;
* BIOS 1811&lt;br /&gt;
* echo modprobe nct6775 &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@dsdaqgw:~# sensors&lt;br /&gt;
amdgpu-pci-0b00&lt;br /&gt;
Adapter: PCI adapter&lt;br /&gt;
vddgfx:      930.00 mV &lt;br /&gt;
vddnb:         1.19 V  &lt;br /&gt;
edge:         +38.0°C  &lt;br /&gt;
PPT:          25.10 W  &lt;br /&gt;
&lt;br /&gt;
nct6799-isa-0290&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
in0:                      920.00 mV (min =  +0.00 V, max =  +1.74 V)&lt;br /&gt;
in1:                        1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in2:                        3.39 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in3:                        3.38 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in4:                        1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in5:                        1.04 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in6:                      320.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in7:                        3.39 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in8:                        3.28 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in9:                        3.38 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in10:                       1.28 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in11:                       1.10 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in12:                       1.04 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in13:                     416.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in14:                     328.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
fan1:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
fan2:                     1253 RPM  (min =    0 RPM)&lt;br /&gt;
fan3:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
fan4:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
fan5:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
fan7:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
SYSTIN:                    +33.0°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermistor&lt;br /&gt;
CPUTIN:                    +35.5°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermistor&lt;br /&gt;
AUXTIN0:                   +78.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN1:                   +11.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN2:                   +20.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN3:                   +82.0°C    sensor = thermistor&lt;br /&gt;
PECI Agent 0 Calibration:  +35.5°C  &lt;br /&gt;
PCH_CHIP_CPU_MAX_TEMP:      +0.0°C  &lt;br /&gt;
PCH_CHIP_TEMP:              +0.0°C  &lt;br /&gt;
PCH_CPU_TEMP:               +0.0°C  &lt;br /&gt;
TSI0_TEMP:                 +42.6°C  &lt;br /&gt;
intrusion0:               ALARM&lt;br /&gt;
intrusion1:               OK&lt;br /&gt;
beep_enable:              disabled&lt;br /&gt;
&lt;br /&gt;
k10temp-pci-00c3&lt;br /&gt;
Adapter: PCI adapter&lt;br /&gt;
Tctl:         +42.6°C  &lt;br /&gt;
Tccd1:        +36.4°C  &lt;br /&gt;
&lt;br /&gt;
root@dsdaqgw:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Enable CPU turbo mode =&lt;br /&gt;
&lt;br /&gt;
* Intel CPU has a nominal CPU frequency (i.e. 3.4GHz) and a turbo-boost CPU frequency (i.e. 4.0GHz). Here we will enable this turbo-boost mode.&lt;br /&gt;
* Find out CPU capability&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq01:~# lscpu | grep Hz&lt;br /&gt;
Model name:                      Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz&lt;br /&gt;
CPU MHz:                         3965.803&lt;br /&gt;
CPU max MHz:                     4000.0000&lt;br /&gt;
CPU min MHz:                     800.0000&lt;br /&gt;
root@daq01:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Look up this CPU in the Intel ARK database - google for the CPU model name, i.e.&lt;br /&gt;
https://ark.intel.com/content/www/us/en/ark/products/88196/intel-core-i7-6700-processor-8m-cache-up-to-4-00-ghz.html&lt;br /&gt;
* Find current frequency settings:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq01:~# cpupower frequency-info&lt;br /&gt;
analyzing CPU 0:&lt;br /&gt;
  driver: intel_pstate&lt;br /&gt;
  CPUs which run at the same hardware frequency: 0&lt;br /&gt;
  CPUs which need to have their frequency coordinated by software: 0&lt;br /&gt;
  maximum transition latency:  Cannot determine or is not supported.&lt;br /&gt;
  hardware limits: 800 MHz - 4.00 GHz&lt;br /&gt;
  available cpufreq governors: performance powersave&lt;br /&gt;
  current policy: frequency should be within 800 MHz and 4.00 GHz.&lt;br /&gt;
                  The governor &amp;quot;powersave&amp;quot; may decide which speed to use&lt;br /&gt;
                  within this range.&lt;br /&gt;
  current CPU frequency: Unable to call hardware&lt;br /&gt;
  current CPU frequency: 2.72 GHz (asserted by call to kernel)&lt;br /&gt;
  boost state support:&lt;br /&gt;
    Supported: yes&lt;br /&gt;
    Active: yes&lt;br /&gt;
root@daq01:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Note the following:&lt;br /&gt;
** current governor is &amp;quot;powersave&amp;quot;&lt;br /&gt;
** &amp;quot;performance&amp;quot; governor is available&lt;br /&gt;
** &amp;quot;boost state support&amp;quot; is supported and active.&lt;br /&gt;
* Confirm CPU frequency governor:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq01:~# cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor&lt;br /&gt;
powersave&lt;br /&gt;
powersave&lt;br /&gt;
powersave&lt;br /&gt;
powersave&lt;br /&gt;
powersave&lt;br /&gt;
powersave&lt;br /&gt;
powersave&lt;br /&gt;
powersave&lt;br /&gt;
root@daq01:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
* Change governor to &amp;quot;performance&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq01:~# cpupower frequency-set --governor performance&lt;br /&gt;
Setting cpu: 0&lt;br /&gt;
Setting cpu: 1&lt;br /&gt;
Setting cpu: 2&lt;br /&gt;
Setting cpu: 3&lt;br /&gt;
Setting cpu: 4&lt;br /&gt;
Setting cpu: 5&lt;br /&gt;
Setting cpu: 6&lt;br /&gt;
Setting cpu: 7&lt;br /&gt;
root@daq01:~# cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor&lt;br /&gt;
performance&lt;br /&gt;
performance&lt;br /&gt;
performance&lt;br /&gt;
performance&lt;br /&gt;
performance&lt;br /&gt;
performance&lt;br /&gt;
performance&lt;br /&gt;
performance&lt;br /&gt;
root@daq01:~# cpupower frequency-info&lt;br /&gt;
analyzing CPU 0:&lt;br /&gt;
  driver: intel_pstate&lt;br /&gt;
  CPUs which run at the same hardware frequency: 0&lt;br /&gt;
  CPUs which need to have their frequency coordinated by software: 0&lt;br /&gt;
  maximum transition latency:  Cannot determine or is not supported.&lt;br /&gt;
  hardware limits: 800 MHz - 4.00 GHz&lt;br /&gt;
  available cpufreq governors: performance powersave&lt;br /&gt;
  current policy: frequency should be within 800 MHz and 4.00 GHz.&lt;br /&gt;
                  The governor &amp;quot;performance&amp;quot; may decide which speed to use&lt;br /&gt;
                  within this range.&lt;br /&gt;
  current CPU frequency: Unable to call hardware&lt;br /&gt;
  current CPU frequency: 3.93 GHz (asserted by call to kernel)&lt;br /&gt;
  boost state support:&lt;br /&gt;
    Supported: yes&lt;br /&gt;
    Active: yes&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* monitor CPU frequency:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq01:~# cpupower monitor&lt;br /&gt;
    | Nehalem                   || Mperf              || Idle_Stats                                     &lt;br /&gt;
 CPU| C3   | C6   | PC3  | PC6   || C0   | Cx   | Freq  || POLL | C1   | C1E  | C3   | C6   | C7s  | C8    &lt;br /&gt;
   0|  0.00|  0.00|  0.00|  0.00|| 88.80| 11.20|  3973||  0.00|  0.00|  0.01|  0.02|  0.31|  0.00|  4.25&lt;br /&gt;
   4|  0.00|  0.00|  0.00|  0.00||  4.70| 95.30|  3945||  0.00|  0.00|  0.00|  0.00|  0.00|  0.00| 95.03&lt;br /&gt;
   1|  0.73|  3.70|  0.00|  0.00||  4.52| 95.48|  3864||  0.00|  0.01|  1.19|  0.44|  2.82|  0.00| 90.23&lt;br /&gt;
   5|  0.73|  3.70|  0.00|  0.00||  0.37| 99.63|  3807||  0.00|  0.00|  0.03|  0.09|  1.70|  0.00| 97.64&lt;br /&gt;
   2|  2.28| 12.86|  0.00|  0.00||  1.41| 98.59|  3829||  0.00|  0.86|  3.17|  0.46|  7.70|  0.00| 85.87&lt;br /&gt;
   6|  2.28| 12.86|  0.00|  0.00||  2.88| 97.12|  3856||  0.00|  0.11|  4.56|  2.15| 10.31|  0.00| 78.99&lt;br /&gt;
   3|  1.33|  4.81|  0.00|  0.00||  0.99| 99.01|  3804||  0.00|  0.49|  0.79|  0.01|  1.03|  0.00| 96.12&lt;br /&gt;
   7|  1.34|  4.81|  0.00|  0.00||  1.26| 98.74|  3818||  0.00|  0.01|  2.32|  0.47|  5.02|  0.00| 90.06&lt;br /&gt;
root@daq01:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* check that the CPU is not overheating:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq01:~# sensors&lt;br /&gt;
coretemp-isa-0000&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
Package id 0:  +51.0°C  (high = +84.0°C, crit = +100.0°C)&lt;br /&gt;
Core 0:        +51.0°C  (high = +84.0°C, crit = +100.0°C)&lt;br /&gt;
Core 1:        +38.0°C  (high = +84.0°C, crit = +100.0°C)&lt;br /&gt;
Core 2:        +34.0°C  (high = +84.0°C, crit = +100.0°C)&lt;br /&gt;
Core 3:        +32.0°C  (high = +84.0°C, crit = +100.0°C)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* congratulations, we are running at 4 GHz now!&lt;br /&gt;
&lt;br /&gt;
= Setup ubuntu as gateway to private network =&lt;br /&gt;
&lt;br /&gt;
See also:&lt;br /&gt;
* https://daq.triumf.ca/DaqWiki/index.php/VME-CPU#Setup_the_boot_host_computer_.28el7.29&lt;br /&gt;
* http://www.triumf.info/wiki/DAQwiki/index.php/Dhcpd_on_eth1&lt;br /&gt;
&lt;br /&gt;
== Steps to do ==&lt;br /&gt;
&lt;br /&gt;
!!! UPDATED 16feb2024 Ubuntu-22.04.03 !!!&lt;br /&gt;
&lt;br /&gt;
* assign network numbers to the private network, i.e. 192.168.1.x, 192.168.2.x, etc&lt;br /&gt;
* (on the gateway machine, each private network interface has to have a different network number)&lt;br /&gt;
* (each network interface can have multiple networks attached, via VLANs or via eth0:0, eth0:1 constructs)&lt;br /&gt;
* assign IP addresses on the private network, save them in /etc/hosts i.e. &amp;quot;hvps 192.168.1.10&amp;quot;&lt;br /&gt;
* (for simplicity, assign 192.168.1.1 to the gateway machine itself)&lt;br /&gt;
* (IP addresses 192.168.1.0 and 192.168.1.255 are &amp;quot;special&amp;quot;, do not use them)&lt;br /&gt;
* setup DNS server (dnsmasq) to serve contents of /etc/hosts via DNS (otherwise, many programs will see inconsistent name to IP address mapping)&lt;br /&gt;
* setup DHCP server (dnsmasq) to give out the IP addresses&lt;br /&gt;
* setup TFTP server (dnsmasq), pxelinux and NFS for diskless booting&lt;br /&gt;
* setup time server (chronyd) to provide common time to all devices&lt;br /&gt;
* setup NAT so machines on private network can access the internet (to get OS updates, etc)&lt;br /&gt;
* setup NIS and NFS so machines on the private network can use common home directories&lt;br /&gt;
* setup rsync backup of machines on the private network&lt;br /&gt;
&lt;br /&gt;
== setup hosts ==&lt;br /&gt;
&lt;br /&gt;
* edit /etc/hosts&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
192.168.1.101 dsfe01&lt;br /&gt;
... and so forth&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== setup dns and dhcp ==&lt;br /&gt;
&lt;br /&gt;
!!! updated 16feb2024 for Ubuntu 22.04.3 !!!&lt;br /&gt;
&lt;br /&gt;
!!! note: stock systemd-resolved remains, is configured to forward queries to dnsmasq, configured to forward queries to TRIUMF DNS !!!&lt;br /&gt;
&lt;br /&gt;
!!! note: per authors of systemd, bare hostnames are not permitted, a DNS domain name must always be used. DNS domain name &amp;quot;dsdaq&amp;quot; is used in this example !!!&lt;br /&gt;
&lt;br /&gt;
* apt install dnsmasq&lt;br /&gt;
* ensure dnsmasq starts after all interfaces are up (Ubuntu-22)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /etc/systemd/system/dnsmasq.service.d&lt;br /&gt;
echo -e &amp;quot;[Unit]\nAfter=network-online.target\n&amp;quot; &amp;gt; /etc/systemd/system/dnsmasq.service.d/local.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* edit /etc/dnsmasq.conf&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# /etc/dnsmasq.conf&lt;br /&gt;
# DNS settings &lt;br /&gt;
#port=0 # disable DNS function &lt;br /&gt;
port=53 # enable DNS function &lt;br /&gt;
bind-interfaces # do not collide with systemd-resolved, we use 127.0.0.1:53, they use 127.0.0.53:53 &lt;br /&gt;
domain-needed &lt;br /&gt;
bogus-priv &lt;br /&gt;
no-resolv &lt;br /&gt;
#log-queries # log DNS quesries &lt;br /&gt;
 &lt;br /&gt;
# TRIUMF DNS settings &lt;br /&gt;
 &lt;br /&gt;
server=142.90.100.19 &lt;br /&gt;
expand-hosts &lt;br /&gt;
domain=dsdaq &lt;br /&gt;
local=/dsdaq/ &lt;br /&gt;
localmx # do not forward MX queries to TRIUMF &lt;br /&gt;
&lt;br /&gt;
# DHCP settings &lt;br /&gt;
interface=enp1s0f0 # VX network 192.168.0.x &lt;br /&gt;
#interface=missing  # FEP and TSP network 192.168.1.x &lt;br /&gt;
interface=enp1s0f1 # controls network 192.168.2.x &lt;br /&gt;
#dhcp-range=192.168.1.50,192.168.1.150,infinite &lt;br /&gt;
dhcp-range=192.168.0.0,static &lt;br /&gt;
dhcp-range=192.168.2.0,static &lt;br /&gt;
log-dhcp # log DHCP queries &lt;br /&gt;
#quiet-dhcp &lt;br /&gt;
dhcp-ignore=tag:!known &lt;br /&gt;
#dhcp-boot=pxelinux.0 &lt;br /&gt;
 &lt;br /&gt;
dhcp-option=option:dns-server,192.168.0.248 &lt;br /&gt;
dhcp-option=option:ntp-server,192.168.0.248 &lt;br /&gt;
 &lt;br /&gt;
# TFTP settings &lt;br /&gt;
 &lt;br /&gt;
enable-tftp &lt;br /&gt;
tftp-root=/tftpboot &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* #mkdir /tftpboot ### per tftp-root (if no ZFS)&lt;br /&gt;
* zfs create -o mountpoint=/tftpboot rpool/tftpboot ### (if root is ZFS)&lt;br /&gt;
* create resolved-dsdaq.conf with main IP address of dnsmasq&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Resolve]&lt;br /&gt;
DNS=192.168.0.248&lt;br /&gt;
Domains=dsdaq triumf.ca&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* mkdir -p /etc/systemd/resolved.conf.d/&lt;br /&gt;
* /bin/rm -f /etc/systemd/resolved.conf.d/*.conf&lt;br /&gt;
* cp resolved-dsdaq.conf /etc/systemd/resolved.conf.d/&lt;br /&gt;
* systemctl stop systemd-resolved.service&lt;br /&gt;
* systemctl disable systemd-resolved.service&lt;br /&gt;
* systemctl enable dnsmasq&lt;br /&gt;
* systemctl restart dnsmasq&lt;br /&gt;
* try to &amp;quot;ping&amp;quot; or &amp;quot;host&amp;quot; some names from /etc/hosts, it should work&lt;br /&gt;
* try to ping daq00, daq00.triumf.ca, all should work&lt;br /&gt;
* resolved-dsdaq.conf goes into /etc/systemd/resolved.conf.d/ of all machines on the private network&lt;br /&gt;
* if not using systemd-resolved, edit /etc/resolv.conf&lt;br /&gt;
&lt;br /&gt;
== setup chronyd ==&lt;br /&gt;
&lt;br /&gt;
* enable ntp server:&lt;br /&gt;
* disable systemd-timesyncd, configure and enable chronyd per instructions above&lt;br /&gt;
* create dsdaq.conf&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# chrony config for dsdaq server&lt;br /&gt;
&lt;br /&gt;
#allow 192.168.0.0&lt;br /&gt;
#allow 192.168.1.0&lt;br /&gt;
#allow 192.168.2.0&lt;br /&gt;
allow all&lt;br /&gt;
&lt;br /&gt;
# end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* cp dsdaq.conf /etc/chrony/conf.d/&lt;br /&gt;
* systemctl restart chronyd&lt;br /&gt;
* chronyc tracking ### wait until time is synchronized (a few seconds)&lt;br /&gt;
* create dsdaq.sources # use hostname or IP address of chronyd server&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Put this file in /etc/chrony/sources.d&lt;br /&gt;
# systemctl restart chrony&lt;br /&gt;
# chronyc sources&lt;br /&gt;
# chronyc tracking&lt;br /&gt;
server dsdaqgw iburst prefer&lt;br /&gt;
# end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* dsdaq.sources goes to /etc/chrony/sources.d of all machines on the private network&lt;br /&gt;
&lt;br /&gt;
== setup diskless network booting ==&lt;br /&gt;
&lt;br /&gt;
=== setup pxelinux for legacy pxe boot ===&lt;br /&gt;
&lt;br /&gt;
* add bits in dnsmasq.conf&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dhcp-host=ac:1f:6b:9e:7f:4a,dsfe01,infinite&lt;br /&gt;
dhcp-boot=pxelinux.0&lt;br /&gt;
dhcp-option=17,&amp;quot;192.168.0.251:/nfsroot/%s,vers=3,tcp&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* setup pxelinux for Ubuntu-18&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~&lt;br /&gt;
wget https://www.kernel.org/pub/linux/utils/boot/syslinux/4.xx/syslinux-4.03.tar.bz2&lt;br /&gt;
tar xjvf syslinux-4.03.tar.bz2&lt;br /&gt;
cd syslinux-4.03&lt;br /&gt;
cp -pv ./core/pxelinux.0 ./com32/hdt/hdt.c32 ./memdisk/memdisk ./com32/menu/menu.c32 /zssd/tftpboot/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* cd /zssd/tftpboot&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://ladd00.triumf.ca/tftpboot/memtest86+-4.20.iso.zip&lt;br /&gt;
wget http://ladd00.triumf.ca/tftpboot/memtest86+-5.01.iso.gz&lt;br /&gt;
wget http://ladd00.triumf.ca/tftpboot/modules.alias&lt;br /&gt;
wget http://ladd00.triumf.ca/tftpboot/modules.pcimap&lt;br /&gt;
wget http://ladd00.triumf.ca/tftpboot/pci.ids&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* mkdir pxelinux.cfg&lt;br /&gt;
* emacs -nw pxelinux.cfg/default&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
default menu.c32&lt;br /&gt;
prompt 0&lt;br /&gt;
&lt;br /&gt;
menu title Welcome to the DSVSLICE PXE boot menu&lt;br /&gt;
&lt;br /&gt;
timeout 50&lt;br /&gt;
&lt;br /&gt;
label hdt&lt;br /&gt;
  kernel hdt.c32&lt;br /&gt;
&lt;br /&gt;
label memtest86+-5.01 &lt;br /&gt;
  kernel memdisk iso initrd=memtest86+-5.01.iso.gz &lt;br /&gt;
&lt;br /&gt;
label memtest86+-4.20&lt;br /&gt;
  kernel memdisk iso initrd=memtest86+-4.20.iso.zip&lt;br /&gt;
&lt;br /&gt;
label vmlinuz-5.3.0-26-generic&lt;br /&gt;
  menu default&lt;br /&gt;
  kernel vmlinuz-5.3.0-26-generic&lt;br /&gt;
  append initrd=initrd.img-5.3.0-26-generic boot=nfs root=/dev/nfs netboot=nfs nfsroot=192.168.1.1:/zssd/nfsroot/dsfe01 toram ip=dhcp panic=60 BOOTIF=enp1s0f0&lt;br /&gt;
&lt;br /&gt;
#end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== setup pxelinux for efi pxe boot ===&lt;br /&gt;
&lt;br /&gt;
* https://c-nergy.be/blog/?p=13808&lt;br /&gt;
* add dnsmasq.conf bits. note: to use dhcp root-path, see the &amp;quot;nfsroot=auto&amp;quot; patch below and make sure to use the &amp;quot;dhcp-option-force&amp;quot; command (mkinitramfs dhcp client does not ask for root-path, we have to force-feed it).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# uefi pxe&lt;br /&gt;
&lt;br /&gt;
dhcp-boot=tag:uefipxe,uefi/syslinux.efi&lt;br /&gt;
dhcp-option-force=tag:fe01,option:root-path,192.168.0.248:/nfsroot/fe01&lt;br /&gt;
&lt;br /&gt;
# VX network 192.168.0.x&lt;br /&gt;
&lt;br /&gt;
dhcp-host=40:a6:b7:c1:d9:c5,fe01,infinite,set:uefipxe,set:fe01&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* apt install syslinux pxelinux syslinux-common syslinux-efi syslinux-utils&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /tftpboot/uefi&lt;br /&gt;
cp /usr/lib/SYSLINUX.EFI/efi64/syslinux.efi /tftpboot/uefi/&lt;br /&gt;
cp /usr/lib/syslinux/modules/efi64/ldlinux.e64 /tftpboot/uefi/&lt;br /&gt;
cp /usr/lib/syslinux/modules/efi64/menu.c32 /tftpboot/uefi/&lt;br /&gt;
cp /usr/lib/syslinux/modules/efi64/hdt.c32 /tftpboot/uefi/&lt;br /&gt;
cp /usr/lib/syslinux/modules/efi64/libutil.c32 /tftpboot/uefi/&lt;br /&gt;
cp /usr/lib/syslinux/modules/efi64/libmenu.c32 /tftpboot/uefi/&lt;br /&gt;
cp /usr/lib/syslinux/modules/efi64/libcom32.c32 /tftpboot/uefi/&lt;br /&gt;
cp /usr/lib/syslinux/modules/efi64/libgpl.c32 /tftpboot/uefi/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* try to boot, it should bomb with &amp;quot;cannot load pxelinux.cfg/default&amp;quot;&lt;br /&gt;
* mkdir /tftpboot/uefi/pxelinux.cfg&lt;br /&gt;
* create /tftpboot/uefi/pxelinux.cfg/default, note nfsroot path is hardwired, note &amp;quot;http:&amp;quot; is used to load vmlinuz and initrd files (because tftp is super slow)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
default menu.c32&lt;br /&gt;
prompt 0&lt;br /&gt;
&lt;br /&gt;
menu title Welcome to the DSDAQGW UEFI PXE boot menu&lt;br /&gt;
&lt;br /&gt;
timeout 50&lt;br /&gt;
&lt;br /&gt;
label vmlinuz-6.5.0-17-generic&lt;br /&gt;
  kernel http://192.168.0.248:8088/uefi/vmlinuz-6.5.0-17-generic&lt;br /&gt;
  append initrd=http://192.168.0.248:8088/uefi/initrd.img-6.5.0-17-generic boot=nfs root=/dev/nfs netboot=nfs nfsroot=auto rw ip=dhcp panic=60&lt;br /&gt;
&lt;br /&gt;
# append initrd=http://192.168.0.248:8088/uefi/initrd.img-6.5.0-17-generic boot=nfs root=/dev/nfs netboot=nfs nfsroot=192.168.0.248:/nfsroot/fe01 rw ip=dhcp panic=60&lt;br /&gt;
&lt;br /&gt;
#  append initrd=initrd.img-6.5.0-17-generic boot=nfs root=/dev/nfs netboot=nfs nfsroot=192.168.0.248:/nfsroot/fe01 rw ip=dhcp panic=60&lt;br /&gt;
#  append initrd=initrd.img-6.5.0-17-generic boot=nfs root=/dev/nfs netboot=nfs nfsroot=auto ip=dhcp rw panic=60&lt;br /&gt;
&lt;br /&gt;
#end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* try to boot, it will bomb with &amp;quot;cannot load http://....&amp;quot;&lt;br /&gt;
* install mini_httpd on port 8088, see https://acme.com/software/mini_httpd/&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install mini-httpd&lt;br /&gt;
emacs -nw /etc/default/mini-httpd # set &amp;quot;START=1&amp;quot;&lt;br /&gt;
emacs -nw /etc/mini-httpd.conf # set &amp;quot;host=192.168.0.248&amp;quot;, &amp;quot;port=8088&amp;quot;, &amp;quot;data_dir=/tftpboot&amp;quot;&lt;br /&gt;
mkdir /etc/systemd/system/mini-httpd.service.d&lt;br /&gt;
echo -e &amp;quot;[Unit]\nAfter=network-online.target\n&amp;quot; &amp;gt; /etc/systemd/system/mini-httpd.service.d/local.conf&lt;br /&gt;
systemctl enable mini-httpd&lt;br /&gt;
systemctl restart mini-httpd&lt;br /&gt;
systemctl status mini-httpd&lt;br /&gt;
wget http://192.168.0.248:8088/uefi/syslinux.efi&lt;br /&gt;
tail -100 /var/log/mini_httpd.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* fix U-22 initramfs bug for &amp;quot;nfsroot=auto&amp;quot;, otherwise, &amp;quot;nfsroot=&amp;quot; has to be different for each machine and you have to have separate pxelinux config files for each machine&lt;br /&gt;
** emacs -nw /usr/lib/initramfs-tools/etc/dhcp/dhclient-enter-hooks.d/config&lt;br /&gt;
** add &amp;quot;echo ROOTPATH=...&amp;quot; if it is missing&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                echo &amp;quot;ROOTSERVER=&#039;${new_routers%% *}&#039;&amp;quot; &lt;br /&gt;
                echo &amp;quot;ROOTPATH=&#039;$new_root_path&#039;&amp;quot; &lt;br /&gt;
                echo &amp;quot;HOSTNAME=&#039;$new_host_name&#039;&amp;quot; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* fix U-24 initramfs bug for &amp;quot;nfsroot=auto&amp;quot;, otherwise, &amp;quot;nfsroot=&amp;quot; has to be different for each machine and you have to have separate pxelinux config files for each machine&lt;br /&gt;
** emacs -nw /usr/share/initramfs-tools/dhcpcd-hooks/70-net-conf&lt;br /&gt;
** add &amp;quot;ROOTPATH=...&amp;quot; if it is missing&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
DNSDOMAIN=&#039;${new_domain_name-}&#039;                                                                                                                                                &lt;br /&gt;
ROOTSERVER=&#039;${new_routers-}&#039;                                                                                                                                                   &lt;br /&gt;
ROOTPATH=&#039;${new_root_path-}&#039;                                                                                                                                                   &lt;br /&gt;
filename=&#039;${new_filename-}&#039;                                                                                                                                                    &lt;br /&gt;
DHCPLEASETIME=&#039;${new_dhcp_lease_time-}&#039;                                                                                                                                        &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
** regenerate initramfs (be careful you generate it for the right kernel!)&lt;br /&gt;
** see https://bugs.launchpad.net/ubuntu/+source/initramfs-tools/+bug/2054482&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitramfs 6.5.0-18-generic&lt;br /&gt;
mkinitramfs 6.8.0-51-generic -o /boot/initrd.img-6.8.0-51-generic&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* copy linux kernel and initrd&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /boot/vmlinuz-6.5.0-18-generic /tftpboot/uefi/&lt;br /&gt;
cp /boot/initrd.img-6.5.0-18-generic /tftpboot/uefi/&lt;br /&gt;
chmod a+r /tftpboot/uefi/*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* try to boot, should bomb with messages about &amp;quot;trying to mount root filesystem&amp;quot;&lt;br /&gt;
* tail /var/log/syslog&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 available DHCP subnet: 192.168.0.0/255.255.255.0&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 vendor class: PXEClient:Arch:00007:UNDI:003016&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 DHCPDISCOVER(enp1s0f0) 40:a6:b7:c1:d9:c5 &lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 tags: uefipxe, fe01, known, enp1s0f0&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 DHCPOFFER(enp1s0f0) 192.168.0.110 40:a6:b7:c1:d9:c5 &lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 1:netmask, 2:time-offset, 3:router, 4, 5, &lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 6:dns-server, 12:hostname, 13:boot-file-size, &lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 15:domain-name, 17:root-path, 18:extension-path, &lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 22:max-datagram-reassembly, 23:default-ttl, &lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 28:broadcast, 40:nis-domain, 41:nis-server, &lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 42:ntp-server, 43:vendor-encap, 50:requested-address, &lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 51:lease-time, 54:server-identifier, 58:T1, &lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 59:T2, 60:vendor-class, 66:tftp-server, 67:bootfile-name, &lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 97:client-machine-id, 128, 129, 130, 131, &lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 132, 133, 134, 135&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 next server: 192.168.0.248&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 broadcast response&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  1 option: 53 message-type  2&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option: 54 server-identifier  192.168.0.248&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option: 51 lease-time  infinite&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size: 18 option: 67 bootfile-name  uefi/syslinux.efi&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option:  1 netmask  255.255.255.0&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option: 28 broadcast  192.168.0.255&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option:  3 router  192.168.0.248&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  5 option: 15 domain-name  dsdaq&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option: 12 hostname  fe01&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size: 27 option: 17 root-path  192.168.0.248:/nfsroot/fe01&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option: 42 ntp-server  192.168.0.248&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option:  6 dns-server  192.168.0.248&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 available DHCP subnet: 192.168.0.0/255.255.255.0&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 vendor class: PXEClient:Arch:00007:UNDI:003016&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 DHCPREQUEST(enp1s0f0) 192.168.0.110 40:a6:b7:c1:d9:c5 &lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 tags: uefipxe, fe01, known, enp1s0f0&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 DHCPACK(enp1s0f0) 192.168.0.110 40:a6:b7:c1:d9:c5 fe01&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 1:netmask, 2:time-offset, 3:router, 4, 5, &lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 6:dns-server, 12:hostname, 13:boot-file-size, &lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 15:domain-name, 17:root-path, 18:extension-path, &lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 22:max-datagram-reassembly, 23:default-ttl, &lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 28:broadcast, 40:nis-domain, 41:nis-server, &lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 42:ntp-server, 43:vendor-encap, 50:requested-address, &lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 51:lease-time, 54:server-identifier, 58:T1, &lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 59:T2, 60:vendor-class, 66:tftp-server, 67:bootfile-name, &lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 97:client-machine-id, 128, 129, 130, 131, &lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 132, 133, 134, 135&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 next server: 192.168.0.248&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 broadcast response&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  1 option: 53 message-type  5&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option: 54 server-identifier  192.168.0.248&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option: 51 lease-time  infinite&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size: 18 option: 67 bootfile-name  uefi/syslinux.efi&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option:  1 netmask  255.255.255.0&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option: 28 broadcast  192.168.0.255&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option:  3 router  192.168.0.248&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  5 option: 15 domain-name  dsdaq&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option: 12 hostname  fe01&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size: 27 option: 17 root-path  192.168.0.248:/nfsroot/fe01&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option: 42 ntp-server  192.168.0.248&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option:  6 dns-server  192.168.0.248&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-tftp[3629416]: error 8 User aborted the transfer received from 192.168.0.110&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-tftp[3629416]: sent /tftpboot/uefi/syslinux.efi to 192.168.0.110&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-tftp[3629416]: sent /tftpboot/uefi/syslinux.efi to 192.168.0.110&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 available DHCP subnet: 192.168.0.0/255.255.255.0&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 DHCPDISCOVER(enp1s0f0) 40:a6:b7:c1:d9:c5 &lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 tags: uefipxe, fe01, known, enp1s0f0&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 DHCPOFFER(enp1s0f0) 192.168.0.110 40:a6:b7:c1:d9:c5 &lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 requested options: 1:netmask, 3:router, 6:dns-server&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 bootfile name: uefi/syslinux.efi&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 next server: 192.168.0.248&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 broadcast response&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  1 option: 53 message-type  2&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  4 option: 54 server-identifier  192.168.0.248&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  4 option: 51 lease-time  infinite&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  4 option:  1 netmask  255.255.255.0&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  4 option: 28 broadcast  192.168.0.255&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  4 option:  3 router  192.168.0.248&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size: 27 option: 17 root-path  192.168.0.248:/nfsroot/fe01&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  4 option:  6 dns-server  192.168.0.248&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 available DHCP subnet: 192.168.0.0/255.255.255.0&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 DHCPREQUEST(enp1s0f0) 192.168.0.110 40:a6:b7:c1:d9:c5 &lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 tags: uefipxe, fe01, known, enp1s0f0&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 DHCPACK(enp1s0f0) 192.168.0.110 40:a6:b7:c1:d9:c5 fe01&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 requested options: 1:netmask, 3:router, 6:dns-server&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 bootfile name: uefi/syslinux.efi&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 next server: 192.168.0.248&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 broadcast response&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  1 option: 53 message-type  5&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  4 option: 54 server-identifier  192.168.0.248&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  4 option: 51 lease-time  infinite&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  4 option:  1 netmask  255.255.255.0&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  4 option: 28 broadcast  192.168.0.255&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  4 option:  3 router  192.168.0.248&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size: 27 option: 17 root-path  192.168.0.248:/nfsroot/fe01&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  4 option:  6 dns-server  192.168.0.248&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-tftp[3629416]: sent /tftpboot/uefi/ldlinux.e64 to 192.168.0.110&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-tftp[3629416]: file /tftpboot/uefi/pxelinux.cfg/01-40-a6-b7-c1-d9-c5 not found&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-tftp[3629416]: file /tftpboot/uefi/pxelinux.cfg/C0A8006E not found&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-tftp[3629416]: file /tftpboot/uefi/pxelinux.cfg/C0A8006 not found&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-tftp[3629416]: file /tftpboot/uefi/pxelinux.cfg/C0A800 not found&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-tftp[3629416]: file /tftpboot/uefi/pxelinux.cfg/C0A80 not found&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-tftp[3629416]: file /tftpboot/uefi/pxelinux.cfg/C0A8 not found&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-tftp[3629416]: file /tftpboot/uefi/pxelinux.cfg/C0A not found&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-tftp[3629416]: file /tftpboot/uefi/pxelinux.cfg/C0 not found&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-tftp[3629416]: file /tftpboot/uefi/pxelinux.cfg/C not found&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-tftp[3629416]: sent /tftpboot/uefi/pxelinux.cfg/default to 192.168.0.110&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-tftp[3629416]: sent /tftpboot/uefi/menu.c32 to 192.168.0.110&lt;br /&gt;
Feb 16 20:43:10 dsdaqgw dnsmasq-tftp[3629416]: sent /tftpboot/uefi/libutil.c32 to 192.168.0.110&lt;br /&gt;
Feb 16 20:43:10 dsdaqgw dnsmasq-tftp[3629416]: sent /tftpboot/uefi/pxelinux.cfg/default to 192.168.0.110&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 available DHCP subnet: 192.168.0.0/255.255.255.0&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 client provides name: dsdaqgw.triumf.ca&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 DHCPDISCOVER(enp1s0f0) 40:a6:b7:c1:d9:c5 &lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 tags: uefipxe, fe01, known, enp1s0f0&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 DHCPOFFER(enp1s0f0) 192.168.0.110 40:a6:b7:c1:d9:c5 &lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 requested options: 1:netmask, 28:broadcast, 2:time-offset, 3:router, &lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 requested options: 15:domain-name, 6:dns-server, 119:domain-search, &lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 requested options: 12:hostname, 44:netbios-ns, 47:netbios-scope, &lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 requested options: 26:mtu, 121:classless-static-route, 42:ntp-server&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 bootfile name: uefi/syslinux.efi&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 next server: 192.168.0.248&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  1 option: 53 message-type  2&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option: 54 server-identifier  192.168.0.248&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option: 51 lease-time  infinite&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option:  1 netmask  255.255.255.0&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option: 28 broadcast  192.168.0.255&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option:  3 router  192.168.0.248&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  5 option: 15 domain-name  dsdaq&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size: 27 option: 17 root-path  192.168.0.248:/nfsroot/fe01&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option: 42 ntp-server  192.168.0.248&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option:  6 dns-server  192.168.0.248&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 available DHCP subnet: 192.168.0.0/255.255.255.0&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 client provides name: dsdaqgw.triumf.ca&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 DHCPREQUEST(enp1s0f0) 192.168.0.110 40:a6:b7:c1:d9:c5 &lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 tags: uefipxe, fe01, known, enp1s0f0&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 DHCPACK(enp1s0f0) 192.168.0.110 40:a6:b7:c1:d9:c5 fe01&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 requested options: 1:netmask, 28:broadcast, 2:time-offset, 3:router, &lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 requested options: 15:domain-name, 6:dns-server, 119:domain-search, &lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 requested options: 12:hostname, 44:netbios-ns, 47:netbios-scope, &lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 requested options: 26:mtu, 121:classless-static-route, 42:ntp-server&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 bootfile name: uefi/syslinux.efi&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 next server: 192.168.0.248&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  1 option: 53 message-type  5&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option: 54 server-identifier  192.168.0.248&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option: 51 lease-time  infinite&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option:  1 netmask  255.255.255.0&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option: 28 broadcast  192.168.0.255&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option:  3 router  192.168.0.248&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  5 option: 15 domain-name  dsdaq&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option: 12 hostname  fe01&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size: 27 option: 17 root-path  192.168.0.248:/nfsroot/fe01&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option: 42 ntp-server  192.168.0.248&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option:  6 dns-server  192.168.0.248&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw rpc.mountd[3350210]: authenticated mount request from 192.168.0.110:981 for /nfsroot/fe01 (/nfsroot/fe01)&lt;br /&gt;
Feb 16 20:45:07 dsdaqgw rpc.mountd[3350210]: authenticated unmount request from 192.168.0.110:859 for /nfsroot/fe01/tmp/autoDY4k5u (/nfsroot/fe01)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* tail /var/log/mini_httpd.log&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
192.168.0.110 - - [16/Feb/2024:20:43:15 -0800] &amp;quot;GET /uefi/vmlinuz-6.5.0-17-generic HTTP/1.0&amp;quot; 200 14227944 &amp;quot;&amp;quot; &amp;quot;Syslinux/6.04&amp;quot;&lt;br /&gt;
192.168.0.110 - - [16/Feb/2024:20:43:24 -0800] &amp;quot;GET /uefi/initrd.img-6.5.0-17-generic HTTP/1.0&amp;quot; 200 137824833 &amp;quot;&amp;quot; &amp;quot;Syslinux/6.04&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== setup efi http boot ===&lt;br /&gt;
&lt;br /&gt;
https://documentation.suse.com/sles/15-SP2/html/SLES-all/cha-deployment-prep-uefi-httpboot.html&lt;br /&gt;
&lt;br /&gt;
=== setup linux kernel ===&lt;br /&gt;
&lt;br /&gt;
* copy the kernel files&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot&lt;br /&gt;
rsync -av config* initrd* System.map* vmlinuz* /tftpboot/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* cd /tftpboot&lt;br /&gt;
* chmod a+r *&lt;br /&gt;
&lt;br /&gt;
=== setup nfs ===&lt;br /&gt;
&lt;br /&gt;
* apt-get install nfs-kernel-server&lt;br /&gt;
* enable NFS over UDP, edit /etc/nfs.conf add &amp;quot;udp=y&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
udp=y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl restart nfs-server.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* emacs -nw /etc/exports&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/nfsroot/dsfe01 dsfe01(rw,no_root_squash,async,no_subtree_check)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* enable services&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl enable nfs-server&lt;br /&gt;
systemctl enable nfs-mountd&lt;br /&gt;
systemctl enable nfs-idmapd&lt;br /&gt;
systemctl restart nfs-server&lt;br /&gt;
systemctl restart nfs-mountd&lt;br /&gt;
systemctl restart nfs-idmapd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* after editing /etc/exports, run&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exportfs -av&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== setup userland ===&lt;br /&gt;
&lt;br /&gt;
!!! ubuntu-18 version !!!&lt;br /&gt;
&lt;br /&gt;
* zfs create rpool/nfsroot&lt;br /&gt;
* zfs set dedup=verify rpool/nfsroot ### enable deduplication to save disk space because most linux images have mostly identical files&lt;br /&gt;
* clone ubuntu&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /nfsroot/dsfe01&lt;br /&gt;
cd /&lt;br /&gt;
rsync -avx . /nfsroot/dsfe01&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* edit config files:&lt;br /&gt;
* cd /nfsroot/dsfe01&lt;br /&gt;
* emacs -nw etc/hostname ### change to dsfe01&lt;br /&gt;
* emacs -nw etc/mailname ### change to dsfe01&lt;br /&gt;
* emacs -nw etc/yp.conf ### change daq00.triumf.ca to musr00.triumf.ca&lt;br /&gt;
* emacs -nw etc/defaultdomain ### change to MUSR-NIS&lt;br /&gt;
* cp -pvf ../lxcpet-SL610/etc/ssh/*key* etc/ssh/ ### preserve the ssh keys&lt;br /&gt;
* emacs -nw opt/gonodeinfo/gonodeinfo.conf ### update information&lt;br /&gt;
* emacs -nw root/.ssh/authorized_keys ### update root ssh keys&lt;br /&gt;
* emacs -nw etc/fstab ### add this&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
192.168.1.1:/nfsroot/dsfe01 / nfs defaults,nolock 0 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* emacs -nw etc/chrony/chrony.conf&lt;br /&gt;
** comment-out all &amp;quot;pool&amp;quot; and &amp;quot;server&amp;quot; entries&lt;br /&gt;
** add entry &amp;quot;server 192.168.1.1 iburst&amp;quot;&lt;br /&gt;
&lt;br /&gt;
After dsfe01 is booted:&lt;br /&gt;
&lt;br /&gt;
* disable services:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl disable apache2&lt;br /&gt;
systemctl disable dnsmasq&lt;br /&gt;
systemctl disable zfs-import-cache&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To setup additional machines, clone dsfe01 instead of cloning the gateway machine&lt;br /&gt;
&lt;br /&gt;
=== Allow manpages to be viewed ===&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; is mounted over NFS, &amp;lt;code&amp;gt;man&amp;lt;/code&amp;gt; will report a permission error. Fix it with:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ln -s /etc/apparmor.d/usr.bin.man /etc/apparmor.d/disable/&lt;br /&gt;
apparmor_parser -R /etc/apparmor.d/usr.bin.man&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== setup shared home directory ==&lt;br /&gt;
&lt;br /&gt;
=== on the gateway machine ===&lt;br /&gt;
* define netgroups&lt;br /&gt;
* emacs -nw /etc/netgroup&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dsfe (dsfe01,,) (dsfe02,,)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* emacs -nw /etc/nsswitch.conf ### edit the netgroup line to read:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
netgroup: files&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* export the home directories:&lt;br /&gt;
* emacs -nw /etc/exports ### add this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/zssd/home1 @dsfe(rw,no_root_squash,async,no_subtree_check)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* exportfs -rc&lt;br /&gt;
&lt;br /&gt;
=== on the frontend machine ===&lt;br /&gt;
&lt;br /&gt;
* mkdir /home&lt;br /&gt;
* emacs -nw /etc/fstab ### add this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
192.168.1.1:/zssd/home1 /home nfs defaults 0 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* mount -a&lt;br /&gt;
&lt;br /&gt;
== setup NAT ==&lt;br /&gt;
&lt;br /&gt;
NAT allows machines on the private network to connect to the internet: https://en.wikipedia.org/wiki/Network_address_translation&lt;br /&gt;
&lt;br /&gt;
In these examples:&lt;br /&gt;
* replace &amp;quot;eno1&amp;quot; with name of the outgoing interface (the one connected to the TRIUMF network).&lt;br /&gt;
* replace &amp;quot;enp11s0&amp;quot; with name of the private network interface (192.168.1.x network)&lt;br /&gt;
&lt;br /&gt;
* emacs -nw /etc/rc.local ### add this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# /etc/rc.local&lt;br /&gt;
&lt;br /&gt;
# enable NAT&lt;br /&gt;
&lt;br /&gt;
/sbin/iptables -t nat -A POSTROUTING -o eno1 -j MASQUERADE&lt;br /&gt;
iptables -L -v&lt;br /&gt;
&lt;br /&gt;
# uncomment following lines if machine has prohibitive FORWARD rules:&lt;br /&gt;
#/sbin/iptables -I FORWARD -i eno1 -o enp11s0 -m state --state RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
#/sbin/iptables -I FORWARD -i enp11s0 -o eno1 -j ACCEPT&lt;br /&gt;
#iptables -L -v&lt;br /&gt;
&lt;br /&gt;
iptables -L -v&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
#sysctl -a | grep forward&lt;br /&gt;
&lt;br /&gt;
sh /etc/firewall-rfc1918.sh&lt;br /&gt;
&lt;br /&gt;
# end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* emacs -nw /etc/firewall-rfc1918.sh&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# firewall-rfc1918.sh&lt;br /&gt;
&lt;br /&gt;
# prevent RFC1918 private network IP addresses from&lt;br /&gt;
# going in and out from our uplink.&lt;br /&gt;
&lt;br /&gt;
ETH=eno1&lt;br /&gt;
&lt;br /&gt;
iptables -F in-rfc1918&lt;br /&gt;
iptables -N in-rfc1918&lt;br /&gt;
iptables -A in-rfc1918 --dst 10.0.0.0/8      -j REJECT&lt;br /&gt;
iptables -A in-rfc1918 --dst 172.16.0.0/12   -j REJECT&lt;br /&gt;
iptables -A in-rfc1918 --dst 192.168.0.0/16  -j REJECT&lt;br /&gt;
&lt;br /&gt;
iptables -D INPUT -j in-rfc1918 -i $ETH&lt;br /&gt;
iptables -D INPUT -j in-rfc1918 -i $ETH&lt;br /&gt;
iptables -I INPUT -j in-rfc1918 -i $ETH&lt;br /&gt;
&lt;br /&gt;
iptables -F out-rfc1918&lt;br /&gt;
iptables -N out-rfc1918&lt;br /&gt;
iptables -A out-rfc1918 --dst 10.0.0.0/8      -j REJECT&lt;br /&gt;
iptables -A out-rfc1918 --dst 172.16.0.0/12   -j REJECT&lt;br /&gt;
iptables -A out-rfc1918 --dst 192.168.0.0/16  -j REJECT&lt;br /&gt;
&lt;br /&gt;
iptables -D OUTPUT -j out-rfc1918 -o $ETH&lt;br /&gt;
iptables -D OUTPUT -j out-rfc1918 -o $ETH&lt;br /&gt;
iptables -I OUTPUT -j out-rfc1918 -o $ETH&lt;br /&gt;
&lt;br /&gt;
iptables -D FORWARD -j out-rfc1918 -o $ETH &lt;br /&gt;
iptables -D FORWARD -j out-rfc1918 -o $ETH &lt;br /&gt;
iptables -I FORWARD -j out-rfc1918 -o $ETH &lt;br /&gt;
&lt;br /&gt;
# allow TRIUMF-SECURE network&lt;br /&gt;
&lt;br /&gt;
iptables -I in-rfc1918 -s 10.90.0.0/255.255.0.0 -j ACCEPT &lt;br /&gt;
iptables -I out-rfc1918 -d 10.90.0.0/255.255.0.0 -j ACCEPT &lt;br /&gt;
&lt;br /&gt;
# show configuration&lt;br /&gt;
&lt;br /&gt;
iptables -L -v&lt;br /&gt;
&lt;br /&gt;
#end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= KVM =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install cpu-checker&lt;br /&gt;
&lt;br /&gt;
root@daq13:~# kvm-ok &lt;br /&gt;
INFO: /dev/kvm exists&lt;br /&gt;
KVM acceleration can be used&lt;br /&gt;
root@daq13:~# &lt;br /&gt;
&lt;br /&gt;
(if not, shutdown, go into BIOS settings, enable CPU virtualization)&lt;br /&gt;
&lt;br /&gt;
apt install virtinst ### will install many packages&lt;br /&gt;
apt install libvirt-clients libvirt-daemon-system-systemd libvirt-daemon qemu qemu-kvm libvirt-daemon-system virtinst bridge-utils&lt;br /&gt;
&lt;br /&gt;
root@daq13:/home1/wheel# virsh list --all&lt;br /&gt;
 Id   Name           State&lt;br /&gt;
------------------------------&lt;br /&gt;
 1    ubuntu-guest   running&lt;br /&gt;
&lt;br /&gt;
apt install virt-manager&lt;br /&gt;
&lt;br /&gt;
virt-install --name ubuntu-guest --os-variant ubuntu20.04 --vcpus 2 --ram 2048 --location /daq/daqstore/olchansk/linux/Ubuntu/ubuntu-20.04.3-desktop-amd64.iso --network bridge=virbr0,model=virtio --graphics none --extra-args=&#039;console=ttyS0,115200n8 serial&#039;&lt;br /&gt;
&lt;br /&gt;
virtual machine will start, boot, etc&lt;br /&gt;
to get out of it, CTRL + Shift followed by ]&lt;br /&gt;
&lt;br /&gt;
ssh wheel@daq13&lt;br /&gt;
virt-manager&lt;br /&gt;
&lt;br /&gt;
run virt-install again, omit &amp;quot;--graphics none&amp;quot;, open graphics console from virt-manager, it booted into ubuntu installer desktop&lt;br /&gt;
&lt;br /&gt;
virt-install --name test10 --os-variant centos6.10 --vcpus 2 --ram 2048 --import --filesystem /kvm_ladd00,/ --network bridge=virbr0,model=virtio --boot kernel=/kvm_ladd00/boot/vmlinuz-2.6.32-754.35.1.el6.x86_64,initrd=/kvm_ladd00/boot/initramfs-2.6.32-754.35.1.el6.x86_64.img,kernel_args=&amp;quot;root=/dev/sda console=ttyS0,115200n8 serial&amp;quot; --graphics none&lt;br /&gt;
&lt;br /&gt;
virt-install --name test14 --os-variant centos6.10 --vcpus 2 --ram 2048 --import --disk /tmp/xxx/ladd00.img,bus=sata --network bridge=virbr0,model=virtio --boot kernel=/kvm_ladd00/boot/vmlinuz-2.6.32-754.35.1.el6.x86_64,initrd=/kvm_ladd00/boot/initramfs-2.6.32-754.35.1.el6.x86_64.img,kernel_args=&amp;quot;root=/dev/sda console=ttyS0,115200n8 serial rdshell&amp;quot; --graphics none --check path_in_use=off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
build image&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dd if=/dev/zero of=/tmp/xxx/ladd00.img bs=1024M count=20&lt;br /&gt;
mkfs.ext3 /tmp/xxx/ladd00.img ### ext4 fails to mount by SL6 kernel, &amp;quot;unknown ext4 options&amp;quot;&lt;br /&gt;
cd /kvm_ladd00/&lt;br /&gt;
mount -o loop /tmp/xxx/ladd00.img /mnt/tmp&lt;br /&gt;
rsync -av . /mnt/tmp/ --delete&lt;br /&gt;
umount /mnt/tmp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
on the guest, configure network: /etc/rc.local&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
#&lt;br /&gt;
# This script will be executed *after* all the other init scripts.&lt;br /&gt;
# You can put your own initialization stuff in here if you don&#039;t&lt;br /&gt;
# want to do the full Sys V style init stuff.&lt;br /&gt;
&lt;br /&gt;
touch /var/lock/subsys/local&lt;br /&gt;
&lt;br /&gt;
ifconfig eth2 192.168.122.2&lt;br /&gt;
route add -net 0.0.0.0 gw 192.168.122.1&lt;br /&gt;
ifconfig -a&lt;br /&gt;
netstat -rn&lt;br /&gt;
&lt;br /&gt;
# end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== virsh commands ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
virsh list --all&lt;br /&gt;
&lt;br /&gt;
virsh start kvm-el7&lt;br /&gt;
virsh console kvm-el7&lt;br /&gt;
virsh destroy kvm-el7&lt;br /&gt;
&lt;br /&gt;
virsh install ...&lt;br /&gt;
virsh undefine kvm-el7&lt;br /&gt;
&lt;br /&gt;
virsh autostart kvm-ladd00&lt;br /&gt;
virsh dominfo kvm-ladd00&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== virtualize SL6 ladd00 ==&lt;br /&gt;
&lt;br /&gt;
* on ladd00:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
yum install dracut-network&lt;br /&gt;
mkinitrd /boot/initramfs-2.6.32-754.35.1.el6.x86_64-netboot.img 2.6.32-754.35.1.el6.x86_64&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* on daq00&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs create rpool/kvm-ladd00&lt;br /&gt;
cd /kvm-ladd00&lt;br /&gt;
rsync -avx ladd00:/ . --exclude nfsroot&lt;br /&gt;
brctl addbr virbr0&lt;br /&gt;
ifconfig virbr0 192.168.1.1&lt;br /&gt;
echo /kvm-ladd00 192.168.1.2(rw,no_root_squash,no_all_squash,async,no_subtree_check) &amp;gt;&amp;gt; /etc/exports&lt;br /&gt;
exportfs -rv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* create virtual machine&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
virt-install --name kvm-ladd00 --os-variant centos6.10 --vcpus 2 --ram 2048 --import --network bridge=virbr0,model=virtio --boot kernel=/kvm-ladd00/boot/vmlinuz-2.6.32-754.35.1.el6.x86_64,initrd=/kvm-ladd00/boot/initramfs-2.6.32-754.35.1.el6.x86_64-netboot.img,kernel_args=&amp;quot;root=/dev/nfs ip=192.168.1.2:192.168.1.1:192.168.1.1:255.255.255.0:ladd00::off nfsroot=192.168.1.1:/kvm-ladd00,vers=3,tcp console=ttyS0,115200n8 serial rdshell&amp;quot; --graphics none --nodisks --check path_in_use=off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* adjust kvm-ladd00 image&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
disable network manager&lt;br /&gt;
edit fstab&lt;br /&gt;
edit yp.conf&lt;br /&gt;
edit resolv.conf&lt;br /&gt;
edit root/.ssh/authorized_keys&lt;br /&gt;
enable rngd or /dev/random does not work, sshd does not work&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* virsh shutdown test24&lt;br /&gt;
* virsh --connect qemu:///system start test24&lt;br /&gt;
* virsh console test24 ### to exit, ctrl+[ or ctrl+]&lt;br /&gt;
* virsh undefine test24&lt;br /&gt;
* virsh autostart kvm-ladd00&lt;br /&gt;
* virsh dominfo kvm-ladd00&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq00:~# virsh dominfo kvm-ladd00&lt;br /&gt;
Id:             1&lt;br /&gt;
Name:           kvm-ladd00&lt;br /&gt;
UUID:           1d1f8fed-8b65-4411-a51b-e0ecf359d2f1&lt;br /&gt;
OS Type:        hvm&lt;br /&gt;
State:          running&lt;br /&gt;
CPU(s):         2&lt;br /&gt;
CPU time:       27.7s&lt;br /&gt;
Max memory:     2097152 KiB&lt;br /&gt;
Used memory:    2097152 KiB&lt;br /&gt;
Persistent:     yes&lt;br /&gt;
Autostart:      enable&lt;br /&gt;
Managed save:   no&lt;br /&gt;
Security model: apparmor&lt;br /&gt;
Security DOI:   0&lt;br /&gt;
Security label: libvirt-1d1f8fed-8b65-4411-a51b-e0ecf359d2f1 (enforcing)&lt;br /&gt;
root@daq00:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* delete unused images in /var/lib/libvirt/images&lt;br /&gt;
* virsh edit kvm-ladd00 # change boot command line, etc&lt;br /&gt;
&lt;br /&gt;
== virtualize CentOS-7 daqstore ==&lt;br /&gt;
&lt;br /&gt;
* similar to ladd00 above:&lt;br /&gt;
* on daqstore, install dracut-network, already there&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
yum install dracut-network&lt;br /&gt;
yum install qemu-kvm libvirt libvirt-python libguestfs-tools virt-install&lt;br /&gt;
# yum install busybox ### no rpm package?!?&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dracut -a nfs -v /boot/initramfs-3.10.0-1160.119.1.el7.x86_64-virt.img 3.10.0-1160.119.1.el7.x86_64 --force&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
scp daqstore:/boot/initramfs-3.10.0-1160.119.1.el7.x86_64-virt.img /kvm-el7/boot/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* on daq00&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs create rpool/kvm-el7&lt;br /&gt;
cd /kvm-el7&lt;br /&gt;
rsync -avx daqstore:/ .&lt;br /&gt;
echo 192.168.1.3 kvm-el7 &amp;gt;&amp;gt; /etc/hosts&lt;br /&gt;
systemctl restart dnsmasq&lt;br /&gt;
echo /kvm-el 192.168.1.3(rw,no_root_squash,no_all_squash,async,no_subtree_check) &amp;gt;&amp;gt; /etc/exports&lt;br /&gt;
exportfs -rv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* manage virtual machine&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
virsh console kvm-el7&lt;br /&gt;
virsh destroy kvm-el7&lt;br /&gt;
virsh undefine kvm-el7&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* create virtual machine&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
virt-install --name kvm-el7 --os-variant centos7 --vcpus 2 --ram 2048 --import --network bridge=virbr0,model=e1000e --boot kernel=/kvm-el7/boot/vmlinuz-3.10.0-1160.119.1.el7.x86_64,initrd=/kvm-el7/boot/initramfs-3.10.0-1160.119.1.el7.x86_64-virt.img,kernel_args=&amp;quot;root=/dev/nfs ip=192.168.1.3:192.168.1.1:192.168.1.1:255.255.255.0:kvm-el7::off nfsroot=192.168.1.1:/kvm-el7,vers=3,tcp rw console=ttyS0,115200n8 serial rdshell&amp;quot; --graphics none --nodisks --check path_in_use=off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* adjust kvm-el7 image&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
disable network manager&lt;br /&gt;
edit fstab&lt;br /&gt;
edit hostname&lt;br /&gt;
disable selinux in /etc/sysconfig/selinux&lt;br /&gt;
&lt;br /&gt;
UP TO HERE --- DNS does not work!!!&lt;br /&gt;
&lt;br /&gt;
edit yp.conf&lt;br /&gt;
edit resolv.conf&lt;br /&gt;
edit root/.ssh/authorized_keys&lt;br /&gt;
enable rngd or /dev/random does not work, sshd does not work&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* virsh shutdown test24&lt;br /&gt;
* virsh --connect qemu:///system start test24&lt;br /&gt;
* virsh console test24 ### to exit, ctrl+[ or ctrl+]&lt;br /&gt;
* virsh undefine test24&lt;br /&gt;
* virsh autostart kvm-ladd00&lt;br /&gt;
* virsh dominfo kvm-ladd00&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq00:~# virsh dominfo kvm-ladd00&lt;br /&gt;
Id:             1&lt;br /&gt;
Name:           kvm-ladd00&lt;br /&gt;
UUID:           1d1f8fed-8b65-4411-a51b-e0ecf359d2f1&lt;br /&gt;
OS Type:        hvm&lt;br /&gt;
State:          running&lt;br /&gt;
CPU(s):         2&lt;br /&gt;
CPU time:       27.7s&lt;br /&gt;
Max memory:     2097152 KiB&lt;br /&gt;
Used memory:    2097152 KiB&lt;br /&gt;
Persistent:     yes&lt;br /&gt;
Autostart:      enable&lt;br /&gt;
Managed save:   no&lt;br /&gt;
Security model: apparmor&lt;br /&gt;
Security DOI:   0&lt;br /&gt;
Security label: libvirt-1d1f8fed-8b65-4411-a51b-e0ecf359d2f1 (enforcing)&lt;br /&gt;
root@daq00:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* delete unused images in /var/lib/libvirt/images&lt;br /&gt;
* virsh edit kvm-ladd00 # change boot command line, etc&lt;br /&gt;
&lt;br /&gt;
= ARM64 cross-compiler =&lt;br /&gt;
&lt;br /&gt;
* arm64, aarch64 are Xilinx FPGA Cortex-A53, RPi4, RPi5 machines&lt;br /&gt;
* install packages:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install g++-12-aarch64-linux-gnu gcc-12-aarch64-linux-gnu-base libstdc++-12-dev-arm64-cross&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
aarch64-linux-gnu-gcc-12 -o ttcp.aarch64 ttcp.c -static&lt;br /&gt;
aarch64-linux-gnu-g++-12 -o fecdm.exe -O2 -g -Wall -Wuninitialized -std=c++20 fecdm.o dsdm.o /home/dsdaqdev/packages_common/midas/linux-aarch64-remoteonly/lib/libmidas.a -pthread -lrt -lutil /nfsroot/gdm00/usr/lib/aarch64-linux-gnu/libi2c.a -static&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= ARM cross-compiler =&lt;br /&gt;
&lt;br /&gt;
NOTE: updated for U-24&lt;br /&gt;
&lt;br /&gt;
* armv7 (Cyclone-V SoC, RPi3, MityARM CAMAC) machines (Debian-12 armhf target, Ubuntu 24.04 host)&lt;br /&gt;
* install packages:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install g++-arm-linux-gnueabihf gcc-arm-linux-gnueabihf libc6-dev-armhf-cross&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* build MIDAS frontend (static linking)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
arm-linux-gnueabihf-g++ -std=c++11 -Wall -Wuninitialized -g -O2 -I/home/dldaq/packages/midas/include -I/home/dldaq/packages/midas/mvodb -c koi2c.cxx&lt;br /&gt;
arm-linux-gnueabihf-g++ -o fedldb.exe -std=c++11 -Wall -Wuninitialized -g -O2 -I/home/dldaq/packages/midas/include -I/home/dldaq/packages/midas/mvodb fedldb.o koi2c.o /home/dldaq/packages/midas/linux-armv7-remoteonly/lib/libmidas.a -L/usr/arm-linux-gnueabihf/lib -L/nfsroot/dltdc/usr/lib/arm-linux-gnueabihf -static -lm -lz -lutil -lnsl -lpthread -lrt -li2c&lt;br /&gt;
/usr/lib/gcc-cross/arm-linux-gnueabihf/13/../../../../arm-linux-gnueabihf/bin/ld: /home/dldaq/packages/midas/linux-armv7-remoteonly/lib/libmidas.a(system.o): in function `ss_socket_connect_tcp(char const*, int, int*, std::__cxx11::basic_string&amp;lt;char, std::char_traits&amp;lt;char&amp;gt;, std::allocator&amp;lt;char&amp;gt; &amp;gt;*)&#039;:&lt;br /&gt;
/home/dldaq/packages/midas/src/system.cxx:4984:(.text+0x252a): warning: Using &#039;getaddrinfo&#039; in statically linked applications requires at runtime the shared libraries from the glibc version used for linking&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= 32-bit intel cross-compiler =&lt;br /&gt;
&lt;br /&gt;
Ubuntu 22.04:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install libstdc++-11-dev:i386&lt;br /&gt;
apt install zlib1g-dev:i386&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
NOTES:&lt;br /&gt;
* &amp;quot;g++ -m32&amp;quot; does not find libstdc++, please use &amp;quot;g++ -m32 -L/usr/lib/gcc/i686-linux-gnu/11/&amp;quot;&lt;br /&gt;
* to cross-build 32-bit MIDAS, use &amp;quot;make linux32&amp;quot;.&lt;br /&gt;
* executables cross-build on Ubuntu-22 do NOT run on 32-bit Debain-11 (GLIBC and GLIBCXX version mismatch)&lt;br /&gt;
* executables cross-build on Ubuntu-22 run on 32-bit Debian-12.&lt;br /&gt;
&lt;br /&gt;
Ubuntu 24.04:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install gcc-i686-linux-gnu&lt;br /&gt;
apt install g++-i686-linux-gnu&lt;br /&gt;
apt install libstdc++-13-dev:i386&lt;br /&gt;
apt install lib32z1 lib32z1-dev&lt;br /&gt;
i686-linux-gnu-gcc -o ttcp.i386 ttcp.c&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
NOTES:&lt;br /&gt;
* executables cross-build on Ubuntu-24 will NOT run on 32-bit Debian-12 (GLIBC mismatch, static executables maybe work)&lt;br /&gt;
* executables cross-build on Ubuntu-24 run on 32-bit Debian-13&lt;br /&gt;
&lt;br /&gt;
= SSH settings for EPICS =&lt;br /&gt;
&lt;br /&gt;
* TRIUMF EPICS runs obsolete version of SSH&lt;br /&gt;
* add this to the use .ssh/config&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Host sbp1*&lt;br /&gt;
HostKeyAlgorithms +ssh-rsa&lt;br /&gt;
PubKeyAcceptedAlgorithms +ssh-rsa&lt;br /&gt;
KexAlgorithms +diffie-hellman-group1-sha1&lt;br /&gt;
ForwardX11 yes&lt;br /&gt;
ForwardX11Trusted yes&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= changes for VME processors =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y remove sysstat man-db&lt;br /&gt;
apt -y purge dkms&lt;br /&gt;
apt -y purge mdadm&lt;br /&gt;
apt -y purge fwupd&lt;br /&gt;
apt -y purge packagekit&lt;br /&gt;
apt -y purge accountsservice&lt;br /&gt;
apt -y purge plocate&lt;br /&gt;
apt -y purge upower power-profiles-daemon&lt;br /&gt;
apt -y autoremove&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
for D-12 32-bit CPUs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt remove &amp;quot;*libavahi*&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= remove snap (U-24) =&lt;br /&gt;
&lt;br /&gt;
Note: snap stores data in $USER/snap/$SNAPNAME, removing a snap on one machine will remove this data from all users even if they want to use snap on some other machine.&lt;br /&gt;
&lt;br /&gt;
Prepare:&lt;br /&gt;
&lt;br /&gt;
NOTE: first remove chromium and firefox, see below.&lt;br /&gt;
&lt;br /&gt;
NOTE: if possible, stop autofs before removing snap - otherwise it will mount all user home directories and complain that it cannot remove some snap data from them&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl stop autofs&lt;br /&gt;
ls -ld /home1/*/snap/* ### remove the per-user snap directories&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove snaps:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
snap list&lt;br /&gt;
echo snap remove --purge chromium ### see below&lt;br /&gt;
echo snap remove --purge firefox ### see below&lt;br /&gt;
snap remove thunderbird&lt;br /&gt;
snap remove cups&lt;br /&gt;
snap remove hello-world&lt;br /&gt;
snap remove firmware-updater&lt;br /&gt;
snap remove gtk-common-themes&lt;br /&gt;
snap remove snapd-desktop-integration&lt;br /&gt;
snap remove snap-store&lt;br /&gt;
snap remove hunspell-dictionaries-1-7-2004&lt;br /&gt;
snap remove gnome-system-monitor&lt;br /&gt;
snap remove gnome-3-26-1604&lt;br /&gt;
snap remove gnome-3-28-1804&lt;br /&gt;
snap remove gnome-3-34-1804&lt;br /&gt;
snap remove gnome-3-38-2004&lt;br /&gt;
snap remove gnome-42-2204&lt;br /&gt;
snap remove gnome-46-2404&lt;br /&gt;
snap remove mesa-2404&lt;br /&gt;
snap remove core&lt;br /&gt;
snap remove core18&lt;br /&gt;
snap remove core20&lt;br /&gt;
snap remove core22&lt;br /&gt;
snap remove core24&lt;br /&gt;
snap remove bare&lt;br /&gt;
snap remove snapd&lt;br /&gt;
snap list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daqubuntu:~# snap list&lt;br /&gt;
No snaps are installed yet. Try &#039;snap install hello-world&#039;.&lt;br /&gt;
root@daqubuntu:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Identify packages that install snaps:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt list | grep snap | grep installed | grep -v -e snappy -e snapshot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Typical output:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
firefox/noble,now 1:1snap1-0ubuntu5 amd64 [installed]&lt;br /&gt;
gir1.2-snapd-2/noble,now 1.64-0ubuntu5 amd64 [installed,automatic]&lt;br /&gt;
libsnapd-glib-2-1/noble,now 1.64-0ubuntu5 amd64 [installed,automatic]&lt;br /&gt;
libsnapd-qt-2-1/noble,now 1.64-0ubuntu5 amd64 [installed,automatic]&lt;br /&gt;
plasma-discover-backend-snap/noble,now 5.27.11-0ubuntu2 amd64 [installed]&lt;br /&gt;
snapd/noble-updates,now 2.66.1+24.04 amd64 [installed]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove packages that install snaps:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt remove chromium-browser&lt;br /&gt;
apt remove chromium-codecs-ffmpeg-extra&lt;br /&gt;
apt remove thunderbird&lt;br /&gt;
apt remove firefox&lt;br /&gt;
apt remove plasma-discover-backend-snap&lt;br /&gt;
apt remove plasma-discover-snap-backend&lt;br /&gt;
apt remove snapd&lt;br /&gt;
apt purge  snapd&lt;br /&gt;
# package gir1.2-snapd-2 is required by ubuntu-mate-desktop &amp;amp; co&lt;br /&gt;
# libsnapd-glib-2-1 is required by gstreamer, gnome-remote-desktop &amp;amp; co&lt;br /&gt;
ls -l /etc/systemd/system/ | grep snap ### remove unwanted stuff&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remove Chromium:&lt;br /&gt;
&lt;br /&gt;
* ls -ld /home/*/snap/chromium/*&lt;br /&gt;
* echo /bin/rm -rf `ls -1d /home/*/snap/chromium/*`&lt;br /&gt;
* snap remove chromium&lt;br /&gt;
&lt;br /&gt;
Remove Firefox:&lt;br /&gt;
&lt;br /&gt;
* ls -ld /home/*/snap/firefox/*&lt;br /&gt;
* echo /bin/rm -rf `ls -1d /home/*/snap/firefox/*` ### this will delete &amp;quot;snap firefox&amp;quot; profiles of all users!!!&lt;br /&gt;
* snap remove firefox ### this will also delete &amp;quot;snap firefox&amp;quot; profiles of all users!!!&lt;br /&gt;
&lt;br /&gt;
Remove gir1.2-snapd-2:&lt;br /&gt;
* echo rm -vf /usr/lib/x86_64-linux-gnu/girepository-1.0/Snapd-2.typelib&lt;br /&gt;
&lt;br /&gt;
If &amp;quot;snap remove&amp;quot; is stuck in &amp;quot;change in progress&amp;quot; (this will remove all snaps and break snapd, which is ok, &lt;br /&gt;
see https://forum.snapcraft.io/t/snap-remove-taking-forever-abort-wasnt-working/48915)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rm /var/lib/snapd/state.json&lt;br /&gt;
systemctl restart snapd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Prevent snap from reinstalling:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/git/scripts/etc&lt;br /&gt;
git pull&lt;br /&gt;
cp etc-apt-preferencesd-disable-snap /etc/apt/preferences.d/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= install non-snap thunderbird =&lt;br /&gt;
&lt;br /&gt;
from: https://ubuntuhandbook.org/index.php/2024/03/install-thunderbird-deb-ubuntu-2404/&lt;br /&gt;
&lt;br /&gt;
* remove snap thunderbird&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
snap remove --purge thunderbird&lt;br /&gt;
apt remove --purge thunderbird&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* add mozilla repository&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
already done after installing firefox-esr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ppa deb and ubuntu snap thunderbird package names are the same, change priority and hide snap package: create /etc/apt/preferences.d/mozillateamppa&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Package: thunderbird*&lt;br /&gt;
Pin: release o=LP-PPA-mozillateam&lt;br /&gt;
Pin-Priority: 1001&lt;br /&gt;
&lt;br /&gt;
Package: thunderbird*&lt;br /&gt;
Pin: release o=Ubuntu&lt;br /&gt;
Pin-Priority: -1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* check that it worked, it should say &amp;quot;build&amp;quot; instead of &amp;quot;snap&amp;quot;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt update&lt;br /&gt;
apt list | grep thunderbird | grep -v locale&lt;br /&gt;
...&lt;br /&gt;
thunderbird/noble 1:128.8.1+build1-0ubuntu0.24.04.1~mt1 amd64&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* install&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install thunderbird&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* run: thunderbird&lt;br /&gt;
&lt;br /&gt;
= EFI boot using syslinux =&lt;br /&gt;
&lt;br /&gt;
* rationale 1: GRUB is the stock boot loader with U-24. It is unnecessarily complicated. EFI BIOS can boot the linux kernel directly, without GRUB, but unfortunately a small shim bootloader is required to specify the initrd file and the root filesystem. the syslinux boot loader can do this in a very simple way.&lt;br /&gt;
* rationale 2: GRUB bootloader configuration is overcomplicated, and when it breaks, it is almost impossible to debug and to recover.&lt;br /&gt;
* rationale 3: GRUB bootloader scripts in U-24 have no support for booting from redundant SSDs.&lt;br /&gt;
* in the case of GRUB bootloader failure, it is simplest to boot the Ubuntu installer in recovery mode and convert the bootloader from GRUB to syslinux. Open firefox on this page and cut-and-paste the steps (only copy of vmlinux and initrd cannot copy-and-paste as of this writing).&lt;br /&gt;
* in the case of servers with redundant SSDs for OS and home directories (ZFS mirror), it is simplest to use the syslinux bootloader to ensure that the machine boots from either SSD (all combinations SSD failures, fail of either EFI partiion, fail of either ZFS mirror partition, machine should boot)&lt;br /&gt;
* check partition tables, SATA SSD&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fdisk -l /dev/sda&lt;br /&gt;
Disk /dev/sda: 232.89 GiB, 250059350016 bytes, 488397168 sectors&lt;br /&gt;
Disk model: WD Blue SA510 2.&lt;br /&gt;
Units: sectors of 1 * 512 = 512 bytes&lt;br /&gt;
Sector size (logical/physical): 512 bytes / 512 bytes&lt;br /&gt;
I/O size (minimum/optimal): 512 bytes / 512 bytes&lt;br /&gt;
Disklabel type: gpt&lt;br /&gt;
Disk identifier: A3F34DAC-DCB4-B74C-B59E-41E754807812&lt;br /&gt;
&lt;br /&gt;
Device       Start       End   Sectors   Size Type&lt;br /&gt;
/dev/sda1     2048   1050623   1048576   512M EFI System&lt;br /&gt;
/dev/sda2  1050624   5244927   4194304     2G Linux swap&lt;br /&gt;
/dev/sda3  5244928   9439231   4194304     2G Solaris boot&lt;br /&gt;
/dev/sda4  9439232 488397134 478957903 228.4G Solaris root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* check partition tables, NVME SSD&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fdisk -l /dev/nvme0n1&lt;br /&gt;
Disk /dev/nvme0n1: 1.75 TiB, 1920383410176 bytes, 3750748848 sectors&lt;br /&gt;
Disk model: SAMSUNG MZ1L21T9HCLS-00A07              &lt;br /&gt;
Units: sectors of 1 * 512 = 512 bytes&lt;br /&gt;
Sector size (logical/physical): 512 bytes / 4096 bytes&lt;br /&gt;
I/O size (minimum/optimal): 131072 bytes / 131072 bytes&lt;br /&gt;
Disklabel type: gpt&lt;br /&gt;
Disk identifier: 04ECCD46-DC2A-454C-B4A8-CCC18AA532F7&lt;br /&gt;
&lt;br /&gt;
Device            Start        End    Sectors  Size Type&lt;br /&gt;
/dev/nvme0n1p1     2048    2203647    2201600    1G EFI System&lt;br /&gt;
/dev/nvme0n1p2  2203648    6397951    4194304    2G Linux filesystem&lt;br /&gt;
/dev/nvme0n1p3  6397952   23175167   16777216    8G Linux swap&lt;br /&gt;
/dev/nvme0n1p4 23175168 3750746111 3727570944  1.7T Linux filesystem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* prepare boot device EFI partition, SATA SSDs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkfs.msdos /dev/sda1&lt;br /&gt;
mkfs.msdos /dev/sdb1&lt;br /&gt;
mkdir /boot/efi-sda&lt;br /&gt;
mkdir /boot/efi-sdb&lt;br /&gt;
mount /dev/sda1 /boot/efi-sda&lt;br /&gt;
mount /dev/sdb1 /boot/efi-sdb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* prepare boot device EFI partition, NVME SSDs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkfs.msdos /dev/nvme0n1p1&lt;br /&gt;
mkfs.msdos /dev/nvme1n1p1&lt;br /&gt;
mkdir /boot/efi-0&lt;br /&gt;
mkdir /boot/efi-1&lt;br /&gt;
mount /dev/nvme0n1p1 /boot/efi-0&lt;br /&gt;
mount /dev/nvme1n1p1 /boot/efi-1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* add them to fstab, note the &amp;quot;nofail&amp;quot; mount option&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
blkid | grep vfat&lt;br /&gt;
/dev/sdb1: UUID=&amp;quot;F30C-13B5&amp;quot; BLOCK_SIZE=&amp;quot;512&amp;quot; TYPE=&amp;quot;vfat&amp;quot; PARTUUID=&amp;quot;20e423b5-ac29-ec42-bab5-f366aefbbd2b&amp;quot;&lt;br /&gt;
/dev/sda1: UUID=&amp;quot;F2DD-7321&amp;quot; BLOCK_SIZE=&amp;quot;512&amp;quot; TYPE=&amp;quot;vfat&amp;quot; PARTUUID=&amp;quot;9427646c-ce5f-fe47-9ed1-4b84cf4c348f&amp;quot;&lt;br /&gt;
grep ^UUID /etc/fstab&lt;br /&gt;
UUID=F2DD-7321  /boot/efi-sda       vfat    umask=0022,fmask=0022,dmask=0022,nofail      0       1&lt;br /&gt;
UUID=F30C-13B5  /boot/efi-sdb       vfat    umask=0022,fmask=0022,dmask=0022.nofail      0       1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* prepare the EFI partitions (remove old previous subdirectories, only empty efi/boot should be there)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot/efi-sda&lt;br /&gt;
mkdir -p efi/boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* get syslinux-6.03&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~&lt;br /&gt;
wget https://daq00.triumf.ca/~olchansk/linux/syslinux-6.03.tar.xz&lt;br /&gt;
xz -d &amp;lt; syslinux-6.03.tar.xz | tar xvf -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* from syslinux-6.03 copy files:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot/efi-sda/efi/boot&lt;br /&gt;
cp ~/syslinux-6.03/efi64/efi/syslinux.efi .&lt;br /&gt;
cp ~/syslinux-6.03/efi64/com32/elflink/ldlinux/ldlinux.e64 .&lt;br /&gt;
cp syslinux.efi bootx64.efi&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* identify the ZFS rpool label&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zfs list | grep ROOT | grep &amp;quot;/$&amp;quot; | cut -f1 -d&amp;quot; &amp;quot;&lt;br /&gt;
rpool/ROOT/ubuntu_9yvb17&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* create syslinux.cfg, change the root=ZFS label to match this computer&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cat &amp;lt;&amp;lt; EOF | sed &amp;quot;s;root=.*$;root=ZFS=`zfs list | grep ROOT | grep &amp;quot;/$&amp;quot; | cut -f1 -d&amp;quot; &amp;quot;`;&amp;quot; &amp;gt; syslinux.cfg&lt;br /&gt;
default linux&lt;br /&gt;
label linux&lt;br /&gt;
kernel vmlinuz&lt;br /&gt;
append ro initrd=initrd.img root=ZFS=rpool/ROOT/ubuntu_02ruwj&lt;br /&gt;
EOF&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* copy linux boot files:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /boot/vmlinuz vmlinuz&lt;br /&gt;
cp /boot/initrd.img initrd.img&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* repeat with /boot/efi-sdb, etc&lt;br /&gt;
* install script to set syslinux to boot the latest kernel&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/git/scripts&lt;br /&gt;
git pull&lt;br /&gt;
ln -s ~/git/scripts/etc/update_efi_syslinux.perl ~&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* update syslinux to boot the latest kernel&lt;br /&gt;
** run &amp;quot;~/update_efi_syslinux.perl&amp;quot; to check that it finds the EFI partitions and finds the correct kernel&lt;br /&gt;
** run &amp;quot;~/update_efi_syslinux.perl -u&amp;quot; to do the actual update&lt;br /&gt;
* or maybe install Ubuntu syslinux 6.04 and use files from there:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install &amp;quot;syslinux*&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= legacy boot using syslinux =&lt;br /&gt;
&lt;br /&gt;
* NOTE: extlinux is not compatible with ext4 &amp;quot;64bit&amp;quot; feature, it should be turned off:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkfs.ext4 -O ^64bit /dev/sdX1&lt;br /&gt;
resize2fs -s /dev/sdX1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* install syslinux and extlinux (THIS DOES NOT WORK!!!)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y install syslinux extlinux&lt;br /&gt;
dd if=/usr/lib/syslinux/mbr/mbr.bin of=/dev/sdX ### NOT /dev/sdX1 NOT !!!&lt;br /&gt;
cd /boot&lt;br /&gt;
cp /usr/lib/syslinux/modules/bios/menu.c32 .&lt;br /&gt;
extlinux -i .&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* install syslinux and extlinux&lt;br /&gt;
&lt;br /&gt;
* copy from old SL6 USB disk (this is extlinux 6.02)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@localhost:/boot# ls -l&lt;br /&gt;
-rwxr-xr-x 1 root root   218952 Jan 28 17:40 extlinux&lt;br /&gt;
-rw-r--r-- 1 root root      402 Jan 29 14:45 extlinux.conf&lt;br /&gt;
-rw-r--r-- 1 root root      496 Jan 29 14:39 extlinux.conf~&lt;br /&gt;
-r--r--r-- 1 root root   122044 Jan 29 14:39 ldlinux.c32&lt;br /&gt;
-r--r--r-- 1 root root    67072 Jan 29 14:39 ldlinux.sys&lt;br /&gt;
-rwxr-xr-x 1 root root    24156 Jan 28 17:40 libutil.c32&lt;br /&gt;
-rw-r--r-- 1 root root      304 Jan 28 17:40 mbr.bin&lt;br /&gt;
-rw-r--r-- 1 root root    26140 Jan 28 17:40 memdisk&lt;br /&gt;
-rw-r--r-- 1 root root    69043 Jan 28 17:40 memtest86+-4.20.iso.zip&lt;br /&gt;
-rw-r--r-- 1 root root   183012 Jan 28 17:40 memtest86+-5.01&lt;br /&gt;
-rw-r--r-- 1 root root    26568 Jan 28 17:40 menu.c32&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* install&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dd if=mbr.bin of=/dev/sdX ### NOT /dev/sdX1 NOT !!!&lt;br /&gt;
extlinux -i .&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* check that partition /dev/sdX1 is marked bootable (fdisk command &amp;quot;a&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
* create /boot/extlinux.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
DEFAULT menu.c32&lt;br /&gt;
PROMPT 0&lt;br /&gt;
TIMEOUT 50&lt;br /&gt;
&lt;br /&gt;
MENU TITLE TRIUMF DAQ USB BOOT32 ver K.O. 2025jan28&lt;br /&gt;
&lt;br /&gt;
LABEL linux&lt;br /&gt;
  MENU DEFAULT&lt;br /&gt;
  kernel /vmlinuz&lt;br /&gt;
  append initrd=/initrd.img panic=60 rootdelay=5 rootwait rw root=/dev/sda1&lt;br /&gt;
&lt;br /&gt;
LABEL linux-6.1.0-28-686&lt;br /&gt;
  kernel vmlinuz-6.1.0-28-686&lt;br /&gt;
  append initrd=initrd.img-6.1.0-28-686 panic=60 rootdelay=5 rootwait rw root=/dev/sda1&lt;br /&gt;
&lt;br /&gt;
LABEL memtest&lt;br /&gt;
  kernel memtest86+-1.65&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Add user to login spash screen =&lt;br /&gt;
&lt;br /&gt;
For user login to local machine, if it doesn&#039;t work by default. User should exist already from NIS service.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo /bin/bash # as root&lt;br /&gt;
cd /var/lib/AccountsService/users&lt;br /&gt;
ls # should at least display the &amp;quot;wheel&amp;quot; user&lt;br /&gt;
cp wheel username # we&#039;re going to copy the user account settings over to our new user&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR:_Software_overview&amp;diff=8769</id>
		<title>BNMR: Software overview</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR:_Software_overview&amp;diff=8769"/>
		<updated>2026-03-09T18:11:50Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Pagelinks}}&lt;br /&gt;
&lt;br /&gt;
== Program list ==&lt;br /&gt;
&lt;br /&gt;
Programs with the _32bit suffix are designed to be run on the VMIC machine; all others are designed to be run on the host PC.&lt;br /&gt;
&lt;br /&gt;
=== Compiled &amp;quot;real&amp;quot; programs ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/febnmr_32bit.exe&amp;lt;/code&amp;gt; ({{bnmr}} only) - see [[BNMR:_frontend|frontend]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/febnqr_32bit.exe&amp;lt;/code&amp;gt; ({{bnqr}} only) - see [[BNMR:_frontend|frontend]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/bnxr_logger.exe&amp;lt;/code&amp;gt; - see [[BNMR: Data Logging|data logging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/logger_cleanup.exe&amp;lt;/code&amp;gt; - see [[BNMR: Data Logging#Cleaning_up_if_end-of-run_fails|data logging]]&lt;br /&gt;
&lt;br /&gt;
=== Python &amp;quot;real&amp;quot; programs ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/beamtime_monitor.py&amp;lt;/code&amp;gt; - see [[BNMR:_Shift_Monitor|shift monitor]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/beamtime_to_excel.py&amp;lt;/code&amp;gt; - see [[BNMR:_Shift_Monitor|shift monitor]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/elog_every_run.py&amp;lt;/code&amp;gt; - see [[BNMR:_Scripts#Run_transition_scripts|run transition scripts]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/mode_changer.py&amp;lt;/code&amp;gt; - see [[BNMR:_Mode_changer|mode changer]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/rf_calculator_fe.py&amp;lt;/code&amp;gt; - see [[BNMR:_RF_calculator|RF calculator]]&lt;br /&gt;
* &amp;lt;code&amp;gt;cycling_framework/ppg/ppg_compiler_fe.py&amp;lt;/code&amp;gt; - see [[BNMR:_PPG_compiler|PPG compiler]]&lt;br /&gt;
* &amp;lt;code&amp;gt;cycling_framework/run_comments/run_comment_editor.py&amp;lt;/code&amp;gt; - see [[BNMR:_Data_Logging#Run_comments|data logging]]&lt;br /&gt;
&lt;br /&gt;
=== Compiled programs for debugging hardware etc ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/bnmrbeamsim_32bit.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/camp_test.exe&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bin/camp_test_32bit.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/epics_test.exe&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bin/epics_test_32bit.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/vppg_interactive_32bit.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/sis3801_interactive_32bit.exe&amp;lt;/code&amp;gt; ({{bnmr}} only) - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/sis3820_interactive_32bit.exe&amp;lt;/code&amp;gt; ({{bnqr}} only) - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/psm_interactive_32bit.exe&amp;lt;/code&amp;gt;  ({{bnqr}} only) - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/psm3_interactive_32bit.exe&amp;lt;/code&amp;gt;  ({{bnmr}} only) - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
&lt;br /&gt;
=== Compiled automated tests ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/unit_tests/*.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Tests#Automated_tests_that_don.27t_use_the_ODB|Automated tests that don&#039;t use the ODB]]&lt;br /&gt;
&lt;br /&gt;
=== Python test programs ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/test_mud_logger.py&amp;lt;/code&amp;gt; - see [[BNMR:_Tests#Automated_tests_that_do_use_the_ODB|automated tests that use the ODB]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/test_ppg_calc.py&amp;lt;/code&amp;gt; - see [[BNMR:_Tests#Automated_tests_that_do_use_the_ODB|automated tests that use the ODB]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/test_psm_calc.py&amp;lt;/code&amp;gt; - see [[BNMR:_Tests#Automated_tests_that_do_use_the_ODB|automated tests that use the ODB]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/diff_mud_file.py&amp;lt;/code&amp;gt; - see [[BNMR:_Data_Logging#MUD_files|data logging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/dump_mud_file.py&amp;lt;/code&amp;gt; - see [[BNMR:_Data_Logging#MUD_files|data logging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;cycling_framework/ppg/tests/test_ppg.py&amp;lt;/code&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
=== Unused compiled programs ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/epics_log.exe&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bin/epics_log_32bit.exe&amp;lt;/code&amp;gt; - EPICS logging is handled by the MUD logger in {{bnmqr|join=/}}&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/tppg_interactive_32bit.exe&amp;lt;/code&amp;gt; - this version is for TRIUMF PPGs; we use PulseBlaster PPGs&lt;br /&gt;
&lt;br /&gt;
== Repository location ==&lt;br /&gt;
&lt;br /&gt;
The main repository is on BitBucket at [https://bitbucket.org/ttriumfdaq/bnmr/ https://bitbucket.org/ttriumfdaq/bnmr/].&lt;br /&gt;
&lt;br /&gt;
== Updating bnmr/bnqr software ==&lt;br /&gt;
&lt;br /&gt;
The main repository uses submodules for some dependencies, so checking out updates requires:&lt;br /&gt;
&lt;br /&gt;
 git pull&lt;br /&gt;
 git submodule update&lt;br /&gt;
&lt;br /&gt;
To compile the real software, we can compile everything from isdaq01 (including the frontend that will eventually run on lxbnmr/lxbnqr). The cross-compilation of the frontend requires some 32-bit libraries that we store in &amp;lt;code&amp;gt;/home/bnmr/packages/libs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 # on isdaq01&lt;br /&gt;
 &lt;br /&gt;
 # For the first install&lt;br /&gt;
 mkdir build&lt;br /&gt;
 cd build&lt;br /&gt;
 cmake .. -DEXP=BNMR&lt;br /&gt;
 # or cmake .. -DEXP=BNQR&lt;br /&gt;
 make install&lt;br /&gt;
 &lt;br /&gt;
 # For updates&lt;br /&gt;
 cd build&lt;br /&gt;
 make install&lt;br /&gt;
&lt;br /&gt;
This will:&lt;br /&gt;
* Cross-compile the frontend to run on the 32-bit VMIC machine (either febnmr or febnqr depending on the &amp;lt;code&amp;gt;-DEXP=...&amp;lt;/code&amp;gt; flag you passed to cmake)&lt;br /&gt;
* Compile the MUD logger&lt;br /&gt;
* Compile various debug executables&lt;br /&gt;
* Compile various automated tests&lt;br /&gt;
&lt;br /&gt;
To compile a dummy version of the software that does not talk to the real hardware or EPICS (and which can be run on a laptop):&lt;br /&gt;
&lt;br /&gt;
 mkdir build&lt;br /&gt;
 cd build&lt;br /&gt;
 cmake .. -DEXP=BNMR -DDUMMY_MODE=1&lt;br /&gt;
 # or cmake .. -DEXP=BNQR -DDUMMY_MODE=1&lt;br /&gt;
 make install&lt;br /&gt;
&lt;br /&gt;
== Updating midas ==&lt;br /&gt;
&lt;br /&gt;
 # Get updates&lt;br /&gt;
 cd $MIDASSYS&lt;br /&gt;
 git pull&lt;br /&gt;
 git submodule update --init --recursive&lt;br /&gt;
 &lt;br /&gt;
 # Compile 64-bit version&lt;br /&gt;
 mkdir -p $MIDASSYS/build&lt;br /&gt;
 cd $MIDASSYS/build&lt;br /&gt;
 make install&lt;br /&gt;
 &lt;br /&gt;
 # Cross-compile 32-bit version&lt;br /&gt;
 cd $MIDASSYS&lt;br /&gt;
 make linux32&lt;br /&gt;
 &lt;br /&gt;
 # Change status page from midas default to a symlink&lt;br /&gt;
 if ! [ -L $MIDASSYS/resources/status.html ]; then&lt;br /&gt;
   mv $MIDASSYS/resources/status.html $MIDASSYS/resources/status.html.orig&lt;br /&gt;
   if [ $USER == &amp;quot;bnmr&amp;quot; ]; then&lt;br /&gt;
     ln -s ~/packages/bnmr/bnxr_common/custom/status.html $MIDASSYS/resources/status.html&lt;br /&gt;
   else&lt;br /&gt;
     ln -s ~/packages/bnqr/bnxr_common/custom/status.html $MIDASSYS/resources/status.html&lt;br /&gt;
   fi&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
Then re-compile the bnmr/bnqr software&lt;br /&gt;
&lt;br /&gt;
== Interactions between programs ==&lt;br /&gt;
&lt;br /&gt;
* RPC between febnmr.exe/febnqr.exe and ppg_compiler_fe.py to generate PPG bytecode at begin-of-run&lt;br /&gt;
* RPC between rf_calculator_fe.py and ppg_compiler_fe.py to generate PPG bytecode when user clicks button on Settings webpage&lt;br /&gt;
* Midas buffers between febnmr.exe/febnqr.exe and bnxr_logger.exe for data&lt;br /&gt;
* Midas buffers between kalliope_fe.exe and bnxr_logger.exe for data&lt;br /&gt;
* RPC between febnmr.exe/febnqr.exe and kalliope_fe.exe to inform it of PPG cycle state&lt;br /&gt;
* run_comment_editor.py writes to a text file in the data directory, which is then read by bnxr_logger.exe when it&#039;s time to write a new MUD file. Text file is deleted at the end of the run.&lt;br /&gt;
&lt;br /&gt;
== Run transitions ==&lt;br /&gt;
&lt;br /&gt;
MIDAS allows clients to register to various transitions (e.g. START,STOP). However, many clients need to perform actions in a certain order. For example, in the {{bnmqr|join=and}} experiments, at begin-of-run, [[BNMR:_RF_calculator|the RF calculator]] is required to check the input parameters and compute various derived values (e.g. the list of I,Q pairs to load on the PSM). This must be completed before the frontend attempts to load these values. &lt;br /&gt;
&lt;br /&gt;
This is accomplished in MIDAS by the use of transition sequence numbers. The RF calculator and the frontend both register to the START transition, but the frontend is registered to only handle the transition after the RF calculator has finished doing the work it need to do.&lt;br /&gt;
&lt;br /&gt;
The full list of transition orderings (higher happens later) is:&lt;br /&gt;
* 1 - mode changer (ensure correct run number)&lt;br /&gt;
* 50 - RF calculator (compute PSM I,Q pairs, create human-readable PPG program to run, setup ODB links for MUD logging etc)&lt;br /&gt;
* 100 - frontend configuration (setup PSM, call PPG compiler to generate bytecode etc)&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:#999999&amp;quot;&amp;gt;100 - run comment editor (no-op)&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:#999999&amp;quot;&amp;gt;500 - PPG compiler (no-op for {{bnmqr|join=/}} as the frontend calls the PPG compiler by JRPC)&amp;lt;/span&amp;gt;&lt;br /&gt;
* 900 - MUD logger (connect to CAMP, open Midas buffers etc)&lt;br /&gt;
* 990 - frontend setup first cycle (configure first scan step and start PPG)&lt;br /&gt;
&lt;br /&gt;
If any of these transitions fail, the latter ones do not happen (and a &amp;quot;STARTABORT&amp;quot; transition signal is sent to all the clients). Having the frontend delay starting the PPG until the end of the sequence ensures that all the clients are ready for when the data starts to flow. Having the frontend configure the hardware early in the sequence prevents the MUD logger from doing unnecessary work if there is a hardware issue.&lt;br /&gt;
&lt;br /&gt;
== Python package list ==&lt;br /&gt;
&lt;br /&gt;
After upgrading python versions, you may need to set up a new python virtual env:&lt;br /&gt;
&lt;br /&gt;
 deactivate&lt;br /&gt;
 python3 -m venv py312venv&lt;br /&gt;
 source ~/py312venv/bin/activate&lt;br /&gt;
 # Edit ~/.bashrc to load new venv&lt;br /&gt;
&lt;br /&gt;
 pip install bdata matplotlib numpy scipy pandas pytz pillow requests jax tomli tqdm tzdata&lt;br /&gt;
 pip install -e $MIDASSYS/python&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
[[Category:BNMR]]&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8601</id>
		<title>TACTIC</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8601"/>
		<updated>2025-09-27T00:25:16Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= TACTIC =&lt;br /&gt;
&lt;br /&gt;
* computer: daq18.triumf.ca&lt;br /&gt;
* midas: https://daq18.triumf.ca&lt;br /&gt;
* elog: https://elog.triumf.ca/Tactic/General/ (has a &amp;quot;tactic&amp;quot; user account)&lt;br /&gt;
&lt;br /&gt;
== Old V1740 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 2x V1740 via CAEN USB interface. 64 channels each - can read out 2 of the 8 TACTIC &amp;quot;sectors&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
These [https://daq18.triumf.ca/?cmd=Programs programs] should be running:&lt;br /&gt;
* mhttpd (web server)&lt;br /&gt;
* Logger (writing data to disk)&lt;br /&gt;
* feMKS (gas mixer)&lt;br /&gt;
* fetactic (data readout from digitizers)&lt;br /&gt;
* ana (online analysis of data)&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:Tactic-v1740-trigger.jpg]]&lt;br /&gt;
&lt;br /&gt;
Trigger and v1740 connections:&lt;br /&gt;
* both v1740 trigger outputs go to logic OR. pulser goes into the same OR&lt;br /&gt;
* from this OR, they fan out to v1740 trigger inputs&lt;br /&gt;
* analog output of first v1740 provides the run gate (via polarity inverting kludge)&lt;br /&gt;
* analog output of second v1740 provides a &amp;quot;buffer-half-full&amp;quot; trigger veto (via polarity inverting kludge)&lt;br /&gt;
&lt;br /&gt;
Trigger notes: (KO 7-oct-2024)&lt;br /&gt;
* trigger signal is not synched with the v1740 clock, actual &amp;quot;adc stop&amp;quot; time will have a jitter between the two v1740 of 1-2 clock periods&lt;br /&gt;
* actual event time jitter between the two v1740 is around 2 clock (from looking at event timestamps).&lt;br /&gt;
* because v1740 busy are not synced (and busy from first v1740 is missing), the second v1740 often has extra events. sometimes the first v1740 has an extra event. fetactic.exe has workaround against this, mostly by dropping mismatched data.&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/manalyzer. &lt;br /&gt;
* Not source-controlled.&lt;br /&gt;
* Contains many hard-coded thresholds/settings/limits. Also includes a hard-coded mapping between digitizer channel number and hardware sector/pad number.&lt;br /&gt;
* Used for both online and offline analysis of data.&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild fetactic.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/v1740mt&lt;br /&gt;
make&lt;br /&gt;
ls -l fetactic.exe&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/manalyzer&lt;br /&gt;
make&lt;br /&gt;
ls -l ./tacticana.exe&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== New V2745 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 6x CAEN V2745 digitizers, with option for reading 8 digitizers if needed. With 8 digitizers can read all 8 sectors from the hardware.&lt;br /&gt;
&lt;br /&gt;
Digitizers are readout over 1G ethernet, and run DPP_ZLE firmware to reduce the data rate significantly. Future versions of TACTIC may run DPP_PHA or custom firmware to further reduce the data rate.&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:TACTIC wiring V2745.png]]&lt;br /&gt;
&lt;br /&gt;
The trigger is a global OR of every channel of every digitizer (though we can suppress certain channels if desired).&lt;br /&gt;
&lt;br /&gt;
Digitizers are set to NIM logic levels, and OR is done using standard NIM fan-in/fan-out modules. Trigger-OR is sent to 9 locations (8 digitizers + 1 visual scaler) so we use a 16x FI/FO. Busy-OR is only sent to 8 locations, so can use an 8x FI/FO.&lt;br /&gt;
&lt;br /&gt;
=== Frontend notes ===&lt;br /&gt;
&lt;br /&gt;
The main frontend code is shared with the Darkside-20k experiment that uses VX2740/VX2745 digitizers running custom firmware. The repository name (dsproto_vx2740) reflects this heritage, but the code now supports more than just Darkside&#039;s usage! The code is located on BitBucket at https://bitbucket.org/ttriumfdaq/dsproto_vx2740/&lt;br /&gt;
&lt;br /&gt;
Digitizer configuration is done via the [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage. The concept is that the &amp;quot;default&amp;quot; value is applied to all digitizers, unless you specifically override the value for a certain digitizer. This means it&#039;s more efficient to change settings, as you only have to change one &amp;quot;default&amp;quot; parameter rather than 8 separate board-specific parameters. Settings that have been overridden for one or more boards appear with a YELLOW background on the webpage.&lt;br /&gt;
&lt;br /&gt;
==== Settings that users may want to configure ====&lt;br /&gt;
* &#039;&#039;&#039;Readout channel mask&#039;&#039;&#039; - which channels get read out when a trigger is accepted&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A en mask&#039;&#039;&#039; - which channels contribute to the self-trigger logic&lt;br /&gt;
* &#039;&#039;&#039;Chan over thresh thresholds&#039;&#039;&#039; - the thresholds in ADC RELATIVE TO THE BASELINE&lt;br /&gt;
* &#039;&#039;&#039;Scope/ZLE waveform length&#039;&#039;&#039; - how long the waveforms should be.&lt;br /&gt;
* &#039;&#039;&#039;Pre-trigger for ZLE mode&#039;&#039;&#039; - where in the waveform the trigger pulse should appear &lt;br /&gt;
* &#039;&#039;&#039;ZLE threshold (ADC)&#039;&#039;&#039; - how many ADC below baseline a signal must be before it gets read out. Note this is different to the trigger threshold! You could trigger readout if the signal goes 50ADC below baseline, but then read out any data that&#039;s 10ADC below baseline.&lt;br /&gt;
* &#039;&#039;&#039;ZLE look back (samples)&#039;&#039;&#039; - how many samples to read out before the signal went below the ZLE threshold&lt;br /&gt;
* &#039;&#039;&#039;ZLE look forward (samples)&#039;&#039;&#039; - how many samples to read out after the signal goes back above the ZLE threshold&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A gate width(ns)&#039;&#039;&#039; - set this to roughly how long you expect a &amp;quot;real&amp;quot; event to last. If you set it too short then the NIM OR module will output triggers multiple times for a single event (e.g. for the first channel to get hit, and then 100ns later for another channel, and then 300ns after that for another channel, ....). The digitizers would still only read out data for the first trigger, but the visual scaler will show a much higher rate, which would be very confusing for debugging.&lt;br /&gt;
* &#039;&#039;&#039;DC offset (pct)&#039;&#039;&#039; - set the baseline between 0ADC and 65535ADC, as a percentage&lt;br /&gt;
* &#039;&#039;&#039;Signal offset (uV)&#039;&#039;&#039; - extra tweak to the input signal - best set using a script&lt;br /&gt;
* &#039;&#039;&#039;VGA gain&#039;&#039;&#039; - 0-40dB in 0.5dB increments&lt;br /&gt;
&lt;br /&gt;
==== Settings that are different for the first digitizer in the chain ====&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Run start source&#039;&#039;&#039;&lt;br /&gt;
** First board: Start acq on midas run start&lt;br /&gt;
** Other boards: Start acq on encoded CLKIN&lt;br /&gt;
* &#039;&#039;&#039;Use external clock&#039;&#039;&#039;&lt;br /&gt;
** First board: True&lt;br /&gt;
** Other boards: False&lt;br /&gt;
&lt;br /&gt;
==== Settings that users shouldn&#039;t touch ====&lt;br /&gt;
* &#039;&#039;&#039;Run start delay (ns)&#039;&#039;&#039; - 0 for the last board, increasing by 48ns for each board in the chain (240, 192, 144, 96, 49, 0).&lt;br /&gt;
* &#039;&#039;&#039;Trigger out mode&#039;&#039;&#039; - ITLA - ensure we output the self-trigger signal&lt;br /&gt;
* &#039;&#039;&#039;Trigger on external signal&#039;&#039;&#039; - True - ensure we only trigger on the global OR that gets fed back in to the board&lt;br /&gt;
* &#039;&#039;&#039;ZLE enable&#039;&#039;&#039; - True for all channels&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A multiplicity&#039;&#039;&#039; - 1 - in principle you could require 2+ hits simultaneously before we trigger (to reduce triggering on noise/bad topology events), but this setting only applies within a single board. So you&#039;ll get weird geometric efficiencies (more likely to trigger on tracks that hit multiple pads in the same sector vs pads in different sectors). If we want to trigger on 2+ hits across multiple boards we can use the DAC or LVDS connectors, and connect them to a board running custom firmware.&lt;br /&gt;
* &#039;&#039;&#039;Chan over thresh rising edge&#039;&#039;&#039; - False - TACTIC uses negative pulses&lt;br /&gt;
* &#039;&#039;&#039;Veto source&#039;&#039;&#039; / &#039;&#039;&#039;Veto when source is high&#039;&#039;&#039; - Disabled / True&lt;br /&gt;
* &#039;&#039;&#039;Use NIM IO&#039;&#039;&#039; - True&lt;br /&gt;
* &#039;&#039;&#039;Enable clock out&#039;&#039;&#039; - True&lt;br /&gt;
* &#039;&#039;&#039;GPIO mode&#039;&#039;&#039; - Busy&lt;br /&gt;
* &#039;&#039;&#039;Busy in source&#039;&#039;&#039; - SIN&lt;br /&gt;
* &#039;&#039;&#039;Sync out mode&#039;&#039;&#039; - Run&lt;br /&gt;
* &#039;&#039;&#039;Enable DC offsets&#039;&#039;&#039; - True&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/tacticana on daq18, and https://bitbucket.org/ttriumfdaq/tacticana/src/master/ on bitbucket.&lt;br /&gt;
* Uses JSON files to define histogram limits, channel mapping etc. See the [https://bitbucket.org/ttriumfdaq/tacticana/src/master/ README.md] file in the repository for details.&lt;br /&gt;
* Specify which config file to use via the --config flag.&lt;br /&gt;
* It replaces &amp;quot;gaps&amp;quot; in the ZLE waveforms with the baseline value (so the rest of the code sees a &amp;quot;normal&amp;quot; waveform with some very flat sections). This was done to minimise the number of changes needed in the rest of the analysis code that was inherited from the V1740-based DAQ.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Run online using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe --midas-progname tacticana -R8081 -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# Run offline using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe /path/to/something.mid -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# NOTE THE --config FLAG MUST COME AFTER A &#039;--&#039;!!!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Custom webpages ===&lt;br /&gt;
&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] page lets you configure all the digitizers. As note above, there is a column for the &amp;quot;default&amp;quot; value for all digitizers, plus optional board-specific &amp;quot;override&amp;quot; values.&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20waveforms VX waveforms] page shows realtime display of waveforms from a handful of channels. It currently only allows you to view 4 channels from a single board. For more advanced options, use the [https://daq18.triumf.ca/proxy/tacticana_new/ tacticana new] webpage.&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20rates VX rates] page shows the readout rate of each board/channel, as well as the overall readout rate over time. The former may be useful for identifying any abnormally &amp;quot;hot&amp;quot;/&amp;quot;cold&amp;quot; channels that have a bad baseline. The latter is useful for tracking stability over time.&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VME%20crate VME crate] page allows you to power-cycle the VME crate remotely. Useful if the digitizers get in a really bad state and can only be fixed by power-cycling (stop the run, stop the VX frontend, power-cycle the crate, start the VX frontend, wait for the status page to show &amp;quot;Initialized&amp;quot;, start the run)&lt;br /&gt;
* The [https://daq18.triumf.ca/proxy/tacticana_new/ tacticana new] page is a ROOT-based display of histograms created by the [[#Analyzer_notes|analyzer]]. You will need to refresh the page when a new run starts.&lt;br /&gt;
&lt;br /&gt;
=== Setting baselines ===&lt;br /&gt;
&lt;br /&gt;
The V2745s have two settings related to the baseline of each channel.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;DC offset&#039;&#039;&#039; sets the target of where the baseline &amp;quot;should&amp;quot; be. It&#039;s specified as a percentage of the full scale 0-65535. For TACTIC with negative pulses, it makes sense to set it to 90% or so (aka 58982 ADC).&lt;br /&gt;
* &#039;&#039;&#039;Signal offset&#039;&#039;&#039; is an extra tweak to each channel (in uV) that can be used to ensure a 0V input actually gets to the expected baseline.&lt;br /&gt;
&lt;br /&gt;
ZLE and trigger thresholds are RELATIVE TO THE EXPECTED BASELINE (i.e. 58982 ADC). The digitizers to not monitor the actual data to decide what the &amp;quot;real baseline&amp;quot; is. It is therefore critical that the signal offset is set so that the real baseline matches the expected baseline. &lt;br /&gt;
&lt;br /&gt;
* If the real baseline is lower than expected, you will trigger more often and your data rate will be higher. &lt;br /&gt;
* If the real baseline is higher than expected, you will miss triggering on small pulses, and may miss some ZLE chunks that would otherwise be readout.&lt;br /&gt;
&lt;br /&gt;
Note that baselines often drift based on the temperature of the board.&lt;br /&gt;
&lt;br /&gt;
There is a script in the dsproto_vx2740 repository that can be used to set the &amp;quot;signal offset&amp;quot; of each channel so that the real baseline matches the expected baseline. This script is very basic at the moment, but could be made smarter (both in terms of the algorithm for finding the optimal offset, and in automating more of the settings that need to be changed).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Stop the run&lt;br /&gt;
# Ensure there aren&#039;t any real signals coming in (i.e. we&#039;re just reading noise)&lt;br /&gt;
# Set the correct trigger by clicking the &amp;quot;For baselines script&amp;quot; button on VX settings webpage&lt;br /&gt;
&lt;br /&gt;
cd ~/newTACTIC/dsproto_vx2740/&lt;br /&gt;
python set_offsets.py &lt;br /&gt;
&lt;br /&gt;
# Reset the trigger by clicking the &amp;quot;Periodic&amp;quot; or &amp;quot;Self-triggers&amp;quot; buttons on VX settings webpage&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding more digitizers to the chain ===&lt;br /&gt;
&lt;br /&gt;
There are currently 6 digitizers in the chain. 2 more will be delivered soon. To fully add a new digitizer to the chain, do the following steps. You should only connect one &amp;quot;new&amp;quot; board to the ethernet network at a time (as otherwise they will fight over who gets to use the hard-coded default IP address).&lt;br /&gt;
&lt;br /&gt;
* Turn off the VME crate&lt;br /&gt;
* Install the new digitizer in the VME crate&lt;br /&gt;
* Connect digitizer via ethernet cable to the switch&lt;br /&gt;
* Connect CLK-IN of this board to the CLK-OUT of previous board in chain&lt;br /&gt;
* Connect LEMO cables to NIM fan-in/fan-out modules (GPIO, S-IN, TRG-IN, TRG-OUT)&lt;br /&gt;
* Turn on the VME crate&lt;br /&gt;
* On daq18 web browser, navigate to http://192.168.0.254 (this is the default IP address that boards use coming from the factory)&lt;br /&gt;
** On the Firmware page, load the DPP-ZLE firmware&lt;br /&gt;
** On the Network page, set the IP address to 192.168.0.xxx, where xxx isn&#039;t already used (e.g. 7 for the 7th board)&lt;br /&gt;
* On daq18, as root, edit /etc/hosts to assign a hostname (e.g. vx07 for 192.168.0.7)&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=Programs Programs] webpage, stop the VX frontend&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage, change the number of boards (first row of first table)&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=Programs Programs] webpage, start the VX frontend. It will abort immediately, but will have created space in the ODB for you to configure the new board&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage, set the hostname of the new board and adjust the run start delay by 48ns for all the earlier boards in the chain&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=Programs Programs] webpage, start the VX frontend. It should start correctly this time&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild vx2740_group_fe.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/dsproto_vx2740/build&lt;br /&gt;
make install -j&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/tacticana&lt;br /&gt;
make -j&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Known issues ===&lt;br /&gt;
&lt;br /&gt;
==== Disabling a digitizer ====&lt;br /&gt;
&lt;br /&gt;
The software currently doesn&#039;t work correctly if a board is completely disabled. Better to disable all channels from the trigger mask, and leave one channel enabled in the readout mask.&lt;br /&gt;
&lt;br /&gt;
==== CAEN software crashes if data rate is too high ====&lt;br /&gt;
&lt;br /&gt;
There is a bug in the CAEN software/firmware that causes the entire frontend to crash on malformed data. This can be quite annoying, and could cause significant downtime if the user doesn&#039;t realise that the program has crashed and/or the run has stopped. &lt;br /&gt;
&lt;br /&gt;
It mostly seems to happen when the data rate is too high, and the CAEN layer says &amp;quot;inconsistent event content&amp;quot;, then crashes. It can mostly be avoided by setting appropriate trigger thresholds so that we don&#039;t trigger on noise.&lt;br /&gt;
&lt;br /&gt;
midas contains a &amp;quot;sequencer&amp;quot; functionality that can be used to mitigate this. Every 10s the sequencer will check to see if the frontend has crashed, and restart it if needed. It will also start a run if the current one has stopped.&lt;br /&gt;
&lt;br /&gt;
To use this sequencer, go to the [https://daq18.triumf.ca/?cmd=Sequencer&amp;amp;SeqODB=/PySequencer PySequencer] page and start the script using the &amp;quot;play&amp;quot; button. You&#039;ll be prompted for how long you want to acquire data for.&lt;br /&gt;
&lt;br /&gt;
Note that if you want to stop data-taking early, you should use the &amp;quot;stop&amp;quot; (square) button on the PySequencer page, not the regular button on the status page for stopping a run (as the sequencer will just detect that the run has stopped and start a new one for you!).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toccolours mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width:800px; overflow:auto;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-weight:bold;line-height:1.6;&amp;quot;&amp;gt;Click &#039;Expand&#039; to view the actual sequencer script I implemented ----&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import datetime&lt;br /&gt;
import midas&lt;br /&gt;
&lt;br /&gt;
def define_params(seq):&lt;br /&gt;
    seq.register_param(&amp;quot;duration_hours&amp;quot;, &amp;quot;Total acquisition time&amp;quot;, 5.0)&lt;br /&gt;
&lt;br /&gt;
def sequence(seq):&lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
    start_time = datetime.datetime.now()&lt;br /&gt;
    elapsed_hours = 0.0&lt;br /&gt;
        &lt;br /&gt;
    while elapsed_hours &amp;lt; seq.get_param(&amp;quot;duration_hours&amp;quot;):&lt;br /&gt;
        validate_prog_running(seq)&lt;br /&gt;
        seq.wait_seconds(10)&lt;br /&gt;
        elapsed_hours = round((datetime.datetime.now() - start_time).total_seconds() / 3600, 2)&lt;br /&gt;
        &lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
        &lt;br /&gt;
def at_exit(seq):&lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
    &lt;br /&gt;
def stop_run_if_needed(seq):&lt;br /&gt;
    if seq.odb_get(&amp;quot;/Runinfo/State&amp;quot;) != midas.STATE_STOPPED:&lt;br /&gt;
        seq.stop_run()&lt;br /&gt;
    &lt;br /&gt;
def validate_prog_running(seq):&lt;br /&gt;
    prog_name = &amp;quot;VX2740_Group_01&amp;quot;&lt;br /&gt;
    if not seq.client_exists(prog_name):&lt;br /&gt;
        stop_run_if_needed(seq)&lt;br /&gt;
        seq.msg(f&amp;quot;Stopped run as {prog_name} was not running! Restarting program.&amp;quot;)&lt;br /&gt;
        seq.wait_seconds(5)&lt;br /&gt;
        seq.start_client(prog_name)&lt;br /&gt;
        seq.wait_clients_running(prog_name)&lt;br /&gt;
        &lt;br /&gt;
        if not seq.client_exists(prog_name):&lt;br /&gt;
            raise RuntimeError(f&amp;quot;Failed to restart {prog_name} - abort sequence!&amp;quot;)&lt;br /&gt;
            &lt;br /&gt;
        seq.wait_odb(&amp;quot;/Equipment/VX2740_Data_Group_001/Common/Status&amp;quot;, &amp;quot;==&amp;quot;, &amp;quot;Initialized&amp;quot;)&lt;br /&gt;
        &lt;br /&gt;
    if seq.odb_get(&amp;quot;/Runinfo/State&amp;quot;) != midas.STATE_RUNNING:&lt;br /&gt;
        seq.start_run()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8599</id>
		<title>TACTIC</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8599"/>
		<updated>2025-09-26T21:39:43Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= TACTIC =&lt;br /&gt;
&lt;br /&gt;
* computer: daq18.triumf.ca&lt;br /&gt;
* midas: https://daq18.triumf.ca&lt;br /&gt;
* elog: https://elog.triumf.ca/Tactic/General/ (has a &amp;quot;tactic&amp;quot; user account)&lt;br /&gt;
&lt;br /&gt;
== Old V1740 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 2x V1740 via CAEN USB interface. 64 channels each - can read out 2 of the 8 TACTIC &amp;quot;sectors&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
These [https://daq18.triumf.ca/?cmd=Programs programs] should be running:&lt;br /&gt;
* mhttpd (web server)&lt;br /&gt;
* Logger (writing data to disk)&lt;br /&gt;
* feMKS (gas mixer)&lt;br /&gt;
* fetactic (data readout from digitizers)&lt;br /&gt;
* ana (online analysis of data)&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:Tactic-v1740-trigger.jpg]]&lt;br /&gt;
&lt;br /&gt;
Trigger and v1740 connections:&lt;br /&gt;
* both v1740 trigger outputs go to logic OR. pulser goes into the same OR&lt;br /&gt;
* from this OR, they fan out to v1740 trigger inputs&lt;br /&gt;
* analog output of first v1740 provides the run gate (via polarity inverting kludge)&lt;br /&gt;
* analog output of second v1740 provides a &amp;quot;buffer-half-full&amp;quot; trigger veto (via polarity inverting kludge)&lt;br /&gt;
&lt;br /&gt;
Trigger notes: (KO 7-oct-2024)&lt;br /&gt;
* trigger signal is not synched with the v1740 clock, actual &amp;quot;adc stop&amp;quot; time will have a jitter between the two v1740 of 1-2 clock periods&lt;br /&gt;
* actual event time jitter between the two v1740 is around 2 clock (from looking at event timestamps).&lt;br /&gt;
* because v1740 busy are not synced (and busy from first v1740 is missing), the second v1740 often has extra events. sometimes the first v1740 has an extra event. fetactic.exe has workaround against this, mostly by dropping mismatched data.&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/manalyzer. &lt;br /&gt;
* Not source-controlled.&lt;br /&gt;
* Contains many hard-coded thresholds/settings/limits. Also includes a hard-coded mapping between digitizer channel number and hardware sector/pad number.&lt;br /&gt;
* Used for both online and offline analysis of data.&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild fetactic.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/v1740mt&lt;br /&gt;
make&lt;br /&gt;
ls -l fetactic.exe&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/manalyzer&lt;br /&gt;
make&lt;br /&gt;
ls -l ./tacticana.exe&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== New V2745 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 6x CAEN V2745 digitizers, with option for reading 8 digitizers if needed. With 8 digitizers can read all 8 sectors from the hardware.&lt;br /&gt;
&lt;br /&gt;
Digitizers are readout over 1G ethernet, and run DPP_ZLE firmware to reduce the data rate significantly. Future versions of TACTIC may run DPP_PHA or custom firmware to further reduce the data rate.&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:TACTIC wiring V2745.png]]&lt;br /&gt;
&lt;br /&gt;
The trigger is a global OR of every channel of every digitizer (though we can suppress certain channels if desired).&lt;br /&gt;
&lt;br /&gt;
Digitizers are set to NIM logic levels, and OR is done using standard NIM fan-in/fan-out modules. Trigger-OR is sent to 9 locations (8 digitizers + 1 visual scaler) so we use a 16x FI/FO. Busy-OR is only sent to 8 locations, so can use an 8x FI/FO.&lt;br /&gt;
&lt;br /&gt;
=== Frontend notes ===&lt;br /&gt;
&lt;br /&gt;
The main frontend code is shared with the Darkside-20k experiment that uses VX2740/VX2745 digitizers running custom firmware. The repository name (dsproto_vx2740) reflects this heritage, but the code now supports more than just Darkside&#039;s usage! The code is located on BitBucket at https://bitbucket.org/ttriumfdaq/dsproto_vx2740/&lt;br /&gt;
&lt;br /&gt;
Digitizer configuration is done via the [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage. The concept is that the &amp;quot;default&amp;quot; value is applied to all digitizers, unless you specifically override the value for a certain digitizer. This means it&#039;s more efficient to change settings, as you only have to change one &amp;quot;default&amp;quot; parameter rather than 8 separate board-specific parameters. Settings that have been overridden for one or more boards appear with a YELLOW background on the webpage.&lt;br /&gt;
&lt;br /&gt;
==== Settings that users may want to configure ====&lt;br /&gt;
* &#039;&#039;&#039;Readout channel mask&#039;&#039;&#039; - which channels get read out when a trigger is accepted&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A en mask&#039;&#039;&#039; - which channels contribute to the self-trigger logic&lt;br /&gt;
* &#039;&#039;&#039;Chan over thresh thresholds&#039;&#039;&#039; - the thresholds in ADC RELATIVE TO THE BASELINE&lt;br /&gt;
* &#039;&#039;&#039;Scope/ZLE waveform length&#039;&#039;&#039; - how long the waveforms should be.&lt;br /&gt;
* &#039;&#039;&#039;Pre-trigger for ZLE mode&#039;&#039;&#039; - where in the waveform the trigger pulse should appear &lt;br /&gt;
* &#039;&#039;&#039;ZLE threshold (ADC)&#039;&#039;&#039; - how many ADC below baseline a signal must be before it gets read out. Note this is different to the trigger threshold! You could trigger readout if the signal goes 50ADC below baseline, but then read out any data that&#039;s 10ADC below baseline.&lt;br /&gt;
* &#039;&#039;&#039;ZLE look back (samples)&#039;&#039;&#039; - how many samples to read out before the signal went below the ZLE threshold&lt;br /&gt;
* &#039;&#039;&#039;ZLE look forward (samples)&#039;&#039;&#039; - how many samples to read out after the signal goes back above the ZLE threshold&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A gate width(ns)&#039;&#039;&#039; - set this to roughly how long you expect a &amp;quot;real&amp;quot; event to last. If you set it too short then the NIM OR module will output triggers multiple times for a single event (e.g. for the first channel to get hit, and then 100ns later for another channel, and then 300ns after that for another channel, ....). The digitizers would still only read out data for the first trigger, but the visual scaler will show a much higher rate, which would be very confusing for debugging.&lt;br /&gt;
* &#039;&#039;&#039;DC offset (pct)&#039;&#039;&#039; - set the baseline between 0ADC and 65535ADC, as a percentage&lt;br /&gt;
* &#039;&#039;&#039;Signal offset (uV)&#039;&#039;&#039; - extra tweak to the input signal - best set using a script&lt;br /&gt;
* &#039;&#039;&#039;VGA gain&#039;&#039;&#039; - 0-40dB in 0.5dB increments&lt;br /&gt;
&lt;br /&gt;
==== Settings that are different for the first digitizer in the chain ====&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Run start source&#039;&#039;&#039;&lt;br /&gt;
** First board: Start acq on midas run start&lt;br /&gt;
** Other boards: Start acq on encoded CLKIN&lt;br /&gt;
* &#039;&#039;&#039;Use external clock&#039;&#039;&#039;&lt;br /&gt;
** First board: True&lt;br /&gt;
** Other boards: False&lt;br /&gt;
&lt;br /&gt;
==== Settings that users shouldn&#039;t touch ====&lt;br /&gt;
* &#039;&#039;&#039;Run start delay (ns)&#039;&#039;&#039; - 0 for the last board, increasing by 48ns for each board in the chain (240, 192, 144, 96, 49, 0).&lt;br /&gt;
* &#039;&#039;&#039;Trigger out mode&#039;&#039;&#039; - ITLA - ensure we output the self-trigger signal&lt;br /&gt;
* &#039;&#039;&#039;Trigger on external signal&#039;&#039;&#039; - True - ensure we only trigger on the global OR that gets fed back in to the board&lt;br /&gt;
* &#039;&#039;&#039;ZLE enable&#039;&#039;&#039; - True for all channels&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A multiplicity&#039;&#039;&#039; - 1 - in principle you could require 2+ hits simultaneously before we trigger (to reduce triggering on noise/bad topology events), but this setting only applies within a single board. So you&#039;ll get weird geometric efficiencies (more likely to trigger on tracks that hit multiple pads in the same sector vs pads in different sectors). If we want to trigger on 2+ hits across multiple boards we can use the DAC or LVDS connectors, and connect them to a board running custom firmware.&lt;br /&gt;
* &#039;&#039;&#039;Chan over thresh rising edge&#039;&#039;&#039; - False - TACTIC uses negative pulses&lt;br /&gt;
* &#039;&#039;&#039;Veto source&#039;&#039;&#039; / &#039;&#039;&#039;Veto when source is high&#039;&#039;&#039; - Disabled / True&lt;br /&gt;
* &#039;&#039;&#039;Use NIM IO&#039;&#039;&#039; - True&lt;br /&gt;
* &#039;&#039;&#039;Enable clock out&#039;&#039;&#039; - True&lt;br /&gt;
* &#039;&#039;&#039;GPIO mode&#039;&#039;&#039; - Busy&lt;br /&gt;
* &#039;&#039;&#039;Busy in source&#039;&#039;&#039; - SIN&lt;br /&gt;
* &#039;&#039;&#039;Sync out mode&#039;&#039;&#039; - Run&lt;br /&gt;
* &#039;&#039;&#039;Enable DC offsets&#039;&#039;&#039; - True&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/tacticana on daq18, and https://bitbucket.org/ttriumfdaq/tacticana/src/master/ on bitbucket.&lt;br /&gt;
* Uses JSON files to define histogram limits, channel mapping etc. See the [https://bitbucket.org/ttriumfdaq/tacticana/src/master/ README.md] file in the repository for details.&lt;br /&gt;
* Specify which config file to use via the --config flag.&lt;br /&gt;
* It replaces &amp;quot;gaps&amp;quot; in the ZLE waveforms with the baseline value (so the rest of the code sees a &amp;quot;normal&amp;quot; waveform with some very flat sections). This was done to minimise the number of changes needed in the rest of the analysis code that was inherited from the V1740-based DAQ.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Run online using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe --midas-progname tacticana -R8081 -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# Run offline using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe /path/to/something.mid -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# NOTE THE --config FLAG MUST COME AFTER A &#039;--&#039;!!!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Custom webpages ===&lt;br /&gt;
&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] page lets you configure all the digitizers. As note above, there is a column for the &amp;quot;default&amp;quot; value for all digitizers, plus optional board-specific &amp;quot;override&amp;quot; values.&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20waveforms VX waveforms] page shows realtime display of waveforms from a handful of channels. It currently only allows you to view 4 channels from a single board. For more advanced options, use the [https://daq18.triumf.ca/proxy/tacticana_new/ tacticana new] webpage.&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20rates VX rates] page shows the readout rate of each board/channel, as well as the overall readout rate over time. The former may be useful for identifying any abnormally &amp;quot;hot&amp;quot;/&amp;quot;cold&amp;quot; channels that have a bad baseline. The latter is useful for tracking stability over time.&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VME%20crate VME crate] page allows you to power-cycle the VME crate remotely. Useful if the digitizers get in a really bad state and can only be fixed by power-cycling (stop the run, stop the VX frontend, power-cycle the crate, start the VX frontend, wait for the status page to show &amp;quot;Initialized&amp;quot;, start the run)&lt;br /&gt;
* The [https://daq18.triumf.ca/proxy/tacticana_new/ tacticana new] page is a ROOT-based display of histograms created by the [[#Analyzer_notes|analyzer]]. You will need to refresh the page when a new run starts.&lt;br /&gt;
&lt;br /&gt;
=== Setting baselines ===&lt;br /&gt;
&lt;br /&gt;
The V2745s have two settings related to the baseline of each channel.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;DC offset&#039;&#039;&#039; sets the target of where the baseline &amp;quot;should&amp;quot; be. It&#039;s specified as a percentage of the full scale 0-65535. For TACTIC with negative pulses, it makes sense to set it to 90% or so (aka 58982 ADC).&lt;br /&gt;
* &#039;&#039;&#039;Signal offset&#039;&#039;&#039; is an extra tweak to each channel (in uV) that can be used to ensure a 0V input actually gets to the expected baseline.&lt;br /&gt;
&lt;br /&gt;
ZLE and trigger thresholds are RELATIVE TO THE EXPECTED BASELINE (i.e. 58982 ADC). The digitizers to not monitor the actual data to decide what the &amp;quot;real baseline&amp;quot; is. It is therefore critical that the signal offset is set so that the real baseline matches the expected baseline. &lt;br /&gt;
&lt;br /&gt;
* If the real baseline is lower than expected, you will trigger more often and your data rate will be higher. &lt;br /&gt;
* If the real baseline is higher than expected, you will miss triggering on small pulses, and may miss some ZLE chunks that would otherwise be readout.&lt;br /&gt;
&lt;br /&gt;
Note that baselines often drift based on the temperature of the board.&lt;br /&gt;
&lt;br /&gt;
There is a script in the dsproto_vx2740 repository that can be used to set the &amp;quot;signal offset&amp;quot; of each channel so that the real baseline matches the expected baseline. This script is very basic at the moment, but could be made smarter (both in terms of the algorithm for finding the optimal offset, and in automating more of the settings that need to be changed).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Stop the run&lt;br /&gt;
# Ensure there aren&#039;t any real signals coming in (i.e. we&#039;re just reading noise)&lt;br /&gt;
# Set the correct trigger by clicking the &amp;quot;For baselines script&amp;quot; button on VX settings webpage&lt;br /&gt;
&lt;br /&gt;
cd ~/newTACTIC/dsproto_vx2740/&lt;br /&gt;
python set_offsets.py &lt;br /&gt;
&lt;br /&gt;
# Reset the trigger by clicking the &amp;quot;Periodic&amp;quot; or &amp;quot;Self-triggers&amp;quot; buttons on VX settings webpage&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding more digitizers to the chain ===&lt;br /&gt;
&lt;br /&gt;
There are currently 6 digitizers in the chain. 2 more will be delivered soon. To fully add a new digitizer to the chain, do the following steps. You should only connect one &amp;quot;new&amp;quot; board to the ethernet network at a time (as otherwise they will fight over who gets to use the hard-coded default IP address).&lt;br /&gt;
&lt;br /&gt;
* Turn off the VME crate&lt;br /&gt;
* Install the new digitizer in the VME crate&lt;br /&gt;
* Connect digitizer via ethernet cable to the switch&lt;br /&gt;
* Connect CLK-IN of this board to the CLK-OUT of previous board in chain&lt;br /&gt;
* Connect LEMO cables to NIM fan-in/fan-out modules (GPIO, S-IN, TRG-IN, TRG-OUT)&lt;br /&gt;
* Turn on the VME crate&lt;br /&gt;
* On daq18 web browser, navigate to http://192.168.0.254 (this is the default IP address that boards use coming from the factory)&lt;br /&gt;
** On the Firmware page, load the DPP-ZLE firmware&lt;br /&gt;
** On the Network page, set the IP address to 192.168.0.xxx, where xxx isn&#039;t already used (e.g. 7 for the 7th board)&lt;br /&gt;
* On daq18, as root, edit /etc/hosts to assign a hostname (e.g. vx07 for 192.168.0.7)&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=Programs Programs] webpage, stop the VX frontend&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage, change the number of boards (first row of first table)&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=Programs Programs] webpage, start the VX frontend. It will abort immediately, but will have created space in the ODB for you to configure the new board&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage, set the hostname of the new board and adjust the run start delay by 48ns for all the earlier boards in the chain&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=Programs Programs] webpage, start the VX frontend. It should start correctly this time&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild vx2740_group_fe.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/dsproto_vx2740/build&lt;br /&gt;
make install -j&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/tacticana&lt;br /&gt;
make -j&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Known issues ===&lt;br /&gt;
&lt;br /&gt;
==== CAEN software crashes if data rate is too high ====&lt;br /&gt;
&lt;br /&gt;
There is a bug in the CAEN software/firmware that causes the entire frontend to crash on malformed data. This can be quite annoying, and could cause significant downtime if the user doesn&#039;t realise that the program has crashed and/or the run has stopped. &lt;br /&gt;
&lt;br /&gt;
It mostly seems to happen when the data rate is too high, and the CAEN layer says &amp;quot;inconsistent event content&amp;quot;, then crashes. It can mostly be avoided by setting appropriate trigger thresholds so that we don&#039;t trigger on noise.&lt;br /&gt;
&lt;br /&gt;
midas contains a &amp;quot;sequencer&amp;quot; functionality that can be used to mitigate this. Every 10s the sequencer will check to see if the frontend has crashed, and restart it if needed. It will also start a run if the current one has stopped.&lt;br /&gt;
&lt;br /&gt;
To use this sequencer, go to the [https://daq18.triumf.ca/?cmd=Sequencer&amp;amp;SeqODB=/PySequencer PySequencer] page and start the script using the &amp;quot;play&amp;quot; button. You&#039;ll be prompted for how long you want to acquire data for.&lt;br /&gt;
&lt;br /&gt;
Note that if you want to stop data-taking early, you should use the &amp;quot;stop&amp;quot; (square) button on the PySequencer page, not the regular button on the status page for stopping a run (as the sequencer will just detect that the run has stopped and start a new one for you!).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toccolours mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width:800px; overflow:auto;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-weight:bold;line-height:1.6;&amp;quot;&amp;gt;Click &#039;Expand&#039; to view the actual sequencer script I implemented ----&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import datetime&lt;br /&gt;
import midas&lt;br /&gt;
&lt;br /&gt;
def define_params(seq):&lt;br /&gt;
    seq.register_param(&amp;quot;duration_hours&amp;quot;, &amp;quot;Total acquisition time&amp;quot;, 5.0)&lt;br /&gt;
&lt;br /&gt;
def sequence(seq):&lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
    start_time = datetime.datetime.now()&lt;br /&gt;
    elapsed_hours = 0.0&lt;br /&gt;
        &lt;br /&gt;
    while elapsed_hours &amp;lt; seq.get_param(&amp;quot;duration_hours&amp;quot;):&lt;br /&gt;
        validate_prog_running(seq)&lt;br /&gt;
        seq.wait_seconds(10)&lt;br /&gt;
        elapsed_hours = round((datetime.datetime.now() - start_time).total_seconds() / 3600, 2)&lt;br /&gt;
        &lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
        &lt;br /&gt;
def at_exit(seq):&lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
    &lt;br /&gt;
def stop_run_if_needed(seq):&lt;br /&gt;
    if seq.odb_get(&amp;quot;/Runinfo/State&amp;quot;) != midas.STATE_STOPPED:&lt;br /&gt;
        seq.stop_run()&lt;br /&gt;
    &lt;br /&gt;
def validate_prog_running(seq):&lt;br /&gt;
    prog_name = &amp;quot;VX2740_Group_01&amp;quot;&lt;br /&gt;
    if not seq.client_exists(prog_name):&lt;br /&gt;
        stop_run_if_needed(seq)&lt;br /&gt;
        seq.msg(f&amp;quot;Stopped run as {prog_name} was not running! Restarting program.&amp;quot;)&lt;br /&gt;
        seq.wait_seconds(5)&lt;br /&gt;
        seq.start_client(prog_name)&lt;br /&gt;
        seq.wait_clients_running(prog_name)&lt;br /&gt;
        &lt;br /&gt;
        if not seq.client_exists(prog_name):&lt;br /&gt;
            raise RuntimeError(f&amp;quot;Failed to restart {prog_name} - abort sequence!&amp;quot;)&lt;br /&gt;
            &lt;br /&gt;
        seq.wait_odb(&amp;quot;/Equipment/VX2740_Data_Group_001/Common/Status&amp;quot;, &amp;quot;==&amp;quot;, &amp;quot;Initialized&amp;quot;)&lt;br /&gt;
        &lt;br /&gt;
    if seq.odb_get(&amp;quot;/Runinfo/State&amp;quot;) != midas.STATE_RUNNING:&lt;br /&gt;
        seq.start_run()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8598</id>
		<title>TACTIC</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8598"/>
		<updated>2025-09-26T19:41:09Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: /* Rare bug in CAEN software */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= TACTIC =&lt;br /&gt;
&lt;br /&gt;
* computer: daq18.triumf.ca&lt;br /&gt;
* midas: https://daq18.triumf.ca&lt;br /&gt;
* elog: https://elog.triumf.ca/Tactic/General/ (has a &amp;quot;tactic&amp;quot; user account)&lt;br /&gt;
&lt;br /&gt;
== Old V1740 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 2x V1740 via CAEN USB interface. 64 channels each - can read out 2 of the 8 TACTIC &amp;quot;sectors&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
These [https://daq18.triumf.ca/?cmd=Programs programs] should be running:&lt;br /&gt;
* mhttpd (web server)&lt;br /&gt;
* Logger (writing data to disk)&lt;br /&gt;
* feMKS (gas mixer)&lt;br /&gt;
* fetactic (data readout from digitizers)&lt;br /&gt;
* ana (online analysis of data)&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:Tactic-v1740-trigger.jpg]]&lt;br /&gt;
&lt;br /&gt;
Trigger and v1740 connections:&lt;br /&gt;
* both v1740 trigger outputs go to logic OR. pulser goes into the same OR&lt;br /&gt;
* from this OR, they fan out to v1740 trigger inputs&lt;br /&gt;
* analog output of first v1740 provides the run gate (via polarity inverting kludge)&lt;br /&gt;
* analog output of second v1740 provides a &amp;quot;buffer-half-full&amp;quot; trigger veto (via polarity inverting kludge)&lt;br /&gt;
&lt;br /&gt;
Trigger notes: (KO 7-oct-2024)&lt;br /&gt;
* trigger signal is not synched with the v1740 clock, actual &amp;quot;adc stop&amp;quot; time will have a jitter between the two v1740 of 1-2 clock periods&lt;br /&gt;
* actual event time jitter between the two v1740 is around 2 clock (from looking at event timestamps).&lt;br /&gt;
* because v1740 busy are not synced (and busy from first v1740 is missing), the second v1740 often has extra events. sometimes the first v1740 has an extra event. fetactic.exe has workaround against this, mostly by dropping mismatched data.&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/manalyzer. &lt;br /&gt;
* Not source-controlled.&lt;br /&gt;
* Contains many hard-coded thresholds/settings/limits. Also includes a hard-coded mapping between digitizer channel number and hardware sector/pad number.&lt;br /&gt;
* Used for both online and offline analysis of data.&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild fetactic.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/v1740mt&lt;br /&gt;
make&lt;br /&gt;
ls -l fetactic.exe&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/manalyzer&lt;br /&gt;
make&lt;br /&gt;
ls -l ./tacticana.exe&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== New V2745 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 6x CAEN V2745 digitizers, with option for reading 8 digitizers if needed. With 8 digitizers can read all 8 sectors from the hardware.&lt;br /&gt;
&lt;br /&gt;
Digitizers are readout over 1G ethernet, and run DPP_ZLE firmware to reduce the data rate significantly. Future versions of TACTIC may run DPP_PHA or custom firmware to further reduce the data rate.&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:TACTIC wiring V2745.png]]&lt;br /&gt;
&lt;br /&gt;
The trigger is a global OR of every channel of every digitizer (though we can suppress certain channels if desired).&lt;br /&gt;
&lt;br /&gt;
Digitizers are set to NIM logic levels, and OR is done using standard NIM fan-in/fan-out modules. Trigger-OR is sent to 9 locations (8 digitizers + 1 visual scaler) so we use a 16x FI/FO. Busy-OR is only sent to 8 locations, so can use an 8x FI/FO.&lt;br /&gt;
&lt;br /&gt;
=== Frontend notes ===&lt;br /&gt;
&lt;br /&gt;
The main frontend code is shared with the Darkside-20k experiment that uses VX2740/VX2745 digitizers running custom firmware. The repository name (dsproto_vx2740) reflects this heritage, but the code now supports more than just Darkside&#039;s usage! The code is located on BitBucket at https://bitbucket.org/ttriumfdaq/dsproto_vx2740/&lt;br /&gt;
&lt;br /&gt;
Digitizer configuration is done via the [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage. The concept is that the &amp;quot;default&amp;quot; value is applied to all digitizers, unless you specifically override the value for a certain digitizer. This means it&#039;s more efficient to change settings, as you only have to change one &amp;quot;default&amp;quot; parameter rather than 8 separate board-specific parameters. Settings that have been overridden for one or more boards appear with a YELLOW background on the webpage.&lt;br /&gt;
&lt;br /&gt;
==== Settings that users may want to configure ====&lt;br /&gt;
* &#039;&#039;&#039;Readout channel mask&#039;&#039;&#039; - which channels get read out when a trigger is accepted&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A en mask&#039;&#039;&#039; - which channels contribute to the self-trigger logic&lt;br /&gt;
* &#039;&#039;&#039;Chan over thresh thresholds&#039;&#039;&#039; - the thresholds in ADC RELATIVE TO THE BASELINE&lt;br /&gt;
* &#039;&#039;&#039;Scope/ZLE waveform length&#039;&#039;&#039; - how long the waveforms should be.&lt;br /&gt;
* &#039;&#039;&#039;Pre-trigger for ZLE mode&#039;&#039;&#039; - where in the waveform the trigger pulse should appear &lt;br /&gt;
* &#039;&#039;&#039;ZLE threshold (ADC)&#039;&#039;&#039; - how many ADC below baseline a signal must be before it gets read out. Note this is different to the trigger threshold! You could trigger readout if the signal goes 50ADC below baseline, but then read out any data that&#039;s 10ADC below baseline.&lt;br /&gt;
* &#039;&#039;&#039;ZLE look back (samples)&#039;&#039;&#039; - how many samples to read out before the signal went below the ZLE threshold&lt;br /&gt;
* &#039;&#039;&#039;ZLE look forward (samples)&#039;&#039;&#039; - how many samples to read out after the signal goes back above the ZLE threshold&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A gate width(ns)&#039;&#039;&#039; - set this to roughly how long you expect a &amp;quot;real&amp;quot; event to last. If you set it too short then the NIM OR module will output triggers multiple times for a single event (e.g. for the first channel to get hit, and then 100ns later for another channel, and then 300ns after that for another channel, ....). The digitizers would still only read out data for the first trigger, but the visual scaler will show a much higher rate, which would be very confusing for debugging.&lt;br /&gt;
* &#039;&#039;&#039;DC offset (pct)&#039;&#039;&#039; - set the baseline between 0ADC and 65535ADC, as a percentage&lt;br /&gt;
* &#039;&#039;&#039;Signal offset (uV)&#039;&#039;&#039; - extra tweak to the input signal - best set using a script&lt;br /&gt;
* &#039;&#039;&#039;VGA gain&#039;&#039;&#039; - 0-40dB in 0.5dB increments&lt;br /&gt;
&lt;br /&gt;
==== Settings that are different for the first digitizer in the chain ====&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Run start source&#039;&#039;&#039;&lt;br /&gt;
** First board: Start acq on midas run start&lt;br /&gt;
** Other boards: Start acq on encoded CLKIN&lt;br /&gt;
* &#039;&#039;&#039;Use external clock&#039;&#039;&#039;&lt;br /&gt;
** First board: True&lt;br /&gt;
** Other boards: False&lt;br /&gt;
&lt;br /&gt;
==== Settings that users shouldn&#039;t touch ====&lt;br /&gt;
* &#039;&#039;&#039;Run start delay (ns)&#039;&#039;&#039; - 0 for the last board, increasing by 48ns for each board in the chain (240, 192, 144, 96, 49, 0).&lt;br /&gt;
* &#039;&#039;&#039;Trigger out mode&#039;&#039;&#039; - ITLA - ensure we output the self-trigger signal&lt;br /&gt;
* &#039;&#039;&#039;Trigger on external signal&#039;&#039;&#039; - True - ensure we only trigger on the global OR that gets fed back in to the board&lt;br /&gt;
* &#039;&#039;&#039;ZLE enable&#039;&#039;&#039; - True for all channels&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A multiplicity&#039;&#039;&#039; - 1 - in principle you could require 2+ hits simultaneously before we trigger (to reduce triggering on noise/bad topology events), but this setting only applies within a single board. So you&#039;ll get weird geometric efficiencies (more likely to trigger on tracks that hit multiple pads in the same sector vs pads in different sectors). If we want to trigger on 2+ hits across multiple boards we can use the DAC or LVDS connectors, and connect them to a board running custom firmware.&lt;br /&gt;
* &#039;&#039;&#039;Chan over thresh rising edge&#039;&#039;&#039; - False - TACTIC uses negative pulses&lt;br /&gt;
* &#039;&#039;&#039;Veto source&#039;&#039;&#039; / &#039;&#039;&#039;Veto when source is high&#039;&#039;&#039; - Disabled / True&lt;br /&gt;
* &#039;&#039;&#039;Use NIM IO&#039;&#039;&#039; - True&lt;br /&gt;
* &#039;&#039;&#039;Enable clock out&#039;&#039;&#039; - True&lt;br /&gt;
* &#039;&#039;&#039;GPIO mode&#039;&#039;&#039; - Busy&lt;br /&gt;
* &#039;&#039;&#039;Busy in source&#039;&#039;&#039; - SIN&lt;br /&gt;
* &#039;&#039;&#039;Sync out mode&#039;&#039;&#039; - Run&lt;br /&gt;
* &#039;&#039;&#039;Enable DC offsets&#039;&#039;&#039; - True&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/tacticana on daq18, and https://bitbucket.org/ttriumfdaq/tacticana/src/master/ on bitbucket.&lt;br /&gt;
* Uses JSON files to define histogram limits, channel mapping etc. See the [https://bitbucket.org/ttriumfdaq/tacticana/src/master/ README.md] file in the repository for details.&lt;br /&gt;
* Specify which config file to use via the --config flag.&lt;br /&gt;
* It replaces &amp;quot;gaps&amp;quot; in the ZLE waveforms with the baseline value (so the rest of the code sees a &amp;quot;normal&amp;quot; waveform with some very flat sections). This was done to minimise the number of changes needed in the rest of the analysis code that was inherited from the V1740-based DAQ.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Run online using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe --midas-progname tacticana -R8081 -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# Run offline using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe /path/to/something.mid -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# NOTE THE --config FLAG MUST COME AFTER A &#039;--&#039;!!!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Custom webpages ===&lt;br /&gt;
&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] page lets you configure all the digitizers. As note above, there is a column for the &amp;quot;default&amp;quot; value for all digitizers, plus optional board-specific &amp;quot;override&amp;quot; values.&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20waveforms VX waveforms] page shows realtime display of waveforms from a handful of channels. It currently only allows you to view 4 channels from a single board. For more advanced options, use the [https://daq18.triumf.ca/proxy/tacticana_new/ tacticana new] webpage.&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20rates VX rates] page shows the readout rate of each board/channel, as well as the overall readout rate over time. The former may be useful for identifying any abnormally &amp;quot;hot&amp;quot;/&amp;quot;cold&amp;quot; channels that have a bad baseline. The latter is useful for tracking stability over time.&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VME%20crate VME crate] page allows you to power-cycle the VME crate remotely. Useful if the digitizers get in a really bad state and can only be fixed by power-cycling (stop the run, stop the VX frontend, power-cycle the crate, start the VX frontend, wait for the status page to show &amp;quot;Initialized&amp;quot;, start the run)&lt;br /&gt;
* The [https://daq18.triumf.ca/proxy/tacticana_new/ tacticana new] page is a ROOT-based display of histograms created by the [[#Analyzer_notes|analyzer]]. You will need to refresh the page when a new run starts.&lt;br /&gt;
&lt;br /&gt;
=== Setting baselines ===&lt;br /&gt;
&lt;br /&gt;
The V2745s have two settings related to the baseline of each channel.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;DC offset&#039;&#039;&#039; sets the target of where the baseline &amp;quot;should&amp;quot; be. It&#039;s specified as a percentage of the full scale 0-65535. For TACTIC with negative pulses, it makes sense to set it to 90% or so (aka 58982 ADC).&lt;br /&gt;
* &#039;&#039;&#039;Signal offset&#039;&#039;&#039; is an extra tweak to each channel (in uV) that can be used to ensure a 0V input actually gets to the expected baseline.&lt;br /&gt;
&lt;br /&gt;
ZLE and trigger thresholds are RELATIVE TO THE EXPECTED BASELINE (i.e. 58982 ADC). The digitizers to not monitor the actual data to decide what the &amp;quot;real baseline&amp;quot; is. It is therefore critical that the signal offset is set so that the real baseline matches the expected baseline. &lt;br /&gt;
&lt;br /&gt;
* If the real baseline is lower than expected, you will trigger more often and your data rate will be higher. &lt;br /&gt;
* If the real baseline is higher than expected, you will miss triggering on small pulses, and may miss some ZLE chunks that would otherwise be readout.&lt;br /&gt;
&lt;br /&gt;
Note that baselines often drift based on the temperature of the board.&lt;br /&gt;
&lt;br /&gt;
There is a script in the dsproto_vx2740 repository that can be used to set the &amp;quot;signal offset&amp;quot; of each channel so that the real baseline matches the expected baseline. This script is very basic at the moment, but could be made smarter (both in terms of the algorithm for finding the optimal offset, and in automating more of the settings that need to be changed).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Stop the run&lt;br /&gt;
# Ensure there aren&#039;t any real signals coming in (i.e. we&#039;re just reading noise)&lt;br /&gt;
# Set &#039;ZLE enable&#039; to False for all channels&lt;br /&gt;
# Set &#039;Trigger out mode&#039; to &#039;TestPulse&#039; for the first board, and &#039;Disabled&#039; for all other boards&lt;br /&gt;
# Set &#039;Chan over thresh rising edge&#039; to True for all channels (to work around a bug in CAEN software)&lt;br /&gt;
&lt;br /&gt;
cd ~/newTACTIC/dsproto_vx2740/&lt;br /&gt;
python set_offsets.py &lt;br /&gt;
&lt;br /&gt;
# Set &#039;ZLE enable&#039; to True for all channels&lt;br /&gt;
# Set &#039;Trigger out mode&#039; to &#039;ITLA&#039; for all boards&lt;br /&gt;
# Set &#039;Chan over thresh rising edge&#039; to False for all channels&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding more digitizers to the chain ===&lt;br /&gt;
&lt;br /&gt;
There are currently 6 digitizers in the chain. 2 more will be delivered soon. To fully add a new digitizer to the chain, do the following steps. You should only connect one &amp;quot;new&amp;quot; board to the ethernet network at a time (as otherwise they will fight over who gets to use the hard-coded default IP address).&lt;br /&gt;
&lt;br /&gt;
* Turn off the VME crate&lt;br /&gt;
* Install the new digitizer in the VME crate&lt;br /&gt;
* Connect digitizer via ethernet cable to the switch&lt;br /&gt;
* Connect CLK-IN of this board to the CLK-OUT of previous board in chain&lt;br /&gt;
* Connect LEMO cables to NIM fan-in/fan-out modules (GPIO, S-IN, TRG-IN, TRG-OUT)&lt;br /&gt;
* Turn on the VME crate&lt;br /&gt;
* On daq18 web browser, navigate to http://192.168.0.254 (this is the default IP address that boards use coming from the factory)&lt;br /&gt;
** On the Firmware page, load the DPP-ZLE firmware&lt;br /&gt;
** On the Network page, set the IP address to 192.168.0.xxx, where xxx isn&#039;t already used (e.g. 7 for the 7th board)&lt;br /&gt;
* On daq18, as root, edit /etc/hosts to assign a hostname (e.g. vx07 for 192.168.0.7)&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=Programs Programs] webpage, stop the VX frontend&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage, change the number of boards (first row of first table)&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=Programs Programs] webpage, start the VX frontend. It will abort immediately, but will have created space in the ODB for you to configure the new board&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage, set the hostname of the new board and adjust the run start delay by 48ns for all the earlier boards in the chain&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=Programs Programs] webpage, start the VX frontend. It should start correctly this time&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild vx2740_group_fe.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/dsproto_vx2740/build&lt;br /&gt;
make install -j&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/tacticana&lt;br /&gt;
make -j&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Known issues ===&lt;br /&gt;
&lt;br /&gt;
==== CAEN software crashes if data rate is too high ====&lt;br /&gt;
&lt;br /&gt;
There is a bug in the CAEN software/firmware that causes the entire frontend to crash on malformed data. This can be quite annoying, and could cause significant downtime if the user doesn&#039;t realise that the program has crashed and/or the run has stopped. &lt;br /&gt;
&lt;br /&gt;
It mostly seems to happen when the data rate is too high, and the CAEN layer says &amp;quot;inconsistent event content&amp;quot;, then crashes. It can mostly be avoided by setting appropriate trigger thresholds so that we don&#039;t trigger on noise.&lt;br /&gt;
&lt;br /&gt;
midas contains a &amp;quot;sequencer&amp;quot; functionality that can be used to mitigate this. Every 10s the sequencer will check to see if the frontend has crashed, and restart it if needed. It will also start a run if the current one has stopped.&lt;br /&gt;
&lt;br /&gt;
To use this sequencer, go to the [https://daq18.triumf.ca/?cmd=Sequencer&amp;amp;SeqODB=/PySequencer PySequencer] page and start the script using the &amp;quot;play&amp;quot; button. You&#039;ll be prompted for how long you want to acquire data for.&lt;br /&gt;
&lt;br /&gt;
Note that if you want to stop data-taking early, you should use the &amp;quot;stop&amp;quot; (square) button on the PySequencer page, not the regular button on the status page for stopping a run (as the sequencer will just detect that the run has stopped and start a new one for you!).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toccolours mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width:800px; overflow:auto;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-weight:bold;line-height:1.6;&amp;quot;&amp;gt;Click &#039;Expand&#039; to view the actual sequencer script I implemented ----&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import datetime&lt;br /&gt;
import midas&lt;br /&gt;
&lt;br /&gt;
def define_params(seq):&lt;br /&gt;
    seq.register_param(&amp;quot;duration_hours&amp;quot;, &amp;quot;Total acquisition time&amp;quot;, 5.0)&lt;br /&gt;
&lt;br /&gt;
def sequence(seq):&lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
    start_time = datetime.datetime.now()&lt;br /&gt;
    elapsed_hours = 0.0&lt;br /&gt;
        &lt;br /&gt;
    while elapsed_hours &amp;lt; seq.get_param(&amp;quot;duration_hours&amp;quot;):&lt;br /&gt;
        validate_prog_running(seq)&lt;br /&gt;
        seq.wait_seconds(10)&lt;br /&gt;
        elapsed_hours = round((datetime.datetime.now() - start_time).total_seconds() / 3600, 2)&lt;br /&gt;
        &lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
        &lt;br /&gt;
def at_exit(seq):&lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
    &lt;br /&gt;
def stop_run_if_needed(seq):&lt;br /&gt;
    if seq.odb_get(&amp;quot;/Runinfo/State&amp;quot;) != midas.STATE_STOPPED:&lt;br /&gt;
        seq.stop_run()&lt;br /&gt;
    &lt;br /&gt;
def validate_prog_running(seq):&lt;br /&gt;
    prog_name = &amp;quot;VX2740_Group_01&amp;quot;&lt;br /&gt;
    if not seq.client_exists(prog_name):&lt;br /&gt;
        stop_run_if_needed(seq)&lt;br /&gt;
        seq.msg(f&amp;quot;Stopped run as {prog_name} was not running! Restarting program.&amp;quot;)&lt;br /&gt;
        seq.wait_seconds(5)&lt;br /&gt;
        seq.start_client(prog_name)&lt;br /&gt;
        seq.wait_clients_running(prog_name)&lt;br /&gt;
        &lt;br /&gt;
        if not seq.client_exists(prog_name):&lt;br /&gt;
            raise RuntimeError(f&amp;quot;Failed to restart {prog_name} - abort sequence!&amp;quot;)&lt;br /&gt;
            &lt;br /&gt;
        seq.wait_odb(&amp;quot;/Equipment/VX2740_Data_Group_001/Common/Status&amp;quot;, &amp;quot;==&amp;quot;, &amp;quot;Initialized&amp;quot;)&lt;br /&gt;
        &lt;br /&gt;
    if seq.odb_get(&amp;quot;/Runinfo/State&amp;quot;) != midas.STATE_RUNNING:&lt;br /&gt;
        seq.start_run()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8597</id>
		<title>TACTIC</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8597"/>
		<updated>2025-09-26T19:26:30Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: /* Setting baselines */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= TACTIC =&lt;br /&gt;
&lt;br /&gt;
* computer: daq18.triumf.ca&lt;br /&gt;
* midas: https://daq18.triumf.ca&lt;br /&gt;
* elog: https://elog.triumf.ca/Tactic/General/ (has a &amp;quot;tactic&amp;quot; user account)&lt;br /&gt;
&lt;br /&gt;
== Old V1740 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 2x V1740 via CAEN USB interface. 64 channels each - can read out 2 of the 8 TACTIC &amp;quot;sectors&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
These [https://daq18.triumf.ca/?cmd=Programs programs] should be running:&lt;br /&gt;
* mhttpd (web server)&lt;br /&gt;
* Logger (writing data to disk)&lt;br /&gt;
* feMKS (gas mixer)&lt;br /&gt;
* fetactic (data readout from digitizers)&lt;br /&gt;
* ana (online analysis of data)&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:Tactic-v1740-trigger.jpg]]&lt;br /&gt;
&lt;br /&gt;
Trigger and v1740 connections:&lt;br /&gt;
* both v1740 trigger outputs go to logic OR. pulser goes into the same OR&lt;br /&gt;
* from this OR, they fan out to v1740 trigger inputs&lt;br /&gt;
* analog output of first v1740 provides the run gate (via polarity inverting kludge)&lt;br /&gt;
* analog output of second v1740 provides a &amp;quot;buffer-half-full&amp;quot; trigger veto (via polarity inverting kludge)&lt;br /&gt;
&lt;br /&gt;
Trigger notes: (KO 7-oct-2024)&lt;br /&gt;
* trigger signal is not synched with the v1740 clock, actual &amp;quot;adc stop&amp;quot; time will have a jitter between the two v1740 of 1-2 clock periods&lt;br /&gt;
* actual event time jitter between the two v1740 is around 2 clock (from looking at event timestamps).&lt;br /&gt;
* because v1740 busy are not synced (and busy from first v1740 is missing), the second v1740 often has extra events. sometimes the first v1740 has an extra event. fetactic.exe has workaround against this, mostly by dropping mismatched data.&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/manalyzer. &lt;br /&gt;
* Not source-controlled.&lt;br /&gt;
* Contains many hard-coded thresholds/settings/limits. Also includes a hard-coded mapping between digitizer channel number and hardware sector/pad number.&lt;br /&gt;
* Used for both online and offline analysis of data.&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild fetactic.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/v1740mt&lt;br /&gt;
make&lt;br /&gt;
ls -l fetactic.exe&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/manalyzer&lt;br /&gt;
make&lt;br /&gt;
ls -l ./tacticana.exe&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== New V2745 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 6x CAEN V2745 digitizers, with option for reading 8 digitizers if needed. With 8 digitizers can read all 8 sectors from the hardware.&lt;br /&gt;
&lt;br /&gt;
Digitizers are readout over 1G ethernet, and run DPP_ZLE firmware to reduce the data rate significantly. Future versions of TACTIC may run DPP_PHA or custom firmware to further reduce the data rate.&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:TACTIC wiring V2745.png]]&lt;br /&gt;
&lt;br /&gt;
The trigger is a global OR of every channel of every digitizer (though we can suppress certain channels if desired).&lt;br /&gt;
&lt;br /&gt;
Digitizers are set to NIM logic levels, and OR is done using standard NIM fan-in/fan-out modules. Trigger-OR is sent to 9 locations (8 digitizers + 1 visual scaler) so we use a 16x FI/FO. Busy-OR is only sent to 8 locations, so can use an 8x FI/FO.&lt;br /&gt;
&lt;br /&gt;
=== Frontend notes ===&lt;br /&gt;
&lt;br /&gt;
The main frontend code is shared with the Darkside-20k experiment that uses VX2740/VX2745 digitizers running custom firmware. The repository name (dsproto_vx2740) reflects this heritage, but the code now supports more than just Darkside&#039;s usage! The code is located on BitBucket at https://bitbucket.org/ttriumfdaq/dsproto_vx2740/&lt;br /&gt;
&lt;br /&gt;
Digitizer configuration is done via the [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage. The concept is that the &amp;quot;default&amp;quot; value is applied to all digitizers, unless you specifically override the value for a certain digitizer. This means it&#039;s more efficient to change settings, as you only have to change one &amp;quot;default&amp;quot; parameter rather than 8 separate board-specific parameters. Settings that have been overridden for one or more boards appear with a YELLOW background on the webpage.&lt;br /&gt;
&lt;br /&gt;
==== Settings that users may want to configure ====&lt;br /&gt;
* &#039;&#039;&#039;Readout channel mask&#039;&#039;&#039; - which channels get read out when a trigger is accepted&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A en mask&#039;&#039;&#039; - which channels contribute to the self-trigger logic&lt;br /&gt;
* &#039;&#039;&#039;Chan over thresh thresholds&#039;&#039;&#039; - the thresholds in ADC RELATIVE TO THE BASELINE&lt;br /&gt;
* &#039;&#039;&#039;Scope/ZLE waveform length&#039;&#039;&#039; - how long the waveforms should be.&lt;br /&gt;
* &#039;&#039;&#039;Pre-trigger for ZLE mode&#039;&#039;&#039; - where in the waveform the trigger pulse should appear &lt;br /&gt;
* &#039;&#039;&#039;ZLE threshold (ADC)&#039;&#039;&#039; - how many ADC below baseline a signal must be before it gets read out. Note this is different to the trigger threshold! You could trigger readout if the signal goes 50ADC below baseline, but then read out any data that&#039;s 10ADC below baseline.&lt;br /&gt;
* &#039;&#039;&#039;ZLE look back (samples)&#039;&#039;&#039; - how many samples to read out before the signal went below the ZLE threshold&lt;br /&gt;
* &#039;&#039;&#039;ZLE look forward (samples)&#039;&#039;&#039; - how many samples to read out after the signal goes back above the ZLE threshold&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A gate width(ns)&#039;&#039;&#039; - set this to roughly how long you expect a &amp;quot;real&amp;quot; event to last. If you set it too short then the NIM OR module will output triggers multiple times for a single event (e.g. for the first channel to get hit, and then 100ns later for another channel, and then 300ns after that for another channel, ....). The digitizers would still only read out data for the first trigger, but the visual scaler will show a much higher rate, which would be very confusing for debugging.&lt;br /&gt;
* &#039;&#039;&#039;DC offset (pct)&#039;&#039;&#039; - set the baseline between 0ADC and 65535ADC, as a percentage&lt;br /&gt;
* &#039;&#039;&#039;Signal offset (uV)&#039;&#039;&#039; - extra tweak to the input signal - best set using a script&lt;br /&gt;
* &#039;&#039;&#039;VGA gain&#039;&#039;&#039; - 0-40dB in 0.5dB increments&lt;br /&gt;
&lt;br /&gt;
==== Settings that are different for the first digitizer in the chain ====&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Run start source&#039;&#039;&#039;&lt;br /&gt;
** First board: Start acq on midas run start&lt;br /&gt;
** Other boards: Start acq on encoded CLKIN&lt;br /&gt;
* &#039;&#039;&#039;Use external clock&#039;&#039;&#039;&lt;br /&gt;
** First board: True&lt;br /&gt;
** Other boards: False&lt;br /&gt;
&lt;br /&gt;
==== Settings that users shouldn&#039;t touch ====&lt;br /&gt;
* &#039;&#039;&#039;Run start delay (ns)&#039;&#039;&#039; - 0 for the last board, increasing by 48ns for each board in the chain (240, 192, 144, 96, 49, 0).&lt;br /&gt;
* &#039;&#039;&#039;Trigger out mode&#039;&#039;&#039; - ITLA - ensure we output the self-trigger signal&lt;br /&gt;
* &#039;&#039;&#039;Trigger on external signal&#039;&#039;&#039; - True - ensure we only trigger on the global OR that gets fed back in to the board&lt;br /&gt;
* &#039;&#039;&#039;ZLE enable&#039;&#039;&#039; - True for all channels&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A multiplicity&#039;&#039;&#039; - 1 - in principle you could require 2+ hits simultaneously before we trigger (to reduce triggering on noise/bad topology events), but this setting only applies within a single board. So you&#039;ll get weird geometric efficiencies (more likely to trigger on tracks that hit multiple pads in the same sector vs pads in different sectors). If we want to trigger on 2+ hits across multiple boards we can use the DAC or LVDS connectors, and connect them to a board running custom firmware.&lt;br /&gt;
* &#039;&#039;&#039;Chan over thresh rising edge&#039;&#039;&#039; - False - TACTIC uses negative pulses&lt;br /&gt;
* &#039;&#039;&#039;Veto source&#039;&#039;&#039; / &#039;&#039;&#039;Veto when source is high&#039;&#039;&#039; - Disabled / True&lt;br /&gt;
* &#039;&#039;&#039;Use NIM IO&#039;&#039;&#039; - True&lt;br /&gt;
* &#039;&#039;&#039;Enable clock out&#039;&#039;&#039; - True&lt;br /&gt;
* &#039;&#039;&#039;GPIO mode&#039;&#039;&#039; - Busy&lt;br /&gt;
* &#039;&#039;&#039;Busy in source&#039;&#039;&#039; - SIN&lt;br /&gt;
* &#039;&#039;&#039;Sync out mode&#039;&#039;&#039; - Run&lt;br /&gt;
* &#039;&#039;&#039;Enable DC offsets&#039;&#039;&#039; - True&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/tacticana on daq18, and https://bitbucket.org/ttriumfdaq/tacticana/src/master/ on bitbucket.&lt;br /&gt;
* Uses JSON files to define histogram limits, channel mapping etc. See the [https://bitbucket.org/ttriumfdaq/tacticana/src/master/ README.md] file in the repository for details.&lt;br /&gt;
* Specify which config file to use via the --config flag.&lt;br /&gt;
* It replaces &amp;quot;gaps&amp;quot; in the ZLE waveforms with the baseline value (so the rest of the code sees a &amp;quot;normal&amp;quot; waveform with some very flat sections). This was done to minimise the number of changes needed in the rest of the analysis code that was inherited from the V1740-based DAQ.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Run online using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe --midas-progname tacticana -R8081 -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# Run offline using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe /path/to/something.mid -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# NOTE THE --config FLAG MUST COME AFTER A &#039;--&#039;!!!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Custom webpages ===&lt;br /&gt;
&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] page lets you configure all the digitizers. As note above, there is a column for the &amp;quot;default&amp;quot; value for all digitizers, plus optional board-specific &amp;quot;override&amp;quot; values.&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20waveforms VX waveforms] page shows realtime display of waveforms from a handful of channels. It currently only allows you to view 4 channels from a single board. For more advanced options, use the [https://daq18.triumf.ca/proxy/tacticana_new/ tacticana new] webpage.&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20rates VX rates] page shows the readout rate of each board/channel, as well as the overall readout rate over time. The former may be useful for identifying any abnormally &amp;quot;hot&amp;quot;/&amp;quot;cold&amp;quot; channels that have a bad baseline. The latter is useful for tracking stability over time.&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VME%20crate VME crate] page allows you to power-cycle the VME crate remotely. Useful if the digitizers get in a really bad state and can only be fixed by power-cycling (stop the run, stop the VX frontend, power-cycle the crate, start the VX frontend, wait for the status page to show &amp;quot;Initialized&amp;quot;, start the run)&lt;br /&gt;
* The [https://daq18.triumf.ca/proxy/tacticana_new/ tacticana new] page is a ROOT-based display of histograms created by the [[#Analyzer_notes|analyzer]]. You will need to refresh the page when a new run starts.&lt;br /&gt;
&lt;br /&gt;
=== Setting baselines ===&lt;br /&gt;
&lt;br /&gt;
The V2745s have two settings related to the baseline of each channel.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;DC offset&#039;&#039;&#039; sets the target of where the baseline &amp;quot;should&amp;quot; be. It&#039;s specified as a percentage of the full scale 0-65535. For TACTIC with negative pulses, it makes sense to set it to 90% or so (aka 58982 ADC).&lt;br /&gt;
* &#039;&#039;&#039;Signal offset&#039;&#039;&#039; is an extra tweak to each channel (in uV) that can be used to ensure a 0V input actually gets to the expected baseline.&lt;br /&gt;
&lt;br /&gt;
ZLE and trigger thresholds are RELATIVE TO THE EXPECTED BASELINE (i.e. 58982 ADC). The digitizers to not monitor the actual data to decide what the &amp;quot;real baseline&amp;quot; is. It is therefore critical that the signal offset is set so that the real baseline matches the expected baseline. &lt;br /&gt;
&lt;br /&gt;
* If the real baseline is lower than expected, you will trigger more often and your data rate will be higher. &lt;br /&gt;
* If the real baseline is higher than expected, you will miss triggering on small pulses, and may miss some ZLE chunks that would otherwise be readout.&lt;br /&gt;
&lt;br /&gt;
Note that baselines often drift based on the temperature of the board.&lt;br /&gt;
&lt;br /&gt;
There is a script in the dsproto_vx2740 repository that can be used to set the &amp;quot;signal offset&amp;quot; of each channel so that the real baseline matches the expected baseline. This script is very basic at the moment, but could be made smarter (both in terms of the algorithm for finding the optimal offset, and in automating more of the settings that need to be changed).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Stop the run&lt;br /&gt;
# Ensure there aren&#039;t any real signals coming in (i.e. we&#039;re just reading noise)&lt;br /&gt;
# Set &#039;ZLE enable&#039; to False for all channels&lt;br /&gt;
# Set &#039;Trigger out mode&#039; to &#039;TestPulse&#039; for the first board, and &#039;Disabled&#039; for all other boards&lt;br /&gt;
# Set &#039;Chan over thresh rising edge&#039; to True for all channels (to work around a bug in CAEN software)&lt;br /&gt;
&lt;br /&gt;
cd ~/newTACTIC/dsproto_vx2740/&lt;br /&gt;
python set_offsets.py &lt;br /&gt;
&lt;br /&gt;
# Set &#039;ZLE enable&#039; to True for all channels&lt;br /&gt;
# Set &#039;Trigger out mode&#039; to &#039;ITLA&#039; for all boards&lt;br /&gt;
# Set &#039;Chan over thresh rising edge&#039; to False for all channels&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding more digitizers to the chain ===&lt;br /&gt;
&lt;br /&gt;
There are currently 6 digitizers in the chain. 2 more will be delivered soon. To fully add a new digitizer to the chain, do the following steps. You should only connect one &amp;quot;new&amp;quot; board to the ethernet network at a time (as otherwise they will fight over who gets to use the hard-coded default IP address).&lt;br /&gt;
&lt;br /&gt;
* Turn off the VME crate&lt;br /&gt;
* Install the new digitizer in the VME crate&lt;br /&gt;
* Connect digitizer via ethernet cable to the switch&lt;br /&gt;
* Connect CLK-IN of this board to the CLK-OUT of previous board in chain&lt;br /&gt;
* Connect LEMO cables to NIM fan-in/fan-out modules (GPIO, S-IN, TRG-IN, TRG-OUT)&lt;br /&gt;
* Turn on the VME crate&lt;br /&gt;
* On daq18 web browser, navigate to http://192.168.0.254 (this is the default IP address that boards use coming from the factory)&lt;br /&gt;
** On the Firmware page, load the DPP-ZLE firmware&lt;br /&gt;
** On the Network page, set the IP address to 192.168.0.xxx, where xxx isn&#039;t already used (e.g. 7 for the 7th board)&lt;br /&gt;
* On daq18, as root, edit /etc/hosts to assign a hostname (e.g. vx07 for 192.168.0.7)&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=Programs Programs] webpage, stop the VX frontend&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage, change the number of boards (first row of first table)&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=Programs Programs] webpage, start the VX frontend. It will abort immediately, but will have created space in the ODB for you to configure the new board&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage, set the hostname of the new board and adjust the run start delay by 48ns for all the earlier boards in the chain&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=Programs Programs] webpage, start the VX frontend. It should start correctly this time&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild vx2740_group_fe.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/dsproto_vx2740/build&lt;br /&gt;
make install -j&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/tacticana&lt;br /&gt;
make -j&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Known issues ===&lt;br /&gt;
&lt;br /&gt;
==== Rare bug in CAEN software ====&lt;br /&gt;
&lt;br /&gt;
There is a rare bug in the CAEN software/firmware that causes the entire frontend to crash on malformed data. This can be quite annoying, and could cause significant downtime if the user doesn&#039;t realise that the program has crashed and/or the run has stopped.&lt;br /&gt;
&lt;br /&gt;
midas contains a &amp;quot;sequencer&amp;quot; functionality that can be used to mitigate this. Every 10s the sequencer will check to see if the frontend has crashed, and restart it if needed. It will also start a run if the current one has stopped.&lt;br /&gt;
&lt;br /&gt;
To use this sequencer, go to the [https://daq18.triumf.ca/?cmd=Sequencer&amp;amp;SeqODB=/PySequencer PySequencer] page and start the script using the &amp;quot;play&amp;quot; button. You&#039;ll be prompted for how long you want to acquire data for.&lt;br /&gt;
&lt;br /&gt;
Note that if you want to stop data-taking early, you should use the &amp;quot;stop&amp;quot; (square) button on the PySequencer page, not the regular button on the status page for stopping a run (as the sequencer will just detect that the run has stopped and start a new one for you!).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toccolours mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width:800px; overflow:auto;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-weight:bold;line-height:1.6;&amp;quot;&amp;gt;Click &#039;Expand&#039; to view the actual sequencer script I implemented ----&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import datetime&lt;br /&gt;
import midas&lt;br /&gt;
&lt;br /&gt;
def define_params(seq):&lt;br /&gt;
    seq.register_param(&amp;quot;duration_hours&amp;quot;, &amp;quot;Total acquisition time&amp;quot;, 5.0)&lt;br /&gt;
&lt;br /&gt;
def sequence(seq):&lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
    start_time = datetime.datetime.now()&lt;br /&gt;
    elapsed_hours = 0.0&lt;br /&gt;
        &lt;br /&gt;
    while elapsed_hours &amp;lt; seq.get_param(&amp;quot;duration_hours&amp;quot;):&lt;br /&gt;
        validate_prog_running(seq)&lt;br /&gt;
        seq.wait_seconds(10)&lt;br /&gt;
        elapsed_hours = round((datetime.datetime.now() - start_time).total_seconds() / 3600, 2)&lt;br /&gt;
        &lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
        &lt;br /&gt;
def at_exit(seq):&lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
    &lt;br /&gt;
def stop_run_if_needed(seq):&lt;br /&gt;
    if seq.odb_get(&amp;quot;/Runinfo/State&amp;quot;) != midas.STATE_STOPPED:&lt;br /&gt;
        seq.stop_run()&lt;br /&gt;
    &lt;br /&gt;
def validate_prog_running(seq):&lt;br /&gt;
    prog_name = &amp;quot;VX2740_Group_01&amp;quot;&lt;br /&gt;
    if not seq.client_exists(prog_name):&lt;br /&gt;
        stop_run_if_needed(seq)&lt;br /&gt;
        seq.msg(f&amp;quot;Stopped run as {prog_name} was not running! Restarting program.&amp;quot;)&lt;br /&gt;
        seq.wait_seconds(5)&lt;br /&gt;
        seq.start_client(prog_name)&lt;br /&gt;
        seq.wait_clients_running(prog_name)&lt;br /&gt;
        &lt;br /&gt;
        if not seq.client_exists(prog_name):&lt;br /&gt;
            raise RuntimeError(f&amp;quot;Failed to restart {prog_name} - abort sequence!&amp;quot;)&lt;br /&gt;
            &lt;br /&gt;
        seq.wait_odb(&amp;quot;/Equipment/VX2740_Data_Group_001/Common/Status&amp;quot;, &amp;quot;==&amp;quot;, &amp;quot;Initialized&amp;quot;)&lt;br /&gt;
        &lt;br /&gt;
    if seq.odb_get(&amp;quot;/Runinfo/State&amp;quot;) != midas.STATE_RUNNING:&lt;br /&gt;
        seq.start_run()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8593</id>
		<title>TACTIC</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8593"/>
		<updated>2025-09-17T22:20:34Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= TACTIC =&lt;br /&gt;
&lt;br /&gt;
* computer: daq18.triumf.ca&lt;br /&gt;
* midas: https://daq18.triumf.ca&lt;br /&gt;
* elog: https://elog.triumf.ca/Tactic/General/ (has a &amp;quot;tactic&amp;quot; user account)&lt;br /&gt;
&lt;br /&gt;
== Old V1740 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 2x V1740 via CAEN USB interface. 64 channels each - can read out 2 of the 8 TACTIC &amp;quot;sectors&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
These [https://daq18.triumf.ca/?cmd=Programs programs] should be running:&lt;br /&gt;
* mhttpd (web server)&lt;br /&gt;
* Logger (writing data to disk)&lt;br /&gt;
* feMKS (gas mixer)&lt;br /&gt;
* fetactic (data readout from digitizers)&lt;br /&gt;
* ana (online analysis of data)&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:Tactic-v1740-trigger.jpg]]&lt;br /&gt;
&lt;br /&gt;
Trigger and v1740 connections:&lt;br /&gt;
* both v1740 trigger outputs go to logic OR. pulser goes into the same OR&lt;br /&gt;
* from this OR, they fan out to v1740 trigger inputs&lt;br /&gt;
* analog output of first v1740 provides the run gate (via polarity inverting kludge)&lt;br /&gt;
* analog output of second v1740 provides a &amp;quot;buffer-half-full&amp;quot; trigger veto (via polarity inverting kludge)&lt;br /&gt;
&lt;br /&gt;
Trigger notes: (KO 7-oct-2024)&lt;br /&gt;
* trigger signal is not synched with the v1740 clock, actual &amp;quot;adc stop&amp;quot; time will have a jitter between the two v1740 of 1-2 clock periods&lt;br /&gt;
* actual event time jitter between the two v1740 is around 2 clock (from looking at event timestamps).&lt;br /&gt;
* because v1740 busy are not synced (and busy from first v1740 is missing), the second v1740 often has extra events. sometimes the first v1740 has an extra event. fetactic.exe has workaround against this, mostly by dropping mismatched data.&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/manalyzer. &lt;br /&gt;
* Not source-controlled.&lt;br /&gt;
* Contains many hard-coded thresholds/settings/limits. Also includes a hard-coded mapping between digitizer channel number and hardware sector/pad number.&lt;br /&gt;
* Used for both online and offline analysis of data.&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild fetactic.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/v1740mt&lt;br /&gt;
make&lt;br /&gt;
ls -l fetactic.exe&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/manalyzer&lt;br /&gt;
make&lt;br /&gt;
ls -l ./tacticana.exe&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== New V2745 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 6x CAEN V2745 digitizers, with option for reading 8 digitizers if needed. With 8 digitizers can read all 8 sectors from the hardware.&lt;br /&gt;
&lt;br /&gt;
Digitizers are readout over 1G ethernet, and run DPP_ZLE firmware to reduce the data rate significantly. Future versions of TACTIC may run DPP_PHA or custom firmware to further reduce the data rate.&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:TACTIC wiring V2745.png]]&lt;br /&gt;
&lt;br /&gt;
The trigger is a global OR of every channel of every digitizer (though we can suppress certain channels if desired).&lt;br /&gt;
&lt;br /&gt;
Digitizers are set to NIM logic levels, and OR is done using standard NIM fan-in/fan-out modules. Trigger-OR is sent to 9 locations (8 digitizers + 1 visual scaler) so we use a 16x FI/FO. Busy-OR is only sent to 8 locations, so can use an 8x FI/FO.&lt;br /&gt;
&lt;br /&gt;
=== Frontend notes ===&lt;br /&gt;
&lt;br /&gt;
The main frontend code is shared with the Darkside-20k experiment that uses VX2740/VX2745 digitizers running custom firmware. The repository name (dsproto_vx2740) reflects this heritage, but the code now supports more than just Darkside&#039;s usage! The code is located on BitBucket at https://bitbucket.org/ttriumfdaq/dsproto_vx2740/&lt;br /&gt;
&lt;br /&gt;
Digitizer configuration is done via the [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage. The concept is that the &amp;quot;default&amp;quot; value is applied to all digitizers, unless you specifically override the value for a certain digitizer. This means it&#039;s more efficient to change settings, as you only have to change one &amp;quot;default&amp;quot; parameter rather than 8 separate board-specific parameters. Settings that have been overridden for one or more boards appear with a YELLOW background on the webpage.&lt;br /&gt;
&lt;br /&gt;
==== Settings that users may want to configure ====&lt;br /&gt;
* &#039;&#039;&#039;Readout channel mask&#039;&#039;&#039; - which channels get read out when a trigger is accepted&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A en mask&#039;&#039;&#039; - which channels contribute to the self-trigger logic&lt;br /&gt;
* &#039;&#039;&#039;Chan over thresh thresholds&#039;&#039;&#039; - the thresholds in ADC RELATIVE TO THE BASELINE&lt;br /&gt;
* &#039;&#039;&#039;Scope/ZLE waveform length&#039;&#039;&#039; - how long the waveforms should be.&lt;br /&gt;
* &#039;&#039;&#039;Pre-trigger for ZLE mode&#039;&#039;&#039; - where in the waveform the trigger pulse should appear &lt;br /&gt;
* &#039;&#039;&#039;ZLE threshold (ADC)&#039;&#039;&#039; - how many ADC below baseline a signal must be before it gets read out. Note this is different to the trigger threshold! You could trigger readout if the signal goes 50ADC below baseline, but then read out any data that&#039;s 10ADC below baseline.&lt;br /&gt;
* &#039;&#039;&#039;ZLE look back (samples)&#039;&#039;&#039; - how many samples to read out before the signal went below the ZLE threshold&lt;br /&gt;
* &#039;&#039;&#039;ZLE look forward (samples)&#039;&#039;&#039; - how many samples to read out after the signal goes back above the ZLE threshold&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A gate width(ns)&#039;&#039;&#039; - set this to roughly how long you expect a &amp;quot;real&amp;quot; event to last. If you set it too short then the NIM OR module will output triggers multiple times for a single event (e.g. for the first channel to get hit, and then 100ns later for another channel, and then 300ns after that for another channel, ....). The digitizers would still only read out data for the first trigger, but the visual scaler will show a much higher rate, which would be very confusing for debugging.&lt;br /&gt;
* &#039;&#039;&#039;DC offset (pct)&#039;&#039;&#039; - set the baseline between 0ADC and 65535ADC, as a percentage&lt;br /&gt;
* &#039;&#039;&#039;Signal offset (uV)&#039;&#039;&#039; - extra tweak to the input signal - best set using a script&lt;br /&gt;
* &#039;&#039;&#039;VGA gain&#039;&#039;&#039; - 0-40dB in 0.5dB increments&lt;br /&gt;
&lt;br /&gt;
==== Settings that are different for the first digitizer in the chain ====&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Run start source&#039;&#039;&#039;&lt;br /&gt;
** First board: Start acq on midas run start&lt;br /&gt;
** Other boards: Start acq on encoded CLKIN&lt;br /&gt;
* &#039;&#039;&#039;Use external clock&#039;&#039;&#039;&lt;br /&gt;
** First board: True&lt;br /&gt;
** Other boards: False&lt;br /&gt;
&lt;br /&gt;
==== Settings that users shouldn&#039;t touch ====&lt;br /&gt;
* &#039;&#039;&#039;Run start delay (ns)&#039;&#039;&#039; - 0 for the last board, increasing by 48ns for each board in the chain (240, 192, 144, 96, 49, 0).&lt;br /&gt;
* &#039;&#039;&#039;Trigger out mode&#039;&#039;&#039; - ITLA - ensure we output the self-trigger signal&lt;br /&gt;
* &#039;&#039;&#039;Trigger on external signal&#039;&#039;&#039; - True - ensure we only trigger on the global OR that gets fed back in to the board&lt;br /&gt;
* &#039;&#039;&#039;ZLE enable&#039;&#039;&#039; - True for all channels&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A multiplicity&#039;&#039;&#039; - 1 - in principle you could require 2+ hits simultaneously before we trigger (to reduce triggering on noise/bad topology events), but this setting only applies within a single board. So you&#039;ll get weird geometric efficiencies (more likely to trigger on tracks that hit multiple pads in the same sector vs pads in different sectors). If we want to trigger on 2+ hits across multiple boards we can use the DAC or LVDS connectors, and connect them to a board running custom firmware.&lt;br /&gt;
* &#039;&#039;&#039;Chan over thresh rising edge&#039;&#039;&#039; - False - TACTIC uses negative pulses&lt;br /&gt;
* &#039;&#039;&#039;Veto source&#039;&#039;&#039; / &#039;&#039;&#039;Veto when source is high&#039;&#039;&#039; - Disabled / True&lt;br /&gt;
* &#039;&#039;&#039;Use NIM IO&#039;&#039;&#039; - True&lt;br /&gt;
* &#039;&#039;&#039;Enable clock out&#039;&#039;&#039; - True&lt;br /&gt;
* &#039;&#039;&#039;GPIO mode&#039;&#039;&#039; - Busy&lt;br /&gt;
* &#039;&#039;&#039;Busy in source&#039;&#039;&#039; - SIN&lt;br /&gt;
* &#039;&#039;&#039;Sync out mode&#039;&#039;&#039; - Run&lt;br /&gt;
* &#039;&#039;&#039;Enable DC offsets&#039;&#039;&#039; - True&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/tacticana on daq18, and https://bitbucket.org/ttriumfdaq/tacticana/src/master/ on bitbucket.&lt;br /&gt;
* Uses JSON files to define histogram limits, channel mapping etc. See the [https://bitbucket.org/ttriumfdaq/tacticana/src/master/ README.md] file in the repository for details.&lt;br /&gt;
* Specify which config file to use via the --config flag.&lt;br /&gt;
* It replaces &amp;quot;gaps&amp;quot; in the ZLE waveforms with the baseline value (so the rest of the code sees a &amp;quot;normal&amp;quot; waveform with some very flat sections). This was done to minimise the number of changes needed in the rest of the analysis code that was inherited from the V1740-based DAQ.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Run online using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe --midas-progname tacticana -R8081 -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# Run offline using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe /path/to/something.mid -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# NOTE THE --config FLAG MUST COME AFTER A &#039;--&#039;!!!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Custom webpages ===&lt;br /&gt;
&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] page lets you configure all the digitizers. As note above, there is a column for the &amp;quot;default&amp;quot; value for all digitizers, plus optional board-specific &amp;quot;override&amp;quot; values.&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20waveforms VX waveforms] page shows realtime display of waveforms from a handful of channels. It currently only allows you to view 4 channels from a single board. For more advanced options, use the [https://daq18.triumf.ca/proxy/tacticana_new/ tacticana new] webpage.&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20rates VX rates] page shows the readout rate of each board/channel, as well as the overall readout rate over time. The former may be useful for identifying any abnormally &amp;quot;hot&amp;quot;/&amp;quot;cold&amp;quot; channels that have a bad baseline. The latter is useful for tracking stability over time.&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VME%20crate VME crate] page allows you to power-cycle the VME crate remotely. Useful if the digitizers get in a really bad state and can only be fixed by power-cycling (stop the run, stop the VX frontend, power-cycle the crate, start the VX frontend, wait for the status page to show &amp;quot;Initialized&amp;quot;, start the run)&lt;br /&gt;
* The [https://daq18.triumf.ca/proxy/tacticana_new/ tacticana new] page is a ROOT-based display of histograms created by the [[#Analyzer_notes|analyzer]]. You will need to refresh the page when a new run starts.&lt;br /&gt;
&lt;br /&gt;
=== Setting baselines ===&lt;br /&gt;
&lt;br /&gt;
The V2745s have two settings related to the baseline of each channel.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;DC offset&#039;&#039;&#039; sets the target of where the baseline &amp;quot;should&amp;quot; be. It&#039;s specified as a percentage of the full scale 0-65535. For TACTIC with negative pulses, it makes sense to set it to 90% or so (aka 58982 ADC).&lt;br /&gt;
* &#039;&#039;&#039;Signal offset&#039;&#039;&#039; is an extra tweak to each channel (in uV) that can be used to ensure a 0V input actually gets to the expected baseline.&lt;br /&gt;
&lt;br /&gt;
ZLE and trigger thresholds are RELATIVE TO THE EXPECTED BASELINE (i.e. 58982 ADC). The digitizers to not monitor the actual data to decide what the &amp;quot;real baseline&amp;quot; is. It is therefore critical that the signal offset is set so that the real baseline matches the expected baseline. &lt;br /&gt;
&lt;br /&gt;
* If the real baseline is lower than expected, you will trigger more often and your data rate will be higher. &lt;br /&gt;
* If the real baseline is higher than expected, you will miss triggering on small pulses, and may miss some ZLE chunks that would otherwise be readout.&lt;br /&gt;
&lt;br /&gt;
Note that baselines often drift based on the temperature of the board.&lt;br /&gt;
&lt;br /&gt;
There is a script in the dsproto_vx2740 repository that can be used to set the &amp;quot;signal offset&amp;quot; of each channel so that the real baseline matches the expected baseline. This script is very basic at the moment, but could be made smarter (both in terms of the algorithm for finding the optimal offset, and in automating more of the settings that need to be changed).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Stop the run&lt;br /&gt;
# Ensure there aren&#039;t any real signals coming in (i.e. we&#039;re just reading noise)&lt;br /&gt;
# Set &#039;ZLE enable&#039; to False for all channels&lt;br /&gt;
# Set &#039;Trigger out mode&#039; to &#039;TestPulse&#039; for the first board, and &#039;Disabled&#039; for all other boards&lt;br /&gt;
&lt;br /&gt;
cd ~/newTACTIC/dsproto_vx2740/&lt;br /&gt;
python set_offsets.py &lt;br /&gt;
&lt;br /&gt;
# Set &#039;ZLE enable&#039; to True for all channels&lt;br /&gt;
# Set &#039;Trigger out mode&#039; to &#039;ITLA&#039; for all boards&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== Adding more digitizers to the chain ===&lt;br /&gt;
&lt;br /&gt;
There are currently 6 digitizers in the chain. 2 more will be delivered soon. To fully add a new digitizer to the chain, do the following steps. You should only connect one &amp;quot;new&amp;quot; board to the ethernet network at a time (as otherwise they will fight over who gets to use the hard-coded default IP address).&lt;br /&gt;
&lt;br /&gt;
* Turn off the VME crate&lt;br /&gt;
* Install the new digitizer in the VME crate&lt;br /&gt;
* Connect digitizer via ethernet cable to the switch&lt;br /&gt;
* Connect CLK-IN of this board to the CLK-OUT of previous board in chain&lt;br /&gt;
* Connect LEMO cables to NIM fan-in/fan-out modules (GPIO, S-IN, TRG-IN, TRG-OUT)&lt;br /&gt;
* Turn on the VME crate&lt;br /&gt;
* On daq18 web browser, navigate to http://192.168.0.254 (this is the default IP address that boards use coming from the factory)&lt;br /&gt;
** On the Firmware page, load the DPP-ZLE firmware&lt;br /&gt;
** On the Network page, set the IP address to 192.168.0.xxx, where xxx isn&#039;t already used (e.g. 7 for the 7th board)&lt;br /&gt;
* On daq18, as root, edit /etc/hosts to assign a hostname (e.g. vx07 for 192.168.0.7)&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=Programs Programs] webpage, stop the VX frontend&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage, change the number of boards (first row of first table)&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=Programs Programs] webpage, start the VX frontend. It will abort immediately, but will have created space in the ODB for you to configure the new board&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage, set the hostname of the new board and adjust the run start delay by 48ns for all the earlier boards in the chain&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=Programs Programs] webpage, start the VX frontend. It should start correctly this time&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild vx2740_group_fe.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/dsproto_vx2740/build&lt;br /&gt;
make install -j&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/tacticana&lt;br /&gt;
make -j&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Known issues ===&lt;br /&gt;
&lt;br /&gt;
==== Rare bug in CAEN software ====&lt;br /&gt;
&lt;br /&gt;
There is a rare bug in the CAEN software/firmware that causes the entire frontend to crash on malformed data. This can be quite annoying, and could cause significant downtime if the user doesn&#039;t realise that the program has crashed and/or the run has stopped.&lt;br /&gt;
&lt;br /&gt;
midas contains a &amp;quot;sequencer&amp;quot; functionality that can be used to mitigate this. Every 10s the sequencer will check to see if the frontend has crashed, and restart it if needed. It will also start a run if the current one has stopped.&lt;br /&gt;
&lt;br /&gt;
To use this sequencer, go to the [https://daq18.triumf.ca/?cmd=Sequencer&amp;amp;SeqODB=/PySequencer PySequencer] page and start the script using the &amp;quot;play&amp;quot; button. You&#039;ll be prompted for how long you want to acquire data for.&lt;br /&gt;
&lt;br /&gt;
Note that if you want to stop data-taking early, you should use the &amp;quot;stop&amp;quot; (square) button on the PySequencer page, not the regular button on the status page for stopping a run (as the sequencer will just detect that the run has stopped and start a new one for you!).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toccolours mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width:800px; overflow:auto;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-weight:bold;line-height:1.6;&amp;quot;&amp;gt;Click &#039;Expand&#039; to view the actual sequencer script I implemented ----&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import datetime&lt;br /&gt;
import midas&lt;br /&gt;
&lt;br /&gt;
def define_params(seq):&lt;br /&gt;
    seq.register_param(&amp;quot;duration_hours&amp;quot;, &amp;quot;Total acquisition time&amp;quot;, 5.0)&lt;br /&gt;
&lt;br /&gt;
def sequence(seq):&lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
    start_time = datetime.datetime.now()&lt;br /&gt;
    elapsed_hours = 0.0&lt;br /&gt;
        &lt;br /&gt;
    while elapsed_hours &amp;lt; seq.get_param(&amp;quot;duration_hours&amp;quot;):&lt;br /&gt;
        validate_prog_running(seq)&lt;br /&gt;
        seq.wait_seconds(10)&lt;br /&gt;
        elapsed_hours = round((datetime.datetime.now() - start_time).total_seconds() / 3600, 2)&lt;br /&gt;
        &lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
        &lt;br /&gt;
def at_exit(seq):&lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
    &lt;br /&gt;
def stop_run_if_needed(seq):&lt;br /&gt;
    if seq.odb_get(&amp;quot;/Runinfo/State&amp;quot;) != midas.STATE_STOPPED:&lt;br /&gt;
        seq.stop_run()&lt;br /&gt;
    &lt;br /&gt;
def validate_prog_running(seq):&lt;br /&gt;
    prog_name = &amp;quot;VX2740_Group_01&amp;quot;&lt;br /&gt;
    if not seq.client_exists(prog_name):&lt;br /&gt;
        stop_run_if_needed(seq)&lt;br /&gt;
        seq.msg(f&amp;quot;Stopped run as {prog_name} was not running! Restarting program.&amp;quot;)&lt;br /&gt;
        seq.wait_seconds(5)&lt;br /&gt;
        seq.start_client(prog_name)&lt;br /&gt;
        seq.wait_clients_running(prog_name)&lt;br /&gt;
        &lt;br /&gt;
        if not seq.client_exists(prog_name):&lt;br /&gt;
            raise RuntimeError(f&amp;quot;Failed to restart {prog_name} - abort sequence!&amp;quot;)&lt;br /&gt;
            &lt;br /&gt;
        seq.wait_odb(&amp;quot;/Equipment/VX2740_Data_Group_001/Common/Status&amp;quot;, &amp;quot;==&amp;quot;, &amp;quot;Initialized&amp;quot;)&lt;br /&gt;
        &lt;br /&gt;
    if seq.odb_get(&amp;quot;/Runinfo/State&amp;quot;) != midas.STATE_RUNNING:&lt;br /&gt;
        seq.start_run()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8592</id>
		<title>TACTIC</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8592"/>
		<updated>2025-09-17T22:10:48Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= TACTIC =&lt;br /&gt;
&lt;br /&gt;
* computer: daq18.triumf.ca&lt;br /&gt;
* midas: https://daq18.triumf.ca&lt;br /&gt;
* elog: https://elog.triumf.ca/Tactic/General/ (has a &amp;quot;tactic&amp;quot; user account)&lt;br /&gt;
&lt;br /&gt;
== Old V1740 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 2x V1740 via CAEN USB interface. 64 channels each - can read out 2 of the 8 TACTIC &amp;quot;sectors&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
These [https://daq18.triumf.ca/?cmd=Programs programs] should be running:&lt;br /&gt;
* mhttpd (web server)&lt;br /&gt;
* Logger (writing data to disk)&lt;br /&gt;
* feMKS (gas mixer)&lt;br /&gt;
* fetactic (data readout from digitizers)&lt;br /&gt;
* ana (online analysis of data)&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:Tactic-v1740-trigger.jpg]]&lt;br /&gt;
&lt;br /&gt;
Trigger and v1740 connections:&lt;br /&gt;
* both v1740 trigger outputs go to logic OR. pulser goes into the same OR&lt;br /&gt;
* from this OR, they fan out to v1740 trigger inputs&lt;br /&gt;
* analog output of first v1740 provides the run gate (via polarity inverting kludge)&lt;br /&gt;
* analog output of second v1740 provides a &amp;quot;buffer-half-full&amp;quot; trigger veto (via polarity inverting kludge)&lt;br /&gt;
&lt;br /&gt;
Trigger notes: (KO 7-oct-2024)&lt;br /&gt;
* trigger signal is not synched with the v1740 clock, actual &amp;quot;adc stop&amp;quot; time will have a jitter between the two v1740 of 1-2 clock periods&lt;br /&gt;
* actual event time jitter between the two v1740 is around 2 clock (from looking at event timestamps).&lt;br /&gt;
* because v1740 busy are not synced (and busy from first v1740 is missing), the second v1740 often has extra events. sometimes the first v1740 has an extra event. fetactic.exe has workaround against this, mostly by dropping mismatched data.&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/manalyzer. &lt;br /&gt;
* Not source-controlled.&lt;br /&gt;
* Contains many hard-coded thresholds/settings/limits. Also includes a hard-coded mapping between digitizer channel number and hardware sector/pad number.&lt;br /&gt;
* Used for both online and offline analysis of data.&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild fetactic.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/v1740mt&lt;br /&gt;
make&lt;br /&gt;
ls -l fetactic.exe&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/manalyzer&lt;br /&gt;
make&lt;br /&gt;
ls -l ./tacticana.exe&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== New V2745 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 6x CAEN V2745 digitizers, with option for reading 8 digitizers if needed. With 8 digitizers can read all 8 sectors from the hardware.&lt;br /&gt;
&lt;br /&gt;
Digitizers are readout over 1G ethernet, and run DPP_ZLE firmware to reduce the data rate significantly. Future versions of TACTIC may run DPP_PHA or custom firmware to further reduce the data rate.&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:TACTIC wiring V2745.png]]&lt;br /&gt;
&lt;br /&gt;
The trigger is a global OR of every channel of every digitizer (though we can suppress certain channels if desired).&lt;br /&gt;
&lt;br /&gt;
Digitizers are set to NIM logic levels, and OR is done using standard NIM fan-in/fan-out modules. Trigger-OR is sent to 9 locations (8 digitizers + 1 visual scaler) so we use a 16x FI/FO. Busy-OR is only sent to 8 locations, so can use an 8x FI/FO.&lt;br /&gt;
&lt;br /&gt;
=== Frontend notes ===&lt;br /&gt;
&lt;br /&gt;
The main frontend code is shared with the Darkside-20k experiment that uses VX2740/VX2745 digitizers running custom firmware. The repository name (dsproto_vx2740) reflects this heritage, but the code now supports more than just Darkside&#039;s usage! The code is located on BitBucket at https://bitbucket.org/ttriumfdaq/dsproto_vx2740/&lt;br /&gt;
&lt;br /&gt;
Digitizer configuration is done via the [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage. The concept is that the &amp;quot;default&amp;quot; value is applied to all digitizers, unless you specifically override the value for a certain digitizer. This means it&#039;s more efficient to change settings, as you only have to change one &amp;quot;default&amp;quot; parameter rather than 8 separate board-specific parameters. Settings that have been overridden for one or more boards appear with a YELLOW background on the webpage.&lt;br /&gt;
&lt;br /&gt;
==== Settings that users may want to configure ====&lt;br /&gt;
* &#039;&#039;&#039;Readout channel mask&#039;&#039;&#039; - which channels get read out when a trigger is accepted&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A en mask&#039;&#039;&#039; - which channels contribute to the self-trigger logic&lt;br /&gt;
* &#039;&#039;&#039;Chan over thresh thresholds&#039;&#039;&#039; - the thresholds in ADC RELATIVE TO THE BASELINE&lt;br /&gt;
* &#039;&#039;&#039;Scope/ZLE waveform length&#039;&#039;&#039; - how long the waveforms should be.&lt;br /&gt;
* &#039;&#039;&#039;Pre-trigger for ZLE mode&#039;&#039;&#039; - where in the waveform the trigger pulse should appear &lt;br /&gt;
* &#039;&#039;&#039;ZLE threshold (ADC)&#039;&#039;&#039; - how many ADC below baseline a signal must be before it gets read out. Note this is different to the trigger threshold! You could trigger readout if the signal goes 50ADC below baseline, but then read out any data that&#039;s 10ADC below baseline.&lt;br /&gt;
* &#039;&#039;&#039;ZLE look back (samples)&#039;&#039;&#039; - how many samples to read out before the signal went below the ZLE threshold&lt;br /&gt;
* &#039;&#039;&#039;ZLE look forward (samples)&#039;&#039;&#039; - how many samples to read out after the signal goes back above the ZLE threshold&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A gate width(ns)&#039;&#039;&#039; - set this to roughly how long you expect a &amp;quot;real&amp;quot; event to last. If you set it too short then the NIM OR module will output triggers multiple times for a single event (e.g. for the first channel to get hit, and then 100ns later for another channel, and then 300ns after that for another channel, ....). The digitizers would still only read out data for the first trigger, but the visual scaler will show a much higher rate, which would be very confusing for debugging.&lt;br /&gt;
* &#039;&#039;&#039;DC offset (pct)&#039;&#039;&#039; - set the baseline between 0ADC and 65535ADC, as a percentage&lt;br /&gt;
* &#039;&#039;&#039;Signal offset (uV)&#039;&#039;&#039; - extra tweak to the input signal - best set using a script&lt;br /&gt;
* &#039;&#039;&#039;VGA gain&#039;&#039;&#039; - 0-40dB in 0.5dB increments&lt;br /&gt;
&lt;br /&gt;
==== Settings that are different for the first digitizer in the chain ====&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Run start source&#039;&#039;&#039;&lt;br /&gt;
** First board: Start acq on midas run start&lt;br /&gt;
** Other boards: Start acq on encoded CLKIN&lt;br /&gt;
* &#039;&#039;&#039;Use external clock&#039;&#039;&#039;&lt;br /&gt;
** First board: True&lt;br /&gt;
** Other boards: False&lt;br /&gt;
&lt;br /&gt;
==== Settings that user&#039;s shouldn&#039;t touch ====&lt;br /&gt;
* &#039;&#039;&#039;Run start delay (ns)&#039;&#039;&#039; - 0 for the last board, increasing by 48ns for each board in the chain (240, 192, 144, 96, 49, 0).&lt;br /&gt;
* &#039;&#039;&#039;Trigger out mode&#039;&#039;&#039; - ITLA - ensure we output the self-trigger signal&lt;br /&gt;
* &#039;&#039;&#039;Trigger on external signal&#039;&#039;&#039; - True - ensure we only trigger on the global OR that gets fed back in to the board&lt;br /&gt;
* &#039;&#039;&#039;ZLE enable&#039;&#039;&#039; - True for all channels&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A multiplicity&#039;&#039;&#039; - 1 - in principle you could require 2+ hits simultaneously before we trigger (to reduce triggering on noise/bad topology events), but this setting only applies within a single board. So you&#039;ll get weird geometric efficiencies (more likely to trigger on tracks that hit multiple pads in the same sector vs pads in different sectors). If we want to trigger on 2+ hits across multiple boards we can use the DAC or LVDS connectors, and connect them to a board running custom firmware.&lt;br /&gt;
* &#039;&#039;&#039;Chan over thresh rising edge&#039;&#039;&#039; - False - TACTIC uses negative pulses&lt;br /&gt;
* &#039;&#039;&#039;Veto source&#039;&#039;&#039; / &#039;&#039;&#039;Veto when source is high&#039;&#039;&#039; - Disabled / True&lt;br /&gt;
* &#039;&#039;&#039;Use NIM IO&#039;&#039;&#039; - True&lt;br /&gt;
* &#039;&#039;&#039;Enable clock out&#039;&#039;&#039; - True&lt;br /&gt;
* &#039;&#039;&#039;GPIO mode&#039;&#039;&#039; - Busy&lt;br /&gt;
* &#039;&#039;&#039;Busy in source&#039;&#039;&#039; - SIN&lt;br /&gt;
* &#039;&#039;&#039;Sync out mode&#039;&#039;&#039; - Run&lt;br /&gt;
* &#039;&#039;&#039;Enable DC offsets&#039;&#039;&#039; - True&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/tacticana on daq18, and https://bitbucket.org/ttriumfdaq/tacticana/src/master/ on bitbucket.&lt;br /&gt;
* Uses JSON files to define histogram limits, channel mapping etc. See the [https://bitbucket.org/ttriumfdaq/tacticana/src/master/ README.md] file in the repository for details.&lt;br /&gt;
* Specify which config file to use via the --config flag.&lt;br /&gt;
* It replaces &amp;quot;gaps&amp;quot; in the ZLE waveforms with the baseline value (so the rest of the code sees a &amp;quot;normal&amp;quot; waveform with some very flat sections). This was done to minimise the number of changes needed in the rest of the analysis code that was inherited from the V1740-based DAQ.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Run online using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe --midas-progname tacticana -R8081 -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# Run offline using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe /path/to/something.mid -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# NOTE THE --config FLAG MUST COME AFTER A &#039;--&#039;!!!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Custom webpages ===&lt;br /&gt;
&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] page lets you configure all the digitizers. As note above, there is a column for the &amp;quot;default&amp;quot; value for all digitizers, plus optional board-specific &amp;quot;override&amp;quot; values.&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20waveforms VX waveforms] page shows realtime display of waveforms from a handful of channels. It currently only allows you to view 4 channels from a single board. For more advanced options, use the [https://daq18.triumf.ca/proxy/tacticana_new/ tacticana new] webpage.&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20rates VX rates] page shows the readout rate of each board/channel, as well as the overall readout rate over time. The former may be useful for identifying any abnormally &amp;quot;hot&amp;quot;/&amp;quot;cold&amp;quot; channels that have a bad baseline. The latter is useful for tracking stability over time.&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VME%20crate VME crate] page allows you to power-cycle the VME crate remotely. Useful if the digitizers get in a really bad state and can only be fixed by power-cycling (stop the run, stop the VX frontend, power-cycle the crate, start the VX frontend, wait for the status page to show &amp;quot;Initialized&amp;quot;, start the run)&lt;br /&gt;
* The [https://daq18.triumf.ca/proxy/tacticana_new/ tacticana new] page is a ROOT-based display of histograms created by the [[#Analyzer_notes|analyzer]]. You will need to refresh the page when a new run starts.&lt;br /&gt;
&lt;br /&gt;
=== Setting baselines ===&lt;br /&gt;
&lt;br /&gt;
The V2745s have two settings related to the baseline of each channel.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;DC offset&#039;&#039;&#039; sets the target of where the baseline &amp;quot;should&amp;quot; be. It&#039;s specified as a percentage of the full scale 0-65535. For TACTIC with negative pulses, it makes sense to set it to 90% or so (aka 58982 ADC).&lt;br /&gt;
* &#039;&#039;&#039;Signal offset&#039;&#039;&#039; is an extra tweak to each channel (in uV) that can be used to ensure a 0V input actually gets to the expected baseline.&lt;br /&gt;
&lt;br /&gt;
ZLE and trigger thresholds are RELATIVE TO THE EXPECTED BASELINE (i.e. 58982 ADC). The digitizers to not monitor the actual data to decide what the &amp;quot;real baseline&amp;quot; is. It is therefore critical that the signal offset is set so that the real baseline matches the expected baseline. &lt;br /&gt;
&lt;br /&gt;
* If the real baseline is lower than expected, you will trigger more often and your data rate will be higher. &lt;br /&gt;
* If the real baseline is higher than expected, you will miss triggering on small pulses, and may miss some ZLE chunks that would otherwise be readout.&lt;br /&gt;
&lt;br /&gt;
Note that baselines often drift based on the temperature of the board.&lt;br /&gt;
&lt;br /&gt;
There is a script in the dsproto_vx2740 repository that can be used to set the &amp;quot;signal offset&amp;quot; of each channel so that the real baseline matches the expected baseline. This script is very basic at the moment, but could be made smarter (both in terms of the algorithm for finding the optimal offset, and in automating more of the settings that need to be changed).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Stop the run&lt;br /&gt;
# Ensure there aren&#039;t any real signals coming in (i.e. we&#039;re just reading noise)&lt;br /&gt;
# Set &#039;ZLE enable&#039; to False for all channels&lt;br /&gt;
# Set &#039;Trigger out mode&#039; to &#039;TestPulse&#039; for the first board, and &#039;Disabled&#039; for all other boards&lt;br /&gt;
&lt;br /&gt;
cd ~/newTACTIC/dsproto_vx2740/&lt;br /&gt;
python set_offsets.py &lt;br /&gt;
&lt;br /&gt;
# Set &#039;ZLE enable&#039; to True for all channels&lt;br /&gt;
# Set &#039;Trigger out mode&#039; to &#039;ITLA&#039; for all boards&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== Adding more digitizers to the chain ===&lt;br /&gt;
&lt;br /&gt;
There are currently 6 digitizers in the chain. 2 more will be delivered soon. To fully add a new digitizer to the chain, do the following steps. You should only connect one &amp;quot;new&amp;quot; board to the ethernet network at a time (as otherwise they will fight over who gets to use the hard-coded default IP address).&lt;br /&gt;
&lt;br /&gt;
* Turn off the VME crate&lt;br /&gt;
* Install the new digitizer in the VME crate&lt;br /&gt;
* Connect digitizer via ethernet cable to the switch&lt;br /&gt;
* Connect CLK-IN of this board to the CLK-OUT of previous board in chain&lt;br /&gt;
* Connect LEMO cables to NIM fan-in/fan-out modules (GPIO, S-IN, TRG-IN, TRG-OUT)&lt;br /&gt;
* Turn on the VME crate&lt;br /&gt;
* On daq18 web browser, navigate to http://192.168.0.254 (this is the default IP address that boards use coming from the factory)&lt;br /&gt;
** On the Firmware page, load the DPP-ZLE firmware&lt;br /&gt;
** On the Network page, set the IP address to 192.168.0.xxx, where xxx isn&#039;t already used (e.g. 7 for the 7th board)&lt;br /&gt;
* On daq18, as root, edit /etc/hosts to assign a hostname (e.g. vx07 for 192.168.0.7)&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=Programs Programs] webpage, stop the VX frontend&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage, change the number of boards (first row of first table)&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=Programs Programs] webpage, start the VX frontend. It will abort immediately, but will have created space in the ODB for you to configure the new board&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage, set the hostname of the new board and adjust the run start delay by 48ns for all the earlier boards in the chain&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=Programs Programs] webpage, start the VX frontend. It should start correctly this time&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild vx2740_group_fe.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/dsproto_vx2740/build&lt;br /&gt;
make install -j&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/tacticana&lt;br /&gt;
make -j&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Known issues ===&lt;br /&gt;
&lt;br /&gt;
==== Rare bug in CAEN software ====&lt;br /&gt;
&lt;br /&gt;
There is a rare bug in the CAEN software/firmware that causes the entire frontend to crash on malformed data. This can be quite annoying, and could cause significant downtime if the user doesn&#039;t realise that the program has crashed and/or the run has stopped.&lt;br /&gt;
&lt;br /&gt;
midas contains a &amp;quot;sequencer&amp;quot; functionality that can be used to mitigate this. Every 10s the sequencer will check to see if the frontend has crashed, and restart it if needed. It will also start a run if the current one has stopped.&lt;br /&gt;
&lt;br /&gt;
To use this sequencer, go to the [https://daq18.triumf.ca/?cmd=Sequencer&amp;amp;SeqODB=/PySequencer PySequencer] page and start the script using the &amp;quot;play&amp;quot; button. You&#039;ll be prompted for how long you want to acquire data for.&lt;br /&gt;
&lt;br /&gt;
Note that if you want to stop data-taking early, you should use the &amp;quot;stop&amp;quot; (square) button on the PySequencer page, not the regular button on the status page for stopping a run (as the sequencer will just detect that the run has stopped and start a new one for you!).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toccolours mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width:800px; overflow:auto;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-weight:bold;line-height:1.6;&amp;quot;&amp;gt;Click &#039;Expand&#039; to view the actual sequencer script I implemented ----&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import datetime&lt;br /&gt;
import midas&lt;br /&gt;
&lt;br /&gt;
def define_params(seq):&lt;br /&gt;
    seq.register_param(&amp;quot;duration_hours&amp;quot;, &amp;quot;Total acquisition time&amp;quot;, 5.0)&lt;br /&gt;
&lt;br /&gt;
def sequence(seq):&lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
    start_time = datetime.datetime.now()&lt;br /&gt;
    elapsed_hours = 0.0&lt;br /&gt;
        &lt;br /&gt;
    while elapsed_hours &amp;lt; seq.get_param(&amp;quot;duration_hours&amp;quot;):&lt;br /&gt;
        validate_prog_running(seq)&lt;br /&gt;
        seq.wait_seconds(10)&lt;br /&gt;
        elapsed_hours = round((datetime.datetime.now() - start_time).total_seconds() / 3600, 2)&lt;br /&gt;
        &lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
        &lt;br /&gt;
def at_exit(seq):&lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
    &lt;br /&gt;
def stop_run_if_needed(seq):&lt;br /&gt;
    if seq.odb_get(&amp;quot;/Runinfo/State&amp;quot;) != midas.STATE_STOPPED:&lt;br /&gt;
        seq.stop_run()&lt;br /&gt;
    &lt;br /&gt;
def validate_prog_running(seq):&lt;br /&gt;
    prog_name = &amp;quot;VX2740_Group_01&amp;quot;&lt;br /&gt;
    if not seq.client_exists(prog_name):&lt;br /&gt;
        stop_run_if_needed(seq)&lt;br /&gt;
        seq.msg(f&amp;quot;Stopped run as {prog_name} was not running! Restarting program.&amp;quot;)&lt;br /&gt;
        seq.wait_seconds(5)&lt;br /&gt;
        seq.start_client(prog_name)&lt;br /&gt;
        seq.wait_clients_running(prog_name)&lt;br /&gt;
        &lt;br /&gt;
        if not seq.client_exists(prog_name):&lt;br /&gt;
            raise RuntimeError(f&amp;quot;Failed to restart {prog_name} - abort sequence!&amp;quot;)&lt;br /&gt;
            &lt;br /&gt;
        seq.wait_odb(&amp;quot;/Equipment/VX2740_Data_Group_001/Common/Status&amp;quot;, &amp;quot;==&amp;quot;, &amp;quot;Initialized&amp;quot;)&lt;br /&gt;
        &lt;br /&gt;
    if seq.odb_get(&amp;quot;/Runinfo/State&amp;quot;) != midas.STATE_RUNNING:&lt;br /&gt;
        seq.start_run()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8591</id>
		<title>TACTIC</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8591"/>
		<updated>2025-09-17T22:07:22Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= TACTIC =&lt;br /&gt;
&lt;br /&gt;
* computer: daq18.triumf.ca&lt;br /&gt;
* midas: https://daq18.triumf.ca&lt;br /&gt;
* elog: https://elog.triumf.ca/Tactic/General/ (has a &amp;quot;tactic&amp;quot; user account)&lt;br /&gt;
&lt;br /&gt;
== Old V1740 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 2x V1740 via CAEN USB interface. 64 channels each - can read out 2 of the 8 TACTIC &amp;quot;sectors&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
These [https://daq18.triumf.ca/?cmd=Programs programs] should be running:&lt;br /&gt;
* mhttpd (web server)&lt;br /&gt;
* Logger (writing data to disk)&lt;br /&gt;
* feMKS (gas mixer)&lt;br /&gt;
* fetactic (data readout from digitizers)&lt;br /&gt;
* ana (online analysis of data)&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:Tactic-v1740-trigger.jpg]]&lt;br /&gt;
&lt;br /&gt;
Trigger and v1740 connections:&lt;br /&gt;
* both v1740 trigger outputs go to logic OR. pulser goes into the same OR&lt;br /&gt;
* from this OR, they fan out to v1740 trigger inputs&lt;br /&gt;
* analog output of first v1740 provides the run gate (via polarity inverting kludge)&lt;br /&gt;
* analog output of second v1740 provides a &amp;quot;buffer-half-full&amp;quot; trigger veto (via polarity inverting kludge)&lt;br /&gt;
&lt;br /&gt;
Trigger notes: (KO 7-oct-2024)&lt;br /&gt;
* trigger signal is not synched with the v1740 clock, actual &amp;quot;adc stop&amp;quot; time will have a jitter between the two v1740 of 1-2 clock periods&lt;br /&gt;
* actual event time jitter between the two v1740 is around 2 clock (from looking at event timestamps).&lt;br /&gt;
* because v1740 busy are not synced (and busy from first v1740 is missing), the second v1740 often has extra events. sometimes the first v1740 has an extra event. fetactic.exe has workaround against this, mostly by dropping mismatched data.&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/manalyzer. &lt;br /&gt;
* Not source-controlled.&lt;br /&gt;
* Contains many hard-coded thresholds/settings/limits. Also includes a hard-coded mapping between digitizer channel number and hardware sector/pad number.&lt;br /&gt;
* Used for both online and offline analysis of data.&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild fetactic.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/v1740mt&lt;br /&gt;
make&lt;br /&gt;
ls -l fetactic.exe&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/manalyzer&lt;br /&gt;
make&lt;br /&gt;
ls -l ./tacticana.exe&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== New V2745 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 6x CAEN V2745 digitizers, with option for reading 8 digitizers if needed. With 8 digitizers can read all 8 sectors from the hardware.&lt;br /&gt;
&lt;br /&gt;
Digitizers are readout over 1G ethernet, and run DPP_ZLE firmware to reduce the data rate significantly. Future versions of TACTIC may run DPP_PHA or custom firmware to further reduce the data rate.&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:TACTIC wiring V2745.png]]&lt;br /&gt;
&lt;br /&gt;
The trigger is a global OR of every channel of every digitizer (though we can suppress certain channels if desired).&lt;br /&gt;
&lt;br /&gt;
Digitizers are set to NIM logic levels, and OR is done using standard NIM fan-in/fan-out modules. Trigger-OR is sent to 9 locations (8 digitizers + 1 visual scaler) so we use a 16x FI/FO. Busy-OR is only sent to 8 locations, so can use an 8x FI/FO.&lt;br /&gt;
&lt;br /&gt;
Digitizer configuration is done via the [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage. The concept is that the &amp;quot;default&amp;quot; value is applied to all digitizers, unless you specifically override the value for a certain digitizer. This means it&#039;s more efficient to change settings, as you only have to change one &amp;quot;default&amp;quot; parameter rather than 8 separate board-specific parameters. Settings that have been overridden for one or more boards appear with a YELLOW background on the webpage.&lt;br /&gt;
&lt;br /&gt;
==== Settings that users may want to configure ====&lt;br /&gt;
* &#039;&#039;&#039;Readout channel mask&#039;&#039;&#039; - which channels get read out when a trigger is accepted&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A en mask&#039;&#039;&#039; - which channels contribute to the self-trigger logic&lt;br /&gt;
* &#039;&#039;&#039;Chan over thresh thresholds&#039;&#039;&#039; - the thresholds in ADC RELATIVE TO THE BASELINE&lt;br /&gt;
* &#039;&#039;&#039;Scope/ZLE waveform length&#039;&#039;&#039; - how long the waveforms should be.&lt;br /&gt;
* &#039;&#039;&#039;Pre-trigger for ZLE mode&#039;&#039;&#039; - where in the waveform the trigger pulse should appear &lt;br /&gt;
* &#039;&#039;&#039;ZLE threshold (ADC)&#039;&#039;&#039; - how many ADC below baseline a signal must be before it gets read out. Note this is different to the trigger threshold! You could trigger readout if the signal goes 50ADC below baseline, but then read out any data that&#039;s 10ADC below baseline.&lt;br /&gt;
* &#039;&#039;&#039;ZLE look back (samples)&#039;&#039;&#039; - how many samples to read out before the signal went below the ZLE threshold&lt;br /&gt;
* &#039;&#039;&#039;ZLE look forward (samples)&#039;&#039;&#039; - how many samples to read out after the signal goes back above the ZLE threshold&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A gate width(ns)&#039;&#039;&#039; - set this to roughly how long you expect a &amp;quot;real&amp;quot; event to last. If you set it too short then the NIM OR module will output triggers multiple times for a single event (e.g. for the first channel to get hit, and then 100ns later for another channel, and then 300ns after that for another channel, ....). The digitizers would still only read out data for the first trigger, but the visual scaler will show a much higher rate, which would be very confusing for debugging.&lt;br /&gt;
* &#039;&#039;&#039;DC offset (pct)&#039;&#039;&#039; - set the baseline between 0ADC and 65535ADC, as a percentage&lt;br /&gt;
* &#039;&#039;&#039;Signal offset (uV)&#039;&#039;&#039; - extra tweak to the input signal - best set using a script&lt;br /&gt;
* &#039;&#039;&#039;VGA gain&#039;&#039;&#039; - 0-40dB in 0.5dB increments&lt;br /&gt;
&lt;br /&gt;
==== Settings that are different for the first digitizer in the chain ====&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Run start source&#039;&#039;&#039;&lt;br /&gt;
** First board: Start acq on midas run start&lt;br /&gt;
** Other boards: Start acq on encoded CLKIN&lt;br /&gt;
* &#039;&#039;&#039;Use external clock&#039;&#039;&#039;&lt;br /&gt;
** First board: True&lt;br /&gt;
** Other boards: False&lt;br /&gt;
&lt;br /&gt;
==== Settings that user&#039;s shouldn&#039;t touch ====&lt;br /&gt;
* &#039;&#039;&#039;Run start delay (ns)&#039;&#039;&#039; - 0 for the last board, increasing by 48ns for each board in the chain (240, 192, 144, 96, 49, 0).&lt;br /&gt;
* &#039;&#039;&#039;Trigger out mode&#039;&#039;&#039; - ITLA - ensure we output the self-trigger signal&lt;br /&gt;
* &#039;&#039;&#039;Trigger on external signal&#039;&#039;&#039; - True - ensure we only trigger on the global OR that gets fed back in to the board&lt;br /&gt;
* &#039;&#039;&#039;ZLE enable&#039;&#039;&#039; - True for all channels&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A multiplicity&#039;&#039;&#039; - 1 - in principle you could require 2+ hits simultaneously before we trigger (to reduce triggering on noise/bad topology events), but this setting only applies within a single board. So you&#039;ll get weird geometric efficiencies (more likely to trigger on tracks that hit multiple pads in the same sector vs pads in different sectors). If we want to trigger on 2+ hits across multiple boards we can use the DAC or LVDS connectors, and connect them to a board running custom firmware.&lt;br /&gt;
* &#039;&#039;&#039;Chan over thresh rising edge&#039;&#039;&#039; - False - TACTIC uses negative pulses&lt;br /&gt;
* &#039;&#039;&#039;Veto source&#039;&#039;&#039; / &#039;&#039;&#039;Veto when source is high&#039;&#039;&#039; - Disabled / True&lt;br /&gt;
* &#039;&#039;&#039;Use NIM IO&#039;&#039;&#039; - True&lt;br /&gt;
* &#039;&#039;&#039;Enable clock out&#039;&#039;&#039; - True&lt;br /&gt;
* &#039;&#039;&#039;GPIO mode&#039;&#039;&#039; - Busy&lt;br /&gt;
* &#039;&#039;&#039;Busy in source&#039;&#039;&#039; - SIN&lt;br /&gt;
* &#039;&#039;&#039;Sync out mode&#039;&#039;&#039; - Run&lt;br /&gt;
* &#039;&#039;&#039;Enable DC offsets&#039;&#039;&#039; - True&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/tacticana on daq18, and https://bitbucket.org/ttriumfdaq/tacticana/src/master/ on bitbucket.&lt;br /&gt;
* Uses JSON files to define histogram limits, channel mapping etc. See the [https://bitbucket.org/ttriumfdaq/tacticana/src/master/ README.md] file in the repository for details.&lt;br /&gt;
* Specify which config file to use via the --config flag.&lt;br /&gt;
* It replaces &amp;quot;gaps&amp;quot; in the ZLE waveforms with the baseline value (so the rest of the code sees a &amp;quot;normal&amp;quot; waveform with some very flat sections). This was done to minimise the number of changes needed in the rest of the analysis code that was inherited from the V1740-based DAQ.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Run online using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe --midas-progname tacticana -R8081 -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# Run offline using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe /path/to/something.mid -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# NOTE THE --config FLAG MUST COME AFTER A &#039;--&#039;!!!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Custom webpages ===&lt;br /&gt;
&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] page lets you configure all the digitizers. As note above, there is a column for the &amp;quot;default&amp;quot; value for all digitizers, plus optional board-specific &amp;quot;override&amp;quot; values.&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20waveforms VX waveforms] page shows realtime display of waveforms from a handful of channels. It currently only allows you to view 4 channels from a single board. For more advanced options, use the [https://daq18.triumf.ca/proxy/tacticana_new/ tacticana new] webpage.&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20rates VX rates] page shows the readout rate of each board/channel, as well as the overall readout rate over time. The former may be useful for identifying any abnormally &amp;quot;hot&amp;quot;/&amp;quot;cold&amp;quot; channels that have a bad baseline. The latter is useful for tracking stability over time.&lt;br /&gt;
* The [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VME%20crate VME crate] page allows you to power-cycle the VME crate remotely. Useful if the digitizers get in a really bad state and can only be fixed by power-cycling (stop the run, stop the VX frontend, power-cycle the crate, start the VX frontend, wait for the status page to show &amp;quot;Initialized&amp;quot;, start the run)&lt;br /&gt;
* The [https://daq18.triumf.ca/proxy/tacticana_new/ tacticana new] page is a ROOT-based display of histograms created by the [[#Analyzer_notes|analyzer]]. You will need to refresh the page when a new run starts.&lt;br /&gt;
&lt;br /&gt;
=== Setting baselines ===&lt;br /&gt;
&lt;br /&gt;
The V2745s have two settings related to the baseline of each channel.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;DC offset&#039;&#039;&#039; sets the target of where the baseline &amp;quot;should&amp;quot; be. It&#039;s specified as a percentage of the full scale 0-65535. For TACTIC with negative pulses, it makes sense to set it to 90% or so (aka 58982 ADC).&lt;br /&gt;
* &#039;&#039;&#039;Signal offset&#039;&#039;&#039; is an extra tweak to each channel (in uV) that can be used to ensure a 0V input actually gets to the expected baseline.&lt;br /&gt;
&lt;br /&gt;
ZLE and trigger thresholds are RELATIVE TO THE EXPECTED BASELINE (i.e. 58982 ADC). The digitizers to not monitor the actual data to decide what the &amp;quot;real baseline&amp;quot; is. It is therefore critical that the signal offset is set so that the real baseline matches the expected baseline. &lt;br /&gt;
&lt;br /&gt;
* If the real baseline is lower than expected, you will trigger more often and your data rate will be higher. &lt;br /&gt;
* If the real baseline is higher than expected, you will miss triggering on small pulses, and may miss some ZLE chunks that would otherwise be readout.&lt;br /&gt;
&lt;br /&gt;
Note that baselines often drift based on the temperature of the board.&lt;br /&gt;
&lt;br /&gt;
There is a script in the dsproto_vx2740 repository that can be used to set the &amp;quot;signal offset&amp;quot; of each channel so that the real baseline matches the expected baseline. This script is very basic at the moment, but could be made smarter (both in terms of the algorithm for finding the optimal offset, and in automating more of the settings that need to be changed).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Stop the run&lt;br /&gt;
# Ensure there aren&#039;t any real signals coming in (i.e. we&#039;re just reading noise)&lt;br /&gt;
# Set &#039;ZLE enable&#039; to False for all channels&lt;br /&gt;
# Set &#039;Trigger out mode&#039; to &#039;TestPulse&#039; for the first board, and &#039;Disabled&#039; for all other boards&lt;br /&gt;
&lt;br /&gt;
cd ~/newTACTIC/dsproto_vx2740/&lt;br /&gt;
python set_offsets.py &lt;br /&gt;
&lt;br /&gt;
# Set &#039;ZLE enable&#039; to True for all channels&lt;br /&gt;
# Set &#039;Trigger out mode&#039; to &#039;ITLA&#039; for all boards&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== Adding more digitizers to the chain ===&lt;br /&gt;
&lt;br /&gt;
There are currently 6 digitizers in the chain. 2 more will be delivered soon. To fully add a new digitizer to the chain, do the following steps. You should only connect one &amp;quot;new&amp;quot; board to the ethernet network at a time (as otherwise they will fight over who gets to use the hard-coded default IP address).&lt;br /&gt;
&lt;br /&gt;
* Turn off the VME crate&lt;br /&gt;
* Install the new digitizer in the VME crate&lt;br /&gt;
* Connect digitizer via ethernet cable to the switch&lt;br /&gt;
* Connect CLK-IN of this board to the CLK-OUT of previous board in chain&lt;br /&gt;
* Connect LEMO cables to NIM fan-in/fan-out modules (GPIO, S-IN, TRG-IN, TRG-OUT)&lt;br /&gt;
* Turn on the VME crate&lt;br /&gt;
* On daq18 web browser, navigate to http://192.168.0.254 (this is the default IP address that boards use coming from the factory)&lt;br /&gt;
** On the Firmware page, load the DPP-ZLE firmware&lt;br /&gt;
** On the Network page, set the IP address to 192.168.0.xxx, where xxx isn&#039;t already used (e.g. 7 for the 7th board)&lt;br /&gt;
* On daq18, as root, edit /etc/hosts to assign a hostname (e.g. vx07 for 192.168.0.7)&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=Programs Programs] webpage, stop the VX frontend&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage, change the number of boards (first row of first table)&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=Programs Programs] webpage, start the VX frontend. It will abort immediately, but will have created space in the ODB for you to configure the new board&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage, set the hostname of the new board and adjust the run start delay by 48ns for all the earlier boards in the chain&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=Programs Programs] webpage, start the VX frontend. It should start correctly this time&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild vx2740_group_fe.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/dsproto_vx2740/build&lt;br /&gt;
make install -j&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/tacticana&lt;br /&gt;
make -j&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Known issues ===&lt;br /&gt;
&lt;br /&gt;
==== Rare bug in CAEN software ====&lt;br /&gt;
&lt;br /&gt;
There is a rare bug in the CAEN software/firmware that causes the entire frontend to crash on malformed data. This can be quite annoying, and could cause significant downtime if the user doesn&#039;t realise that the program has crashed and/or the run has stopped.&lt;br /&gt;
&lt;br /&gt;
midas contains a &amp;quot;sequencer&amp;quot; functionality that can be used to mitigate this. Every 10s the sequencer will check to see if the frontend has crashed, and restart it if needed. It will also start a run if the current one has stopped.&lt;br /&gt;
&lt;br /&gt;
To use this sequencer, go to the [https://daq18.triumf.ca/?cmd=Sequencer&amp;amp;SeqODB=/PySequencer PySequencer] page and start the script using the &amp;quot;play&amp;quot; button. You&#039;ll be prompted for how long you want to acquire data for.&lt;br /&gt;
&lt;br /&gt;
Note that if you want to stop data-taking early, you should use the &amp;quot;stop&amp;quot; (square) button on the PySequencer page, not the regular button on the status page for stopping a run (as the sequencer will just detect that the run has stopped and start a new one for you!).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toccolours mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width:800px; overflow:auto;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-weight:bold;line-height:1.6;&amp;quot;&amp;gt;Click &#039;Expand&#039; to view the actual sequencer script I implemented ----&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import datetime&lt;br /&gt;
import midas&lt;br /&gt;
&lt;br /&gt;
def define_params(seq):&lt;br /&gt;
    seq.register_param(&amp;quot;duration_hours&amp;quot;, &amp;quot;Total acquisition time&amp;quot;, 5.0)&lt;br /&gt;
&lt;br /&gt;
def sequence(seq):&lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
    start_time = datetime.datetime.now()&lt;br /&gt;
    elapsed_hours = 0.0&lt;br /&gt;
        &lt;br /&gt;
    while elapsed_hours &amp;lt; seq.get_param(&amp;quot;duration_hours&amp;quot;):&lt;br /&gt;
        validate_prog_running(seq)&lt;br /&gt;
        seq.wait_seconds(10)&lt;br /&gt;
        elapsed_hours = round((datetime.datetime.now() - start_time).total_seconds() / 3600, 2)&lt;br /&gt;
        &lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
        &lt;br /&gt;
def at_exit(seq):&lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
    &lt;br /&gt;
def stop_run_if_needed(seq):&lt;br /&gt;
    if seq.odb_get(&amp;quot;/Runinfo/State&amp;quot;) != midas.STATE_STOPPED:&lt;br /&gt;
        seq.stop_run()&lt;br /&gt;
    &lt;br /&gt;
def validate_prog_running(seq):&lt;br /&gt;
    prog_name = &amp;quot;VX2740_Group_01&amp;quot;&lt;br /&gt;
    if not seq.client_exists(prog_name):&lt;br /&gt;
        stop_run_if_needed(seq)&lt;br /&gt;
        seq.msg(f&amp;quot;Stopped run as {prog_name} was not running! Restarting program.&amp;quot;)&lt;br /&gt;
        seq.wait_seconds(5)&lt;br /&gt;
        seq.start_client(prog_name)&lt;br /&gt;
        seq.wait_clients_running(prog_name)&lt;br /&gt;
        &lt;br /&gt;
        if not seq.client_exists(prog_name):&lt;br /&gt;
            raise RuntimeError(f&amp;quot;Failed to restart {prog_name} - abort sequence!&amp;quot;)&lt;br /&gt;
            &lt;br /&gt;
        seq.wait_odb(&amp;quot;/Equipment/VX2740_Data_Group_001/Common/Status&amp;quot;, &amp;quot;==&amp;quot;, &amp;quot;Initialized&amp;quot;)&lt;br /&gt;
        &lt;br /&gt;
    if seq.odb_get(&amp;quot;/Runinfo/State&amp;quot;) != midas.STATE_RUNNING:&lt;br /&gt;
        seq.start_run()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8590</id>
		<title>TACTIC</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8590"/>
		<updated>2025-09-17T21:56:17Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= TACTIC =&lt;br /&gt;
&lt;br /&gt;
* computer: daq18.triumf.ca&lt;br /&gt;
* midas: https://daq18.triumf.ca&lt;br /&gt;
* elog: https://elog.triumf.ca/Tactic/General/ (has a &amp;quot;tactic&amp;quot; user account)&lt;br /&gt;
&lt;br /&gt;
== Old V1740 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 2x V1740 via CAEN USB interface. 64 channels each - can read out 2 of the 8 TACTIC &amp;quot;sectors&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
These [https://daq18.triumf.ca/?cmd=Programs programs] should be running:&lt;br /&gt;
* mhttpd (web server)&lt;br /&gt;
* Logger (writing data to disk)&lt;br /&gt;
* feMKS (gas mixer)&lt;br /&gt;
* fetactic (data readout from digitizers)&lt;br /&gt;
* ana (online analysis of data)&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:Tactic-v1740-trigger.jpg]]&lt;br /&gt;
&lt;br /&gt;
Trigger and v1740 connections:&lt;br /&gt;
* both v1740 trigger outputs go to logic OR. pulser goes into the same OR&lt;br /&gt;
* from this OR, they fan out to v1740 trigger inputs&lt;br /&gt;
* analog output of first v1740 provides the run gate (via polarity inverting kludge)&lt;br /&gt;
* analog output of second v1740 provides a &amp;quot;buffer-half-full&amp;quot; trigger veto (via polarity inverting kludge)&lt;br /&gt;
&lt;br /&gt;
Trigger notes: (KO 7-oct-2024)&lt;br /&gt;
* trigger signal is not synched with the v1740 clock, actual &amp;quot;adc stop&amp;quot; time will have a jitter between the two v1740 of 1-2 clock periods&lt;br /&gt;
* actual event time jitter between the two v1740 is around 2 clock (from looking at event timestamps).&lt;br /&gt;
* because v1740 busy are not synced (and busy from first v1740 is missing), the second v1740 often has extra events. sometimes the first v1740 has an extra event. fetactic.exe has workaround against this, mostly by dropping mismatched data.&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/manalyzer. &lt;br /&gt;
* Not source-controlled.&lt;br /&gt;
* Contains many hard-coded thresholds/settings/limits. Also includes a hard-coded mapping between digitizer channel number and hardware sector/pad number.&lt;br /&gt;
* Used for both online and offline analysis of data.&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild fetactic.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/v1740mt&lt;br /&gt;
make&lt;br /&gt;
ls -l fetactic.exe&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/manalyzer&lt;br /&gt;
make&lt;br /&gt;
ls -l ./tacticana.exe&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== New V2745 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 6x CAEN V2745 digitizers, with option for reading 8 digitizers if needed. With 8 digitizers can read all 8 sectors from the hardware.&lt;br /&gt;
&lt;br /&gt;
Digitizers are readout over 1G ethernet, and run DPP_ZLE firmware to reduce the data rate significantly. Future versions of TACTIC may run DPP_PHA or custom firmware to further reduce the data rate.&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:TACTIC wiring V2745.png]]&lt;br /&gt;
&lt;br /&gt;
The trigger is a global OR of every channel of every digitizer (though we can suppress certain channels if desired).&lt;br /&gt;
&lt;br /&gt;
Digitizers are set to NIM logic levels, and OR is done using standard NIM fan-in/fan-out modules. Trigger-OR is sent to 9 locations (8 digitizers + 1 visual scaler) so we use a 16x FI/FO. Busy-OR is only sent to 8 locations, so can use an 8x FI/FO.&lt;br /&gt;
&lt;br /&gt;
Digitizer configuration is done via the [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage. The concept is that the &amp;quot;default&amp;quot; value is applied to all digitizers, unless you specifically override the value for a certain digitizer. This means it&#039;s more efficient to change settings, as you only have to change one &amp;quot;default&amp;quot; parameter rather than 8 separate board-specific parameters. Settings that have been overridden for one or more boards appear with a YELLOW background on the webpage.&lt;br /&gt;
&lt;br /&gt;
==== Settings that users may want to configure ====&lt;br /&gt;
* &#039;&#039;&#039;Readout channel mask&#039;&#039;&#039; - which channels get read out when a trigger is accepted&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A en mask&#039;&#039;&#039; - which channels contribute to the self-trigger logic&lt;br /&gt;
* &#039;&#039;&#039;Chan over thresh thresholds&#039;&#039;&#039; - the thresholds in ADC RELATIVE TO THE BASELINE&lt;br /&gt;
* &#039;&#039;&#039;Scope/ZLE waveform length&#039;&#039;&#039; - how long the waveforms should be.&lt;br /&gt;
* &#039;&#039;&#039;Pre-trigger for ZLE mode&#039;&#039;&#039; - where in the waveform the trigger pulse should appear &lt;br /&gt;
* &#039;&#039;&#039;ZLE threshold (ADC)&#039;&#039;&#039; - how many ADC below baseline a signal must be before it gets read out. Note this is different to the trigger threshold! You could trigger readout if the signal goes 50ADC below baseline, but then read out any data that&#039;s 10ADC below baseline.&lt;br /&gt;
* &#039;&#039;&#039;ZLE look back (samples)&#039;&#039;&#039; - how many samples to read out before the signal went below the ZLE threshold&lt;br /&gt;
* &#039;&#039;&#039;ZLE look forward (samples)&#039;&#039;&#039; - how many samples to read out after the signal goes back above the ZLE threshold&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A gate width(ns)&#039;&#039;&#039; - set this to roughly how long you expect a &amp;quot;real&amp;quot; event to last. If you set it too short then the NIM OR module will output triggers multiple times for a single event (e.g. for the first channel to get hit, and then 100ns later for another channel, and then 300ns after that for another channel, ....). The digitizers would still only read out data for the first trigger, but the visual scaler will show a much higher rate, which would be very confusing for debugging.&lt;br /&gt;
* &#039;&#039;&#039;DC offset (pct)&#039;&#039;&#039; - set the baseline between 0ADC and 65535ADC, as a percentage&lt;br /&gt;
* &#039;&#039;&#039;Signal offset (uV)&#039;&#039;&#039; - extra tweak to the input signal - best set using a script&lt;br /&gt;
* &#039;&#039;&#039;VGA gain&#039;&#039;&#039; - 0-40dB in 0.5dB increments&lt;br /&gt;
&lt;br /&gt;
==== Settings that are different for the first digitizer in the chain ====&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Run start source&#039;&#039;&#039;&lt;br /&gt;
** First board: Start acq on midas run start&lt;br /&gt;
** Other boards: Start acq on encoded CLKIN&lt;br /&gt;
* &#039;&#039;&#039;Use external clock&#039;&#039;&#039;&lt;br /&gt;
** First board: True&lt;br /&gt;
** Other boards: False&lt;br /&gt;
&lt;br /&gt;
==== Settings that user&#039;s shouldn&#039;t touch ====&lt;br /&gt;
* &#039;&#039;&#039;Run start delay (ns)&#039;&#039;&#039; - 0 for the last board, increasing by 48ns for each board in the chain (240, 192, 144, 96, 49, 0).&lt;br /&gt;
* &#039;&#039;&#039;Trigger out mode&#039;&#039;&#039; - ITLA - ensure we output the self-trigger signal&lt;br /&gt;
* &#039;&#039;&#039;Trigger on external signal&#039;&#039;&#039; - True - ensure we only trigger on the global OR that gets fed back in to the board&lt;br /&gt;
* &#039;&#039;&#039;ZLE enable&#039;&#039;&#039; - True for all channels&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A multiplicity&#039;&#039;&#039; - 1 - in principle you could require 2+ hits simultaneously before we trigger (to reduce triggering on noise/bad topology events), but this setting only applies within a single board. So you&#039;ll get weird geometric efficiencies (more likely to trigger on tracks that hit multiple pads in the same sector vs pads in different sectors). If we want to trigger on 2+ hits across multiple boards we can use the DAC or LVDS connectors, and connect them to a board running custom firmware.&lt;br /&gt;
* &#039;&#039;&#039;Chan over thresh rising edge&#039;&#039;&#039; - False - TACTIC uses negative pulses&lt;br /&gt;
* &#039;&#039;&#039;Veto source&#039;&#039;&#039; / &#039;&#039;&#039;Veto when source is high&#039;&#039;&#039; - Disabled / True&lt;br /&gt;
* &#039;&#039;&#039;Use NIM IO&#039;&#039;&#039; - True&lt;br /&gt;
* &#039;&#039;&#039;Enable clock out&#039;&#039;&#039; - True&lt;br /&gt;
* &#039;&#039;&#039;GPIO mode&#039;&#039;&#039; - Busy&lt;br /&gt;
* &#039;&#039;&#039;Busy in source&#039;&#039;&#039; - SIN&lt;br /&gt;
* &#039;&#039;&#039;Sync out mode&#039;&#039;&#039; - Run&lt;br /&gt;
* &#039;&#039;&#039;Enable DC offsets&#039;&#039;&#039; - True&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/tacticana on daq18, and https://bitbucket.org/ttriumfdaq/tacticana/src/master/ on bitbucket.&lt;br /&gt;
* Uses JSON files to define histogram limits, channel mapping etc. See the [https://bitbucket.org/ttriumfdaq/tacticana/src/master/ README.md] file in the repository for details.&lt;br /&gt;
* Specify which config file to use via the --config flag.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Run online using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe --midas-progname tacticana -R8081 -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# Run offline using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe /path/to/something.mid -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# NOTE THE --config FLAG MUST COME AFTER A &#039;--&#039;!!!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Setting baselines ===&lt;br /&gt;
&lt;br /&gt;
The V2745s have two settings related to the baseline of each channel.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;DC offset&#039;&#039;&#039; sets the target of where the baseline &amp;quot;should&amp;quot; be. It&#039;s specified as a percentage of the full scale 0-65535. For TACTIC with negative pulses, it makes sense to set it to 90% or so (aka 58982 ADC).&lt;br /&gt;
* &#039;&#039;&#039;Signal offset&#039;&#039;&#039; is an extra tweak to each channel (in uV) that can be used to ensure a 0V input actually gets to the expected baseline.&lt;br /&gt;
&lt;br /&gt;
ZLE and trigger thresholds are RELATIVE TO THE EXPECTED BASELINE (i.e. 58982 ADC). The digitizers to not monitor the actual data to decide what the &amp;quot;real baseline&amp;quot; is. It is therefore critical that the signal offset is set so that the real baseline matches the expected baseline. &lt;br /&gt;
&lt;br /&gt;
* If the real baseline is lower than expected, you will trigger more often and your data rate will be higher. &lt;br /&gt;
* If the real baseline is higher than expected, you will miss triggering on small pulses, and may miss some ZLE chunks that would otherwise be readout.&lt;br /&gt;
&lt;br /&gt;
Note that baselines often drift based on the temperature of the board.&lt;br /&gt;
&lt;br /&gt;
There is a script in the dsproto_vx2740 repository that can be used to set the &amp;quot;signal offset&amp;quot; of each channel so that the real baseline matches the expected baseline. This script is very basic at the moment, but could be made smarter (both in terms of the algorithm for finding the optimal offset, and in automating more of the settings that need to be changed).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Stop the run&lt;br /&gt;
# Ensure there aren&#039;t any real signals coming in (i.e. we&#039;re just reading noise)&lt;br /&gt;
# Set &#039;ZLE enable&#039; to False for all channels&lt;br /&gt;
# Set &#039;Trigger out mode&#039; to &#039;TestPulse&#039; for the first board, and &#039;Disabled&#039; for all other boards&lt;br /&gt;
&lt;br /&gt;
cd ~/newTACTIC/dsproto_vx2740/&lt;br /&gt;
python set_offsets.py &lt;br /&gt;
&lt;br /&gt;
# Set &#039;ZLE enable&#039; to True for all channels&lt;br /&gt;
# Set &#039;Trigger out mode&#039; to &#039;ITLA&#039; for all boards&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== Adding more digitizers to the chain ===&lt;br /&gt;
&lt;br /&gt;
There are currently 6 digitizers in the chain. 2 more will be delivered soon. To fully add a new digitizer to the chain, do the following steps. You should only connect one &amp;quot;new&amp;quot; board to the ethernet network at a time (as otherwise they will fight over who gets to use the hard-coded default IP address).&lt;br /&gt;
&lt;br /&gt;
* Turn off the VME crate&lt;br /&gt;
* Install the new digitizer in the VME crate&lt;br /&gt;
* Connect digitizer via ethernet cable to the switch&lt;br /&gt;
* Connect CLK-IN of this board to the CLK-OUT of previous board in chain&lt;br /&gt;
* Connect LEMO cables to NIM fan-in/fan-out modules (GPIO, S-IN, TRG-IN, TRG-OUT)&lt;br /&gt;
* Turn on the VME crate&lt;br /&gt;
* On daq18 web browser, navigate to http://192.168.0.254 (this is the default IP address that boards use coming from the factory)&lt;br /&gt;
** On the Firmware page, load the DPP-ZLE firmware&lt;br /&gt;
** On the Network page, set the IP address to 192.168.0.xxx, where xxx isn&#039;t already used (e.g. 7 for the 7th board)&lt;br /&gt;
* On daq18, as root, edit /etc/hosts to assign a hostname (e.g. vx07 for 192.168.0.7)&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=Programs Programs] webpage, stop the VX frontend&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage, change the number of boards (first row of first table)&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=Programs Programs] webpage, start the VX frontend. It will abort immediately, but will have created space in the ODB for you to configure the new board&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage, set the hostname of the new board and adjust the run start delay by 48ns for all the earlier boards in the chain&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=Programs Programs] webpage, start the VX frontend. It should start correctly this time&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild vx2740_group_fe.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/dsproto_vx2740/build&lt;br /&gt;
make install -j&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/tacticana&lt;br /&gt;
make -j&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Known issues ===&lt;br /&gt;
&lt;br /&gt;
==== Rare bug in CAEN software ====&lt;br /&gt;
&lt;br /&gt;
There is a rare bug in the CAEN software/firmware that causes the entire frontend to crash on malformed data. This can be quite annoying, and could cause significant downtime if the user doesn&#039;t realise that the program has crashed and/or the run has stopped.&lt;br /&gt;
&lt;br /&gt;
midas contains a &amp;quot;sequencer&amp;quot; functionality that can be used to mitigate this. Every 10s the sequencer will check to see if the frontend has crashed, and restart it if needed. It will also start a run if the current one has stopped.&lt;br /&gt;
&lt;br /&gt;
To use this sequencer, go to the [https://daq18.triumf.ca/?cmd=Sequencer&amp;amp;SeqODB=/PySequencer PySequencer] page and start the script using the &amp;quot;play&amp;quot; button. You&#039;ll be prompted for how long you want to acquire data for.&lt;br /&gt;
&lt;br /&gt;
Note that if you want to stop data-taking early, you should use the &amp;quot;stop&amp;quot; (square) button on the PySequencer page, not the regular button on the status page for stopping a run (as the sequencer will just detect that the run has stopped and start a new one for you!).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toccolours mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width:800px; overflow:auto;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-weight:bold;line-height:1.6;&amp;quot;&amp;gt;Click &#039;Expand&#039; to view the actual sequencer script I implemented ----&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import datetime&lt;br /&gt;
import midas&lt;br /&gt;
&lt;br /&gt;
def define_params(seq):&lt;br /&gt;
    seq.register_param(&amp;quot;duration_hours&amp;quot;, &amp;quot;Total acquisition time&amp;quot;, 5.0)&lt;br /&gt;
&lt;br /&gt;
def sequence(seq):&lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
    start_time = datetime.datetime.now()&lt;br /&gt;
    elapsed_hours = 0.0&lt;br /&gt;
        &lt;br /&gt;
    while elapsed_hours &amp;lt; seq.get_param(&amp;quot;duration_hours&amp;quot;):&lt;br /&gt;
        validate_prog_running(seq)&lt;br /&gt;
        seq.wait_seconds(10)&lt;br /&gt;
        elapsed_hours = round((datetime.datetime.now() - start_time).total_seconds() / 3600, 2)&lt;br /&gt;
        &lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
        &lt;br /&gt;
def at_exit(seq):&lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
    &lt;br /&gt;
def stop_run_if_needed(seq):&lt;br /&gt;
    if seq.odb_get(&amp;quot;/Runinfo/State&amp;quot;) != midas.STATE_STOPPED:&lt;br /&gt;
        seq.stop_run()&lt;br /&gt;
    &lt;br /&gt;
def validate_prog_running(seq):&lt;br /&gt;
    prog_name = &amp;quot;VX2740_Group_01&amp;quot;&lt;br /&gt;
    if not seq.client_exists(prog_name):&lt;br /&gt;
        stop_run_if_needed(seq)&lt;br /&gt;
        seq.msg(f&amp;quot;Stopped run as {prog_name} was not running! Restarting program.&amp;quot;)&lt;br /&gt;
        seq.wait_seconds(5)&lt;br /&gt;
        seq.start_client(prog_name)&lt;br /&gt;
        seq.wait_clients_running(prog_name)&lt;br /&gt;
        &lt;br /&gt;
        if not seq.client_exists(prog_name):&lt;br /&gt;
            raise RuntimeError(f&amp;quot;Failed to restart {prog_name} - abort sequence!&amp;quot;)&lt;br /&gt;
            &lt;br /&gt;
        seq.wait_odb(&amp;quot;/Equipment/VX2740_Data_Group_001/Common/Status&amp;quot;, &amp;quot;==&amp;quot;, &amp;quot;Initialized&amp;quot;)&lt;br /&gt;
        &lt;br /&gt;
    if seq.odb_get(&amp;quot;/Runinfo/State&amp;quot;) != midas.STATE_RUNNING:&lt;br /&gt;
        seq.start_run()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8589</id>
		<title>TACTIC</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8589"/>
		<updated>2025-09-17T21:55:29Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= TACTIC =&lt;br /&gt;
&lt;br /&gt;
* computer: daq18.triumf.ca&lt;br /&gt;
* midas: https://daq18.triumf.ca&lt;br /&gt;
* elog: https://elog.triumf.ca/Tactic/General/ (has a &amp;quot;tactic&amp;quot; user account)&lt;br /&gt;
&lt;br /&gt;
== Old V1740 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 2x V1740 via CAEN USB interface. 64 channels each - can read out 2 of the 8 TACTIC &amp;quot;sectors&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
These [https://daq18.triumf.ca/?cmd=Programs programs] should be running:&lt;br /&gt;
* mhttpd (web server)&lt;br /&gt;
* Logger (writing data to disk)&lt;br /&gt;
* feMKS (gas mixer)&lt;br /&gt;
* fetactic (data readout from digitizers)&lt;br /&gt;
* ana (online analysis of data)&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:Tactic-v1740-trigger.jpg]]&lt;br /&gt;
&lt;br /&gt;
Trigger and v1740 connections:&lt;br /&gt;
* both v1740 trigger outputs go to logic OR. pulser goes into the same OR&lt;br /&gt;
* from this OR, they fan out to v1740 trigger inputs&lt;br /&gt;
* analog output of first v1740 provides the run gate (via polarity inverting kludge)&lt;br /&gt;
* analog output of second v1740 provides a &amp;quot;buffer-half-full&amp;quot; trigger veto (via polarity inverting kludge)&lt;br /&gt;
&lt;br /&gt;
Trigger notes: (KO 7-oct-2024)&lt;br /&gt;
* trigger signal is not synched with the v1740 clock, actual &amp;quot;adc stop&amp;quot; time will have a jitter between the two v1740 of 1-2 clock periods&lt;br /&gt;
* actual event time jitter between the two v1740 is around 2 clock (from looking at event timestamps).&lt;br /&gt;
* because v1740 busy are not synced (and busy from first v1740 is missing), the second v1740 often has extra events. sometimes the first v1740 has an extra event. fetactic.exe has workaround against this, mostly by dropping mismatched data.&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/manalyzer. &lt;br /&gt;
* Not source-controlled.&lt;br /&gt;
* Contains many hard-coded thresholds/settings/limits. Also includes a hard-coded mapping between digitizer channel number and hardware sector/pad number.&lt;br /&gt;
* Used for both online and offline analysis of data.&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild fetactic.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/v1740mt&lt;br /&gt;
make&lt;br /&gt;
ls -l fetactic.exe&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/manalyzer&lt;br /&gt;
make&lt;br /&gt;
ls -l ./tacticana.exe&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== New V2745 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 6x CAEN V2745 digitizers, with option for reading 8 digitizers if needed. With 8 digitizers can read all 8 sectors from the hardware.&lt;br /&gt;
&lt;br /&gt;
Digitizers are readout over 1G ethernet, and run DPP_ZLE firmware to reduce the data rate significantly. Future versions of TACTIC may run DPP_PHA or custom firmware to further reduce the data rate.&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:TACTIC wiring V2745.png]]&lt;br /&gt;
&lt;br /&gt;
The trigger is a global OR of every channel of every digitizer (though we can suppress certain channels if desired).&lt;br /&gt;
&lt;br /&gt;
Digitizers are set to NIM logic levels, and OR is done using standard NIM fan-in/fan-out modules. Trigger-OR is sent to 9 locations (8 digitizers + 1 visual scaler) so we use a 16x FI/FO. Busy-OR is only sent to 8 locations, so can use an 8x FI/FO.&lt;br /&gt;
&lt;br /&gt;
Digitizer configuration is done via the [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage. The concept is that the &amp;quot;default&amp;quot; value is applied to all digitizers, unless you specifically override the value for a certain digitizer. This means it&#039;s more efficient to change settings, as you only have to change one &amp;quot;default&amp;quot; parameter rather than 8 separate board-specific parameters. Settings that have been overridden for one or more boards appear with a YELLOW background on the webpage.&lt;br /&gt;
&lt;br /&gt;
==== Settings that users may want to configure ====&lt;br /&gt;
* &#039;&#039;&#039;Readout channel mask&#039;&#039;&#039; - which channels get read out when a trigger is accepted&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A en mask&#039;&#039;&#039; - which channels contribute to the self-trigger logic&lt;br /&gt;
* &#039;&#039;&#039;Chan over thresh thresholds&#039;&#039;&#039; - the thresholds in ADC RELATIVE TO THE BASELINE&lt;br /&gt;
* &#039;&#039;&#039;Scope/ZLE waveform length&#039;&#039;&#039; - how long the waveforms should be.&lt;br /&gt;
* &#039;&#039;&#039;Pre-trigger for ZLE mode&#039;&#039;&#039; - where in the waveform the trigger pulse should appear &lt;br /&gt;
* &#039;&#039;&#039;ZLE threshold (ADC)&#039;&#039;&#039; - how many ADC below baseline a signal must be before it gets read out. Note this is different to the trigger threshold! You could trigger readout if the signal goes 50ADC below baseline, but then read out any data that&#039;s 10ADC below baseline.&lt;br /&gt;
* &#039;&#039;&#039;ZLE look back (samples)&#039;&#039;&#039; - how many samples to read out before the signal went below the ZLE threshold&lt;br /&gt;
* &#039;&#039;&#039;ZLE look forward (samples)&#039;&#039;&#039; - how many samples to read out after the signal goes back above the ZLE threshold&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A gate width(ns)&#039;&#039;&#039; - set this to roughly how long you expect a &amp;quot;real&amp;quot; event to last. If you set it too short then the NIM OR module will output triggers multiple times for a single event (e.g. for the first channel to get hit, and then 100ns later for another channel, and then 300ns after that for another channel, ....). The digitizers would still only read out data for the first trigger, but the visual scaler will show a much higher rate, which would be very confusing for debugging.&lt;br /&gt;
* &#039;&#039;&#039;DC offset (pct)&#039;&#039;&#039; - set the baseline between 0ADC and 65535ADC, as a percentage&lt;br /&gt;
* &#039;&#039;&#039;Signal offset (uV)&#039;&#039;&#039; - extra tweak to the input signal - best set using a script&lt;br /&gt;
* &#039;&#039;&#039;VGA gain&#039;&#039;&#039; - 0-40dB in 0.5dB increments&lt;br /&gt;
&lt;br /&gt;
==== Settings that are different for the first digitizer in the chain ====&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Run start source&#039;&#039;&#039;&lt;br /&gt;
** First board: Start acq on midas run start&lt;br /&gt;
** Other boards: Start acq on encoded CLKIN&lt;br /&gt;
* &#039;&#039;&#039;Use external clock&#039;&#039;&#039;&lt;br /&gt;
** First board: True&lt;br /&gt;
** Other boards: False&lt;br /&gt;
&lt;br /&gt;
==== Settings that user&#039;s shouldn&#039;t touch ====&lt;br /&gt;
* &#039;&#039;&#039;Run start delay (ns)&#039;&#039;&#039; - 0 for the last board, increasing by 48ns for each board in the chain (240, 192, 144, 96, 49, 0).&lt;br /&gt;
* &#039;&#039;&#039;Trigger out mode&#039;&#039;&#039; - ITLA - ensure we output the self-trigger signal&lt;br /&gt;
* &#039;&#039;&#039;Trigger on external signal&#039;&#039;&#039; - True - ensure we only trigger on the global OR that gets fed back in to the board&lt;br /&gt;
* &#039;&#039;&#039;ZLE enable&#039;&#039;&#039; - True for all channels&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A multiplicity&#039;&#039;&#039; - 1 - in principle you could require 2+ hits simultaneously before we trigger (to reduce triggering on noise/bad topology events), but this setting only applies within a single board. So you&#039;ll get weird geometric efficiencies (more likely to trigger on tracks that hit multiple pads in the same sector vs pads in different sectors). If we want to trigger on 2+ hits across multiple boards we can use the DAC or LVDS connectors, and connect them to a board running custom firmware.&lt;br /&gt;
* &#039;&#039;&#039;Chan over thresh rising edge&#039;&#039;&#039; - False - TACTIC uses negative pulses&lt;br /&gt;
* &#039;&#039;&#039;Veto source&#039;&#039;&#039; / &#039;&#039;&#039;Veto when source is high&#039;&#039;&#039; - Disabled / True&lt;br /&gt;
* &#039;&#039;&#039;Use NIM IO&#039;&#039;&#039; - True&lt;br /&gt;
* &#039;&#039;&#039;Enable clock out&#039;&#039;&#039; - True&lt;br /&gt;
* &#039;&#039;&#039;GPIO mode&#039;&#039;&#039; - Busy&lt;br /&gt;
* &#039;&#039;&#039;Busy in source&#039;&#039;&#039; - SIN&lt;br /&gt;
* &#039;&#039;&#039;Sync out mode&#039;&#039;&#039; - Run&lt;br /&gt;
* &#039;&#039;&#039;Enable DC offsets&#039;&#039;&#039; - True&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/tacticana on daq18, and https://bitbucket.org/ttriumfdaq/tacticana/src/master/ on bitbucket.&lt;br /&gt;
* Uses JSON files to define histogram limits, channel mapping etc. See the [https://bitbucket.org/ttriumfdaq/tacticana/src/master/ README.md] file in the repository for details.&lt;br /&gt;
* Specify which config file to use via the --config flag.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Run online using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe --midas-progname tacticana -R8081 -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# Run offline using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe /path/to/something.mid -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# NOTE THE --config FLAG MUST COME AFTER A &#039;--&#039;!!!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Setting baselines ===&lt;br /&gt;
&lt;br /&gt;
The V2745s have two settings related to the baseline of each channel.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;DC offset&#039;&#039;&#039; sets the target of where the baseline &amp;quot;should&amp;quot; be. It&#039;s specified as a percentage of the full scale 0-65535. For TACTIC with negative pulses, it makes sense to set it to 90% or so (aka 58982 ADC).&lt;br /&gt;
* &#039;&#039;&#039;Signal offset&#039;&#039;&#039; is an extra tweak to each channel (in uV) that can be used to ensure a 0V input actually gets to the expected baseline.&lt;br /&gt;
&lt;br /&gt;
ZLE and trigger thresholds are RELATIVE TO THE EXPECTED BASELINE (i.e. 58982 ADC). The digitizers to not monitor the actual data to decide what the &amp;quot;real baseline&amp;quot; is. It is therefore critical that the signal offset is set so that the real baseline matches the expected baseline. &lt;br /&gt;
&lt;br /&gt;
* If the real baseline is lower than expected, you will trigger more often and your data rate will be higher. &lt;br /&gt;
* If the real baseline is higher than expected, you will miss triggering on small pulses, and may miss some ZLE chunks that would otherwise be readout.&lt;br /&gt;
&lt;br /&gt;
Note that baselines often drift based on the temperature of the board.&lt;br /&gt;
&lt;br /&gt;
There is a script in the dsproto_vx2740 repository that can be used to set the &amp;quot;signal offset&amp;quot; of each channel so that the real baseline matches the expected baseline. This script is very basic at the moment, but could be made smarter (both in terms of the algorithm for finding the optimal offset, and in automating more of the settings that need to be changed).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Stop the run&lt;br /&gt;
# Ensure there aren&#039;t any real signals coming in (i.e. we&#039;re just reading noise)&lt;br /&gt;
# Set &#039;ZLE enable&#039; to False for all channels&lt;br /&gt;
# Set &#039;Trigger out mode&#039; to &#039;TestPulse&#039; for the first board, and &#039;Disabled&#039; for all other boards&lt;br /&gt;
&lt;br /&gt;
cd ~/newTACTIC/dsproto_vx2740/&lt;br /&gt;
python set_offsets.py &lt;br /&gt;
&lt;br /&gt;
# Set &#039;ZLE enable&#039; to True for all channels&lt;br /&gt;
# Set &#039;Trigger out mode&#039; to &#039;ITLA&#039; for all boards&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== Rare bug in CAEN software ===&lt;br /&gt;
&lt;br /&gt;
There is a rare bug in the CAEN software/firmware that causes the entire frontend to crash on malformed data. This can be quite annoying, and could cause significant downtime if the user doesn&#039;t realise that the program has crashed and/or the run has stopped.&lt;br /&gt;
&lt;br /&gt;
midas contains a &amp;quot;sequencer&amp;quot; functionality that can be used to mitigate this. Every 10s the sequencer will check to see if the frontend has crashed, and restart it if needed. It will also start a run if the current one has stopped.&lt;br /&gt;
&lt;br /&gt;
To use this sequencer, go to the [https://daq18.triumf.ca/?cmd=Sequencer&amp;amp;SeqODB=/PySequencer PySequencer] page and start the script using the &amp;quot;play&amp;quot; button. You&#039;ll be prompted for how long you want to acquire data for.&lt;br /&gt;
&lt;br /&gt;
Note that if you want to stop data-taking early, you should use the &amp;quot;stop&amp;quot; (square) button on the PySequencer page, not the regular button on the status page for stopping a run (as the sequencer will just detect that the run has stopped and start a new one for you!).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toccolours mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width:800px; overflow:auto;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-weight:bold;line-height:1.6;&amp;quot;&amp;gt;Click &#039;Expand&#039; to view the actual sequencer script I implemented ----&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import datetime&lt;br /&gt;
import midas&lt;br /&gt;
&lt;br /&gt;
def define_params(seq):&lt;br /&gt;
    seq.register_param(&amp;quot;duration_hours&amp;quot;, &amp;quot;Total acquisition time&amp;quot;, 5.0)&lt;br /&gt;
&lt;br /&gt;
def sequence(seq):&lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
    start_time = datetime.datetime.now()&lt;br /&gt;
    elapsed_hours = 0.0&lt;br /&gt;
        &lt;br /&gt;
    while elapsed_hours &amp;lt; seq.get_param(&amp;quot;duration_hours&amp;quot;):&lt;br /&gt;
        validate_prog_running(seq)&lt;br /&gt;
        seq.wait_seconds(10)&lt;br /&gt;
        elapsed_hours = round((datetime.datetime.now() - start_time).total_seconds() / 3600, 2)&lt;br /&gt;
        &lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
        &lt;br /&gt;
def at_exit(seq):&lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
    &lt;br /&gt;
def stop_run_if_needed(seq):&lt;br /&gt;
    if seq.odb_get(&amp;quot;/Runinfo/State&amp;quot;) != midas.STATE_STOPPED:&lt;br /&gt;
        seq.stop_run()&lt;br /&gt;
    &lt;br /&gt;
def validate_prog_running(seq):&lt;br /&gt;
    prog_name = &amp;quot;VX2740_Group_01&amp;quot;&lt;br /&gt;
    if not seq.client_exists(prog_name):&lt;br /&gt;
        stop_run_if_needed(seq)&lt;br /&gt;
        seq.msg(f&amp;quot;Stopped run as {prog_name} was not running! Restarting program.&amp;quot;)&lt;br /&gt;
        seq.wait_seconds(5)&lt;br /&gt;
        seq.start_client(prog_name)&lt;br /&gt;
        seq.wait_clients_running(prog_name)&lt;br /&gt;
        &lt;br /&gt;
        if not seq.client_exists(prog_name):&lt;br /&gt;
            raise RuntimeError(f&amp;quot;Failed to restart {prog_name} - abort sequence!&amp;quot;)&lt;br /&gt;
            &lt;br /&gt;
        seq.wait_odb(&amp;quot;/Equipment/VX2740_Data_Group_001/Common/Status&amp;quot;, &amp;quot;==&amp;quot;, &amp;quot;Initialized&amp;quot;)&lt;br /&gt;
        &lt;br /&gt;
    if seq.odb_get(&amp;quot;/Runinfo/State&amp;quot;) != midas.STATE_RUNNING:&lt;br /&gt;
        seq.start_run()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding more digitizers to the chain ===&lt;br /&gt;
&lt;br /&gt;
There are currently 6 digitizers in the chain. 2 more will be delivered soon. To fully add a new digitizer to the chain, do the following steps. You should only connect one &amp;quot;new&amp;quot; board to the ethernet network at a time (as otherwise they will fight over who gets to use the hard-coded default IP address).&lt;br /&gt;
&lt;br /&gt;
* Turn off the VME crate&lt;br /&gt;
* Install the new digitizer in the VME crate&lt;br /&gt;
* Connect digitizer via ethernet cable to the switch&lt;br /&gt;
* Connect CLK-IN of this board to the CLK-OUT of previous board in chain&lt;br /&gt;
* Connect LEMO cables to NIM fan-in/fan-out modules (GPIO, S-IN, TRG-IN, TRG-OUT)&lt;br /&gt;
* Turn on the VME crate&lt;br /&gt;
* On daq18 web browser, navigate to http://192.168.0.254 (this is the default IP address that boards use coming from the factory)&lt;br /&gt;
** On the Firmware page, load the DPP-ZLE firmware&lt;br /&gt;
** On the Network page, set the IP address to 192.168.0.xxx, where xxx isn&#039;t already used (e.g. 7 for the 7th board)&lt;br /&gt;
* On daq18, as root, edit /etc/hosts to assign a hostname (e.g. vx07 for 192.168.0.7)&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=Programs Programs] webpage, stop the VX frontend&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage, change the number of boards (first row of first table)&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=Programs Programs] webpage, start the VX frontend. It will abort immediately, but will have created space in the ODB for you to configure the new board&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage, set the hostname of the new board and adjust the run start delay by 48ns for all the earlier boards in the chain&lt;br /&gt;
* On the midas [https://daq18.triumf.ca/?cmd=Programs Programs] webpage, start the VX frontend. It should start correctly this time&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild vx2740_group_fe.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/dsproto_vx2740/build&lt;br /&gt;
make install -j&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/tacticana&lt;br /&gt;
make -j&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8588</id>
		<title>TACTIC</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8588"/>
		<updated>2025-09-17T21:12:01Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= TACTIC =&lt;br /&gt;
&lt;br /&gt;
* computer: daq18.triumf.ca&lt;br /&gt;
* midas: https://daq18.triumf.ca&lt;br /&gt;
* elog: https://elog.triumf.ca/Tactic/General/ (has a &amp;quot;tactic&amp;quot; user account)&lt;br /&gt;
&lt;br /&gt;
== Old V1740 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 2x V1740 via CAEN USB interface. 64 channels each - can read out 2 of the 8 TACTIC &amp;quot;sectors&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
These [https://daq18.triumf.ca/?cmd=Programs programs] should be running:&lt;br /&gt;
* mhttpd (web server)&lt;br /&gt;
* Logger (writing data to disk)&lt;br /&gt;
* feMKS (gas mixer)&lt;br /&gt;
* fetactic (data readout from digitizers)&lt;br /&gt;
* ana (online analysis of data)&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:Tactic-v1740-trigger.jpg]]&lt;br /&gt;
&lt;br /&gt;
Trigger and v1740 connections:&lt;br /&gt;
* both v1740 trigger outputs go to logic OR. pulser goes into the same OR&lt;br /&gt;
* from this OR, they fan out to v1740 trigger inputs&lt;br /&gt;
* analog output of first v1740 provides the run gate (via polarity inverting kludge)&lt;br /&gt;
* analog output of second v1740 provides a &amp;quot;buffer-half-full&amp;quot; trigger veto (via polarity inverting kludge)&lt;br /&gt;
&lt;br /&gt;
Trigger notes: (KO 7-oct-2024)&lt;br /&gt;
* trigger signal is not synched with the v1740 clock, actual &amp;quot;adc stop&amp;quot; time will have a jitter between the two v1740 of 1-2 clock periods&lt;br /&gt;
* actual event time jitter between the two v1740 is around 2 clock (from looking at event timestamps).&lt;br /&gt;
* because v1740 busy are not synced (and busy from first v1740 is missing), the second v1740 often has extra events. sometimes the first v1740 has an extra event. fetactic.exe has workaround against this, mostly by dropping mismatched data.&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/manalyzer. &lt;br /&gt;
* Not source-controlled.&lt;br /&gt;
* Contains many hard-coded thresholds/settings/limits. Also includes a hard-coded mapping between digitizer channel number and hardware sector/pad number.&lt;br /&gt;
* Used for both online and offline analysis of data.&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild fetactic.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/v1740mt&lt;br /&gt;
make&lt;br /&gt;
ls -l fetactic.exe&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/manalyzer&lt;br /&gt;
make&lt;br /&gt;
ls -l ./tacticana.exe&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== New V2745 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 6x CAEN V2745 digitizers, with option for reading 8 digitizers if needed. With 8 digitizers can read all 8 sectors from the hardware.&lt;br /&gt;
&lt;br /&gt;
Digitizers are readout over 1G ethernet, and run DPP_ZLE firmware to reduce the data rate significantly. Future versions of TACTIC may run DPP_PHA or custom firmware to further reduce the data rate.&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:TACTIC wiring V2745.png]]&lt;br /&gt;
&lt;br /&gt;
The trigger is a global OR of every channel of every digitizer (though we can suppress certain channels if desired).&lt;br /&gt;
&lt;br /&gt;
Digitizers are set to NIM logic levels, and OR is done using standard NIM fan-in/fan-out modules. Trigger-OR is sent to 9 locations (8 digitizers + 1 visual scaler) so we use a 16x FI/FO. Busy-OR is only sent to 8 locations, so can use an 8x FI/FO.&lt;br /&gt;
&lt;br /&gt;
Digitizer configuration is done via the [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage. The concept is that the &amp;quot;default&amp;quot; value is applied to all digitizers, unless you specifically override the value for a certain digitizer. This means it&#039;s more efficient to change settings, as you only have to change one &amp;quot;default&amp;quot; parameter rather than 8 separate board-specific parameters. Settings that have been overridden for one or more boards appear with a YELLOW background on the webpage.&lt;br /&gt;
&lt;br /&gt;
==== Settings that users may want to configure ====&lt;br /&gt;
* &#039;&#039;&#039;Readout channel mask&#039;&#039;&#039; - which channels get read out when a trigger is accepted&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A en mask&#039;&#039;&#039; - which channels contribute to the self-trigger logic&lt;br /&gt;
* &#039;&#039;&#039;Chan over thresh thresholds&#039;&#039;&#039; - the thresholds in ADC RELATIVE TO THE BASELINE&lt;br /&gt;
* &#039;&#039;&#039;Scope/ZLE waveform length&#039;&#039;&#039; - how long the waveforms should be.&lt;br /&gt;
* &#039;&#039;&#039;Pre-trigger for ZLE mode&#039;&#039;&#039; - where in the waveform the trigger pulse should appear &lt;br /&gt;
* &#039;&#039;&#039;ZLE threshold (ADC)&#039;&#039;&#039; - how many ADC below baseline a signal must be before it gets read out. Note this is different to the trigger threshold! You could trigger readout if the signal goes 50ADC below baseline, but then read out any data that&#039;s 10ADC below baseline.&lt;br /&gt;
* &#039;&#039;&#039;ZLE look back (samples)&#039;&#039;&#039; - how many samples to read out before the signal went below the ZLE threshold&lt;br /&gt;
* &#039;&#039;&#039;ZLE look forward (samples)&#039;&#039;&#039; - how many samples to read out after the signal goes back above the ZLE threshold&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A gate width(ns)&#039;&#039;&#039; - set this to roughly how long you expect a &amp;quot;real&amp;quot; event to last. If you set it too short then the NIM OR module will output triggers multiple times for a single event (e.g. for the first channel to get hit, and then 100ns later for another channel, and then 300ns after that for another channel, ....). The digitizers would still only read out data for the first trigger, but the visual scaler will show a much higher rate, which would be very confusing for debugging.&lt;br /&gt;
* &#039;&#039;&#039;DC offset (pct)&#039;&#039;&#039; - set the baseline between 0ADC and 65535ADC, as a percentage&lt;br /&gt;
* &#039;&#039;&#039;Signal offset (uV)&#039;&#039;&#039; - extra tweak to the input signal - best set using a script&lt;br /&gt;
* &#039;&#039;&#039;VGA gain&#039;&#039;&#039; - 0-40dB in 0.5dB increments&lt;br /&gt;
&lt;br /&gt;
==== Settings that are different for the first digitizer in the chain ====&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Run start source&#039;&#039;&#039;&lt;br /&gt;
** First board: Start acq on midas run start&lt;br /&gt;
** Other boards: Start acq on encoded CLKIN&lt;br /&gt;
* &#039;&#039;&#039;Use external clock&#039;&#039;&#039;&lt;br /&gt;
** First board: True&lt;br /&gt;
** Other boards: False&lt;br /&gt;
&lt;br /&gt;
==== Settings that user&#039;s shouldn&#039;t touch ====&lt;br /&gt;
* &#039;&#039;&#039;Run start delay (ns)&#039;&#039;&#039; - 0 for the last board, increasing by 48ns for each board in the chain (240, 192, 144, 96, 49, 0).&lt;br /&gt;
* &#039;&#039;&#039;Trigger out mode&#039;&#039;&#039; - ITLA - ensure we output the self-trigger signal&lt;br /&gt;
* &#039;&#039;&#039;Trigger on external signal&#039;&#039;&#039; - True - ensure we only trigger on the global OR that gets fed back in to the board&lt;br /&gt;
* &#039;&#039;&#039;ZLE enable&#039;&#039;&#039; - True for all channels&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A multiplicity&#039;&#039;&#039; - 1 - in principle you could require 2+ hits simultaneously before we trigger (to reduce triggering on noise/bad topology events), but this setting only applies within a single board. So you&#039;ll get weird geometric efficiencies (more likely to trigger on tracks that hit multiple pads in the same sector vs pads in different sectors). If we want to trigger on 2+ hits across multiple boards we can use the DAC or LVDS connectors, and connect them to a board running custom firmware.&lt;br /&gt;
* &#039;&#039;&#039;Chan over thresh rising edge&#039;&#039;&#039; - False - TACTIC uses negative pulses&lt;br /&gt;
* &#039;&#039;&#039;Veto source&#039;&#039;&#039; / &#039;&#039;&#039;Veto when source is high&#039;&#039;&#039; - Disabled / True&lt;br /&gt;
* &#039;&#039;&#039;Use NIM IO&#039;&#039;&#039; - True&lt;br /&gt;
* &#039;&#039;&#039;Enable clock out&#039;&#039;&#039; - True&lt;br /&gt;
* &#039;&#039;&#039;GPIO mode&#039;&#039;&#039; - Busy&lt;br /&gt;
* &#039;&#039;&#039;Busy in source&#039;&#039;&#039; - SIN&lt;br /&gt;
* &#039;&#039;&#039;Sync out mode&#039;&#039;&#039; - Run&lt;br /&gt;
* &#039;&#039;&#039;Enable DC offsets&#039;&#039;&#039; - True&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/tacticana on daq18, and https://bitbucket.org/ttriumfdaq/tacticana/src/master/ on bitbucket.&lt;br /&gt;
* Uses JSON files to define histogram limits, channel mapping etc. See the [https://bitbucket.org/ttriumfdaq/tacticana/src/master/ README.md] file in the repository for details.&lt;br /&gt;
* Specify which config file to use via the --config flag.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Run online using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe --midas-progname tacticana -R8081 -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# Run offline using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe /path/to/something.mid -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# NOTE THE --config FLAG MUST COME AFTER A &#039;--&#039;!!!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Setting baselines ===&lt;br /&gt;
&lt;br /&gt;
The V2745s have two settings related to the baseline of each channel.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;DC offset&#039;&#039;&#039; sets the target of where the baseline &amp;quot;should&amp;quot; be. It&#039;s specified as a percentage of the full scale 0-65535. For TACTIC with negative pulses, it makes sense to set it to 90% or so (aka 58982 ADC).&lt;br /&gt;
* &#039;&#039;&#039;Signal offset&#039;&#039;&#039; is an extra tweak to each channel (in uV) that can be used to ensure a 0V input actually gets to the expected baseline.&lt;br /&gt;
&lt;br /&gt;
ZLE and trigger thresholds are RELATIVE TO THE EXPECTED BASELINE (i.e. 58982 ADC). The digitizers to not monitor the actual data to decide what the &amp;quot;real baseline&amp;quot; is. It is therefore critical that the signal offset is set so that the real baseline matches the expected baseline. &lt;br /&gt;
&lt;br /&gt;
* If the real baseline is lower than expected, you will trigger more often and your data rate will be higher. &lt;br /&gt;
* If the real baseline is higher than expected, you will miss triggering on small pulses, and may miss some ZLE chunks that would otherwise be readout.&lt;br /&gt;
&lt;br /&gt;
Note that baselines often drift based on the temperature of the board.&lt;br /&gt;
&lt;br /&gt;
There is a script in the dsproto_vx2740 repository that can be used to set the &amp;quot;signal offset&amp;quot; of each channel so that the real baseline matches the expected baseline. This script is very basic at the moment, but could be made smarter (both in terms of the algorithm for finding the optimal offset, and in automating more of the settings that need to be changed).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Stop the run&lt;br /&gt;
# Ensure there aren&#039;t any real signals coming in (i.e. we&#039;re just reading noise)&lt;br /&gt;
# Set &#039;ZLE enable&#039; to False for all channels&lt;br /&gt;
# Set &#039;Trigger out mode&#039; to &#039;TestPulse&#039; for the first board, and &#039;Disabled&#039; for all other boards&lt;br /&gt;
&lt;br /&gt;
cd ~/newTACTIC/dsproto_vx2740/&lt;br /&gt;
python set_offsets.py &lt;br /&gt;
&lt;br /&gt;
# Set &#039;ZLE enable&#039; to True for all channels&lt;br /&gt;
# Set &#039;Trigger out mode&#039; to &#039;ITLA&#039; for all boards&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== Rare bug in CAEN software ===&lt;br /&gt;
&lt;br /&gt;
There is a rare bug in the CAEN software/firmware that causes the entire frontend to crash on malformed data. This can be quite annoying, and could cause significant downtime if the user doesn&#039;t realise that the program has crashed and/or the run has stopped.&lt;br /&gt;
&lt;br /&gt;
midas contains a &amp;quot;sequencer&amp;quot; functionality that can be used to mitigate this. Every 10s the sequencer will check to see if the frontend has crashed, and restart it if needed. It will also start a run if the current one has stopped.&lt;br /&gt;
&lt;br /&gt;
To use this sequencer, go to the [https://daq18.triumf.ca/?cmd=Sequencer&amp;amp;SeqODB=/PySequencer PySequencer] page and start the script using the &amp;quot;play&amp;quot; button. You&#039;ll be prompted for how long you want to acquire data for.&lt;br /&gt;
&lt;br /&gt;
Note that if you want to stop data-taking early, you should use the &amp;quot;stop&amp;quot; (square) button on the PySequencer page, not the regular button on the status page for stopping a run (as the sequencer will just detect that the run has stopped and start a new one for you!).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toccolours mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width:800px; overflow:auto;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-weight:bold;line-height:1.6;&amp;quot;&amp;gt;Click &#039;Expand&#039; to view the actual sequencer script I implemented ----&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import datetime&lt;br /&gt;
import midas&lt;br /&gt;
&lt;br /&gt;
def define_params(seq):&lt;br /&gt;
    seq.register_param(&amp;quot;duration_hours&amp;quot;, &amp;quot;Total acquisition time&amp;quot;, 5.0)&lt;br /&gt;
&lt;br /&gt;
def sequence(seq):&lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
    start_time = datetime.datetime.now()&lt;br /&gt;
    elapsed_hours = 0.0&lt;br /&gt;
        &lt;br /&gt;
    while elapsed_hours &amp;lt; seq.get_param(&amp;quot;duration_hours&amp;quot;):&lt;br /&gt;
        validate_prog_running(seq)&lt;br /&gt;
        seq.wait_seconds(10)&lt;br /&gt;
        elapsed_hours = round((datetime.datetime.now() - start_time).total_seconds() / 3600, 2)&lt;br /&gt;
        &lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
        &lt;br /&gt;
def at_exit(seq):&lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
    &lt;br /&gt;
def stop_run_if_needed(seq):&lt;br /&gt;
    if seq.odb_get(&amp;quot;/Runinfo/State&amp;quot;) != midas.STATE_STOPPED:&lt;br /&gt;
        seq.stop_run()&lt;br /&gt;
    &lt;br /&gt;
def validate_prog_running(seq):&lt;br /&gt;
    prog_name = &amp;quot;VX2740_Group_01&amp;quot;&lt;br /&gt;
    if not seq.client_exists(prog_name):&lt;br /&gt;
        stop_run_if_needed(seq)&lt;br /&gt;
        seq.msg(f&amp;quot;Stopped run as {prog_name} was not running! Restarting program.&amp;quot;)&lt;br /&gt;
        seq.wait_seconds(5)&lt;br /&gt;
        seq.start_client(prog_name)&lt;br /&gt;
        seq.wait_clients_running(prog_name)&lt;br /&gt;
        &lt;br /&gt;
        if not seq.client_exists(prog_name):&lt;br /&gt;
            raise RuntimeError(f&amp;quot;Failed to restart {prog_name} - abort sequence!&amp;quot;)&lt;br /&gt;
            &lt;br /&gt;
        seq.wait_odb(&amp;quot;/Equipment/VX2740_Data_Group_001/Common/Status&amp;quot;, &amp;quot;==&amp;quot;, &amp;quot;Initialized&amp;quot;)&lt;br /&gt;
        &lt;br /&gt;
    if seq.odb_get(&amp;quot;/Runinfo/State&amp;quot;) != midas.STATE_RUNNING:&lt;br /&gt;
        seq.start_run()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild vx2740_group_fe.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/dsproto_vx2740/build&lt;br /&gt;
make install -j&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/tacticana&lt;br /&gt;
make -j&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8587</id>
		<title>TACTIC</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8587"/>
		<updated>2025-09-17T20:50:16Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= TACTIC =&lt;br /&gt;
&lt;br /&gt;
* computer: daq18.triumf.ca&lt;br /&gt;
* midas: https://daq18.triumf.ca&lt;br /&gt;
* elog: https://elog.triumf.ca/Tactic/General/ (has a &amp;quot;tactic&amp;quot; user account)&lt;br /&gt;
&lt;br /&gt;
== Old V1740 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 2x V1740 via CAEN USB interface. 64 channels each - can read out 2 of the 8 TACTIC &amp;quot;sectors&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
These [https://daq18.triumf.ca/?cmd=Programs programs] should be running:&lt;br /&gt;
* mhttpd (web server)&lt;br /&gt;
* Logger (writing data to disk)&lt;br /&gt;
* feMKS (gas mixer)&lt;br /&gt;
* fetactic (data readout from digitizers)&lt;br /&gt;
* ana (online analysis of data)&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:Tactic-v1740-trigger.jpg]]&lt;br /&gt;
&lt;br /&gt;
Trigger and v1740 connections:&lt;br /&gt;
* both v1740 trigger outputs go to logic OR. pulser goes into the same OR&lt;br /&gt;
* from this OR, they fan out to v1740 trigger inputs&lt;br /&gt;
* analog output of first v1740 provides the run gate (via polarity inverting kludge)&lt;br /&gt;
* analog output of second v1740 provides a &amp;quot;buffer-half-full&amp;quot; trigger veto (via polarity inverting kludge)&lt;br /&gt;
&lt;br /&gt;
Trigger notes: (KO 7-oct-2024)&lt;br /&gt;
* trigger signal is not synched with the v1740 clock, actual &amp;quot;adc stop&amp;quot; time will have a jitter between the two v1740 of 1-2 clock periods&lt;br /&gt;
* actual event time jitter between the two v1740 is around 2 clock (from looking at event timestamps).&lt;br /&gt;
* because v1740 busy are not synced (and busy from first v1740 is missing), the second v1740 often has extra events. sometimes the first v1740 has an extra event. fetactic.exe has workaround against this, mostly by dropping mismatched data.&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/manalyzer. &lt;br /&gt;
* Not source-controlled.&lt;br /&gt;
* Contains many hard-coded thresholds/settings/limits. Also includes a hard-coded mapping between digitizer channel number and hardware sector/pad number.&lt;br /&gt;
* Used for both online and offline analysis of data.&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild fetactic.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/v1740mt&lt;br /&gt;
make&lt;br /&gt;
ls -l fetactic.exe&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/manalyzer&lt;br /&gt;
make&lt;br /&gt;
ls -l ./tacticana.exe&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== New V2745 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 6x CAEN V2745 digitizers, with option for reading 8 digitizers if needed. With 8 digitizers can read all 8 sectors from the hardware.&lt;br /&gt;
&lt;br /&gt;
Digitizers are readout over 1G ethernet, and run DPP_ZLE firmware to reduce the data rate significantly. Future versions of TACTIC may run DPP_PHA or custom firmware to further reduce the data rate.&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:TACTIC wiring V2745.png]]&lt;br /&gt;
&lt;br /&gt;
The trigger is a global OR of every channel of every digitizer (though we can suppress certain channels if desired).&lt;br /&gt;
&lt;br /&gt;
Digitizers are set to NIM logic levels, and OR is done using standard NIM fan-in/fan-out modules. Trigger-OR is sent to 9 locations (8 digitizers + 1 visual scaler) so we use a 16x FI/FO. Busy-OR is only sent to 8 locations, so can use an 8x FI/FO.&lt;br /&gt;
&lt;br /&gt;
Digitizer configuration is done via the [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage.  The concept is that the &amp;quot;default&amp;quot; value is applied to all digitizers, unless you specifically override the value for a certain digitizer. This means it&#039;s more efficient to change settings, as you only have to change one &amp;quot;default&amp;quot; parameter rather than 8 separate board-specific parameters. Settings that have been overridden for one or more boards appear with a YELLOW background on the webpage.&lt;br /&gt;
&lt;br /&gt;
==== Settings that users may want to configure ====&lt;br /&gt;
* &#039;&#039;&#039;Readout channel mask&#039;&#039;&#039; - which channels get read out when a trigger is accepted&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A en mask&#039;&#039;&#039; - which channels contribute to the self-trigger logic&lt;br /&gt;
* &#039;&#039;&#039;Chan over thresh thresholds&#039;&#039;&#039; - the thresholds in ADC RELATIVE TO THE BASELINE&lt;br /&gt;
* &#039;&#039;&#039;Scope/ZLE waveform length&#039;&#039;&#039; - how long the waveforms should be.&lt;br /&gt;
* &#039;&#039;&#039;Pre-trigger for ZLE mode&#039;&#039;&#039; - where in the waveform the trigger pulse should appear &lt;br /&gt;
* &#039;&#039;&#039;ZLE threshold (ADC)&#039;&#039;&#039; - how many ADC below baseline a signal must be before it gets read out. Note this is different to the trigger threshold! You could trigger readout if the signal goes 50ADC below baseline, but then read out any data that&#039;s 10ADC below baseline.&lt;br /&gt;
* &#039;&#039;&#039;ZLE look back (samples)&#039;&#039;&#039; - how many samples to read out before the signal went below the ZLE threshold&lt;br /&gt;
* &#039;&#039;&#039;ZLE look forward (samples)&#039;&#039;&#039; - how many samples to read out after the signal goes back above the ZLE threshold&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A gate width(ns)&#039;&#039;&#039; - set this to roughly how long you expect a &amp;quot;real&amp;quot; event to last. If you set it too short then the NIM OR module will output triggers multiple times for a single event (e.g. for the first channel to get hit, and then 100ns later for another channel, and then 300ns after that for another channel, ....). The digitizers would still only read out data for the first trigger, but the visual scaler will show a much higher rate, which would be very confusing for debugging.&lt;br /&gt;
* &#039;&#039;&#039;DC offset (pct)&#039;&#039;&#039; - set the baseline between 0ADC and 65535ADC, as a percentage&lt;br /&gt;
* &#039;&#039;&#039;Signal offset (uV)&#039;&#039;&#039; - extra tweak to the input signal - best set using a script&lt;br /&gt;
* &#039;&#039;&#039;VGA gain&#039;&#039;&#039; - 0-40dB in 0.5dB increments&lt;br /&gt;
&lt;br /&gt;
==== Important settings that are different for the first digitizer in the chain ====&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Run start source&#039;&#039;&#039;&lt;br /&gt;
** First board: Start acq on midas run start&lt;br /&gt;
** Other boards: Start acq on encoded CLKIN&lt;br /&gt;
* &#039;&#039;&#039;Use external clock&#039;&#039;&#039;&lt;br /&gt;
** First board: True&lt;br /&gt;
** Other boards: False&lt;br /&gt;
&lt;br /&gt;
==== Settings that user&#039;s shouldn&#039;t touch ====&lt;br /&gt;
* &#039;&#039;&#039;Run start delay (ns)&#039;&#039;&#039; - 0 for the last board, increasing by 48ns for each board in the chain (240, 192, 144, 96, 49, 0).&lt;br /&gt;
* &#039;&#039;&#039;Trigger out mode&#039;&#039;&#039; - ITLA - ensure we output the self-trigger signal&lt;br /&gt;
* &#039;&#039;&#039;Trigger on external signal&#039;&#039;&#039; - True - ensure we only trigger on the global OR that gets fed back in to the board&lt;br /&gt;
* &#039;&#039;&#039;ZLE enable&#039;&#039;&#039; - True for all channels&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A multiplicity&#039;&#039;&#039; - 1 - in principle you could require 2+ hits simultaneously before we trigger (to reduce triggering on noise/bad topology events), but this setting only applies within a single board. So you&#039;ll get weird geometric efficiencies (more likely to trigger on tracks that hit multiple pads in the same sector vs pads in different sectors). If we want to trigger on 2+ hits across multiple boards we can use the DAC or LVDS connectors, and connect them to a board running custom firmware.&lt;br /&gt;
* &#039;&#039;&#039;Chan over thresh rising edge&#039;&#039;&#039; - False - TACTIC uses negative pulses&lt;br /&gt;
* &#039;&#039;&#039;Veto source&#039;&#039;&#039; / &#039;&#039;&#039;Veto when source is high&#039;&#039;&#039; - Disabled / True&lt;br /&gt;
* &#039;&#039;&#039;Use NIM IO&#039;&#039;&#039; - True&lt;br /&gt;
* &#039;&#039;&#039;Enable clock out&#039;&#039;&#039; - True&lt;br /&gt;
* &#039;&#039;&#039;GPIO mode&#039;&#039;&#039; - Busy&lt;br /&gt;
* &#039;&#039;&#039;Busy in source&#039;&#039;&#039; - SIN&lt;br /&gt;
* &#039;&#039;&#039;Sync out mode&#039;&#039;&#039; - Run&lt;br /&gt;
* &#039;&#039;&#039;Enable DC offsets&#039;&#039;&#039; - True&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/tacticana on daq18, and https://bitbucket.org/ttriumfdaq/tacticana/src/master/ on bitbucket.&lt;br /&gt;
* Uses JSON files to define histogram limits, channel mapping etc. See the [https://bitbucket.org/ttriumfdaq/tacticana/src/master/ README.md] file in the repository for details.&lt;br /&gt;
* Specify which config file to use via the --config flag.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Run online using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe --midas-progname tacticana -R8081 -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# Run offline using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe /path/to/something.mid -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# NOTE THE --config FLAG MUST COME AFTER A &#039;--&#039;!!!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Setting baselines ===&lt;br /&gt;
&lt;br /&gt;
The V2745s have two settings related to the baseline of each channel.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;DC offset&#039;&#039;&#039; sets the target of where the baseline &amp;quot;should&amp;quot; be. It&#039;s specified as a percentage of the full scale 0-65535. For TACTIC with negative pulses, it makes sense to set it to 90% or so (aka 58982 ADC).&lt;br /&gt;
* &#039;&#039;&#039;Signal offset&#039;&#039;&#039; is an extra tweak to each channel (in uV) that can be used to ensure a 0V input actually gets to the expected baseline.&lt;br /&gt;
&lt;br /&gt;
ZLE and trigger thresholds are RELATIVE TO THE EXPECTED BASELINE (i.e. 58982 ADC). The digitizers to not monitor the actual data to decide what the &amp;quot;real baseline&amp;quot; is. It is therefore critical that the signal offset is set so that the real baseline matches the expected baseline. &lt;br /&gt;
&lt;br /&gt;
* If the real baseline is lower than expected, you will trigger more often and your data rate will be higher. &lt;br /&gt;
* If the real baseline is higher than expected, you will miss triggering on small pulses, and may miss some ZLE chunks that would otherwise be readout.&lt;br /&gt;
&lt;br /&gt;
Note that baselines often drift based on the temperature of the board.&lt;br /&gt;
&lt;br /&gt;
There is a script in the dsproto_vx2740 repository that can be used to set the &amp;quot;signal offset&amp;quot; of each channel so that the real baseline matches the expected baseline. This script is very basic at the moment, but could be made smarter (both in terms of the algorithm for finding the optimal offset, and in automating more of the settings that need to be changed).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Stop the run&lt;br /&gt;
# Ensure there aren&#039;t any real signals coming in (i.e. we&#039;re just reading noise)&lt;br /&gt;
# Set &#039;ZLE enable&#039; to False for all channels&lt;br /&gt;
# Set &#039;Trigger out mode&#039; to &#039;TestPulse&#039; for the first board, and &#039;Disabled&#039; for all other boards&lt;br /&gt;
&lt;br /&gt;
cd ~/newTACTIC/dsproto_vx2740/&lt;br /&gt;
python set_offsets.py &lt;br /&gt;
&lt;br /&gt;
# Set &#039;ZLE enable&#039; to True for all channels&lt;br /&gt;
# Set &#039;Trigger out mode&#039; to &#039;ITLA&#039; for all boards&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== Rare bug in CAEN software ===&lt;br /&gt;
&lt;br /&gt;
There is a rare bug in the CAEN software/firmware that causes the entire frontend to crash on malformed data. This can be quite annoying, and could cause significant downtime if the user doesn&#039;t realise that the program has crashed and/or the run has stopped.&lt;br /&gt;
&lt;br /&gt;
midas contains a &amp;quot;sequencer&amp;quot; functionality that can be used to mitigate this. Every 10s the sequencer will check to see if the frontend has crashed, and restart it if needed. It will also start a run if the current one has stopped.&lt;br /&gt;
&lt;br /&gt;
To use this sequencer, go to the [https://daq18.triumf.ca/?cmd=Sequencer&amp;amp;SeqODB=/PySequencer PySequencer] page and start the script using the &amp;quot;play&amp;quot; button. You&#039;ll be prompted for how long you want to acquire data for.&lt;br /&gt;
&lt;br /&gt;
Note that if you want to stop data-taking early, you should use the &amp;quot;stop&amp;quot; (square) button on the PySequencer page, not the regular button on the status page for stopping a run (as the sequencer will just detect that the run has stopped and start a new one for you!).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toccolours mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width:800px; overflow:auto;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-weight:bold;line-height:1.6;&amp;quot;&amp;gt;Click &#039;Expand&#039; to view the actual sequencer script I implemented ----&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import datetime&lt;br /&gt;
import midas&lt;br /&gt;
&lt;br /&gt;
def define_params(seq):&lt;br /&gt;
    seq.register_param(&amp;quot;duration_hours&amp;quot;, &amp;quot;Total acquisition time&amp;quot;, 5.0)&lt;br /&gt;
&lt;br /&gt;
def sequence(seq):&lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
    start_time = datetime.datetime.now()&lt;br /&gt;
    elapsed_hours = 0.0&lt;br /&gt;
        &lt;br /&gt;
    while elapsed_hours &amp;lt; seq.get_param(&amp;quot;duration_hours&amp;quot;):&lt;br /&gt;
        validate_prog_running(seq)&lt;br /&gt;
        seq.wait_seconds(10)&lt;br /&gt;
        elapsed_hours = round((datetime.datetime.now() - start_time).total_seconds() / 3600, 2)&lt;br /&gt;
        &lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
        &lt;br /&gt;
def at_exit(seq):&lt;br /&gt;
    stop_run_if_needed(seq)&lt;br /&gt;
    &lt;br /&gt;
def stop_run_if_needed(seq):&lt;br /&gt;
    if seq.odb_get(&amp;quot;/Runinfo/State&amp;quot;) != midas.STATE_STOPPED:&lt;br /&gt;
        seq.stop_run()&lt;br /&gt;
    &lt;br /&gt;
def validate_prog_running(seq):&lt;br /&gt;
    prog_name = &amp;quot;VX2740_Group_01&amp;quot;&lt;br /&gt;
    if not seq.client_exists(prog_name):&lt;br /&gt;
        stop_run_if_needed(seq)&lt;br /&gt;
        seq.msg(f&amp;quot;Stopped run as {prog_name} was not running! Restarting program.&amp;quot;)&lt;br /&gt;
        seq.wait_seconds(5)&lt;br /&gt;
        seq.start_client(prog_name)&lt;br /&gt;
        seq.wait_clients_running(prog_name)&lt;br /&gt;
        &lt;br /&gt;
        if not seq.client_exists(prog_name):&lt;br /&gt;
            raise RuntimeError(f&amp;quot;Failed to restart {prog_name} - abort sequence!&amp;quot;)&lt;br /&gt;
            &lt;br /&gt;
        seq.wait_odb(&amp;quot;/Equipment/VX2740_Data_Group_001/Common/Status&amp;quot;, &amp;quot;==&amp;quot;, &amp;quot;Initialized&amp;quot;)&lt;br /&gt;
        &lt;br /&gt;
    if seq.odb_get(&amp;quot;/Runinfo/State&amp;quot;) != midas.STATE_RUNNING:&lt;br /&gt;
        seq.start_run()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild vx2740_group_fe.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/dsproto_vx2740/build&lt;br /&gt;
make install -j&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/tacticana&lt;br /&gt;
make -j&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8586</id>
		<title>TACTIC</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8586"/>
		<updated>2025-09-17T20:35:31Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= TACTIC =&lt;br /&gt;
&lt;br /&gt;
* computer: daq18.triumf.ca&lt;br /&gt;
* midas: https://daq18.triumf.ca&lt;br /&gt;
* elog: https://elog.triumf.ca/Tactic/General/ (has a &amp;quot;tactic&amp;quot; user account)&lt;br /&gt;
&lt;br /&gt;
== Old V1740 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 2x V1740 via CAEN USB interface. 64 channels each - can read out 2 of the 8 TACTIC &amp;quot;sectors&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
These [https://daq18.triumf.ca/?cmd=Programs programs] should be running:&lt;br /&gt;
* mhttpd (web server)&lt;br /&gt;
* Logger (writing data to disk)&lt;br /&gt;
* feMKS (gas mixer)&lt;br /&gt;
* fetactic (data readout from digitizers)&lt;br /&gt;
* ana (online analysis of data)&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:Tactic-v1740-trigger.jpg]]&lt;br /&gt;
&lt;br /&gt;
Trigger and v1740 connections:&lt;br /&gt;
* both v1740 trigger outputs go to logic OR. pulser goes into the same OR&lt;br /&gt;
* from this OR, they fan out to v1740 trigger inputs&lt;br /&gt;
* analog output of first v1740 provides the run gate (via polarity inverting kludge)&lt;br /&gt;
* analog output of second v1740 provides a &amp;quot;buffer-half-full&amp;quot; trigger veto (via polarity inverting kludge)&lt;br /&gt;
&lt;br /&gt;
Trigger notes: (KO 7-oct-2024)&lt;br /&gt;
* trigger signal is not synched with the v1740 clock, actual &amp;quot;adc stop&amp;quot; time will have a jitter between the two v1740 of 1-2 clock periods&lt;br /&gt;
* actual event time jitter between the two v1740 is around 2 clock (from looking at event timestamps).&lt;br /&gt;
* because v1740 busy are not synced (and busy from first v1740 is missing), the second v1740 often has extra events. sometimes the first v1740 has an extra event. fetactic.exe has workaround against this, mostly by dropping mismatched data.&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/manalyzer. &lt;br /&gt;
* Not source-controlled.&lt;br /&gt;
* Contains many hard-coded thresholds/settings/limits. Also includes a hard-coded mapping between digitizer channel number and hardware sector/pad number.&lt;br /&gt;
* Used for both online and offline analysis of data.&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild fetactic.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/v1740mt&lt;br /&gt;
make&lt;br /&gt;
ls -l fetactic.exe&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/manalyzer&lt;br /&gt;
make&lt;br /&gt;
ls -l ./tacticana.exe&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== New V2745 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 6x CAEN V2745 digitizers, with option for reading 8 digitizers if needed. With 8 digitizers can read all 8 sectors from the hardware.&lt;br /&gt;
&lt;br /&gt;
Digitizers are readout over 1G ethernet, and run DPP_ZLE firmware to reduce the data rate significantly. Future versions of TACTIC may run DPP_PHA or custom firmware to further reduce the data rate.&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:TACTIC wiring V2745.png]]&lt;br /&gt;
&lt;br /&gt;
The trigger is a global OR of every channel of every digitizer (though we can suppress certain channels if desired).&lt;br /&gt;
&lt;br /&gt;
Digitizers are set to NIM logic levels, and OR is done using standard NIM fan-in/fan-out modules. Trigger-OR is sent to 9 locations (8 digitizers + 1 visual scaler) so we use a 16x FI/FO. Busy-OR is only sent to 8 locations, so can use an 8x FI/FO.&lt;br /&gt;
&lt;br /&gt;
Digitizer configuration is done via the [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage.  The concept is that the &amp;quot;default&amp;quot; value is applied to all digitizers, unless you specifically override the value for a certain digitizer. This means it&#039;s more efficient to change settings, as you only have to change one &amp;quot;default&amp;quot; parameter rather than 8 separate board-specific parameters. Settings that have been overridden for one or more boards appear with a YELLOW background on the webpage.&lt;br /&gt;
&lt;br /&gt;
==== Settings that users may want to configure ====&lt;br /&gt;
* &#039;&#039;&#039;Readout channel mask&#039;&#039;&#039; - which channels get read out when a trigger is accepted&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A en mask&#039;&#039;&#039; - which channels contribute to the self-trigger logic&lt;br /&gt;
* &#039;&#039;&#039;Chan over thresh thresholds&#039;&#039;&#039; - the thresholds in ADC RELATIVE TO THE BASELINE&lt;br /&gt;
* &#039;&#039;&#039;Scope/ZLE waveform length&#039;&#039;&#039; - how long the waveforms should be.&lt;br /&gt;
* &#039;&#039;&#039;Pre-trigger for ZLE mode&#039;&#039;&#039; - where in the waveform the trigger pulse should appear &lt;br /&gt;
* &#039;&#039;&#039;ZLE threshold (ADC)&#039;&#039;&#039; - how many ADC below baseline a signal must be before it gets read out. Note this is different to the trigger threshold! You could trigger readout if the signal goes 50ADC below baseline, but then read out any data that&#039;s 10ADC below baseline.&lt;br /&gt;
* &#039;&#039;&#039;ZLE look back (samples)&#039;&#039;&#039; - how many samples to read out before the signal went below the ZLE threshold&lt;br /&gt;
* &#039;&#039;&#039;ZLE look forward (samples)&#039;&#039;&#039; - how many samples to read out after the signal goes back above the ZLE threshold&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A gate width(ns)&#039;&#039;&#039; - set this to roughly how long you expect a &amp;quot;real&amp;quot; event to last. If you set it too short then the NIM OR module will output triggers multiple times for a single event (e.g. for the first channel to get hit, and then 100ns later for another channel, and then 300ns after that for another channel, ....). The digitizers would still only read out data for the first trigger, but the visual scaler will show a much higher rate, which would be very confusing for debugging.&lt;br /&gt;
* &#039;&#039;&#039;DC offset (pct)&#039;&#039;&#039; - set the baseline between 0ADC and 65535ADC, as a percentage&lt;br /&gt;
* &#039;&#039;&#039;Signal offset (uV)&#039;&#039;&#039; - extra tweak to the input signal - best set using a script&lt;br /&gt;
* &#039;&#039;&#039;VGA gain&#039;&#039;&#039; - 0-40dB in 0.5dB increments&lt;br /&gt;
&lt;br /&gt;
==== Important settings that are different for the first digitizer in the chain ====&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Run start source&#039;&#039;&#039;&lt;br /&gt;
** First board: Start acq on midas run start&lt;br /&gt;
** Other boards: Start acq on encoded CLKIN&lt;br /&gt;
* &#039;&#039;&#039;Use external clock&#039;&#039;&#039;&lt;br /&gt;
** First board: True&lt;br /&gt;
** Other boards: False&lt;br /&gt;
&lt;br /&gt;
==== Settings that user&#039;s shouldn&#039;t touch ====&lt;br /&gt;
* &#039;&#039;&#039;Run start delay (ns)&#039;&#039;&#039; - 0 for the last board, increasing by 48ns for each board in the chain (240, 192, 144, 96, 49, 0).&lt;br /&gt;
* &#039;&#039;&#039;Trigger out mode&#039;&#039;&#039; - ITLA - ensure we output the self-trigger signal&lt;br /&gt;
* &#039;&#039;&#039;Trigger on external signal&#039;&#039;&#039; - True - ensure we only trigger on the global OR that gets fed back in to the board&lt;br /&gt;
* &#039;&#039;&#039;ZLE enable&#039;&#039;&#039; - True for all channels&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A multiplicity&#039;&#039;&#039; - 1 - in principle you could require 2+ hits simultaneously before we trigger (to reduce triggering on noise/bad topology events), but this setting only applies within a single board. So you&#039;ll get weird geometric efficiencies (more likely to trigger on tracks that hit multiple pads in the same sector vs pads in different sectors). If we want to trigger on 2+ hits across multiple boards we can use the DAC or LVDS connectors, and connect them to a board running custom firmware.&lt;br /&gt;
* &#039;&#039;&#039;Chan over thresh rising edge&#039;&#039;&#039; - False - TACTIC uses negative pulses&lt;br /&gt;
* &#039;&#039;&#039;Veto source&#039;&#039;&#039; / &#039;&#039;&#039;Veto when source is high&#039;&#039;&#039; - Disabled / True&lt;br /&gt;
* &#039;&#039;&#039;Use NIM IO&#039;&#039;&#039; - True&lt;br /&gt;
* &#039;&#039;&#039;Enable clock out&#039;&#039;&#039; - True&lt;br /&gt;
* &#039;&#039;&#039;GPIO mode&#039;&#039;&#039; - Busy&lt;br /&gt;
* &#039;&#039;&#039;Busy in source&#039;&#039;&#039; - SIN&lt;br /&gt;
* &#039;&#039;&#039;Sync out mode&#039;&#039;&#039; - Run&lt;br /&gt;
* &#039;&#039;&#039;Enable DC offsets&#039;&#039;&#039; - True&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/tacticana on daq18, and https://bitbucket.org/ttriumfdaq/tacticana/src/master/ on bitbucket.&lt;br /&gt;
* Uses JSON files to define histogram limits, channel mapping etc. See the [https://bitbucket.org/ttriumfdaq/tacticana/src/master/ README.md] file in the repository for details.&lt;br /&gt;
* Specify which config file to use via the --config flag.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Run online using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe --midas-progname tacticana -R8081 -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# Run offline using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe /path/to/something.mid -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# NOTE THE --config FLAG MUST COME AFTER A &#039;--&#039;!!!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Setting baselines ===&lt;br /&gt;
&lt;br /&gt;
The V2745s have two settings related to the baseline of each channel.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;DC offset&#039;&#039;&#039; sets the target of where the baseline &amp;quot;should&amp;quot; be. It&#039;s specified as a percentage of the full scale 0-65535. For TACTIC with negative pulses, it makes sense to set it to 90% or so (aka 58982 ADC).&lt;br /&gt;
* &#039;&#039;&#039;Signal offset&#039;&#039;&#039; is an extra tweak to each channel (in uV) that can be used to ensure a 0V input actually gets to the expected baseline.&lt;br /&gt;
&lt;br /&gt;
ZLE and trigger thresholds are RELATIVE TO THE EXPECTED BASELINE (i.e. 58982 ADC). The digitizers to not monitor the actual data to decide what the &amp;quot;real baseline&amp;quot; is. It is therefore critical that the signal offset is set so that the real baseline matches the expected baseline. &lt;br /&gt;
&lt;br /&gt;
* If the real baseline is lower than expected, you will trigger more often and your data rate will be higher. &lt;br /&gt;
* If the real baseline is higher than expected, you will miss triggering on small pulses, and may miss some ZLE chunks that would otherwise be readout.&lt;br /&gt;
&lt;br /&gt;
Note that baselines often drift based on the temperature of the board.&lt;br /&gt;
&lt;br /&gt;
There is a script in the dsproto_vx2740 repository that can be used to set the &amp;quot;signal offset&amp;quot; of each channel so that the real baseline matches the expected baseline.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Stop the run&lt;br /&gt;
# Ensure there aren&#039;t any real signals coming in (i.e. we&#039;re just reading noise)&lt;br /&gt;
# Set &#039;ZLE enable&#039; to False for all channels&lt;br /&gt;
# Set &#039;Trigger out mode&#039; to &#039;TestPulse&#039; for the first board, and &#039;Disabled&#039; for all other boards&lt;br /&gt;
cd ~/newTACTIC/dsproto_vx2740/&lt;br /&gt;
python set_offsets.py &lt;br /&gt;
# Set &#039;ZLE enable&#039; to True for all channels&lt;br /&gt;
# Set &#039;Trigger out mode&#039; to &#039;ITLA&#039; for all boards&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild vx2740_group_fe.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/dsproto_vx2740/build&lt;br /&gt;
make install -j&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/tacticana&lt;br /&gt;
make -j&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8585</id>
		<title>TACTIC</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8585"/>
		<updated>2025-09-17T20:11:41Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= TACTIC =&lt;br /&gt;
&lt;br /&gt;
* computer: daq18.triumf.ca&lt;br /&gt;
* midas: https://daq18.triumf.ca&lt;br /&gt;
* elog: https://elog.triumf.ca/Tactic/General/ (has a &amp;quot;tactic&amp;quot; user account)&lt;br /&gt;
&lt;br /&gt;
== Old V1740 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 2x V1740 via CAEN USB interface. 64 channels each - can read out 2 of the 8 TACTIC &amp;quot;sectors&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
These [https://daq18.triumf.ca/?cmd=Programs programs] should be running:&lt;br /&gt;
* mhttpd (web server)&lt;br /&gt;
* Logger (writing data to disk)&lt;br /&gt;
* feMKS (gas mixer)&lt;br /&gt;
* fetactic (data readout from digitizers)&lt;br /&gt;
* ana (online analysis of data)&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:Tactic-v1740-trigger.jpg]]&lt;br /&gt;
&lt;br /&gt;
Trigger and v1740 connections:&lt;br /&gt;
* both v1740 trigger outputs go to logic OR. pulser goes into the same OR&lt;br /&gt;
* from this OR, they fan out to v1740 trigger inputs&lt;br /&gt;
* analog output of first v1740 provides the run gate (via polarity inverting kludge)&lt;br /&gt;
* analog output of second v1740 provides a &amp;quot;buffer-half-full&amp;quot; trigger veto (via polarity inverting kludge)&lt;br /&gt;
&lt;br /&gt;
Trigger notes: (KO 7-oct-2024)&lt;br /&gt;
* trigger signal is not synched with the v1740 clock, actual &amp;quot;adc stop&amp;quot; time will have a jitter between the two v1740 of 1-2 clock periods&lt;br /&gt;
* actual event time jitter between the two v1740 is around 2 clock (from looking at event timestamps).&lt;br /&gt;
* because v1740 busy are not synced (and busy from first v1740 is missing), the second v1740 often has extra events. sometimes the first v1740 has an extra event. fetactic.exe has workaround against this, mostly by dropping mismatched data.&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/manalyzer. &lt;br /&gt;
* Not source-controlled.&lt;br /&gt;
* Contains many hard-coded thresholds/settings/limits. Also includes a hard-coded mapping between digitizer channel number and hardware sector/pad number.&lt;br /&gt;
* Used for both online and offline analysis of data.&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild fetactic.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/v1740mt&lt;br /&gt;
make&lt;br /&gt;
ls -l fetactic.exe&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/manalyzer&lt;br /&gt;
make&lt;br /&gt;
ls -l ./tacticana.exe&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== New V2745 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 6x CAEN V2745 digitizers, with option for reading 8 digitizers if needed. With 8 digitizers can read all 8 sectors from the hardware.&lt;br /&gt;
&lt;br /&gt;
Digitizers are readout over 1G ethernet, and run DPP_ZLE firmware to reduce the data rate significantly. Future versions of TACTIC may run DPP_PHA or custom firmware to further reduce the data rate.&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:TACTIC wiring V2745.png]]&lt;br /&gt;
&lt;br /&gt;
The trigger is a global OR of every channel of every digitizer (though we can suppress certain channels if desired).&lt;br /&gt;
&lt;br /&gt;
Digitizers are set to NIM logic levels, and OR is done using standard NIM fan-in/fan-out modules. Trigger-OR is sent to 9 locations (8 digitizers + 1 visual scaler) so we use a 16x FI/FO. Busy-OR is only sent to 8 locations, so can use an 8x FI/FO.&lt;br /&gt;
&lt;br /&gt;
Digitizer configuration is done via the [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage.  The concept is that the &amp;quot;default&amp;quot; value is applied to all digitizers, unless you specifically override the value for a certain digitizer. This means it&#039;s more efficient to change settings, as you only have to change one &amp;quot;default&amp;quot; parameter rather than 8 separate board-specific parameters. Settings that have been overridden for one or more boards appear with a YELLOW background on the webpage.&lt;br /&gt;
&lt;br /&gt;
==== Settings that users may want to configure ====&lt;br /&gt;
* &#039;&#039;&#039;Readout channel mask&#039;&#039;&#039; - which channels get read out when a trigger is accepted&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A en mask&#039;&#039;&#039; - which channels contribute to the self-trigger logic&lt;br /&gt;
* &#039;&#039;&#039;Chan over thresh thresholds&#039;&#039;&#039; - the thresholds in ADC RELATIVE TO THE BASELINE&lt;br /&gt;
* &#039;&#039;&#039;Scope/ZLE waveform length&#039;&#039;&#039; - how long the waveforms should be.&lt;br /&gt;
* &#039;&#039;&#039;Pre-trigger for ZLE mode&#039;&#039;&#039; - where in the waveform the trigger pulse should appear &lt;br /&gt;
* &#039;&#039;&#039;ZLE threshold (ADC)&#039;&#039;&#039; - how many ADC below baseline a signal must be before it gets read out. Note this is different to the trigger threshold! You could trigger readout if the signal goes 50ADC below baseline, but then read out any data that&#039;s 10ADC below baseline.&lt;br /&gt;
* &#039;&#039;&#039;ZLE look back (samples)&#039;&#039;&#039; - how many samples to read out before the signal went below the ZLE threshold&lt;br /&gt;
* &#039;&#039;&#039;ZLE look forward (samples)&#039;&#039;&#039; - how many samples to read out after the signal goes back above the ZLE threshold&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A gate width(ns)&#039;&#039;&#039; - set this to roughly how long you expect a &amp;quot;real&amp;quot; event to last. If you set it too short then the NIM OR module will output triggers multiple times for a single event (e.g. for the first channel to get hit, and then 100ns later for another channel, and then 300ns after that for another channel, ....). The digitizers would still only read out data for the first trigger, but the visual scaler will show a much higher rate, which would be very confusing for debugging.&lt;br /&gt;
* &#039;&#039;&#039;DC offset (pct)&#039;&#039;&#039; - set the baseline between 0ADC and 65535ADC, as a percentage&lt;br /&gt;
* &#039;&#039;&#039;Signal offset (uV)&#039;&#039;&#039; - extra tweak to the input signal - best set using a script&lt;br /&gt;
* &#039;&#039;&#039;VGA gain&#039;&#039;&#039; - 0-40dB in 0.5dB increments&lt;br /&gt;
&lt;br /&gt;
==== Important settings that are different for the first digitizer in the chain ====&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Run start source&#039;&#039;&#039;&lt;br /&gt;
** First board: Start acq on midas run start&lt;br /&gt;
** Other boards: Start acq on encoded CLKIN&lt;br /&gt;
* &#039;&#039;&#039;Use external clock&#039;&#039;&#039;&lt;br /&gt;
** First board: True&lt;br /&gt;
** Other boards: False&lt;br /&gt;
&lt;br /&gt;
==== Settings that user&#039;s shouldn&#039;t touch ====&lt;br /&gt;
* &#039;&#039;&#039;Run start delay (ns)&#039;&#039;&#039; - 0 for the last board, increasing by 48ns for each board in the chain (240, 192, 144, 96, 49, 0).&lt;br /&gt;
* &#039;&#039;&#039;Trigger out mode&#039;&#039;&#039; - ITLA - ensure we output the self-trigger signal&lt;br /&gt;
* &#039;&#039;&#039;Trigger on external signal&#039;&#039;&#039; - True - ensure we only trigger on the global OR that gets fed back in to the board&lt;br /&gt;
* &#039;&#039;&#039;ZLE enable&#039;&#039;&#039; - True for all channels&lt;br /&gt;
* &#039;&#039;&#039;Ch over thresh A multiplicity&#039;&#039;&#039; - 1 - in principle you could require 2+ hits simultaneously before we trigger (to reduce triggering on noise/bad topology events), but this setting only applies within a single board. So you&#039;ll get weird geometric efficiencies (more likely to trigger on tracks that hit multiple pads in the same sector vs pads in different sectors). If we want to trigger on 2+ hits across multiple boards we can use the DAC or LVDS connectors, and connect them to a board running custom firmware.&lt;br /&gt;
* &#039;&#039;&#039;Chan over thresh rising edge&#039;&#039;&#039; - False - TACTIC uses negative pulses&lt;br /&gt;
* &#039;&#039;&#039;Veto source&#039;&#039;&#039; / &#039;&#039;&#039;Veto when source is high&#039;&#039;&#039; - Disabled / True&lt;br /&gt;
* &#039;&#039;&#039;Use NIM IO&#039;&#039;&#039; - True&lt;br /&gt;
* &#039;&#039;&#039;Enable clock out&#039;&#039;&#039; - True&lt;br /&gt;
* &#039;&#039;&#039;GPIO mode&#039;&#039;&#039; - Busy&lt;br /&gt;
* &#039;&#039;&#039;Busy in source&#039;&#039;&#039; - SIN&lt;br /&gt;
* &#039;&#039;&#039;Sync out mode&#039;&#039;&#039; - Run&lt;br /&gt;
* &#039;&#039;&#039;Enable DC offsets&#039;&#039;&#039; - True&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/tacticana on daq18, and https://bitbucket.org/ttriumfdaq/tacticana/src/master/ on bitbucket.&lt;br /&gt;
* Uses JSON files to define histogram limits, channel mapping etc. See README.md file in the repository for details.&lt;br /&gt;
* Specify which config file to use via the --config flag.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Run online using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe --midas-progname tacticana -R8081 -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# Run offline using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe /path/to/something.mid -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# NOTE THE --config FLAG MUST COME AFTER A &#039;--&#039;!!!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild vx2740_group_fe.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/dsproto_vx2740/build&lt;br /&gt;
make install -j&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/tacticana&lt;br /&gt;
make -j&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8563</id>
		<title>TACTIC</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8563"/>
		<updated>2025-09-04T21:48:55Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= TACTIC =&lt;br /&gt;
&lt;br /&gt;
* computer: daq18.triumf.ca&lt;br /&gt;
* midas: https://daq18.triumf.ca&lt;br /&gt;
* elog: https://elog.triumf.ca/Tactic/General/ (has a &amp;quot;tactic&amp;quot; user account)&lt;br /&gt;
&lt;br /&gt;
== Old V1740 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 2x V1740 via CAEN USB interface. 64 channels each - can read out 2 of the 8 TACTIC &amp;quot;sectors&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
These [https://daq18.triumf.ca/?cmd=Programs programs] should be running:&lt;br /&gt;
* mhttpd (web server)&lt;br /&gt;
* Logger (writing data to disk)&lt;br /&gt;
* feMKS (gas mixer)&lt;br /&gt;
* fetactic (data readout from digitizers)&lt;br /&gt;
* ana (online analysis of data)&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:Tactic-v1740-trigger.jpg]]&lt;br /&gt;
&lt;br /&gt;
Trigger and v1740 connections:&lt;br /&gt;
* both v1740 trigger outputs go to logic OR. pulser goes into the same OR&lt;br /&gt;
* from this OR, they fan out to v1740 trigger inputs&lt;br /&gt;
* analog output of first v1740 provides the run gate (via polarity inverting kludge)&lt;br /&gt;
* analog output of second v1740 provides a &amp;quot;buffer-half-full&amp;quot; trigger veto (via polarity inverting kludge)&lt;br /&gt;
&lt;br /&gt;
Trigger notes: (KO 7-oct-2024)&lt;br /&gt;
* trigger signal is not synched with the v1740 clock, actual &amp;quot;adc stop&amp;quot; time will have a jitter between the two v1740 of 1-2 clock periods&lt;br /&gt;
* actual event time jitter between the two v1740 is around 2 clock (from looking at event timestamps).&lt;br /&gt;
* because v1740 busy are not synced (and busy from first v1740 is missing), the second v1740 often has extra events. sometimes the first v1740 has an extra event. fetactic.exe has workaround against this, mostly by dropping mismatched data.&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/manalyzer. &lt;br /&gt;
* Not source-controlled.&lt;br /&gt;
* Contains many hard-coded thresholds/settings/limits. Also includes a hard-coded mapping between digitizer channel number and hardware sector/pad number.&lt;br /&gt;
* Used for both online and offline analysis of data.&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild fetactic.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/v1740mt&lt;br /&gt;
make&lt;br /&gt;
ls -l fetactic.exe&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/manalyzer&lt;br /&gt;
make&lt;br /&gt;
ls -l ./tacticana.exe&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== New V2745 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 6x CAEN V2745 digitizers, with option for reading 8 digitizers if needed. With 8 digitizers can read all 8 sectors from the hardware.&lt;br /&gt;
&lt;br /&gt;
Digitizers are readout over 1G ethernet, and run DPP_ZLE firmware to reduce the data rate significantly. Future versions of TACTIC may run DPP_PHA or custom firmware to further reduce the data rate.&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:TACTIC wiring V2745.png]]&lt;br /&gt;
&lt;br /&gt;
The trigger is a global OR of every channel of every digitizer (though we can suppress certain channels if desired).&lt;br /&gt;
&lt;br /&gt;
Digitizers are set to NIM logic levels, and OR is done using standard NIM fan-in/fan-out modules. Trigger-OR is sent to 9 locations (8 digitizers + 1 visual scaler) so we use a 16x FI/FO. Busy-OR is only sent to 8 locations, so can use an 8x FI/FO.&lt;br /&gt;
&lt;br /&gt;
Digitizer configuration is done via the [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage.  The concept is that the &amp;quot;default&amp;quot; value is applied to all digitizers, unless you specifically override the value for a certain digitizer. This means it&#039;s more efficient to change settings, as you only have to change one &amp;quot;default&amp;quot; parameter rather than 8 separate board-specific parameters. Settings that have been overridden for one or more boards appear with a YELLOW background on the webpage.&lt;br /&gt;
&lt;br /&gt;
==== Settings that users may want to configure ====&lt;br /&gt;
* Readout channel mask - which channels get read out when a trigger is accepted&lt;br /&gt;
* Ch over thresh A en mask - which channels contribute to the self-trigger logic&lt;br /&gt;
* Chan over thresh thresholds - the thresholds in ADC RELATIVE TO THE BASELINE&lt;br /&gt;
* Scope/ZLE waveform length - how long the waveforms should be.&lt;br /&gt;
* Pre-trigger for ZLE mode - where in the waveform the trigger pulse should appear &lt;br /&gt;
* ZLE threshold (ADC) - how many ADC below baseline a signal must be before it gets read out. Note this is different to the trigger threshold! You could trigger readout if the signal goes 50ADC below baseline, but then read out any data that&#039;s 10ADC below baseline.&lt;br /&gt;
* ZLE look back (samples) - how many samples to read out before the signal went below the ZLE threshold&lt;br /&gt;
* ZLE look forward (samples) - how many samples to read out after the signal goes back above the ZLE threshold&lt;br /&gt;
* Ch over thresh A gate width(ns) - set this to roughly how long you expect a &amp;quot;real&amp;quot; event to last. If you set it too short then the NIM OR module will output triggers multiple times for a single event (e.g. for the first channel to get hit, and then 100ns later for another channel, and then 300ns after that for another channel, ....). The digitizers would still only read out data for the first trigger, but the visual scaler will show a much higher rate, which would be very confusing for debugging.&lt;br /&gt;
* DC offset (pct) - set the baseline between 0ADC and 65535ADC, as a percentage&lt;br /&gt;
* Signal offset (uV) - extra tweak to the input signal&lt;br /&gt;
* VGA gain - 0-40dB in 0.5dB increments&lt;br /&gt;
&lt;br /&gt;
==== Important settings that are different for the first digitizer in the chain ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Setting !! First board !! Other boards&lt;br /&gt;
|-&lt;br /&gt;
| Run start source || Start acq on midas run start || Start acq on encoded CLKIN&lt;br /&gt;
|-&lt;br /&gt;
| Use external clock || True || False&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Other important settings that shouldn&#039;t be changed ====&lt;br /&gt;
* Run start delay (ns) - 0 for the last board, increasing by 48ns for each board in the chain (240, 192, 144, 96, 49, 0).&lt;br /&gt;
* Trigger out mode - ITLA - ensure we output the self-trigger signal&lt;br /&gt;
* Trigger on external signal - True - ensure we only trigger on the global OR that gets fed back in to the board&lt;br /&gt;
* ZLE enable - True for all channels&lt;br /&gt;
* Ch over thresh A multiplicity - 1 - in principle you could require 2+ hits simultaneously before we trigger (to reduce triggering on noise/bad topology events), but this setting only applies within a single board. So you&#039;ll get weird geometric efficiencies (more likely to trigger on tracks that hit multiple pads in the same sector vs pads in different sectors). If we want to trigger on 2+ hits across multiple boards we can use the DAC or LVDS connectors, and connect them to a board running custom firmware.&lt;br /&gt;
* Chan over thresh rising edge - False - TACTIC uses negative pulses&lt;br /&gt;
* Veto source / Veto when source is high - Disabled / True&lt;br /&gt;
* Use NIM IO - True&lt;br /&gt;
* Enable clock out - True&lt;br /&gt;
* GPIO mode - Busy&lt;br /&gt;
* Busy in source - SIN&lt;br /&gt;
* Sync out mode - Run&lt;br /&gt;
* Enable DC offsets - True&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/tacticana on daq18, and https://bitbucket.org/ttriumfdaq/tacticana/src/master/ on bitbucket.&lt;br /&gt;
* Uses JSON files to define histogram limits, channel mapping etc. See README.md file in the repository for details.&lt;br /&gt;
* Specify which config file to use via the --config flag.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Run online using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe --midas-progname tacticana -R8081 -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# Run offline using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe /path/to/something.mid -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# NOTE THE --config FLAG MUST COME AFTER A &#039;--&#039;!!!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild vx2740_group_fe.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/dsproto_vx2740/build&lt;br /&gt;
make install -j&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/tacticana&lt;br /&gt;
make -j&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8562</id>
		<title>TACTIC</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8562"/>
		<updated>2025-09-04T21:47:21Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= TACTIC =&lt;br /&gt;
&lt;br /&gt;
* computer: daq18.triumf.ca&lt;br /&gt;
* midas: https://daq18.triumf.ca&lt;br /&gt;
* elog: https://elog.triumf.ca/Tactic/General/ (has a &amp;quot;tactic&amp;quot; user account)&lt;br /&gt;
&lt;br /&gt;
== Old V1740 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 2x V1740 via CAEN USB interface. 64 channels each - can read out 2 of the 8 TACTIC &amp;quot;sectors&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
These [https://daq18.triumf.ca/?cmd=Programs programs] should be running:&lt;br /&gt;
* mhttpd (web server)&lt;br /&gt;
* Logger (writing data to disk)&lt;br /&gt;
* feMKS (gas mixer)&lt;br /&gt;
* fetactic (data readout from digitizers)&lt;br /&gt;
* ana (online analysis of data)&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:Tactic-v1740-trigger.jpg]]&lt;br /&gt;
&lt;br /&gt;
Trigger and v1740 connections:&lt;br /&gt;
* both v1740 trigger outputs go to logic OR. pulser goes into the same OR&lt;br /&gt;
* from this OR, they fan out to v1740 trigger inputs&lt;br /&gt;
* analog output of first v1740 provides the run gate (via polarity inverting kludge)&lt;br /&gt;
* analog output of second v1740 provides a &amp;quot;buffer-half-full&amp;quot; trigger veto (via polarity inverting kludge)&lt;br /&gt;
&lt;br /&gt;
Trigger notes: (KO 7-oct-2024)&lt;br /&gt;
* trigger signal is not synched with the v1740 clock, actual &amp;quot;adc stop&amp;quot; time will have a jitter between the two v1740 of 1-2 clock periods&lt;br /&gt;
* actual event time jitter between the two v1740 is around 2 clock (from looking at event timestamps).&lt;br /&gt;
* because v1740 busy are not synced (and busy from first v1740 is missing), the second v1740 often has extra events. sometimes the first v1740 has an extra event. fetactic.exe has workaround against this, mostly by dropping mismatched data.&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/manalyzer. &lt;br /&gt;
* Not source-controlled.&lt;br /&gt;
* Contains many hard-coded thresholds/settings/limits. Also includes a hard-coded mapping between digitizer channel number and hardware sector/pad number.&lt;br /&gt;
* Used for both online and offline analysis of data.&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild fetactic.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/v1740mt&lt;br /&gt;
make&lt;br /&gt;
ls -l fetactic.exe&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/manalyzer&lt;br /&gt;
make&lt;br /&gt;
ls -l ./tacticana.exe&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== New V2745 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 6x CAEN V2745 digitizers, with option for reading 8 digitizers if needed. With 8 digitizers can read all 8 sectors from the hardware.&lt;br /&gt;
&lt;br /&gt;
Digitizers are readout over 1G ethernet, and run DPP_ZLE firmware to reduce the data rate significantly. Future versions of TACTIC may run DPP_PHA or custom firmware to further reduce the data rate.&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:TACTIC wiring V2745.png]]&lt;br /&gt;
&lt;br /&gt;
The trigger is a global OR of every channel of every digitizer (though we can suppress certain channels if desired).&lt;br /&gt;
&lt;br /&gt;
Digitizers are set to NIM logic levels, and OR is done using standard NIM fan-in/fan-out modules. Trigger-OR is sent to 9 locations (8 digitizers + 1 visual scaler) so we use a 16x FI/FO. Busy-OR is only sent to 8 locations, so can use an 8x FI/FO.&lt;br /&gt;
&lt;br /&gt;
Digitizer configuration is done via the [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage.  The concept is that the &amp;quot;default&amp;quot; value is applied to all digitizers, unless you specifically override the value for a certain digitizer. This means it&#039;s more efficient to change settings, as you only have to change one &amp;quot;default&amp;quot; parameter rather than 8 separate board-specific parameters. Settings that have been overridden for one or more boards appear with a YELLOW background on the webpage.&lt;br /&gt;
&lt;br /&gt;
Settings that users may want to configure:&lt;br /&gt;
* Readout channel mask - which channels get read out when a trigger is accepted&lt;br /&gt;
* Ch over thresh A en mask - which channels contribute to the self-trigger logic&lt;br /&gt;
* Chan over thresh thresholds - the thresholds in ADC RELATIVE TO THE BASELINE&lt;br /&gt;
* Scope/ZLE waveform length - how long the waveforms should be.&lt;br /&gt;
* Pre-trigger for ZLE mode - where in the waveform the trigger pulse should appear &lt;br /&gt;
* ZLE threshold (ADC) - how many ADC below baseline a signal must be before it gets read out. Note this is different to the trigger threshold! You could trigger readout if the signal goes 50ADC below baseline, but then read out any data that&#039;s 10ADC below baseline.&lt;br /&gt;
* ZLE look back (samples) - how many samples to read out before the signal went below the ZLE threshold&lt;br /&gt;
* ZLE look forward (samples) - how many samples to read out after the signal goes back above the ZLE threshold&lt;br /&gt;
* Ch over thresh A gate width(ns) - set this to roughly how long you expect a &amp;quot;real&amp;quot; event to last. If you set it too short then the NIM OR module will output triggers multiple times for a single event (e.g. for the first channel to get hit, and then 100ns later for another channel, and then 300ns after that for another channel, ....). The digitizers would still only read out data for the first trigger, but the visual scaler will show a much higher rate, which would be very confusing for debugging.&lt;br /&gt;
* DC offset (pct) - set the baseline between 0ADC and 65535ADC, as a percentage&lt;br /&gt;
* Signal offset (uV) - extra tweak to the input signal&lt;br /&gt;
* VGA gain - 0-40dB in 0.5dB increments&lt;br /&gt;
&lt;br /&gt;
Important settings that are different for the first digitizer in the chain:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Setting !! First board !! Other boards&lt;br /&gt;
|-&lt;br /&gt;
| Run start source || Start acq on midas run start || Start acq on encoded CLKIN&lt;br /&gt;
|-&lt;br /&gt;
| Use external clock || True || False&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Other important settings that shouldn&#039;t be changed:&lt;br /&gt;
* Run start delay (ns) - 0 for the last board, increasing by 48ns for each board in the chain (240, 192, 144, 96, 49, 0).&lt;br /&gt;
* Trigger out mode - ITLA - ensure we output the self-trigger signal&lt;br /&gt;
* Trigger on external signal - True - ensure we only trigger on the global OR that gets fed back in to the board&lt;br /&gt;
* ZLE enable - True for all channels&lt;br /&gt;
* Ch over thresh A multiplicity - 1 - in principle you could require 2+ hits simultaneously before we trigger (to reduce triggering on noise/bad topology events), but this setting only applies within a single board. So you&#039;ll get weird geometric efficiencies (more likely to trigger on tracks that hit multiple pads in the same sector vs pads in different sectors). If we want to trigger on 2+ hits across multiple boards we can use the DAC or LVDS connectors, and connect them to a board running custom firmware.&lt;br /&gt;
* Chan over thresh rising edge - False - TACTIC uses negative pulses&lt;br /&gt;
* Veto source / Veto when source is high - Disabled / True&lt;br /&gt;
* Use NIM IO - True&lt;br /&gt;
* Enable clock out - True&lt;br /&gt;
* GPIO mode - Busy&lt;br /&gt;
* Busy in source - SIN&lt;br /&gt;
* Sync out mode - Run&lt;br /&gt;
* Enable DC offsets - True&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/tacticana on daq18, and https://bitbucket.org/ttriumfdaq/tacticana/src/master/ on bitbucket.&lt;br /&gt;
* Uses JSON files to define histogram limits, channel mapping etc. See README.md file in the repository for details.&lt;br /&gt;
* Specify which config file to use via the --config flag.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Run online using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe --midas-progname tacticana -R8081 -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# Run offline using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe /path/to/something.mid -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# NOTE THE --config FLAG MUST COME AFTER A &#039;--&#039;!!!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild vx2740_group_fe.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/dsproto_vx2740/build&lt;br /&gt;
make install -j&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/tacticana&lt;br /&gt;
make -j&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=File:TACTIC_wiring_V2745.png&amp;diff=8561</id>
		<title>File:TACTIC wiring V2745.png</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=File:TACTIC_wiring_V2745.png&amp;diff=8561"/>
		<updated>2025-09-04T21:31:23Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;TACTIC wiring for newer V2745 DAQ&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8560</id>
		<title>TACTIC</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=TACTIC&amp;diff=8560"/>
		<updated>2025-09-04T20:37:28Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= TACTIC =&lt;br /&gt;
&lt;br /&gt;
* computer: daq18.triumf.ca&lt;br /&gt;
* midas: https://daq18.triumf.ca&lt;br /&gt;
* elog: https://elog.triumf.ca/Tactic/General/ (has a &amp;quot;tactic&amp;quot; user account)&lt;br /&gt;
&lt;br /&gt;
== Old v1740 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 2x V1740 via CAEN USB interface. 64 channels each - can read out 2 of the 8 TACTIC &amp;quot;sectors&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
These [https://daq18.triumf.ca/?cmd=Programs programs] should be running:&lt;br /&gt;
* mhttpd (web server)&lt;br /&gt;
* Logger (writing data to disk)&lt;br /&gt;
* feMKS (gas mixer)&lt;br /&gt;
* fetactic (data readout from digitizers)&lt;br /&gt;
* ana (online analysis of data)&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
[[File:Tactic-v1740-trigger.jpg]]&lt;br /&gt;
&lt;br /&gt;
Trigger and v1740 connections:&lt;br /&gt;
* both v1740 trigger outputs go to logic OR. pulser goes into the same OR&lt;br /&gt;
* from this OR, they fan out to v1740 trigger inputs&lt;br /&gt;
* analog output of first v1740 provides the run gate (via polarity inverting kludge)&lt;br /&gt;
* analog output of second v1740 provides a &amp;quot;buffer-half-full&amp;quot; trigger veto (via polarity inverting kludge)&lt;br /&gt;
&lt;br /&gt;
Trigger notes: (KO 7-oct-2024)&lt;br /&gt;
* trigger signal is not synched with the v1740 clock, actual &amp;quot;adc stop&amp;quot; time will have a jitter between the two v1740 of 1-2 clock periods&lt;br /&gt;
* actual event time jitter between the two v1740 is around 2 clock (from looking at event timestamps).&lt;br /&gt;
* because v1740 busy are not synced (and busy from first v1740 is missing), the second v1740 often has extra events. sometimes the first v1740 has an extra event. fetactic.exe has workaround against this, mostly by dropping mismatched data.&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/manalyzer. &lt;br /&gt;
* Not source-controlled.&lt;br /&gt;
* Contains many hard-coded thresholds/settings/limits. Also includes a hard-coded mapping between digitizer channel number and hardware sector/pad number.&lt;br /&gt;
* Used for both online and offline analysis of data.&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild fetactic.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/v1740mt&lt;br /&gt;
make&lt;br /&gt;
ls -l fetactic.exe&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/manalyzer&lt;br /&gt;
make&lt;br /&gt;
ls -l ./tacticana.exe&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== New V2745 DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== Overview === &lt;br /&gt;
&lt;br /&gt;
Uses 6x CAEN V2745 digitizers, with option for reading 8 digitizers if needed. With 8 digitizers can read all 8 sectors from the hardware.&lt;br /&gt;
&lt;br /&gt;
Digitizers are readout over 1G ethernet, and run DPP_ZLE firmware to reduce the data rate significantly. Future versions of TACTIC may run DPP_PHA or custom firmware to further reduce the data rate.&lt;br /&gt;
&lt;br /&gt;
=== Wiring diagram and trigger logic ===&lt;br /&gt;
&lt;br /&gt;
Digitizer configuration is done via the [https://daq18.triumf.ca/?cmd=custom&amp;amp;page=VX%20settings VX settings] webpage.  The concept is that the &amp;quot;default&amp;quot; value is applied to all digitizers, unless you specifically override the value for a certain digitizer. This means it&#039;s more efficient to change settings, as you only have to change one &amp;quot;default&amp;quot; parameter rather than 8 separate board-specific parameters. Settings that have been overridden for one or more boards appear with a YELLOW background on the webpage.&lt;br /&gt;
&lt;br /&gt;
Settings that users may want to configure:&lt;br /&gt;
* Readout channel mask&lt;br /&gt;
* Ch over thresh A en mask&lt;br /&gt;
* Chan over thresh thresholds&lt;br /&gt;
* Ch over thresh A gate width(ns)&lt;br /&gt;
* Scope/ZLE waveform length&lt;br /&gt;
* Pre-trigger for ZLE mode&lt;br /&gt;
* ZLE threshold (ADC)&lt;br /&gt;
* ZLE look back (samples)&lt;br /&gt;
* ZLE look forward (samples)&lt;br /&gt;
* DC offset (pct)&lt;br /&gt;
* Signal offset (uV)&lt;br /&gt;
* VGA gain - 0-40dB in 0.5dB increments&lt;br /&gt;
&lt;br /&gt;
Important settings that are different for the first digitizer in the chain:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Setting !! First board !! Other boards&lt;br /&gt;
|-&lt;br /&gt;
| Run start source || Start acq on midas run start || Start acq on encoded CLKIN&lt;br /&gt;
|-&lt;br /&gt;
| Use external clock || True || False&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Other important settings that shouldn&#039;t be changed:&lt;br /&gt;
* Run start delay (ns) - 0 for the last board, increasing by 48ns for each board in the chain (240, 192, 144, 96, 49, 0).&lt;br /&gt;
* Trigger out mode - ITLA&lt;br /&gt;
* Trigger on external signal - True&lt;br /&gt;
* ZLE enable&lt;br /&gt;
* Ch over thresh A multiplicity&lt;br /&gt;
* Chan over thresh rising edge&lt;br /&gt;
* Veto source / Veto when source is high - &lt;br /&gt;
* Use NIM IO - True&lt;br /&gt;
* Enable clock out - True&lt;br /&gt;
* GPIO mode - Busy&lt;br /&gt;
* Busy in source - SIN&lt;br /&gt;
* Sync out mode - Run&lt;br /&gt;
* Enable DC offsets - True&lt;br /&gt;
&lt;br /&gt;
=== Analyzer notes ===&lt;br /&gt;
&lt;br /&gt;
* Code is in /home/tactic/newTACTIC/tacticana on daq18, and https://bitbucket.org/ttriumfdaq/tacticana/src/master/ on bitbucket.&lt;br /&gt;
* Uses JSON files to define histogram limits, channel mapping etc. See README.md file in the repository for details.&lt;br /&gt;
* Specify which config file to use via the --config flag.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Run online using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe --midas-progname tacticana -R8081 -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# Run offline using the v2745.json config file:&lt;br /&gt;
/home/tactic/newTACTIC/tacticana/tacticana.exe /path/to/something.mid -- --conf /home/tactic/newTACTIC/tacticana/v2745.json&lt;br /&gt;
&lt;br /&gt;
# NOTE THE --config FLAG MUST COME AFTER A &#039;--&#039;!!!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Re-compilation === &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Rebuild vx2740_group_fe.exe&lt;br /&gt;
cd /home/tactic/newTACTIC/dsproto_vx2740/build&lt;br /&gt;
make install -j&lt;br /&gt;
&lt;br /&gt;
# Rebuild analyzer&lt;br /&gt;
cd /home/tactic/newTACTIC/tacticana&lt;br /&gt;
make -j&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=File:Tactic-v1740-trigger.jpg&amp;diff=8559</id>
		<title>File:Tactic-v1740-trigger.jpg</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=File:Tactic-v1740-trigger.jpg&amp;diff=8559"/>
		<updated>2025-09-04T20:03:58Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;TACTIC V1740 DAQ trigger&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=MPET_DAQ&amp;diff=8203</id>
		<title>MPET DAQ</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=MPET_DAQ&amp;diff=8203"/>
		<updated>2025-02-05T23:41:00Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Links =&lt;br /&gt;
&amp;lt;div style=&amp;quot;column-count:3;-moz-column-count:3;-webkit-column-count:3&amp;quot;&amp;gt;&lt;br /&gt;
* [[TITAN]] TITAN Page&lt;br /&gt;
* [[TITAN DAQ General Documentation]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
MPET has:&lt;br /&gt;
&lt;br /&gt;
* A PPG for programming pulses&lt;br /&gt;
* A 2-channel Tektronix AFG for generating RF (was previously two Agilent AFGs)&lt;br /&gt;
* An 8-channel GSC 16ao16 to control the trap voltages (was previously an Alphi Softdac). There is a breakout box to convert to BNC connections. The breakout box has many connectors, but only 8 channels are actually controllable!&lt;br /&gt;
* An older VT2 TDC for recording timestamps&lt;br /&gt;
* A position analyzer to determine X/Y positions of ions&lt;br /&gt;
* A Lecroy LRS1190 memory buffer that records the X/Y position&lt;br /&gt;
* A newer CAEN V1290 25ps TDC for recording timestamps&lt;br /&gt;
&lt;br /&gt;
Note that the VT2/V1290 TDCs are enabled in different ways:&lt;br /&gt;
* The VT2 has a &amp;quot;gate&amp;quot; that is set to 1 for the entire period that timestamps should be recorded&lt;br /&gt;
* The V1290 has a &amp;quot;trigger&amp;quot; that is issued at the end of the desired period; the times of any hits within the &amp;quot;trigger window&amp;quot; (normally 50us) before the trigger are recorded&lt;br /&gt;
&lt;br /&gt;
The wiring diagram for the MPET DAQ is:&lt;br /&gt;
&lt;br /&gt;
[[Image:MPET wiring.png]]&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
&lt;br /&gt;
The DAQ system is based on the [https://midas.triumf.ca/MidasWiki/index.php/Midas_documentation MIDAS DAQ package]. Software written for MPET is linked with the MIDAS libraries and uses common framework for MPET/CPET/EBIT. &lt;br /&gt;
&lt;br /&gt;
The MPET software can be found at &#039;&#039;/home/mpet/packages/mpet&#039;&#039; on &#039;&#039;&#039;titan01&#039;&#039;&#039; (note that historical versions of the software were located in &#039;&#039;/home/mpet/online&#039;&#039;).  &lt;br /&gt;
&lt;br /&gt;
Run control is done using the MIDAS webserver [https://midas.triumf.ca/MidasWiki/index.php/Mhttpd mhttpd] with [https://midas.triumf.ca/MidasWiki/index.php/Custom_Page Custom Pages] written for &#039;&#039;mpet&#039;&#039; users so that they can easily enter the parameters required to program the PPG and to run the DAQ.&lt;br /&gt;
&lt;br /&gt;
The default login shell for the mpet user is now bash. If you want to use the legacy DAQ (which only supports the VT2/VT4 and Softdac, not the CAEN V1290 and GSC 16ao16), then change to the tcsh shell by typing &#039;tcsh&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Program listing ===&lt;br /&gt;
&lt;br /&gt;
In the order that programs appear on the [http://titan01.triumf.ca:8088/?cmd=Programs Programs page]:&lt;br /&gt;
* mserver - midas RPC server that allows the programs on lxebit to talk to the main experiment on titan01&lt;br /&gt;
* fempet - main MPET frontend that talks to the PPG, scans EPICS values etc. Runs on lxmpet.&lt;br /&gt;
* mhttpd - midas web server&lt;br /&gt;
* PPGCompilerFrontend - converts a user-supplied PPG program into bytecode that can be loaded onto the PPG&lt;br /&gt;
* saveload - helps save and load scan settings&lt;br /&gt;
* AfgFrontend - frontend that configures the Agilent Quad/Dipole AFGs at the start of each run (written in python)&lt;br /&gt;
* AfgTekFrontend - frontend that configures the Tektronix AFG at the start of each run (written in python)&lt;br /&gt;
* Logger - midas data logger&lt;br /&gt;
* mpetana - python analyzer that creates plots based on live data (plots are viewed via the [http://titan01.triumf.ca:8088/?cmd=custom&amp;amp;page=Web%20plots Web plots] page)&lt;br /&gt;
&lt;br /&gt;
=== Starting and stopping DAQ programs ===&lt;br /&gt;
If the MPET webpage is unavailable, log in to mpet@titan01.triumf.ca, and type&lt;br /&gt;
&lt;br /&gt;
  mhttpd -D&lt;br /&gt;
&lt;br /&gt;
Then you can use the [http://titan01.triumf.ca:8080/?cmd=Programs Midas programs page] to start/stop the remaining DAQ programs.&lt;br /&gt;
&lt;br /&gt;
At the very least, the following programs &#039;&#039;&#039;should be running&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
* mserver (start this before fempet!)&lt;br /&gt;
* fempet&lt;br /&gt;
* mhttpd&lt;br /&gt;
* PPGCompilerFrontend&lt;br /&gt;
* saveload&lt;br /&gt;
* AfgFrontend OR AfgTekFrontend (depending on which device you&#039;re using)&lt;br /&gt;
* Logger&lt;br /&gt;
* mpetana&lt;br /&gt;
&lt;br /&gt;
The following programs &#039;&#039;&#039;may be started&#039;&#039;&#039; if they are useful for your analysis:&lt;br /&gt;
&lt;br /&gt;
* Sequencer&lt;br /&gt;
* midas_to_df_scan_live&lt;br /&gt;
* mpetana_df&lt;br /&gt;
&lt;br /&gt;
The following programs are &#039;&#039;&#039;not required&#039;&#039;&#039; during normal operation:&lt;br /&gt;
&lt;br /&gt;
* feCrossTest&lt;br /&gt;
&lt;br /&gt;
=== Pulling the latest version of the MPET DAQ software ===&lt;br /&gt;
  cd ~/packages/mpet&lt;br /&gt;
  git pull&lt;br /&gt;
  git submodule update&lt;br /&gt;
&lt;br /&gt;
=== Building the MPET DAQ software ===&lt;br /&gt;
 cd ~/packages/mpet/build&lt;br /&gt;
 cmake ..&lt;br /&gt;
 make install&lt;br /&gt;
&lt;br /&gt;
This will build the appropriate 32-bit frontend program that can be used by lxmpet.&lt;br /&gt;
&lt;br /&gt;
=== 16ao16 driver and software ===&lt;br /&gt;
&lt;br /&gt;
The [http://www.generalstandards.com/view-products2.php?BD_family=16ao16 16ao16] is used to control the trap voltages. It is mounted on lxmpet as a PMC board, and requires a kernel module and software. GSC seem very good at supporting this and continue releasing updates for newer linux versions.&lt;br /&gt;
&lt;br /&gt;
There is one tweak we need to make for the build to work vs what is documented in the manual. &lt;br /&gt;
&lt;br /&gt;
 1. Download the latest 16ao16.linux.******.tar.gz bundle from http://www.generalstandards.com/downloads/ and copy it to ~/packages. Extract it using tar. It should create the directory ~/packages/16ao16.&lt;br /&gt;
 &lt;br /&gt;
 2. Run `uname -r` to find your current kernel version.&lt;br /&gt;
 &lt;br /&gt;
 3. Check if a file exists called /usr/src/linux-headers-&amp;lt;kernel_version&amp;gt;-common/scripts/file-size.sh. &lt;br /&gt;
    If not, create it and fill it with this content:&lt;br /&gt;
    #!/bin/sh  &lt;br /&gt;
    #SPDX-License-Identifier: GPL-2.0  &lt;br /&gt;
    set -- $(ls -dn &amp;quot;$1&amp;quot;)  &lt;br /&gt;
    printf &#039;%s\n&#039; &amp;quot;$5&amp;quot;&lt;br /&gt;
   &lt;br /&gt;
 4. Build the software:&lt;br /&gt;
    cd ~/packages/16ao16&lt;br /&gt;
    ./make_all&lt;br /&gt;
 &lt;br /&gt;
 5. Do the final installation of library and driver as root:&lt;br /&gt;
    su - root&lt;br /&gt;
    cd ~/packages/16ao16&lt;br /&gt;
    ./make_all&lt;br /&gt;
 &lt;br /&gt;
 6. Verify that the driver has been loaded, by seeing if /proc/16ao16 exists.&lt;br /&gt;
 &lt;br /&gt;
 7. Configure things so the driver loads each time lxmpet boots, by adding the following line to /etc/rc.local:&lt;br /&gt;
    /home/mpet/packages/16ao16/driver/start&lt;br /&gt;
&lt;br /&gt;
The make_all script builds both the driver and the software libraries. The mpet software builds and links against the GSC library. By default it looks for the headers/libraries in /home/mpet/packages/16ao16, but if you&#039;ve built it elsewhere you can specify an alternate directory using the &amp;lt;code&amp;gt;-DGSC_16AO16_DIR=/path/to/somewhere&amp;lt;/code&amp;gt; argument when running cmake.&lt;br /&gt;
&lt;br /&gt;
== Agilent vs Tektronix AFGs ==&lt;br /&gt;
&lt;br /&gt;
In summer 2022, MPET bought a Tektronix 35052 2-channel AFG to replace two Agilent AFGs (both types of AFG are used to generate RF signals).&lt;br /&gt;
&lt;br /&gt;
The Agilent AFGs could be programmed with a list of frequencies, with the next frequency being loaded when a PPG signal was issued. This allowed the frequencies to be scanned within a single PPG loop. The Tektronix AFG does have a sequencing option (if you pay extra money), but has severe limitations that do not allow it to be used the way we need (especially if wanting to run both channels simultaneously).&lt;br /&gt;
&lt;br /&gt;
Therefore, when using the Tektronix AFG, the frequency must be scanned outside of the PPG loop (same as if you were scanning an EPICS PV or trap voltage).&lt;br /&gt;
&lt;br /&gt;
=== AfgFrontend vs AfgTekFrontend ===&lt;br /&gt;
&lt;br /&gt;
There are two separate programs that may be run:&lt;br /&gt;
* AfgFrontend is the program that controls the Agilent AFGs&lt;br /&gt;
* AfgTekFrontend is the program that controls the Tektronix AFG&lt;br /&gt;
&lt;br /&gt;
The code has some sanity-checks to make it easier for you to determine which AFG was being used when looking at the midas files:&lt;br /&gt;
* The run will not start if both the Agilent and Tektronix frontends are running&lt;br /&gt;
* The run will not start if an Agilent AFG is set as &amp;quot;enabled&amp;quot; in the ODB, but the Tektronix frontend is running (or vice-versa)&lt;br /&gt;
&lt;br /&gt;
=== Changing between the AFGs ===&lt;br /&gt;
&lt;br /&gt;
To change from using the Agilent to Agilent AFG:&lt;br /&gt;
* Stop the AfgFrontend program on the Programs page&lt;br /&gt;
* Start the AfgTekFrontend program on the Programs page&lt;br /&gt;
* Go to the &amp;quot;RF (Tek)&amp;quot; page and configure the frequencies&lt;br /&gt;
&lt;br /&gt;
To change from using the Tektronix to Agilent AFG:&lt;br /&gt;
* Stop the AfgTekFrontend program on the Programs page&lt;br /&gt;
* Start the AfgFrontend program on the Programs page&lt;br /&gt;
* Go to the &amp;quot;RF (Agilent)&amp;quot; page and configure the frequencies&lt;br /&gt;
&lt;br /&gt;
For the Agilent AFG, the number of frequencies is determined by the number of loops of the &amp;quot;begin_ramp&amp;quot; loop of the PPG program.&lt;br /&gt;
&lt;br /&gt;
For the Tektronix AFG, the number of frequencies is determined by the number of X/Y/Z scan steps. &amp;lt;b&amp;gt;You may still have &amp;gt; 1 loops in the &amp;quot;begin_ramp&amp;quot; loop of the PPG program, but they will all be taken with the same frequency&amp;lt;/b&amp;gt; (take care of this when doing analysis!). Having &amp;gt; 1 loops is the lowest-latency (most efficient) way of increasing your statistics as the DAQ won&#039;t do anything until all the loops have completed; only then will there be some deadtime as the DAQ moves to the next scan point.&lt;br /&gt;
&lt;br /&gt;
=== X/Y/Z scan ordering ===&lt;br /&gt;
&lt;br /&gt;
For a 2D scan, all the Y points are covered at a given X point before moving to the next X point.&lt;br /&gt;
&lt;br /&gt;
For a 3D scan, all the Z points are covered at a given X+Y point before moving to the next Y point. After all the Y points have been covered we move to the next X point.&lt;br /&gt;
&lt;br /&gt;
So for a 3D scan, the Z variable is changed a lot more often than the X variable. For maximum efficiency, it is recommended that you use the Z variable for the parameter that is quickest to react to the change (e.g. EPICS voltages can be slow to react, so changing EPICS in the X variable and the frequency in the Z variable is likely to be most efficient).&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=TITAN&amp;diff=8202</id>
		<title>TITAN</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=TITAN&amp;diff=8202"/>
		<updated>2025-02-05T23:39:59Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: /* TITAN Linux DAQ cluster */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Information on TITAN DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== General info ===&lt;br /&gt;
&lt;br /&gt;
* [http://titan.triumf.ca TITAN Main Web page]&lt;br /&gt;
* [http://daq-plone.triumf.ca/ESI/titan TITAN Documentation on the DAQ plone site]&lt;br /&gt;
* https://titan00.triumf.ca/elog/ - TITAN ELOG&lt;br /&gt;
* https://titan00.triumf.ca/triumf_nodeinfo/config.html&lt;br /&gt;
&lt;br /&gt;
=== Contacts ===&lt;br /&gt;
&lt;br /&gt;
* TITAN general: amaudruz olchansk lindner bsmith aniak@triumf.ca&lt;br /&gt;
&lt;br /&gt;
=== Components ===&lt;br /&gt;
&lt;br /&gt;
* MPET http://titan06.triumf.ca:8080/&lt;br /&gt;
* EBIT http://titan05.triumf.ca:8089/&lt;br /&gt;
* EBIT2 (TITAN EC electron capture) https://titan01.triumf.ca:8444&lt;br /&gt;
* CPET  http://titan02.triumf.ca:8081/ - Decommissioned&lt;br /&gt;
* MRTOF (time of flight) - Not a midas DAQ; maintained by TITAN group&lt;br /&gt;
&lt;br /&gt;
=== TITAN Linux DAQ cluster ===&lt;br /&gt;
&lt;br /&gt;
Computers:&lt;br /&gt;
* titan00 - main file server for home directories and data disks, boot server for VME CPUs, runs CentOS7. Located in ISAC2 server room on UPS power.&lt;br /&gt;
* titan01 - MPET DAQ, runs Ubuntu&lt;br /&gt;
* titan05 - EBIT DAQ, runs Ubuntu (replaced titan02)&lt;br /&gt;
* titan07 - mini PC on titan platform that runs cryo/HV, managed by titan group not DAQ&lt;br /&gt;
* lxmpet - MPET VME DAQ&lt;br /&gt;
* lxebit - EBIT VME DAQ&lt;br /&gt;
* lxebit2 - EBIT2 VME DAQ&lt;br /&gt;
* titan-pi04 - Raspberry pi for talking to EBIT&#039;s Fastcom MCA4, standalone, no mounts&lt;br /&gt;
&lt;br /&gt;
Deprecated computers:&lt;br /&gt;
* titan02 (replaced by titan05)&lt;br /&gt;
* titan03 (replaced by titan07)&lt;br /&gt;
* lxcpet - CPET VME DAQ (CPET decommissioned)&lt;br /&gt;
&lt;br /&gt;
Disk space:&lt;br /&gt;
* home directories are on titan00 2x240GB SSD (RAID1), backups on amanda&lt;br /&gt;
* data disks are on titan00 2x4TB (RAID1) /titan/data0&lt;br /&gt;
* zfs mirror 2x240GB SSD (RAID1) on titan05&lt;br /&gt;
&lt;br /&gt;
Nodeinfo:&lt;br /&gt;
* https://titan00.triumf.ca/triumf_nodeinfo/config.html&lt;br /&gt;
&lt;br /&gt;
Disk quota report:&lt;br /&gt;
* https://titan00.triumf.ca/quotareport/quota.html&lt;br /&gt;
&lt;br /&gt;
== Links to DAQ Instructions ==&lt;br /&gt;
&lt;br /&gt;
* [[TITAN DAQ General Documentation]] &lt;br /&gt;
** [[MPET DAQ|MPET DAQ Instructions]]&lt;br /&gt;
** [[EBIT DAQ|EBIT DAQ instructions]]&lt;br /&gt;
** [[CPET DAQ|CPET DAQ Instructions]]&lt;br /&gt;
** [[EBIT2 DAQ|EBIT2 DAQ Instructions]]&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=TITAN&amp;diff=8201</id>
		<title>TITAN</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=TITAN&amp;diff=8201"/>
		<updated>2025-02-05T23:39:21Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Information on TITAN DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== General info ===&lt;br /&gt;
&lt;br /&gt;
* [http://titan.triumf.ca TITAN Main Web page]&lt;br /&gt;
* [http://daq-plone.triumf.ca/ESI/titan TITAN Documentation on the DAQ plone site]&lt;br /&gt;
* https://titan00.triumf.ca/elog/ - TITAN ELOG&lt;br /&gt;
* https://titan00.triumf.ca/triumf_nodeinfo/config.html&lt;br /&gt;
&lt;br /&gt;
=== Contacts ===&lt;br /&gt;
&lt;br /&gt;
* TITAN general: amaudruz olchansk lindner bsmith aniak@triumf.ca&lt;br /&gt;
&lt;br /&gt;
=== Components ===&lt;br /&gt;
&lt;br /&gt;
* MPET http://titan06.triumf.ca:8080/&lt;br /&gt;
* EBIT http://titan05.triumf.ca:8089/&lt;br /&gt;
* EBIT2 (TITAN EC electron capture) https://titan01.triumf.ca:8444&lt;br /&gt;
* CPET  http://titan02.triumf.ca:8081/ - Decommissioned&lt;br /&gt;
* MRTOF (time of flight) - Not a midas DAQ; maintained by TITAN group&lt;br /&gt;
&lt;br /&gt;
=== TITAN Linux DAQ cluster ===&lt;br /&gt;
&lt;br /&gt;
Computers:&lt;br /&gt;
* titan00 - main file server for home directories and data disks, boot server for VME CPUs, runs CentOS7. Located in ISAC2 server room on UPS power.&lt;br /&gt;
* titan01 - MPET DAQ, runs Ubuntu&lt;br /&gt;
* titan05 - EBIT DAQ, runs Ubuntu (replaced titan02)&lt;br /&gt;
* titan07 - mini PC on titan platform that runs cryo/HV, managed by titan group not DAQ&lt;br /&gt;
* lxmpet - MPET VME DAQ&lt;br /&gt;
* lxebit - EBIT VME DAQ&lt;br /&gt;
* lxcpet - CPET VME DAQ&lt;br /&gt;
* lxebit2 - EBIT2 VME DAQ&lt;br /&gt;
* titan-pi04 - Raspberry pi for talking to EBIT&#039;s Fastcom MCA4, standalone, no mounts&lt;br /&gt;
&lt;br /&gt;
Deprecated computers:&lt;br /&gt;
* titan02 (replaced by titan05)&lt;br /&gt;
* titan03 (replaced by titan07)&lt;br /&gt;
&lt;br /&gt;
Disk space:&lt;br /&gt;
* home directories are on titan00 2x240GB SSD (RAID1), backups on amanda&lt;br /&gt;
* data disks are on titan00 2x4TB (RAID1) /titan/data0&lt;br /&gt;
* zfs mirror 2x240GB SSD (RAID1) on titan05&lt;br /&gt;
&lt;br /&gt;
Nodeinfo:&lt;br /&gt;
* https://titan00.triumf.ca/triumf_nodeinfo/config.html&lt;br /&gt;
&lt;br /&gt;
Disk quota report:&lt;br /&gt;
* https://titan00.triumf.ca/quotareport/quota.html&lt;br /&gt;
&lt;br /&gt;
== Links to DAQ Instructions ==&lt;br /&gt;
&lt;br /&gt;
* [[TITAN DAQ General Documentation]] &lt;br /&gt;
** [[MPET DAQ|MPET DAQ Instructions]]&lt;br /&gt;
** [[EBIT DAQ|EBIT DAQ instructions]]&lt;br /&gt;
** [[CPET DAQ|CPET DAQ Instructions]]&lt;br /&gt;
** [[EBIT2 DAQ|EBIT2 DAQ Instructions]]&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR&amp;diff=7978</id>
		<title>BNMR</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR&amp;diff=7978"/>
		<updated>2024-10-02T21:33:18Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: /* Tasks to be done before each beamtime */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Pagelinks}}&lt;br /&gt;
&lt;br /&gt;
== BNMR and BNQR Experiments at TRIUMF ==&lt;br /&gt;
This is the main page of the documentation for the Data Acquisition System (DAQ) for the BetaNMR (BNMR) and BetaNQR (BNQR) experiments at TRIUMF&lt;br /&gt;
&lt;br /&gt;
[[:Category:BNMR|Click here for a full list of all the pages in the BNMR documentation]].&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
The Data Acquisition System is based on the [https://midas.triumf.ca/MidasWiki/index.php/Midas_documentation MIDAS] data acquisition package. &lt;br /&gt;
&lt;br /&gt;
There are two separate &#039;&#039;&#039;beamlines&#039;&#039;&#039;, BNMR and BNQR, each with its own experimental setup :&lt;br /&gt;
&lt;br /&gt;
* {{bnmr}} running on the BNMR high-voltage platform&lt;br /&gt;
* {{bnqr}} running on the BNQR high-voltage platform&lt;br /&gt;
&lt;br /&gt;
Each experimental setup has its own  [[#Hardware Components]] (i.e. a VME crate containing DAQ modules).  Each runs as a separate MIDAS experiment named {{bnmqr|join=or}}. DAQ software specific to these experiments (MIDAS clients) run the experiments - see [[#Software Components]]. Experimenters control the experiment using the MIDAS Web Server (mhttpd).&lt;br /&gt;
  &lt;br /&gt;
== Beam Control ==&lt;br /&gt;
The main TRIUMF EPICS Control System is used to control the beam, which can be switched to either experiment&#039;s &#039;&#039;&#039;beamline&#039;&#039;&#039;.  There are two &#039;&#039;&#039;Beam Modes&#039;&#039;&#039; that the experiments can be run in:&lt;br /&gt;
&lt;br /&gt;
;     [[BNMR Dual Channel Mode #Single Channel Mode|single channel mode]]&lt;br /&gt;
: where the beam is sent to one beamline (channel) only, either BNMR or BNQR. Only &#039;&#039;&#039;one&#039;&#039;&#039; of the DAQ systems &amp;lt;span style=&amp;quot;color:#7b68ee; font-style=italic&amp;quot;&amp;gt;bnmr &amp;lt;/span&amp;gt; or &amp;lt;span style=&amp;quot;color:#20b2aa; font-style=italic&amp;quot;&amp;gt;bnqr&amp;lt;/span&amp;gt; is active.&lt;br /&gt;
;    [[BNMR Dual Channel Mode|dual channel mode]]&lt;br /&gt;
: where the beam is switched between the two beamlines (channels) BNMR and BNQR at regular intervals. &#039;&#039;&#039;Both&#039;&#039;&#039; DAQ systems  &amp;lt;span style=&amp;quot;color:#7b68ee; font-style=italic&amp;quot;&amp;gt;bnmr &amp;lt;/span&amp;gt; and &amp;lt;span style=&amp;quot;color:#20b2aa; font-style=italic&amp;quot;&amp;gt;bnqr&amp;lt;/span&amp;gt; are active.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Experimental modes ==&lt;br /&gt;
For both experiments, two types of environment are defined (cf MUSR experiments):&lt;br /&gt;
&lt;br /&gt;
*    &#039;&#039;&#039;Integral or TI (Type 1)&#039;&#039;&#039;&lt;br /&gt;
*    &#039;&#039;&#039;Time Differential or TD (Type 2)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
There are two separate concepts that use similar naming schemes (e.g. 1f, 20) - the timing of pulses issued by the PPG and the name of the overall experimental mode. The overall mode determines both which timing scheme is run, as well as which hardware is scanned during the run (e.g. RF frequency, Na cell voltage). Multiple experimental modes may use the same PPG timing scheme (e.g. modes 1c, 1d, 1e, 1n use the PPG timing scheme called 1n).&lt;br /&gt;
&lt;br /&gt;
Below is a full list of experimental modes, with the most common ones highlighted in bold. More details about each mode can be found on the [https://isdaq01.triumf.ca:8447/?cmd=custom&amp;amp;page=Modes BNMR mode changer] page and the [https://isdaq01.triumf.ca:8448/?cmd=custom&amp;amp;page=Modes BNQR mode changer] page.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Experimental modes&lt;br /&gt;
|-&lt;br /&gt;
! Mode name !! PPG timing !! BNMR? !! BNQR? !! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;10&#039;&#039;&#039; || 10 || &amp;amp;#10003; || &amp;amp;#10003; || No RF, nothing scanned&lt;br /&gt;
|-&lt;br /&gt;
| 1a || 1a || &amp;amp;#10003; || &amp;amp;#10003; || Scan RF frequency&lt;br /&gt;
|-&lt;br /&gt;
| 1b || 1b || &amp;amp;#10003; || &amp;amp;#10003; || Scan RF frequency&lt;br /&gt;
|-&lt;br /&gt;
| 1c || 1n || &amp;amp;#10003; || &amp;amp;#10003; || Scan settings on a Camp device&lt;br /&gt;
|-&lt;br /&gt;
| 1d || 1n || &amp;amp;#10003; || &amp;amp;#10003; || Scan the laser intensity&lt;br /&gt;
|-&lt;br /&gt;
| 1e || 1n ||  || &amp;amp;#10003; || Scan the magnetic field strength&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;1f&#039;&#039;&#039; || 1f || &amp;amp;#10003; || &amp;amp;#10003; || Scan RF frequency&lt;br /&gt;
|-&lt;br /&gt;
| 1g || 20 || &amp;amp;#10003; || &amp;amp;#10003; || Scan RF frequency&lt;br /&gt;
|-&lt;br /&gt;
| 1j || 20 || &amp;amp;#10003; || &amp;amp;#10003; || Scan settings on a Camp device&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;1n&#039;&#039;&#039; || 1n || &amp;amp;#10003; || &amp;amp;#10003; || Scan the Rb cell voltage or any other EPICS device&lt;br /&gt;
|-&lt;br /&gt;
| 1w || 1w || &amp;amp;#10003; || || Parametric scan of RF frequencies&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;1x&#039;&#039;&#039; || 1f || &amp;amp;#10003; || &amp;amp;#10003; || Scan RF frequency with one region at higher resolution&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;20&#039;&#039;&#039; || 20 || &amp;amp;#10003; || &amp;amp;#10003; || Nothing scanned&lt;br /&gt;
|-&lt;br /&gt;
| 2a || 2a || &amp;amp;#10003; || &amp;amp;#10003; || Scan RF frequency&lt;br /&gt;
|-&lt;br /&gt;
| 2b || 2b || &amp;amp;#10003; || &amp;amp;#10003; || Scan RF frequency&lt;br /&gt;
|-&lt;br /&gt;
| 2d || 1b || &amp;amp;#10003; || &amp;amp;#10003; || RF on, nothing scanned&lt;br /&gt;
|-&lt;br /&gt;
| 2e || 2e || &amp;amp;#10003; || &amp;amp;#10003; || Scan RF frequency&lt;br /&gt;
|-&lt;br /&gt;
| 2f || 2f || &amp;amp;#10003; || &amp;amp;#10003; || Scan RF frequency&lt;br /&gt;
|-&lt;br /&gt;
| 2h || 20 ||  || &amp;amp;#10003; || Read alpha channels from scalers&lt;br /&gt;
|-&lt;br /&gt;
| 2s || 2s || &amp;amp;#10003; ||  || Spin-echo&lt;br /&gt;
|-&lt;br /&gt;
| 2w || 2w || &amp;amp;#10003; ||  || RF Wurst modulation&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Any of these modes may be run in [[#Beam Control|single channel mode]]. Only Type 2 modes may be run in [[#Beam Control|dual channel mode]].&lt;br /&gt;
&lt;br /&gt;
Users change which mode is active using the webpages for each experiment, which in turn interact with the [[#Software_Components|mode changer]] python script.&lt;br /&gt;
&lt;br /&gt;
== Hardware Components ==&lt;br /&gt;
&lt;br /&gt;
DAQ hardware components for each DAQ system (BNMR/BNQR) include the following VME modules:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=1 cellspacing=3 cellpadding=10&lt;br /&gt;
|+ &amp;lt;b&amp;gt;&amp;lt;center&amp;gt; Table 2: VME Modules for each Experiment&amp;lt;/center&amp;gt;&amp;lt;/b&amp;gt;&lt;br /&gt;
|- &lt;br /&gt;
! Module  !! Description  !! VME Base Address !! BNMR? !! BNQR? !! Manual&lt;br /&gt;
|-&lt;br /&gt;
| SIS3801 version E || multichannel scaler  A || 0x2800 || &amp;amp;#10003; || ||rowspan=&amp;quot;2&amp;quot; | [[Media:Sis3801_V5_to_VE.pdf|SIS3801 manual (PDF)]]&lt;br /&gt;
|-&lt;br /&gt;
| SIS3801 version E || multichannel scaler  B || 0x1800 || &amp;amp;#10003; || &lt;br /&gt;
|- &lt;br /&gt;
| SIS3820  || multichannel scaler  B || 0x38000000 ||  || &amp;amp;#10003; || [[Media:Sis3820-M-0-001-v186-scaler.pdf|SIS3820 manual (PDF)]]&lt;br /&gt;
|- &lt;br /&gt;
| PPG (Pulseblaster)|| Pulse Programmer  ||0x8000 || &amp;amp;#10003; || &amp;amp;#10003;|| [[Media:PPG.pdf|PPG manual (PDF)]] [[Media:Spincore.pdf|Spincore Pulseblaster (PDF)]]&lt;br /&gt;
|- &lt;br /&gt;
| PSM || Pol Synthesizer module (RF)||  0x820000 ||  || &amp;amp;#10003; ||rowspan=&amp;quot;3&amp;quot; |[[BNMR:_PSM_(Pol_Synth_Module)|PSM]]&lt;br /&gt;
|-&lt;br /&gt;
| PSMII || Pol Synthesizer module II (RF) || 0x820000 || || &lt;br /&gt;
|- &lt;br /&gt;
| PSMIII|| Pol Synthesizer module III(RF) || 0x820000 || &amp;amp;#10003; || &lt;br /&gt;
|- &lt;br /&gt;
| NIMIO32 || Input/Output Register  ||0x100000 || &amp;amp;#10003; || &amp;amp;#10003; || [[VME-NIMIO32| NIMIO32]]&lt;br /&gt;
|- &lt;br /&gt;
| MVME162 || 68040 board (VxWorks) that runs CAMP  || || &amp;amp;#10003; (bnmrvw) || &amp;amp;#10003; (polvw) || &amp;lt;div id=VMIC&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
|- &lt;br /&gt;
| VMIC|| Linux machine in VME crate that runs frontend || || &amp;amp;#10003; (lxbnmr) || &amp;amp;#10003; (lxbnqr) || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The connections between the DAQ VME Modules are shown in [[BNMR DAQ Hardware Connections]].&lt;br /&gt;
&lt;br /&gt;
== Software Components ==&lt;br /&gt;
The DAQ system is based on the [https://midas.triumf.ca/MidasWiki/index.php/Midas_documentation MIDAS] package. Data acquisition software to run the  {{bnmqr|join=and}} experiments has been written to run under MIDAS. This includes the frontend, custom logger etc. This software is mostly common to both experiments, with the differences between each experiment handled by Midas ODB settings (most things) and a compile-time flag (choosing whether to build the febnmr or febnqr frontend).&lt;br /&gt;
&lt;br /&gt;
The experiment is controlled using the MIDAS webserver (mhttpd). Due to the large number of experimental parameters required, Midas custom pages have been written for the experimenters to control and monitor their experiment. &lt;br /&gt;
&lt;br /&gt;
The custom logger (mdarc/midbnmr) saves the data into MUSR MUD format files, and the MUSR CAMP slow control system is used for slow controls. Analysis is done by physica.&lt;br /&gt;
&lt;br /&gt;
The DAQ software components are started by the script &#039;&#039;start-all&#039;&#039; and stopped by the script &#039;&#039;kill-all&#039;&#039;. These include &#039;&#039;&#039;standard MIDAS utilities&#039;&#039;&#039; (e.g. [https://midas.triumf.ca/MidasWiki/index.php/Mhttpd mhttpd], [https://midas.triumf.ca/MidasWiki/index.php/Mlogger mlogger], [https://midas.triumf.ca/MidasWiki/index.php/Mserver mserver]) as well as components specific to the  {{bnmqr|join=and}} experiments.&lt;br /&gt;
&lt;br /&gt;
The main DAQ software components specific to the {{bnmqr|join=and}} experiments are shown in the table below. A full ist can be found on the [[BNMR:_Software_overview|software overview page]].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=1 cellspacing=3 cellpadding=2 style=&amp;quot;background-color:#f0f0f5&amp;quot;&lt;br /&gt;
|+  &amp;lt;b&amp;gt;&amp;lt;center&amp;gt; Table 3: DAQ Software Components&amp;lt;/center&amp;gt;&amp;lt;/b&amp;gt;&lt;br /&gt;
|- style=&amp;quot;background-color: #e0e0eb;&amp;quot;&lt;br /&gt;
! Component !! Host !! Experiment !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
|- &lt;br /&gt;
| colspan=4| &#039;&#039;Midas frontends&#039;&#039;&lt;br /&gt;
|-  style=&amp;quot;background-color:floralwhite;&amp;quot;&lt;br /&gt;
| [[BNMR: frontend|febnmr_32bit.exe]] || &#039;&#039;&#039;lxbnmr&#039;&#039;&#039; || bnmr || rowspan=2| the &#039;&#039;&#039;frontend&#039;&#039;&#039; sets up, reads out hardware modules, sends histograms.&amp;lt;br&amp;gt;The frontend code for both experiments is identical.&lt;br /&gt;
|-  style=&amp;quot;background-color:floralwhite;&amp;quot;&lt;br /&gt;
| [[BNMR: frontend|febnqr_32bit.exe]] || &#039;&#039;&#039;lxbnqr&#039;&#039;&#039; || bnqr&lt;br /&gt;
|- &lt;br /&gt;
| colspan=4| &#039;&#039;Midas clients - configuration&#039;&#039;&lt;br /&gt;
|- style=&amp;quot;background-color:mintcream&amp;quot;&lt;br /&gt;
| [[BNMR:_Mode_changer|mode_changer.py]]|| isdaq01|| both || changes between experimental modes and between real/test runs&lt;br /&gt;
|- style=&amp;quot;background-color:mintcream&amp;quot;&lt;br /&gt;
| [[BNMR:_RF_calculator|rf_calculator_fe.py]]|| isdaq01|| both || generates PPG program based on user-specified ODB parameters; reports calculated quantities in the ODB; sets up links in the ODB that should be stored in MUD files&lt;br /&gt;
|- style=&amp;quot;background-color:mintcream&amp;quot;&lt;br /&gt;
| [[BNMR:_PPG_compiler|ppg_compiler_fe.py]]|| isdaq01|| both || low-level conversion of PPG program to PPG bytecode&lt;br /&gt;
|- &lt;br /&gt;
| colspan=4| &#039;&#039;Midas clients - logging&#039;&#039;&lt;br /&gt;
|- style=&amp;quot;background-color: mintcream;&amp;quot;&lt;br /&gt;
| [[BNMR:_Data_Logging|bnxr_logger.exe]]|| isdaq01|| both|| writes data to MUD files. Reads information from midas banks (for scaler histograms), EPICS, and CAMP&lt;br /&gt;
|- style=&amp;quot;background-color: mintcream;&amp;quot;&lt;br /&gt;
| [[BNMR:_Data_Logging#Cleaning_up_if_end-of-run_fails|logger_cleanup.exe]]|| isdaq01|| both|| cleans up and archives any saved run files that were not properly archived. Run by user occasionally as needed.&lt;br /&gt;
|- style=&amp;quot;background-color:mintcream&amp;quot;&lt;br /&gt;
| [[BNMR:_Data_Logging#Run_comments|run_comment_editor.py ]]|| isdaq01|| both || responds to comments written by user in text box on the status page, saving to disk and/or midas banks&lt;br /&gt;
|- &lt;br /&gt;
| colspan=4| &#039;&#039;Other&#039;&#039;&lt;br /&gt;
|- style=&amp;quot;background-color:#ffe6e6;&amp;quot;&lt;br /&gt;
| [[BNMR: autorun|autorun]]|| isdaq01|| both|| automatic run controller&lt;br /&gt;
|- style=&amp;quot;background-color:#ffe6e6&amp;quot;&lt;br /&gt;
| [[BNMR: Scripts|scripts]]|| isdaq01 || both|| scripts perform important functions e.g. kill-all, start-all. Scripts run at the begin and end of each run send information to the elog etc. &lt;br /&gt;
|- style=&amp;quot;background-color:#ffe6e6&amp;quot;&lt;br /&gt;
| rowspan=2| [[BNMR: CAMP|camp]] || &#039;&#039;&#039;bnmrvw&#039;&#039;&#039; || bnmr || rowspan=2| MUSR slow control system&lt;br /&gt;
|- style=&amp;quot;background-color:#ffe6e6&amp;quot;&lt;br /&gt;
| &#039;&#039;&#039;polvw&#039;&#039;&#039; || bnqr&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Click the links in the above table for more details of each program.&lt;br /&gt;
&lt;br /&gt;
Not listed above are various [[BNMR:_Tests|automated test]] programs for both the C++ and python programs. There are also some interactive test programs for [[BNMR: Hardware Debugging|debugging hardware issues]].&lt;br /&gt;
&lt;br /&gt;
Note that the DAQ was rewritten in 2020. Details of the rewritten in 2020. Details of the differences between the new DAQ (documented here) and legacy DAQ (documentation removed) can be found on the [[BNMR:_Rewrite_2020|2020 rewrite]] page.&lt;br /&gt;
&lt;br /&gt;
== DAQ  Summary ==&lt;br /&gt;
;The VMIC front end computer &lt;br /&gt;
* runs the [[BNMR: frontend|frontend code]]&#039;&#039;&#039; which&lt;br /&gt;
**   controls PSM,PPG, VMEIO, Scaler modules&lt;br /&gt;
**    acquires data from SIS MCS (scaler) module(s), builds [[BNMR: Histograms and Scalers|histograms]]&lt;br /&gt;
**    uses channel access to control EPICS variable(s) (e.g. helicity)&lt;br /&gt;
**    periodically sends the data out into the data buffer&lt;br /&gt;
&lt;br /&gt;
;The host computer (isdaq01)&lt;br /&gt;
* runs all other software components which&lt;br /&gt;
** acquire the data from the data buffer&lt;br /&gt;
** log the data&lt;br /&gt;
** monitor the experiment&lt;br /&gt;
** start/stop runs&lt;br /&gt;
&lt;br /&gt;
== Tasks to be done before each beamtime ==&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;b&amp;gt;If this is the first beamtime of the year&amp;lt;/b&amp;gt;, [[BNMR:_Data_Logging#Resetting_the_run_numbers|create a new data directory and reset the run numbers]].&lt;br /&gt;
* &amp;lt;b&amp;gt;If there have been changes to the code that affect the ODB structure&amp;lt;/b&amp;gt;, [[BNMR:_Mode_changer#Handling_changes_to_the_ODB_structure|ensure saved settings have been updated to contain the new variables]].&lt;br /&gt;
* &amp;lt;b&amp;gt;Always&amp;lt;/b&amp;gt; edit the bnmr user&#039;s cronjob (using &amp;lt;code&amp;gt;crontab -e&amp;lt;/code&amp;gt;) to specify the schedule number and date range to include in the generated Excel file. See the [[BNMR:_Shift_Monitor#beamtime_to_excel.py|supported arguments to beamtime_to_excel.py]] and the [https://mis.triumf.ca/science/schedules.jsf TRIUMF beamtime schedule].&lt;br /&gt;
* &amp;lt;b&amp;gt;Strongly recommended&amp;lt;/b&amp;gt; to try changing between a few common modes (e.g. 20, 1f, 1n, and back to 20) and ensure the run can start (in test mode, not real mode). You may need to disable &amp;quot;switching&amp;quot; checks on the [[BNMR:_Custom_Status_page|status page]] if the beamline is not currently configured for BNMR/BNQR.&lt;br /&gt;
&lt;br /&gt;
== Nomenclature ==&lt;br /&gt;
In this document, &amp;quot; &#039;&#039;bnmr&#039;&#039; or &#039;&#039;bnqr&#039;&#039; &amp;quot; may be written as &amp;quot; &#039;&#039;bn[&#039;&#039;&#039;mq&#039;&#039;&#039;]r&#039;&#039; &amp;quot; &lt;br /&gt;
&lt;br /&gt;
For example,  directories :&lt;br /&gt;
: &amp;lt;span style=&amp;quot;color:#004d4d; font-weight:normal; font-style:italic &amp;quot;&amp;gt;/home/&amp;lt;span style=&amp;quot;font-weight:bold;&amp;quot;&amp;gt;bnmr&amp;lt;/span&amp;gt;/online/&amp;lt;span style=&amp;quot;font-weight:bold;&amp;quot;&amp;gt;bnmr&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color:white&amp;quot;&amp;gt;spc&amp;lt;/span&amp;gt;  and &amp;lt;span style=&amp;quot;color:white&amp;quot;&amp;gt;spc&amp;lt;/span&amp;gt;  &amp;lt;span style=&amp;quot;color:#004d4d; font-weight:normal; font-style:italic &amp;quot;&amp;gt;/home/&amp;lt;span style=&amp;quot;font-weight:bold;&amp;quot;&amp;gt;bnqr&amp;lt;/span&amp;gt;/online/&amp;lt;span style=&amp;quot;font-weight:bold;&amp;quot;&amp;gt;bnqr&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
are referred to by &#039;&#039;&#039;shortcuts&#039;&#039;&#039; such as&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:white&amp;quot;&amp;gt;space&amp;lt;/span&amp;gt; {{Filepath|path=/home/bn&amp;lt;span style=&amp;quot;font-weight:bold;&amp;quot;&amp;gt;[nm]&amp;lt;/span&amp;gt;r/online/b&amp;lt;span style=&amp;quot;font-weight:bold;&amp;quot;&amp;gt;[nm]&amp;lt;/span&amp;gt;r}} &amp;lt;span style=&amp;quot;color:white&amp;quot;&amp;gt;spc&amp;lt;/span&amp;gt; and  &amp;lt;span style=&amp;quot;color:white&amp;quot;&amp;gt;spc&amp;lt;/span&amp;gt; {{Filepath|path=~/online/b&amp;lt;span style=&amp;quot;font-weight:bold;&amp;quot;&amp;gt;[nm]&amp;lt;/span&amp;gt;r}}&lt;br /&gt;
&lt;br /&gt;
Alternatively, these directories may be written as&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; {{Filepath|path=/home/&amp;lt;experiment&amp;gt;/online/&amp;lt;beamline&amp;gt;}}  &lt;br /&gt;
&amp;lt;li&amp;gt; {{Filepath|path=/home/&amp;lt;expt&amp;gt;/online/&amp;lt;beamline&amp;gt;}}  &lt;br /&gt;
&amp;lt;li&amp;gt; {{Filepath|path=~/online/&amp;lt;beamline&amp;gt;}}&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
where {{Filepath|path=&amp;lt;experiment&amp;gt;}} {{Filepath|path=&amp;lt;expt&amp;gt;}} and {{Filepath|path=&amp;lt;beamline&amp;gt;}} are {{bnmqr|join=or}}.&lt;br /&gt;
&lt;br /&gt;
[[Category:BNMR]]&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR:_Data_Logging&amp;diff=7977</id>
		<title>BNMR: Data Logging</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR:_Data_Logging&amp;diff=7977"/>
		<updated>2024-10-02T21:31:09Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: /* Saved data files */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Pagelinks}}&lt;br /&gt;
&lt;br /&gt;
== MUD files ==&lt;br /&gt;
{{bnmqr|join=and}} do not save their data as Midas files, but use [http://musr.ca/mud/mud_fmt.html MUD files] instead (&amp;lt;code&amp;gt;.msr&amp;lt;/code&amp;gt; extension).&lt;br /&gt;
&lt;br /&gt;
Therefore we only use the Midas [https://daq00.triumf.ca/MidasWiki/index.php/Mlogger mlogger] for recording [https://daq00.triumf.ca/MidasWiki/index.php/History_System history] data, not the regular event data.&lt;br /&gt;
&lt;br /&gt;
The key feature to note is that &#039;&#039;&#039;MUD files are not event-based&#039;&#039;&#039;. One can save statistics and histograms, but not complex per-event data. Histograms may be used to a single number per event (the X-axis is event number) or the total counts over an entire run (the X-axis is time-of-flight in ns, for example). Data saved as statistics can include the mean/min/max/std.dev. and more information.&lt;br /&gt;
&lt;br /&gt;
Users analyze MUD files using:&lt;br /&gt;
* the [https://github.com/dfujim/mudpy mudpy] and [https://github.com/dfujim/bdata bdata] python packages (with some GUIs built on top of them)&lt;br /&gt;
* the MUSR/BNMR analyzer program &#039;&#039;physica&#039;&#039;&lt;br /&gt;
* the MUD utility program &#039;&#039;mud_util&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
A couple of python utilities based on &amp;lt;code&amp;gt;bdata&amp;lt;/code&amp;gt; are provided in the bnmr repository, which may be useful when adding new features to the data logger:&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/dump_mud_file.py&amp;lt;/code&amp;gt; dumps the content of a MUD file to screen&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/diff_mud_files.py&amp;lt;/code&amp;gt; compares the content of 2 MUD files&lt;br /&gt;
&lt;br /&gt;
DAQ experts may enable dumping of Midas banks to a Midas file for debugging purposes. The banks written will come from the [[BNMR:_frontend frontend]] program only, and will not contain any EPICS variables, CAMP variables, or any manipulation of histograms performed in the &amp;lt;code&amp;gt;bnxr_logger.exe&amp;lt;/code&amp;gt; program.&lt;br /&gt;
&lt;br /&gt;
== bnxr_logger.exe introduction ==&lt;br /&gt;
The &amp;lt;code&amp;gt;bnxr_logger.exe&amp;lt;/code&amp;gt; program is responsible for collecting data and writing to MUD files.&lt;br /&gt;
 &lt;br /&gt;
Most of the parameters controlling the data logging are found in the ODB at {{Odbpath|path=/MUD Logging}}. Most settings are configured manually, though some are set/computed by the [[BNMR:_RF_calculator|RF calculator]] program and the beginning of each run. &lt;br /&gt;
&lt;br /&gt;
The program gets data from the following sources:&lt;br /&gt;
* [[#Histograms|Histograms]] - read from midas banks sent by the [[BNMR: frontend|frontend]]&lt;br /&gt;
* [[#CAMP|Camp]] - read directly from CAMP&lt;br /&gt;
* [[#EPICS|EPICS]] - read directly from EPICS&lt;br /&gt;
* [[#ODB_variables|ODB variables]] - read directly from the ODB&lt;br /&gt;
* [[#Run_Comments|Run comments]] - read from a text file that is edited via a web interface&lt;br /&gt;
&lt;br /&gt;
More details on each of these is presented further down this page.&lt;br /&gt;
&lt;br /&gt;
== Saved data files ==&lt;br /&gt;
&lt;br /&gt;
The {{bnmqr|join=and}} experiments use the MUSR-style [[BNMR: Run numbering|Run Numbering]] scheme. The data files are named according to the run number. [[BNMR: Run numbering|Real]] data files are archived in the MUSR Data Archive at the end of the run.&lt;br /&gt;
&lt;br /&gt;
During a run, several versions of the .msr (or MUD) data file are retained with a version number appended (in case of any problems with the most recent saved data). A symlink to the most recent version is updated during the run, so analysis programs do not have to concern themselves with the versioning information.&lt;br /&gt;
&lt;br /&gt;
For example, for BNMR run 40362, while the run is in progress, the saved data directory would contain files such as&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lrwxrwxrwx    1 bnmr     bnmr           48   Feb 26 12:09 040362.msr -&amp;gt; /isdaq/data1/bnmr/dlog/current/040362.msr_v27&lt;br /&gt;
-rw-r--r--    1 bnmr     bnmr         4403   Feb 26 12:09 040362.msr_v27&lt;br /&gt;
-rw-r--r--    1 bnmr     bnmr         4403   Feb 26 12:09 040362.msr_v26&lt;br /&gt;
-rw-r--r--    1 bnmr     bnmr         4403   Feb 26 12:09 040362.msr_v25&lt;br /&gt;
-rw-r--r--    1 bnmr     bnmr         4403   Feb 26 12:08 040362.msr_v24&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At end-of-run, normally all earlier versions are purged and the final data file is renamed without the appended version number, and the file archived to the MUSR Data Archive. These steps can be suppressed by setting {{Odbpath|path=/MUD Logging/Global/Settings/Purge and archive at end of run}} to false, for example if the user decides it would be better to keep the version 26 of a file instead of the most recent version 27.&lt;br /&gt;
&lt;br /&gt;
Using the same example as before, after the run the saved data directory would contain:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-rw-r--r--    1 bnmr     bnmr         4399 Feb 26 12:10 040362.msr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Archiving ===&lt;br /&gt;
&lt;br /&gt;
The ODB keys {{Odbpath|path=Archiver task}} and {{Odbpath|path=Archiver dir}} in {{Odbpath|path=/MUD Logging/Global/Settings}} determine where files for &amp;quot;real&amp;quot; runs get copied to after a run is complete. This is normally just an &amp;lt;code&amp;gt;scp&amp;lt;/code&amp;gt; to a directory on &amp;lt;code&amp;gt;cmms.triumf.ca&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Nuking a run ===&lt;br /&gt;
&lt;br /&gt;
If the user decides that a run is irredeemable, they may choose to &amp;quot;nuke&amp;quot; the run and start again. This involves deleting ALL the files that have been written, pretending that the run never happened. The same run number will then be used for the next run. Users appreciate this feature as it allows analysis to occur on contiguous ranges of run numbers.&lt;br /&gt;
&lt;br /&gt;
Indicating that a run should be nuked is done with the {{Odbpath|path=/MUD Logging/Global/Settings/Nuke this run}} flag in the ODB, which is generally achieved by the user clicking the &amp;quot;Nuke ⚠️&amp;quot; button on the [[BNMR: Custom Status page|Status page]]&lt;br /&gt;
&lt;br /&gt;
=== Cleaning up if end-of-run fails ===&lt;br /&gt;
&lt;br /&gt;
The {{Client|name=logger_cleanup.exe}} program can be used if {{Client|name=bnxr_logger.exe}} crashes during a run and fails to perform the standard cleanup/archive duties at the end of a run.&lt;br /&gt;
&lt;br /&gt;
It effectively just runs the same code as the main MUD logger runs at the end of the run, but allows the user to specify any run number in the past if they wish.&lt;br /&gt;
&lt;br /&gt;
It will:&lt;br /&gt;
* Delete any temporary files that are no longer needed&lt;br /&gt;
* Archive the final file if this was a &amp;quot;real&amp;quot; run (not a &amp;quot;test&amp;quot; run)&lt;br /&gt;
&lt;br /&gt;
Usage is:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      logger_cleanup.exe&lt;br /&gt;
           [-r Run number]&lt;br /&gt;
                        Run number of run to be cleaned up and/or archived. Defaults to the most recent run.&lt;br /&gt;
&lt;br /&gt;
           [-h Hostname  ]&lt;br /&gt;
                      hostname is supplied only for a remote host&lt;br /&gt;
&lt;br /&gt;
           [-e Experiment]&lt;br /&gt;
                       experiment name (default is given by environment variable MIDAS_EXPT_NAME)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Resetting the run numbers ===&lt;br /&gt;
&lt;br /&gt;
BNMR and BNQR reuse [[BNMR:_Run_numbering|run numbers]] each year (i.e. you need to specify both the year and run number to identify a dataset).&lt;br /&gt;
&lt;br /&gt;
At the start of each year, you need to change where the data is being written to. This will automatically reset the run numbers to the new values for the year as well&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /isdaq/data1/&amp;lt;expt&amp;gt;/dlog&lt;br /&gt;
mkdir &amp;lt;year&amp;gt;&lt;br /&gt;
rm current&lt;br /&gt;
ln -s &amp;lt;year&amp;gt; current&lt;br /&gt;
# Use the web interface to toggle between real and test modes (without starting a run), and verify that the run numbers are 30000/40000 (for BNMR) and 30000/45000 (for BNQR).&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== bnxr_logger.exe details ==&lt;br /&gt;
&lt;br /&gt;
The code for the MUD logger is found in the bnmr repository at &amp;lt;code&amp;gt;bnxr_common/logging&amp;lt;/code&amp;gt;. {{bnmqr|join=and}} are very similar, so the executable is almost identical for both (just an &amp;lt;code&amp;gt;#ifdef&amp;lt;/code&amp;gt; for the default ODB settings to use). The main configuration is all done through ODB keys.&lt;br /&gt;
&lt;br /&gt;
The program is built as part of the main build (&amp;lt;code&amp;gt;cd build; make install&amp;lt;/code&amp;gt; from the bnmr repository).&lt;br /&gt;
&lt;br /&gt;
The general functions performed by the program are:&lt;br /&gt;
* Read data sent by the [[BNMR: frontend|frontend]] and process it. This includes both the data from the scalers as well as metadata like the current cycle number.&lt;br /&gt;
* Read data from EPICS and CAMP, either periodically or each time we get data from the [[BNMR: frontend|frontend]].&lt;br /&gt;
* Write data to a MUD file periodically during the run.&lt;br /&gt;
&lt;br /&gt;
=== Histograms ===&lt;br /&gt;
&lt;br /&gt;
See the [[BNMR:_Histograms_and_Scalers#Histograms|histograms and scalers]] page for more details.&lt;br /&gt;
&lt;br /&gt;
Settings are stored in the ODB at {{Odbpath|path=/MUD Logging/Histos/Settings}}.&lt;br /&gt;
&lt;br /&gt;
=== CAMP ===&lt;br /&gt;
&lt;br /&gt;
[[BNMR:_CAMP|CAMP]] data is logged in two separate sections of the MUD file - in the run description and as independent variables. The {{Client|name=bnxr_logger.exe}} program connects directly to the CAMP server and reads the values from there.&lt;br /&gt;
&lt;br /&gt;
==== Run description ====&lt;br /&gt;
&lt;br /&gt;
The MUD run description section has entries for the magnetic field strength and temperature of the sample. This data can be exposed to users when searching for data files taken previously.&lt;br /&gt;
&lt;br /&gt;
ODB settings in {{Odbpath|path=/MUD Logging/Run description/Settings}} specify whether to read the magnetic field and/or temperature from CAMP, and if so, which instrument to read from. CAMP can automatically compute the standard deviation of variables throughout a run, and the user can choose to record this value in the file too.&lt;br /&gt;
&lt;br /&gt;
Only a single number gets written to the run description for each variable - the average value throughout the run.&lt;br /&gt;
&lt;br /&gt;
NOTE: Automatic CAMP variables to be logged must be set &#039;&#039;loggable&#039;&#039; in the CAMP CUI - see [[#Set CAMP variable loggable]].&lt;br /&gt;
&lt;br /&gt;
==== Independent variables ====&lt;br /&gt;
&lt;br /&gt;
Other CAMP variables can be logged during a run too. &lt;br /&gt;
&lt;br /&gt;
ODB settings in {{Odbpath|path=/MUD Logging/Camp/Settings}} define whether CAMP variables should be written as histograms of readings or just average values. The general configuration is to log a per-cycle histograms for T1 (TI) modes and just average values for T2 (TD) modes.&lt;br /&gt;
&lt;br /&gt;
The user does not list each individual CAMP variable to be logged in the ODB, but instead lists which &amp;quot;categories&amp;quot; of variables should be included in the MUD file (e.g. &amp;lt;code&amp;gt;log_mdarc&amp;lt;/code&amp;gt;). The mapping between CAMP variable and &amp;quot;category&amp;quot; is done via CAMP itself (see next section).&lt;br /&gt;
&lt;br /&gt;
This CAMP data is stored as &amp;quot;independent variables&amp;quot; in the MUD file, keyed by the CAMP path (of format like &amp;lt;code&amp;gt;/Magnet/mag_field&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Set CAMP variable loggable ====&lt;br /&gt;
&lt;br /&gt;
All CAMP variables to be logged must be set loggable in the [[BNMR:_CAMP#CAMP User Interface|CAMP user interface]]. This includes the parameters to be used in the run description.&lt;br /&gt;
&lt;br /&gt;
The loggable categories are shown in Table 1.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; width=50% style=&amp;quot;border-collapse:collapse; color:black; background-color:silver; text-align:center&amp;quot;&lt;br /&gt;
|+ Table 1 : CAMP logging for Type 1 and Type 2 runs&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; style=&amp;quot;background-color:silver; text-align:left&amp;quot;|Set logging !!colspan=2 style=&amp;quot;text-align:center&amp;quot;| Variable Logged for&lt;br /&gt;
|- style=&amp;quot;text-align:center;background-color:silver;font-weight:bold;&amp;quot;&lt;br /&gt;
! style=&amp;quot;text-align:center;&amp;quot; | Type1 (I-MUSR)!! style=&amp;quot;text-align:center; &amp;quot;| Type2 (TD-MUSR)&lt;br /&gt;
|- style=&amp;quot;background-color:springgreen;text-align:center&amp;quot;&lt;br /&gt;
| style=&amp;quot;text-align:left&amp;quot;| log_mdarc&lt;br /&gt;
| Y&lt;br /&gt;
| Y&lt;br /&gt;
|-  style=&amp;quot;background-color:yellow;&amp;quot;&lt;br /&gt;
| style=&amp;quot;text-align:left&amp;quot;| log_mdarc_td || rowspan=&amp;quot;2&amp;quot;  style=&amp;quot;background-color:silver;text-align:center&amp;quot;| N || rowspan=&amp;quot;2&amp;quot;| Y &lt;br /&gt;
|-  style=&amp;quot;background-color:yellow;&amp;quot;&lt;br /&gt;
| style=&amp;quot;text-align:left&amp;quot;| log_td_musr&lt;br /&gt;
|- style=&amp;quot;background-color:skyblue;&amp;quot;&lt;br /&gt;
| style=&amp;quot;text-align:left&amp;quot;|log_mdarc_ti || rowspan=2 | Y || rowspan=2  style=&amp;quot;background-color:silver;text-align:center&amp;quot;| N &lt;br /&gt;
|- style=&amp;quot;background-color:lightblue;&amp;quot;&lt;br /&gt;
| style=&amp;quot;text-align:left&amp;quot;|log_i_musr&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Checking which variables will be logged ====&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Logging&amp;quot; custom webpage includes a feature that allows the user to see which CAMP variables will be logged given the current ODB and CAMP settings. This is implemented using the midas JRPC system to talk to the &amp;lt;code&amp;gt;bnxr_logger.exe&amp;lt;/code&amp;gt; program, which returns the list of variables.&lt;br /&gt;
&lt;br /&gt;
==== CAMP error file ====&lt;br /&gt;
CAMP keeps a log file for errors. This can be found in {{File|name=camp_srv.log}} at path {{Filepath|path=/home/musrdaq/musr/camp/[&#039;&#039;camphost&#039;&#039;]/log/}} where &#039;&#039;camphost&#039;&#039; is &#039;&#039;bnmrvw&#039;&#039; for  {{bnmr}} or &#039;&#039;polvw &#039;&#039;for  {{bnqr}}. Error counts can also be found on the CAMP CUI&lt;br /&gt;
under R.Errors and W.Errors in [[#CAMP User Interface|Figure 1]] above.&lt;br /&gt;
&lt;br /&gt;
e.g.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 tail -f ~musrdaq/musr/camp/bnmrvw/log/camp_srv.log&lt;br /&gt;
[JUN 26 17:46:41:2018] camp_srv: instrument &#039;biasV&#039; not online in insIfWriteVerify /biasV | failed 2 attempts&lt;br /&gt;
[JUN 26 17:46:43:2018] camp_srv: instrument &#039;biasV&#039; not online in insIfWriteVerify /biasV | failed 2 attempts&lt;br /&gt;
[JUN 26 17:46:45:2018] camp_srv: instrument &#039;biasV&#039; not online in insIfWriteVerify /biasV | failed 2 attempts&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== EPICS ===&lt;br /&gt;
&lt;br /&gt;
See [[BNMR: EPICS|the EPICS page]] for an overview of EPICS in {{bnmqr|join=and}}.&lt;br /&gt;
&lt;br /&gt;
Users directly specify which EPICS variables should be logged in {{Odbpath|path=/MUD Logging/Epics/Settings}} (or by using the relevant bit of the [[BNMR: Custom Logging page|Custom Logging page]]). The {{Client|name=bnxr_logger.exe}} program connects directly to EPICS and reads the values itself.&lt;br /&gt;
&lt;br /&gt;
The code allows for deciding whether to store a histogram of readings throughout the run or just summary statistics. In general, a histogram is written for TI runs, where the scaler data is being store in a per-cycle style; the histograms for the EPICS data and scaler data will be the same length, with one entry per PPG cycle. To avoid overloading the EPICS server, we can read from it periodically rather than every time a new PPG cycle starts. Each time we read a value, we will apply it to all the cycles that happened since we last read.&lt;br /&gt;
&lt;br /&gt;
EPICS data is stored as &amp;quot;independent variables&amp;quot; in the MUD file, keyed by the PV name (of format like &amp;lt;code&amp;gt;ILE2:BIAS15:RDVOL&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Run comments ===&lt;br /&gt;
&lt;br /&gt;
When a run is in progress, the user is presented with a &amp;lt;code&amp;gt;textarea&amp;lt;/code&amp;gt; element on the [[BNMR: Custom Status page|status page]]. This allows the user to note any critical information about the run that should be stored in the file, not just in a separate logbook. The textarea is hooked up to the {{Client|name=run_comment_editor.py}} program using Midas JRPC. The python program just writes a text file on disk in the directory specified by {{Odbpath|path=/Logger/Data dir}}. Other settings for the python program are in {{Odbpath|path=/Equipment/RunComments/Settings}}.&lt;br /&gt;
&lt;br /&gt;
When it is time for the {{Client|name=bnxr_logger.exe}} program to write a new MUD file, it just reads the file that was written by the python program. There are a couple of extra settings in {{Odbpath|path=/MUD Logging/TextFileComments/Settings}}.&lt;br /&gt;
&lt;br /&gt;
MUD files have a section dedicated to storing run comments.&lt;br /&gt;
&lt;br /&gt;
=== ODB variables ===&lt;br /&gt;
&lt;br /&gt;
==== Independent variables ====&lt;br /&gt;
&lt;br /&gt;
ODB variables specifying the configuration of the run are stored as independent variables in the MUD file. The user does not specify directly which variables log for each mode; the decision is made by the [[BNMR:_RF_calculator|RF calculator]] program.&lt;br /&gt;
&lt;br /&gt;
In particular, the variables to be saved are stored as ODB links in the {{Odbpath|path=/Equipment/RFCalculator/Computed/Mud links/PPG/PPG20}} directory (for mode 20; similar names for other modes). The definition of the links is in &amp;lt;code&amp;gt;mud_ind_var_links.py&amp;lt;/code&amp;gt;, which is included by {{Client|name=rf_calculator_fe.py}}. This keeps all the mode-specific complexity in one place, and in a language that is more expressive. The C++ code in {{Client|name=bnxr_logger.exe}} simply has to iterate over all the links in the relevant directory.&lt;br /&gt;
&lt;br /&gt;
Note the following conversions between C++/ODB data types and MUD independent variables:&lt;br /&gt;
* Arrays/vectors are not supported (in principle we could store a histogram, but users have not requested that yet)&lt;br /&gt;
* Numbers are stored in the &amp;lt;code&amp;gt;mean&amp;lt;/code&amp;gt; member of the MUD variable.&lt;br /&gt;
* Strings are stored in the &amp;lt;code&amp;gt;units&amp;lt;/code&amp;gt; member of the MUD variable.&lt;br /&gt;
* Booleans are stored with 1/0 in the &amp;lt;code&amp;gt;mean&amp;lt;/code&amp;gt; member and yes/no in the &amp;lt;code&amp;gt;units&amp;lt;/code&amp;gt; member of the MUD variable.&lt;br /&gt;
* If the ODB link name contains parentheses, the string between the parenthesis is stored in the &amp;lt;code&amp;gt;units&amp;lt;/code&amp;gt; member of the MUD variable (e.g. a link called &amp;lt;code&amp;gt;Frequency (Hz)&amp;lt;/code&amp;gt; will end up with &amp;lt;code&amp;gt;Hz&amp;lt;/code&amp;gt; as the units).&lt;br /&gt;
* If the ODB link name does not contain parentheses (e.g. &amp;lt;code&amp;gt;Frequency&amp;lt;/code&amp;gt;), but there is another ODB key called &amp;lt;code&amp;gt;Frequency ((UNITS))&amp;lt;/code&amp;gt;, the string in the latter key is stored as the &amp;lt;code&amp;gt;units&amp;lt;/code&amp;gt; for the former. This is for backwards-compatibility with older files that were not consistent about whether MUD variables contain units in the &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;, or only in the &amp;lt;code&amp;gt;units&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ODB settings are stored as &amp;quot;independent variables&amp;quot; in the MUD file, keyed by the ODB link name (of format like &amp;lt;code&amp;gt;PPG/PPG20/Enable RF&amp;lt;/code&amp;gt; to be backwards-compatible with older files). To be clear, the name of the link itself is used, not the name of the target of the link.&lt;br /&gt;
&lt;br /&gt;
See the [[BNMR:_Mode_changer|mode changer]] page for details about how the user may load settings from a MUD file to replicate a previous experimental configuration.&lt;br /&gt;
&lt;br /&gt;
==== Run description ====&lt;br /&gt;
&lt;br /&gt;
Some ODB variables are also used to build the run description in the MUD file (along with any [[#Run_description|CAMP variables]] being used for the run description).&lt;br /&gt;
&lt;br /&gt;
The variables used are:&lt;br /&gt;
* {{Odbpath|path=/Experiment/Edit on start/experiment number}} for the &amp;lt;code&amp;gt;exptNumber&amp;lt;/code&amp;gt;&lt;br /&gt;
* {{Odbpath|path=/Experiment/Edit on start/experimenter}} for the &amp;lt;code&amp;gt;experimenter&amp;lt;/code&amp;gt;&lt;br /&gt;
* {{Odbpath|path=/Experiment/Edit on start/run_title}} for the &amp;lt;code&amp;gt;run_title&amp;lt;/code&amp;gt;&lt;br /&gt;
* {{Odbpath|path=/Experiment/Edit on start/sample}} for the &amp;lt;code&amp;gt;sample&amp;lt;/code&amp;gt;&lt;br /&gt;
* {{Odbpath|path=/Experiment/Edit on start/orientation}} for the &amp;lt;code&amp;gt;orient&amp;lt;/code&amp;gt;&lt;br /&gt;
* {{Odbpath|path=/Experiment/Name}} for the &amp;lt;code&amp;gt;area&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;apparatus&amp;lt;/code&amp;gt;, &lt;br /&gt;
* {{Odbpath|path=/CurrentMode/Name}} for the &amp;lt;code&amp;gt;insert&amp;lt;/code&amp;gt; (hijacking a field used by MUSR but not {{bnmqr|join=or}})&lt;br /&gt;
* {{Odbpath|path=/Runinfo/Start time binary}} for the &amp;lt;code&amp;gt;timeBegin&amp;lt;/code&amp;gt;&lt;br /&gt;
* {{Odbpath|path=/Runinfo/Stop time binary}} for the &amp;lt;code&amp;gt;timeEnd&amp;lt;/code&amp;gt;&lt;br /&gt;
* {{Odbpath|path=/MUD Logging/Run description/Settings/Manual field value}} if not reading from CAMP&lt;br /&gt;
* {{Odbpath|path=/MUD Logging/Run description/Settings/Manual temperature value}} if not reading from CAMP&lt;br /&gt;
&lt;br /&gt;
See [[BNMR:_Edit-on-start_parameters|edit-on-start parameters]] for more details on those variables.&lt;br /&gt;
&lt;br /&gt;
[[Category:BNMR]] [[Category:Logging]]&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR:_Mode_changer&amp;diff=7976</id>
		<title>BNMR: Mode changer</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR:_Mode_changer&amp;diff=7976"/>
		<updated>2024-10-02T21:30:31Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Pagelinks}}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
The mode changer program {{Client|name=mode_changer.py}} is responsible for:&lt;br /&gt;
* re-configuring the ODB when the user wants to change [[BNMR:_Experimental_Modes|experimental mode]]&lt;br /&gt;
* letting the user change between [[BNMR:_Run_numbering|real and test runs]] (including changing the run number accordingly)&lt;br /&gt;
* saving ODB settings (both manually and automatically when the user changes mode)&lt;br /&gt;
* loading ODB settings (both manually, automatically when the user changes mode, and from previous [[BNMR:_Data_Logging#MUD_files|MUD files]])&lt;br /&gt;
&lt;br /&gt;
The program is built using Midas&#039; python tools, and provides a JRPC interface that webpages can use to interact with it (e.g. getting the list of supported modes; requesting that the mode be changed).&lt;br /&gt;
&lt;br /&gt;
== Changing mode ==&lt;br /&gt;
&lt;br /&gt;
Modes are defined as a combination of features. For example:&lt;br /&gt;
* Mode &amp;lt;code&amp;gt;1c&amp;lt;/code&amp;gt; has &amp;lt;code&amp;gt;Enables CAMP scan=True&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;PPG timing=1n&amp;lt;/code&amp;gt;&lt;br /&gt;
* Mode &amp;lt;code&amp;gt;2b&amp;lt;/code&amp;gt; has &amp;lt;code&amp;gt;Enables RF=True&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;RF scanned in PPG loop=True&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;PPG timing=2b&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When changing modes, the program:&lt;br /&gt;
* saves the current ODB settings for the old mode&lt;br /&gt;
* loads the most recent settings that were used with the new mode (if available)&lt;br /&gt;
* changes the flags in {{Odbpath|path=/CurrentMode}} to those of the new mode (this lets other programs know what features should be enabled, without having to refer directly to mode names)&lt;br /&gt;
&lt;br /&gt;
== Saving and loading ODB settings ==&lt;br /&gt;
Saving and loading of ODB parameters build on the [https://bitbucket.org/ttriumfdaq/odb_save_load/src odb_save_load] package, which provides the raw tools for saving parts of the ODB as JSON files on disk, with metadata like a comment and save date.&lt;br /&gt;
&lt;br /&gt;
The mode changer program extends this functionality by automatically saving/loading settings when changing modes, and integrating the &amp;quot;manual&amp;quot; saving/loading with the custom settings page.&lt;br /&gt;
&lt;br /&gt;
=== What gets saved ===&lt;br /&gt;
&lt;br /&gt;
The definition of which bits of the ODB get saved is stored in {{Odbpath|path=/Saveload/Sections}}. It currently includes:&lt;br /&gt;
* {{Odbpath|path=/Equipment/PPGCompiler/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Equipment/PPGCompiler/Programming}}&lt;br /&gt;
* {{Odbpath|path=/Equipment/RFCalculator/PPG questions}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/PSM/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/BNXRCustomCycleLogic/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/Histograms/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/SampleReference/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/Epics/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/Camp/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/Global/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/Helicity/Settings}}&lt;br /&gt;
&lt;br /&gt;
=== Handling changes to the ODB structure ===&lt;br /&gt;
&lt;br /&gt;
Experiments often edit their DAQ code to add/remove keys. This can cause a problem if you later try to load some settings that were saved with the &amp;quot;old&amp;quot; ODB structure. To avoid these issues, the {{Client|name=odb_save_load/save_load.py}} python script allows you to adjust the saved settings in a fairly user-friendly way.&lt;br /&gt;
&lt;br /&gt;
All of the commands accept an &amp;lt;code&amp;gt;--odb-path&amp;lt;/code&amp;gt; argument. The script will automatically determine which section that ODB path belongs to, find the right bit of the ODB structure in the saved file, and modify it accordingly.&lt;br /&gt;
&lt;br /&gt;
The possible commands are:&lt;br /&gt;
* &amp;lt;code&amp;gt;add_from_live&amp;lt;/code&amp;gt; - read the current value of an ODB key from the live experiment, and store it in any files that don&#039;t currently have that key. Files that already have that key present are not touched.&lt;br /&gt;
* &amp;lt;code&amp;gt;add&amp;lt;/code&amp;gt; - like add_from_live, but manually specify the value to store as the --json-value parameter. You should encode the new value as the value member of a JSON string, e.g. --json-value=&#039;{&amp;quot;value&amp;quot;: true}&#039;&amp;lt;/code&amp;gt; to store a boolean true. Files that already have the key present are not touched.&lt;br /&gt;
* &amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt; - remove the specified ODB key from all saved settings that contain it.&lt;br /&gt;
* &amp;lt;code&amp;gt;edit_from_live&amp;lt;/code&amp;gt; - like add_from_live, but also change the value in files that already have the key present.&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; - like add, but also change the value in files that already have the key present.&lt;br /&gt;
&lt;br /&gt;
A full example command would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;python save_load.py add_from_live --odb-path=&amp;quot;/Equipment/PPGCompiler/Settings/Enable formulae&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
odb_save_load/save_load.py&lt;br /&gt;
&lt;br /&gt;
=== Loading settings from a MUD file ===&lt;br /&gt;
&lt;br /&gt;
The mode changer also allows loading any [[BNMR:_Data_Logging#ODB_variables|ODB settings that were saved in the MUD file]]. It uses the [https://github.com/dfujim/bdata bdata] package to load the file and get the list of variables that were saved. The [[BNMR:_RF_calculator|RF calculator]] uses the &amp;lt;code&amp;gt;mud_ind_var_links.py&amp;lt;/code&amp;gt; file to decide which ODB variables should be saved for each mode (mapping &amp;quot;real&amp;quot; ODB locations to names in the MUD file), and the mode changer uses the same file to go in the opposite direction (mapping names in the MUD file to ODB locations).&lt;br /&gt;
&lt;br /&gt;
Unfortunately, some variables are stored differently in the MUD file vs the ODB (e.g. booleans in the ODB vs a string in the MUD file). These &amp;quot;manipulations&amp;quot; are defined in two places:&lt;br /&gt;
* ODB to MUD in &amp;lt;code&amp;gt;compute_ppg_xxx()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;ppg_prog_helper.py&amp;lt;/code&amp;gt;&lt;br /&gt;
* MUD to ODB in &amp;lt;code&amp;gt;load_from_old_run()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mode_changer.py&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that not all ODB settings are stored in the MUD file; in particular, PSM RF modulation parameters are generally not stored.&lt;br /&gt;
&lt;br /&gt;
=== Changing mode without loading saved settings ===&lt;br /&gt;
&lt;br /&gt;
Sometimes the saved settings for a mode can fail to load correctly. If this is the case, you can use the [[BNMR:_Custom_Expert_page|Expert]] webpage to change the mode and load the default settings for that mode.&lt;br /&gt;
&lt;br /&gt;
=== Changing mode from the command-line ===&lt;br /&gt;
&lt;br /&gt;
You may change the mode via a command-line interface as well as via webpages. This may be useful for scripting a series of runs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;python mode_changer.py --oneshot --mode=1f&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Changing between real and test runs ==&lt;br /&gt;
Note that the user may change between real/test while a run is in progress!&lt;br /&gt;
&lt;br /&gt;
When changing between real and test runs, the program:&lt;br /&gt;
* changes the key {{Odbpath|path=/RealOrTest/Name}} to &amp;lt;code&amp;gt;real&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt;&lt;br /&gt;
* computes the new run number to use&lt;br /&gt;
* enables the alarm system and helicity checks if changing to a real run&lt;br /&gt;
* tells the [[BNMR:_Data_Logging#bnxr_logger.exe_introduction|data logger]] about the new configuration via JRPC (this lets it rename data files that have already been written for this run and name new files appropriately). JRPC is used rather than an ODB hotlink so that errors can be reported to the user more effectively. &lt;br /&gt;
&lt;br /&gt;
[[Category:BNMR]] [[Category:Client]]&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR:_Mode_changer&amp;diff=7975</id>
		<title>BNMR: Mode changer</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR:_Mode_changer&amp;diff=7975"/>
		<updated>2024-10-02T21:27:40Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Pagelinks}}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
The mode changer program {{Client|name=mode_changer.py}} is responsible for:&lt;br /&gt;
* re-configuring the ODB when the user wants to change [[BNMR:_Experimental_Modes|experimental mode]]&lt;br /&gt;
* letting the user change between [[BNMR:_Run_numbering|real and test runs]] (including changing the run number accordingly)&lt;br /&gt;
* saving ODB settings (both manually and automatically when the user changes mode)&lt;br /&gt;
* loading ODB settings (both manually, automatically when the user changes mode, and from previous [[BNMR:_Data_Logging#MUD_files|MUD files]])&lt;br /&gt;
&lt;br /&gt;
The program is built using Midas&#039; python tools, and provides a JRPC interface that webpages can use to interact with it (e.g. getting the list of supported modes; requesting that the mode be changed).&lt;br /&gt;
&lt;br /&gt;
== Changing mode ==&lt;br /&gt;
&lt;br /&gt;
Modes are defined as a combination of features. For example:&lt;br /&gt;
* Mode &amp;lt;code&amp;gt;1c&amp;lt;/code&amp;gt; has &amp;lt;code&amp;gt;Enables CAMP scan=True&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;PPG timing=1n&amp;lt;/code&amp;gt;&lt;br /&gt;
* Mode &amp;lt;code&amp;gt;2b&amp;lt;/code&amp;gt; has &amp;lt;code&amp;gt;Enables RF=True&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;RF scanned in PPG loop=True&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;PPG timing=2b&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When changing modes, the program:&lt;br /&gt;
* saves the current ODB settings for the old mode&lt;br /&gt;
* loads the most recent settings that were used with the new mode (if available)&lt;br /&gt;
* changes the flags in {{Odbpath|path=/CurrentMode}} to those of the new mode (this lets other programs know what features should be enabled, without having to refer directly to mode names)&lt;br /&gt;
&lt;br /&gt;
== Saving and loading ODB settings ==&lt;br /&gt;
Saving and loading of ODB parameters build on the [https://bitbucket.org/ttriumfdaq/odb_save_load/src odb_save_load] package, which provides the raw tools for saving parts of the ODB as JSON files on disk, with metadata like a comment and save date.&lt;br /&gt;
&lt;br /&gt;
The mode changer program extends this functionality by automatically saving/loading settings when changing modes, and integrating the &amp;quot;manual&amp;quot; saving/loading with the custom settings page.&lt;br /&gt;
&lt;br /&gt;
=== What gets saved ===&lt;br /&gt;
&lt;br /&gt;
The definition of which bits of the ODB get saved is stored in {{Odbpath|path=/Saveload/Sections}}. It currently includes:&lt;br /&gt;
* {{Odbpath|path=/Equipment/PPGCompiler/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Equipment/PPGCompiler/Programming}}&lt;br /&gt;
* {{Odbpath|path=/Equipment/RFCalculator/PPG questions}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/PSM/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/BNXRCustomCycleLogic/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/Histograms/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/SampleReference/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/Epics/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/Camp/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/Global/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/Helicity/Settings}}&lt;br /&gt;
&lt;br /&gt;
=== Handling changes to the ODB structure ===&lt;br /&gt;
&lt;br /&gt;
Experiments often edit their DAQ code to add/remove keys. This can cause a problem if you later try to load some settings that were saved with the &amp;quot;old&amp;quot; ODB structure. To avoid these issues, the {{Client|name=odb_save_load/save_load.py}} python script allows you to adjust the saved settings in a fairly user-friendly way.&lt;br /&gt;
&lt;br /&gt;
All of the commands accept an &amp;lt;code&amp;gt;--odb-path&amp;lt;/code&amp;gt; argument. The script will automatically determine which section that ODB path belongs to, find the right bit of the ODB structure in the saved file, and modify it accordingly.&lt;br /&gt;
&lt;br /&gt;
The possible commands are:&lt;br /&gt;
* &amp;lt;code&amp;gt;add_from_live&amp;lt;/code&amp;gt; - read the current value of an ODB key from the live experiment, and store it in any files that don&#039;t currently have that key. Files that already have that key present are not touched.&lt;br /&gt;
* &amp;lt;code&amp;gt;add&amp;lt;/code&amp;gt; - like add_from_live, but manually specify the value to store as the --json-value parameter. You should encode the new value as the value member of a JSON string, e.g. --json-value=&#039;{&amp;quot;value&amp;quot;: true}&#039;&amp;lt;/code&amp;gt; to store a boolean true. Files that already have the key present are not touched.&lt;br /&gt;
* &amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt; - remove the specified ODB key from all saved settings that contain it.&lt;br /&gt;
* &amp;lt;code&amp;gt;edit_from_live&amp;lt;/code&amp;gt; - like add_from_live, but also change the value in files that already have the key present.&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; - like add, but also change the value in files that already have the key present.&lt;br /&gt;
&lt;br /&gt;
A full example command would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;python save_load.py add_from_live --odb-path=&amp;quot;/Equipment/PPGCompiler/Settings/Enable formulae&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
odb_save_load/save_load.py&lt;br /&gt;
&lt;br /&gt;
=== Loading settings from a MUD file ===&lt;br /&gt;
&lt;br /&gt;
The mode changer also allows loading any [[BNMR:_Data_Logging#ODB_variables|ODB settings that were saved in the MUD file]]. It uses the [https://github.com/dfujim/bdata bdata] package to load the file and get the list of variables that were saved. The [[BNMR:_RF_calculator|RF calculator]] uses the &amp;lt;code&amp;gt;mud_ind_var_links.py&amp;lt;/code&amp;gt; file to decide which ODB variables should be saved for each mode (mapping &amp;quot;real&amp;quot; ODB locations to names in the MUD file), and the mode changer uses the same file to go in the opposite direction (mapping names in the MUD file to ODB locations).&lt;br /&gt;
&lt;br /&gt;
Unfortunately, some variables are stored differently in the MUD file vs the ODB (e.g. booleans in the ODB vs a string in the MUD file). These &amp;quot;manipulations&amp;quot; are defined in two places:&lt;br /&gt;
* ODB to MUD in &amp;lt;code&amp;gt;compute_ppg_xxx()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;ppg_prog_helper.py&amp;lt;/code&amp;gt;&lt;br /&gt;
* MUD to ODB in &amp;lt;code&amp;gt;load_from_old_run()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mode_changer.py&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that not all ODB settings are stored in the MUD file; in particular, PSM RF modulation parameters are generally not stored.&lt;br /&gt;
&lt;br /&gt;
=== Changing mode without loading saved settings ===&lt;br /&gt;
&lt;br /&gt;
Sometimes the saved settings for a mode can fail to load correctly. If this is the case, you can use the [[BNMR:_Custom_Expert_page|Expert]] webpage to change the mode and load the default settings for that mode.&lt;br /&gt;
&lt;br /&gt;
=== Changing mode from the command-line ===&lt;br /&gt;
&lt;br /&gt;
You may change the mode via a command-line interface as well as via webpages. This may be useful for scripting a series of runs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;python mode_changer.py --oneshot --mode=1f&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Changing between real and test runs ==&lt;br /&gt;
Note that the user may change between real/test while a run is in progress!&lt;br /&gt;
&lt;br /&gt;
When changing between real and test runs, the program:&lt;br /&gt;
* changes the key {{Odbpath|path=/RealOrTest/Name}} to &amp;lt;code&amp;gt;real&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt;&lt;br /&gt;
* computes the new run number to use&lt;br /&gt;
* enables the alarm system and helicity checks if changing to a real run&lt;br /&gt;
* tells the [[BNMR:_Data_Logging#bnxr_logger.exe_introduction|data logger]] about the new configuration via JRPC (this lets it rename data files that have already been written for this run and name new files appropriately). JRPC is used rather than an ODB hotlink so that errors can be reported to the user more effectively. &lt;br /&gt;
&lt;br /&gt;
== Resetting the run numbers ==&lt;br /&gt;
&lt;br /&gt;
BNMR and BNQR reuse [[BNMR:_Run_numbering|run numbers]] each year (i.e. you need to specify both the year and run number to identify a dataset).&lt;br /&gt;
&lt;br /&gt;
At the start of each year, you need to change where the data is being written to. This will automatically reset the run numbers to the new values for the year as well&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /isdaq/data1/&amp;lt;expt&amp;gt;/dlog&lt;br /&gt;
mkdir &amp;lt;year&amp;gt;&lt;br /&gt;
rm current&lt;br /&gt;
ln -s &amp;lt;year&amp;gt; current&lt;br /&gt;
# Use the web interface to toggle between real and test modes (without starting a run), and verify that the run numbers are 30000/40000 (for BNMR) and 30000/45000 (for BNQR).&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:BNMR]] [[Category:Client]]&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR:_Mode_changer&amp;diff=7974</id>
		<title>BNMR: Mode changer</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR:_Mode_changer&amp;diff=7974"/>
		<updated>2024-10-02T21:24:19Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: /* Resetting the run numbers */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Pagelinks}}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
The mode changer program {{Client|name=mode_changer.py}} is responsible for:&lt;br /&gt;
* re-configuring the ODB when the user wants to change [[BNMR:_Experimental_Modes|experimental mode]]&lt;br /&gt;
* letting the user change between [[BNMR:_Run_numbering|real and test runs]] (including changing the run number accordingly)&lt;br /&gt;
* saving ODB settings (both manually and automatically when the user changes mode)&lt;br /&gt;
* loading ODB settings (both manually, automatically when the user changes mode, and from previous [[BNMR:_Data_Logging#MUD_files|MUD files]])&lt;br /&gt;
&lt;br /&gt;
The program is built using Midas&#039; python tools, and provides a JRPC interface that webpages can use to interact with it (e.g. getting the list of supported modes; requesting that the mode be changed).&lt;br /&gt;
&lt;br /&gt;
== Changing mode ==&lt;br /&gt;
&lt;br /&gt;
Modes are defined as a combination of features. For example:&lt;br /&gt;
* Mode &amp;lt;code&amp;gt;1c&amp;lt;/code&amp;gt; has &amp;lt;code&amp;gt;Enables CAMP scan=True&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;PPG timing=1n&amp;lt;/code&amp;gt;&lt;br /&gt;
* Mode &amp;lt;code&amp;gt;2b&amp;lt;/code&amp;gt; has &amp;lt;code&amp;gt;Enables RF=True&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;RF scanned in PPG loop=True&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;PPG timing=2b&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When changing modes, the program:&lt;br /&gt;
* saves the current ODB settings for the old mode&lt;br /&gt;
* loads the most recent settings that were used with the new mode (if available)&lt;br /&gt;
* changes the flags in {{Odbpath|path=/CurrentMode}} to those of the new mode (this lets other programs know what features should be enabled, without having to refer directly to mode names)&lt;br /&gt;
&lt;br /&gt;
== Saving and loading ODB settings ==&lt;br /&gt;
Saving and loading of ODB parameters build on the [https://bitbucket.org/ttriumfdaq/odb_save_load/src odb_save_load] package, which provides the raw tools for saving parts of the ODB as JSON files on disk, with metadata like a comment and save date.&lt;br /&gt;
&lt;br /&gt;
The mode changer program extends this functionality by automatically saving/loading settings when changing modes, and integrating the &amp;quot;manual&amp;quot; saving/loading with the custom settings page.&lt;br /&gt;
&lt;br /&gt;
=== What gets saved ===&lt;br /&gt;
&lt;br /&gt;
The definition of which bits of the ODB get saved is stored in {{Odbpath|path=/Saveload/Sections}}. It currently includes:&lt;br /&gt;
* {{Odbpath|path=/Equipment/PPGCompiler/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Equipment/PPGCompiler/Programming}}&lt;br /&gt;
* {{Odbpath|path=/Equipment/RFCalculator/PPG questions}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/PSM/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/BNXRCustomCycleLogic/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/Histograms/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/SampleReference/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/Epics/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/Camp/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/Global/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/Helicity/Settings}}&lt;br /&gt;
&lt;br /&gt;
=== Handling changes to the ODB structure ===&lt;br /&gt;
&lt;br /&gt;
Experiments often edit their DAQ code to add/remove keys. This can cause a problem if you later try to load some settings that were saved with the &amp;quot;old&amp;quot; ODB structure. To avoid these issues, the {{Client|name=odb_save_load/save_load.py}} python script allows you to adjust the saved settings in a fairly user-friendly way.&lt;br /&gt;
&lt;br /&gt;
All of the commands accept an &amp;lt;code&amp;gt;--odb-path&amp;lt;/code&amp;gt; argument. The script will automatically determine which section that ODB path belongs to, find the right bit of the ODB structure in the saved file, and modify it accordingly.&lt;br /&gt;
&lt;br /&gt;
The possible commands are:&lt;br /&gt;
* &amp;lt;code&amp;gt;add_from_live&amp;lt;/code&amp;gt; - read the current value of an ODB key from the live experiment, and store it in any files that don&#039;t currently have that key. Files that already have that key present are not touched.&lt;br /&gt;
* &amp;lt;code&amp;gt;add&amp;lt;/code&amp;gt; - like add_from_live, but manually specify the value to store as the --json-value parameter. You should encode the new value as the value member of a JSON string, e.g. --json-value=&#039;{&amp;quot;value&amp;quot;: true}&#039;&amp;lt;/code&amp;gt; to store a boolean true. Files that already have the key present are not touched.&lt;br /&gt;
* &amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt; - remove the specified ODB key from all saved settings that contain it.&lt;br /&gt;
* &amp;lt;code&amp;gt;edit_from_live&amp;lt;/code&amp;gt; - like add_from_live, but also change the value in files that already have the key present.&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; - like add, but also change the value in files that already have the key present.&lt;br /&gt;
&lt;br /&gt;
A full example command would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;python save_load.py add_from_live --odb-path=&amp;quot;/Equipment/PPGCompiler/Settings/Enable formulae&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
odb_save_load/save_load.py&lt;br /&gt;
&lt;br /&gt;
=== Loading settings from a MUD file ===&lt;br /&gt;
&lt;br /&gt;
The mode changer also allows loading any [[BNMR:_Data_Logging#ODB_variables|ODB settings that were saved in the MUD file]]. It uses the [https://github.com/dfujim/bdata bdata] package to load the file and get the list of variables that were saved. The [[BNMR:_RF_calculator|RF calculator]] uses the &amp;lt;code&amp;gt;mud_ind_var_links.py&amp;lt;/code&amp;gt; file to decide which ODB variables should be saved for each mode (mapping &amp;quot;real&amp;quot; ODB locations to names in the MUD file), and the mode changer uses the same file to go in the opposite direction (mapping names in the MUD file to ODB locations).&lt;br /&gt;
&lt;br /&gt;
Unfortunately, some variables are stored differently in the MUD file vs the ODB (e.g. booleans in the ODB vs a string in the MUD file). These &amp;quot;manipulations&amp;quot; are defined in two places:&lt;br /&gt;
* ODB to MUD in &amp;lt;code&amp;gt;compute_ppg_xxx()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;ppg_prog_helper.py&amp;lt;/code&amp;gt;&lt;br /&gt;
* MUD to ODB in &amp;lt;code&amp;gt;load_from_old_run()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mode_changer.py&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that not all ODB settings are stored in the MUD file; in particular, PSM RF modulation parameters are generally not stored.&lt;br /&gt;
&lt;br /&gt;
=== Changing mode without loading saved settings ===&lt;br /&gt;
&lt;br /&gt;
Sometimes the saved settings for a mode can fail to load correctly. If this is the case, you can use the [[BNMR:_Custom_Expert_page|Expert]] webpage to change the mode and load the default settings for that mode.&lt;br /&gt;
&lt;br /&gt;
=== Changing mode from the command-line ===&lt;br /&gt;
&lt;br /&gt;
You may change the mode via a command-line interface as well as via webpages. This may be useful for scripting a series of runs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;python mode_changer.py --oneshot --mode=1f&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Changing between real and test runs ==&lt;br /&gt;
Note that the user may change between real/test while a run is in progress!&lt;br /&gt;
&lt;br /&gt;
When changing between real and test runs, the program:&lt;br /&gt;
* changes the key {{Odbpath|path=/RealOrTest/Name}} to &amp;lt;code&amp;gt;real&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt;&lt;br /&gt;
* computes the new run number to use&lt;br /&gt;
* enables the alarm system and helicity checks if changing to a real run&lt;br /&gt;
* tells the [[BNMR:_Data_Logging#bnxr_logger.exe_introduction|data logger]] about the new configuration via JRPC (this lets it rename data files that have already been written for this run and name new files appropriately). JRPC is used rather than an ODB hotlink so that errors can be reported to the user more effectively. &lt;br /&gt;
&lt;br /&gt;
== Resetting the run numbers ==&lt;br /&gt;
&lt;br /&gt;
BNMR and BNQR reuse [[BNMR:_Run_numbering|run numbers]] each year (i.e. you need to specify both the year and run number to identify a dataset).&lt;br /&gt;
&lt;br /&gt;
At the start of each year, you need to reset the first run number to be used (and where the data is being written to).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /isdaq/data1/&amp;lt;expt&amp;gt;/dlog&lt;br /&gt;
mkdir &amp;lt;year&amp;gt;&lt;br /&gt;
rm current&lt;br /&gt;
ln -s &amp;lt;year&amp;gt; current&lt;br /&gt;
python ~/packages/&amp;lt;expt&amp;gt;/bnxr_common/mode_changer.py --oneshot --reset_run_numbers&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:BNMR]] [[Category:Client]]&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR:_Software_overview&amp;diff=7973</id>
		<title>BNMR: Software overview</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR:_Software_overview&amp;diff=7973"/>
		<updated>2024-10-02T20:51:00Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: /* Updating bnmr/bnqr software */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Pagelinks}}&lt;br /&gt;
&lt;br /&gt;
== Program list ==&lt;br /&gt;
&lt;br /&gt;
Programs with the _32bit suffix are designed to be run on the VMIC machine; all others are designed to be run on the host PC.&lt;br /&gt;
&lt;br /&gt;
=== Compiled &amp;quot;real&amp;quot; programs ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/febnmr_32bit.exe&amp;lt;/code&amp;gt; ({{bnmr}} only) - see [[BNMR:_frontend|frontend]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/febnqr_32bit.exe&amp;lt;/code&amp;gt; ({{bnqr}} only) - see [[BNMR:_frontend|frontend]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/bnxr_logger.exe&amp;lt;/code&amp;gt; - see [[BNMR: Data Logging|data logging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/logger_cleanup.exe&amp;lt;/code&amp;gt; - see [[BNMR: Data Logging#Cleaning_up_if_end-of-run_fails|data logging]]&lt;br /&gt;
&lt;br /&gt;
=== Python &amp;quot;real&amp;quot; programs ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/beamtime_monitor.py&amp;lt;/code&amp;gt; - see [[BNMR:_Shift_Monitor|shift monitor]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/beamtime_to_excel.py&amp;lt;/code&amp;gt; - see [[BNMR:_Shift_Monitor|shift monitor]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/elog_every_run.py&amp;lt;/code&amp;gt; - see [[BNMR:_Scripts#Run_transition_scripts|run transition scripts]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/mode_changer.py&amp;lt;/code&amp;gt; - see [[BNMR:_Mode_changer|mode changer]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/rf_calculator_fe.py&amp;lt;/code&amp;gt; - see [[BNMR:_RF_calculator|RF calculator]]&lt;br /&gt;
* &amp;lt;code&amp;gt;cycling_framework/ppg/ppg_compiler_fe.py&amp;lt;/code&amp;gt; - see [[BNMR:_PPG_compiler|PPG compiler]]&lt;br /&gt;
* &amp;lt;code&amp;gt;cycling_framework/run_comments/run_comment_editor.py&amp;lt;/code&amp;gt; - see [[BNMR:_Data_Logging#Run_comments|data logging]]&lt;br /&gt;
&lt;br /&gt;
=== Compiled programs for debugging hardware etc ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/bnmrbeamsim_32bit.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/camp_test.exe&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bin/camp_test_32bit.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/epics_test.exe&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bin/epics_test_32bit.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/vppg_interactive_32bit.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/sis3801_interactive_32bit.exe&amp;lt;/code&amp;gt; ({{bnmr}} only) - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/sis3820_interactive_32bit.exe&amp;lt;/code&amp;gt; ({{bnqr}} only) - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/psm_interactive_32bit.exe&amp;lt;/code&amp;gt;  ({{bnqr}} only) - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/psm3_interactive_32bit.exe&amp;lt;/code&amp;gt;  ({{bnmr}} only) - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
&lt;br /&gt;
=== Compiled automated tests ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/unit_tests/*.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Tests#Automated_tests_that_don.27t_use_the_ODB|Automated tests that don&#039;t use the ODB]]&lt;br /&gt;
&lt;br /&gt;
=== Python test programs ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/test_mud_logger.py&amp;lt;/code&amp;gt; - see [[BNMR:_Tests#Automated_tests_that_do_use_the_ODB|automated tests that use the ODB]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/test_ppg_calc.py&amp;lt;/code&amp;gt; - see [[BNMR:_Tests#Automated_tests_that_do_use_the_ODB|automated tests that use the ODB]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/test_psm_calc.py&amp;lt;/code&amp;gt; - see [[BNMR:_Tests#Automated_tests_that_do_use_the_ODB|automated tests that use the ODB]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/diff_mud_file.py&amp;lt;/code&amp;gt; - see [[BNMR:_Data_Logging#MUD_files|data logging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/dump_mud_file.py&amp;lt;/code&amp;gt; - see [[BNMR:_Data_Logging#MUD_files|data logging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;cycling_framework/ppg/tests/test_ppg.py&amp;lt;/code&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
=== Unused compiled programs ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/epics_log.exe&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bin/epics_log_32bit.exe&amp;lt;/code&amp;gt; - EPICS logging is handled by the MUD logger in {{bnmqr|join=/}}&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/tppg_interactive_32bit.exe&amp;lt;/code&amp;gt; - this version is for TRIUMF PPGs; we use PulseBlaster PPGs&lt;br /&gt;
&lt;br /&gt;
== Repository location ==&lt;br /&gt;
&lt;br /&gt;
The main repository is on BitBucket at [https://bitbucket.org/ttriumfdaq/bnmr/ https://bitbucket.org/ttriumfdaq/bnmr/].&lt;br /&gt;
&lt;br /&gt;
== Updating bnmr/bnqr software ==&lt;br /&gt;
&lt;br /&gt;
The main repository uses submodules for some dependencies, so checking out updates requires:&lt;br /&gt;
&lt;br /&gt;
 git pull&lt;br /&gt;
 git submodule update&lt;br /&gt;
&lt;br /&gt;
To compile the real software, we can compile everything from isdaq01 (including the frontend that will eventually run on lxbnmr/lxbnqr). The cross-compilation of the frontend requires some 32-bit libraries that we store in &amp;lt;code&amp;gt;/home/bnmr/packages/libs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 # on isdaq01&lt;br /&gt;
 &lt;br /&gt;
 # For the first install&lt;br /&gt;
 mkdir build&lt;br /&gt;
 cd build&lt;br /&gt;
 cmake .. -DEXP=BNMR&lt;br /&gt;
 # or cmake .. -DEXP=BNQR&lt;br /&gt;
 make install&lt;br /&gt;
 &lt;br /&gt;
 # For updates&lt;br /&gt;
 cd build&lt;br /&gt;
 make install&lt;br /&gt;
&lt;br /&gt;
This will:&lt;br /&gt;
* Cross-compile the frontend to run on the 32-bit VMIC machine (either febnmr or febnqr depending on the &amp;lt;code&amp;gt;-DEXP=...&amp;lt;/code&amp;gt; flag you passed to cmake)&lt;br /&gt;
* Compile the MUD logger&lt;br /&gt;
* Compile various debug executables&lt;br /&gt;
* Compile various automated tests&lt;br /&gt;
&lt;br /&gt;
To compile a dummy version of the software that does not talk to the real hardware or EPICS (and which can be run on a laptop):&lt;br /&gt;
&lt;br /&gt;
 mkdir build&lt;br /&gt;
 cd build&lt;br /&gt;
 cmake .. -DEXP=BNMR -DDUMMY_MODE=1&lt;br /&gt;
 # or cmake .. -DEXP=BNQR -DDUMMY_MODE=1&lt;br /&gt;
 make install&lt;br /&gt;
&lt;br /&gt;
== Updating midas ==&lt;br /&gt;
&lt;br /&gt;
 # Get updates&lt;br /&gt;
 cd $MIDASSYS&lt;br /&gt;
 git pull&lt;br /&gt;
 git submodule update --init --recursive&lt;br /&gt;
 &lt;br /&gt;
 # Compile 64-bit version&lt;br /&gt;
 mkdir -p $MIDASSYS/build&lt;br /&gt;
 cd $MIDASSYS/build&lt;br /&gt;
 make install&lt;br /&gt;
 &lt;br /&gt;
 # Cross-compile 32-bit version&lt;br /&gt;
 cd $MIDASSYS&lt;br /&gt;
 make linux32&lt;br /&gt;
 &lt;br /&gt;
 # Change status page from midas default to a symlink&lt;br /&gt;
 if ! [ -L $MIDASSYS/resources/status.html ]; then&lt;br /&gt;
   mv $MIDASSYS/resources/status.html $MIDASSYS/resources/status.html.orig&lt;br /&gt;
   if [ $USER == &amp;quot;bnmr&amp;quot; ]; then&lt;br /&gt;
     ln -s ~/packages/bnmr/bnxr_common/custom/status.html $MIDASSYS/resources/status.html&lt;br /&gt;
   else&lt;br /&gt;
     ln -s ~/packages/bnqr/bnxr_common/custom/status.html $MIDASSYS/resources/status.html&lt;br /&gt;
   fi&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
Then re-compile the bnmr/bnqr software&lt;br /&gt;
&lt;br /&gt;
== Interactions between programs ==&lt;br /&gt;
&lt;br /&gt;
* RPC between febnmr.exe/febnqr.exe and ppg_compiler_fe.py to generate PPG bytecode at begin-of-run&lt;br /&gt;
* RPC between rf_calculator_fe.py and ppg_compiler_fe.py to generate PPG bytecode when user clicks button on Settings webpage&lt;br /&gt;
* Midas buffers between febnmr.exe/febnqr.exe and bnxr_logger.exe for data&lt;br /&gt;
* Midas buffers between kalliope_fe.exe and bnxr_logger.exe for data&lt;br /&gt;
* RPC between febnmr.exe/febnqr.exe and kalliope_fe.exe to inform it of PPG cycle state&lt;br /&gt;
* run_comment_editor.py writes to a text file in the data directory, which is then read by bnxr_logger.exe when it&#039;s time to write a new MUD file. Text file is deleted at the end of the run.&lt;br /&gt;
&lt;br /&gt;
== Run transitions ==&lt;br /&gt;
&lt;br /&gt;
MIDAS allows clients to register to various transitions (e.g. START,STOP). However, many clients need to perform actions in a certain order. For example, in the {{bnmqr|join=and}} experiments, at begin-of-run, [[BNMR:_RF_calculator|the RF calculator]] is required to check the input parameters and compute various derived values (e.g. the list of I,Q pairs to load on the PSM). This must be completed before the frontend attempts to load these values. &lt;br /&gt;
&lt;br /&gt;
This is accomplished in MIDAS by the use of transition sequence numbers. The RF calculator and the frontend both register to the START transition, but the frontend is registered to only handle the transition after the RF calculator has finished doing the work it need to do.&lt;br /&gt;
&lt;br /&gt;
The full list of transition orderings (higher happens later) is:&lt;br /&gt;
* 1 - mode changer (ensure correct run number)&lt;br /&gt;
* 50 - RF calculator (compute PSM I,Q pairs, create human-readable PPG program to run, setup ODB links for MUD logging etc)&lt;br /&gt;
* 100 - frontend configuration (setup PSM, call PPG compiler to generate bytecode etc)&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:#999999&amp;quot;&amp;gt;100 - run comment editor (no-op)&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:#999999&amp;quot;&amp;gt;500 - PPG compiler (no-op for {{bnmqr|join=/}} as the frontend calls the PPG compiler by JRPC)&amp;lt;/span&amp;gt;&lt;br /&gt;
* 900 - MUD logger (connect to CAMP, open Midas buffers etc)&lt;br /&gt;
* 990 - frontend setup first cycle (configure first scan step and start PPG)&lt;br /&gt;
&lt;br /&gt;
If any of these transitions fail, the latter ones do not happen (and a &amp;quot;STARTABORT&amp;quot; transition signal is sent to all the clients). Having the frontend delay starting the PPG until the end of the sequence ensures that all the clients are ready for when the data starts to flow. Having the frontend configure the hardware early in the sequence prevents the MUD logger from doing unnecessary work if there is a hardware issue.&lt;br /&gt;
&lt;br /&gt;
[[Category:BNMR]]&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR:_Software_overview&amp;diff=7972</id>
		<title>BNMR: Software overview</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR:_Software_overview&amp;diff=7972"/>
		<updated>2024-10-02T20:47:28Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: /* Updating bnmr/bnqr software */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Pagelinks}}&lt;br /&gt;
&lt;br /&gt;
== Program list ==&lt;br /&gt;
&lt;br /&gt;
Programs with the _32bit suffix are designed to be run on the VMIC machine; all others are designed to be run on the host PC.&lt;br /&gt;
&lt;br /&gt;
=== Compiled &amp;quot;real&amp;quot; programs ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/febnmr_32bit.exe&amp;lt;/code&amp;gt; ({{bnmr}} only) - see [[BNMR:_frontend|frontend]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/febnqr_32bit.exe&amp;lt;/code&amp;gt; ({{bnqr}} only) - see [[BNMR:_frontend|frontend]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/bnxr_logger.exe&amp;lt;/code&amp;gt; - see [[BNMR: Data Logging|data logging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/logger_cleanup.exe&amp;lt;/code&amp;gt; - see [[BNMR: Data Logging#Cleaning_up_if_end-of-run_fails|data logging]]&lt;br /&gt;
&lt;br /&gt;
=== Python &amp;quot;real&amp;quot; programs ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/beamtime_monitor.py&amp;lt;/code&amp;gt; - see [[BNMR:_Shift_Monitor|shift monitor]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/beamtime_to_excel.py&amp;lt;/code&amp;gt; - see [[BNMR:_Shift_Monitor|shift monitor]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/elog_every_run.py&amp;lt;/code&amp;gt; - see [[BNMR:_Scripts#Run_transition_scripts|run transition scripts]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/mode_changer.py&amp;lt;/code&amp;gt; - see [[BNMR:_Mode_changer|mode changer]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/rf_calculator_fe.py&amp;lt;/code&amp;gt; - see [[BNMR:_RF_calculator|RF calculator]]&lt;br /&gt;
* &amp;lt;code&amp;gt;cycling_framework/ppg/ppg_compiler_fe.py&amp;lt;/code&amp;gt; - see [[BNMR:_PPG_compiler|PPG compiler]]&lt;br /&gt;
* &amp;lt;code&amp;gt;cycling_framework/run_comments/run_comment_editor.py&amp;lt;/code&amp;gt; - see [[BNMR:_Data_Logging#Run_comments|data logging]]&lt;br /&gt;
&lt;br /&gt;
=== Compiled programs for debugging hardware etc ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/bnmrbeamsim_32bit.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/camp_test.exe&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bin/camp_test_32bit.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/epics_test.exe&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bin/epics_test_32bit.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/vppg_interactive_32bit.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/sis3801_interactive_32bit.exe&amp;lt;/code&amp;gt; ({{bnmr}} only) - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/sis3820_interactive_32bit.exe&amp;lt;/code&amp;gt; ({{bnqr}} only) - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/psm_interactive_32bit.exe&amp;lt;/code&amp;gt;  ({{bnqr}} only) - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/psm3_interactive_32bit.exe&amp;lt;/code&amp;gt;  ({{bnmr}} only) - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
&lt;br /&gt;
=== Compiled automated tests ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/unit_tests/*.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Tests#Automated_tests_that_don.27t_use_the_ODB|Automated tests that don&#039;t use the ODB]]&lt;br /&gt;
&lt;br /&gt;
=== Python test programs ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/test_mud_logger.py&amp;lt;/code&amp;gt; - see [[BNMR:_Tests#Automated_tests_that_do_use_the_ODB|automated tests that use the ODB]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/test_ppg_calc.py&amp;lt;/code&amp;gt; - see [[BNMR:_Tests#Automated_tests_that_do_use_the_ODB|automated tests that use the ODB]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/test_psm_calc.py&amp;lt;/code&amp;gt; - see [[BNMR:_Tests#Automated_tests_that_do_use_the_ODB|automated tests that use the ODB]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/diff_mud_file.py&amp;lt;/code&amp;gt; - see [[BNMR:_Data_Logging#MUD_files|data logging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/dump_mud_file.py&amp;lt;/code&amp;gt; - see [[BNMR:_Data_Logging#MUD_files|data logging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;cycling_framework/ppg/tests/test_ppg.py&amp;lt;/code&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
=== Unused compiled programs ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/epics_log.exe&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bin/epics_log_32bit.exe&amp;lt;/code&amp;gt; - EPICS logging is handled by the MUD logger in {{bnmqr|join=/}}&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/tppg_interactive_32bit.exe&amp;lt;/code&amp;gt; - this version is for TRIUMF PPGs; we use PulseBlaster PPGs&lt;br /&gt;
&lt;br /&gt;
== Repository location ==&lt;br /&gt;
&lt;br /&gt;
The main repository is on BitBucket at [https://bitbucket.org/ttriumfdaq/bnmr/ https://bitbucket.org/ttriumfdaq/bnmr/].&lt;br /&gt;
&lt;br /&gt;
== Updating bnmr/bnqr software ==&lt;br /&gt;
&lt;br /&gt;
The main repository uses submodules for some dependencies, so checking out updates requires:&lt;br /&gt;
&lt;br /&gt;
 git pull&lt;br /&gt;
 git submodule update&lt;br /&gt;
&lt;br /&gt;
To compile the real software, we currently have to compile separately on isdaq01 (for stuff that runs there) and isdaq06 (for stuff that runs on lxbnmr/lxbnqr). This is because isdaq06 and the lx machines run modern OSes, and isdaq01 is still on an old OS (so we can&#039;t cross-compile from it). Once isdaq01 has been upgraded, we will be able to run all compilation from there again and compile times will be significantly faster.&lt;br /&gt;
&lt;br /&gt;
 #&lt;br /&gt;
 # For the first install&lt;br /&gt;
 #&lt;br /&gt;
 # on isdaq01&lt;br /&gt;
 mkdir build&lt;br /&gt;
 cd build&lt;br /&gt;
 cmake .. -DEXP=BNMR&lt;br /&gt;
 # or cmake .. -DEXP=BNQR&lt;br /&gt;
 make install&lt;br /&gt;
&lt;br /&gt;
 #&lt;br /&gt;
 # For updates&lt;br /&gt;
 #&lt;br /&gt;
 # on isdaq01&lt;br /&gt;
 cd build&lt;br /&gt;
 make install&lt;br /&gt;
&lt;br /&gt;
This will:&lt;br /&gt;
* Cross-compile the frontend to run on the 32-bit VMIC machine (either febnmr or febnqr depending on the &amp;lt;code&amp;gt;-DEXP=...&amp;lt;/code&amp;gt; flag you passed to cmake)&lt;br /&gt;
* Compile the MUD logger&lt;br /&gt;
* Compile various debug executables&lt;br /&gt;
* Compile various automated tests&lt;br /&gt;
&lt;br /&gt;
To compile a dummy version of the software that does not talk to the real hardware or EPICS (and which can be run on a laptop):&lt;br /&gt;
&lt;br /&gt;
 mkdir build&lt;br /&gt;
 cd build&lt;br /&gt;
 cmake .. -DEXP=BNMR -DDUMMY_MODE=1&lt;br /&gt;
 # or cmake .. -DEXP=BNQR -DDUMMY_MODE=1&lt;br /&gt;
 make install&lt;br /&gt;
&lt;br /&gt;
== Updating midas ==&lt;br /&gt;
&lt;br /&gt;
 # Get updates&lt;br /&gt;
 cd $MIDASSYS&lt;br /&gt;
 git pull&lt;br /&gt;
 git submodule update --init --recursive&lt;br /&gt;
 &lt;br /&gt;
 # Compile 64-bit version&lt;br /&gt;
 mkdir -p $MIDASSYS/build&lt;br /&gt;
 cd $MIDASSYS/build&lt;br /&gt;
 make install&lt;br /&gt;
 &lt;br /&gt;
 # Cross-compile 32-bit version&lt;br /&gt;
 cd $MIDASSYS&lt;br /&gt;
 make linux32&lt;br /&gt;
 &lt;br /&gt;
 # Change status page from midas default to a symlink&lt;br /&gt;
 if ! [ -L $MIDASSYS/resources/status.html ]; then&lt;br /&gt;
   mv $MIDASSYS/resources/status.html $MIDASSYS/resources/status.html.orig&lt;br /&gt;
   if [ $USER == &amp;quot;bnmr&amp;quot; ]; then&lt;br /&gt;
     ln -s ~/packages/bnmr/bnxr_common/custom/status.html $MIDASSYS/resources/status.html&lt;br /&gt;
   else&lt;br /&gt;
     ln -s ~/packages/bnqr/bnxr_common/custom/status.html $MIDASSYS/resources/status.html&lt;br /&gt;
   fi&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
Then re-compile the bnmr/bnqr software&lt;br /&gt;
&lt;br /&gt;
== Interactions between programs ==&lt;br /&gt;
&lt;br /&gt;
* RPC between febnmr.exe/febnqr.exe and ppg_compiler_fe.py to generate PPG bytecode at begin-of-run&lt;br /&gt;
* RPC between rf_calculator_fe.py and ppg_compiler_fe.py to generate PPG bytecode when user clicks button on Settings webpage&lt;br /&gt;
* Midas buffers between febnmr.exe/febnqr.exe and bnxr_logger.exe for data&lt;br /&gt;
* Midas buffers between kalliope_fe.exe and bnxr_logger.exe for data&lt;br /&gt;
* RPC between febnmr.exe/febnqr.exe and kalliope_fe.exe to inform it of PPG cycle state&lt;br /&gt;
* run_comment_editor.py writes to a text file in the data directory, which is then read by bnxr_logger.exe when it&#039;s time to write a new MUD file. Text file is deleted at the end of the run.&lt;br /&gt;
&lt;br /&gt;
== Run transitions ==&lt;br /&gt;
&lt;br /&gt;
MIDAS allows clients to register to various transitions (e.g. START,STOP). However, many clients need to perform actions in a certain order. For example, in the {{bnmqr|join=and}} experiments, at begin-of-run, [[BNMR:_RF_calculator|the RF calculator]] is required to check the input parameters and compute various derived values (e.g. the list of I,Q pairs to load on the PSM). This must be completed before the frontend attempts to load these values. &lt;br /&gt;
&lt;br /&gt;
This is accomplished in MIDAS by the use of transition sequence numbers. The RF calculator and the frontend both register to the START transition, but the frontend is registered to only handle the transition after the RF calculator has finished doing the work it need to do.&lt;br /&gt;
&lt;br /&gt;
The full list of transition orderings (higher happens later) is:&lt;br /&gt;
* 1 - mode changer (ensure correct run number)&lt;br /&gt;
* 50 - RF calculator (compute PSM I,Q pairs, create human-readable PPG program to run, setup ODB links for MUD logging etc)&lt;br /&gt;
* 100 - frontend configuration (setup PSM, call PPG compiler to generate bytecode etc)&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:#999999&amp;quot;&amp;gt;100 - run comment editor (no-op)&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:#999999&amp;quot;&amp;gt;500 - PPG compiler (no-op for {{bnmqr|join=/}} as the frontend calls the PPG compiler by JRPC)&amp;lt;/span&amp;gt;&lt;br /&gt;
* 900 - MUD logger (connect to CAMP, open Midas buffers etc)&lt;br /&gt;
* 990 - frontend setup first cycle (configure first scan step and start PPG)&lt;br /&gt;
&lt;br /&gt;
If any of these transitions fail, the latter ones do not happen (and a &amp;quot;STARTABORT&amp;quot; transition signal is sent to all the clients). Having the frontend delay starting the PPG until the end of the sequence ensures that all the clients are ready for when the data starts to flow. Having the frontend configure the hardware early in the sequence prevents the MUD logger from doing unnecessary work if there is a hardware issue.&lt;br /&gt;
&lt;br /&gt;
[[Category:BNMR]]&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR&amp;diff=7971</id>
		<title>BNMR</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR&amp;diff=7971"/>
		<updated>2024-10-01T22:48:22Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: /* Tasks to be done before each beamtime */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Pagelinks}}&lt;br /&gt;
&lt;br /&gt;
== BNMR and BNQR Experiments at TRIUMF ==&lt;br /&gt;
This is the main page of the documentation for the Data Acquisition System (DAQ) for the BetaNMR (BNMR) and BetaNQR (BNQR) experiments at TRIUMF&lt;br /&gt;
&lt;br /&gt;
[[:Category:BNMR|Click here for a full list of all the pages in the BNMR documentation]].&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
The Data Acquisition System is based on the [https://midas.triumf.ca/MidasWiki/index.php/Midas_documentation MIDAS] data acquisition package. &lt;br /&gt;
&lt;br /&gt;
There are two separate &#039;&#039;&#039;beamlines&#039;&#039;&#039;, BNMR and BNQR, each with its own experimental setup :&lt;br /&gt;
&lt;br /&gt;
* {{bnmr}} running on the BNMR high-voltage platform&lt;br /&gt;
* {{bnqr}} running on the BNQR high-voltage platform&lt;br /&gt;
&lt;br /&gt;
Each experimental setup has its own  [[#Hardware Components]] (i.e. a VME crate containing DAQ modules).  Each runs as a separate MIDAS experiment named {{bnmqr|join=or}}. DAQ software specific to these experiments (MIDAS clients) run the experiments - see [[#Software Components]]. Experimenters control the experiment using the MIDAS Web Server (mhttpd).&lt;br /&gt;
  &lt;br /&gt;
== Beam Control ==&lt;br /&gt;
The main TRIUMF EPICS Control System is used to control the beam, which can be switched to either experiment&#039;s &#039;&#039;&#039;beamline&#039;&#039;&#039;.  There are two &#039;&#039;&#039;Beam Modes&#039;&#039;&#039; that the experiments can be run in:&lt;br /&gt;
&lt;br /&gt;
;     [[BNMR Dual Channel Mode #Single Channel Mode|single channel mode]]&lt;br /&gt;
: where the beam is sent to one beamline (channel) only, either BNMR or BNQR. Only &#039;&#039;&#039;one&#039;&#039;&#039; of the DAQ systems &amp;lt;span style=&amp;quot;color:#7b68ee; font-style=italic&amp;quot;&amp;gt;bnmr &amp;lt;/span&amp;gt; or &amp;lt;span style=&amp;quot;color:#20b2aa; font-style=italic&amp;quot;&amp;gt;bnqr&amp;lt;/span&amp;gt; is active.&lt;br /&gt;
;    [[BNMR Dual Channel Mode|dual channel mode]]&lt;br /&gt;
: where the beam is switched between the two beamlines (channels) BNMR and BNQR at regular intervals. &#039;&#039;&#039;Both&#039;&#039;&#039; DAQ systems  &amp;lt;span style=&amp;quot;color:#7b68ee; font-style=italic&amp;quot;&amp;gt;bnmr &amp;lt;/span&amp;gt; and &amp;lt;span style=&amp;quot;color:#20b2aa; font-style=italic&amp;quot;&amp;gt;bnqr&amp;lt;/span&amp;gt; are active.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Experimental modes ==&lt;br /&gt;
For both experiments, two types of environment are defined (cf MUSR experiments):&lt;br /&gt;
&lt;br /&gt;
*    &#039;&#039;&#039;Integral or TI (Type 1)&#039;&#039;&#039;&lt;br /&gt;
*    &#039;&#039;&#039;Time Differential or TD (Type 2)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
There are two separate concepts that use similar naming schemes (e.g. 1f, 20) - the timing of pulses issued by the PPG and the name of the overall experimental mode. The overall mode determines both which timing scheme is run, as well as which hardware is scanned during the run (e.g. RF frequency, Na cell voltage). Multiple experimental modes may use the same PPG timing scheme (e.g. modes 1c, 1d, 1e, 1n use the PPG timing scheme called 1n).&lt;br /&gt;
&lt;br /&gt;
Below is a full list of experimental modes, with the most common ones highlighted in bold. More details about each mode can be found on the [https://isdaq01.triumf.ca:8447/?cmd=custom&amp;amp;page=Modes BNMR mode changer] page and the [https://isdaq01.triumf.ca:8448/?cmd=custom&amp;amp;page=Modes BNQR mode changer] page.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Experimental modes&lt;br /&gt;
|-&lt;br /&gt;
! Mode name !! PPG timing !! BNMR? !! BNQR? !! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;10&#039;&#039;&#039; || 10 || &amp;amp;#10003; || &amp;amp;#10003; || No RF, nothing scanned&lt;br /&gt;
|-&lt;br /&gt;
| 1a || 1a || &amp;amp;#10003; || &amp;amp;#10003; || Scan RF frequency&lt;br /&gt;
|-&lt;br /&gt;
| 1b || 1b || &amp;amp;#10003; || &amp;amp;#10003; || Scan RF frequency&lt;br /&gt;
|-&lt;br /&gt;
| 1c || 1n || &amp;amp;#10003; || &amp;amp;#10003; || Scan settings on a Camp device&lt;br /&gt;
|-&lt;br /&gt;
| 1d || 1n || &amp;amp;#10003; || &amp;amp;#10003; || Scan the laser intensity&lt;br /&gt;
|-&lt;br /&gt;
| 1e || 1n ||  || &amp;amp;#10003; || Scan the magnetic field strength&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;1f&#039;&#039;&#039; || 1f || &amp;amp;#10003; || &amp;amp;#10003; || Scan RF frequency&lt;br /&gt;
|-&lt;br /&gt;
| 1g || 20 || &amp;amp;#10003; || &amp;amp;#10003; || Scan RF frequency&lt;br /&gt;
|-&lt;br /&gt;
| 1j || 20 || &amp;amp;#10003; || &amp;amp;#10003; || Scan settings on a Camp device&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;1n&#039;&#039;&#039; || 1n || &amp;amp;#10003; || &amp;amp;#10003; || Scan the Rb cell voltage or any other EPICS device&lt;br /&gt;
|-&lt;br /&gt;
| 1w || 1w || &amp;amp;#10003; || || Parametric scan of RF frequencies&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;1x&#039;&#039;&#039; || 1f || &amp;amp;#10003; || &amp;amp;#10003; || Scan RF frequency with one region at higher resolution&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;20&#039;&#039;&#039; || 20 || &amp;amp;#10003; || &amp;amp;#10003; || Nothing scanned&lt;br /&gt;
|-&lt;br /&gt;
| 2a || 2a || &amp;amp;#10003; || &amp;amp;#10003; || Scan RF frequency&lt;br /&gt;
|-&lt;br /&gt;
| 2b || 2b || &amp;amp;#10003; || &amp;amp;#10003; || Scan RF frequency&lt;br /&gt;
|-&lt;br /&gt;
| 2d || 1b || &amp;amp;#10003; || &amp;amp;#10003; || RF on, nothing scanned&lt;br /&gt;
|-&lt;br /&gt;
| 2e || 2e || &amp;amp;#10003; || &amp;amp;#10003; || Scan RF frequency&lt;br /&gt;
|-&lt;br /&gt;
| 2f || 2f || &amp;amp;#10003; || &amp;amp;#10003; || Scan RF frequency&lt;br /&gt;
|-&lt;br /&gt;
| 2h || 20 ||  || &amp;amp;#10003; || Read alpha channels from scalers&lt;br /&gt;
|-&lt;br /&gt;
| 2s || 2s || &amp;amp;#10003; ||  || Spin-echo&lt;br /&gt;
|-&lt;br /&gt;
| 2w || 2w || &amp;amp;#10003; ||  || RF Wurst modulation&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Any of these modes may be run in [[#Beam Control|single channel mode]]. Only Type 2 modes may be run in [[#Beam Control|dual channel mode]].&lt;br /&gt;
&lt;br /&gt;
Users change which mode is active using the webpages for each experiment, which in turn interact with the [[#Software_Components|mode changer]] python script.&lt;br /&gt;
&lt;br /&gt;
== Hardware Components ==&lt;br /&gt;
&lt;br /&gt;
DAQ hardware components for each DAQ system (BNMR/BNQR) include the following VME modules:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=1 cellspacing=3 cellpadding=10&lt;br /&gt;
|+ &amp;lt;b&amp;gt;&amp;lt;center&amp;gt; Table 2: VME Modules for each Experiment&amp;lt;/center&amp;gt;&amp;lt;/b&amp;gt;&lt;br /&gt;
|- &lt;br /&gt;
! Module  !! Description  !! VME Base Address !! BNMR? !! BNQR? !! Manual&lt;br /&gt;
|-&lt;br /&gt;
| SIS3801 version E || multichannel scaler  A || 0x2800 || &amp;amp;#10003; || ||rowspan=&amp;quot;2&amp;quot; | [[Media:Sis3801_V5_to_VE.pdf|SIS3801 manual (PDF)]]&lt;br /&gt;
|-&lt;br /&gt;
| SIS3801 version E || multichannel scaler  B || 0x1800 || &amp;amp;#10003; || &lt;br /&gt;
|- &lt;br /&gt;
| SIS3820  || multichannel scaler  B || 0x38000000 ||  || &amp;amp;#10003; || [[Media:Sis3820-M-0-001-v186-scaler.pdf|SIS3820 manual (PDF)]]&lt;br /&gt;
|- &lt;br /&gt;
| PPG (Pulseblaster)|| Pulse Programmer  ||0x8000 || &amp;amp;#10003; || &amp;amp;#10003;|| [[Media:PPG.pdf|PPG manual (PDF)]] [[Media:Spincore.pdf|Spincore Pulseblaster (PDF)]]&lt;br /&gt;
|- &lt;br /&gt;
| PSM || Pol Synthesizer module (RF)||  0x820000 ||  || &amp;amp;#10003; ||rowspan=&amp;quot;3&amp;quot; |[[BNMR:_PSM_(Pol_Synth_Module)|PSM]]&lt;br /&gt;
|-&lt;br /&gt;
| PSMII || Pol Synthesizer module II (RF) || 0x820000 || || &lt;br /&gt;
|- &lt;br /&gt;
| PSMIII|| Pol Synthesizer module III(RF) || 0x820000 || &amp;amp;#10003; || &lt;br /&gt;
|- &lt;br /&gt;
| NIMIO32 || Input/Output Register  ||0x100000 || &amp;amp;#10003; || &amp;amp;#10003; || [[VME-NIMIO32| NIMIO32]]&lt;br /&gt;
|- &lt;br /&gt;
| MVME162 || 68040 board (VxWorks) that runs CAMP  || || &amp;amp;#10003; (bnmrvw) || &amp;amp;#10003; (polvw) || &amp;lt;div id=VMIC&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
|- &lt;br /&gt;
| VMIC|| Linux machine in VME crate that runs frontend || || &amp;amp;#10003; (lxbnmr) || &amp;amp;#10003; (lxbnqr) || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The connections between the DAQ VME Modules are shown in [[BNMR DAQ Hardware Connections]].&lt;br /&gt;
&lt;br /&gt;
== Software Components ==&lt;br /&gt;
The DAQ system is based on the [https://midas.triumf.ca/MidasWiki/index.php/Midas_documentation MIDAS] package. Data acquisition software to run the  {{bnmqr|join=and}} experiments has been written to run under MIDAS. This includes the frontend, custom logger etc. This software is mostly common to both experiments, with the differences between each experiment handled by Midas ODB settings (most things) and a compile-time flag (choosing whether to build the febnmr or febnqr frontend).&lt;br /&gt;
&lt;br /&gt;
The experiment is controlled using the MIDAS webserver (mhttpd). Due to the large number of experimental parameters required, Midas custom pages have been written for the experimenters to control and monitor their experiment. &lt;br /&gt;
&lt;br /&gt;
The custom logger (mdarc/midbnmr) saves the data into MUSR MUD format files, and the MUSR CAMP slow control system is used for slow controls. Analysis is done by physica.&lt;br /&gt;
&lt;br /&gt;
The DAQ software components are started by the script &#039;&#039;start-all&#039;&#039; and stopped by the script &#039;&#039;kill-all&#039;&#039;. These include &#039;&#039;&#039;standard MIDAS utilities&#039;&#039;&#039; (e.g. [https://midas.triumf.ca/MidasWiki/index.php/Mhttpd mhttpd], [https://midas.triumf.ca/MidasWiki/index.php/Mlogger mlogger], [https://midas.triumf.ca/MidasWiki/index.php/Mserver mserver]) as well as components specific to the  {{bnmqr|join=and}} experiments.&lt;br /&gt;
&lt;br /&gt;
The main DAQ software components specific to the {{bnmqr|join=and}} experiments are shown in the table below. A full ist can be found on the [[BNMR:_Software_overview|software overview page]].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=1 cellspacing=3 cellpadding=2 style=&amp;quot;background-color:#f0f0f5&amp;quot;&lt;br /&gt;
|+  &amp;lt;b&amp;gt;&amp;lt;center&amp;gt; Table 3: DAQ Software Components&amp;lt;/center&amp;gt;&amp;lt;/b&amp;gt;&lt;br /&gt;
|- style=&amp;quot;background-color: #e0e0eb;&amp;quot;&lt;br /&gt;
! Component !! Host !! Experiment !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
|- &lt;br /&gt;
| colspan=4| &#039;&#039;Midas frontends&#039;&#039;&lt;br /&gt;
|-  style=&amp;quot;background-color:floralwhite;&amp;quot;&lt;br /&gt;
| [[BNMR: frontend|febnmr_32bit.exe]] || &#039;&#039;&#039;lxbnmr&#039;&#039;&#039; || bnmr || rowspan=2| the &#039;&#039;&#039;frontend&#039;&#039;&#039; sets up, reads out hardware modules, sends histograms.&amp;lt;br&amp;gt;The frontend code for both experiments is identical.&lt;br /&gt;
|-  style=&amp;quot;background-color:floralwhite;&amp;quot;&lt;br /&gt;
| [[BNMR: frontend|febnqr_32bit.exe]] || &#039;&#039;&#039;lxbnqr&#039;&#039;&#039; || bnqr&lt;br /&gt;
|- &lt;br /&gt;
| colspan=4| &#039;&#039;Midas clients - configuration&#039;&#039;&lt;br /&gt;
|- style=&amp;quot;background-color:mintcream&amp;quot;&lt;br /&gt;
| [[BNMR:_Mode_changer|mode_changer.py]]|| isdaq01|| both || changes between experimental modes and between real/test runs&lt;br /&gt;
|- style=&amp;quot;background-color:mintcream&amp;quot;&lt;br /&gt;
| [[BNMR:_RF_calculator|rf_calculator_fe.py]]|| isdaq01|| both || generates PPG program based on user-specified ODB parameters; reports calculated quantities in the ODB; sets up links in the ODB that should be stored in MUD files&lt;br /&gt;
|- style=&amp;quot;background-color:mintcream&amp;quot;&lt;br /&gt;
| [[BNMR:_PPG_compiler|ppg_compiler_fe.py]]|| isdaq01|| both || low-level conversion of PPG program to PPG bytecode&lt;br /&gt;
|- &lt;br /&gt;
| colspan=4| &#039;&#039;Midas clients - logging&#039;&#039;&lt;br /&gt;
|- style=&amp;quot;background-color: mintcream;&amp;quot;&lt;br /&gt;
| [[BNMR:_Data_Logging|bnxr_logger.exe]]|| isdaq01|| both|| writes data to MUD files. Reads information from midas banks (for scaler histograms), EPICS, and CAMP&lt;br /&gt;
|- style=&amp;quot;background-color: mintcream;&amp;quot;&lt;br /&gt;
| [[BNMR:_Data_Logging#Cleaning_up_if_end-of-run_fails|logger_cleanup.exe]]|| isdaq01|| both|| cleans up and archives any saved run files that were not properly archived. Run by user occasionally as needed.&lt;br /&gt;
|- style=&amp;quot;background-color:mintcream&amp;quot;&lt;br /&gt;
| [[BNMR:_Data_Logging#Run_comments|run_comment_editor.py ]]|| isdaq01|| both || responds to comments written by user in text box on the status page, saving to disk and/or midas banks&lt;br /&gt;
|- &lt;br /&gt;
| colspan=4| &#039;&#039;Other&#039;&#039;&lt;br /&gt;
|- style=&amp;quot;background-color:#ffe6e6;&amp;quot;&lt;br /&gt;
| [[BNMR: autorun|autorun]]|| isdaq01|| both|| automatic run controller&lt;br /&gt;
|- style=&amp;quot;background-color:#ffe6e6&amp;quot;&lt;br /&gt;
| [[BNMR: Scripts|scripts]]|| isdaq01 || both|| scripts perform important functions e.g. kill-all, start-all. Scripts run at the begin and end of each run send information to the elog etc. &lt;br /&gt;
|- style=&amp;quot;background-color:#ffe6e6&amp;quot;&lt;br /&gt;
| rowspan=2| [[BNMR: CAMP|camp]] || &#039;&#039;&#039;bnmrvw&#039;&#039;&#039; || bnmr || rowspan=2| MUSR slow control system&lt;br /&gt;
|- style=&amp;quot;background-color:#ffe6e6&amp;quot;&lt;br /&gt;
| &#039;&#039;&#039;polvw&#039;&#039;&#039; || bnqr&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Click the links in the above table for more details of each program.&lt;br /&gt;
&lt;br /&gt;
Not listed above are various [[BNMR:_Tests|automated test]] programs for both the C++ and python programs. There are also some interactive test programs for [[BNMR: Hardware Debugging|debugging hardware issues]].&lt;br /&gt;
&lt;br /&gt;
Note that the DAQ was rewritten in 2020. Details of the rewritten in 2020. Details of the differences between the new DAQ (documented here) and legacy DAQ (documentation removed) can be found on the [[BNMR:_Rewrite_2020|2020 rewrite]] page.&lt;br /&gt;
&lt;br /&gt;
== DAQ  Summary ==&lt;br /&gt;
;The VMIC front end computer &lt;br /&gt;
* runs the [[BNMR: frontend|frontend code]]&#039;&#039;&#039; which&lt;br /&gt;
**   controls PSM,PPG, VMEIO, Scaler modules&lt;br /&gt;
**    acquires data from SIS MCS (scaler) module(s), builds [[BNMR: Histograms and Scalers|histograms]]&lt;br /&gt;
**    uses channel access to control EPICS variable(s) (e.g. helicity)&lt;br /&gt;
**    periodically sends the data out into the data buffer&lt;br /&gt;
&lt;br /&gt;
;The host computer (isdaq01)&lt;br /&gt;
* runs all other software components which&lt;br /&gt;
** acquire the data from the data buffer&lt;br /&gt;
** log the data&lt;br /&gt;
** monitor the experiment&lt;br /&gt;
** start/stop runs&lt;br /&gt;
&lt;br /&gt;
== Tasks to be done before each beamtime ==&lt;br /&gt;
&lt;br /&gt;
* If this is the first beamtime of the year, [[BNMR:_Mode_changer#Resetting_the_run_numbers|create a new data directory and reset the run numbers]].&lt;br /&gt;
* If there have been changes to the code that affect the ODB structure, [[BNMR:_Mode_changer#Handling_changes_to_the_ODB_structure|ensure saved settings have been updated to contain the new variables]].&lt;br /&gt;
* Edit the bnmr user&#039;s cronjob (using &amp;lt;code&amp;gt;crontab -e&amp;lt;/code&amp;gt;) to specify the schedule number and date range to include in the generated Excel file. See the [[BNMR:_Shift_Monitor#beamtime_to_excel.py|supported arguments to beamtime_to_excel.py]] and the [https://mis.triumf.ca/science/schedules.jsf TRIUMF beamtime schedule].&lt;br /&gt;
* Try changing between a few common modes (e.g. 20, 1f, 1n, and back to 20) and ensure the run can start (in test mode, not real mode). You may need to disable &amp;quot;switching&amp;quot; checks on the [[BNMR:_Custom_Status_page|status page]] if the beamline is not currently configured for BNMR/BNQR.&lt;br /&gt;
&lt;br /&gt;
== Nomenclature ==&lt;br /&gt;
In this document, &amp;quot; &#039;&#039;bnmr&#039;&#039; or &#039;&#039;bnqr&#039;&#039; &amp;quot; may be written as &amp;quot; &#039;&#039;bn[&#039;&#039;&#039;mq&#039;&#039;&#039;]r&#039;&#039; &amp;quot; &lt;br /&gt;
&lt;br /&gt;
For example,  directories :&lt;br /&gt;
: &amp;lt;span style=&amp;quot;color:#004d4d; font-weight:normal; font-style:italic &amp;quot;&amp;gt;/home/&amp;lt;span style=&amp;quot;font-weight:bold;&amp;quot;&amp;gt;bnmr&amp;lt;/span&amp;gt;/online/&amp;lt;span style=&amp;quot;font-weight:bold;&amp;quot;&amp;gt;bnmr&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color:white&amp;quot;&amp;gt;spc&amp;lt;/span&amp;gt;  and &amp;lt;span style=&amp;quot;color:white&amp;quot;&amp;gt;spc&amp;lt;/span&amp;gt;  &amp;lt;span style=&amp;quot;color:#004d4d; font-weight:normal; font-style:italic &amp;quot;&amp;gt;/home/&amp;lt;span style=&amp;quot;font-weight:bold;&amp;quot;&amp;gt;bnqr&amp;lt;/span&amp;gt;/online/&amp;lt;span style=&amp;quot;font-weight:bold;&amp;quot;&amp;gt;bnqr&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
are referred to by &#039;&#039;&#039;shortcuts&#039;&#039;&#039; such as&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:white&amp;quot;&amp;gt;space&amp;lt;/span&amp;gt; {{Filepath|path=/home/bn&amp;lt;span style=&amp;quot;font-weight:bold;&amp;quot;&amp;gt;[nm]&amp;lt;/span&amp;gt;r/online/b&amp;lt;span style=&amp;quot;font-weight:bold;&amp;quot;&amp;gt;[nm]&amp;lt;/span&amp;gt;r}} &amp;lt;span style=&amp;quot;color:white&amp;quot;&amp;gt;spc&amp;lt;/span&amp;gt; and  &amp;lt;span style=&amp;quot;color:white&amp;quot;&amp;gt;spc&amp;lt;/span&amp;gt; {{Filepath|path=~/online/b&amp;lt;span style=&amp;quot;font-weight:bold;&amp;quot;&amp;gt;[nm]&amp;lt;/span&amp;gt;r}}&lt;br /&gt;
&lt;br /&gt;
Alternatively, these directories may be written as&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; {{Filepath|path=/home/&amp;lt;experiment&amp;gt;/online/&amp;lt;beamline&amp;gt;}}  &lt;br /&gt;
&amp;lt;li&amp;gt; {{Filepath|path=/home/&amp;lt;expt&amp;gt;/online/&amp;lt;beamline&amp;gt;}}  &lt;br /&gt;
&amp;lt;li&amp;gt; {{Filepath|path=~/online/&amp;lt;beamline&amp;gt;}}&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
where {{Filepath|path=&amp;lt;experiment&amp;gt;}} {{Filepath|path=&amp;lt;expt&amp;gt;}} and {{Filepath|path=&amp;lt;beamline&amp;gt;}} are {{bnmqr|join=or}}.&lt;br /&gt;
&lt;br /&gt;
[[Category:BNMR]]&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR&amp;diff=7970</id>
		<title>BNMR</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR&amp;diff=7970"/>
		<updated>2024-10-01T22:45:51Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Pagelinks}}&lt;br /&gt;
&lt;br /&gt;
== BNMR and BNQR Experiments at TRIUMF ==&lt;br /&gt;
This is the main page of the documentation for the Data Acquisition System (DAQ) for the BetaNMR (BNMR) and BetaNQR (BNQR) experiments at TRIUMF&lt;br /&gt;
&lt;br /&gt;
[[:Category:BNMR|Click here for a full list of all the pages in the BNMR documentation]].&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
The Data Acquisition System is based on the [https://midas.triumf.ca/MidasWiki/index.php/Midas_documentation MIDAS] data acquisition package. &lt;br /&gt;
&lt;br /&gt;
There are two separate &#039;&#039;&#039;beamlines&#039;&#039;&#039;, BNMR and BNQR, each with its own experimental setup :&lt;br /&gt;
&lt;br /&gt;
* {{bnmr}} running on the BNMR high-voltage platform&lt;br /&gt;
* {{bnqr}} running on the BNQR high-voltage platform&lt;br /&gt;
&lt;br /&gt;
Each experimental setup has its own  [[#Hardware Components]] (i.e. a VME crate containing DAQ modules).  Each runs as a separate MIDAS experiment named {{bnmqr|join=or}}. DAQ software specific to these experiments (MIDAS clients) run the experiments - see [[#Software Components]]. Experimenters control the experiment using the MIDAS Web Server (mhttpd).&lt;br /&gt;
  &lt;br /&gt;
== Beam Control ==&lt;br /&gt;
The main TRIUMF EPICS Control System is used to control the beam, which can be switched to either experiment&#039;s &#039;&#039;&#039;beamline&#039;&#039;&#039;.  There are two &#039;&#039;&#039;Beam Modes&#039;&#039;&#039; that the experiments can be run in:&lt;br /&gt;
&lt;br /&gt;
;     [[BNMR Dual Channel Mode #Single Channel Mode|single channel mode]]&lt;br /&gt;
: where the beam is sent to one beamline (channel) only, either BNMR or BNQR. Only &#039;&#039;&#039;one&#039;&#039;&#039; of the DAQ systems &amp;lt;span style=&amp;quot;color:#7b68ee; font-style=italic&amp;quot;&amp;gt;bnmr &amp;lt;/span&amp;gt; or &amp;lt;span style=&amp;quot;color:#20b2aa; font-style=italic&amp;quot;&amp;gt;bnqr&amp;lt;/span&amp;gt; is active.&lt;br /&gt;
;    [[BNMR Dual Channel Mode|dual channel mode]]&lt;br /&gt;
: where the beam is switched between the two beamlines (channels) BNMR and BNQR at regular intervals. &#039;&#039;&#039;Both&#039;&#039;&#039; DAQ systems  &amp;lt;span style=&amp;quot;color:#7b68ee; font-style=italic&amp;quot;&amp;gt;bnmr &amp;lt;/span&amp;gt; and &amp;lt;span style=&amp;quot;color:#20b2aa; font-style=italic&amp;quot;&amp;gt;bnqr&amp;lt;/span&amp;gt; are active.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Experimental modes ==&lt;br /&gt;
For both experiments, two types of environment are defined (cf MUSR experiments):&lt;br /&gt;
&lt;br /&gt;
*    &#039;&#039;&#039;Integral or TI (Type 1)&#039;&#039;&#039;&lt;br /&gt;
*    &#039;&#039;&#039;Time Differential or TD (Type 2)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
There are two separate concepts that use similar naming schemes (e.g. 1f, 20) - the timing of pulses issued by the PPG and the name of the overall experimental mode. The overall mode determines both which timing scheme is run, as well as which hardware is scanned during the run (e.g. RF frequency, Na cell voltage). Multiple experimental modes may use the same PPG timing scheme (e.g. modes 1c, 1d, 1e, 1n use the PPG timing scheme called 1n).&lt;br /&gt;
&lt;br /&gt;
Below is a full list of experimental modes, with the most common ones highlighted in bold. More details about each mode can be found on the [https://isdaq01.triumf.ca:8447/?cmd=custom&amp;amp;page=Modes BNMR mode changer] page and the [https://isdaq01.triumf.ca:8448/?cmd=custom&amp;amp;page=Modes BNQR mode changer] page.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Experimental modes&lt;br /&gt;
|-&lt;br /&gt;
! Mode name !! PPG timing !! BNMR? !! BNQR? !! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;10&#039;&#039;&#039; || 10 || &amp;amp;#10003; || &amp;amp;#10003; || No RF, nothing scanned&lt;br /&gt;
|-&lt;br /&gt;
| 1a || 1a || &amp;amp;#10003; || &amp;amp;#10003; || Scan RF frequency&lt;br /&gt;
|-&lt;br /&gt;
| 1b || 1b || &amp;amp;#10003; || &amp;amp;#10003; || Scan RF frequency&lt;br /&gt;
|-&lt;br /&gt;
| 1c || 1n || &amp;amp;#10003; || &amp;amp;#10003; || Scan settings on a Camp device&lt;br /&gt;
|-&lt;br /&gt;
| 1d || 1n || &amp;amp;#10003; || &amp;amp;#10003; || Scan the laser intensity&lt;br /&gt;
|-&lt;br /&gt;
| 1e || 1n ||  || &amp;amp;#10003; || Scan the magnetic field strength&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;1f&#039;&#039;&#039; || 1f || &amp;amp;#10003; || &amp;amp;#10003; || Scan RF frequency&lt;br /&gt;
|-&lt;br /&gt;
| 1g || 20 || &amp;amp;#10003; || &amp;amp;#10003; || Scan RF frequency&lt;br /&gt;
|-&lt;br /&gt;
| 1j || 20 || &amp;amp;#10003; || &amp;amp;#10003; || Scan settings on a Camp device&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;1n&#039;&#039;&#039; || 1n || &amp;amp;#10003; || &amp;amp;#10003; || Scan the Rb cell voltage or any other EPICS device&lt;br /&gt;
|-&lt;br /&gt;
| 1w || 1w || &amp;amp;#10003; || || Parametric scan of RF frequencies&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;1x&#039;&#039;&#039; || 1f || &amp;amp;#10003; || &amp;amp;#10003; || Scan RF frequency with one region at higher resolution&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;20&#039;&#039;&#039; || 20 || &amp;amp;#10003; || &amp;amp;#10003; || Nothing scanned&lt;br /&gt;
|-&lt;br /&gt;
| 2a || 2a || &amp;amp;#10003; || &amp;amp;#10003; || Scan RF frequency&lt;br /&gt;
|-&lt;br /&gt;
| 2b || 2b || &amp;amp;#10003; || &amp;amp;#10003; || Scan RF frequency&lt;br /&gt;
|-&lt;br /&gt;
| 2d || 1b || &amp;amp;#10003; || &amp;amp;#10003; || RF on, nothing scanned&lt;br /&gt;
|-&lt;br /&gt;
| 2e || 2e || &amp;amp;#10003; || &amp;amp;#10003; || Scan RF frequency&lt;br /&gt;
|-&lt;br /&gt;
| 2f || 2f || &amp;amp;#10003; || &amp;amp;#10003; || Scan RF frequency&lt;br /&gt;
|-&lt;br /&gt;
| 2h || 20 ||  || &amp;amp;#10003; || Read alpha channels from scalers&lt;br /&gt;
|-&lt;br /&gt;
| 2s || 2s || &amp;amp;#10003; ||  || Spin-echo&lt;br /&gt;
|-&lt;br /&gt;
| 2w || 2w || &amp;amp;#10003; ||  || RF Wurst modulation&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Any of these modes may be run in [[#Beam Control|single channel mode]]. Only Type 2 modes may be run in [[#Beam Control|dual channel mode]].&lt;br /&gt;
&lt;br /&gt;
Users change which mode is active using the webpages for each experiment, which in turn interact with the [[#Software_Components|mode changer]] python script.&lt;br /&gt;
&lt;br /&gt;
== Hardware Components ==&lt;br /&gt;
&lt;br /&gt;
DAQ hardware components for each DAQ system (BNMR/BNQR) include the following VME modules:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=1 cellspacing=3 cellpadding=10&lt;br /&gt;
|+ &amp;lt;b&amp;gt;&amp;lt;center&amp;gt; Table 2: VME Modules for each Experiment&amp;lt;/center&amp;gt;&amp;lt;/b&amp;gt;&lt;br /&gt;
|- &lt;br /&gt;
! Module  !! Description  !! VME Base Address !! BNMR? !! BNQR? !! Manual&lt;br /&gt;
|-&lt;br /&gt;
| SIS3801 version E || multichannel scaler  A || 0x2800 || &amp;amp;#10003; || ||rowspan=&amp;quot;2&amp;quot; | [[Media:Sis3801_V5_to_VE.pdf|SIS3801 manual (PDF)]]&lt;br /&gt;
|-&lt;br /&gt;
| SIS3801 version E || multichannel scaler  B || 0x1800 || &amp;amp;#10003; || &lt;br /&gt;
|- &lt;br /&gt;
| SIS3820  || multichannel scaler  B || 0x38000000 ||  || &amp;amp;#10003; || [[Media:Sis3820-M-0-001-v186-scaler.pdf|SIS3820 manual (PDF)]]&lt;br /&gt;
|- &lt;br /&gt;
| PPG (Pulseblaster)|| Pulse Programmer  ||0x8000 || &amp;amp;#10003; || &amp;amp;#10003;|| [[Media:PPG.pdf|PPG manual (PDF)]] [[Media:Spincore.pdf|Spincore Pulseblaster (PDF)]]&lt;br /&gt;
|- &lt;br /&gt;
| PSM || Pol Synthesizer module (RF)||  0x820000 ||  || &amp;amp;#10003; ||rowspan=&amp;quot;3&amp;quot; |[[BNMR:_PSM_(Pol_Synth_Module)|PSM]]&lt;br /&gt;
|-&lt;br /&gt;
| PSMII || Pol Synthesizer module II (RF) || 0x820000 || || &lt;br /&gt;
|- &lt;br /&gt;
| PSMIII|| Pol Synthesizer module III(RF) || 0x820000 || &amp;amp;#10003; || &lt;br /&gt;
|- &lt;br /&gt;
| NIMIO32 || Input/Output Register  ||0x100000 || &amp;amp;#10003; || &amp;amp;#10003; || [[VME-NIMIO32| NIMIO32]]&lt;br /&gt;
|- &lt;br /&gt;
| MVME162 || 68040 board (VxWorks) that runs CAMP  || || &amp;amp;#10003; (bnmrvw) || &amp;amp;#10003; (polvw) || &amp;lt;div id=VMIC&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
|- &lt;br /&gt;
| VMIC|| Linux machine in VME crate that runs frontend || || &amp;amp;#10003; (lxbnmr) || &amp;amp;#10003; (lxbnqr) || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The connections between the DAQ VME Modules are shown in [[BNMR DAQ Hardware Connections]].&lt;br /&gt;
&lt;br /&gt;
== Software Components ==&lt;br /&gt;
The DAQ system is based on the [https://midas.triumf.ca/MidasWiki/index.php/Midas_documentation MIDAS] package. Data acquisition software to run the  {{bnmqr|join=and}} experiments has been written to run under MIDAS. This includes the frontend, custom logger etc. This software is mostly common to both experiments, with the differences between each experiment handled by Midas ODB settings (most things) and a compile-time flag (choosing whether to build the febnmr or febnqr frontend).&lt;br /&gt;
&lt;br /&gt;
The experiment is controlled using the MIDAS webserver (mhttpd). Due to the large number of experimental parameters required, Midas custom pages have been written for the experimenters to control and monitor their experiment. &lt;br /&gt;
&lt;br /&gt;
The custom logger (mdarc/midbnmr) saves the data into MUSR MUD format files, and the MUSR CAMP slow control system is used for slow controls. Analysis is done by physica.&lt;br /&gt;
&lt;br /&gt;
The DAQ software components are started by the script &#039;&#039;start-all&#039;&#039; and stopped by the script &#039;&#039;kill-all&#039;&#039;. These include &#039;&#039;&#039;standard MIDAS utilities&#039;&#039;&#039; (e.g. [https://midas.triumf.ca/MidasWiki/index.php/Mhttpd mhttpd], [https://midas.triumf.ca/MidasWiki/index.php/Mlogger mlogger], [https://midas.triumf.ca/MidasWiki/index.php/Mserver mserver]) as well as components specific to the  {{bnmqr|join=and}} experiments.&lt;br /&gt;
&lt;br /&gt;
The main DAQ software components specific to the {{bnmqr|join=and}} experiments are shown in the table below. A full ist can be found on the [[BNMR:_Software_overview|software overview page]].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=1 cellspacing=3 cellpadding=2 style=&amp;quot;background-color:#f0f0f5&amp;quot;&lt;br /&gt;
|+  &amp;lt;b&amp;gt;&amp;lt;center&amp;gt; Table 3: DAQ Software Components&amp;lt;/center&amp;gt;&amp;lt;/b&amp;gt;&lt;br /&gt;
|- style=&amp;quot;background-color: #e0e0eb;&amp;quot;&lt;br /&gt;
! Component !! Host !! Experiment !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
|- &lt;br /&gt;
| colspan=4| &#039;&#039;Midas frontends&#039;&#039;&lt;br /&gt;
|-  style=&amp;quot;background-color:floralwhite;&amp;quot;&lt;br /&gt;
| [[BNMR: frontend|febnmr_32bit.exe]] || &#039;&#039;&#039;lxbnmr&#039;&#039;&#039; || bnmr || rowspan=2| the &#039;&#039;&#039;frontend&#039;&#039;&#039; sets up, reads out hardware modules, sends histograms.&amp;lt;br&amp;gt;The frontend code for both experiments is identical.&lt;br /&gt;
|-  style=&amp;quot;background-color:floralwhite;&amp;quot;&lt;br /&gt;
| [[BNMR: frontend|febnqr_32bit.exe]] || &#039;&#039;&#039;lxbnqr&#039;&#039;&#039; || bnqr&lt;br /&gt;
|- &lt;br /&gt;
| colspan=4| &#039;&#039;Midas clients - configuration&#039;&#039;&lt;br /&gt;
|- style=&amp;quot;background-color:mintcream&amp;quot;&lt;br /&gt;
| [[BNMR:_Mode_changer|mode_changer.py]]|| isdaq01|| both || changes between experimental modes and between real/test runs&lt;br /&gt;
|- style=&amp;quot;background-color:mintcream&amp;quot;&lt;br /&gt;
| [[BNMR:_RF_calculator|rf_calculator_fe.py]]|| isdaq01|| both || generates PPG program based on user-specified ODB parameters; reports calculated quantities in the ODB; sets up links in the ODB that should be stored in MUD files&lt;br /&gt;
|- style=&amp;quot;background-color:mintcream&amp;quot;&lt;br /&gt;
| [[BNMR:_PPG_compiler|ppg_compiler_fe.py]]|| isdaq01|| both || low-level conversion of PPG program to PPG bytecode&lt;br /&gt;
|- &lt;br /&gt;
| colspan=4| &#039;&#039;Midas clients - logging&#039;&#039;&lt;br /&gt;
|- style=&amp;quot;background-color: mintcream;&amp;quot;&lt;br /&gt;
| [[BNMR:_Data_Logging|bnxr_logger.exe]]|| isdaq01|| both|| writes data to MUD files. Reads information from midas banks (for scaler histograms), EPICS, and CAMP&lt;br /&gt;
|- style=&amp;quot;background-color: mintcream;&amp;quot;&lt;br /&gt;
| [[BNMR:_Data_Logging#Cleaning_up_if_end-of-run_fails|logger_cleanup.exe]]|| isdaq01|| both|| cleans up and archives any saved run files that were not properly archived. Run by user occasionally as needed.&lt;br /&gt;
|- style=&amp;quot;background-color:mintcream&amp;quot;&lt;br /&gt;
| [[BNMR:_Data_Logging#Run_comments|run_comment_editor.py ]]|| isdaq01|| both || responds to comments written by user in text box on the status page, saving to disk and/or midas banks&lt;br /&gt;
|- &lt;br /&gt;
| colspan=4| &#039;&#039;Other&#039;&#039;&lt;br /&gt;
|- style=&amp;quot;background-color:#ffe6e6;&amp;quot;&lt;br /&gt;
| [[BNMR: autorun|autorun]]|| isdaq01|| both|| automatic run controller&lt;br /&gt;
|- style=&amp;quot;background-color:#ffe6e6&amp;quot;&lt;br /&gt;
| [[BNMR: Scripts|scripts]]|| isdaq01 || both|| scripts perform important functions e.g. kill-all, start-all. Scripts run at the begin and end of each run send information to the elog etc. &lt;br /&gt;
|- style=&amp;quot;background-color:#ffe6e6&amp;quot;&lt;br /&gt;
| rowspan=2| [[BNMR: CAMP|camp]] || &#039;&#039;&#039;bnmrvw&#039;&#039;&#039; || bnmr || rowspan=2| MUSR slow control system&lt;br /&gt;
|- style=&amp;quot;background-color:#ffe6e6&amp;quot;&lt;br /&gt;
| &#039;&#039;&#039;polvw&#039;&#039;&#039; || bnqr&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Click the links in the above table for more details of each program.&lt;br /&gt;
&lt;br /&gt;
Not listed above are various [[BNMR:_Tests|automated test]] programs for both the C++ and python programs. There are also some interactive test programs for [[BNMR: Hardware Debugging|debugging hardware issues]].&lt;br /&gt;
&lt;br /&gt;
Note that the DAQ was rewritten in 2020. Details of the rewritten in 2020. Details of the differences between the new DAQ (documented here) and legacy DAQ (documentation removed) can be found on the [[BNMR:_Rewrite_2020|2020 rewrite]] page.&lt;br /&gt;
&lt;br /&gt;
== DAQ  Summary ==&lt;br /&gt;
;The VMIC front end computer &lt;br /&gt;
* runs the [[BNMR: frontend|frontend code]]&#039;&#039;&#039; which&lt;br /&gt;
**   controls PSM,PPG, VMEIO, Scaler modules&lt;br /&gt;
**    acquires data from SIS MCS (scaler) module(s), builds [[BNMR: Histograms and Scalers|histograms]]&lt;br /&gt;
**    uses channel access to control EPICS variable(s) (e.g. helicity)&lt;br /&gt;
**    periodically sends the data out into the data buffer&lt;br /&gt;
&lt;br /&gt;
;The host computer (isdaq01)&lt;br /&gt;
* runs all other software components which&lt;br /&gt;
** acquire the data from the data buffer&lt;br /&gt;
** log the data&lt;br /&gt;
** monitor the experiment&lt;br /&gt;
** start/stop runs&lt;br /&gt;
&lt;br /&gt;
== Tasks to be done before each beamtime ==&lt;br /&gt;
&lt;br /&gt;
* If this is the first beamtime of the year, [[BNMR:_Mode_changer#Resetting_the_run_numbers|create a new data directory and reset the run numbers]].&lt;br /&gt;
* If there have been changes to the code that affect the ODB structure, [[BNMR:_Mode_changer#Handling_changes_to_the_ODB_structure|ensure saved settings have been updated to contain the new variables]].&lt;br /&gt;
* Edit the bnmr user&#039;s cronjob (using &amp;lt;code&amp;gt;crontab -e&amp;lt;/code&amp;gt;) to specify the schedule number and date range to include in the generated Excel file ([[BNMR:_Shift_Monitor#beamtime_to_excel.py|see the supported arguments to beamtime_to_excel.py]]).&lt;br /&gt;
* Try changing between a few common modes (e.g. 20, 1f, 1n, and back to 20) and ensure the run can start (in test mode, not real mode). You may need to disable &amp;quot;switching&amp;quot; checks on the [[BNMR:_Custom_Status_page|status page]] if the beamline is not currently configured for BNMR/BNQR.&lt;br /&gt;
&lt;br /&gt;
== Nomenclature ==&lt;br /&gt;
In this document, &amp;quot; &#039;&#039;bnmr&#039;&#039; or &#039;&#039;bnqr&#039;&#039; &amp;quot; may be written as &amp;quot; &#039;&#039;bn[&#039;&#039;&#039;mq&#039;&#039;&#039;]r&#039;&#039; &amp;quot; &lt;br /&gt;
&lt;br /&gt;
For example,  directories :&lt;br /&gt;
: &amp;lt;span style=&amp;quot;color:#004d4d; font-weight:normal; font-style:italic &amp;quot;&amp;gt;/home/&amp;lt;span style=&amp;quot;font-weight:bold;&amp;quot;&amp;gt;bnmr&amp;lt;/span&amp;gt;/online/&amp;lt;span style=&amp;quot;font-weight:bold;&amp;quot;&amp;gt;bnmr&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color:white&amp;quot;&amp;gt;spc&amp;lt;/span&amp;gt;  and &amp;lt;span style=&amp;quot;color:white&amp;quot;&amp;gt;spc&amp;lt;/span&amp;gt;  &amp;lt;span style=&amp;quot;color:#004d4d; font-weight:normal; font-style:italic &amp;quot;&amp;gt;/home/&amp;lt;span style=&amp;quot;font-weight:bold;&amp;quot;&amp;gt;bnqr&amp;lt;/span&amp;gt;/online/&amp;lt;span style=&amp;quot;font-weight:bold;&amp;quot;&amp;gt;bnqr&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
are referred to by &#039;&#039;&#039;shortcuts&#039;&#039;&#039; such as&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:white&amp;quot;&amp;gt;space&amp;lt;/span&amp;gt; {{Filepath|path=/home/bn&amp;lt;span style=&amp;quot;font-weight:bold;&amp;quot;&amp;gt;[nm]&amp;lt;/span&amp;gt;r/online/b&amp;lt;span style=&amp;quot;font-weight:bold;&amp;quot;&amp;gt;[nm]&amp;lt;/span&amp;gt;r}} &amp;lt;span style=&amp;quot;color:white&amp;quot;&amp;gt;spc&amp;lt;/span&amp;gt; and  &amp;lt;span style=&amp;quot;color:white&amp;quot;&amp;gt;spc&amp;lt;/span&amp;gt; {{Filepath|path=~/online/b&amp;lt;span style=&amp;quot;font-weight:bold;&amp;quot;&amp;gt;[nm]&amp;lt;/span&amp;gt;r}}&lt;br /&gt;
&lt;br /&gt;
Alternatively, these directories may be written as&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; {{Filepath|path=/home/&amp;lt;experiment&amp;gt;/online/&amp;lt;beamline&amp;gt;}}  &lt;br /&gt;
&amp;lt;li&amp;gt; {{Filepath|path=/home/&amp;lt;expt&amp;gt;/online/&amp;lt;beamline&amp;gt;}}  &lt;br /&gt;
&amp;lt;li&amp;gt; {{Filepath|path=~/online/&amp;lt;beamline&amp;gt;}}&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
where {{Filepath|path=&amp;lt;experiment&amp;gt;}} {{Filepath|path=&amp;lt;expt&amp;gt;}} and {{Filepath|path=&amp;lt;beamline&amp;gt;}} are {{bnmqr|join=or}}.&lt;br /&gt;
&lt;br /&gt;
[[Category:BNMR]]&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR:_Mode_changer&amp;diff=7969</id>
		<title>BNMR: Mode changer</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR:_Mode_changer&amp;diff=7969"/>
		<updated>2024-10-01T22:38:38Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Pagelinks}}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
The mode changer program {{Client|name=mode_changer.py}} is responsible for:&lt;br /&gt;
* re-configuring the ODB when the user wants to change [[BNMR:_Experimental_Modes|experimental mode]]&lt;br /&gt;
* letting the user change between [[BNMR:_Run_numbering|real and test runs]] (including changing the run number accordingly)&lt;br /&gt;
* saving ODB settings (both manually and automatically when the user changes mode)&lt;br /&gt;
* loading ODB settings (both manually, automatically when the user changes mode, and from previous [[BNMR:_Data_Logging#MUD_files|MUD files]])&lt;br /&gt;
&lt;br /&gt;
The program is built using Midas&#039; python tools, and provides a JRPC interface that webpages can use to interact with it (e.g. getting the list of supported modes; requesting that the mode be changed).&lt;br /&gt;
&lt;br /&gt;
== Changing mode ==&lt;br /&gt;
&lt;br /&gt;
Modes are defined as a combination of features. For example:&lt;br /&gt;
* Mode &amp;lt;code&amp;gt;1c&amp;lt;/code&amp;gt; has &amp;lt;code&amp;gt;Enables CAMP scan=True&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;PPG timing=1n&amp;lt;/code&amp;gt;&lt;br /&gt;
* Mode &amp;lt;code&amp;gt;2b&amp;lt;/code&amp;gt; has &amp;lt;code&amp;gt;Enables RF=True&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;RF scanned in PPG loop=True&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;PPG timing=2b&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When changing modes, the program:&lt;br /&gt;
* saves the current ODB settings for the old mode&lt;br /&gt;
* loads the most recent settings that were used with the new mode (if available)&lt;br /&gt;
* changes the flags in {{Odbpath|path=/CurrentMode}} to those of the new mode (this lets other programs know what features should be enabled, without having to refer directly to mode names)&lt;br /&gt;
&lt;br /&gt;
== Saving and loading ODB settings ==&lt;br /&gt;
Saving and loading of ODB parameters build on the [https://bitbucket.org/ttriumfdaq/odb_save_load/src odb_save_load] package, which provides the raw tools for saving parts of the ODB as JSON files on disk, with metadata like a comment and save date.&lt;br /&gt;
&lt;br /&gt;
The mode changer program extends this functionality by automatically saving/loading settings when changing modes, and integrating the &amp;quot;manual&amp;quot; saving/loading with the custom settings page.&lt;br /&gt;
&lt;br /&gt;
=== What gets saved ===&lt;br /&gt;
&lt;br /&gt;
The definition of which bits of the ODB get saved is stored in {{Odbpath|path=/Saveload/Sections}}. It currently includes:&lt;br /&gt;
* {{Odbpath|path=/Equipment/PPGCompiler/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Equipment/PPGCompiler/Programming}}&lt;br /&gt;
* {{Odbpath|path=/Equipment/RFCalculator/PPG questions}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/PSM/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/BNXRCustomCycleLogic/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/Histograms/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/SampleReference/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/Epics/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/Camp/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/Global/Settings}}&lt;br /&gt;
* {{Odbpath|path=/Scanning/Helicity/Settings}}&lt;br /&gt;
&lt;br /&gt;
=== Handling changes to the ODB structure ===&lt;br /&gt;
&lt;br /&gt;
Experiments often edit their DAQ code to add/remove keys. This can cause a problem if you later try to load some settings that were saved with the &amp;quot;old&amp;quot; ODB structure. To avoid these issues, the {{Client|name=odb_save_load/save_load.py}} python script allows you to adjust the saved settings in a fairly user-friendly way.&lt;br /&gt;
&lt;br /&gt;
All of the commands accept an &amp;lt;code&amp;gt;--odb-path&amp;lt;/code&amp;gt; argument. The script will automatically determine which section that ODB path belongs to, find the right bit of the ODB structure in the saved file, and modify it accordingly.&lt;br /&gt;
&lt;br /&gt;
The possible commands are:&lt;br /&gt;
* &amp;lt;code&amp;gt;add_from_live&amp;lt;/code&amp;gt; - read the current value of an ODB key from the live experiment, and store it in any files that don&#039;t currently have that key. Files that already have that key present are not touched.&lt;br /&gt;
* &amp;lt;code&amp;gt;add&amp;lt;/code&amp;gt; - like add_from_live, but manually specify the value to store as the --json-value parameter. You should encode the new value as the value member of a JSON string, e.g. --json-value=&#039;{&amp;quot;value&amp;quot;: true}&#039;&amp;lt;/code&amp;gt; to store a boolean true. Files that already have the key present are not touched.&lt;br /&gt;
* &amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt; - remove the specified ODB key from all saved settings that contain it.&lt;br /&gt;
* &amp;lt;code&amp;gt;edit_from_live&amp;lt;/code&amp;gt; - like add_from_live, but also change the value in files that already have the key present.&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; - like add, but also change the value in files that already have the key present.&lt;br /&gt;
&lt;br /&gt;
A full example command would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;python save_load.py add_from_live --odb-path=&amp;quot;/Equipment/PPGCompiler/Settings/Enable formulae&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
odb_save_load/save_load.py&lt;br /&gt;
&lt;br /&gt;
=== Loading settings from a MUD file ===&lt;br /&gt;
&lt;br /&gt;
The mode changer also allows loading any [[BNMR:_Data_Logging#ODB_variables|ODB settings that were saved in the MUD file]]. It uses the [https://github.com/dfujim/bdata bdata] package to load the file and get the list of variables that were saved. The [[BNMR:_RF_calculator|RF calculator]] uses the &amp;lt;code&amp;gt;mud_ind_var_links.py&amp;lt;/code&amp;gt; file to decide which ODB variables should be saved for each mode (mapping &amp;quot;real&amp;quot; ODB locations to names in the MUD file), and the mode changer uses the same file to go in the opposite direction (mapping names in the MUD file to ODB locations).&lt;br /&gt;
&lt;br /&gt;
Unfortunately, some variables are stored differently in the MUD file vs the ODB (e.g. booleans in the ODB vs a string in the MUD file). These &amp;quot;manipulations&amp;quot; are defined in two places:&lt;br /&gt;
* ODB to MUD in &amp;lt;code&amp;gt;compute_ppg_xxx()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;ppg_prog_helper.py&amp;lt;/code&amp;gt;&lt;br /&gt;
* MUD to ODB in &amp;lt;code&amp;gt;load_from_old_run()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mode_changer.py&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that not all ODB settings are stored in the MUD file; in particular, PSM RF modulation parameters are generally not stored.&lt;br /&gt;
&lt;br /&gt;
=== Changing mode without loading saved settings ===&lt;br /&gt;
&lt;br /&gt;
Sometimes the saved settings for a mode can fail to load correctly. If this is the case, you can use the [[BNMR:_Custom_Expert_page|Expert]] webpage to change the mode and load the default settings for that mode.&lt;br /&gt;
&lt;br /&gt;
=== Changing mode from the command-line ===&lt;br /&gt;
&lt;br /&gt;
You may change the mode via a command-line interface as well as via webpages. This may be useful for scripting a series of runs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;python mode_changer.py --oneshot --mode=1f&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Changing between real and test runs ==&lt;br /&gt;
Note that the user may change between real/test while a run is in progress!&lt;br /&gt;
&lt;br /&gt;
When changing between real and test runs, the program:&lt;br /&gt;
* changes the key {{Odbpath|path=/RealOrTest/Name}} to &amp;lt;code&amp;gt;real&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt;&lt;br /&gt;
* computes the new run number to use&lt;br /&gt;
* enables the alarm system and helicity checks if changing to a real run&lt;br /&gt;
* tells the [[BNMR:_Data_Logging#bnxr_logger.exe_introduction|data logger]] about the new configuration via JRPC (this lets it rename data files that have already been written for this run and name new files appropriately). JRPC is used rather than an ODB hotlink so that errors can be reported to the user more effectively. &lt;br /&gt;
&lt;br /&gt;
== Resetting the run numbers ==&lt;br /&gt;
&lt;br /&gt;
BNMR and BNQR reuse [[BNMR:_Run_numbering|run numbers]] each year (i.e. you need to specify both the year and run number to identify a dataset).&lt;br /&gt;
&lt;br /&gt;
At the start of each year, you need to reset the first run number to be used (and where the data is being written to).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /isdaq/data1/&amp;lt;expt&amp;gt;/dlog&lt;br /&gt;
mkdir &amp;lt;year&amp;gt;&lt;br /&gt;
rm current&lt;br /&gt;
ln -s &amp;lt;year&amp;gt; current&lt;br /&gt;
python ~/packages/&amp;lt;expt&amp;gt;/bnxr_common/mode_changer.py --reset_run_numbers&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:BNMR]] [[Category:Client]]&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=Ubuntu&amp;diff=7943</id>
		<title>Ubuntu</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=Ubuntu&amp;diff=7943"/>
		<updated>2024-09-10T06:18:54Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= About Ubuntu =&lt;br /&gt;
&lt;br /&gt;
AAA&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Ubuntu version =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lsb_release -a&lt;br /&gt;
uname -a&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Ubuntu installer =&lt;br /&gt;
&lt;br /&gt;
* updated for Ububtu LTS 20.04.01, 22.04.1, 24.04 (only minor differences)&lt;br /&gt;
&lt;br /&gt;
* download the latest Ubuntu LTS desktop installer iso image&lt;br /&gt;
* dd the image to a USB key&lt;br /&gt;
* power down, disconnect all disks (all HDDs, all SSDs, all M.2)&lt;br /&gt;
* connect the SSD to be used as system disk&lt;br /&gt;
* if system will use mirrored SSDs (using ZFS mirror), leave second SSD disconnected, we will activate it later&lt;br /&gt;
* power up&lt;br /&gt;
* boot from USB key in legacy mode or UEFI mode (select this in the BIOS boot menu - F8 for ASUS, F11 for Supermicro)&lt;br /&gt;
* follow the instruction:&lt;br /&gt;
* &amp;quot;try ubuntu or install ubuntu&amp;quot; - choose &amp;quot;install&amp;quot;&lt;br /&gt;
* select language - accept default&lt;br /&gt;
* &amp;quot;updates and other software&amp;quot; - accept default settings (&amp;quot;normal install&amp;quot;)&lt;br /&gt;
* &amp;quot;installation type&amp;quot; - select &amp;quot;advanced features&amp;quot; and &amp;quot;experimental: use ZFS&amp;quot;&lt;br /&gt;
* accept partition choice&lt;br /&gt;
* &amp;quot;where are you?&amp;quot; - select &amp;quot;Vancouver&amp;quot; (PST time zone)&lt;br /&gt;
* &amp;quot;who are you?&amp;quot; - leave all fields blank, except &amp;quot;username&amp;quot; set to &amp;quot;wheel&amp;quot;, &amp;quot;password&amp;quot; set to the root password. hostname will be set later after configuring the network&lt;br /&gt;
* installation runs in a few minutes, when finished, reboot&lt;br /&gt;
* login as user wheel&lt;br /&gt;
* answer annouying questions:&lt;br /&gt;
* &amp;quot;livepatch&amp;quot; - say &amp;quot;next&amp;quot;&lt;br /&gt;
* &amp;quot;help improve&amp;quot; - select &amp;quot;do not send&amp;quot;, say &amp;quot;next&amp;quot;&lt;br /&gt;
* &amp;quot;privacy&amp;quot; - leave &amp;quot;location&amp;quot; as &amp;quot;off&amp;quot;, say &amp;quot;next&amp;quot;&lt;br /&gt;
* &amp;quot;ready to go&amp;quot;, say &amp;quot;done&amp;quot;&lt;br /&gt;
* right-click on the desktop, say &amp;quot;open in terminal&amp;quot;, a shell will open&lt;br /&gt;
* say &amp;quot;sudo /bin/bash&amp;quot;, enter the root password, you now have the root shell&lt;br /&gt;
* run nm-connection-editor to configure the network. use netmask 255.255.224.0, gateway 142.90.100.18, DNS 142.90.100.19, search path &amp;quot;triumf.ca&amp;quot;&lt;br /&gt;
* after network is up (can ping ladd00), continue with post-installation steps below&lt;br /&gt;
&lt;br /&gt;
= Install instructions =&lt;br /&gt;
&lt;br /&gt;
== prepare ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt update&lt;br /&gt;
apt upgrade&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install ssh ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install ssh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install git/scripts ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y install git&lt;br /&gt;
mkdir ~root/git&lt;br /&gt;
cd ~root/git&lt;br /&gt;
git clone https://daq00.triumf.ca/~olchansk/git/scripts.git&lt;br /&gt;
cd scripts&lt;br /&gt;
git pull&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== configure hostname ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vi /etc/hostname&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== disable swap ==&lt;br /&gt;
&lt;br /&gt;
ubuntu installer creates a 2 GB swap partition, not useful&lt;br /&gt;
on 32-64 GB machine, disable it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vi /etc/fstab ### comment out the &amp;quot;swap&amp;quot; line&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== maybe reboot ==&lt;br /&gt;
&lt;br /&gt;
this is a good point to reboot the machine to boot&lt;br /&gt;
the latest kernel and to set the correct hostname&lt;br /&gt;
&lt;br /&gt;
== install etckeeper ==&lt;br /&gt;
&lt;br /&gt;
keep contents of /etc in a git repository:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y install etckeeper&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== set timezone ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
timedatectl list-timezones | grep -i vancouver&lt;br /&gt;
timedatectl set-timezone America/Vancouver&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install time synchronization ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y install chrony&lt;br /&gt;
#echo server time1.triumf.ca iburst &amp;gt;&amp;gt; /etc/chrony/chrony.conf&lt;br /&gt;
#echo server time2.triumf.ca iburst &amp;gt;&amp;gt; /etc/chrony/chrony.conf&lt;br /&gt;
#echo server time3.triumf.ca iburst &amp;gt;&amp;gt; /etc/chrony/chrony.conf&lt;br /&gt;
cd ~/git/scripts&lt;br /&gt;
git pull&lt;br /&gt;
cd ~&lt;br /&gt;
cp ~/git/scripts/etc/triumf.sources /etc/chrony/sources.d/&lt;br /&gt;
systemctl disable systemd-timesyncd.service&lt;br /&gt;
systemctl stop systemd-timesyncd.service&lt;br /&gt;
systemctl disable ntp&lt;br /&gt;
systemctl stop ntp&lt;br /&gt;
systemctl enable chrony&lt;br /&gt;
systemctl restart chrony&lt;br /&gt;
chronyc sources&lt;br /&gt;
chronyc tracking&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
NOTE1: if time1, time2, time3 are already listed in /etc/crony/chrony.conf, please remove them and restart chrony.&lt;br /&gt;
&lt;br /&gt;
NOTE2: if time1, time2, time3 are not listed in &amp;quot;chronyc tracking&amp;quot; or if they are not selected by &amp;quot;chronyc tracking&amp;quot;, check that /etc/crony/chrony.conf contains &amp;quot;sourcedir /etc/chrony/sources.d&amp;quot;. old versions of this file may not have it.&lt;br /&gt;
&lt;br /&gt;
NOTE3: read https://chrony-project.org/faq.html#_should_i_prefer_chrony_over_timesyncd_if_i_do_not_need_to_run_a_server&lt;br /&gt;
&lt;br /&gt;
== reenable systemd-timesyncd ==&lt;br /&gt;
&lt;br /&gt;
ONLY IF CHRONY DOES NOT WORK&lt;br /&gt;
&lt;br /&gt;
To configure systemd-timesyncd, set &amp;quot;NTP=&amp;quot; in /etc/systemd/timesyncd.conf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt remove chrony&lt;br /&gt;
cat /etc/systemd/timesyncd.conf&lt;br /&gt;
systemctl enable systemd-timesyncd.service&lt;br /&gt;
systemctl restart systemd-timesyncd.service&lt;br /&gt;
systemctl status systemd-timesyncd.service&lt;br /&gt;
timedatectl status&lt;br /&gt;
timedatectl timesync-status&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== enable outgoing email (debian 11) ==&lt;br /&gt;
&lt;br /&gt;
this is different from ubuntu 20. it uses /etc/mailname and it hardwires the hostname into main.cf.&lt;br /&gt;
&lt;br /&gt;
== enable outgoing email ==&lt;br /&gt;
&lt;br /&gt;
we have an unusual email configuration. outgoing email should work to deliver error messages, notices, etc. incoming email is disabled, we do not receive email for local users.&lt;br /&gt;
&lt;br /&gt;
this causes problems with TRIUMF smtp server. if our message cannot be delivered (wrong email address or receipient computer is turned off), TRIUMF smtp server will generate a delivery failure notification email and try to send it to the &amp;quot;from&amp;quot; address of the failed message. but the &amp;quot;from&amp;quot; address does not receive any email, so another delivery failure  notification email is generated and an attempt to deliver it. which again fails, rinse and repeat.&lt;br /&gt;
&lt;br /&gt;
as solution, kray created a special rule, email from scrap.triumf.ca does not generate delivery failure notices. failed messages sit in the queue for 5 days, then they are deleted. (K.O. - confirmed with kray 3jan2024).&lt;br /&gt;
&lt;br /&gt;
to make this work we use the msmtp MTA package.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~&lt;br /&gt;
apt -y remove postfix&lt;br /&gt;
apt -y purge postfix # remove old config files&lt;br /&gt;
apt -y install mailutils msmtp msmtp-mta # say &amp;quot;no&amp;quot; to apparmor support&lt;br /&gt;
apt -y install bsd-mailx&lt;br /&gt;
cd ~/git/scripts/etc&lt;br /&gt;
git pull&lt;br /&gt;
/bin/cp -fv aliases /etc/aliases&lt;br /&gt;
/bin/cp -fv msmtprc /etc/msmtprc&lt;br /&gt;
/bin/rm -vf ~root/.forward&lt;br /&gt;
/bin/rm -vf /etc/mailname&lt;br /&gt;
Mail root&lt;br /&gt;
Subject: test&lt;br /&gt;
test&lt;br /&gt;
^D&lt;br /&gt;
CC: &amp;lt;CR&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== enable outgoing email (postfix) ==&lt;br /&gt;
&lt;br /&gt;
THIS IS OBSOLETE!!!&lt;br /&gt;
&lt;br /&gt;
* TRIUMF: use smtp.triumf.ca&lt;br /&gt;
* CERN: use cernmx.cern.ch&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install postfix ### select &amp;quot;satellite system&amp;quot;, enter full hostname &amp;quot;xxx.triumf.ca&amp;quot;, enter &amp;quot;smtp.triumf.ca&amp;quot;&lt;br /&gt;
apt install mailutils&lt;br /&gt;
dpkg-reconfigure postfix ### (if postfix already installed)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo olchansk@triumf.ca lindner@triumf.ca bsmith@triumf.ca &amp;gt;&amp;gt; ~root/.forward&lt;br /&gt;
mailx root&lt;br /&gt;
test&lt;br /&gt;
^D&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== enable ping for all users (debian 11) ==&lt;br /&gt;
&lt;br /&gt;
Without this tweak, Debian will report &amp;quot;operation not permitted&amp;quot; if a user tries to ping somewhere.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo &#039;net.ipv4.ping_group_range = 0 1000&#039; &amp;gt; /etc/sysctl.d/99-ping.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== disable apparmor ==&lt;br /&gt;
&lt;br /&gt;
On NFS-Root network booted machines!&lt;br /&gt;
&lt;br /&gt;
If &amp;quot;man man&amp;quot; returns &amp;quot;permission denied&amp;quot; and syslog reports apparmor &amp;quot;sendmsg DENIED&amp;quot; errors, disable apparmor. This is supposedly fixed in kernel 6.0 and later (to be confirmed), see https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/1784499&lt;br /&gt;
&lt;br /&gt;
Disable apparmor, see https://ubuntu.com/server/docs/security-apparmor&lt;br /&gt;
&lt;br /&gt;
This takes effect after a reboot.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl stop apparmor.service&lt;br /&gt;
systemctl disable apparmor.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install missing packages ==&lt;br /&gt;
&lt;br /&gt;
(apt eats terminal input, even the &amp;quot;yes |&amp;quot; trick does not quite work,&lt;br /&gt;
repeat the following commands until they report that everything&lt;br /&gt;
is installed)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
yes | apt -y install ssh tcsh ethtool ncat rsync strace net-tools traceroute time minicom screen git lsof debsums tmux iptables telnet&lt;br /&gt;
yes | apt -y install sysstat smartmontools lm-sensors&lt;br /&gt;
yes | apt -y install lsb-release&lt;br /&gt;
apt -y install vim # in addition to default vim-tiny, requested by IRIS&lt;br /&gt;
yes | apt -y install flex bison&lt;br /&gt;
yes | apt -y install neofetch&lt;br /&gt;
yes | apt -y install snmp snmp-mibs-downloader&lt;br /&gt;
yes | apt -y install git subversion g++ gfortran cmake doxygen&lt;br /&gt;
yes | apt -y install curl libcurl4 libcurl4-openssl-dev&lt;br /&gt;
yes | apt -y install mariadb-client ### mysql client&lt;br /&gt;
yes | apt -y install libz-dev libzstd-dev sqlite3 libsqlite3-dev unixodbc-dev&lt;br /&gt;
yes | apt -y install libssl-dev&lt;br /&gt;
yes | apt -y install emacs xemacs21 joe&lt;br /&gt;
yes | apt -y install gnuplot dos2unix&lt;br /&gt;
yes | apt -y install mutt bsd-mailx # email clients&lt;br /&gt;
yes | apt -y install liblz4-tool pbzip2&lt;br /&gt;
yes | apt -y install libc6-dev-i386 # otherwise no /usr/include/sys/types.h&lt;br /&gt;
yes | apt -y install libreadline-dev&lt;br /&gt;
yes | apt -y install ubuntu-mate-themes&lt;br /&gt;
yes | apt -y install libmotif-dev libxmu-dev&lt;br /&gt;
yes | apt -y install libusb-dev libusb-1.0-0-dev&lt;br /&gt;
yes | apt -y install i2c-tools libi2c-dev libi2c0&lt;br /&gt;
yes | apt -y install xfig gsfonts-x11 gsfonts-other # install fonts for xfig&lt;br /&gt;
yes | apt -y install libjson-perl&lt;br /&gt;
yes | apt -y install libgsl-dev # additional GNU Scientific Library&lt;br /&gt;
yes | apt -y install qt5-default # Qt development&lt;br /&gt;
yes | apt -y install python3-full python3-dev python3-dbg python3-pip ### for pyROOT&lt;br /&gt;
yes | apt -y install imagemagick imagemagick-common ckeditor # for elog&lt;br /&gt;
yes | apt -y install libjpeg-dev libjpeg-progs libjpeg-tools&lt;br /&gt;
yes | apt -y install linux-tools-common linux-tools-generic # cpupower frequency-info&lt;br /&gt;
yes | apt -y install rdesktop remmina remmina-plugin&amp;quot;*&amp;quot; # requested by POL&lt;br /&gt;
yes | apt -y install nlohmann-json3-dev # required to build MIDAS with ROOT 6.30 on Ubuntu-22&lt;br /&gt;
apt -y install dpkg-dev cmake g++ gcc binutils libx11-dev libxpm-dev libxft-dev libxext-dev python3 libssl-dev libafterimage0 # from https://root.cern/install/dependencies/&lt;br /&gt;
apt -y install gfortran libpcre3-dev xlibmesa-glu-dev libglew-dev libftgl-dev libmysqlclient-dev libfftw3-dev libcfitsio-dev graphviz-dev libldap2-dev python3-dev python3-numpy libxml2-dev libkrb5-dev libgsl0-dev qtwebengine5-dev nlohmann-json3-dev libtbb-dev libavahi-compat-libdnssd-dev # from https://root.cern/install/dependencies/&lt;br /&gt;
apt -y install u-boot-tools # for Xilinx petalinux&lt;br /&gt;
#apt -y install linux-headers-generic # to build linux kernel drivers&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ubuntu LTS 20.04:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
yes | apt -y install linux-image-generic-hwe-20.04 linux-tools-virtual-hwe-20.04 # enable linux 5.11 series kernel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ubuntu LTS 22.04:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y install linux-generic-hwe-22.04 # enable linux 6.2.0 series kernel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ubuntu LTS 24.04:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y install linux-generic-hwe-24.04 # enable linux 6.8.0 series kernel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== disable swap (debian 11) ==&lt;br /&gt;
&lt;br /&gt;
* on 64 GB RAM machines swap is not useful&lt;br /&gt;
* on machines booted from network (NFS-ROOT), swap does not work&lt;br /&gt;
* on machines running from flash (RPi, etc), flash is too slow for useful swap&lt;br /&gt;
* swap configured by linux installers invariably has wrong size and is not useful&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl disable dphys-swapfile&lt;br /&gt;
systemctl stop dphys-swapfile&lt;br /&gt;
dphys-swapfile uninstall&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== configure DNS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/git/scripts&lt;br /&gt;
git pull&lt;br /&gt;
mkdir /etc/systemd/resolved.conf.d&lt;br /&gt;
cp etc/resolved-triumf.conf /etc/systemd/resolved.conf.d/&lt;br /&gt;
systemctl restart systemd-resolved&lt;br /&gt;
resolvectl&lt;br /&gt;
#systemd-analyze cat-config systemd/resolved.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install ganglia ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y install ganglia-monitor&lt;br /&gt;
cd ~root/git/scripts/ganglia&lt;br /&gt;
git pull&lt;br /&gt;
make install&lt;br /&gt;
./ganglia-all.perl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
fix gmond start before network is ready:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /etc/systemd/system/ganglia-monitor.service.d&lt;br /&gt;
echo -e &amp;quot;[Unit]\nAfter=network-online.target\n&amp;quot; &amp;gt; /etc/systemd/system/ganglia-monitor.service.d/local.conf&lt;br /&gt;
systemctl daemon-reload&lt;br /&gt;
systemctl cat ganglia-monitor.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install gonodeinfo ==&lt;br /&gt;
&lt;br /&gt;
* go to https://bitbucket.org/dd1/gonodeinfo follow instructions:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
yes | apt-get -y install golang&lt;br /&gt;
mkdir ~/git&lt;br /&gt;
cd ~/git&lt;br /&gt;
#git clone https://bitbucket.org/dd1/gonodeinfo.git&lt;br /&gt;
git clone https://daq00.triumf.ca/~olchansk/git/gonodeinfo.git&lt;br /&gt;
cd gonodeinfo&lt;br /&gt;
git pull&lt;br /&gt;
make&lt;br /&gt;
make install # install gonodeinfo agent&lt;br /&gt;
cd ~ # this is important&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* edit /etc/gonodeinfo.conf&lt;br /&gt;
* change &amp;quot;Description&amp;quot;, &amp;quot;Location&amp;quot;, &amp;quot;User&amp;quot; and &amp;quot;Administrator&amp;quot; as appropriate (or delete them)&lt;br /&gt;
* change &amp;quot;Servers&amp;quot; to read: Servers: daq00.triumf.ca:8601&lt;br /&gt;
* run &amp;quot;gonodeinfo -v&amp;quot;&lt;br /&gt;
* if error is &amp;quot;connection refused&amp;quot;. go to the nodeinfo server to add this client to the access control list:&lt;br /&gt;
* on the gonodeinfo server: run /opt/gonodeinfo/gonodereceive.exe -a daq13&lt;br /&gt;
* try gonodeinfo again, there should be no error&lt;br /&gt;
* on the gonodeinfo server: run gonodereport, look at the web pages, the new machine should be listed now&lt;br /&gt;
&lt;br /&gt;
== install fonts for EPICS ==&lt;br /&gt;
&lt;br /&gt;
* apt install xfonts-100dpi xfonts-75dpi&lt;br /&gt;
* restart Xorg (i.e. &amp;quot;killall Xorg&amp;quot;, this will log you out from the console)&lt;br /&gt;
* xlsfonts | grep -i helvetica ### should show fonts with different sizes, not just size 0 (scalable)&lt;br /&gt;
&lt;br /&gt;
== install libz.so.1 for CentOS compatibility ==&lt;br /&gt;
&lt;br /&gt;
KO - confirm which versions on quartus need this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
yes | apt-get -y install zlib1g&lt;br /&gt;
yes | apt-get -y install zlib1g:i386 libc6:i386 libgcc1:i386 gcc-6-base:i386&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install libpng12.so.0 for Quartus compatibility ==&lt;br /&gt;
&lt;br /&gt;
(does not work anymore!!!)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://ftp.ca.debian.org/debian/pool/main/libp/libpng/libpng12-0_1.2.50-2+deb8u2_amd64.deb&lt;br /&gt;
dpkg --install libpng12-0_1.2.50-2+deb8u2_amd64.deb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install libpng12.so.0 for Quartus 13.0sp1 ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget https://daq00.triumf.ca/~olchansk/linux/libpng12.so.0&lt;br /&gt;
wget https://daq00.triumf.ca/~olchansk/linux/libpng12.so.0.50.0&lt;br /&gt;
/bin/cp -pv libpng12.so.0 libpng12.so.0.50.0 /lib/x86_64-linux-gnu/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install packages for Xilinx ==&lt;br /&gt;
&lt;br /&gt;
ubuntu LTS 22.04 vivado 2020.1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install autoconf libtool&lt;br /&gt;
apt install libtinfo5&lt;br /&gt;
apt install texinfo&lt;br /&gt;
apt install zlib1g:i386&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install packages for building ROOT ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y install libx11-dev libxpm-dev libxft-dev libxext-dev libpng-dev libjpeg-dev xlibmesa-glu-dev libxml2-dev libgsl-dev cmake&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install 32-bit libraries for PHYSICA ==&lt;br /&gt;
&lt;br /&gt;
these instructions are for running 32-bit physica executable built for SL6 on ubuntu LTS 20.04&lt;br /&gt;
&lt;br /&gt;
install physica sources (cannot build, do not have g77)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/packages&lt;br /&gt;
git clone https://bitbucket.org/ttriumfdaq/physica.git&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
install 32-bit libraries using ubuntu package manager:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install lib32z1 # libz.so&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
copy 32-bit SL6 shared libraries to /lib32&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@trinatdaq:~# cp /daq/daqstore/olchansk/daq/physica-SL6/libX11.so.6 /lib32/&lt;br /&gt;
root@trinatdaq:~# cp /daq/daqstore/olchansk/daq/physica-SL6/libgd.so.2 /lib32/&lt;br /&gt;
root@trinatdaq:~# cp /daq/daqstore/olchansk/daq/physica-SL6/libpng12.so.0 /lib32/&lt;br /&gt;
root@trinatdaq:~# cp /daq/daqstore/olchansk/daq/physica-SL6/libreadline.so.6 /lib32/&lt;br /&gt;
root@trinatdaq:~# cp /daq/daqstore/olchansk/daq/physica-SL6/libncurses.so.5 /lib32/&lt;br /&gt;
root@trinatdaq:~# cp /daq/daqstore/olchansk/daq/physica-SL6/libg2c.so.0 /lib32/&lt;br /&gt;
root@trinatdaq:~# cp /daq/daqstore/olchansk/daq/physica-SL6/libxcb.so.1 /lib32/&lt;br /&gt;
root@trinatdaq:~# cp /daq/daqstore/olchansk/daq/physica-SL6/libXpm.so.4 /lib32/&lt;br /&gt;
root@trinatdaq:~# cp /daq/daqstore/olchansk/daq/physica-SL6/libjpeg.so.62 /lib32/&lt;br /&gt;
root@trinatdaq:~# cp /daq/daqstore/olchansk/daq/physica-SL6/libfontconfig.so.1 /lib32/&lt;br /&gt;
root@trinatdaq:~# cp /daq/daqstore/olchansk/daq/physica-SL6/libfreetype.so.6 /lib32/&lt;br /&gt;
root@trinatdaq:~# cp /daq/daqstore/olchansk/daq/physica-SL6/libtinfo.so.5 /lib32/&lt;br /&gt;
root@trinatdaq:~# cp /daq/daqstore/olchansk/daq/physica-SL6/libXau.so.6 /lib32/&lt;br /&gt;
root@trinatdaq:~# cp /daq/daqstore/olchansk/daq/physica-SL6/libexpat.so.1 /lib32/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ldd should report:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
trinatdaq:trinat&amp;gt; ldd /usr/local/physica/physica.exe&lt;br /&gt;
	linux-gate.so.1 (0xf7fa2000)&lt;br /&gt;
	libX11.so.6 =&amp;gt; /lib32/libX11.so.6 (0xf7e43000)&lt;br /&gt;
	libgd.so.2 =&amp;gt; /lib32/libgd.so.2 (0xf7dfe000)&lt;br /&gt;
	libpng12.so.0 =&amp;gt; /lib32/libpng12.so.0 (0xf7dd6000)&lt;br /&gt;
	libz.so.1 =&amp;gt; /lib32/libz.so.1 (0xf7db8000)&lt;br /&gt;
	libreadline.so.6 =&amp;gt; /lib32/libreadline.so.6 (0xf7d7e000)&lt;br /&gt;
	libncurses.so.5 =&amp;gt; /lib32/libncurses.so.5 (0xf7d5b000)&lt;br /&gt;
	libg2c.so.0 =&amp;gt; /lib32/libg2c.so.0 (0xf7d3d000)&lt;br /&gt;
	libm.so.6 =&amp;gt; /lib32/libm.so.6 (0xf7c39000)&lt;br /&gt;
	libgcc_s.so.1 =&amp;gt; /lib32/libgcc_s.so.1 (0xf7c1a000)&lt;br /&gt;
	libc.so.6 =&amp;gt; /lib32/libc.so.6 (0xf7a2f000)&lt;br /&gt;
	libxcb.so.1 =&amp;gt; /lib32/libxcb.so.1 (0xf7a05000)&lt;br /&gt;
	libdl.so.2 =&amp;gt; /lib32/libdl.so.2 (0xf79ff000)&lt;br /&gt;
	libXpm.so.4 =&amp;gt; /lib32/libXpm.so.4 (0xf79ee000)&lt;br /&gt;
	libjpeg.so.62 =&amp;gt; /lib32/libjpeg.so.62 (0xf7997000)&lt;br /&gt;
	libfontconfig.so.1 =&amp;gt; /lib32/libfontconfig.so.1 (0xf7962000)&lt;br /&gt;
	libfreetype.so.6 =&amp;gt; /lib32/libfreetype.so.6 (0xf78c9000)&lt;br /&gt;
	libtinfo.so.5 =&amp;gt; /lib32/libtinfo.so.5 (0xf78b0000)&lt;br /&gt;
	/lib/ld-linux.so.2 (0xf7fa4000)&lt;br /&gt;
	libXau.so.6 =&amp;gt; /lib32/libXau.so.6 (0xf78ad000)&lt;br /&gt;
	libexpat.so.1 =&amp;gt; /lib32/libexpat.so.1 (0xf7885000)&lt;br /&gt;
trinatdaq:trinat&amp;gt; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
set login environment:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setenv TRIUMF_FONTS $HOME/packages/physica/fonts&lt;br /&gt;
setenv PHYSICA_DIR $HOME/packages/physica&lt;br /&gt;
alias physica $PHYSICA_DIR/physica-SL6-32&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/packages/physica&lt;br /&gt;
physica&lt;br /&gt;
@rangauss.pcm&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install wine ==&lt;br /&gt;
&lt;br /&gt;
As far as I know, only needed for BNMR/BNQR&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install wine winetricks&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install lightdm ==&lt;br /&gt;
&lt;br /&gt;
unlike the default gdm login manager, lightdm shows the machine hostname and does not require an extra mouse click to swicth from screen saver to login mode.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y install lightdm&lt;br /&gt;
# select lightdm&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install desktop environments ==&lt;br /&gt;
&lt;br /&gt;
note: default display manager and default desktop are deficient, please do not skip this step.&lt;br /&gt;
&lt;br /&gt;
note: if apt asks to choose the display manager, select &amp;quot;lightdm&amp;quot;&lt;br /&gt;
&lt;br /&gt;
note: KO - I recommend the &amp;quot;MATE&amp;quot; desktop.&lt;br /&gt;
&lt;br /&gt;
note: you will have to cut-and-paste this several times because &amp;quot;apt&amp;quot; eats commands, even with &amp;quot;-y&amp;quot; and even piped from &amp;quot;yes&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# install MATE desktop&lt;br /&gt;
DEBIAN_FRONTEND=noninteractive apt -y install ubuntu-mate-core ubuntu-mate-desktop ubuntu-mate-themes&lt;br /&gt;
# install Cinnamon desktop&lt;br /&gt;
DEBIAN_FRONTEND=noninteractive apt -y install cinnamon&lt;br /&gt;
# install KDE desktop&lt;br /&gt;
DEBIAN_FRONTEND=noninteractive apt -y install kubuntu-desktop&lt;br /&gt;
# install Lxqt desktop&lt;br /&gt;
DEBIAN_FRONTEND=noninteractive apt -y install lxqt&lt;br /&gt;
# install Xfce4 desktop&lt;br /&gt;
DEBIAN_FRONTEND=noninteractive apt -y install xfce4&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install ROOT ==&lt;br /&gt;
&lt;br /&gt;
Please install ROOT per instructions at https://root.cern.ch.&lt;br /&gt;
&lt;br /&gt;
NOTE1: The ROOT package available from Ubuntu repositories is severely out of date and cannot be used with MIDAS and ROOTANA. ### DO NOT DO THIS! apt-get install root-system&lt;br /&gt;
&lt;br /&gt;
NOTE2: as of 2017-Jan-09, ROOT binary kits for Ubuntu do not work (use GCC 5 instead of GCC6), build from source instead.&lt;br /&gt;
&lt;br /&gt;
== Install x2go ==&lt;br /&gt;
&lt;br /&gt;
KO - is this still needed? does it cause any security problems?&lt;br /&gt;
&lt;br /&gt;
x2go instructions, thanks to Art O.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
add-apt-repository ppa:x2go/stable&lt;br /&gt;
apt-get update&lt;br /&gt;
apt-get install x2goserver x2goserver-xsession&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== enable root login from ladd00/daq00 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ssh localhost&lt;br /&gt;
CTRL-C&lt;br /&gt;
/bin/cp ~root/git/scripts/etc/authorized_keys ~root/.ssh/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== disable ssh access from outside of TRIUMF ==&lt;br /&gt;
&lt;br /&gt;
to stop ssh login spam, disable ssh access from outside of TRIUMF. this can be done by requesting a firewall block through the helpdesk or by local firewall rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo iptables -I INPUT ! -s 142.90.0.0/255.255.0.0 -p tcp --dport 22 -j REJECT &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
/etc/rc.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== install smart-status ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ln -s ~/git/scripts/smart-status/smart-status.perl ~root/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== enable boot menu and boot messages ==&lt;br /&gt;
&lt;br /&gt;
This will enable the grub menu (with a 10 sec timeout) and&lt;br /&gt;
replace black screen with exciting linux boot messages.&lt;br /&gt;
&lt;br /&gt;
* emacs -nw /etc/default/grub&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
GRUB_DEFAULT=0&lt;br /&gt;
#GRUB_TIMEOUT_STYLE=hidden&lt;br /&gt;
GRUB_TIMEOUT=10&lt;br /&gt;
GRUB_DISTRIBUTOR=`lsb_release -i -s 2&amp;gt; /dev/null || echo Debian`&lt;br /&gt;
#GRUB_CMDLINE_LINUX_DEFAULT=&amp;quot;vga=769 video=640x480&amp;quot;&lt;br /&gt;
GRUB_CMDLINE_LINUX_DEFAULT=&amp;quot;&amp;quot;&lt;br /&gt;
GRUB_CMDLINE_LINUX=&amp;quot;&amp;quot;&lt;br /&gt;
#GRUB_GFXMODE=640x480&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* update grub config:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
grub-mkconfig -o /boot/grub/grub.cfg&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== reboot ==&lt;br /&gt;
&lt;br /&gt;
this completes installation of the base system.&lt;br /&gt;
&lt;br /&gt;
following sections modify basic ubuntu to fix known problems and to enable special stuff.&lt;br /&gt;
&lt;br /&gt;
= Enable automatic updates =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install unattended-upgrades&lt;br /&gt;
cd ~/git/scripts&lt;br /&gt;
git pull&lt;br /&gt;
/bin/cp -v etc/99apt-conf-ko /etc/apt/apt.conf.d/&lt;br /&gt;
apt-config dump | grep Unattended&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Following is obsolete:&lt;br /&gt;
&lt;br /&gt;
* emacs -nw /etc/apt/apt.conf.d/50unattended-upgrades&lt;br /&gt;
** uncomment in Allowed-Origins &amp;quot;-security&amp;quot; and &amp;quot;-updates&amp;quot;&lt;br /&gt;
** add in Allowed-Origins: &amp;quot;Google LLC:stable&amp;quot;;&lt;br /&gt;
** uncomment/add: &amp;quot;Unattended-Upgrade::Mail &amp;quot;root&amp;quot;;&lt;br /&gt;
* emacs -nw /etc/apt/apt.conf.d/10periodic&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
APT::Periodic::Update-Package-Lists &amp;quot;1&amp;quot;;&lt;br /&gt;
APT::Periodic::Download-Upgradeable-Packages &amp;quot;1&amp;quot;;&lt;br /&gt;
APT::Periodic::AutocleanInterval &amp;quot;7&amp;quot;;&lt;br /&gt;
APT::Periodic::Unattended-Upgrade &amp;quot;1&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* test: unattended-upgrade --dry-run -v&lt;br /&gt;
&lt;br /&gt;
NOTE: update-on-shutdown is disabled.&lt;br /&gt;
&lt;br /&gt;
NOTE: there is no update-on-boot, but:&lt;br /&gt;
&lt;br /&gt;
NOTE: if machine was off for a long time, the systemd update timer would have expired and it will fire soon after reboot, causing an automatic update run. this is unwanted, and there is no fix or workaround for it. K.O. June-2023.&lt;br /&gt;
&lt;br /&gt;
= Fix bpool is full (obsolete) =&lt;br /&gt;
&lt;br /&gt;
THIS IS CAUSED BY OBSOLETE PACKAGE zsys. PLEASE: apt remove zsys&lt;br /&gt;
&lt;br /&gt;
!!! only if ROOT on ZFS !!!&lt;br /&gt;
&lt;br /&gt;
There is an error in the zsys package that causes bpool to run out of space,&lt;br /&gt;
see [[#Ubuntu zsys]] for more details.&lt;br /&gt;
&lt;br /&gt;
To fix:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/git/scripts&lt;br /&gt;
git pull&lt;br /&gt;
cp etc/zsys.conf /etc/&lt;br /&gt;
zsysctl service reload&lt;br /&gt;
zsysctl service gc&lt;br /&gt;
zpool list bpool&lt;br /&gt;
zfs list bpool&lt;br /&gt;
df /boot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= IPMI instructions =&lt;br /&gt;
&lt;br /&gt;
IPMI is the board management hardware on Supermicro and other server motherboards. This includes hardware sensors - fan rotation speed, temperatures and power supply voltages.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt-get install ipmitool&lt;br /&gt;
systemctl enable ipmievd&lt;br /&gt;
systemctl restart ipmievd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Run:&lt;br /&gt;
* ipmitool sel list ### event list&lt;br /&gt;
* ipmitool sel elist ### event list&lt;br /&gt;
* ipmitool sel clear ### clear event list (if it becomes full)&lt;br /&gt;
* ipmitool sensor ### report hardware sensors&lt;br /&gt;
&lt;br /&gt;
= move /home/wheel =&lt;br /&gt;
&lt;br /&gt;
note: this MUST be done if ZFS root and NIS/autofs with /home.&lt;br /&gt;
&lt;br /&gt;
Default location of wheel&#039;s home directory will collide with autofs /home, it has to be moved,&lt;br /&gt;
for example to /wheel.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# logout from the wheel user&lt;br /&gt;
# go to another computer&lt;br /&gt;
ssh root@daqubuntuxxx&lt;br /&gt;
zfs list | grep wheel ### identify zfs name wheel_xxxxxx&lt;br /&gt;
#zfs set mountpoint=/wheel rpool/USERDATA/wheel_hm8fzh&lt;br /&gt;
zfs set mountpoint=/wheel `zfs list | grep wheel | cut -f1 -d&amp;quot; &amp;quot;`&lt;br /&gt;
zfs list | grep wheel&lt;br /&gt;
emacs -nw /etc/passwd ### change wheel&#039;s home directory from /home/wheel to /wheel&lt;br /&gt;
su - wheel ### check that user wheel still works&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will break wheel&#039;s ability to run snap programs, such as firefox, install chrome as listed below.&lt;br /&gt;
&lt;br /&gt;
= enable NIS (ubuntu 22.04, 24.04, debian 11, 12) =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y install rpcbind nis&lt;br /&gt;
echo DAQ-NIS &amp;gt;&amp;gt; /etc/defaultdomain&lt;br /&gt;
echo ypserver daq00.triumf.ca &amp;gt;&amp;gt; /etc/yp.conf&lt;br /&gt;
systemctl enable ypbind.service&lt;br /&gt;
systemctl restart ypbind.service&lt;br /&gt;
systemctl status ypbind.service&lt;br /&gt;
ypwhich -m&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
enable ypserv:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sed -i s/NISSERVER=false/NISSERVER=slave/ /etc/default/nis&lt;br /&gt;
/usr/lib/yp/ypinit -s daq00&lt;br /&gt;
echo ypserver localhost &amp;gt;&amp;gt; /etc/yp.conf&lt;br /&gt;
sed -i &amp;quot;s/ypserver .*/ypserver localhost/&amp;quot; /etc/yp.conf&lt;br /&gt;
systemctl enable ypserv&lt;br /&gt;
systemctl restart ypserv&lt;br /&gt;
systemctl restart ypbind&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
edit /etc/nsswitch.conf to read:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# begin get data from nis&lt;br /&gt;
passwd: files nis&lt;br /&gt;
group: files nis&lt;br /&gt;
shadow: files nis&lt;br /&gt;
automount:  files nis&lt;br /&gt;
netgroup: files nis&lt;br /&gt;
# end get data from nis&lt;br /&gt;
&lt;br /&gt;
#passwd: ...&lt;br /&gt;
#group: ...&lt;br /&gt;
#shadow: ...&lt;br /&gt;
&lt;br /&gt;
#netgroup: ...&lt;br /&gt;
#automount: ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
enable hourly update of nis maps:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir ~root/git&lt;br /&gt;
cd ~root/git&lt;br /&gt;
git clone https://daq00.triumf.ca/~olchansk/git/scripts.git&lt;br /&gt;
cd ~/git/scripts/etc&lt;br /&gt;
git pull&lt;br /&gt;
ln -s $PWD/ypxfr-cron-hourly /etc/cron.hourly&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this is a new machine, then on the master NIS node (daq00), add this new node to /etc/netgroup, and update NIS maps (cd /var/yp; make)&lt;br /&gt;
&lt;br /&gt;
= enable NIS (ubuntu 20.04) =&lt;br /&gt;
&lt;br /&gt;
* apt-get -y install portmap nis ### will ask for NIS domain (DAQ-NIS)&lt;br /&gt;
* dpkg-reconfigure nis ### reconfigure if already installed&lt;br /&gt;
* ypwhich -m&lt;br /&gt;
* edit /etc/default/nis&lt;br /&gt;
** set &amp;quot;NISSERVER=slave&amp;quot;&lt;br /&gt;
** Ubuntu LTS 20.04, check that &amp;quot;YPBINDARGS=&amp;quot; is blank, remove &amp;quot;-no-dbus&amp;quot; if it is there&lt;br /&gt;
* #edit /etc/yp.conf, comment-out everything, add &amp;quot;domain DAQ-NIS server localhost&amp;quot;&lt;br /&gt;
* edit /etc/yp.conf, comment-out everything, add &amp;quot;ypserver localhost&amp;quot;&lt;br /&gt;
* /usr/lib/yp/ypinit -s daq00&lt;br /&gt;
* systemctl enable nis&lt;br /&gt;
* systemctl restart nis&lt;br /&gt;
* ypwhich&lt;br /&gt;
* ypwhich -m&lt;br /&gt;
* ypcat -k passwd&lt;br /&gt;
* vi /etc/nsswitch.conf ### add the automount line, modify the passwd, group and shadow lines to read this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# begin get data from nis&lt;br /&gt;
passwd: files nis&lt;br /&gt;
group: files nis&lt;br /&gt;
shadow: files nis&lt;br /&gt;
automount:  files nis&lt;br /&gt;
netgroup: files nis&lt;br /&gt;
# end get data from nis&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* enable hourly update of NIS maps&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir ~root/git&lt;br /&gt;
cd ~root/git&lt;br /&gt;
git clone https://daq00.triumf.ca/~olchansk/git/scripts.git&lt;br /&gt;
cd ~/git/scripts/etc&lt;br /&gt;
git pull&lt;br /&gt;
ln -s $PWD/ypxfr-cron-hourly /etc/cron.hourly&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ### NOT NEEDED sudo vi /etc/idmapd.conf ### add line: &amp;quot;Domain = triumf.ca&amp;quot;&lt;br /&gt;
&lt;br /&gt;
= enable autofs =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y install autofs&lt;br /&gt;
systemctl enable autofs&lt;br /&gt;
systemctl restart autofs&lt;br /&gt;
ls -l /home/olchansk ### test autofs, check file owner is correct&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= enable NFS server =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install nfs-kernel-server&lt;br /&gt;
#edit /etc/exports&lt;br /&gt;
systemctl enable nfs-server&lt;br /&gt;
systemctl restart nfs-server&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= NIS master =&lt;br /&gt;
&lt;br /&gt;
notes for setting up the NIS master&lt;br /&gt;
&lt;br /&gt;
== wheel user ==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;wheel&amp;quot; is the default administrative user. We do not want it&#039;s password exported to NIS (encrypted password hash is world visible) and we do not want it&#039;s home directory exported to NFS (~wheel/.ssh is world visible and potentially writable: anybody can change ~wheel/.ssh/authorized_keys).&lt;br /&gt;
&lt;br /&gt;
* move wheel&#039;s home directory from /home/wheel to /wheel (see special section about this)&lt;br /&gt;
* change wheel&#039;s UID and GID from 1000 to a value below MINUID in /var/yp/Makefile&lt;br /&gt;
&lt;br /&gt;
== coherent uids ==&lt;br /&gt;
&lt;br /&gt;
we do not want system accounts defined in /etc/passwd of the NIS master&lt;br /&gt;
to be included in the NIS map &amp;quot;passwd&amp;quot;. this causes trouble on NIS clients&lt;br /&gt;
where newly installed packages fail to create local system users because same&lt;br /&gt;
user already exists in NIS.&lt;br /&gt;
&lt;br /&gt;
This is controlled by MINUID in /var/yp/Makefile.&lt;br /&gt;
&lt;br /&gt;
Historical TRIUMF uids start from around 200, but several clusters do not have any historic TRIUMF uids below 500 and MINUID is set to:&lt;br /&gt;
* DAQ-NIS: MINUID=200&lt;br /&gt;
* ISAC-NIS: MINUID=500&lt;br /&gt;
* TITAN-NIS: MINUID=500&lt;br /&gt;
* MUSR-NIS: MINUID=500&lt;br /&gt;
* TIG-NIS: MINUID=500 (100 on SL6 mother8pi)&lt;br /&gt;
&lt;br /&gt;
Ubuntu 20 has two programs to create users:&lt;br /&gt;
* adduser - creates new users with UID 1000 and up as specified in /etc/adduser.conf. No problems here.&lt;br /&gt;
* adduser --system - creates new system users with UID 100 and up as specified in /etc/adduser.conf. No problems here.&lt;br /&gt;
* useradd - creates new users with UID 1000 and up as specified in /etc/login.defs. No problems here.&lt;br /&gt;
* useradd --system - creates new system users with UID 999 and down (read &amp;quot;man useradd&amp;quot;, section at the end about SYS_UID_MAX). This collides with NIS MINUID, these system users will be included in the NIS map and cause trouble.&lt;br /&gt;
&lt;br /&gt;
This problem cannot be fixed, SYS_UID_MIN, SYS_UID_MAX and UID_MIN in /etc/login.defs do not seem&lt;br /&gt;
to have any effect on UIDs chosen by &amp;quot;useradd --system&amp;quot;. (tested on Ubuntu LTS 20.04).&lt;br /&gt;
&lt;br /&gt;
So far only these system accounts seem to be affected by this:&lt;br /&gt;
* systemd-coredump&lt;br /&gt;
* ganglia&lt;br /&gt;
&lt;br /&gt;
To fix:&lt;br /&gt;
* run &amp;quot;sort -r -n -t: -k3 /etc/passwd&amp;quot; to identify the last unused system user uid (range 100..200)&lt;br /&gt;
* run &amp;quot;sort -r -n -t: -k3 /etc/group&amp;quot; to identify the last unused system user gid (range 100.200)&lt;br /&gt;
* systemd-coredump: manually change UID and GID (package systemd-coredump is usually not installed)&lt;br /&gt;
* ganglia: same thing, then change ownership on all ganglia files.&lt;br /&gt;
&lt;br /&gt;
Also read systemd author&#039;s opinion on system vs user UIDs:&lt;br /&gt;
https://github.com/systemd/systemd/issues/4850#issuecomment-265698275&lt;br /&gt;
&lt;br /&gt;
= Fix systemd-logind NIS breakage =&lt;br /&gt;
&lt;br /&gt;
!!! THIS IS NOT NEEDED FOR UBUNTU LTS 20.04 !!!&lt;br /&gt;
&lt;br /&gt;
there is a delay in ssh logins for normal users. &amp;quot;ssh -v&amp;quot; shows the delay is after &amp;quot;pledge...&amp;quot;. this&lt;br /&gt;
fix removes the delay.&lt;br /&gt;
&lt;br /&gt;
systemd developers think that we should not use NIS and made sure there are&lt;br /&gt;
problems if we do. To give them credit, they do offer a workaround. Read this:&lt;br /&gt;
https://github.com/poettering/systemd/commit/695fe4078f0df6564a1be1c4a6a9e8a640d23b67&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /etc/systemd/system/systemd-logind.service.d&lt;br /&gt;
echo -e &amp;quot;[Service]\nIPAddressDeny=\n&amp;quot; &amp;gt; /etc/systemd/system/systemd-logind.service.d/local.conf&lt;br /&gt;
systemctl daemon-reload&lt;br /&gt;
systemctl cat systemd-logind.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Fix systemd-udevd NIS breakage =&lt;br /&gt;
&lt;br /&gt;
see same problem as above with udev getting stuck. ubuntu lts 20.04.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /etc/systemd/system/systemd-udevd.service.d&lt;br /&gt;
echo -e &amp;quot;[Service]\nIPAddressDeny=\n&amp;quot; &amp;gt; /etc/systemd/system/systemd-udevd.service.d/local.conf&lt;br /&gt;
systemctl daemon-reload&lt;br /&gt;
systemctl cat systemd-udevd.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Configure USB device permissions =&lt;br /&gt;
&lt;br /&gt;
Configure USB device permissions for user access to USB-serial devices, Altera USB Blaster, etc.&lt;br /&gt;
&lt;br /&gt;
* create file /etc/udev/rules.d/99-usb-chmod.rules with this contents:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
emacs -nw /etc/udev/rules.d/99-usb-chmod.rules&lt;br /&gt;
ACTION==&amp;quot;add&amp;quot;, SUBSYSTEM==&amp;quot;usbmisc&amp;quot;, RUN+=&amp;quot;/bin/chmod a+wr $env{DEVNAME}&amp;quot; &lt;br /&gt;
ACTION==&amp;quot;add&amp;quot;, SUBSYSTEM==&amp;quot;usb_device&amp;quot;, RUN+=&amp;quot;/bin/chmod a+wr /dev/%c&amp;quot;&lt;br /&gt;
ACTION==&amp;quot;add&amp;quot;, SUBSYSTEM==&amp;quot;usb_device&amp;quot;, RUN+=&amp;quot;/bin/chmod a+wr /proc/%c&amp;quot;&lt;br /&gt;
ACTION==&amp;quot;add&amp;quot;, ENV{DEVTYPE}==&amp;quot;usb_device&amp;quot;, RUN+=&amp;quot;/bin/chmod a+wr $env{DEVNAME}&amp;quot;&lt;br /&gt;
ACTION==&amp;quot;add&amp;quot;, ENV{DEVTYPE}==&amp;quot;usb_device&amp;quot;, RUN+=&amp;quot;/bin/chmod a+wr $env{DEVICE}&amp;quot;&lt;br /&gt;
ACTION==&amp;quot;add&amp;quot;, ENV{PHYSDEVBUS}==&amp;quot;usb-serial&amp;quot;, RUN+=&amp;quot;/bin/chmod a+wr $env{DEVNAME}&amp;quot;&lt;br /&gt;
ACTION==&amp;quot;add&amp;quot;, ENV{DEVPATH}==&amp;quot;/class/tty/ttyS*&amp;quot;, RUN+=&amp;quot;/bin/chmod a+wr $env{DEVNAME}&amp;quot;&lt;br /&gt;
ACTION==&amp;quot;add&amp;quot;, SUBSYSTEM==&amp;quot;tty&amp;quot;, DEVPATH==&amp;quot;*ttyUSB*&amp;quot;, RUN+=&amp;quot;/bin/chmod a+rw $env{DEVNAME}&amp;quot;&lt;br /&gt;
ACTION==&amp;quot;add&amp;quot;, SUBSYSTEM==&amp;quot;tty&amp;quot;, DEVPATH==&amp;quot;*ttyACM*&amp;quot;, RUN+=&amp;quot;/bin/chmod a+rw $env{DEVNAME}&amp;quot;&lt;br /&gt;
ACTION==&amp;quot;add&amp;quot;, SUBSYSTEM==&amp;quot;tty&amp;quot;, DEVPATH==&amp;quot;*ttyS*&amp;quot;, RUN+=&amp;quot;/bin/chmod a+rw $env{DEVNAME}&amp;quot;&lt;br /&gt;
ACTION==&amp;quot;add&amp;quot;, DEVPATH==&amp;quot;*video*&amp;quot;, RUN+=&amp;quot;/bin/chmod a+rw $env{DEVNAME}&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* reload udev rules: udevadm control --reload-rules&lt;br /&gt;
* apply new permissions: udevadm trigger --action=add&lt;br /&gt;
* watch udev activity: udevadm monitor -p&lt;br /&gt;
&lt;br /&gt;
= Configure lightdm display manager =&lt;br /&gt;
&lt;br /&gt;
* enable it&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo lightdm | dpkg-reconfigure -fteletype lightdm&lt;br /&gt;
systemctl disable gdm&lt;br /&gt;
systemctl disable sddm&lt;br /&gt;
systemctl enable lightdm&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* make the MATE desktop as default&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~root/git/scripts/&lt;br /&gt;
git pull&lt;br /&gt;
/bin/cp -v etc/lightdm_default_mate.conf /etc/lightdm/lightdm.conf.d/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* enable login by NIS users&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/bin/cp -v etc/lightdm_enable_nis_login.conf /etc/lightdm/lightdm.conf.d/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* restart lightdm&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl stop gdm&lt;br /&gt;
systemctl restart lightdm&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Install libpng12.so.0 =&lt;br /&gt;
&lt;br /&gt;
Quartus 16 needs libpng12:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://mirrors.kernel.org/ubuntu/pool/main/libp/libpng/libpng12-0_1.2.54-1ubuntu1_amd64.deb&lt;br /&gt;
dpkg --install libpng12-0_1.2.54-1ubuntu1_amd64.deb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Install google-chrome =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb&lt;br /&gt;
dpkg -i google-chrome-stable_current_amd64.deb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
confirm autoupdate is enabled, observe dl.google.com is present in the list of repositories:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt update&lt;br /&gt;
...&lt;br /&gt;
Get:5 https://dl.google.com/linux/chrome/deb stable/main amd64 Packages [1,094 B]&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
FOLLOWING IS OBSOLETE:&lt;br /&gt;
&lt;br /&gt;
Instructions from here:&lt;br /&gt;
https://www.ubuntuupdates.org/ppa/google_chrome?dist=stable&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -&lt;br /&gt;
sh -c &#039;echo &amp;quot;deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main&amp;quot; &amp;gt;&amp;gt; /etc/apt/sources.list.d/google-tmp.list&#039;&lt;br /&gt;
apt update&lt;br /&gt;
apt install google-chrome-stable&lt;br /&gt;
/bin/rm -f /etc/apt/sources.list.d/google-tmp.list&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Install amanda client =&lt;br /&gt;
&lt;br /&gt;
ONLY ONE MACHINES THAT HOST HOME DIRECTORIES&lt;br /&gt;
&lt;br /&gt;
* apt install amanda-client&lt;br /&gt;
* edit /etc/amandahosts&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
amanda.triumf.ca amanda amdump&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* check permissions on /etc/amandahosts:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq00:/var/log/amanda# ls -l /etc/amandahosts&lt;br /&gt;
-rw------- 1 backup backup 49 Jan 27 10:48 /etc/amandahosts&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* fix if needed: chown backup.backup /etc/amandahosts; chmod a= /etc/amandahosts; chmod u=wr /etc/amandahosts&lt;br /&gt;
* edit /etc/amanda-security.conf, add this line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
runtar:gnutar_path=/usr/bin/tar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On the amanda machine:&lt;br /&gt;
&lt;br /&gt;
* in amanda disklist, use dump type &amp;quot;bsdtcp-comp-user-tar&amp;quot;&lt;br /&gt;
* su - amanda and run amcheck -c daily daq00&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-bash-4.1$ amcheck -c daily daq00&lt;br /&gt;
&lt;br /&gt;
Amanda Backup Client Hosts Check&lt;br /&gt;
--------------------------------&lt;br /&gt;
Client check: 1 host checked in 0.092 seconds.  0 problems found.&lt;br /&gt;
&lt;br /&gt;
(brought to you by Amanda 3.3.7p1.git.685ff76d)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Enable rc.local =&lt;br /&gt;
&lt;br /&gt;
For reasons unknown, Ubuntu LTS 20.04 does not enable /etc/rc.local. Do this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/git/scripts&lt;br /&gt;
git pull&lt;br /&gt;
cp -n -v etc/rc.local /etc/&lt;br /&gt;
chmod a+rx /etc/rc.local&lt;br /&gt;
cp etc/rc-local.service /etc/systemd/system/&lt;br /&gt;
systemctl daemon-reload&lt;br /&gt;
systemctl enable rc-local&lt;br /&gt;
systemctl start rc-local&lt;br /&gt;
systemctl status rc-local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Remove unwanted packages =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt remove zsys # broken, do not use&lt;br /&gt;
apt remove sddm # login manager&lt;br /&gt;
apt remove avahi-daemon avahi-autoipd # not sure what it does, observed using 100% CPU&lt;br /&gt;
apt remove modemmanager # probes all serial ports to see if it&#039;s a modem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Disable unwanted services =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl disable mpd&lt;br /&gt;
systemctl disable snapd&lt;br /&gt;
systemctl disable ModemManager&lt;br /&gt;
systemctl --global mask tracker-extract-3.service&lt;br /&gt;
systemctl --global mask tracker-miner-fs-3.service&lt;br /&gt;
systemctl daemon-reload&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Disable sleep and suspend =&lt;br /&gt;
&lt;br /&gt;
note: we see some computers randomly shutdown or go to sleep, log files indicates the &amp;quot;sleep&amp;quot; or &amp;quot;suspend&amp;quot; button was pushed by user, but no such buttons actually exist. this is the fix for this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target systemd-suspend.service systemd-hybrid-sleep.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Enable crontab @reboot for MIDAS =&lt;br /&gt;
&lt;br /&gt;
startup scripts have a bug - cron @reboot entries for normal users can run before autofs is ready, so if the home directory is on autofs/NFS, it cannot be accessed and the cron job fails. If MIDAS is supposed to be started by cron @reboot, it will not start (there *will* be an error message in /var/log/cron).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /etc/systemd/system/cron.service.d&lt;br /&gt;
echo -e &amp;quot;[Unit]\nAfter=ypbind.service autofs.service\n&amp;quot; &amp;gt; /etc/systemd/system/cron.service.d/local.conf&lt;br /&gt;
systemctl daemon-reload&lt;br /&gt;
systemctl cat cron.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explore the systemd dependency tree using &amp;quot;systemctl list-dependencies&amp;quot; maybe with &amp;quot;--all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Visualize the exact boot sequence from previous boot: &amp;quot;systemd-analyze plot &amp;gt; xxx.svg&amp;quot;, look at the svg file using a web browser.&lt;br /&gt;
&lt;br /&gt;
Crontab entry to start midas: (install in the midas user crontab, not root crontab)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
su - midasuser&lt;br /&gt;
crontab -l&lt;br /&gt;
#@reboot /bin/bash -l -c &amp;quot;/home/trinat/bin/start-daq-applications&amp;quot;&lt;br /&gt;
#@reboot /bin/tcsh -c &amp;quot;/home/trinat/bin/start-daq-applications&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Install apache httpd proxy for midas and elog =&lt;br /&gt;
&lt;br /&gt;
This will configure the HTTPS/SSL certificate using &amp;quot;certbot&amp;quot; and &amp;quot;letsencrypt&amp;quot; and configure an HTTPS web server using apache2.&lt;br /&gt;
&lt;br /&gt;
First, configure apache2:&lt;br /&gt;
&lt;br /&gt;
* execute these commands:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y install apache2&lt;br /&gt;
cd /etc/apache2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* create new file conf-available/ssl-daq14.conf # use actual hostname instead of daq14&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SSLSessionCache         shmcb:/run/httpd/sslcache(512000)&lt;br /&gt;
SSLSessionCacheTimeout  300&lt;br /&gt;
SSLRandomSeed startup file:/dev/urandom  256&lt;br /&gt;
SSLRandomSeed connect builtin&lt;br /&gt;
SSLCryptoDevice builtin&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* create new file sites-available/daq14-ssl.conf # use actual hostname instead of daq14&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;IfModule mod_ssl.c&amp;gt;&lt;br /&gt;
    &amp;lt;VirtualHost *:443&amp;gt;&lt;br /&gt;
        ServerName daq14.triumf.ca&lt;br /&gt;
        DocumentRoot /var/www/html&lt;br /&gt;
        ErrorLog /var/log/apache2/daq14.log&lt;br /&gt;
        SSLEngine on&lt;br /&gt;
        # note SSLProtocol, SSLCipherSuite and some other settings are overwritten by /etc/letsencrypt/options-ssl-apache.conf&lt;br /&gt;
        SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1&lt;br /&gt;
        SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5:!SEED:!IDEA:!RC4&lt;br /&gt;
        ## use port specified in elogd.cfg&lt;br /&gt;
        #ProxyPass /elog/ http://localhost:8082/ retry=1 &lt;br /&gt;
        ## use mhttpd port&lt;br /&gt;
        #ProxyPass /      http://localhost:8080/ retry=1 &lt;br /&gt;
        Header always set Strict-Transport-Security &amp;quot;max-age=31536000; includeSubDomains&amp;quot;&lt;br /&gt;
        &amp;lt;Location /&amp;gt;&lt;br /&gt;
            SSLRequireSSL&lt;br /&gt;
            AuthType Basic&lt;br /&gt;
            AuthName &amp;quot;DAQ password protected site&amp;quot;&lt;br /&gt;
            Require valid-user&lt;br /&gt;
            # create password file: touch /etc/apache2/htpasswd&lt;br /&gt;
            # to add new user or change password: htpasswd /etc/apache2/htpasswd username&lt;br /&gt;
            AuthUserFile /etc/apache2/htpasswd&lt;br /&gt;
        &amp;lt;/Location&amp;gt;&lt;br /&gt;
    &amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;
&amp;lt;/IfModule&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* stop apache2 from listening on port 80: edit /etc/apache2/ports.conf, comment-out the line &amp;quot;Listen 80&amp;quot;&lt;br /&gt;
* stop apache2 from listening on port 80: edit /etc/apache2/ports.conf, comment-out the line &amp;quot;Listen 80&amp;quot;&lt;br /&gt;
* enable ssl module&lt;br /&gt;
* enable new configurations&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a2enmod ssl&lt;br /&gt;
a2enmod headers&lt;br /&gt;
a2enmod proxy&lt;br /&gt;
a2enmod proxy_http&lt;br /&gt;
a2enconf ssl-daq14&lt;br /&gt;
a2ensite daq14-ssl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* disable default ssl sites&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a2dissite 000-default-le-ssl&lt;br /&gt;
a2dissite 000-default&lt;br /&gt;
ls -l /etc/apache2/sites-enabled/ ### should show only daq14-ssl.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* check that there are no syntax problems&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apache2ctl configtest&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* enable and start apache2:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl enable apache2&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
systemctl status apache2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* apache2 may fail to start, look in /var/log/apache2/error.log and /var/log/apache2/daq14.log&lt;br /&gt;
* if it says &amp;quot;Failed to configure ... certificate&amp;quot;, proceed to the step for setting certbot.&lt;br /&gt;
* try to access https://daq14.triumf.ca&lt;br /&gt;
** you should see a complaint about self-signed certificate&lt;br /&gt;
** you should see a request for password (do not login yet)&lt;br /&gt;
** if you get &amp;quot;connection refused&amp;quot;, HTTPS port 443 may need to be enabled in the local firewall, look at documentation for ufw.&lt;br /&gt;
Second, configure certbot:&lt;br /&gt;
&lt;br /&gt;
(Note: as of 2018-01-18 certbot requires use of http port 80 to get the initial https certificate,&lt;br /&gt;
renewal can continue to use the https port 443)&lt;br /&gt;
&lt;br /&gt;
(Note: as of 2019-01-?? certbot requires use of port 80 for renewals)&lt;br /&gt;
&lt;br /&gt;
(Note: unsurprisingly, this requires outside access to connect with letsencrypt, so won&#039;t work if PC is only accessible from on-site network)&lt;br /&gt;
&lt;br /&gt;
* check that port 80 is not used by anything:&lt;br /&gt;
* netstat -an | grep LISTEN | grep ^tcp | grep 80&lt;br /&gt;
* lsof -P | grep -i tcp | grep LISTEN | grep 80&lt;br /&gt;
* if lsof reports that apache2 is listening on port 80, follow the apache2 instructions above (remove &amp;quot;listen 80&amp;quot; from apache2.conf&lt;br /&gt;
&lt;br /&gt;
* install certbot (if necessary open tcp port 80 in the firewall, see documentation for ufw):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install certbot python3-certbot-apache&lt;br /&gt;
certbot certonly --standalone --installer apache&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* then answer questions:&lt;br /&gt;
* &amp;quot;activate HTTPS for daq14.triumf.ca&amp;quot; - say ok&lt;br /&gt;
* &amp;quot;enter email address&amp;quot; - enter your own email address&lt;br /&gt;
* &amp;quot;please read terms...&amp;quot; - read the terms and say &amp;quot;agree&amp;quot;&lt;br /&gt;
* it will take a few moments...&lt;br /&gt;
* &amp;quot;congratulations...&amp;quot; - say ok.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
certbot install --apache --cert-name daq14.triumf.ca&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* then answer questions:&lt;br /&gt;
* &amp;quot;choose redirect...&amp;quot; - say &amp;quot;1&amp;quot; (no redirect)&lt;br /&gt;
* look inside /etc/apache2/sites-enabled/daq14-ssl.conf to see that SSLCertificateFile &amp;amp; co point to certbot certificates in&lt;br /&gt;
/etc/letsencrypt/live/daq14.triumf.ca/&lt;br /&gt;
* to check current renewal and to update the certbot config file in /etc/letsencrypt/renewal, run this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
certbot renew --standalone --installer apache --force-renewal&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
NOTE: this certificate will expire in 3 months, automatic renewal should work with current version of certbot&lt;br /&gt;
&lt;br /&gt;
Third, activate password protection:&lt;br /&gt;
&lt;br /&gt;
* as shown in the config file above, create password file and initial user: (replace &amp;quot;midas&amp;quot; with specific username)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch /etc/apache2/htpasswd&lt;br /&gt;
htpasswd /etc/apache2/htpasswd midas&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* restart apache2&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
systemctl status apache2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From here:&lt;br /&gt;
* enable proxy for MIDAS mhttpd - uncomment redirect in the config file above&lt;br /&gt;
* enable proxy for ELOG - ditto&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a2enmod proxy&lt;br /&gt;
a2enmod proxy_http&lt;br /&gt;
apache2ctl configtest&lt;br /&gt;
systemctl restart apache2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* try accessing MIDAS https://daq14.triumf.ca/ (make sure mhttpd is running)&lt;br /&gt;
* if it&#039;s not working, check odb setting FIXME!&lt;br /&gt;
* try accessing ELog https://daq14.triumf.ca/elog/ (make sure elogd is running)&lt;br /&gt;
* if it&#039;s not working, check elogd.cfg file and make sure&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SSL                  = 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
NOTE: if certbot fails with errors about &#039;module&#039; object has no attribute &#039;pyopenssl&#039;,&lt;br /&gt;
try this: pip install requests==2.6.0&lt;br /&gt;
&lt;br /&gt;
== generate self-signed certificate ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@alphacpc05:~# openssl req  -nodes -new -x509  -keyout server.key -out server.cert -days 1001&lt;br /&gt;
...+....+..+..........+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*....+..+...+.........+......+.+...+...+.....+...............+.........+...+.+......+...+...........+....+...+..+......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*....+......+.+...+..+.......+..+...+.......+......+...+..+...+......+....+...............+..+...+....+...........+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++&lt;br /&gt;
......+......+.+..+......+.+......+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.+.....+......+.+.........+......+.....+.+..+...+.......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.......+....+......+.....+...+...+.......+..+.+........+.+...+......+..+..........+..+.+...........+...+.......+......+.....+.......+...+.........+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++&lt;br /&gt;
-----&lt;br /&gt;
You are about to be asked to enter information that will be incorporated&lt;br /&gt;
into your certificate request.&lt;br /&gt;
What you are about to enter is what is called a Distinguished Name or a DN.&lt;br /&gt;
There are quite a few fields but you can leave some blank&lt;br /&gt;
For some fields there will be a default value,&lt;br /&gt;
If you enter &#039;.&#039;, the field will be left blank.&lt;br /&gt;
-----&lt;br /&gt;
Country Name (2 letter code) [AU]:CH&lt;br /&gt;
State or Province Name (full name) [Some-State]:Geneve&lt;br /&gt;
Locality Name (eg, city) []:CERN&lt;br /&gt;
Organization Name (eg, company) [Internet Widgits Pty Ltd]:CERN&lt;br /&gt;
Organizational Unit Name (eg, section) []:ALPHA experiment           &lt;br /&gt;
Common Name (e.g. server FQDN or YOUR name) []:alphacpc05.cern.ch&lt;br /&gt;
Email Address []:&lt;br /&gt;
root@alphacpc05:~# &lt;br /&gt;
root@alphacpc05:~# &lt;br /&gt;
root@alphacpc05:~# ls -l&lt;br /&gt;
-rw-r--r-- 1 root root 1375 juil. 10 21:43 server.cert&lt;br /&gt;
-rw------- 1 root root 1708 juil. 10 21:42 server.key&lt;br /&gt;
root@alphacpc05:~# systemctl restart apache2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Enable elog PDF preview =&lt;br /&gt;
&lt;br /&gt;
see https://stackoverflow.com/questions/52998331/imagemagick-security-policy-pdf-blocking-conversion&lt;br /&gt;
&lt;br /&gt;
* xemacs -nw /etc/ImageMagick-6/policy.xml&lt;br /&gt;
* remove this section at the end:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;!-- disable ghostscript format types --&amp;gt;&lt;br /&gt;
&amp;lt;policy domain=&amp;quot;coder&amp;quot; rights=&amp;quot;none&amp;quot; pattern=&amp;quot;PS&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;policy domain=&amp;quot;coder&amp;quot; rights=&amp;quot;none&amp;quot; pattern=&amp;quot;PS2&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;policy domain=&amp;quot;coder&amp;quot; rights=&amp;quot;none&amp;quot; pattern=&amp;quot;PS3&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;policy domain=&amp;quot;coder&amp;quot; rights=&amp;quot;none&amp;quot; pattern=&amp;quot;EPS&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;policy domain=&amp;quot;coder&amp;quot; rights=&amp;quot;none&amp;quot; pattern=&amp;quot;PDF&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;policy domain=&amp;quot;coder&amp;quot; rights=&amp;quot;none&amp;quot; pattern=&amp;quot;XPS&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Install Jupyter notebook =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
From https://jupyter.org/install&lt;br /&gt;
apt install python3-pip&lt;br /&gt;
pip install jupyterlab&lt;br /&gt;
pip install notebook&lt;br /&gt;
~/.local/bin/jupyter notebook&lt;br /&gt;
watch the http://localhost:8888 URL that it printed&lt;br /&gt;
say &amp;quot;no&amp;quot; to offer to start firefox (it will not work!)&lt;br /&gt;
URL is: http://localhost:8888/tree?token=xxx&lt;br /&gt;
from the machine where you are running the web browser (i.e. google-chrome), run (replace trinat@trinatdaq with the username and machine name where you started jupyter)&lt;br /&gt;
open a new shell and run: ssh -v trinat@trinatdaq -L 8888:localhost:8888&lt;br /&gt;
in the web browser, open http://localhost:8888&lt;br /&gt;
this gives us the login page&lt;br /&gt;
in the password or token entry field, put the token from the &amp;quot;tree?token=xxx&amp;quot; above (printed by jupyter on startup)&lt;br /&gt;
push button &amp;quot;login&amp;quot;&lt;br /&gt;
jupyter page should open with the list of files in the trinat home directory&lt;br /&gt;
congratulate Brian with full success&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Install ZFS quota report =&lt;br /&gt;
&lt;br /&gt;
If there are any ZFS volumes, install script to report disk and quota usage&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/git/scripts/quotareport&lt;br /&gt;
git pull&lt;br /&gt;
mkdir /var/www/html/zfsquotareport&lt;br /&gt;
cp -pv ~/git/scripts/quotareport/sorttable.js /var/www/html/zfsquotareport/&lt;br /&gt;
ln -s $PWD/zfsquotareport.perl /etc/cron.daily/&lt;br /&gt;
touch /etc/crontab&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If httpd is configured to redirect &amp;quot;/&amp;quot; to MIDAS mhttpd:&lt;br /&gt;
* add following to /etc/apache2/sites-enabled/xxx-ssl.conf in front of &amp;quot;ProxyPass / ...&amp;quot;&lt;br /&gt;
* run &amp;quot;systemctl reload apache2&amp;quot;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
## do not proxy zfs quota report directory &lt;br /&gt;
ProxyPass /zfsquotareport/ ! &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Install PHP =&lt;br /&gt;
&lt;br /&gt;
* apt install php libapache2-mod-php&lt;br /&gt;
* systemctl restart apache2&lt;br /&gt;
* create /var/www/html/info.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php &lt;br /&gt;
 &lt;br /&gt;
phpinfo(); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* open https://daq00.triumf.ca/info.php&lt;br /&gt;
&lt;br /&gt;
= Configure TRIUMF printers =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl stop cups&lt;br /&gt;
systemctl disable cups&lt;br /&gt;
echo &amp;quot;ServerName printers.triumf.ca&amp;quot; &amp;gt; /etc/cups/client.conf&lt;br /&gt;
lpstat -a&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Enable core dumps =&lt;br /&gt;
&lt;br /&gt;
By default, Ubuntu LTS 20.04 installs the apport package&lt;br /&gt;
which disabled core dumps from user applications. (google it up!).&lt;br /&gt;
It is not meant to do this and documentation claims that&lt;br /&gt;
it is not installed and not enabled by default. Oh, well...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt remove apport&lt;br /&gt;
apt autoremove ### will remove apport-symptoms and a few other packages&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After this, core dumps are written to file &amp;quot;core&amp;quot; in the current directory.&lt;br /&gt;
See /proc/sys/kernel/core_pattern and /proc/sys/kernel/core_uses_pid.&lt;br /&gt;
&lt;br /&gt;
Enable core dump file names to include process id, add following to /etc/rc.local&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/kernel/core_uses_pid&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Enable debugger =&lt;br /&gt;
&lt;br /&gt;
By default, Ubuntu LTS 20.04 does not permit debugger to attach and debug&lt;br /&gt;
already running programs. To enable it, add following to /etc/rc.local&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 0 &amp;gt; /proc/sys/kernel/yama/ptrace_scope&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Disable Ubuntu Pro nag =&lt;br /&gt;
&lt;br /&gt;
If &amp;quot;apt upgrade&amp;quot; requests Ubuntu Pro or esm-apps, disable the nag:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/bin/rm /etc/apt/apt.conf.d/20apt-esm-hook.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Update packages =&lt;br /&gt;
&lt;br /&gt;
* apt-get update # update package list&lt;br /&gt;
* apt-get dist-upgrade # install updated packages and update &amp;quot;kept back&amp;quot; packages&lt;br /&gt;
* apt-get autoremove # remove packages that apt thinks should be removed&lt;br /&gt;
&lt;br /&gt;
= Finish installation =&lt;br /&gt;
&lt;br /&gt;
Congratulations. There is nothing more to do!&lt;br /&gt;
&lt;br /&gt;
* reboot&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
shutdown -r now&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Update to new version of Ubuntu =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
vi /etc/update-manager/release-upgrades # set &amp;quot;Prompt=normal&amp;quot;&lt;br /&gt;
do-release-upgrade&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Update Ubuntu LTS 20.04 to LTS 22.04:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt remove zsys&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== daqubuntu ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# reboot to clear out all updates&lt;br /&gt;
# vi /etc/update-manager/release-upgrades # set &amp;quot;Prompt=normal&amp;quot;&lt;br /&gt;
# do-release-upgrade -c&lt;br /&gt;
Checking for a new Ubuntu release&lt;br /&gt;
New release &#039;22.04 LTS&#039; available.&lt;br /&gt;
Run &#039;do-release-upgrade&#039; to upgrade to it.&lt;br /&gt;
# do-release-upgrade&lt;br /&gt;
...&lt;br /&gt;
say yes...&lt;br /&gt;
...&lt;br /&gt;
login.defs, say &amp;quot;Y&amp;quot; (erase local changes, use packaged version)&lt;br /&gt;
/etc/systemd/resolved.conf, say &amp;quot;Y&amp;quot; (same as above)&lt;br /&gt;
firefox snap, say yes&lt;br /&gt;
unable to reach snap store, say &amp;quot;skip&amp;quot;&lt;br /&gt;
/etc/gmond.conf, say &amp;quot;Y&amp;quot;&lt;br /&gt;
/var/yp/Makefile, say &amp;quot;install the package maintainer&#039;s version&amp;quot;&lt;br /&gt;
/etc/ypserv.conf, same thing&lt;br /&gt;
/etc/ypserv.securenets, same thing&lt;br /&gt;
/etc/default/nis, same thing&lt;br /&gt;
/etc/speech-dispatcher/modules/mary-generic.conf, same thing&lt;br /&gt;
/etc/apt/apt.conf.d/50unattended-upgrades, same thing&lt;br /&gt;
...&lt;br /&gt;
278 packages are going to be removed, say yes&lt;br /&gt;
...&lt;br /&gt;
restart required, say yes&lt;br /&gt;
...&lt;br /&gt;
no ping... yes ping...&lt;br /&gt;
...&lt;br /&gt;
ssh daqubuntu, ok&lt;br /&gt;
apt update, fail, DNS does not work, &amp;quot;host security.ubuntu.com&amp;quot; does not resolve.&lt;br /&gt;
fix resolver per https://daq00.triumf.ca/DaqWiki/index.php/Ubuntu#Disable_NetworkManager&lt;br /&gt;
apt update, apt upgrade now works, 0 packages to update&lt;br /&gt;
NIS does not work.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== midm9a ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
login.defs&lt;br /&gt;
firefox snap&lt;br /&gt;
gmond.conf&lt;br /&gt;
ypserv&lt;br /&gt;
/etc/default/nis&lt;br /&gt;
unattended-upgrades&lt;br /&gt;
amanda-security.conf&lt;br /&gt;
remove obsolete (no)&lt;br /&gt;
reboot&lt;br /&gt;
configure dns&lt;br /&gt;
reenable nis&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== daq17 ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
firefox snap&lt;br /&gt;
imagemagick policy.xml&lt;br /&gt;
gmond.conf&lt;br /&gt;
chrony.conf&lt;br /&gt;
/var/yp/Makefile&lt;br /&gt;
ypserv.conf&lt;br /&gt;
ypserv.securenets&lt;br /&gt;
/etc/default/nis&lt;br /&gt;
50unattended-upgrades&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== daq00 ==&lt;br /&gt;
&lt;br /&gt;
per https://serverpilot.io/docs/how-to-upgrade-ubuntu-20.04-to-22.04/&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
do-release-upgrade -f DistUpgradeViewNonInteractive&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
if it exists &amp;quot;too soon&amp;quot; without doing anything, run it without &amp;quot;-f xxx&amp;quot;, most likely it does not like something about this machine. in case of daq00 it did not like how the EFI partitions were mounted. after fixing it, non-interactive upgrade was successful.&lt;br /&gt;
&lt;br /&gt;
== isdaq08 ==&lt;br /&gt;
&lt;br /&gt;
* prepare&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/git/scripts&lt;br /&gt;
git pull&lt;br /&gt;
cd ~&lt;br /&gt;
apt -y install debsums&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* check for modified config files that make upgrade unhappy, deal with all files reported by debsums.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@isdaq08:~# debsums -ce&lt;br /&gt;
/etc/ganglia/gmond.conf&lt;br /&gt;
/etc/yp.conf&lt;br /&gt;
/etc/apt/apt.conf.d/10periodic&lt;br /&gt;
root@isdaq08:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* restore original /etc/apt/apt.conf.d/10periodic&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
APT::Periodic::Update-Package-Lists &amp;quot;1&amp;quot;; &lt;br /&gt;
APT::Periodic::Download-Upgradeable-Packages &amp;quot;0&amp;quot;; &lt;br /&gt;
APT::Periodic::AutocleanInterval &amp;quot;0&amp;quot;; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* apt remove ganglia-monitor&lt;br /&gt;
* apt remove nis&lt;br /&gt;
* &amp;quot;debsums -ce&amp;quot; is now empty&lt;br /&gt;
&lt;br /&gt;
Run the upgrade:&lt;br /&gt;
&lt;br /&gt;
* do-release-upgrade -f DistUpgradeViewNonInteractive&lt;br /&gt;
&lt;br /&gt;
Post upgrade:&lt;br /&gt;
&lt;br /&gt;
* configure DNS&lt;br /&gt;
* apt -y install linux-generic-hwe-22.04&lt;br /&gt;
* /bin/cp -v ~/git/scripts/etc/99apt-conf-ko /etc/apt/apt.conf.d/ # restore nightly updates&lt;br /&gt;
* /bin/rm /etc/apt/apt.conf.d/20apt-esm-hook.conf # remove the ubuntu-pro nag&lt;br /&gt;
* install missing packages&lt;br /&gt;
* restore ganglia&lt;br /&gt;
* restore nis&lt;br /&gt;
* check zpool status, may need zpool upgrade&lt;br /&gt;
* reboot&lt;br /&gt;
&lt;br /&gt;
== daqubuntu, U-24 ==&lt;br /&gt;
&lt;br /&gt;
* prepare&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~/git/scripts&lt;br /&gt;
git pull&lt;br /&gt;
cd ~&lt;br /&gt;
apt -y install debsums&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* check for modified config files that make upgrade unhappy, deal with all files reported by debsums.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daqubuntu:~# debsums -ce&lt;br /&gt;
/etc/ganglia/gmond.conf&lt;br /&gt;
debsums: missing file /etc/init.d/nis (from nis package)&lt;br /&gt;
/etc/default/nis&lt;br /&gt;
/etc/ypserv.conf&lt;br /&gt;
/etc/ypserv.securenets&lt;br /&gt;
/var/yp/Makefile&lt;br /&gt;
/etc/update-manager/release-upgrades&lt;br /&gt;
/etc/apt/apt.conf.d/10periodic&lt;br /&gt;
/etc/yp.conf&lt;br /&gt;
root@daqubuntu:~# &lt;br /&gt;
* restore original /etc/apt/apt.conf.d/10periodic&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
APT::Periodic::Update-Package-Lists &amp;quot;1&amp;quot;; &lt;br /&gt;
APT::Periodic::Download-Upgradeable-Packages &amp;quot;0&amp;quot;; &lt;br /&gt;
APT::Periodic::AutocleanInterval &amp;quot;0&amp;quot;; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* apt remove ganglia-monitor&lt;br /&gt;
* apt remove nis&lt;br /&gt;
* apt autoremove&lt;br /&gt;
* restore original release-upgrades: &amp;quot;Prompt: lts&amp;quot;&lt;br /&gt;
* &amp;quot;debsums -ce&amp;quot; is now empty&lt;br /&gt;
&lt;br /&gt;
Check for upgrade:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daqubuntu:~# do-release-upgrade -c&lt;br /&gt;
Checking for a new Ubuntu release&lt;br /&gt;
There is no development version of an LTS available.&lt;br /&gt;
To upgrade to the latest non-LTS development release &lt;br /&gt;
set Prompt=normal in /etc/update-manager/release-upgrades.&lt;br /&gt;
root@daqubuntu:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Run the upgrade:&lt;br /&gt;
&lt;br /&gt;
* do-release-upgrade -f DistUpgradeViewNonInteractive&lt;br /&gt;
&lt;br /&gt;
Post upgrade:&lt;br /&gt;
&lt;br /&gt;
* configure DNS&lt;br /&gt;
* apt -y install linux-generic-hwe-22.04&lt;br /&gt;
* /bin/cp -v ~/git/scripts/etc/99apt-conf-ko /etc/apt/apt.conf.d/ # restore nightly updates&lt;br /&gt;
* /bin/rm /etc/apt/apt.conf.d/20apt-esm-hook.conf # remove the ubuntu-pro nag&lt;br /&gt;
* install missing packages&lt;br /&gt;
* restore ganglia&lt;br /&gt;
* restore nis&lt;br /&gt;
* check zpool status, may need zpool upgrade&lt;br /&gt;
* reboot&lt;br /&gt;
&lt;br /&gt;
= Upgrade to new version of Debian =&lt;br /&gt;
&lt;br /&gt;
https://www.debian.org/releases/bookworm/amd64/release-notes/ch-upgrading.en.html&lt;br /&gt;
&lt;br /&gt;
== 32-bit VME processor Debian 11 to 12 ==&lt;br /&gt;
&lt;br /&gt;
* cd git/scripts; git pull; cd ~&lt;br /&gt;
* apt update&lt;br /&gt;
* apt upgrade&lt;br /&gt;
* edit /etc/apt/sources.list&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
deb http://deb.debian.org/debian/ bookworm main&lt;br /&gt;
#deb http://deb.debian.org/debian/ bullseye main&lt;br /&gt;
#deb-src http://deb.debian.org/debian/ bullseye main&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* apt update&lt;br /&gt;
* apt upgrade --without-new-pkgs&lt;br /&gt;
* apt full-upgrade&lt;br /&gt;
* apt list &#039;~c&#039;; apt purge &#039;~c&#039; # purge left-over config files [residual-config]&lt;br /&gt;
* reboot&lt;br /&gt;
&lt;br /&gt;
= Ubuntu package manager =&lt;br /&gt;
&lt;br /&gt;
* apt-get install xxx # install package xxx&lt;br /&gt;
* apt-get update&lt;br /&gt;
* apt-get upgrade&lt;br /&gt;
* apt-get dist-upgrade&lt;br /&gt;
* apt-get autoremove # remove automatically installed packages required by a removed package&lt;br /&gt;
* apt-get remove xxx # remove package xxx&lt;br /&gt;
* apt-cache search . # list all available packages&lt;br /&gt;
* apt-cache show &amp;quot;.&amp;quot; | grep ^Package # list al available packages&lt;br /&gt;
* apt-cache madison root-system # show all available versions of package root-system&lt;br /&gt;
* apt list # list all installed packages&lt;br /&gt;
* dpkg --listfiles libpng16-16 # list all files from this package&lt;br /&gt;
* apt list --installed # list all installed packages&lt;br /&gt;
* dpkg -S /bin/bash # what package provides this file?&lt;br /&gt;
* dpkg -L bash # what files provided by this package?&lt;br /&gt;
* debsums -ce # show modified config files&lt;br /&gt;
* apt-config dump # show apt configuration&lt;br /&gt;
&lt;br /&gt;
= Ubuntu zsys =&lt;br /&gt;
&lt;br /&gt;
NOTE: DO NOT USE ZSYS, see https://github.com/ubuntu/zsys/issues/218 and https://github.com/ubuntu/zsys/issues/230&lt;br /&gt;
&lt;br /&gt;
* manual removal of old snapshots&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zsysctl show&lt;br /&gt;
zsysctl state remove xy69ye -s&lt;br /&gt;
zsysctl state remove xy69ye&lt;br /&gt;
zsysctl state remove xy69ye -u wheel&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* apt remove zsys&lt;br /&gt;
&lt;br /&gt;
NOTE: old zsys snapshots must be cleaned manually, &amp;quot;zsysctl state remove xxx --system&amp;quot; is broken and does not remove user data snapshots&lt;br /&gt;
&lt;br /&gt;
* manages system snapshots&lt;br /&gt;
* documentation: https://github.com/ubuntu/zsys&lt;br /&gt;
* documentation: (go to next article via link &amp;quot;newer&amp;quot; at the bottom) https://didrocks.fr/2020/05/21/zfs-focus-on-ubuntu-20.04-lts-whats-new/&lt;br /&gt;
* ubuntu 20.04 bug, too many snapshots cause /boot to become full and updates fail. https://github.com/ubuntu/zsys/issues/155&lt;br /&gt;
* solution: use custom /etc/zsys.conf, limit number of snapshots to 10, see trinatdaq:/etc/zsys.conf&lt;br /&gt;
* zsys commands:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
update-grub # list of all snapshots, errors if some snapshots are broken&lt;br /&gt;
zsysctl state remove lnc0k7 --system # remove snapshot&lt;br /&gt;
xemacs -nw /etc/zsys.conf; zsysctl service reload; zsysctl service gc # cause gc to run with new settings in zsys.conf&lt;br /&gt;
zfs list -r -t snapshot -o name,used,referenced,creation bpool/BOOT # list snapshots&lt;br /&gt;
zsysctl show # show snapshots&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Ubuntu cloning =&lt;br /&gt;
&lt;br /&gt;
to clone a ubuntu image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /nfsroot/lxcpet&lt;br /&gt;
emacs -nw etc/hostname ### change hostname&lt;br /&gt;
emacs -nw etc/mailname ### change hostname (debian 11)&lt;br /&gt;
emacs -nw etc/defaultdomain ### change the NIS domainname&lt;br /&gt;
emacs -nw etc/yp.conf ### change the NIS server&lt;br /&gt;
cp -pvf ../lxcpet-SL610/etc/ssh/*key* etc/ssh/ ### preserve the ssh keys&lt;br /&gt;
emacs -nw opt/gonodeinfo/gonodeinfo.conf ### update information&lt;br /&gt;
emacs -nw root/.ssh/authorized_keys ### update root ssh keys&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Ubuntu boot loader =&lt;br /&gt;
&lt;br /&gt;
== maintenance commands ==&lt;br /&gt;
&lt;br /&gt;
* update-initramfs -v -u&lt;br /&gt;
* grub-install /dev/sda&lt;br /&gt;
&lt;br /&gt;
= Convert from single to dual mirrored ZFS SSD =&lt;br /&gt;
&lt;br /&gt;
Assuming Ubuntu LTS 22.04 with &amp;quot;instal on ZFS&amp;quot; option, we will&lt;br /&gt;
add a second SSD, configure ZFS to use both SSDs in mirrored&lt;br /&gt;
configuration and setup grub to boot from either SSD. This&lt;br /&gt;
is intended to create a full redundant system where failure&lt;br /&gt;
of either SSD does not break the system.&lt;br /&gt;
&lt;br /&gt;
* identify first SSD&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@midm9b:~# ./smart-status.perl &lt;br /&gt;
        Disk                    model               serial     temperature  realloc  pending   uncorr  CRC err     RRER Errors     Link&lt;br /&gt;
    /dev/sda  WD Blue SA510 2.5 250GB         22243Z803769              24        .        ?        ?        .        ?        .      6.0&lt;br /&gt;
root@midm9b:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* connect second SSD of identical size&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@midm9b:~# ./smart-status.perl &lt;br /&gt;
        Disk                    model               serial     temperature  realloc  pending   uncorr  CRC err     RRER   Errors     Link&lt;br /&gt;
    /dev/sda  WD Blue SA510 2.5 250GB         22243Z803769              24        .        ?        ?        .        ?        .      6.0&lt;br /&gt;
    /dev/sdb  WD Blue SA510 2.5 250GB         22243Z803852              25        .        ?        ?        .        ?        .      6.0&lt;br /&gt;
root@midm9b:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* if second SSD is not autodetected, reboot&lt;br /&gt;
* Clone partition table automatically&lt;br /&gt;
If both SSDs are identical size, use this simpler method of duplicating the partition table:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@midm9b:~# sfdisk -d /dev/sda &amp;gt; part_table&lt;br /&gt;
root@midm9b:~# grep -v ^label-id part_table | sed -e &#039;s/, *uuid=[0-9A-F-]*//&#039; | sfdisk /dev/sdb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The grep and sed in the second command are there to prevent disk ID and partition IDs from being cloned. Alternatively the part_table file can be edited manually to remove the label-id line and the uuid entries from the individual partitions.&lt;br /&gt;
&lt;br /&gt;
* Clone partition table manually (e.g. for different size disks)&lt;br /&gt;
* list partition table of first SSD:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@midm9b:~# fdisk -l /dev/sda&lt;br /&gt;
Disk /dev/sda: 232.89 GiB, 250059350016 bytes, 488397168 sectors&lt;br /&gt;
Disk model: WD Blue SA510 2.&lt;br /&gt;
Units: sectors of 1 * 512 = 512 bytes&lt;br /&gt;
Sector size (logical/physical): 512 bytes / 512 bytes&lt;br /&gt;
I/O size (minimum/optimal): 512 bytes / 512 bytes&lt;br /&gt;
Disklabel type: gpt&lt;br /&gt;
Disk identifier: 951A4174-B4C6-400D-99F5-BE9B5627FA8E&lt;br /&gt;
&lt;br /&gt;
Device       Start       End   Sectors   Size Type&lt;br /&gt;
/dev/sda1     2048   1050623   1048576   512M EFI System&lt;br /&gt;
/dev/sda2  1050624   5244927   4194304     2G Linux swap&lt;br /&gt;
/dev/sda3  5244928   9439231   4194304     2G Solaris boot&lt;br /&gt;
/dev/sda4  9439232 488397134 478957903 228.4G Solaris root&lt;br /&gt;
root@midm9b:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* create identical partitions on second SSD, use sector numbers from above.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@midm9b:~# gdisk /dev/sdb&lt;br /&gt;
GPT fdisk (gdisk) version 1.0.8&lt;br /&gt;
&lt;br /&gt;
Partition table scan:&lt;br /&gt;
  MBR: not present&lt;br /&gt;
  BSD: not present&lt;br /&gt;
  APM: not present&lt;br /&gt;
  GPT: not present&lt;br /&gt;
&lt;br /&gt;
Creating new GPT entries in memory.&lt;br /&gt;
&lt;br /&gt;
Command (? for help): n&lt;br /&gt;
Partition number (1-128, default 1): &lt;br /&gt;
First sector (34-488397134, default = 2048) or {+-}size{KMGTP}: &lt;br /&gt;
Last sector (2048-488397134, default = 488397134) or {+-}size{KMGTP}: 1050623&lt;br /&gt;
Current type is 8300 (Linux filesystem)&lt;br /&gt;
Hex code or GUID (L to show codes, Enter = 8300): ef00&lt;br /&gt;
Changed type of partition to &#039;EFI system partition&#039;&lt;br /&gt;
&lt;br /&gt;
Command (? for help): n&lt;br /&gt;
Partition number (2-128, default 2): &lt;br /&gt;
First sector (34-488397134, default = 1050624) or {+-}size{KMGTP}: &lt;br /&gt;
Last sector (1050624-488397134, default = 488397134) or {+-}size{KMGTP}: 5244927&lt;br /&gt;
Current type is 8300 (Linux filesystem)&lt;br /&gt;
Hex code or GUID (L to show codes, Enter = 8300): 8200&lt;br /&gt;
Changed type of partition to &#039;Linux swap&#039;&lt;br /&gt;
&lt;br /&gt;
Command (? for help): n&lt;br /&gt;
Partition number (3-128, default 3): &lt;br /&gt;
First sector (34-488397134, default = 5244928) or {+-}size{KMGTP}: &lt;br /&gt;
Last sector (5244928-488397134, default = 488397134) or {+-}size{KMGTP}: 9439231&lt;br /&gt;
Current type is 8300 (Linux filesystem)&lt;br /&gt;
Hex code or GUID (L to show codes, Enter = 8300): be00&lt;br /&gt;
Changed type of partition to &#039;Solaris boot&#039;&lt;br /&gt;
&lt;br /&gt;
Command (? for help): n&lt;br /&gt;
Partition number (4-128, default 4): &lt;br /&gt;
First sector (34-488397134, default = 9439232) or {+-}size{KMGTP}: &lt;br /&gt;
Last sector (9439232-488397134, default = 488397134) or {+-}size{KMGTP}: &lt;br /&gt;
Current type is 8300 (Linux filesystem)&lt;br /&gt;
Hex code or GUID (L to show codes, Enter = 8300): bf00&lt;br /&gt;
Changed type of partition to &#039;Solaris root&#039;&lt;br /&gt;
&lt;br /&gt;
Command (? for help): w&lt;br /&gt;
&lt;br /&gt;
Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING&lt;br /&gt;
PARTITIONS!!&lt;br /&gt;
&lt;br /&gt;
Do you want to proceed? (Y/N): y&lt;br /&gt;
OK; writing new GUID partition table (GPT) to /dev/sdb.&lt;br /&gt;
The operation has completed successfully.&lt;br /&gt;
root@midm9b:~# fdisk -l /dev/sda /dev/sdb&lt;br /&gt;
Disk /dev/sda: 232.89 GiB, 250059350016 bytes, 488397168 sectors&lt;br /&gt;
Disk model: WD Blue SA510 2.&lt;br /&gt;
Units: sectors of 1 * 512 = 512 bytes&lt;br /&gt;
Sector size (logical/physical): 512 bytes / 512 bytes&lt;br /&gt;
I/O size (minimum/optimal): 512 bytes / 512 bytes&lt;br /&gt;
Disklabel type: gpt&lt;br /&gt;
Disk identifier: 951A4174-B4C6-400D-99F5-BE9B5627FA8E&lt;br /&gt;
&lt;br /&gt;
Device       Start       End   Sectors   Size Type&lt;br /&gt;
/dev/sda1     2048   1050623   1048576   512M EFI System&lt;br /&gt;
/dev/sda2  1050624   5244927   4194304     2G Linux swap&lt;br /&gt;
/dev/sda3  5244928   9439231   4194304     2G Solaris boot&lt;br /&gt;
/dev/sda4  9439232 488397134 478957903 228.4G Solaris root&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Disk /dev/sdb: 232.89 GiB, 250059350016 bytes, 488397168 sectors&lt;br /&gt;
Disk model: WD Blue SA510 2.&lt;br /&gt;
Units: sectors of 1 * 512 = 512 bytes&lt;br /&gt;
Sector size (logical/physical): 512 bytes / 512 bytes&lt;br /&gt;
I/O size (minimum/optimal): 512 bytes / 512 bytes&lt;br /&gt;
Disklabel type: gpt&lt;br /&gt;
Disk identifier: EB251739-30C6-422F-A505-5887B5A0B603&lt;br /&gt;
&lt;br /&gt;
Device       Start       End   Sectors   Size Type&lt;br /&gt;
/dev/sdb1     2048   1050623   1048576   512M EFI System&lt;br /&gt;
/dev/sdb2  1050624   5244927   4194304     2G Linux swap&lt;br /&gt;
/dev/sdb3  5244928   9439231   4194304     2G Solaris boot&lt;br /&gt;
/dev/sdb4  9439232 488397134 478957903 228.4G Solaris root&lt;br /&gt;
root@midm9b:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* identify second SSD partitions&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@midm9b:~# ls -l /dev/disk/by-id/ata*part3&lt;br /&gt;
lrwxrwxrwx 1 root root 10 Jan 20 18:37 /dev/disk/by-id/ata-WD_Blue_SA510_2.5_250GB_22243Z803769-part3 -&amp;gt; ../../sda3&lt;br /&gt;
lrwxrwxrwx 1 root root 10 Jan 20 19:34 /dev/disk/by-id/ata-WD_Blue_SA510_2.5_250GB_22243Z803852-part3 -&amp;gt; ../../sdb3&lt;br /&gt;
root@midm9b:~# ls -l /dev/disk/by-id/ata*part4&lt;br /&gt;
lrwxrwxrwx 1 root root 10 Jan 20 18:37 /dev/disk/by-id/ata-WD_Blue_SA510_2.5_250GB_22243Z803769-part4 -&amp;gt; ../../sda4&lt;br /&gt;
lrwxrwxrwx 1 root root 10 Jan 20 19:34 /dev/disk/by-id/ata-WD_Blue_SA510_2.5_250GB_22243Z803852-part4 -&amp;gt; ../../sdb4&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* convert bpool from single disk to mirrored disk:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@midm9b:~# zpool status&lt;br /&gt;
  pool: bpool&lt;br /&gt;
 state: ONLINE&lt;br /&gt;
config:&lt;br /&gt;
&lt;br /&gt;
	NAME                                    STATE     READ WRITE CKSUM&lt;br /&gt;
	bpool                                   ONLINE       0     0     0&lt;br /&gt;
	  99e03dc0-7d4d-f24b-8fa1-f042b9f135db  ONLINE       0     0     0&lt;br /&gt;
&lt;br /&gt;
errors: No known data errors&lt;br /&gt;
&lt;br /&gt;
  pool: rpool&lt;br /&gt;
 state: ONLINE&lt;br /&gt;
config:&lt;br /&gt;
&lt;br /&gt;
	NAME                                    STATE     READ WRITE CKSUM&lt;br /&gt;
	rpool                                   ONLINE       0     0     0&lt;br /&gt;
	  f6fd54f8-3af7-b943-ae3d-a4e480537fb9  ONLINE       0     0     0&lt;br /&gt;
&lt;br /&gt;
errors: No known data errors&lt;br /&gt;
root@midm9b:~# zpool attach bpool 99e03dc0-7d4d-f24b-8fa1-f042b9f135db /dev/disk/by-id/ata-WD_Blue_SA510_2.5_250GB_22243Z803852-part3&lt;br /&gt;
root@midm9b:~# zpool status bpool&lt;br /&gt;
  pool: bpool&lt;br /&gt;
 state: ONLINE&lt;br /&gt;
  scan: resilvered 247M in 00:00:00 with 0 errors on Fri Jan 20 19:39:40 2023&lt;br /&gt;
config:&lt;br /&gt;
&lt;br /&gt;
	NAME                                                STATE     READ WRITE CKSUM&lt;br /&gt;
	bpool                                               ONLINE       0     0     0&lt;br /&gt;
	  mirror-0                                          ONLINE       0     0     0&lt;br /&gt;
	    99e03dc0-7d4d-f24b-8fa1-f042b9f135db            ONLINE       0     0     0&lt;br /&gt;
	    ata-WD_Blue_SA510_2.5_250GB_22243Z803852-part3  ONLINE       0     0     0&lt;br /&gt;
&lt;br /&gt;
errors: No known data errors&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* convert rpool&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@midm9b:~# ls -l /dev/disk/by-id/ata*part4&lt;br /&gt;
lrwxrwxrwx 1 root root 10 Jan 20 18:37 /dev/disk/by-id/ata-WD_Blue_SA510_2.5_250GB_22243Z803769-part4 -&amp;gt; ../../sda4&lt;br /&gt;
lrwxrwxrwx 1 root root 10 Jan 20 19:34 /dev/disk/by-id/ata-WD_Blue_SA510_2.5_250GB_22243Z803852-part4 -&amp;gt; ../../sdb4&lt;br /&gt;
root@midm9b:~# zpool attach rpool f6fd54f8-3af7-b943-ae3d-a4e480537fb9 /dev/disk/by-id/ata-WD_Blue_SA510_2.5_250GB_22243Z803852-part4&lt;br /&gt;
root@midm9b:~# zpool status rpool&lt;br /&gt;
  pool: rpool&lt;br /&gt;
 state: ONLINE&lt;br /&gt;
status: One or more devices is currently being resilvered.  The pool will&lt;br /&gt;
	continue to function, possibly in a degraded state.&lt;br /&gt;
action: Wait for the resilver to complete.&lt;br /&gt;
  scan: resilver in progress since Fri Jan 20 19:40:45 2023&lt;br /&gt;
	5.83G scanned at 664M/s, 2.92M issued at 332K/s, 9.11G total&lt;br /&gt;
	0B resilvered, 0.03% done, no estimated completion time&lt;br /&gt;
config:&lt;br /&gt;
&lt;br /&gt;
	NAME                                                STATE     READ WRITE CKSUM&lt;br /&gt;
	rpool                                               ONLINE       0     0     0&lt;br /&gt;
	  mirror-0                                          ONLINE       0     0     0&lt;br /&gt;
	    f6fd54f8-3af7-b943-ae3d-a4e480537fb9            ONLINE       0     0     0&lt;br /&gt;
	    ata-WD_Blue_SA510_2.5_250GB_22243Z803852-part4  ONLINE       0     0     0&lt;br /&gt;
&lt;br /&gt;
errors: No known data errors&lt;br /&gt;
root@midm9b:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* wait for resilver to complete&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@midm9b:~# zpool status&lt;br /&gt;
  pool: bpool&lt;br /&gt;
 state: ONLINE&lt;br /&gt;
  scan: resilvered 247M in 00:00:00 with 0 errors on Fri Jan 20 19:39:40 2023&lt;br /&gt;
config:&lt;br /&gt;
&lt;br /&gt;
	NAME                                                STATE     READ WRITE CKSUM&lt;br /&gt;
	bpool                                               ONLINE       0     0     0&lt;br /&gt;
	  mirror-0                                          ONLINE       0     0     0&lt;br /&gt;
	    99e03dc0-7d4d-f24b-8fa1-f042b9f135db            ONLINE       0     0     0&lt;br /&gt;
	    ata-WD_Blue_SA510_2.5_250GB_22243Z803852-part3  ONLINE       0     0     0&lt;br /&gt;
&lt;br /&gt;
errors: No known data errors&lt;br /&gt;
&lt;br /&gt;
  pool: rpool&lt;br /&gt;
 state: ONLINE&lt;br /&gt;
  scan: resilvered 9.65G in 00:00:36 with 0 errors on Fri Jan 20 19:41:21 2023&lt;br /&gt;
config:&lt;br /&gt;
&lt;br /&gt;
	NAME                                                STATE     READ WRITE CKSUM&lt;br /&gt;
	rpool                                               ONLINE       0     0     0&lt;br /&gt;
	  mirror-0                                          ONLINE       0     0     0&lt;br /&gt;
	    f6fd54f8-3af7-b943-ae3d-a4e480537fb9            ONLINE       0     0     0&lt;br /&gt;
	    ata-WD_Blue_SA510_2.5_250GB_22243Z803852-part4  ONLINE       0     0     0&lt;br /&gt;
&lt;br /&gt;
errors: No known data errors&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* enable booting from second SSD: (instead of /dev/sda1, /dev/sdb1, use UUID=xxx)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@midm9b:~# mkfs.msdos /dev/sdb1&lt;br /&gt;
root@midm9b:~# mkdir /boot/efi-sda&lt;br /&gt;
root@midm9b:~# mkdir /boot/efi-sdb&lt;br /&gt;
root@midm20c:~# blkid | grep vfat ### identify UUID&lt;br /&gt;
/dev/sdb1: UUID=&amp;quot;DD89-5081&amp;quot; BLOCK_SIZE=&amp;quot;512&amp;quot; TYPE=&amp;quot;vfat&amp;quot; PARTLABEL=&amp;quot;EFI System Partition&amp;quot; PARTUUID=&amp;quot;d0cb6be4-2f67-5b42-9b26-9e6905e9f774&amp;quot;&lt;br /&gt;
/dev/sdc1: UUID=&amp;quot;D970-86BA&amp;quot; BLOCK_SIZE=&amp;quot;512&amp;quot; TYPE=&amp;quot;vfat&amp;quot; PARTLABEL=&amp;quot;EFI System Partition&amp;quot; PARTUUID=&amp;quot;e6d3b5b9-a512-44a2-9205-1a4db06ed2a2&amp;quot;&lt;br /&gt;
/dev/sda1: UUID=&amp;quot;DDA1-044C&amp;quot; BLOCK_SIZE=&amp;quot;512&amp;quot; TYPE=&amp;quot;vfat&amp;quot; PARTLABEL=&amp;quot;EFI System Partition&amp;quot; PARTUUID=&amp;quot;6dc9dff0-1c13-8045-a906-7803d3074c70&amp;quot;&lt;br /&gt;
root@midm20c:~# cat /etc/fstab | grep vfat ### add mount points with correct UUID&lt;br /&gt;
#UUID=D970-86BA  /boot/efi       vfat    umask=0022,fmask=0022,dmask=0022      0       1&lt;br /&gt;
UUID=DDA1-044C  /boot/efi-sda       vfat    umask=0022,fmask=0022,dmask=0022      0       1&lt;br /&gt;
UUID=DD89-5081  /boot/efi-sdb       vfat    umask=0022,fmask=0022,dmask=0022      0       1&lt;br /&gt;
root@midm9b:~# mount -a&lt;br /&gt;
root@midm9b:~# df -kl&lt;br /&gt;
Filesystem                                       1K-blocks    Used Available Use% Mounted on&lt;br /&gt;
...&lt;br /&gt;
/dev/sda1                                           523244   13720    509524   3% /boot/efi&lt;br /&gt;
/dev/sdb1                                           523244       4    523240   1% /boot/efi-sdb&lt;br /&gt;
...&lt;br /&gt;
root@midm9b:~# rsync -av /boot/efi/ /boot/efi-sdb/&lt;br /&gt;
sending incremental file list&lt;br /&gt;
EFI/&lt;br /&gt;
...&lt;br /&gt;
root@midm9b:~# ls -l /boot/efi-sda&lt;br /&gt;
total 8&lt;br /&gt;
drwxr-xr-x 4 root root 4096 Jan 19 23:26 EFI&lt;br /&gt;
drwxr-xr-x 5 root root 4096 Jan 19 23:26 grub&lt;br /&gt;
root@midm9b:~# ls -l /boot/efi-sdb&lt;br /&gt;
total 8&lt;br /&gt;
drwxr-xr-x 4 root root 4096 Jan 19 23:26 EFI&lt;br /&gt;
drwxr-xr-x 5 root root 4096 Jan 19 23:26 grub&lt;br /&gt;
root@midm9b:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* setup script to update grub on second SSD, it must be run manually after every kernel update&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@midm9b:~# ln -s ~/git/scripts/etc/update_efi_grub.perl ~/&lt;br /&gt;
root@midm9b:~# ~/update_efi_grub.perl -u&lt;br /&gt;
EFI dir: /boot/efi-sda&lt;br /&gt;
/boot/efi-sda: update grub: rsync  -av --delete-after --modify-window=2 /boot/efi/grub/ /boot/efi-sda/grub&lt;br /&gt;
building file list ... done&lt;br /&gt;
&lt;br /&gt;
sent 5,313 bytes  received 11 bytes  10,648.00 bytes/sec&lt;br /&gt;
total size is 7,944,644  speedup is 1,492.23&lt;br /&gt;
/boot/efi-sda: update efi:  rsync  -av --delete-after --modify-window=2 /boot/efi/EFI/  /boot/efi-sda/EFI&lt;br /&gt;
building file list ... done&lt;br /&gt;
&lt;br /&gt;
sent 216 bytes  received 11 bytes  454.00 bytes/sec&lt;br /&gt;
total size is 5,452,378  speedup is 24,019.29&lt;br /&gt;
EFI dir: /boot/efi-sdb&lt;br /&gt;
/boot/efi-sdb: update grub: rsync  -av --delete-after --modify-window=2 /boot/efi/grub/ /boot/efi-sdb/grub&lt;br /&gt;
building file list ... done&lt;br /&gt;
&lt;br /&gt;
sent 5,313 bytes  received 11 bytes  10,648.00 bytes/sec&lt;br /&gt;
total size is 7,944,644  speedup is 1,492.23&lt;br /&gt;
/boot/efi-sdb: update efi:  rsync  -av --delete-after --modify-window=2 /boot/efi/EFI/  /boot/efi-sdb/EFI&lt;br /&gt;
building file list ... done&lt;br /&gt;
&lt;br /&gt;
sent 216 bytes  received 11 bytes  454.00 bytes/sec&lt;br /&gt;
total size is 5,452,378  speedup is 24,019.29&lt;br /&gt;
root@midm9b:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Disable NetworkManager =&lt;br /&gt;
&lt;br /&gt;
NOTE: THIS IS BROKEN IN UBUNTU LTS 22.04&lt;br /&gt;
&lt;br /&gt;
NetworkManager is useful for configuring dynamic&lt;br /&gt;
network interfaces, i.e. laptops that often move&lt;br /&gt;
between networks, or connect to multiple choice&lt;br /&gt;
of wifi networks, etc.&lt;br /&gt;
&lt;br /&gt;
For machines with statically configured network interfaces,&lt;br /&gt;
NetworkManager is not necessary.&lt;br /&gt;
&lt;br /&gt;
As it has been observed to become confused and observed&lt;br /&gt;
to malfunction when network links go up and down (it keeps&lt;br /&gt;
unnecessarily reconfiguring the ip address, etc), it can&lt;br /&gt;
be usefuil to disable it.&lt;br /&gt;
&lt;br /&gt;
* list all network interfaces&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# /bin/ls -1 /sys/class/net/&lt;br /&gt;
enp0s31f6&lt;br /&gt;
lo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* edit /etc/network/interfaces:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rename enp0s31f6=eth0&lt;br /&gt;
auto eth0&lt;br /&gt;
iface eth0 inet static&lt;br /&gt;
   address 142.90.120.94/19&lt;br /&gt;
   gateway 142.90.100.18&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* statically configure systemd-resolved&lt;br /&gt;
** create /etc/systemd/resolved.conf.d/resolved.conf with this contents:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Resolve]&lt;br /&gt;
DNS=142.90.100.19&lt;br /&gt;
Domains=triumf.ca&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
** systemctl restart systemd-resolved&lt;br /&gt;
** resolvectl&lt;br /&gt;
** systemd-analyze cat-config systemd/resolved.conf&lt;br /&gt;
* disable NetworkManager&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl disable NetworkManager&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* reboot&lt;br /&gt;
&lt;br /&gt;
= Configure ECC memory =&lt;br /&gt;
&lt;br /&gt;
== Configure EDAC ==&lt;br /&gt;
&lt;br /&gt;
* apt install edac-utils&lt;br /&gt;
&lt;br /&gt;
=== Intel i3-2120 ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@musr00:~# edac-ctl --mainboard&lt;br /&gt;
edac-ctl: mainboard: Supermicro X9SCL/X9SCM&lt;br /&gt;
root@musr00:~# edac-ctl --status&lt;br /&gt;
edac-ctl: drivers not loaded.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Intel E-2236 ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq00:~# edac-ctl --mainboard&lt;br /&gt;
edac-ctl: mainboard: Supermicro X11SCM-F&lt;br /&gt;
root@daq00:~# edac-ctl --status&lt;br /&gt;
edac-ctl: drivers are loaded.&lt;br /&gt;
root@daq00:~# edac-util &lt;br /&gt;
edac-util: No errors to report.&lt;br /&gt;
root@daq00:~# edac-util -s&lt;br /&gt;
edac-util: EDAC drivers are loaded. 1 MC detected&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* check edac sysfs files (Intel)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq00:~# ls -l /sys/devices/system/edac/mc/mc0&lt;br /&gt;
total 0&lt;br /&gt;
-r--r--r-- 1 root root 4096 Jan 25 15:10 ce_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Jan 25 15:10 ce_noinfo_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Jan 25 15:10 max_location&lt;br /&gt;
-r--r--r-- 1 root root 4096 Jan 25 15:10 mc_name&lt;br /&gt;
drwxr-xr-x 2 root root    0 Jan 25 15:10 power&lt;br /&gt;
drwxr-xr-x 3 root root    0 Jan 25 15:10 rank0&lt;br /&gt;
drwxr-xr-x 3 root root    0 Jan 25 15:10 rank1&lt;br /&gt;
drwxr-xr-x 3 root root    0 Jan 25 15:10 rank2&lt;br /&gt;
drwxr-xr-x 3 root root    0 Jan 25 15:10 rank3&lt;br /&gt;
drwxr-xr-x 3 root root    0 Jan 25 15:10 rank4&lt;br /&gt;
drwxr-xr-x 3 root root    0 Jan 25 15:10 rank5&lt;br /&gt;
drwxr-xr-x 3 root root    0 Jan 25 15:10 rank6&lt;br /&gt;
drwxr-xr-x 3 root root    0 Jan 25 15:10 rank7&lt;br /&gt;
--w------- 1 root root 4096 Jan 25 15:10 reset_counters&lt;br /&gt;
-r--r--r-- 1 root root 4096 Jan 25 15:10 seconds_since_reset&lt;br /&gt;
-r--r--r-- 1 root root 4096 Jan 25 15:10 size_mb&lt;br /&gt;
-r--r--r-- 1 root root 4096 Jan 25 15:10 ue_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Jan 25 15:10 ue_noinfo_count&lt;br /&gt;
-rw-r--r-- 1 root root 4096 Jan 25 15:10 uevent&lt;br /&gt;
root@daq00:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Intel E3-1270 v6 ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@wheel-SYS-5019S-M:~/git/scripts# edac-ctl --mainboard&lt;br /&gt;
edac-ctl: mainboard: Supermicro X11SSH-F&lt;br /&gt;
root@wheel-SYS-5019S-M:~/git/scripts# edac-ctl --status&lt;br /&gt;
edac-ctl: drivers are loaded.&lt;br /&gt;
root@grsnis01:~# edac-util&lt;br /&gt;
edac-util: No errors to report.&lt;br /&gt;
root@grsnis01:~# edac-util -s&lt;br /&gt;
edac-util: EDAC drivers are loaded. 1 MC detected&lt;br /&gt;
root@grsnis01:~# ls -l /sys/devices/system/edac/mc/mc0&lt;br /&gt;
total 0&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 19 12:35 ce_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 19 12:35 ce_noinfo_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 19 12:35 max_location&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 19 12:35 mc_name&lt;br /&gt;
drwxr-xr-x 2 root root    0 Feb 19 12:35 power&lt;br /&gt;
drwxr-xr-x 3 root root    0 Feb 19 12:35 rank0&lt;br /&gt;
drwxr-xr-x 3 root root    0 Feb 19 12:35 rank1&lt;br /&gt;
drwxr-xr-x 3 root root    0 Feb 19 12:35 rank2&lt;br /&gt;
drwxr-xr-x 3 root root    0 Feb 19 12:35 rank3&lt;br /&gt;
drwxr-xr-x 3 root root    0 Feb 19 12:35 rank4&lt;br /&gt;
drwxr-xr-x 3 root root    0 Feb 19 12:35 rank5&lt;br /&gt;
drwxr-xr-x 3 root root    0 Feb 19 12:35 rank6&lt;br /&gt;
drwxr-xr-x 3 root root    0 Feb 19 12:35 rank7&lt;br /&gt;
--w------- 1 root root 4096 Feb 19 12:35 reset_counters&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 19 12:35 seconds_since_reset&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 19 12:35 size_mb&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 19 12:35 ue_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 19 12:35 ue_noinfo_count&lt;br /&gt;
-rw-r--r-- 1 root root 4096 Feb 19 12:35 uevent&lt;br /&gt;
root@grsnis01:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Intel E3-1245 v6 ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[root@alphagdaq ~]# edac-ctl --mainboard&lt;br /&gt;
edac-ctl: mainboard: Supermicro X11SSH-F&lt;br /&gt;
[root@alphagdaq ~]# edac-ctl --mainboard&lt;br /&gt;
edac-ctl: mainboard: Supermicro X11SSH-F&lt;br /&gt;
[root@alphagdaq ~]# edac-ctl --status&lt;br /&gt;
edac-ctl: drivers are loaded.&lt;br /&gt;
[root@alphagdaq ~]# edac-util&lt;br /&gt;
edac-util: No errors to report.&lt;br /&gt;
[root@alphagdaq ~]# edac-util -s&lt;br /&gt;
edac-util: EDAC drivers are loaded. 1 MC detected&lt;br /&gt;
[root@alphagdaq ~]# ras-mc-ctl --layout&lt;br /&gt;
          +-----------------------------------------------+&lt;br /&gt;
          |                      mc0                      |&lt;br /&gt;
          |  csrow0   |  csrow1   |  csrow2   |  csrow3   |&lt;br /&gt;
----------+-----------------------------------------------+&lt;br /&gt;
channel1: |  8192 MB  |  8192 MB  |  8192 MB  |  8192 MB  |&lt;br /&gt;
channel0: |  8192 MB  |  8192 MB  |  8192 MB  |  8192 MB  |&lt;br /&gt;
----------+-----------------------------------------------+&lt;br /&gt;
[root@alphagdaq ~]# ras-mc-ctl --error-count&lt;br /&gt;
Label               	CE	UE&lt;br /&gt;
mc#0csrow#3channel#0	0	0&lt;br /&gt;
mc#0csrow#2channel#1	0	0&lt;br /&gt;
mc#0csrow#3channel#1	0	0&lt;br /&gt;
mc#0csrow#0channel#0	0	0&lt;br /&gt;
mc#0csrow#1channel#1	0	0&lt;br /&gt;
mc#0csrow#0channel#1	0	0&lt;br /&gt;
mc#0csrow#1channel#0	0	0&lt;br /&gt;
mc#0csrow#2channel#0	0	0&lt;br /&gt;
[root@alphagdaq ~]# ras-mc-ctl --mainboard&lt;br /&gt;
ras-mc-ctl: mainboard: Supermicro model X11SSH-F&lt;br /&gt;
[root@alphagdaq ~]# ras-mc-ctl --summary&lt;br /&gt;
DBD::SQLite::db prepare failed: no such table: mc_event at /usr/sbin/ras-mc-ctl line 1129.&lt;br /&gt;
Can&#039;t call method &amp;quot;execute&amp;quot; on an undefined value at /usr/sbin/ras-mc-ctl line 1130.&lt;br /&gt;
[root@alphagdaq ~]# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== AMD 3700X ===&lt;br /&gt;
&lt;br /&gt;
(memory is non-ECC)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq13:~# edac-ctl --mainboard&lt;br /&gt;
edac-ctl: mainboard: ASUSTeK COMPUTER INC. ROG STRIX B550-E GAMING&lt;br /&gt;
root@daq13:~# &lt;br /&gt;
root@daq13:~# &lt;br /&gt;
root@daq13:~# edac-ctl --status&lt;br /&gt;
edac-ctl: drivers not loaded.&lt;br /&gt;
root@daq13:~# edac-util &lt;br /&gt;
edac-util: Error: No memory controller data found.&lt;br /&gt;
root@daq13:~# edac-util -s&lt;br /&gt;
edac-util: EDAC drivers loaded. No memory controllers found&lt;br /&gt;
root@daq13:~# ls -l /sys/devices/system/edac/mc&lt;br /&gt;
total 0&lt;br /&gt;
drwxr-xr-x 2 root root    0 Jan 25 15:26 power&lt;br /&gt;
lrwxrwxrwx 1 root root    0 Jan 21 16:16 subsystem -&amp;gt; ../../../../bus/edac&lt;br /&gt;
-rw-r--r-- 1 root root 4096 Jan 21 16:16 uevent&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(memory is ECC)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@trinatdaq:~# edac-ctl --mainboard&lt;br /&gt;
edac-ctl: mainboard: ASUSTeK COMPUTER INC. ROG STRIX B550-E GAMING&lt;br /&gt;
root@trinatdaq:~# edac-ctl --status&lt;br /&gt;
edac-ctl: drivers are loaded.&lt;br /&gt;
root@trinatdaq:~# edac-util &lt;br /&gt;
edac-util: No errors to report.&lt;br /&gt;
root@trinatdaq:~# edac-util -s&lt;br /&gt;
edac-util: EDAC drivers are loaded. 1 MC detected&lt;br /&gt;
root@trinatdaq:~# ls -l /sys/devices/system/edac/mc&lt;br /&gt;
total 0&lt;br /&gt;
drwxr-xr-x 7 root root    0 Dec 15 13:04 mc0&lt;br /&gt;
drwxr-xr-x 2 root root    0 Dec 15 13:04 power&lt;br /&gt;
lrwxrwxrwx 1 root root    0 Dec 13 18:31 subsystem -&amp;gt; ../../../../bus/edac&lt;br /&gt;
-rw-r--r-- 1 root root 4096 Dec 13 18:31 uevent&lt;br /&gt;
root@trinatdaq:~# ls -l /sys/devices/system/edac/mc/mc0&lt;br /&gt;
total 0&lt;br /&gt;
-r--r--r-- 1 root root 4096 Dec 15 13:04 ce_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Dec 15 13:04 ce_noinfo_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Dec 15 13:04 max_location&lt;br /&gt;
-r--r--r-- 1 root root 4096 Dec 15 13:04 mc_name&lt;br /&gt;
drwxr-xr-x 2 root root    0 Dec 15 13:04 power&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dec 15 13:04 rank4&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dec 15 13:04 rank5&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dec 15 13:04 rank6&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dec 15 13:04 rank7&lt;br /&gt;
--w------- 1 root root 4096 Dec 15 13:04 reset_counters&lt;br /&gt;
-rw-r--r-- 1 root root 4096 Dec 15 13:04 sdram_scrub_rate&lt;br /&gt;
-r--r--r-- 1 root root 4096 Dec 15 13:04 seconds_since_reset&lt;br /&gt;
-r--r--r-- 1 root root 4096 Dec 15 13:04 size_mb&lt;br /&gt;
-r--r--r-- 1 root root 4096 Dec 15 13:04 ue_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Dec 15 13:04 ue_noinfo_count&lt;br /&gt;
-rw-r--r-- 1 root root 4096 Dec 15 13:04 uevent&lt;br /&gt;
root@trinatdaq:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== AMD 5000G ===&lt;br /&gt;
&lt;br /&gt;
* no linux driver for AMD 5000-series &amp;quot;G&amp;quot; CPU&lt;br /&gt;
* no mention of ECC in the BIOS settings&lt;br /&gt;
* unclear status of ECC support in AMD documentation (sais only &amp;quot;pro&amp;quot; &amp;quot;G&amp;quot; CPUs have ECC)&lt;br /&gt;
* unclear status of ECC support in ASUS documentation (web page out of date)&lt;br /&gt;
&lt;br /&gt;
=== AMD 5600X ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq17:~# edac-ctl --mainboard&lt;br /&gt;
edac-ctl: mainboard: ASUSTeK COMPUTER INC. ROG STRIX B550-XE GAMING WIFI&lt;br /&gt;
root@daq17:~# edac-ctl --status&lt;br /&gt;
edac-ctl: drivers are loaded.&lt;br /&gt;
root@daq17:~# edac-util&lt;br /&gt;
edac-util: No errors to report.&lt;br /&gt;
root@daq17:~# edac-util -s&lt;br /&gt;
edac-util: EDAC drivers are loaded. 1 MC detected&lt;br /&gt;
root@daq17:~# ls -l /sys/devices/system/edac/mc&lt;br /&gt;
total 0&lt;br /&gt;
drwxr-xr-x 7 root root    0 Aug 19 19:27 mc0&lt;br /&gt;
drwxr-xr-x 2 root root    0 Aug 19 19:27 power&lt;br /&gt;
lrwxrwxrwx 1 root root    0 May 10 10:11 subsystem -&amp;gt; ../../../../bus/edac&lt;br /&gt;
-rw-r--r-- 1 root root 4096 May 10 10:11 uevent&lt;br /&gt;
root@daq17:~# ls -l /sys/devices/system/edac/mc/mc0&lt;br /&gt;
total 0&lt;br /&gt;
-r--r--r-- 1 root root 4096 Aug 19 19:27 ce_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Aug 19 19:27 ce_noinfo_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Aug 19 19:27 max_location&lt;br /&gt;
-r--r--r-- 1 root root 4096 Aug 19 19:27 mc_name&lt;br /&gt;
drwxr-xr-x 2 root root    0 Aug 19 19:27 power&lt;br /&gt;
drwxr-xr-x 3 root root    0 Aug 19 19:27 rank4&lt;br /&gt;
drwxr-xr-x 3 root root    0 Aug 19 19:27 rank5&lt;br /&gt;
drwxr-xr-x 3 root root    0 Aug 19 19:27 rank6&lt;br /&gt;
drwxr-xr-x 3 root root    0 Aug 19 19:27 rank7&lt;br /&gt;
--w------- 1 root root 4096 Aug 19 19:27 reset_counters&lt;br /&gt;
-rw-r--r-- 1 root root 4096 Aug 19 19:27 sdram_scrub_rate&lt;br /&gt;
-r--r--r-- 1 root root 4096 Aug 19 19:27 seconds_since_reset&lt;br /&gt;
-r--r--r-- 1 root root 4096 Aug 19 19:27 size_mb&lt;br /&gt;
-r--r--r-- 1 root root 4096 Aug 19 19:27 ue_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Aug 19 19:27 ue_noinfo_count&lt;br /&gt;
-rw-r--r-- 1 root root 4096 Aug 19 19:27 uevent&lt;br /&gt;
root@daq17:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== AMD 3955WX ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@alphasuperdaq:~/git/scripts/quotareport# edac-ctl --mainboard&lt;br /&gt;
edac-ctl: mainboard: ASUSTeK COMPUTER INC. Pro WS WRX80E-SAGE SE WIFI&lt;br /&gt;
root@alphasuperdaq:~/git/scripts/quotareport# edac-ctl --status&lt;br /&gt;
edac-ctl: drivers are loaded.&lt;br /&gt;
root@alphasuperdaq:~/git/scripts/quotareport# edac-util &lt;br /&gt;
edac-util: No errors to report.&lt;br /&gt;
root@alphasuperdaq:~/git/scripts/quotareport# edac-util -s&lt;br /&gt;
edac-util: EDAC drivers are loaded. 1 MC detected&lt;br /&gt;
root@alphasuperdaq:~/git/scripts/quotareport# ls -l /sys/devices/system/edac/mc&lt;br /&gt;
total 0&lt;br /&gt;
drwxr-xr-x 19 root root    0 Dez 12 04:48 mc0&lt;br /&gt;
drwxr-xr-x  2 root root    0 Dez 12 04:48 power&lt;br /&gt;
lrwxrwxrwx  1 root root    0 Dez  9 05:31 subsystem -&amp;gt; ../../../../bus/edac&lt;br /&gt;
-rw-r--r--  1 root root 4096 Dez  9 05:31 uevent&lt;br /&gt;
root@alphasuperdaq:~/git/scripts/quotareport# &lt;br /&gt;
root@alphasuperdaq:~# ls -l /sys/devices/system/edac/mc/mc0&lt;br /&gt;
total 0&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 28 22:19 ce_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 28 22:19 ce_noinfo_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 28 22:19 max_location&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 28 22:19 mc_name&lt;br /&gt;
drwxr-xr-x 2 root root    0 Dez 12 04:48 power&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank0&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank1&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank10&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank11&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank12&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank13&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank14&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank15&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank2&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank3&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank4&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank5&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank6&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank7&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank8&lt;br /&gt;
drwxr-xr-x 3 root root    0 Dez 12 04:48 rank9&lt;br /&gt;
--w------- 1 root root 4096 Feb 28 22:19 reset_counters&lt;br /&gt;
-rw-r--r-- 1 root root 4096 Feb 28 22:19 sdram_scrub_rate&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 28 22:19 seconds_since_reset&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 28 22:19 size_mb&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 28 22:19 ue_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 Feb 28 22:19 ue_noinfo_count&lt;br /&gt;
-rw-r--r-- 1 root root 4096 Feb 28 22:19 uevent&lt;br /&gt;
root@alphasuperdaq:~# &lt;br /&gt;
root@alphasuperdaq:~# ras-mc-ctl --layout&lt;br /&gt;
Use of uninitialized value $max_pos[3] in modulus (%) at /usr/sbin/ras-mc-ctl line 868.&lt;br /&gt;
Use of uninitialized value $d in numeric ge (&amp;gt;=) at /usr/sbin/ras-mc-ctl line 869.&lt;br /&gt;
Use of uninitialized value $d in sprintf at /usr/sbin/ras-mc-ctl line 872.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 791.&lt;br /&gt;
    +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+&lt;br /&gt;
    |                                                                                              mc0                                                                                              |&lt;br /&gt;
    |                                            csrow0                                             |                                            csrow1                                             |&lt;br /&gt;
    | channel0  | channel1  | channel2  | channel3  | channel4  | channel5  | channel6  | channel7  | channel0  | channel1  | channel2  | channel3  | channel4  | channel5  | channel6  | channel7  |&lt;br /&gt;
----+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+&lt;br /&gt;
&lt;br /&gt;
0: |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |&lt;br /&gt;
----+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+&lt;br /&gt;
root@alphasuperdaq:~# ras-mc-ctl --error-count&lt;br /&gt;
Label               	CE	UE&lt;br /&gt;
mc#0csrow#0channel#2	0	0&lt;br /&gt;
mc#0csrow#1channel#7	0	0&lt;br /&gt;
mc#0csrow#0channel#3	0	0&lt;br /&gt;
mc#0csrow#1channel#4	0	0&lt;br /&gt;
mc#0csrow#1channel#2	0	0&lt;br /&gt;
mc#0csrow#0channel#7	0	0&lt;br /&gt;
mc#0csrow#1channel#3	0	0&lt;br /&gt;
mc#0csrow#0channel#4	0	0&lt;br /&gt;
mc#0csrow#1channel#1	0	0&lt;br /&gt;
mc#0csrow#1channel#0	0	0&lt;br /&gt;
mc#0csrow#1channel#5	0	0&lt;br /&gt;
mc#0csrow#0channel#6	0	0&lt;br /&gt;
mc#0csrow#0channel#1	0	0&lt;br /&gt;
mc#0csrow#0channel#5	0	0&lt;br /&gt;
mc#0csrow#0channel#0	0	0&lt;br /&gt;
mc#0csrow#1channel#6	0	0&lt;br /&gt;
root@alphasuperdaq:~# ras-mc-ctl --mainboard&lt;br /&gt;
ras-mc-ctl: mainboard: ASUSTeK COMPUTER INC. model Pro WS WRX80E-SAGE SE WIFI&lt;br /&gt;
root@alphasuperdaq:~# ras-mc-ctl --summary&lt;br /&gt;
No Memory errors.&lt;br /&gt;
&lt;br /&gt;
No PCIe AER errors.&lt;br /&gt;
&lt;br /&gt;
No Extlog errors.&lt;br /&gt;
&lt;br /&gt;
DBD::SQLite::db prepare failed: no such table: devlink_event at /usr/sbin/ras-mc-ctl line 1181.&lt;br /&gt;
Can&#039;t call method &amp;quot;execute&amp;quot; on an undefined value at /usr/sbin/ras-mc-ctl line 1182.&lt;br /&gt;
root@alphasuperdaq:~#&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== AMD 7700X ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@dsfe05:~# apt install edac-utils&lt;br /&gt;
root@dsfe05:~# edac-ctl --mainboard&lt;br /&gt;
edac-ctl: mainboard: Supermicro H13SAE-MF&lt;br /&gt;
root@dsfe05:~# edac-ctl --status&lt;br /&gt;
edac-ctl: drivers are loaded.&lt;br /&gt;
root@dsfe05:~# edac-util&lt;br /&gt;
edac-util: No errors to report.&lt;br /&gt;
root@dsfe05:~# edac-util -s&lt;br /&gt;
edac-util: EDAC drivers are loaded. 1 MC detected&lt;br /&gt;
root@dsfe05:~# ls -l /sys/devices/system/edac/mc/mc0&lt;br /&gt;
total 0&lt;br /&gt;
-r--r--r-- 1 root root 4096 May 14 09:33 ce_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 May 14 09:33 ce_noinfo_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 May 14 09:33 max_location&lt;br /&gt;
-r--r--r-- 1 root root 4096 May 14 09:33 mc_name&lt;br /&gt;
drwxr-xr-x 2 root root    0 May 14 09:33 power&lt;br /&gt;
drwxr-xr-x 3 root root    0 May 14 09:33 rank4&lt;br /&gt;
drwxr-xr-x 3 root root    0 May 14 09:33 rank5&lt;br /&gt;
--w------- 1 root root 4096 May 14 09:33 reset_counters&lt;br /&gt;
-r--r--r-- 1 root root 4096 May 14 09:33 seconds_since_reset&lt;br /&gt;
-r--r--r-- 1 root root 4096 May 14 09:33 size_mb&lt;br /&gt;
-r--r--r-- 1 root root 4096 May 14 09:33 ue_count&lt;br /&gt;
-r--r--r-- 1 root root 4096 May 14 09:33 ue_noinfo_count&lt;br /&gt;
-rw-r--r-- 1 root root 4096 May 14 09:33 uevent&lt;br /&gt;
root@dsfe05:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configure rasdaemon ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install rasdaemon&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl enable rasdaemon&lt;br /&gt;
systemctl restart rasdaemon&lt;br /&gt;
systemctl status rasdaemon&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
● rasdaemon.service - RAS daemon to log the RAS events&lt;br /&gt;
     Loaded: loaded (/lib/systemd/system/rasdaemon.service; enabled; vendor preset: enabled)&lt;br /&gt;
     Active: active (running) since Mon 2021-01-25 15:16:37 PST; 3min 5s ago&lt;br /&gt;
   Main PID: 2477175 (rasdaemon)&lt;br /&gt;
      Tasks: 1 (limit: 76958)&lt;br /&gt;
     Memory: 17.1M&lt;br /&gt;
     CGroup: /system.slice/rasdaemon.service&lt;br /&gt;
             └─2477175 /usr/sbin/rasdaemon -f -r&lt;br /&gt;
&lt;br /&gt;
Jan 25 15:16:37 daq00.triumf.ca rasdaemon[2477175]: rasdaemon: ras:extlog_mem_event event enabled&lt;br /&gt;
Jan 25 15:16:37 daq00.triumf.ca rasdaemon[2477175]: rasdaemon: Enabled event ras:extlog_mem_event&lt;br /&gt;
Jan 25 15:16:37 daq00.triumf.ca rasdaemon[2477175]: ras:extlog_mem_event event enabled&lt;br /&gt;
Jan 25 15:16:37 daq00.triumf.ca rasdaemon[2477175]: rasdaemon: Listening to events for cpus 0 to 11&lt;br /&gt;
Jan 25 15:16:37 daq00.triumf.ca rasdaemon[2477175]: Enabled event ras:extlog_mem_event&lt;br /&gt;
Jan 25 15:16:37 daq00.triumf.ca rasdaemon[2477175]: rasdaemon: Recording mc_event events&lt;br /&gt;
Jan 25 15:16:37 daq00.triumf.ca rasdaemon[2477175]: rasdaemon: Recording aer_event events&lt;br /&gt;
Jan 25 15:16:37 daq00.triumf.ca rasdaemon[2477175]: rasdaemon: Recording extlog_event events&lt;br /&gt;
Jan 25 15:16:37 daq00.triumf.ca rasdaemon[2477175]: rasdaemon: Recording mce_record events&lt;br /&gt;
Jan 25 15:16:37 daq00.triumf.ca rasdaemon[2477175]: rasdaemon: Recording arm_event events&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Get reports ==&lt;br /&gt;
&lt;br /&gt;
* Intel 2x32GB ECC DIMMs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq00:~# ras-mc-ctl --layout&lt;br /&gt;
          +-------------------------+&lt;br /&gt;
          |           mc0           |&lt;br /&gt;
          |   csrow0   |   csrow1   |&lt;br /&gt;
----------+-------------------------+&lt;br /&gt;
channel1: |  16384 MB  |  16384 MB  |&lt;br /&gt;
channel0: |  16384 MB  |  16384 MB  |&lt;br /&gt;
----------+-------------------------+&lt;br /&gt;
root@daq00:~# ras-mc-ctl --error-count&lt;br /&gt;
Label                   CE      UE&lt;br /&gt;
mc#0csrow#1channel#1    0       0&lt;br /&gt;
mc#0csrow#1channel#0    0       0&lt;br /&gt;
mc#0csrow#0channel#0    0       0&lt;br /&gt;
mc#0csrow#0channel#1    0       0&lt;br /&gt;
root@daq00:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Intel 4x16GB ECC DIMMs&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq00:~# ras-mc-ctl --error-count&lt;br /&gt;
Label                   CE      UE&lt;br /&gt;
mc#0csrow#0channel#1    0       0&lt;br /&gt;
mc#0csrow#2channel#0    0       0&lt;br /&gt;
mc#0csrow#0channel#0    0       0&lt;br /&gt;
mc#0csrow#2channel#1    0       0&lt;br /&gt;
mc#0csrow#1channel#0    0       0&lt;br /&gt;
mc#0csrow#1channel#1    0       0&lt;br /&gt;
mc#0csrow#3channel#0    0       0&lt;br /&gt;
mc#0csrow#3channel#1    0       0&lt;br /&gt;
root@daq00:~# &lt;br /&gt;
root@daq00:~# ras-mc-ctl --layout&lt;br /&gt;
          +-----------------------+&lt;br /&gt;
          |          mc0          |&lt;br /&gt;
          |  csrow0   |  csrow1   |&lt;br /&gt;
----------+-----------------------+&lt;br /&gt;
channel1: |  8192 MB  |  8192 MB  |&lt;br /&gt;
channel0: |  8192 MB  |  8192 MB  |&lt;br /&gt;
----------+-----------------------+&lt;br /&gt;
root@daq00:~# &lt;br /&gt;
root@daq00:~# &lt;br /&gt;
root@daq00:~# &lt;br /&gt;
root@daq00:~# ras-mc-ctl --print-labels&lt;br /&gt;
ras-mc-ctl: Error: No dimm labels for Supermicro model X11SCM-F&lt;br /&gt;
root@daq00:~# ras-mc-ctl --mainboard&lt;br /&gt;
ras-mc-ctl: mainboard: Supermicro model X11SCM-F&lt;br /&gt;
root@daq00:~# ras-mc-ctl --summary&lt;br /&gt;
No Memory errors.&lt;br /&gt;
&lt;br /&gt;
No PCIe AER errors.&lt;br /&gt;
&lt;br /&gt;
No Extlog errors.&lt;br /&gt;
&lt;br /&gt;
DBD::SQLite::db prepare failed: no such table: devlink_event at /usr/sbin/ras-mc-ctl line 1181.&lt;br /&gt;
Can&#039;t call method &amp;quot;execute&amp;quot; on an undefined value at /usr/sbin/ras-mc-ctl line 1182.&lt;br /&gt;
root@daq00:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
note: ubuntu LTS 22.04 DBD::SQLite::db error is not there.&lt;br /&gt;
&lt;br /&gt;
* AMD 7700 2x32GB DDR5 ECC DIMMs&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@dsfe05:~# systemctl status rasdaemon&lt;br /&gt;
● rasdaemon.service - RAS daemon to log the RAS events&lt;br /&gt;
     Loaded: loaded (/lib/systemd/system/rasdaemon.service; enabled; vendor preset: enabled)&lt;br /&gt;
     Active: active (running) since Tue 2024-05-14 09:36:43 PDT; 33ms ago&lt;br /&gt;
    Process: 4088418 ExecStartPost=/usr/sbin/rasdaemon --enable (code=exited, status=0/SUCCESS)&lt;br /&gt;
   Main PID: 4088417 (rasdaemon)&lt;br /&gt;
      Tasks: 1 (limit: 37300)&lt;br /&gt;
     Memory: 788.0K&lt;br /&gt;
        CPU: 5ms&lt;br /&gt;
     CGroup: /system.slice/rasdaemon.service&lt;br /&gt;
             └─4088417 /usr/sbin/rasdaemon -f -r&lt;br /&gt;
&lt;br /&gt;
May 14 09:36:43 dsfe05 rasdaemon[4088417]: ras:aer_event event enabled&lt;br /&gt;
May 14 09:36:43 dsfe05 rasdaemon[4088417]: Enabled event ras:aer_event&lt;br /&gt;
May 14 09:36:43 dsfe05 rasdaemon[4088417]: mce:mce_record event enabled&lt;br /&gt;
May 14 09:36:43 dsfe05 rasdaemon[4088417]: Enabled event mce:mce_record&lt;br /&gt;
May 14 09:36:43 dsfe05 rasdaemon[4088417]: ras:extlog_mem_event event enabled&lt;br /&gt;
May 14 09:36:43 dsfe05 rasdaemon[4088417]: Enabled event ras:extlog_mem_event&lt;br /&gt;
May 14 09:36:43 dsfe05 rasdaemon[4088417]: rasdaemon: Recording mc_event events&lt;br /&gt;
May 14 09:36:43 dsfe05 rasdaemon[4088417]: rasdaemon: Recording aer_event events&lt;br /&gt;
May 14 09:36:43 dsfe05 rasdaemon[4088417]: rasdaemon: Recording extlog_event events&lt;br /&gt;
May 14 09:36:43 dsfe05 rasdaemon[4088417]: rasdaemon: Recording mce_record events&lt;br /&gt;
root@dsfe05:~# ras-mc-ctl --layout&lt;br /&gt;
Use of uninitialized value $max_pos[3] in modulus (%) at /usr/sbin/ras-mc-ctl line 907.&lt;br /&gt;
Use of uninitialized value $d in numeric ge (&amp;gt;=) at /usr/sbin/ras-mc-ctl line 908.&lt;br /&gt;
Use of uninitialized value $d in sprintf at /usr/sbin/ras-mc-ctl line 911.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 830.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 830.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 830.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 830.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 830.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 830.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 830.&lt;br /&gt;
Use of uninitialized value $pos[3] in join or string at /usr/sbin/ras-mc-ctl line 830.&lt;br /&gt;
    +-----------------------------------------------------------------------------------------------+&lt;br /&gt;
    |                                              mc0                                              |&lt;br /&gt;
    |        csrow0         |        csrow1         |        csrow2         |        csrow3         |&lt;br /&gt;
    | channel0  | channel1  | channel0  | channel1  | channel0  | channel1  | channel0  | channel1  |&lt;br /&gt;
----+-----------------------------------------------------------------------------------------------+&lt;br /&gt;
&lt;br /&gt;
0: |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |     0 MB  |&lt;br /&gt;
----+-----------------------------------------------------------------------------------------------+&lt;br /&gt;
root@dsfe05:~# ras-mc-ctl --error-count&lt;br /&gt;
Label               	CE	UE&lt;br /&gt;
mc#0csrow#2channel#1	0	0&lt;br /&gt;
mc#0csrow#2channel#0	0	0&lt;br /&gt;
root@dsfe05:~# ras-mc-ctl --print-labels&lt;br /&gt;
ras-mc-ctl: Error: No dimm labels for Supermicro model H13SAE-MF&lt;br /&gt;
root@dsfe05:~# ras-mc-ctl --mainboard&lt;br /&gt;
ras-mc-ctl: mainboard: Supermicro model H13SAE-MF&lt;br /&gt;
root@dsfe05:~# ras-mc-ctl --summary&lt;br /&gt;
No Memory errors.&lt;br /&gt;
&lt;br /&gt;
No PCIe AER errors.&lt;br /&gt;
&lt;br /&gt;
No Extlog errors.&lt;br /&gt;
&lt;br /&gt;
No MCE errors.&lt;br /&gt;
root@dsfe05:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= sensors =&lt;br /&gt;
&lt;br /&gt;
== ASUS P7P55D EVO ==&lt;br /&gt;
&lt;br /&gt;
* BIOS version 2101&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@iris01:~# sensors&lt;br /&gt;
coretemp-isa-0000&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
Core 0:       +34.0°C  (high = +83.0°C, crit = +99.0°C)&lt;br /&gt;
Core 1:       +37.0°C  (high = +83.0°C, crit = +99.0°C)&lt;br /&gt;
Core 2:       +38.0°C  (high = +83.0°C, crit = +99.0°C)&lt;br /&gt;
Core 3:       +35.0°C  (high = +83.0°C, crit = +99.0°C)&lt;br /&gt;
&lt;br /&gt;
nouveau-pci-0100&lt;br /&gt;
Adapter: PCI adapter&lt;br /&gt;
GPU core:    900.00 mV (min =  +0.85 V, max =  +1.05 V)&lt;br /&gt;
temp1:        +46.0°C  (high = +95.0°C, hyst =  +3.0°C)&lt;br /&gt;
                       (crit = +105.0°C, hyst =  +5.0°C)&lt;br /&gt;
                       (emerg = +135.0°C, hyst =  +5.0°C)&lt;br /&gt;
&lt;br /&gt;
atk0110-acpi-0&lt;br /&gt;
Adapter: ACPI interface&lt;br /&gt;
Vcore Voltage:      864.00 mV (min =  +0.80 V, max =  +1.60 V)&lt;br /&gt;
+3.3V Voltage:        3.38 V  (min =  +2.97 V, max =  +3.63 V)&lt;br /&gt;
+5V Voltage:          5.04 V  (min =  +4.50 V, max =  +5.50 V)&lt;br /&gt;
+12V Voltage:        12.15 V  (min = +10.20 V, max = +13.80 V)&lt;br /&gt;
CPU Fan Speed:       968 RPM  (min =  600 RPM, max = 7200 RPM)&lt;br /&gt;
Chassis1 Fan Speed: 1288 RPM  (min =  600 RPM, max = 7200 RPM)&lt;br /&gt;
Chassis2 Fan Speed: 1316 RPM  (min =  600 RPM, max = 7200 RPM)&lt;br /&gt;
Power Fan Speed:       0 RPM  (min =    0 RPM, max = 7200 RPM)&lt;br /&gt;
CPU Temperature:     +34.0°C  (high = +45.0°C, crit = +45.5°C)&lt;br /&gt;
MB Temperature:      +30.0°C  (high = +45.0°C, crit = +46.0°C)&lt;br /&gt;
&lt;br /&gt;
root@iris01:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ASUS Z170-DELUXE ==&lt;br /&gt;
&lt;br /&gt;
* BIOS version 3801&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo modprobe coretemp &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
echo modprobe jc42 &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
echo modprobe lm92 &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
echo modprobe nct6775 &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@iris00:~# sensors&lt;br /&gt;
jc42-i2c-0-1a&lt;br /&gt;
Adapter: SMBus I801 adapter at f040&lt;br /&gt;
temp1:        +32.0°C  (low  =  +0.0°C)                  ALARM (HIGH, CRIT)&lt;br /&gt;
                       (high =  +0.0°C, hyst =  +0.0°C)&lt;br /&gt;
                       (crit =  +0.0°C, hyst =  +0.0°C)&lt;br /&gt;
&lt;br /&gt;
jc42-i2c-0-18&lt;br /&gt;
Adapter: SMBus I801 adapter at f040&lt;br /&gt;
temp1:        +30.0°C  (low  =  +0.0°C)                  ALARM (HIGH, CRIT)&lt;br /&gt;
                       (high =  +0.0°C, hyst =  +0.0°C)&lt;br /&gt;
                       (crit =  +0.0°C, hyst =  +0.0°C)&lt;br /&gt;
&lt;br /&gt;
jc42-i2c-0-1b&lt;br /&gt;
Adapter: SMBus I801 adapter at f040&lt;br /&gt;
temp1:        +31.5°C  (low  =  +0.0°C)                  ALARM (HIGH, CRIT)&lt;br /&gt;
                       (high =  +0.0°C, hyst =  +0.0°C)&lt;br /&gt;
                       (crit =  +0.0°C, hyst =  +0.0°C)&lt;br /&gt;
&lt;br /&gt;
jc42-i2c-0-19&lt;br /&gt;
Adapter: SMBus I801 adapter at f040&lt;br /&gt;
temp1:        +31.5°C  (low  =  +0.0°C)                  ALARM (HIGH, CRIT)&lt;br /&gt;
                       (high =  +0.0°C, hyst =  +0.0°C)&lt;br /&gt;
                       (crit =  +0.0°C, hyst =  +0.0°C)&lt;br /&gt;
&lt;br /&gt;
coretemp-isa-0000&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
Package id 0:  +28.0°C  (high = +84.0°C, crit = +100.0°C)&lt;br /&gt;
Core 0:        +24.0°C  (high = +84.0°C, crit = +100.0°C)&lt;br /&gt;
Core 1:        +25.0°C  (high = +84.0°C, crit = +100.0°C)&lt;br /&gt;
Core 2:        +25.0°C  (high = +84.0°C, crit = +100.0°C)&lt;br /&gt;
Core 3:        +22.0°C  (high = +84.0°C, crit = +100.0°C)&lt;br /&gt;
&lt;br /&gt;
root@iris00:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ASUS H110M-A/M.2 ==&lt;br /&gt;
&lt;br /&gt;
* BIOS version 4202&lt;br /&gt;
* echo modprobe coretemp &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
* echo modprobe nct6775 &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@midpol:~# sensors&lt;br /&gt;
coretemp-isa-0000&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
Package id 0:  +33.0°C  (high = +80.0°C, crit = +100.0°C)&lt;br /&gt;
Core 0:        +33.0°C  (high = +80.0°C, crit = +100.0°C)&lt;br /&gt;
Core 1:        +30.0°C  (high = +80.0°C, crit = +100.0°C)&lt;br /&gt;
&lt;br /&gt;
acpitz-acpi-0&lt;br /&gt;
Adapter: ACPI interface&lt;br /&gt;
temp1:        +27.8°C  (crit = +119.0°C)&lt;br /&gt;
temp2:        +29.8°C  (crit = +119.0°C)&lt;br /&gt;
&lt;br /&gt;
nct6793-isa-0290&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
in0:                      368.00 mV (min =  +0.00 V, max =  +1.74 V)&lt;br /&gt;
in1:                        1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in2:                        3.39 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in3:                        3.36 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in4:                        1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in5:                      152.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in6:                      928.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in7:                        3.39 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in8:                        3.14 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in9:                      1000.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in10:                     152.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in11:                     128.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in12:                     136.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in13:                     120.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in14:                     136.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
fan1:                     1004 RPM  (min =    0 RPM)&lt;br /&gt;
fan2:                     1143 RPM  (min =    0 RPM)&lt;br /&gt;
fan5:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
fan6:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
SYSTIN:                   +118.0°C  (high = +98.0°C, hyst = +95.0°C)  sensor = thermistor&lt;br /&gt;
CPUTIN:                    +29.0°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermistor&lt;br /&gt;
AUXTIN0:                   +30.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN1:                  +112.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN2:                  +111.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN3:                  +110.0°C    sensor = thermistor&lt;br /&gt;
PECI Agent 0:              +31.0°C  (high = +98.0°C, hyst = +95.0°C)&lt;br /&gt;
                                    (crit = +100.0°C)&lt;br /&gt;
PECI Agent 0 Calibration:  +36.5°C  &lt;br /&gt;
PCH_CHIP_CPU_MAX_TEMP:      +0.0°C  &lt;br /&gt;
PCH_CHIP_TEMP:              +0.0°C  &lt;br /&gt;
TSI2_TEMP:                +3892314.0°C  &lt;br /&gt;
TSI3_TEMP:                +3892314.0°C  &lt;br /&gt;
TSI4_TEMP:                +3892314.0°C  &lt;br /&gt;
TSI5_TEMP:                +3892314.0°C  &lt;br /&gt;
TSI6_TEMP:                +3892314.0°C  &lt;br /&gt;
TSI7_TEMP:                +3892314.0°C  &lt;br /&gt;
intrusion0:               ALARM&lt;br /&gt;
intrusion1:               ALARM&lt;br /&gt;
beep_enable:              disabled&lt;br /&gt;
&lt;br /&gt;
root@midpol:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ASUS P9X79 WS ==&lt;br /&gt;
&lt;br /&gt;
* https://www.asus.com/supportonly/P9X79%20WS/HelpDesk_Manual/&lt;br /&gt;
* BIOS version 4802&lt;br /&gt;
* modprobe nct6775&lt;br /&gt;
* modprobe coretemp&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq14:~# sensors&lt;br /&gt;
coretemp-isa-0000&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
Package id 0:  +35.0°C  (high = +82.0°C, crit = +100.0°C)&lt;br /&gt;
Core 0:        +29.0°C  (high = +82.0°C, crit = +100.0°C)&lt;br /&gt;
Core 1:        +24.0°C  (high = +82.0°C, crit = +100.0°C)&lt;br /&gt;
Core 2:        +35.0°C  (high = +82.0°C, crit = +100.0°C)&lt;br /&gt;
Core 3:        +32.0°C  (high = +82.0°C, crit = +100.0°C)&lt;br /&gt;
&lt;br /&gt;
nouveau-pci-0200&lt;br /&gt;
Adapter: PCI adapter&lt;br /&gt;
GPU core:    900.00 mV (min =  +0.85 V, max =  +1.00 V)&lt;br /&gt;
temp1:        +39.0°C  (high = +95.0°C, hyst =  +3.0°C)&lt;br /&gt;
                       (crit = +105.0°C, hyst =  +5.0°C)&lt;br /&gt;
                       (emerg = +135.0°C, hyst =  +5.0°C)&lt;br /&gt;
&lt;br /&gt;
nct6776-isa-0290&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
Vcore:           1.04 V  (min =  +0.00 V, max =  +1.74 V)&lt;br /&gt;
in1:             1.01 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
AVCC:            3.33 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
+3.3V:           3.33 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in4:             1.01 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in5:             2.04 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in6:           904.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
3VSB:            3.41 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
Vbat:            3.30 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
fan1:          1265 RPM  (min =    0 RPM)&lt;br /&gt;
fan2:          1909 RPM  (min =    0 RPM)&lt;br /&gt;
fan3:             0 RPM  (min =    0 RPM)&lt;br /&gt;
fan4:             0 RPM  (min =    0 RPM)&lt;br /&gt;
fan5:             0 RPM  (min =    0 RPM)&lt;br /&gt;
SYSTIN:         +34.0°C  (high =  +0.0°C, hyst =  +0.0°C)  ALARM  sensor = thermistor&lt;br /&gt;
CPUTIN:         +58.0°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermal diode&lt;br /&gt;
AUXTIN:         +31.5°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermistor&lt;br /&gt;
PECI Agent 0:   +31.0°C  (high = +80.0°C, hyst = +75.0°C)&lt;br /&gt;
                         (crit = +96.0°C)&lt;br /&gt;
PCH_CHIP_TEMP:   +0.0°C  &lt;br /&gt;
PCH_CPU_TEMP:    +0.0°C  &lt;br /&gt;
PCH_MCH_TEMP:    +0.0°C  &lt;br /&gt;
intrusion0:    ALARM&lt;br /&gt;
intrusion1:    ALARM&lt;br /&gt;
beep_enable:   disabled&lt;br /&gt;
&lt;br /&gt;
root@daq14:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ASUS TUF GAMING B550M-PLUS WIFI II ==&lt;br /&gt;
&lt;br /&gt;
* BIOS 2803, 2806&lt;br /&gt;
* echo modprobe nct6775 &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@midm9a:~# sensors&lt;br /&gt;
nct6798-isa-0290&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
in0:                      488.00 mV (min =  +0.00 V, max =  +1.74 V)&lt;br /&gt;
in1:                        1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in2:                        3.41 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in3:                        3.38 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in4:                        1.01 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in5:                        1.01 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in6:                      208.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in7:                        3.41 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in8:                        3.33 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in9:                        1.82 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in10:                       1.01 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in11:                       1.01 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in12:                       1.03 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in13:                       1.01 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in14:                       1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
fan1:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
fan2:                      760 RPM  (min =    0 RPM)&lt;br /&gt;
fan3:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
fan7:                     1264 RPM  (min =    0 RPM)&lt;br /&gt;
SYSTIN:                    +25.0°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermistor&lt;br /&gt;
CPUTIN:                    +22.5°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermistor&lt;br /&gt;
AUXTIN0:                   +95.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN1:                   +25.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN2:                   +25.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN3:                   +25.0°C    sensor = thermistor&lt;br /&gt;
PECI Agent 0 Calibration:  +23.5°C  &lt;br /&gt;
PCH_CHIP_CPU_MAX_TEMP:      +0.0°C  &lt;br /&gt;
PCH_CHIP_TEMP:              +0.0°C  &lt;br /&gt;
PCH_CPU_TEMP:               +0.0°C  &lt;br /&gt;
TSI0_TEMP:                 +32.4°C  &lt;br /&gt;
intrusion0:               ALARM&lt;br /&gt;
intrusion1:               ALARM&lt;br /&gt;
beep_enable:              disabled&lt;br /&gt;
&lt;br /&gt;
amdgpu-pci-0800&lt;br /&gt;
Adapter: PCI adapter&lt;br /&gt;
vddgfx:        1.45 V  &lt;br /&gt;
vddnb:       993.00 mV &lt;br /&gt;
edge:         +28.0°C  &lt;br /&gt;
PPT:          20.00 W  &lt;br /&gt;
&lt;br /&gt;
k10temp-pci-00c3&lt;br /&gt;
Adapter: PCI adapter&lt;br /&gt;
Tctl:         +33.4°C  &lt;br /&gt;
&lt;br /&gt;
root@midm9a:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ASUS ASUS ROG STRIX B550-XE GAMING WIFI ==&lt;br /&gt;
&lt;br /&gt;
* BIOS 2423, 2604&lt;br /&gt;
* echo modprobe nct6775 &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq13:~# sensors&lt;br /&gt;
nct6798-isa-0290&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
in0:                      344.00 mV (min =  +0.00 V, max =  +1.74 V)&lt;br /&gt;
in1:                      992.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in2:                        3.41 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in3:                        3.39 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in4:                        1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in5:                      960.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in6:                      216.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in7:                        3.41 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in8:                        3.30 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in9:                        1.81 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in10:                     960.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in11:                     960.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in12:                       1.03 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in13:                     280.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in14:                     208.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
fan1:                      845 RPM  (min =    0 RPM)&lt;br /&gt;
fan2:                      998 RPM  (min =    0 RPM)&lt;br /&gt;
fan3:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
fan4:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
fan5:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
SYSTIN:                    +28.0°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermistor&lt;br /&gt;
CPUTIN:                    +27.5°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermistor&lt;br /&gt;
AUXTIN0:                   +94.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN1:                   +28.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN2:                   +28.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN3:                   +97.0°C    sensor = thermistor&lt;br /&gt;
PECI Agent 0 Calibration:  +27.5°C  &lt;br /&gt;
PCH_CHIP_CPU_MAX_TEMP:      +0.0°C  &lt;br /&gt;
PCH_CHIP_TEMP:              +0.0°C  &lt;br /&gt;
PCH_CPU_TEMP:               +0.0°C  &lt;br /&gt;
TSI0_TEMP:                 +33.6°C  &lt;br /&gt;
intrusion0:               ALARM&lt;br /&gt;
intrusion1:               ALARM&lt;br /&gt;
beep_enable:              disabled&lt;br /&gt;
&lt;br /&gt;
amdgpu-pci-0600&lt;br /&gt;
Adapter: PCI adapter&lt;br /&gt;
vddgfx:        1.45 V  &lt;br /&gt;
vddnb:       999.00 mV &lt;br /&gt;
edge:         +29.0°C  &lt;br /&gt;
PPT:          14.00 W  &lt;br /&gt;
&lt;br /&gt;
iwlwifi_1-virtual-0&lt;br /&gt;
Adapter: Virtual device&lt;br /&gt;
temp1:        +30.0°C  &lt;br /&gt;
&lt;br /&gt;
k10temp-pci-00c3&lt;br /&gt;
Adapter: PCI adapter&lt;br /&gt;
Tctl:         +33.9°C  &lt;br /&gt;
&lt;br /&gt;
root@daq13:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ASUS ASUS ROG STRIX B550-E GAMING ==&lt;br /&gt;
&lt;br /&gt;
* bios 2803&lt;br /&gt;
* echo modprobe jc42 &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
* echo modprobe nct6775 &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq17:~# sensors&lt;br /&gt;
jc42-i2c-1-1b&lt;br /&gt;
Adapter: SMBus PIIX4 adapter port 0 at 0b00&lt;br /&gt;
temp1:        +25.0°C  (low  =  +0.0°C)                  ALARM (HIGH, CRIT)&lt;br /&gt;
                       (high =  +0.0°C, hyst =  +0.0°C)&lt;br /&gt;
                       (crit =  +0.0°C, hyst =  +0.0°C)&lt;br /&gt;
&lt;br /&gt;
iwlwifi_1-virtual-0&lt;br /&gt;
Adapter: Virtual device&lt;br /&gt;
temp1:        +28.0°C  &lt;br /&gt;
&lt;br /&gt;
nouveau-pci-0800&lt;br /&gt;
Adapter: PCI adapter&lt;br /&gt;
GPU core:    900.00 mV (min =  +0.85 V, max =  +1.00 V)&lt;br /&gt;
temp1:        +34.0°C  (high = +95.0°C, hyst =  +3.0°C)&lt;br /&gt;
                       (crit = +105.0°C, hyst =  +5.0°C)&lt;br /&gt;
                       (emerg = +135.0°C, hyst =  +5.0°C)&lt;br /&gt;
&lt;br /&gt;
nct6798-isa-0290&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
in0:                      288.00 mV (min =  +0.00 V, max =  +1.74 V)&lt;br /&gt;
in1:                        1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in2:                        3.36 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in3:                        3.38 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in4:                        1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in5:                        1.06 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in6:                      224.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in7:                        3.36 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in8:                        3.31 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in9:                        1.79 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in10:                       1.06 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in11:                       1.06 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in12:                       1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in13:                     280.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in14:                     208.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
fan1:                      843 RPM  (min =    0 RPM)&lt;br /&gt;
fan2:                      629 RPM  (min =    0 RPM)&lt;br /&gt;
fan3:                      746 RPM  (min =    0 RPM)&lt;br /&gt;
fan4:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
fan5:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
SYSTIN:                    +22.0°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermistor&lt;br /&gt;
CPUTIN:                    +25.0°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermistor&lt;br /&gt;
AUXTIN0:                   +93.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN1:                   +22.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN2:                   +22.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN3:                   +96.0°C    sensor = thermistor&lt;br /&gt;
PECI Agent 0 Calibration:  +25.5°C  &lt;br /&gt;
PCH_CHIP_CPU_MAX_TEMP:      +0.0°C  &lt;br /&gt;
PCH_CHIP_TEMP:              +0.0°C  &lt;br /&gt;
PCH_CPU_TEMP:               +0.0°C  &lt;br /&gt;
TSI0_TEMP:                 +27.6°C  &lt;br /&gt;
intrusion0:               ALARM&lt;br /&gt;
intrusion1:               ALARM&lt;br /&gt;
beep_enable:              disabled&lt;br /&gt;
&lt;br /&gt;
jc42-i2c-1-1a&lt;br /&gt;
Adapter: SMBus PIIX4 adapter port 0 at 0b00&lt;br /&gt;
temp1:        +23.2°C  (low  =  +0.0°C)                  ALARM (HIGH, CRIT)&lt;br /&gt;
                       (high =  +0.0°C, hyst =  +0.0°C)&lt;br /&gt;
                       (crit =  +0.0°C, hyst =  +0.0°C)&lt;br /&gt;
&lt;br /&gt;
asusec-isa-0000&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
CPU_Opt:        0 RPM&lt;br /&gt;
Chipset:      +34.0°C  &lt;br /&gt;
CPU:          +25.0°C  &lt;br /&gt;
Motherboard:  +22.0°C  &lt;br /&gt;
T_Sensor:     -40.0°C  &lt;br /&gt;
VRM:          +31.0°C  &lt;br /&gt;
&lt;br /&gt;
k10temp-pci-00c3&lt;br /&gt;
Adapter: PCI adapter&lt;br /&gt;
Tctl:         +28.0°C  &lt;br /&gt;
Tccd1:        +27.5°C  &lt;br /&gt;
&lt;br /&gt;
root@daq17:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ASUS PRIME B650-PLUS ==&lt;br /&gt;
&lt;br /&gt;
* BIOS 1811&lt;br /&gt;
* echo modprobe nct6775 &amp;gt;&amp;gt; /etc/rc.local&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@dsdaqgw:~# sensors&lt;br /&gt;
amdgpu-pci-0b00&lt;br /&gt;
Adapter: PCI adapter&lt;br /&gt;
vddgfx:      930.00 mV &lt;br /&gt;
vddnb:         1.19 V  &lt;br /&gt;
edge:         +38.0°C  &lt;br /&gt;
PPT:          25.10 W  &lt;br /&gt;
&lt;br /&gt;
nct6799-isa-0290&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
in0:                      920.00 mV (min =  +0.00 V, max =  +1.74 V)&lt;br /&gt;
in1:                        1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in2:                        3.39 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in3:                        3.38 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in4:                        1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in5:                        1.04 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in6:                      320.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in7:                        3.39 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in8:                        3.28 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in9:                        3.38 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in10:                       1.28 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in11:                       1.10 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in12:                       1.04 V  (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in13:                     416.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
in14:                     328.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM&lt;br /&gt;
fan1:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
fan2:                     1253 RPM  (min =    0 RPM)&lt;br /&gt;
fan3:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
fan4:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
fan5:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
fan7:                        0 RPM  (min =    0 RPM)&lt;br /&gt;
SYSTIN:                    +33.0°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermistor&lt;br /&gt;
CPUTIN:                    +35.5°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermistor&lt;br /&gt;
AUXTIN0:                   +78.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN1:                   +11.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN2:                   +20.0°C    sensor = thermistor&lt;br /&gt;
AUXTIN3:                   +82.0°C    sensor = thermistor&lt;br /&gt;
PECI Agent 0 Calibration:  +35.5°C  &lt;br /&gt;
PCH_CHIP_CPU_MAX_TEMP:      +0.0°C  &lt;br /&gt;
PCH_CHIP_TEMP:              +0.0°C  &lt;br /&gt;
PCH_CPU_TEMP:               +0.0°C  &lt;br /&gt;
TSI0_TEMP:                 +42.6°C  &lt;br /&gt;
intrusion0:               ALARM&lt;br /&gt;
intrusion1:               OK&lt;br /&gt;
beep_enable:              disabled&lt;br /&gt;
&lt;br /&gt;
k10temp-pci-00c3&lt;br /&gt;
Adapter: PCI adapter&lt;br /&gt;
Tctl:         +42.6°C  &lt;br /&gt;
Tccd1:        +36.4°C  &lt;br /&gt;
&lt;br /&gt;
root@dsdaqgw:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Enable CPU turbo mode =&lt;br /&gt;
&lt;br /&gt;
* Intel CPU has a nominal CPU frequency (i.e. 3.4GHz) and a turbo-boost CPU frequency (i.e. 4.0GHz). Here we will enable this turbo-boost mode.&lt;br /&gt;
* Find out CPU capability&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq01:~# lscpu | grep Hz&lt;br /&gt;
Model name:                      Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz&lt;br /&gt;
CPU MHz:                         3965.803&lt;br /&gt;
CPU max MHz:                     4000.0000&lt;br /&gt;
CPU min MHz:                     800.0000&lt;br /&gt;
root@daq01:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Look up this CPU in the Intel ARK database - google for the CPU model name, i.e.&lt;br /&gt;
https://ark.intel.com/content/www/us/en/ark/products/88196/intel-core-i7-6700-processor-8m-cache-up-to-4-00-ghz.html&lt;br /&gt;
* Find current frequency settings:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq01:~# cpupower frequency-info&lt;br /&gt;
analyzing CPU 0:&lt;br /&gt;
  driver: intel_pstate&lt;br /&gt;
  CPUs which run at the same hardware frequency: 0&lt;br /&gt;
  CPUs which need to have their frequency coordinated by software: 0&lt;br /&gt;
  maximum transition latency:  Cannot determine or is not supported.&lt;br /&gt;
  hardware limits: 800 MHz - 4.00 GHz&lt;br /&gt;
  available cpufreq governors: performance powersave&lt;br /&gt;
  current policy: frequency should be within 800 MHz and 4.00 GHz.&lt;br /&gt;
                  The governor &amp;quot;powersave&amp;quot; may decide which speed to use&lt;br /&gt;
                  within this range.&lt;br /&gt;
  current CPU frequency: Unable to call hardware&lt;br /&gt;
  current CPU frequency: 2.72 GHz (asserted by call to kernel)&lt;br /&gt;
  boost state support:&lt;br /&gt;
    Supported: yes&lt;br /&gt;
    Active: yes&lt;br /&gt;
root@daq01:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Note the following:&lt;br /&gt;
** current governor is &amp;quot;powersave&amp;quot;&lt;br /&gt;
** &amp;quot;performance&amp;quot; governor is available&lt;br /&gt;
** &amp;quot;boost state support&amp;quot; is supported and active.&lt;br /&gt;
* Confirm CPU frequency governor:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq01:~# cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor&lt;br /&gt;
powersave&lt;br /&gt;
powersave&lt;br /&gt;
powersave&lt;br /&gt;
powersave&lt;br /&gt;
powersave&lt;br /&gt;
powersave&lt;br /&gt;
powersave&lt;br /&gt;
powersave&lt;br /&gt;
root@daq01:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
* Change governor to &amp;quot;performance&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq01:~# cpupower frequency-set --governor performance&lt;br /&gt;
Setting cpu: 0&lt;br /&gt;
Setting cpu: 1&lt;br /&gt;
Setting cpu: 2&lt;br /&gt;
Setting cpu: 3&lt;br /&gt;
Setting cpu: 4&lt;br /&gt;
Setting cpu: 5&lt;br /&gt;
Setting cpu: 6&lt;br /&gt;
Setting cpu: 7&lt;br /&gt;
root@daq01:~# cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor&lt;br /&gt;
performance&lt;br /&gt;
performance&lt;br /&gt;
performance&lt;br /&gt;
performance&lt;br /&gt;
performance&lt;br /&gt;
performance&lt;br /&gt;
performance&lt;br /&gt;
performance&lt;br /&gt;
root@daq01:~# cpupower frequency-info&lt;br /&gt;
analyzing CPU 0:&lt;br /&gt;
  driver: intel_pstate&lt;br /&gt;
  CPUs which run at the same hardware frequency: 0&lt;br /&gt;
  CPUs which need to have their frequency coordinated by software: 0&lt;br /&gt;
  maximum transition latency:  Cannot determine or is not supported.&lt;br /&gt;
  hardware limits: 800 MHz - 4.00 GHz&lt;br /&gt;
  available cpufreq governors: performance powersave&lt;br /&gt;
  current policy: frequency should be within 800 MHz and 4.00 GHz.&lt;br /&gt;
                  The governor &amp;quot;performance&amp;quot; may decide which speed to use&lt;br /&gt;
                  within this range.&lt;br /&gt;
  current CPU frequency: Unable to call hardware&lt;br /&gt;
  current CPU frequency: 3.93 GHz (asserted by call to kernel)&lt;br /&gt;
  boost state support:&lt;br /&gt;
    Supported: yes&lt;br /&gt;
    Active: yes&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* monitor CPU frequency:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq01:~# cpupower monitor&lt;br /&gt;
    | Nehalem                   || Mperf              || Idle_Stats                                     &lt;br /&gt;
 CPU| C3   | C6   | PC3  | PC6   || C0   | Cx   | Freq  || POLL | C1   | C1E  | C3   | C6   | C7s  | C8    &lt;br /&gt;
   0|  0.00|  0.00|  0.00|  0.00|| 88.80| 11.20|  3973||  0.00|  0.00|  0.01|  0.02|  0.31|  0.00|  4.25&lt;br /&gt;
   4|  0.00|  0.00|  0.00|  0.00||  4.70| 95.30|  3945||  0.00|  0.00|  0.00|  0.00|  0.00|  0.00| 95.03&lt;br /&gt;
   1|  0.73|  3.70|  0.00|  0.00||  4.52| 95.48|  3864||  0.00|  0.01|  1.19|  0.44|  2.82|  0.00| 90.23&lt;br /&gt;
   5|  0.73|  3.70|  0.00|  0.00||  0.37| 99.63|  3807||  0.00|  0.00|  0.03|  0.09|  1.70|  0.00| 97.64&lt;br /&gt;
   2|  2.28| 12.86|  0.00|  0.00||  1.41| 98.59|  3829||  0.00|  0.86|  3.17|  0.46|  7.70|  0.00| 85.87&lt;br /&gt;
   6|  2.28| 12.86|  0.00|  0.00||  2.88| 97.12|  3856||  0.00|  0.11|  4.56|  2.15| 10.31|  0.00| 78.99&lt;br /&gt;
   3|  1.33|  4.81|  0.00|  0.00||  0.99| 99.01|  3804||  0.00|  0.49|  0.79|  0.01|  1.03|  0.00| 96.12&lt;br /&gt;
   7|  1.34|  4.81|  0.00|  0.00||  1.26| 98.74|  3818||  0.00|  0.01|  2.32|  0.47|  5.02|  0.00| 90.06&lt;br /&gt;
root@daq01:~# &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* check that the CPU is not overheating:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@daq01:~# sensors&lt;br /&gt;
coretemp-isa-0000&lt;br /&gt;
Adapter: ISA adapter&lt;br /&gt;
Package id 0:  +51.0°C  (high = +84.0°C, crit = +100.0°C)&lt;br /&gt;
Core 0:        +51.0°C  (high = +84.0°C, crit = +100.0°C)&lt;br /&gt;
Core 1:        +38.0°C  (high = +84.0°C, crit = +100.0°C)&lt;br /&gt;
Core 2:        +34.0°C  (high = +84.0°C, crit = +100.0°C)&lt;br /&gt;
Core 3:        +32.0°C  (high = +84.0°C, crit = +100.0°C)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* congratulations, we are running at 4 GHz now!&lt;br /&gt;
&lt;br /&gt;
= Setup ubuntu as gateway to private network =&lt;br /&gt;
&lt;br /&gt;
See also:&lt;br /&gt;
* https://daq.triumf.ca/DaqWiki/index.php/VME-CPU#Setup_the_boot_host_computer_.28el7.29&lt;br /&gt;
* http://www.triumf.info/wiki/DAQwiki/index.php/Dhcpd_on_eth1&lt;br /&gt;
&lt;br /&gt;
== Steps to do ==&lt;br /&gt;
&lt;br /&gt;
!!! UPDATED 16feb2024 Ubuntu-22.04.03 !!!&lt;br /&gt;
&lt;br /&gt;
* assign network numbers to the private network, i.e. 192.168.1.x, 192.168.2.x, etc&lt;br /&gt;
* (on the gateway machine, each private network interface has to have a different network number)&lt;br /&gt;
* (each network interface can have multiple networks attached, via VLANs or via eth0:0, eth0:1 constructs)&lt;br /&gt;
* assign IP addresses on the private network, save them in /etc/hosts i.e. &amp;quot;hvps 192.168.1.10&amp;quot;&lt;br /&gt;
* (for simplicity, assign 192.168.1.1 to the gateway machine itself)&lt;br /&gt;
* (IP addresses 192.168.1.0 and 192.168.1.255 are &amp;quot;special&amp;quot;, do not use them)&lt;br /&gt;
* setup DNS server (dnsmasq) to serve contents of /etc/hosts via DNS (otherwise, many programs will see inconsistent name to IP address mapping)&lt;br /&gt;
* setup DHCP server (dnsmasq) to give out the IP addresses&lt;br /&gt;
* setup TFTP server (dnsmasq), pxelinux and NFS for diskless booting&lt;br /&gt;
* setup time server (chronyd) to provide common time to all devices&lt;br /&gt;
* setup NAT so machines on private network can access the internet (to get OS updates, etc)&lt;br /&gt;
* setup NIS and NFS so machines on the private network can use common home directories&lt;br /&gt;
* setup rsync backup of machines on the private network&lt;br /&gt;
&lt;br /&gt;
== setup hosts ==&lt;br /&gt;
&lt;br /&gt;
* edit /etc/hosts&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
192.168.1.101 dsfe01&lt;br /&gt;
... and so forth&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== setup dns and dhcp ==&lt;br /&gt;
&lt;br /&gt;
!!! updated 16feb2024 for Ubuntu 22.04.3 !!!&lt;br /&gt;
&lt;br /&gt;
!!! note: stock systemd-resolved remains, is configured to forward queries to dnsmasq, configured to forward queries to TRIUMF DNS !!!&lt;br /&gt;
&lt;br /&gt;
!!! note: per authors of systemd, bare hostnames are not permitted, a DNS domain name must always be used. DNS domain name &amp;quot;dsdaq&amp;quot; is used in this example !!!&lt;br /&gt;
&lt;br /&gt;
* apt install dnsmasq&lt;br /&gt;
* ensure dnsmasq starts after all interfaces are up (Ubuntu-22)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /etc/systemd/system/dnsmasq.service.d&lt;br /&gt;
echo -e &amp;quot;[Unit]\nAfter=network-online.target\n&amp;quot; &amp;gt; /etc/systemd/system/dnsmasq.service.d/local.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* edit /etc/dnsmasq.conf&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# /etc/dnsmasq.conf&lt;br /&gt;
# DNS settings &lt;br /&gt;
#port=0 # disable DNS function &lt;br /&gt;
port=53 # enable DNS function &lt;br /&gt;
bind-interfaces # do not collide with systemd-resolved, we use 127.0.0.1:53, they use 127.0.0.53:53 &lt;br /&gt;
domain-needed &lt;br /&gt;
bogus-priv &lt;br /&gt;
no-resolv &lt;br /&gt;
#log-queries # log DNS quesries &lt;br /&gt;
 &lt;br /&gt;
# TRIUMF DNS settings &lt;br /&gt;
 &lt;br /&gt;
server=142.90.100.19 &lt;br /&gt;
expand-hosts &lt;br /&gt;
domain=dsdaq &lt;br /&gt;
local=/dsdaq/ &lt;br /&gt;
localmx # do not forward MX queries to TRIUMF &lt;br /&gt;
&lt;br /&gt;
# DHCP settings &lt;br /&gt;
interface=enp1s0f0 # VX network 192.168.0.x &lt;br /&gt;
#interface=missing  # FEP and TSP network 192.168.1.x &lt;br /&gt;
interface=enp1s0f1 # controls network 192.168.2.x &lt;br /&gt;
#dhcp-range=192.168.1.50,192.168.1.150,infinite &lt;br /&gt;
dhcp-range=192.168.0.0,static &lt;br /&gt;
dhcp-range=192.168.2.0,static &lt;br /&gt;
log-dhcp # log DHCP queries &lt;br /&gt;
#quiet-dhcp &lt;br /&gt;
dhcp-ignore=tag:!known &lt;br /&gt;
#dhcp-boot=pxelinux.0 &lt;br /&gt;
 &lt;br /&gt;
dhcp-option=option:dns-server,192.168.0.248 &lt;br /&gt;
dhcp-option=option:ntp-server,192.168.0.248 &lt;br /&gt;
 &lt;br /&gt;
# TFTP settings &lt;br /&gt;
 &lt;br /&gt;
enable-tftp &lt;br /&gt;
tftp-root=/tftpboot &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* #mkdir /tftpboot ### per tftp-root (if no ZFS)&lt;br /&gt;
* zfs create -o mountpoint=/tftpboot rpool/tftpboot ### (if root is ZFS)&lt;br /&gt;
* create resolved-dsdaq.conf with main IP address of dnsmasq&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Resolve]&lt;br /&gt;
DNS=192.168.0.248&lt;br /&gt;
Domains=dsdaq triumf.ca&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* mkdir -p /etc/systemd/resolved.conf.d/&lt;br /&gt;
* /bin/rm -f /etc/systemd/resolved.conf.d/*.conf&lt;br /&gt;
* cp resolved-dsdaq.conf /etc/systemd/resolved.conf.d/&lt;br /&gt;
* systemctl stop systemd-resolved.service&lt;br /&gt;
* systemctl disable systemd-resolved.service&lt;br /&gt;
* systemctl enable dnsmasq&lt;br /&gt;
* systemctl restart dnsmasq&lt;br /&gt;
* try to &amp;quot;ping&amp;quot; or &amp;quot;host&amp;quot; some names from /etc/hosts, it should work&lt;br /&gt;
* try to ping daq00, daq00.triumf.ca, all should work&lt;br /&gt;
* resolved-dsdaq.conf goes into /etc/systemd/resolved.conf.d/ of all machines on the private network&lt;br /&gt;
* if not using systemd-resolved, edit /etc/resolv.conf&lt;br /&gt;
&lt;br /&gt;
== setup chronyd ==&lt;br /&gt;
&lt;br /&gt;
* enable ntp server:&lt;br /&gt;
* disable systemd-timesyncd, configure and enable chronyd per instructions above&lt;br /&gt;
* create dsdaq.conf&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# chrony config for dsdaq server&lt;br /&gt;
&lt;br /&gt;
#allow 192.168.0.0&lt;br /&gt;
#allow 192.168.1.0&lt;br /&gt;
#allow 192.168.2.0&lt;br /&gt;
allow all&lt;br /&gt;
&lt;br /&gt;
# end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* cp dsdaq.conf /etc/chrony/conf.d/&lt;br /&gt;
* systemctl restart chronyd&lt;br /&gt;
* chronyc tracking ### wait until time is synchronized (a few seconds)&lt;br /&gt;
* create dsdaq.sources # use hostname or IP address of chronyd server&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Put this file in /etc/chrony/sources.d&lt;br /&gt;
# systemctl restart chrony&lt;br /&gt;
# chronyc sources&lt;br /&gt;
# chronyc tracking&lt;br /&gt;
server dsdaqgw iburst prefer&lt;br /&gt;
# end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* dsdaq.sources goes to /etc/chrony/sources.d of all machines on the private network&lt;br /&gt;
&lt;br /&gt;
== setup diskless network booting ==&lt;br /&gt;
&lt;br /&gt;
=== setup pxelinux for legacy pxe boot ===&lt;br /&gt;
&lt;br /&gt;
* add bits in dnsmasq.conf&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dhcp-host=ac:1f:6b:9e:7f:4a,dsfe01,infinite&lt;br /&gt;
dhcp-boot=pxelinux.0&lt;br /&gt;
dhcp-option=17,&amp;quot;192.168.0.251:/nfsroot/%s,vers=3&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* setup pxelinux for Ubuntu-18&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd ~&lt;br /&gt;
wget https://www.kernel.org/pub/linux/utils/boot/syslinux/4.xx/syslinux-4.03.tar.bz2&lt;br /&gt;
tar xjvf syslinux-4.03.tar.bz2&lt;br /&gt;
cd syslinux-4.03&lt;br /&gt;
cp -pv ./core/pxelinux.0 ./com32/hdt/hdt.c32 ./memdisk/memdisk ./com32/menu/menu.c32 /zssd/tftpboot/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* cd /zssd/tftpboot&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wget http://ladd00.triumf.ca/tftpboot/memtest86+-4.20.iso.zip&lt;br /&gt;
wget http://ladd00.triumf.ca/tftpboot/memtest86+-5.01.iso.gz&lt;br /&gt;
wget http://ladd00.triumf.ca/tftpboot/modules.alias&lt;br /&gt;
wget http://ladd00.triumf.ca/tftpboot/modules.pcimap&lt;br /&gt;
wget http://ladd00.triumf.ca/tftpboot/pci.ids&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* mkdir pxelinux.cfg&lt;br /&gt;
* emacs -nw pxelinux.cfg/default&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
default menu.c32&lt;br /&gt;
prompt 0&lt;br /&gt;
&lt;br /&gt;
menu title Welcome to the DSVSLICE PXE boot menu&lt;br /&gt;
&lt;br /&gt;
timeout 50&lt;br /&gt;
&lt;br /&gt;
label hdt&lt;br /&gt;
  kernel hdt.c32&lt;br /&gt;
&lt;br /&gt;
label memtest86+-5.01 &lt;br /&gt;
  kernel memdisk iso initrd=memtest86+-5.01.iso.gz &lt;br /&gt;
&lt;br /&gt;
label memtest86+-4.20&lt;br /&gt;
  kernel memdisk iso initrd=memtest86+-4.20.iso.zip&lt;br /&gt;
&lt;br /&gt;
label vmlinuz-5.3.0-26-generic&lt;br /&gt;
  menu default&lt;br /&gt;
  kernel vmlinuz-5.3.0-26-generic&lt;br /&gt;
  append initrd=initrd.img-5.3.0-26-generic boot=nfs root=/dev/nfs netboot=nfs nfsroot=192.168.1.1:/zssd/nfsroot/dsfe01 toram ip=dhcp panic=60 BOOTIF=enp1s0f0&lt;br /&gt;
&lt;br /&gt;
#end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== setup pxelinux for efi pxe boot ===&lt;br /&gt;
&lt;br /&gt;
* https://c-nergy.be/blog/?p=13808&lt;br /&gt;
* add dnsmasq.conf bits. note: root-path does not actually work, it is hardwired pxelinux.cfg/default file.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# uefi pxe&lt;br /&gt;
&lt;br /&gt;
dhcp-boot=tag:uefipxe,uefi/syslinux.efi&lt;br /&gt;
dhcp-option-force=tag:fe01,option:root-path,192.168.0.248:/nfsroot/fe01&lt;br /&gt;
&lt;br /&gt;
# VX network 192.168.0.x&lt;br /&gt;
&lt;br /&gt;
dhcp-host=40:a6:b7:c1:d9:c5,fe01,infinite,set:uefipxe,set:fe01&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* apt install syslinux pxelinux syslinux-common syslinux-efi syslinux-utils&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /tftpboot/uefi&lt;br /&gt;
cp /usr/lib/SYSLINUX.EFI/efi64/syslinux.efi /tftpboot/uefi/&lt;br /&gt;
cp /usr/lib/syslinux/modules/efi64/ldlinux.e64 /tftpboot/uefi/&lt;br /&gt;
cp /usr/lib/syslinux/modules/efi64/menu.c32 /tftpboot/uefi/&lt;br /&gt;
cp /usr/lib/syslinux/modules/efi64/hdt.c32 /tftpboot/uefi/&lt;br /&gt;
cp /usr/lib/syslinux/modules/efi64/libutil.c32 /tftpboot/uefi/&lt;br /&gt;
cp /usr/lib/syslinux/modules/efi64/libmenu.c32 /tftpboot/uefi/&lt;br /&gt;
cp /usr/lib/syslinux/modules/efi64/libcom32.c32 /tftpboot/uefi/&lt;br /&gt;
cp /usr/lib/syslinux/modules/efi64/libgpl.c32 /tftpboot/uefi/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* try to boot, it should bomb with &amp;quot;cannot load pxelinux.cfg/default&amp;quot;&lt;br /&gt;
* mkdir /tftpboot/uefi/pxelinux.cfg&lt;br /&gt;
* create /tftpboot/uefi/pxelinux.cfg/default, note nfsroot path is hardwired, note &amp;quot;http:&amp;quot; is used to load vmlinuz and initrd files (because tftp is super slow)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
default menu.c32&lt;br /&gt;
prompt 0&lt;br /&gt;
&lt;br /&gt;
menu title Welcome to the DSDAQGW UEFI PXE boot menu&lt;br /&gt;
&lt;br /&gt;
timeout 50&lt;br /&gt;
&lt;br /&gt;
label vmlinuz-6.5.0-17-generic&lt;br /&gt;
  kernel http://192.168.0.248:8088/uefi/vmlinuz-6.5.0-17-generic&lt;br /&gt;
  append initrd=http://192.168.0.248:8088/uefi/initrd.img-6.5.0-17-generic boot=nfs root=/dev/nfs netboot=nfs nfsroot=auto rw ip=dhcp panic=60&lt;br /&gt;
&lt;br /&gt;
# append initrd=http://192.168.0.248:8088/uefi/initrd.img-6.5.0-17-generic boot=nfs root=/dev/nfs netboot=nfs nfsroot=192.168.0.248:/nfsroot/fe01 rw ip=dhcp panic=60&lt;br /&gt;
&lt;br /&gt;
#  append initrd=initrd.img-6.5.0-17-generic boot=nfs root=/dev/nfs netboot=nfs nfsroot=192.168.0.248:/nfsroot/fe01 rw ip=dhcp panic=60&lt;br /&gt;
#  append initrd=initrd.img-6.5.0-17-generic boot=nfs root=/dev/nfs netboot=nfs nfsroot=auto ip=dhcp rw panic=60&lt;br /&gt;
&lt;br /&gt;
#end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* try to boot, it will bomb with &amp;quot;cannot load http://....&amp;quot;&lt;br /&gt;
* install mini_httpd on port 8088, see https://acme.com/software/mini_httpd/&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install mini-httpd&lt;br /&gt;
emacs -nw /etc/default/mini-httpd # set &amp;quot;START=1&amp;quot;&lt;br /&gt;
emacs -nw /etc/mini-httpd.conf # set &amp;quot;host=192.168.0.248&amp;quot;, &amp;quot;port=8088&amp;quot;, &amp;quot;data_dir=/tftpboot&amp;quot;&lt;br /&gt;
mkdir /etc/systemd/system/mini-httpd.service.d&lt;br /&gt;
echo -e &amp;quot;[Unit]\nAfter=network-online.target\n&amp;quot; &amp;gt; /etc/systemd/system/mini-httpd.service.d/local.conf&lt;br /&gt;
systemctl enable mini-httpd&lt;br /&gt;
systemctl restart mini-httpd&lt;br /&gt;
systemctl status mini-httpd&lt;br /&gt;
wget http://192.168.0.248:8088/uefi/syslinux.efi&lt;br /&gt;
tail -100 /var/log/mini_httpd.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* fix initramfs bug for &amp;quot;nfsroot=auto&amp;quot;, otherwise, &amp;quot;nfsroot=&amp;quot; has to be different for each machine and you have to have separate pxelinux config files for each machine&lt;br /&gt;
** emacs -nw /usr/lib/initramfs-tools/etc/dhcp/dhclient-enter-hooks.d/config&lt;br /&gt;
** add &amp;quot;echo ROOTPATH=...&amp;quot; if it is missing (Ubuntu LTS 22.04)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                echo &amp;quot;ROOTSERVER=&#039;${new_routers%% *}&#039;&amp;quot; &lt;br /&gt;
                echo &amp;quot;ROOTPATH=&#039;$new_root_path&#039;&amp;quot; &lt;br /&gt;
                echo &amp;quot;HOSTNAME=&#039;$new_host_name&#039;&amp;quot; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
** regenerate initramfs (be careful you generate it for the right kernel!)&lt;br /&gt;
** see https://bugs.launchpad.net/ubuntu/+source/initramfs-tools/+bug/2054482&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkinitramfs 6.5.0-18-generic&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* copy linux kernel and initrd&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /boot/vmlinuz-6.5.0-18-generic /tftpboot/uefi/&lt;br /&gt;
cp /boot/initrd.img-6.5.0-18-generic /tftpboot/uefi/&lt;br /&gt;
chmod a+r /tftpboot/uefi/*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* try to boot, should bomb with messages about &amp;quot;trying to mount root filesystem&amp;quot;&lt;br /&gt;
* tail /var/log/syslog&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 available DHCP subnet: 192.168.0.0/255.255.255.0&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 vendor class: PXEClient:Arch:00007:UNDI:003016&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 DHCPDISCOVER(enp1s0f0) 40:a6:b7:c1:d9:c5 &lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 tags: uefipxe, fe01, known, enp1s0f0&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 DHCPOFFER(enp1s0f0) 192.168.0.110 40:a6:b7:c1:d9:c5 &lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 1:netmask, 2:time-offset, 3:router, 4, 5, &lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 6:dns-server, 12:hostname, 13:boot-file-size, &lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 15:domain-name, 17:root-path, 18:extension-path, &lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 22:max-datagram-reassembly, 23:default-ttl, &lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 28:broadcast, 40:nis-domain, 41:nis-server, &lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 42:ntp-server, 43:vendor-encap, 50:requested-address, &lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 51:lease-time, 54:server-identifier, 58:T1, &lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 59:T2, 60:vendor-class, 66:tftp-server, 67:bootfile-name, &lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 97:client-machine-id, 128, 129, 130, 131, &lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 132, 133, 134, 135&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 next server: 192.168.0.248&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 broadcast response&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  1 option: 53 message-type  2&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option: 54 server-identifier  192.168.0.248&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option: 51 lease-time  infinite&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size: 18 option: 67 bootfile-name  uefi/syslinux.efi&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option:  1 netmask  255.255.255.0&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option: 28 broadcast  192.168.0.255&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option:  3 router  192.168.0.248&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  5 option: 15 domain-name  dsdaq&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option: 12 hostname  fe01&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size: 27 option: 17 root-path  192.168.0.248:/nfsroot/fe01&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option: 42 ntp-server  192.168.0.248&lt;br /&gt;
Feb 16 20:43:02 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option:  6 dns-server  192.168.0.248&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 available DHCP subnet: 192.168.0.0/255.255.255.0&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 vendor class: PXEClient:Arch:00007:UNDI:003016&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 DHCPREQUEST(enp1s0f0) 192.168.0.110 40:a6:b7:c1:d9:c5 &lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 tags: uefipxe, fe01, known, enp1s0f0&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 DHCPACK(enp1s0f0) 192.168.0.110 40:a6:b7:c1:d9:c5 fe01&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 1:netmask, 2:time-offset, 3:router, 4, 5, &lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 6:dns-server, 12:hostname, 13:boot-file-size, &lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 15:domain-name, 17:root-path, 18:extension-path, &lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 22:max-datagram-reassembly, 23:default-ttl, &lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 28:broadcast, 40:nis-domain, 41:nis-server, &lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 42:ntp-server, 43:vendor-encap, 50:requested-address, &lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 51:lease-time, 54:server-identifier, 58:T1, &lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 59:T2, 60:vendor-class, 66:tftp-server, 67:bootfile-name, &lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 97:client-machine-id, 128, 129, 130, 131, &lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 requested options: 132, 133, 134, 135&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 next server: 192.168.0.248&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 broadcast response&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  1 option: 53 message-type  5&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option: 54 server-identifier  192.168.0.248&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option: 51 lease-time  infinite&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size: 18 option: 67 bootfile-name  uefi/syslinux.efi&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option:  1 netmask  255.255.255.0&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option: 28 broadcast  192.168.0.255&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option:  3 router  192.168.0.248&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  5 option: 15 domain-name  dsdaq&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option: 12 hostname  fe01&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size: 27 option: 17 root-path  192.168.0.248:/nfsroot/fe01&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option: 42 ntp-server  192.168.0.248&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065885 sent size:  4 option:  6 dns-server  192.168.0.248&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-tftp[3629416]: error 8 User aborted the transfer received from 192.168.0.110&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-tftp[3629416]: sent /tftpboot/uefi/syslinux.efi to 192.168.0.110&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-tftp[3629416]: sent /tftpboot/uefi/syslinux.efi to 192.168.0.110&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 available DHCP subnet: 192.168.0.0/255.255.255.0&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 DHCPDISCOVER(enp1s0f0) 40:a6:b7:c1:d9:c5 &lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 tags: uefipxe, fe01, known, enp1s0f0&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 DHCPOFFER(enp1s0f0) 192.168.0.110 40:a6:b7:c1:d9:c5 &lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 requested options: 1:netmask, 3:router, 6:dns-server&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 bootfile name: uefi/syslinux.efi&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 next server: 192.168.0.248&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 broadcast response&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  1 option: 53 message-type  2&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  4 option: 54 server-identifier  192.168.0.248&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  4 option: 51 lease-time  infinite&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  4 option:  1 netmask  255.255.255.0&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  4 option: 28 broadcast  192.168.0.255&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  4 option:  3 router  192.168.0.248&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size: 27 option: 17 root-path  192.168.0.248:/nfsroot/fe01&lt;br /&gt;
Feb 16 20:43:05 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  4 option:  6 dns-server  192.168.0.248&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 available DHCP subnet: 192.168.0.0/255.255.255.0&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 DHCPREQUEST(enp1s0f0) 192.168.0.110 40:a6:b7:c1:d9:c5 &lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 tags: uefipxe, fe01, known, enp1s0f0&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 DHCPACK(enp1s0f0) 192.168.0.110 40:a6:b7:c1:d9:c5 fe01&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 requested options: 1:netmask, 3:router, 6:dns-server&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 bootfile name: uefi/syslinux.efi&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 next server: 192.168.0.248&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 broadcast response&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  1 option: 53 message-type  5&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  4 option: 54 server-identifier  192.168.0.248&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  4 option: 51 lease-time  infinite&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  4 option:  1 netmask  255.255.255.0&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  4 option: 28 broadcast  192.168.0.255&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  4 option:  3 router  192.168.0.248&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size: 27 option: 17 root-path  192.168.0.248:/nfsroot/fe01&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-dhcp[3629416]: 2348065887 sent size:  4 option:  6 dns-server  192.168.0.248&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-tftp[3629416]: sent /tftpboot/uefi/ldlinux.e64 to 192.168.0.110&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-tftp[3629416]: file /tftpboot/uefi/pxelinux.cfg/01-40-a6-b7-c1-d9-c5 not found&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-tftp[3629416]: file /tftpboot/uefi/pxelinux.cfg/C0A8006E not found&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-tftp[3629416]: file /tftpboot/uefi/pxelinux.cfg/C0A8006 not found&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-tftp[3629416]: file /tftpboot/uefi/pxelinux.cfg/C0A800 not found&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-tftp[3629416]: file /tftpboot/uefi/pxelinux.cfg/C0A80 not found&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-tftp[3629416]: file /tftpboot/uefi/pxelinux.cfg/C0A8 not found&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-tftp[3629416]: file /tftpboot/uefi/pxelinux.cfg/C0A not found&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-tftp[3629416]: file /tftpboot/uefi/pxelinux.cfg/C0 not found&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-tftp[3629416]: file /tftpboot/uefi/pxelinux.cfg/C not found&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-tftp[3629416]: sent /tftpboot/uefi/pxelinux.cfg/default to 192.168.0.110&lt;br /&gt;
Feb 16 20:43:09 dsdaqgw dnsmasq-tftp[3629416]: sent /tftpboot/uefi/menu.c32 to 192.168.0.110&lt;br /&gt;
Feb 16 20:43:10 dsdaqgw dnsmasq-tftp[3629416]: sent /tftpboot/uefi/libutil.c32 to 192.168.0.110&lt;br /&gt;
Feb 16 20:43:10 dsdaqgw dnsmasq-tftp[3629416]: sent /tftpboot/uefi/pxelinux.cfg/default to 192.168.0.110&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 available DHCP subnet: 192.168.0.0/255.255.255.0&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 client provides name: dsdaqgw.triumf.ca&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 DHCPDISCOVER(enp1s0f0) 40:a6:b7:c1:d9:c5 &lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 tags: uefipxe, fe01, known, enp1s0f0&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 DHCPOFFER(enp1s0f0) 192.168.0.110 40:a6:b7:c1:d9:c5 &lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 requested options: 1:netmask, 28:broadcast, 2:time-offset, 3:router, &lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 requested options: 15:domain-name, 6:dns-server, 119:domain-search, &lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 requested options: 12:hostname, 44:netbios-ns, 47:netbios-scope, &lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 requested options: 26:mtu, 121:classless-static-route, 42:ntp-server&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 bootfile name: uefi/syslinux.efi&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 next server: 192.168.0.248&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  1 option: 53 message-type  2&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option: 54 server-identifier  192.168.0.248&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option: 51 lease-time  infinite&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option:  1 netmask  255.255.255.0&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option: 28 broadcast  192.168.0.255&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option:  3 router  192.168.0.248&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  5 option: 15 domain-name  dsdaq&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size: 27 option: 17 root-path  192.168.0.248:/nfsroot/fe01&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option: 42 ntp-server  192.168.0.248&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option:  6 dns-server  192.168.0.248&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 available DHCP subnet: 192.168.0.0/255.255.255.0&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 client provides name: dsdaqgw.triumf.ca&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 DHCPREQUEST(enp1s0f0) 192.168.0.110 40:a6:b7:c1:d9:c5 &lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 tags: uefipxe, fe01, known, enp1s0f0&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 DHCPACK(enp1s0f0) 192.168.0.110 40:a6:b7:c1:d9:c5 fe01&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 requested options: 1:netmask, 28:broadcast, 2:time-offset, 3:router, &lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 requested options: 15:domain-name, 6:dns-server, 119:domain-search, &lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 requested options: 12:hostname, 44:netbios-ns, 47:netbios-scope, &lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 requested options: 26:mtu, 121:classless-static-route, 42:ntp-server&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 bootfile name: uefi/syslinux.efi&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 next server: 192.168.0.248&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  1 option: 53 message-type  5&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option: 54 server-identifier  192.168.0.248&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option: 51 lease-time  infinite&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option:  1 netmask  255.255.255.0&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option: 28 broadcast  192.168.0.255&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option:  3 router  192.168.0.248&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  5 option: 15 domain-name  dsdaq&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option: 12 hostname  fe01&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size: 27 option: 17 root-path  192.168.0.248:/nfsroot/fe01&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option: 42 ntp-server  192.168.0.248&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw dnsmasq-dhcp[3629416]: 3693523458 sent size:  4 option:  6 dns-server  192.168.0.248&lt;br /&gt;
Feb 16 20:44:54 dsdaqgw rpc.mountd[3350210]: authenticated mount request from 192.168.0.110:981 for /nfsroot/fe01 (/nfsroot/fe01)&lt;br /&gt;
Feb 16 20:45:07 dsdaqgw rpc.mountd[3350210]: authenticated unmount request from 192.168.0.110:859 for /nfsroot/fe01/tmp/autoDY4k5u (/nfsroot/fe01)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* tail /var/log/mini_httpd.log&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
192.168.0.110 - - [16/Feb/2024:20:43:15 -0800] &amp;quot;GET /uefi/vmlinuz-6.5.0-17-generic HTTP/1.0&amp;quot; 200 14227944 &amp;quot;&amp;quot; &amp;quot;Syslinux/6.04&amp;quot;&lt;br /&gt;
192.168.0.110 - - [16/Feb/2024:20:43:24 -0800] &amp;quot;GET /uefi/initrd.img-6.5.0-17-generic HTTP/1.0&amp;quot; 200 137824833 &amp;quot;&amp;quot; &amp;quot;Syslinux/6.04&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== setup efi http boot ===&lt;br /&gt;
&lt;br /&gt;
https://documentation.suse.com/sles/15-SP2/html/SLES-all/cha-deployment-prep-uefi-httpboot.html&lt;br /&gt;
&lt;br /&gt;
=== setup linux kernel ===&lt;br /&gt;
&lt;br /&gt;
* copy the kernel files&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /boot&lt;br /&gt;
rsync -av config* initrd* System.map* vmlinuz* /tftpboot/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* cd /tftpboot&lt;br /&gt;
* chmod a+r *&lt;br /&gt;
&lt;br /&gt;
=== setup nfs ===&lt;br /&gt;
&lt;br /&gt;
* apt-get install nfs-kernel-server&lt;br /&gt;
* enable NFS over UDP, edit /etc/nfs.conf add &amp;quot;udp=y&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
udp=y&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl restart nfs-server.service&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* emacs -nw /etc/exports&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/nfsroot/dsfe01 dsfe01(rw,no_root_squash,async,no_subtree_check)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* enable services&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl enable nfs-server&lt;br /&gt;
systemctl enable nfs-mountd&lt;br /&gt;
systemctl enable nfs-idmapd&lt;br /&gt;
systemctl restart nfs-server&lt;br /&gt;
systemctl restart nfs-mountd&lt;br /&gt;
systemctl restart nfs-idmapd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* after editing /etc/exports, run&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
exportfs -av&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== setup userland ===&lt;br /&gt;
&lt;br /&gt;
!!! ubuntu-18 version !!!&lt;br /&gt;
&lt;br /&gt;
* zfs create rpool/nfsroot&lt;br /&gt;
* zfs set dedup=verify rpool/nfsroot ### enable deduplication to save disk space because most linux images have mostly identical files&lt;br /&gt;
* clone ubuntu&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /nfsroot/dsfe01&lt;br /&gt;
cd /&lt;br /&gt;
rsync -avx . /nfsroot/dsfe01&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* edit config files:&lt;br /&gt;
* cd /nfsroot/dsfe01&lt;br /&gt;
* emacs -nw etc/hostname ### change to dsfe01&lt;br /&gt;
* emacs -nw etc/mailname ### change to dsfe01&lt;br /&gt;
* emacs -nw etc/yp.conf ### change daq00.triumf.ca to musr00.triumf.ca&lt;br /&gt;
* emacs -nw etc/defaultdomain ### change to MUSR-NIS&lt;br /&gt;
* cp -pvf ../lxcpet-SL610/etc/ssh/*key* etc/ssh/ ### preserve the ssh keys&lt;br /&gt;
* emacs -nw opt/gonodeinfo/gonodeinfo.conf ### update information&lt;br /&gt;
* emacs -nw root/.ssh/authorized_keys ### update root ssh keys&lt;br /&gt;
* emacs -nw etc/fstab ### add this&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
192.168.1.1:/nfsroot/dsfe01 / nfs defaults,nolock 0 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* emacs -nw etc/chrony/chrony.conf&lt;br /&gt;
** comment-out all &amp;quot;pool&amp;quot; and &amp;quot;server&amp;quot; entries&lt;br /&gt;
** add entry &amp;quot;server 192.168.1.1 iburst&amp;quot;&lt;br /&gt;
&lt;br /&gt;
After dsfe01 is booted:&lt;br /&gt;
&lt;br /&gt;
* disable services:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
systemctl disable apache2&lt;br /&gt;
systemctl disable dnsmasq&lt;br /&gt;
systemctl disable zfs-import-cache&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To setup additional machines, clone dsfe01 instead of cloning the gateway machine&lt;br /&gt;
&lt;br /&gt;
=== Allow manpages to be viewed ===&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; is mounted over NFS, &amp;lt;code&amp;gt;man&amp;lt;/code&amp;gt; will report a permission error. Fix it with:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ln -s /etc/apparmor.d/usr.bin.man /etc/apparmor.d/disable/&lt;br /&gt;
apparmor_parser -R /etc/apparmor.d/usr.bin.man&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== setup shared home directory ==&lt;br /&gt;
&lt;br /&gt;
=== on the gateway machine ===&lt;br /&gt;
* define netgroups&lt;br /&gt;
* emacs -nw /etc/netgroup&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dsfe (dsfe01,,) (dsfe02,,)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* emacs -nw /etc/nsswitch.conf ### edit the netgroup line to read:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
netgroup: files&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* export the home directories:&lt;br /&gt;
* emacs -nw /etc/exports ### add this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/zssd/home1 @dsfe(rw,no_root_squash,async,no_subtree_check)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* exportfs -rc&lt;br /&gt;
&lt;br /&gt;
=== on the frontend machine ===&lt;br /&gt;
&lt;br /&gt;
* mkdir /home&lt;br /&gt;
* emacs -nw /etc/fstab ### add this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
192.168.1.1:/zssd/home1 /home nfs defaults 0 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* mount -a&lt;br /&gt;
&lt;br /&gt;
== setup NAT ==&lt;br /&gt;
&lt;br /&gt;
NAT allows machines on the private network to connect to the internet: https://en.wikipedia.org/wiki/Network_address_translation&lt;br /&gt;
&lt;br /&gt;
In these examples:&lt;br /&gt;
* replace &amp;quot;eno1&amp;quot; with name of the outgoing interface (the one connected to the TRIUMF network).&lt;br /&gt;
* replace &amp;quot;enp11s0&amp;quot; with name of the private network interface (192.168.1.x network)&lt;br /&gt;
&lt;br /&gt;
* emacs -nw /etc/rc.local ### add this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# /etc/rc.local&lt;br /&gt;
&lt;br /&gt;
# enable NAT&lt;br /&gt;
&lt;br /&gt;
/sbin/iptables -t nat -A POSTROUTING -o eno1 -j MASQUERADE&lt;br /&gt;
iptables -L -v&lt;br /&gt;
&lt;br /&gt;
# uncomment following lines if machine has prohibitive FORWARD rules:&lt;br /&gt;
#/sbin/iptables -I FORWARD -i eno1 -o enp11s0 -m state --state RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
#/sbin/iptables -I FORWARD -i enp11s0 -o eno1 -j ACCEPT&lt;br /&gt;
#iptables -L -v&lt;br /&gt;
&lt;br /&gt;
iptables -L -v&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
#sysctl -a | grep forward&lt;br /&gt;
&lt;br /&gt;
sh /etc/firewall-rfc1918.sh&lt;br /&gt;
&lt;br /&gt;
# end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* emacs -nw /etc/firewall-rfc1918.sh&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# firewall-rfc1918.sh&lt;br /&gt;
&lt;br /&gt;
# prevent RFC1918 private network IP addresses from&lt;br /&gt;
# going in and out from our uplink.&lt;br /&gt;
&lt;br /&gt;
ETH=eno1&lt;br /&gt;
&lt;br /&gt;
iptables -F in-rfc1918&lt;br /&gt;
iptables -N in-rfc1918&lt;br /&gt;
iptables -A in-rfc1918 --dst 10.0.0.0/8      -j REJECT&lt;br /&gt;
iptables -A in-rfc1918 --dst 172.16.0.0/12   -j REJECT&lt;br /&gt;
iptables -A in-rfc1918 --dst 192.168.0.0/16  -j REJECT&lt;br /&gt;
&lt;br /&gt;
iptables -D INPUT -j in-rfc1918 -i $ETH&lt;br /&gt;
iptables -D INPUT -j in-rfc1918 -i $ETH&lt;br /&gt;
iptables -I INPUT -j in-rfc1918 -i $ETH&lt;br /&gt;
&lt;br /&gt;
iptables -F out-rfc1918&lt;br /&gt;
iptables -N out-rfc1918&lt;br /&gt;
iptables -A out-rfc1918 --dst 10.0.0.0/8      -j REJECT&lt;br /&gt;
iptables -A out-rfc1918 --dst 172.16.0.0/12   -j REJECT&lt;br /&gt;
iptables -A out-rfc1918 --dst 192.168.0.0/16  -j REJECT&lt;br /&gt;
&lt;br /&gt;
iptables -D OUTPUT -j out-rfc1918 -o $ETH&lt;br /&gt;
iptables -D OUTPUT -j out-rfc1918 -o $ETH&lt;br /&gt;
iptables -I OUTPUT -j out-rfc1918 -o $ETH&lt;br /&gt;
&lt;br /&gt;
iptables -D FORWARD -j out-rfc1918 -o $ETH &lt;br /&gt;
iptables -D FORWARD -j out-rfc1918 -o $ETH &lt;br /&gt;
iptables -I FORWARD -j out-rfc1918 -o $ETH &lt;br /&gt;
&lt;br /&gt;
# allow TRIUMF-SECURE network&lt;br /&gt;
&lt;br /&gt;
iptables -I in-rfc1918 -s 10.90.0.0/255.255.0.0 -j ACCEPT &lt;br /&gt;
iptables -I out-rfc1918 -d 10.90.0.0/255.255.0.0 -j ACCEPT &lt;br /&gt;
&lt;br /&gt;
# show configuration&lt;br /&gt;
&lt;br /&gt;
iptables -L -v&lt;br /&gt;
&lt;br /&gt;
#end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= KVM =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install cpu-checker&lt;br /&gt;
&lt;br /&gt;
root@daq13:~# kvm-ok &lt;br /&gt;
INFO: /dev/kvm exists&lt;br /&gt;
KVM acceleration can be used&lt;br /&gt;
root@daq13:~# &lt;br /&gt;
&lt;br /&gt;
(if not, shutdown, go into BIOS settings, enable CPU virtualization)&lt;br /&gt;
&lt;br /&gt;
apt install virtinst ### will install many packages&lt;br /&gt;
apt install libvirt-clients libvirt-daemon-system-systemd libvirt-daemon qemu qemu-kvm libvirt-daemon-system virtinst bridge-utils&lt;br /&gt;
&lt;br /&gt;
root@daq13:/home1/wheel# virsh list --all&lt;br /&gt;
 Id   Name           State&lt;br /&gt;
------------------------------&lt;br /&gt;
 1    ubuntu-guest   running&lt;br /&gt;
&lt;br /&gt;
apt install virt-manager&lt;br /&gt;
&lt;br /&gt;
virt-install --name ubuntu-guest --os-variant ubuntu20.04 --vcpus 2 --ram 2048 --location /daq/daqstore/olchansk/linux/Ubuntu/ubuntu-20.04.3-desktop-amd64.iso --network bridge=virbr0,model=virtio --graphics none --extra-args=&#039;console=ttyS0,115200n8 serial&#039;&lt;br /&gt;
&lt;br /&gt;
virtual machine will start, boot, etc&lt;br /&gt;
to get out of it, CTRL + Shift followed by ]&lt;br /&gt;
&lt;br /&gt;
ssh wheel@daq13&lt;br /&gt;
virt-manager&lt;br /&gt;
&lt;br /&gt;
run virt-install again, omit &amp;quot;--graphics none&amp;quot;, open graphics console from virt-manager, it booted into ubuntu installer desktop&lt;br /&gt;
&lt;br /&gt;
virt-install --name test10 --os-variant centos6.10 --vcpus 2 --ram 2048 --import --filesystem /kvm_ladd00,/ --network bridge=virbr0,model=virtio --boot kernel=/kvm_ladd00/boot/vmlinuz-2.6.32-754.35.1.el6.x86_64,initrd=/kvm_ladd00/boot/initramfs-2.6.32-754.35.1.el6.x86_64.img,kernel_args=&amp;quot;root=/dev/sda console=ttyS0,115200n8 serial&amp;quot; --graphics none&lt;br /&gt;
&lt;br /&gt;
virt-install --name test14 --os-variant centos6.10 --vcpus 2 --ram 2048 --import --disk /tmp/xxx/ladd00.img,bus=sata --network bridge=virbr0,model=virtio --boot kernel=/kvm_ladd00/boot/vmlinuz-2.6.32-754.35.1.el6.x86_64,initrd=/kvm_ladd00/boot/initramfs-2.6.32-754.35.1.el6.x86_64.img,kernel_args=&amp;quot;root=/dev/sda console=ttyS0,115200n8 serial rdshell&amp;quot; --graphics none --check path_in_use=off&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
build image&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dd if=/dev/zero of=/tmp/xxx/ladd00.img bs=1024M count=20&lt;br /&gt;
mkfs.ext3 /tmp/xxx/ladd00.img ### ext4 fails to mount by SL6 kernel, &amp;quot;unknown ext4 options&amp;quot;&lt;br /&gt;
cd /kvm_ladd00/&lt;br /&gt;
mount -o loop /tmp/xxx/ladd00.img /mnt/tmp&lt;br /&gt;
rsync -av . /mnt/tmp/ --delete&lt;br /&gt;
umount /mnt/tmp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
on the guest, configure network: /etc/rc.local&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
#&lt;br /&gt;
# This script will be executed *after* all the other init scripts.&lt;br /&gt;
# You can put your own initialization stuff in here if you don&#039;t&lt;br /&gt;
# want to do the full Sys V style init stuff.&lt;br /&gt;
&lt;br /&gt;
touch /var/lock/subsys/local&lt;br /&gt;
&lt;br /&gt;
ifconfig eth2 192.168.122.2&lt;br /&gt;
route add -net 0.0.0.0 gw 192.168.122.1&lt;br /&gt;
ifconfig -a&lt;br /&gt;
netstat -rn&lt;br /&gt;
&lt;br /&gt;
# end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= ARM64 cross-compiler =&lt;br /&gt;
&lt;br /&gt;
* arm64, aarch64 are Xilinx FPGA Cortex-A53, RPi4, RPi5 machines&lt;br /&gt;
* install packages:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install g++-12-aarch64-linux-gnu gcc-12-aarch64-linux-gnu-base libstdc++-12-dev-arm64-cross&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
aarch64-linux-gnu-gcc-12 -o ttcp.aarch64 ttcp.c -static&lt;br /&gt;
aarch64-linux-gnu-g++-12 -o fecdm.exe -O2 -g -Wall -Wuninitialized -std=c++20 fecdm.o dsdm.o /home/dsdaqdev/packages_common/midas/linux-aarch64-remoteonly/lib/libmidas.a -pthread -lrt -lutil /nfsroot/gdm00/usr/lib/aarch64-linux-gnu/libi2c.a -static&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= ARM cross-compiler =&lt;br /&gt;
&lt;br /&gt;
NOTE!!!&lt;br /&gt;
&lt;br /&gt;
THIS IS NOT AN AARCH64 (arm64) CROSSCOMPILER!&lt;br /&gt;
&lt;br /&gt;
NOTE!!!&lt;br /&gt;
&lt;br /&gt;
* install packages:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install libgcc-9-dev-arm64-cross&lt;br /&gt;
apt install gcc-arm-linux-gnueabi&lt;br /&gt;
apt install gcc-arm-linux-gnueabihf&lt;br /&gt;
apt install g++-arm-linux-gnueabihf&lt;br /&gt;
apt install g++-arm-linux-gnueabi&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* find out the correct -march setting, on the target machine, run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@gdm00:~# g++ -Q --help=target | grep march&lt;br /&gt;
  -march=                     		armv8-a&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
arm-linux-gnueabi-gcc -o ttcp1 ttcp.c -march=armv7 -static&lt;br /&gt;
arm-linux-gnueabi-gcc -o memcpy.armv7 memcpy.cc -march=armv7 -static -O2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= 32-bit intel cross-compiler =&lt;br /&gt;
&lt;br /&gt;
Ubuntu 22.04:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt install libstdc++-11-dev:i386&lt;br /&gt;
apt install zlib1g-dev:i386&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
NOTES:&lt;br /&gt;
* &amp;quot;g++ -m32&amp;quot; does not find libstdc++, please use &amp;quot;g++ -m32 -L/usr/lib/gcc/i686-linux-gnu/11/&amp;quot;&lt;br /&gt;
* to cross-build 32-bit MIDAS, use &amp;quot;make linux32&amp;quot;.&lt;br /&gt;
* executables cross-build on Ubuntu-22 do NOT run on 32-bit Debain-11 (GLIBC and GLIBCXX version mismatch)&lt;br /&gt;
* executables cross-build on Ubuntu-22 run on 32-bit Debian-12.&lt;br /&gt;
&lt;br /&gt;
= SSH settings for EPICS =&lt;br /&gt;
&lt;br /&gt;
* TRIUMF EPICS runs obsolete version of SSH&lt;br /&gt;
* add this to the use .ssh/config&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Host sbp1*&lt;br /&gt;
HostKeyAlgorithms +ssh-rsa&lt;br /&gt;
PubKeyAcceptedAlgorithms +ssh-rsa&lt;br /&gt;
KexAlgorithms +diffie-hellman-group1-sha1&lt;br /&gt;
ForwardX11 yes&lt;br /&gt;
ForwardX11Trusted yes&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= changes for VME processors =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt -y remove sysstat man-db&lt;br /&gt;
apt -y purge dkms&lt;br /&gt;
apt -y purge mdadm&lt;br /&gt;
apt -y autoremove&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR:_Software_overview&amp;diff=7853</id>
		<title>BNMR: Software overview</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR:_Software_overview&amp;diff=7853"/>
		<updated>2024-07-26T22:16:53Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Pagelinks}}&lt;br /&gt;
&lt;br /&gt;
== Program list ==&lt;br /&gt;
&lt;br /&gt;
Programs with the _32bit suffix are designed to be run on the VMIC machine; all others are designed to be run on the host PC.&lt;br /&gt;
&lt;br /&gt;
=== Compiled &amp;quot;real&amp;quot; programs ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/febnmr_32bit.exe&amp;lt;/code&amp;gt; ({{bnmr}} only) - see [[BNMR:_frontend|frontend]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/febnqr_32bit.exe&amp;lt;/code&amp;gt; ({{bnqr}} only) - see [[BNMR:_frontend|frontend]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/bnxr_logger.exe&amp;lt;/code&amp;gt; - see [[BNMR: Data Logging|data logging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/logger_cleanup.exe&amp;lt;/code&amp;gt; - see [[BNMR: Data Logging#Cleaning_up_if_end-of-run_fails|data logging]]&lt;br /&gt;
&lt;br /&gt;
=== Python &amp;quot;real&amp;quot; programs ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/beamtime_monitor.py&amp;lt;/code&amp;gt; - see [[BNMR:_Shift_Monitor|shift monitor]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/beamtime_to_excel.py&amp;lt;/code&amp;gt; - see [[BNMR:_Shift_Monitor|shift monitor]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/elog_every_run.py&amp;lt;/code&amp;gt; - see [[BNMR:_Scripts#Run_transition_scripts|run transition scripts]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/mode_changer.py&amp;lt;/code&amp;gt; - see [[BNMR:_Mode_changer|mode changer]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/rf_calculator_fe.py&amp;lt;/code&amp;gt; - see [[BNMR:_RF_calculator|RF calculator]]&lt;br /&gt;
* &amp;lt;code&amp;gt;cycling_framework/ppg/ppg_compiler_fe.py&amp;lt;/code&amp;gt; - see [[BNMR:_PPG_compiler|PPG compiler]]&lt;br /&gt;
* &amp;lt;code&amp;gt;cycling_framework/run_comments/run_comment_editor.py&amp;lt;/code&amp;gt; - see [[BNMR:_Data_Logging#Run_comments|data logging]]&lt;br /&gt;
&lt;br /&gt;
=== Compiled programs for debugging hardware etc ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/bnmrbeamsim_32bit.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/camp_test.exe&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bin/camp_test_32bit.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/epics_test.exe&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bin/epics_test_32bit.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/vppg_interactive_32bit.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/sis3801_interactive_32bit.exe&amp;lt;/code&amp;gt; ({{bnmr}} only) - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/sis3820_interactive_32bit.exe&amp;lt;/code&amp;gt; ({{bnqr}} only) - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/psm_interactive_32bit.exe&amp;lt;/code&amp;gt;  ({{bnqr}} only) - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/psm3_interactive_32bit.exe&amp;lt;/code&amp;gt;  ({{bnmr}} only) - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
&lt;br /&gt;
=== Compiled automated tests ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/unit_tests/*.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Tests#Automated_tests_that_don.27t_use_the_ODB|Automated tests that don&#039;t use the ODB]]&lt;br /&gt;
&lt;br /&gt;
=== Python test programs ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/test_mud_logger.py&amp;lt;/code&amp;gt; - see [[BNMR:_Tests#Automated_tests_that_do_use_the_ODB|automated tests that use the ODB]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/test_ppg_calc.py&amp;lt;/code&amp;gt; - see [[BNMR:_Tests#Automated_tests_that_do_use_the_ODB|automated tests that use the ODB]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/test_psm_calc.py&amp;lt;/code&amp;gt; - see [[BNMR:_Tests#Automated_tests_that_do_use_the_ODB|automated tests that use the ODB]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/diff_mud_file.py&amp;lt;/code&amp;gt; - see [[BNMR:_Data_Logging#MUD_files|data logging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/dump_mud_file.py&amp;lt;/code&amp;gt; - see [[BNMR:_Data_Logging#MUD_files|data logging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;cycling_framework/ppg/tests/test_ppg.py&amp;lt;/code&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
=== Unused compiled programs ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/epics_log.exe&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bin/epics_log_32bit.exe&amp;lt;/code&amp;gt; - EPICS logging is handled by the MUD logger in {{bnmqr|join=/}}&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/tppg_interactive_32bit.exe&amp;lt;/code&amp;gt; - this version is for TRIUMF PPGs; we use PulseBlaster PPGs&lt;br /&gt;
&lt;br /&gt;
== Repository location ==&lt;br /&gt;
&lt;br /&gt;
The main repository is on BitBucket at [https://bitbucket.org/ttriumfdaq/bnmr/ https://bitbucket.org/ttriumfdaq/bnmr/].&lt;br /&gt;
&lt;br /&gt;
== Updating bnmr/bnqr software ==&lt;br /&gt;
&lt;br /&gt;
The main repository uses submodules for some dependencies, so checking out updates requires:&lt;br /&gt;
&lt;br /&gt;
 git pull&lt;br /&gt;
 git submodule update&lt;br /&gt;
&lt;br /&gt;
To compile the real software, we currently have to compile separately on isdaq01 (for stuff that runs there) and isdaq06 (for stuff that runs on lxbnmr/lxbnqr). This is because isdaq06 and the lx machines run modern OSes, and isdaq01 is still on an old OS (so we can&#039;t cross-compile from it). Once isdaq01 has been upgraded, we will be able to run all compilation from there again and compile times will be significantly faster.&lt;br /&gt;
&lt;br /&gt;
 #&lt;br /&gt;
 # For the first install&lt;br /&gt;
 #&lt;br /&gt;
 # on isdaq01&lt;br /&gt;
 mkdir build&lt;br /&gt;
 cd build&lt;br /&gt;
 cmake .. -DEXP=BNMR -DONLY_64=1 -DNO_MTRPC=1&lt;br /&gt;
 # or cmake .. -DEXP=BNQR -DONLY_64=1 -DNO_MTRPC=1&lt;br /&gt;
 make install&lt;br /&gt;
 &lt;br /&gt;
 # on isdaq06&lt;br /&gt;
 mkdir build_32&lt;br /&gt;
 cd build_32&lt;br /&gt;
 cmake .. -DEXP=BNMR -DNO_UNIT_TESTS=1 -DONLY_32=1&lt;br /&gt;
 # or cmake .. -DEXP=BNQR -DNO_UNIT_TESTS=1 -DONLY_32=1&lt;br /&gt;
 make install &lt;br /&gt;
&lt;br /&gt;
 #&lt;br /&gt;
 # For updates&lt;br /&gt;
 #&lt;br /&gt;
 # on isdaq01&lt;br /&gt;
 cd build&lt;br /&gt;
 make install&lt;br /&gt;
 &lt;br /&gt;
 # on isdaq06&lt;br /&gt;
 cd build_32&lt;br /&gt;
 make install&lt;br /&gt;
&lt;br /&gt;
This will:&lt;br /&gt;
* Cross-compile the frontend to run on the 32-bit VMIC machine (either febnmr or febnqr depending on the &amp;lt;code&amp;gt;-DEXP=...&amp;lt;/code&amp;gt; flag you passed to cmake)&lt;br /&gt;
* Compile the MUD logger&lt;br /&gt;
* Compile various debug executables&lt;br /&gt;
* Compile various automated tests&lt;br /&gt;
&lt;br /&gt;
To compile a dummy version of the software that does not talk to the real hardware or EPICS (and which can be run on a laptop):&lt;br /&gt;
&lt;br /&gt;
 mkdir build&lt;br /&gt;
 cd build&lt;br /&gt;
 cmake .. -DEXP=BNMR -DDUMMY_MODE=1&lt;br /&gt;
 # or cmake .. -DEXP=BNQR -DDUMMY_MODE=1&lt;br /&gt;
 make install&lt;br /&gt;
&lt;br /&gt;
== Updating midas ==&lt;br /&gt;
&lt;br /&gt;
 # Get updates&lt;br /&gt;
 cd $MIDASSYS&lt;br /&gt;
 git pull&lt;br /&gt;
 git submodule update --init --recursive&lt;br /&gt;
 &lt;br /&gt;
 # Compile 64-bit version&lt;br /&gt;
 mkdir -p $MIDASSYS/build&lt;br /&gt;
 cd $MIDASSYS/build&lt;br /&gt;
 make install&lt;br /&gt;
 &lt;br /&gt;
 # Cross-compile 32-bit version&lt;br /&gt;
 cd $MIDASSYS&lt;br /&gt;
 make linux32&lt;br /&gt;
 &lt;br /&gt;
 # Change status page from midas default to a symlink&lt;br /&gt;
 if ! [ -L $MIDASSYS/resources/status.html ]; then&lt;br /&gt;
   mv $MIDASSYS/resources/status.html $MIDASSYS/resources/status.html.orig&lt;br /&gt;
   if [ $USER == &amp;quot;bnmr&amp;quot; ]; then&lt;br /&gt;
     ln -s ~/packages/bnmr/bnxr_common/custom/status.html $MIDASSYS/resources/status.html&lt;br /&gt;
   else&lt;br /&gt;
     ln -s ~/packages/bnqr/bnxr_common/custom/status.html $MIDASSYS/resources/status.html&lt;br /&gt;
   fi&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
Then re-compile the bnmr/bnqr software&lt;br /&gt;
&lt;br /&gt;
== Interactions between programs ==&lt;br /&gt;
&lt;br /&gt;
* RPC between febnmr.exe/febnqr.exe and ppg_compiler_fe.py to generate PPG bytecode at begin-of-run&lt;br /&gt;
* RPC between rf_calculator_fe.py and ppg_compiler_fe.py to generate PPG bytecode when user clicks button on Settings webpage&lt;br /&gt;
* Midas buffers between febnmr.exe/febnqr.exe and bnxr_logger.exe for data&lt;br /&gt;
* Midas buffers between kalliope_fe.exe and bnxr_logger.exe for data&lt;br /&gt;
* RPC between febnmr.exe/febnqr.exe and kalliope_fe.exe to inform it of PPG cycle state&lt;br /&gt;
* run_comment_editor.py writes to a text file in the data directory, which is then read by bnxr_logger.exe when it&#039;s time to write a new MUD file. Text file is deleted at the end of the run.&lt;br /&gt;
&lt;br /&gt;
== Run transitions ==&lt;br /&gt;
&lt;br /&gt;
MIDAS allows clients to register to various transitions (e.g. START,STOP). However, many clients need to perform actions in a certain order. For example, in the {{bnmqr|join=and}} experiments, at begin-of-run, [[BNMR:_RF_calculator|the RF calculator]] is required to check the input parameters and compute various derived values (e.g. the list of I,Q pairs to load on the PSM). This must be completed before the frontend attempts to load these values. &lt;br /&gt;
&lt;br /&gt;
This is accomplished in MIDAS by the use of transition sequence numbers. The RF calculator and the frontend both register to the START transition, but the frontend is registered to only handle the transition after the RF calculator has finished doing the work it need to do.&lt;br /&gt;
&lt;br /&gt;
The full list of transition orderings (higher happens later) is:&lt;br /&gt;
* 1 - mode changer (ensure correct run number)&lt;br /&gt;
* 50 - RF calculator (compute PSM I,Q pairs, create human-readable PPG program to run, setup ODB links for MUD logging etc)&lt;br /&gt;
* 100 - frontend configuration (setup PSM, call PPG compiler to generate bytecode etc)&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:#999999&amp;quot;&amp;gt;100 - run comment editor (no-op)&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:#999999&amp;quot;&amp;gt;500 - PPG compiler (no-op for {{bnmqr|join=/}} as the frontend calls the PPG compiler by JRPC)&amp;lt;/span&amp;gt;&lt;br /&gt;
* 900 - MUD logger (connect to CAMP, open Midas buffers etc)&lt;br /&gt;
* 990 - frontend setup first cycle (configure first scan step and start PPG)&lt;br /&gt;
&lt;br /&gt;
If any of these transitions fail, the latter ones do not happen (and a &amp;quot;STARTABORT&amp;quot; transition signal is sent to all the clients). Having the frontend delay starting the PPG until the end of the sequence ensures that all the clients are ready for when the data starts to flow. Having the frontend configure the hardware early in the sequence prevents the MUD logger from doing unnecessary work if there is a hardware issue.&lt;br /&gt;
&lt;br /&gt;
[[Category:BNMR]]&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR:_Software_overview&amp;diff=7852</id>
		<title>BNMR: Software overview</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR:_Software_overview&amp;diff=7852"/>
		<updated>2024-07-26T21:42:52Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: /* Updating bnmr/bnqr software */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Pagelinks}}&lt;br /&gt;
&lt;br /&gt;
== Program list ==&lt;br /&gt;
&lt;br /&gt;
Programs with the _32bit suffix are designed to be run on the VMIC machine; all others are designed to be run on the host PC.&lt;br /&gt;
&lt;br /&gt;
=== Compiled &amp;quot;real&amp;quot; programs ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/febnmr_32bit.exe&amp;lt;/code&amp;gt; ({{bnmr}} only) - see [[BNMR:_frontend|frontend]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/febnqr_32bit.exe&amp;lt;/code&amp;gt; ({{bnqr}} only) - see [[BNMR:_frontend|frontend]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/bnxr_logger.exe&amp;lt;/code&amp;gt; - see [[BNMR: Data Logging|data logging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/logger_cleanup.exe&amp;lt;/code&amp;gt; - see [[BNMR: Data Logging#Cleaning_up_if_end-of-run_fails|data logging]]&lt;br /&gt;
&lt;br /&gt;
=== Python &amp;quot;real&amp;quot; programs ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/beamtime_monitor.py&amp;lt;/code&amp;gt; - see [[BNMR:_Shift_Monitor|shift monitor]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/beamtime_to_excel.py&amp;lt;/code&amp;gt; - see [[BNMR:_Shift_Monitor|shift monitor]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/elog_every_run.py&amp;lt;/code&amp;gt; - see [[BNMR:_Scripts#Run_transition_scripts|run transition scripts]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/mode_changer.py&amp;lt;/code&amp;gt; - see [[BNMR:_Mode_changer|mode changer]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/rf_calculator_fe.py&amp;lt;/code&amp;gt; - see [[BNMR:_RF_calculator|RF calculator]]&lt;br /&gt;
* &amp;lt;code&amp;gt;cycling_framework/ppg/ppg_compiler_fe.py&amp;lt;/code&amp;gt; - see [[BNMR:_PPG_compiler|PPG compiler]]&lt;br /&gt;
* &amp;lt;code&amp;gt;cycling_framework/run_comments/run_comment_editor.py&amp;lt;/code&amp;gt; - see [[BNMR:_Data_Logging#Run_comments|data logging]]&lt;br /&gt;
&lt;br /&gt;
=== Compiled programs for debugging hardware etc ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/bnmrbeamsim_32bit.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/camp_test.exe&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bin/camp_test_32bit.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/epics_test.exe&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bin/epics_test_32bit.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/vppg_interactive_32bit.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/sis3801_interactive_32bit.exe&amp;lt;/code&amp;gt; ({{bnmr}} only) - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/sis3820_interactive_32bit.exe&amp;lt;/code&amp;gt; ({{bnqr}} only) - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/psm_interactive_32bit.exe&amp;lt;/code&amp;gt;  ({{bnqr}} only) - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/psm3_interactive_32bit.exe&amp;lt;/code&amp;gt;  ({{bnmr}} only) - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
&lt;br /&gt;
=== Compiled automated tests ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/unit_tests/*.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Tests#Automated_tests_that_don.27t_use_the_ODB|Automated tests that don&#039;t use the ODB]]&lt;br /&gt;
&lt;br /&gt;
=== Python test programs ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/test_mud_logger.py&amp;lt;/code&amp;gt; - see [[BNMR:_Tests#Automated_tests_that_do_use_the_ODB|automated tests that use the ODB]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/test_ppg_calc.py&amp;lt;/code&amp;gt; - see [[BNMR:_Tests#Automated_tests_that_do_use_the_ODB|automated tests that use the ODB]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/test_psm_calc.py&amp;lt;/code&amp;gt; - see [[BNMR:_Tests#Automated_tests_that_do_use_the_ODB|automated tests that use the ODB]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/diff_mud_file.py&amp;lt;/code&amp;gt; - see [[BNMR:_Data_Logging#MUD_files|data logging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/dump_mud_file.py&amp;lt;/code&amp;gt; - see [[BNMR:_Data_Logging#MUD_files|data logging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;cycling_framework/ppg/tests/test_ppg.py&amp;lt;/code&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
=== Unused compiled programs ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/epics_log.exe&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bin/epics_log_32bit.exe&amp;lt;/code&amp;gt; - EPICS logging is handled by the MUD logger in {{bnmqr|join=/}}&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/tppg_interactive_32bit.exe&amp;lt;/code&amp;gt; - this version is for TRIUMF PPGs; we use PulseBlaster PPGs&lt;br /&gt;
&lt;br /&gt;
== Repository location ==&lt;br /&gt;
&lt;br /&gt;
The main repository is on BitBucket at [https://bitbucket.org/ttriumfdaq/bnmr/ https://bitbucket.org/ttriumfdaq/bnmr/].&lt;br /&gt;
&lt;br /&gt;
== Updating bnmr/bnqr software ==&lt;br /&gt;
&lt;br /&gt;
The main repository uses submodules for some dependencies, so checking out updates requires:&lt;br /&gt;
&lt;br /&gt;
 git pull&lt;br /&gt;
 git submodule update&lt;br /&gt;
&lt;br /&gt;
To compile the real software, we currently have to compile separately on isdaq01 and lxbnmr/lxbnqr (as the lx machines have had their OS upgraded, but isdaq01 has not, and the two are mutually incompatible for cross-compilation). Once isdaq01 has been upgraded, we will be able to run all compilation from there again and compile times will be significantly faster.&lt;br /&gt;
&lt;br /&gt;
 #&lt;br /&gt;
 # For the first install&lt;br /&gt;
 #&lt;br /&gt;
 # on isdaq01&lt;br /&gt;
 mkdir build&lt;br /&gt;
 cd build&lt;br /&gt;
 cmake .. -DEXP=BNMR -DONLY_64=1 -DNO_MTRPC=1&lt;br /&gt;
 # or cmake .. -DEXP=BNQR -DONLY_64=1 -DNO_MTRPC=1&lt;br /&gt;
 make install&lt;br /&gt;
 &lt;br /&gt;
 # on lxbnmr (or lxbnqr)&lt;br /&gt;
 mkdir build_32&lt;br /&gt;
 cd build_32&lt;br /&gt;
 cmake .. -DEXP=BNMR -DNO_UNIT_TESTS=1 -DONLY_32=1 -DNO_MTRPC=1&lt;br /&gt;
 # or cmake .. -DEXP=BNQR -DNO_UNIT_TESTS=1 -DONLY_32=1 -DNO_MTRPC=1&lt;br /&gt;
 make install &lt;br /&gt;
&lt;br /&gt;
 #&lt;br /&gt;
 # For updates&lt;br /&gt;
 #&lt;br /&gt;
 # on isdaq01&lt;br /&gt;
 cd build&lt;br /&gt;
 make install&lt;br /&gt;
 &lt;br /&gt;
 # on lxbnmr (or lxbnqr)&lt;br /&gt;
 cd build_32&lt;br /&gt;
 make install&lt;br /&gt;
&lt;br /&gt;
This will:&lt;br /&gt;
* Compile the frontend to run on the 32-bit VMIC machine (either febnmr or febnqr depending on the &amp;lt;code&amp;gt;-DEXP=...&amp;lt;/code&amp;gt; flag you passed to cmake)&lt;br /&gt;
* Compile the MUD logger&lt;br /&gt;
* Compile various debug executables&lt;br /&gt;
* Compile various automated tests&lt;br /&gt;
&lt;br /&gt;
To compile a dummy version of the software that does not talk to the real hardware or EPICS (and which can be run on a laptop):&lt;br /&gt;
&lt;br /&gt;
 mkdir build&lt;br /&gt;
 cd build&lt;br /&gt;
 cmake .. -DEXP=BNMR -DDUMMY_MODE=1&lt;br /&gt;
 # or cmake .. -DEXP=BNQR -DDUMMY_MODE=1&lt;br /&gt;
 make install&lt;br /&gt;
&lt;br /&gt;
== Updating midas ==&lt;br /&gt;
&lt;br /&gt;
 # Get updates&lt;br /&gt;
 cd $MIDASSYS&lt;br /&gt;
 git pull&lt;br /&gt;
 git submodule update --init --recursive&lt;br /&gt;
 &lt;br /&gt;
 # Compile 64-bit version&lt;br /&gt;
 mkdir -p $MIDASSYS/build&lt;br /&gt;
 cd $MIDASSYS/build&lt;br /&gt;
 make install&lt;br /&gt;
 &lt;br /&gt;
 # Cross-compile 32-bit version&lt;br /&gt;
 cd $MIDASSYS&lt;br /&gt;
 make linux32&lt;br /&gt;
 &lt;br /&gt;
 # Change status page from midas default to a symlink&lt;br /&gt;
 if ! [ -L $MIDASSYS/resources/status.html ]; then&lt;br /&gt;
   mv $MIDASSYS/resources/status.html $MIDASSYS/resources/status.html.orig&lt;br /&gt;
   if [ $USER == &amp;quot;bnmr&amp;quot; ]; then&lt;br /&gt;
     ln -s ~/packages/bnmr/bnxr_common/custom/status.html $MIDASSYS/resources/status.html&lt;br /&gt;
   else&lt;br /&gt;
     ln -s ~/packages/bnqr/bnxr_common/custom/status.html $MIDASSYS/resources/status.html&lt;br /&gt;
   fi&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
Then re-compile the bnmr/bnqr software&lt;br /&gt;
&lt;br /&gt;
== Interactions between programs ==&lt;br /&gt;
&lt;br /&gt;
* RPC between febnmr.exe/febnqr.exe and ppg_compiler_fe.py to generate PPG bytecode at begin-of-run&lt;br /&gt;
* RPC between rf_calculator_fe.py and ppg_compiler_fe.py to generate PPG bytecode when user clicks button on Settings webpage&lt;br /&gt;
* Midas buffers between febnmr.exe/febnqr.exe and bnxr_logger.exe for data&lt;br /&gt;
* Midas buffers between kalliope_fe.exe and bnxr_logger.exe for data&lt;br /&gt;
* RPC between febnmr.exe/febnqr.exe and kalliope_fe.exe to inform it of PPG cycle state&lt;br /&gt;
* run_comment_editor.py writes to a text file in the data directory, which is then read by bnxr_logger.exe when it&#039;s time to write a new MUD file. Text file is deleted at the end of the run.&lt;br /&gt;
&lt;br /&gt;
== Run transitions ==&lt;br /&gt;
&lt;br /&gt;
MIDAS allows clients to register to various transitions (e.g. START,STOP). However, many clients need to perform actions in a certain order. For example, in the {{bnmqr|join=and}} experiments, at begin-of-run, [[BNMR:_RF_calculator|the RF calculator]] is required to check the input parameters and compute various derived values (e.g. the list of I,Q pairs to load on the PSM). This must be completed before the frontend attempts to load these values. &lt;br /&gt;
&lt;br /&gt;
This is accomplished in MIDAS by the use of transition sequence numbers. The RF calculator and the frontend both register to the START transition, but the frontend is registered to only handle the transition after the RF calculator has finished doing the work it need to do.&lt;br /&gt;
&lt;br /&gt;
The full list of transition orderings (higher happens later) is:&lt;br /&gt;
* 1 - mode changer (ensure correct run number)&lt;br /&gt;
* 50 - RF calculator (compute PSM I,Q pairs, create human-readable PPG program to run, setup ODB links for MUD logging etc)&lt;br /&gt;
* 100 - frontend configuration (setup PSM, call PPG compiler to generate bytecode etc)&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:#999999&amp;quot;&amp;gt;100 - run comment editor (no-op)&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:#999999&amp;quot;&amp;gt;500 - PPG compiler (no-op for {{bnmqr|join=/}} as the frontend calls the PPG compiler by JRPC)&amp;lt;/span&amp;gt;&lt;br /&gt;
* 900 - MUD logger (connect to CAMP, open Midas buffers etc)&lt;br /&gt;
* 990 - frontend setup first cycle (configure first scan step and start PPG)&lt;br /&gt;
&lt;br /&gt;
If any of these transitions fail, the latter ones do not happen (and a &amp;quot;STARTABORT&amp;quot; transition signal is sent to all the clients). Having the frontend delay starting the PPG until the end of the sequence ensures that all the clients are ready for when the data starts to flow. Having the frontend configure the hardware early in the sequence prevents the MUD logger from doing unnecessary work if there is a hardware issue.&lt;br /&gt;
&lt;br /&gt;
[[Category:BNMR]]&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR:_Software_overview&amp;diff=7851</id>
		<title>BNMR: Software overview</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=BNMR:_Software_overview&amp;diff=7851"/>
		<updated>2024-07-26T21:42:18Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: /* Updating bnmr/bnqr software */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Pagelinks}}&lt;br /&gt;
&lt;br /&gt;
== Program list ==&lt;br /&gt;
&lt;br /&gt;
Programs with the _32bit suffix are designed to be run on the VMIC machine; all others are designed to be run on the host PC.&lt;br /&gt;
&lt;br /&gt;
=== Compiled &amp;quot;real&amp;quot; programs ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/febnmr_32bit.exe&amp;lt;/code&amp;gt; ({{bnmr}} only) - see [[BNMR:_frontend|frontend]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/febnqr_32bit.exe&amp;lt;/code&amp;gt; ({{bnqr}} only) - see [[BNMR:_frontend|frontend]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/bnxr_logger.exe&amp;lt;/code&amp;gt; - see [[BNMR: Data Logging|data logging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/logger_cleanup.exe&amp;lt;/code&amp;gt; - see [[BNMR: Data Logging#Cleaning_up_if_end-of-run_fails|data logging]]&lt;br /&gt;
&lt;br /&gt;
=== Python &amp;quot;real&amp;quot; programs ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/beamtime_monitor.py&amp;lt;/code&amp;gt; - see [[BNMR:_Shift_Monitor|shift monitor]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/beamtime_to_excel.py&amp;lt;/code&amp;gt; - see [[BNMR:_Shift_Monitor|shift monitor]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/elog_every_run.py&amp;lt;/code&amp;gt; - see [[BNMR:_Scripts#Run_transition_scripts|run transition scripts]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/mode_changer.py&amp;lt;/code&amp;gt; - see [[BNMR:_Mode_changer|mode changer]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/rf_calculator_fe.py&amp;lt;/code&amp;gt; - see [[BNMR:_RF_calculator|RF calculator]]&lt;br /&gt;
* &amp;lt;code&amp;gt;cycling_framework/ppg/ppg_compiler_fe.py&amp;lt;/code&amp;gt; - see [[BNMR:_PPG_compiler|PPG compiler]]&lt;br /&gt;
* &amp;lt;code&amp;gt;cycling_framework/run_comments/run_comment_editor.py&amp;lt;/code&amp;gt; - see [[BNMR:_Data_Logging#Run_comments|data logging]]&lt;br /&gt;
&lt;br /&gt;
=== Compiled programs for debugging hardware etc ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/bnmrbeamsim_32bit.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/camp_test.exe&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bin/camp_test_32bit.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/epics_test.exe&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bin/epics_test_32bit.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/vppg_interactive_32bit.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/sis3801_interactive_32bit.exe&amp;lt;/code&amp;gt; ({{bnmr}} only) - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/sis3820_interactive_32bit.exe&amp;lt;/code&amp;gt; ({{bnqr}} only) - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/psm_interactive_32bit.exe&amp;lt;/code&amp;gt;  ({{bnqr}} only) - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/psm3_interactive_32bit.exe&amp;lt;/code&amp;gt;  ({{bnmr}} only) - see [[BNMR:_Hardware_Debugging|hardware debugging]]&lt;br /&gt;
&lt;br /&gt;
=== Compiled automated tests ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/unit_tests/*.exe&amp;lt;/code&amp;gt; - see [[BNMR:_Tests#Automated_tests_that_don.27t_use_the_ODB|Automated tests that don&#039;t use the ODB]]&lt;br /&gt;
&lt;br /&gt;
=== Python test programs ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/test_mud_logger.py&amp;lt;/code&amp;gt; - see [[BNMR:_Tests#Automated_tests_that_do_use_the_ODB|automated tests that use the ODB]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/test_ppg_calc.py&amp;lt;/code&amp;gt; - see [[BNMR:_Tests#Automated_tests_that_do_use_the_ODB|automated tests that use the ODB]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/test_psm_calc.py&amp;lt;/code&amp;gt; - see [[BNMR:_Tests#Automated_tests_that_do_use_the_ODB|automated tests that use the ODB]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/diff_mud_file.py&amp;lt;/code&amp;gt; - see [[BNMR:_Data_Logging#MUD_files|data logging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;bnxr_common/tests/dump_mud_file.py&amp;lt;/code&amp;gt; - see [[BNMR:_Data_Logging#MUD_files|data logging]]&lt;br /&gt;
* &amp;lt;code&amp;gt;cycling_framework/ppg/tests/test_ppg.py&amp;lt;/code&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
=== Unused compiled programs ===&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/epics_log.exe&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;bin/epics_log_32bit.exe&amp;lt;/code&amp;gt; - EPICS logging is handled by the MUD logger in {{bnmqr|join=/}}&lt;br /&gt;
* &amp;lt;code&amp;gt;bin/tppg_interactive_32bit.exe&amp;lt;/code&amp;gt; - this version is for TRIUMF PPGs; we use PulseBlaster PPGs&lt;br /&gt;
&lt;br /&gt;
== Repository location ==&lt;br /&gt;
&lt;br /&gt;
The main repository is on BitBucket at [https://bitbucket.org/ttriumfdaq/bnmr/ https://bitbucket.org/ttriumfdaq/bnmr/].&lt;br /&gt;
&lt;br /&gt;
== Updating bnmr/bnqr software ==&lt;br /&gt;
&lt;br /&gt;
The main repository uses submodules for some dependencies, so checking out updates requires:&lt;br /&gt;
&lt;br /&gt;
 git pull&lt;br /&gt;
 git submodule update&lt;br /&gt;
&lt;br /&gt;
To compile the real software, we currently have to compile separately on isdaq01 and lxbnmr/lxbnqr (as the lx machines have had their OS upgraded, but isdaq01 has not, and the two are mutually incompatible for cross-compilation). Once isdaq01 has been upgraded, we will be able to run all compilation from there again and compile times will be significantly faster.&lt;br /&gt;
&lt;br /&gt;
 #&lt;br /&gt;
 # For the first install&lt;br /&gt;
 #&lt;br /&gt;
 # on isdaq01&lt;br /&gt;
 mkdir build&lt;br /&gt;
 cd build&lt;br /&gt;
 cmake .. -DEXP=BNMR -DONLY_64=1 -DNO_MTRPC=1&lt;br /&gt;
 # or cmake .. -DEXP=BNQR -DONLY_64=1 -DNO_MTRPC=1&lt;br /&gt;
 make install&lt;br /&gt;
&lt;br /&gt;
 # on lxbnmr (or lxbnqr)&lt;br /&gt;
 mkdir build_32&lt;br /&gt;
 cd build_32&lt;br /&gt;
 cmake .. -DEXP=BNMR -DNO_UNIT_TESTS=1 -DONLY_32=1 -DNO_MTRPC=1&lt;br /&gt;
 # or cmake .. -DEXP=BNQR -DNO_UNIT_TESTS=1 -DONLY_32=1 -DNO_MTRPC=1&lt;br /&gt;
 make install &lt;br /&gt;
 &lt;br /&gt;
 #&lt;br /&gt;
 # For updates&lt;br /&gt;
 #&lt;br /&gt;
 # on isdaq01&lt;br /&gt;
 cd build&lt;br /&gt;
 make install&lt;br /&gt;
&lt;br /&gt;
 # on lxbnmr (or lxbnqr)&lt;br /&gt;
 cd build_32&lt;br /&gt;
 make install&lt;br /&gt;
&lt;br /&gt;
This will:&lt;br /&gt;
* Cross-compile the frontend to run on the 32-bit VMIC machine (either febnmr or febnqr depending on the &amp;lt;code&amp;gt;-DEXP=...&amp;lt;/code&amp;gt; flag you passed to cmake)&lt;br /&gt;
* Compile the MUD logger&lt;br /&gt;
* Compile and/or cross-compile various debug executables&lt;br /&gt;
* Compile and/or cross-compile various automated tests&lt;br /&gt;
&lt;br /&gt;
To compile a dummy version of the software that does not talk to the real hardware or EPICS (and which can be run on a laptop):&lt;br /&gt;
&lt;br /&gt;
 mkdir build&lt;br /&gt;
 cd build&lt;br /&gt;
 cmake .. -DEXP=BNMR -DDUMMY_MODE=1&lt;br /&gt;
 # or cmake .. -DEXP=BNQR -DDUMMY_MODE=1&lt;br /&gt;
 make install&lt;br /&gt;
&lt;br /&gt;
== Updating midas ==&lt;br /&gt;
&lt;br /&gt;
 # Get updates&lt;br /&gt;
 cd $MIDASSYS&lt;br /&gt;
 git pull&lt;br /&gt;
 git submodule update --init --recursive&lt;br /&gt;
 &lt;br /&gt;
 # Compile 64-bit version&lt;br /&gt;
 mkdir -p $MIDASSYS/build&lt;br /&gt;
 cd $MIDASSYS/build&lt;br /&gt;
 make install&lt;br /&gt;
 &lt;br /&gt;
 # Cross-compile 32-bit version&lt;br /&gt;
 cd $MIDASSYS&lt;br /&gt;
 make linux32&lt;br /&gt;
 &lt;br /&gt;
 # Change status page from midas default to a symlink&lt;br /&gt;
 if ! [ -L $MIDASSYS/resources/status.html ]; then&lt;br /&gt;
   mv $MIDASSYS/resources/status.html $MIDASSYS/resources/status.html.orig&lt;br /&gt;
   if [ $USER == &amp;quot;bnmr&amp;quot; ]; then&lt;br /&gt;
     ln -s ~/packages/bnmr/bnxr_common/custom/status.html $MIDASSYS/resources/status.html&lt;br /&gt;
   else&lt;br /&gt;
     ln -s ~/packages/bnqr/bnxr_common/custom/status.html $MIDASSYS/resources/status.html&lt;br /&gt;
   fi&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
Then re-compile the bnmr/bnqr software&lt;br /&gt;
&lt;br /&gt;
== Interactions between programs ==&lt;br /&gt;
&lt;br /&gt;
* RPC between febnmr.exe/febnqr.exe and ppg_compiler_fe.py to generate PPG bytecode at begin-of-run&lt;br /&gt;
* RPC between rf_calculator_fe.py and ppg_compiler_fe.py to generate PPG bytecode when user clicks button on Settings webpage&lt;br /&gt;
* Midas buffers between febnmr.exe/febnqr.exe and bnxr_logger.exe for data&lt;br /&gt;
* Midas buffers between kalliope_fe.exe and bnxr_logger.exe for data&lt;br /&gt;
* RPC between febnmr.exe/febnqr.exe and kalliope_fe.exe to inform it of PPG cycle state&lt;br /&gt;
* run_comment_editor.py writes to a text file in the data directory, which is then read by bnxr_logger.exe when it&#039;s time to write a new MUD file. Text file is deleted at the end of the run.&lt;br /&gt;
&lt;br /&gt;
== Run transitions ==&lt;br /&gt;
&lt;br /&gt;
MIDAS allows clients to register to various transitions (e.g. START,STOP). However, many clients need to perform actions in a certain order. For example, in the {{bnmqr|join=and}} experiments, at begin-of-run, [[BNMR:_RF_calculator|the RF calculator]] is required to check the input parameters and compute various derived values (e.g. the list of I,Q pairs to load on the PSM). This must be completed before the frontend attempts to load these values. &lt;br /&gt;
&lt;br /&gt;
This is accomplished in MIDAS by the use of transition sequence numbers. The RF calculator and the frontend both register to the START transition, but the frontend is registered to only handle the transition after the RF calculator has finished doing the work it need to do.&lt;br /&gt;
&lt;br /&gt;
The full list of transition orderings (higher happens later) is:&lt;br /&gt;
* 1 - mode changer (ensure correct run number)&lt;br /&gt;
* 50 - RF calculator (compute PSM I,Q pairs, create human-readable PPG program to run, setup ODB links for MUD logging etc)&lt;br /&gt;
* 100 - frontend configuration (setup PSM, call PPG compiler to generate bytecode etc)&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:#999999&amp;quot;&amp;gt;100 - run comment editor (no-op)&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:#999999&amp;quot;&amp;gt;500 - PPG compiler (no-op for {{bnmqr|join=/}} as the frontend calls the PPG compiler by JRPC)&amp;lt;/span&amp;gt;&lt;br /&gt;
* 900 - MUD logger (connect to CAMP, open Midas buffers etc)&lt;br /&gt;
* 990 - frontend setup first cycle (configure first scan step and start PPG)&lt;br /&gt;
&lt;br /&gt;
If any of these transitions fail, the latter ones do not happen (and a &amp;quot;STARTABORT&amp;quot; transition signal is sent to all the clients). Having the frontend delay starting the PPG until the end of the sequence ensures that all the clients are ready for when the data starts to flow. Having the frontend configure the hardware early in the sequence prevents the MUD logger from doing unnecessary work if there is a hardware issue.&lt;br /&gt;
&lt;br /&gt;
[[Category:BNMR]]&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=MPET_DAQ&amp;diff=7796</id>
		<title>MPET DAQ</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=MPET_DAQ&amp;diff=7796"/>
		<updated>2024-06-05T22:48:39Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: /* Starting and stopping DAQ programs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Links =&lt;br /&gt;
&amp;lt;div style=&amp;quot;column-count:3;-moz-column-count:3;-webkit-column-count:3&amp;quot;&amp;gt;&lt;br /&gt;
* [[TITAN]] TITAN Page&lt;br /&gt;
* [[TITAN DAQ General Documentation]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
MPET has:&lt;br /&gt;
&lt;br /&gt;
* A PPG for programming pulses&lt;br /&gt;
* A 2-channel Tektronix AFG for generating RF (was previously two Agilent AFGs)&lt;br /&gt;
* An 8-channel GSC 16ao16 to control the trap voltages (was previously an Alphi Softdac). There is a breakout box to convert to BNC connections. The breakout box has many connectors, but only 8 channels are actually controllable!&lt;br /&gt;
* An older VT2 TDC for recording timestamps&lt;br /&gt;
* A position analyzer to determine X/Y positions of ions&lt;br /&gt;
* A Lecroy LRS1190 memory buffer that records the X/Y position&lt;br /&gt;
* A newer CAEN V1290 25ps TDC for recording timestamps&lt;br /&gt;
&lt;br /&gt;
Note that the VT2/V1290 TDCs are enabled in different ways:&lt;br /&gt;
* The VT2 has a &amp;quot;gate&amp;quot; that is set to 1 for the entire period that timestamps should be recorded&lt;br /&gt;
* The V1290 has a &amp;quot;trigger&amp;quot; that is issued at the end of the desired period; the times of any hits within the &amp;quot;trigger window&amp;quot; (normally 50us) before the trigger are recorded&lt;br /&gt;
&lt;br /&gt;
The wiring diagram for the MPET DAQ is:&lt;br /&gt;
&lt;br /&gt;
[[Image:MPET wiring.png]]&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
&lt;br /&gt;
The DAQ system is based on the [https://midas.triumf.ca/MidasWiki/index.php/Midas_documentation MIDAS DAQ package]. Software written for MPET is linked with the MIDAS libraries and uses common framework for MPET/CPET/EBIT. &lt;br /&gt;
&lt;br /&gt;
The MPET software can be found at &#039;&#039;/home/mpet/packages/mpet&#039;&#039; on &#039;&#039;&#039;titan06&#039;&#039;&#039; (note that historical versions of the software were located in &#039;&#039;/home/mpet/online&#039;&#039;).  &lt;br /&gt;
&lt;br /&gt;
Run control is done using the MIDAS webserver [https://midas.triumf.ca/MidasWiki/index.php/Mhttpd mhttpd] with [https://midas.triumf.ca/MidasWiki/index.php/Custom_Page Custom Pages] written for &#039;&#039;mpet&#039;&#039; users so that they can easily enter the parameters required to program the PPG and to run the DAQ.&lt;br /&gt;
&lt;br /&gt;
The default login shell for the mpet user is now bash. If you want to use the legacy DAQ (which only supports the VT2/VT4 and Softdac, not the CAEN V1290 and GSC 16ao16), then change to the tcsh shell by typing &#039;tcsh&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Program listing ===&lt;br /&gt;
&lt;br /&gt;
In the order that programs appear on the [http://titan06.triumf.ca:8088/?cmd=Programs Programs page]:&lt;br /&gt;
* mserver - midas RPC server that allows the programs on lxebit to talk to the main experiment on titan06&lt;br /&gt;
* fempet - main MPET frontend that talks to the PPG, scans EPICS values etc. Runs on lxmpet.&lt;br /&gt;
* mhttpd - midas web server&lt;br /&gt;
* PPGCompilerFrontend - converts a user-supplied PPG program into bytecode that can be loaded onto the PPG&lt;br /&gt;
* saveload - helps save and load scan settings&lt;br /&gt;
* AfgFrontend - frontend that configures the Agilent Quad/Dipole AFGs at the start of each run (written in python)&lt;br /&gt;
* AfgTekFrontend - frontend that configures the Tektronix AFG at the start of each run (written in python)&lt;br /&gt;
* Logger - midas data logger&lt;br /&gt;
* mpetana - python analyzer that creates plots based on live data (plots are viewed via the [http://titan06.triumf.ca:8088/?cmd=custom&amp;amp;page=Web%20plots Web plots] page)&lt;br /&gt;
&lt;br /&gt;
=== Starting and stopping DAQ programs ===&lt;br /&gt;
If the MPET webpage is unavailable, log in to mpet@titan06.triumf.ca, and type&lt;br /&gt;
&lt;br /&gt;
  mhttpd -D&lt;br /&gt;
&lt;br /&gt;
Then you can use the [http://titan06.triumf.ca:8080/?cmd=Programs Midas programs page] to start/stop the remaining DAQ programs.&lt;br /&gt;
&lt;br /&gt;
At the very least, the following programs &#039;&#039;&#039;should be running&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
* mserver (start this before fempet!)&lt;br /&gt;
* fempet&lt;br /&gt;
* mhttpd&lt;br /&gt;
* PPGCompilerFrontend&lt;br /&gt;
* saveload&lt;br /&gt;
* AfgFrontend OR AfgTekFrontend (depending on which device you&#039;re using)&lt;br /&gt;
* Logger&lt;br /&gt;
* mpetana&lt;br /&gt;
&lt;br /&gt;
The following programs &#039;&#039;&#039;may be started&#039;&#039;&#039; if they are useful for your analysis:&lt;br /&gt;
&lt;br /&gt;
* Sequencer&lt;br /&gt;
* midas_to_df_scan_live&lt;br /&gt;
* mpetana_df&lt;br /&gt;
&lt;br /&gt;
The following programs are &#039;&#039;&#039;not required&#039;&#039;&#039; during normal operation:&lt;br /&gt;
&lt;br /&gt;
* feCrossTest&lt;br /&gt;
&lt;br /&gt;
=== Pulling the latest version of the MPET DAQ software ===&lt;br /&gt;
  cd ~/packages/mpet&lt;br /&gt;
  git pull&lt;br /&gt;
  git submodule update&lt;br /&gt;
&lt;br /&gt;
=== Building the MPET DAQ software ===&lt;br /&gt;
 cd ~/packages/mpet/build&lt;br /&gt;
 cmake ..&lt;br /&gt;
 make install&lt;br /&gt;
&lt;br /&gt;
This will build the appropriate 32-bit frontend program that can be used by lxmpet.&lt;br /&gt;
&lt;br /&gt;
=== 16ao16 driver and software ===&lt;br /&gt;
&lt;br /&gt;
The [http://www.generalstandards.com/view-products2.php?BD_family=16ao16 16ao16] is used to control the trap voltages. It is mounted on lxmpet as a PMC board, and requires a kernel module and software. GSC seem very good at supporting this and continue releasing updates for newer linux versions.&lt;br /&gt;
&lt;br /&gt;
There is one tweak we need to make for the build to work vs what is documented in the manual. &lt;br /&gt;
&lt;br /&gt;
 1. Download the latest 16ao16.linux.******.tar.gz bundle from http://www.generalstandards.com/downloads/ and copy it to ~/packages. Extract it using tar. It should create the directory ~/packages/16ao16.&lt;br /&gt;
 &lt;br /&gt;
 2. Run `uname -r` to find your current kernel version.&lt;br /&gt;
 &lt;br /&gt;
 3. Check if a file exists called /usr/src/linux-headers-&amp;lt;kernel_version&amp;gt;-common/scripts/file-size.sh. &lt;br /&gt;
    If not, create it and fill it with this content:&lt;br /&gt;
    #!/bin/sh  &lt;br /&gt;
    #SPDX-License-Identifier: GPL-2.0  &lt;br /&gt;
    set -- $(ls -dn &amp;quot;$1&amp;quot;)  &lt;br /&gt;
    printf &#039;%s\n&#039; &amp;quot;$5&amp;quot;&lt;br /&gt;
   &lt;br /&gt;
 4. Build the software:&lt;br /&gt;
    cd ~/packages/16ao16&lt;br /&gt;
    ./make_all&lt;br /&gt;
 &lt;br /&gt;
 5. Do the final installation of library and driver as root:&lt;br /&gt;
    su - root&lt;br /&gt;
    cd ~/packages/16ao16&lt;br /&gt;
    ./make_all&lt;br /&gt;
 &lt;br /&gt;
 6. Verify that the driver has been loaded, by seeing if /proc/16ao16 exists.&lt;br /&gt;
 &lt;br /&gt;
 7. Configure things so the driver loads each time lxmpet boots, by adding the following line to /etc/rc.local:&lt;br /&gt;
    /home/mpet/packages/16ao16/driver/start&lt;br /&gt;
&lt;br /&gt;
The make_all script builds both the driver and the software libraries. The mpet software builds and links against the GSC library. By default it looks for the headers/libraries in /home/mpet/packages/16ao16, but if you&#039;ve built it elsewhere you can specify an alternate directory using the &amp;lt;code&amp;gt;-DGSC_16AO16_DIR=/path/to/somewhere&amp;lt;/code&amp;gt; argument when running cmake.&lt;br /&gt;
&lt;br /&gt;
== Agilent vs Tektronix AFGs ==&lt;br /&gt;
&lt;br /&gt;
In summer 2022, MPET bought a Tektronix 35052 2-channel AFG to replace two Agilent AFGs (both types of AFG are used to generate RF signals).&lt;br /&gt;
&lt;br /&gt;
The Agilent AFGs could be programmed with a list of frequencies, with the next frequency being loaded when a PPG signal was issued. This allowed the frequencies to be scanned within a single PPG loop. The Tektronix AFG does have a sequencing option (if you pay extra money), but has severe limitations that do not allow it to be used the way we need (especially if wanting to run both channels simultaneously).&lt;br /&gt;
&lt;br /&gt;
Therefore, when using the Tektronix AFG, the frequency must be scanned outside of the PPG loop (same as if you were scanning an EPICS PV or trap voltage).&lt;br /&gt;
&lt;br /&gt;
=== AfgFrontend vs AfgTekFrontend ===&lt;br /&gt;
&lt;br /&gt;
There are two separate programs that may be run:&lt;br /&gt;
* AfgFrontend is the program that controls the Agilent AFGs&lt;br /&gt;
* AfgTekFrontend is the program that controls the Tektronix AFG&lt;br /&gt;
&lt;br /&gt;
The code has some sanity-checks to make it easier for you to determine which AFG was being used when looking at the midas files:&lt;br /&gt;
* The run will not start if both the Agilent and Tektronix frontends are running&lt;br /&gt;
* The run will not start if an Agilent AFG is set as &amp;quot;enabled&amp;quot; in the ODB, but the Tektronix frontend is running (or vice-versa)&lt;br /&gt;
&lt;br /&gt;
=== Changing between the AFGs ===&lt;br /&gt;
&lt;br /&gt;
To change from using the Agilent to Agilent AFG:&lt;br /&gt;
* Stop the AfgFrontend program on the Programs page&lt;br /&gt;
* Start the AfgTekFrontend program on the Programs page&lt;br /&gt;
* Go to the &amp;quot;RF (Tek)&amp;quot; page and configure the frequencies&lt;br /&gt;
&lt;br /&gt;
To change from using the Tektronix to Agilent AFG:&lt;br /&gt;
* Stop the AfgTekFrontend program on the Programs page&lt;br /&gt;
* Start the AfgFrontend program on the Programs page&lt;br /&gt;
* Go to the &amp;quot;RF (Agilent)&amp;quot; page and configure the frequencies&lt;br /&gt;
&lt;br /&gt;
For the Agilent AFG, the number of frequencies is determined by the number of loops of the &amp;quot;begin_ramp&amp;quot; loop of the PPG program.&lt;br /&gt;
&lt;br /&gt;
For the Tektronix AFG, the number of frequencies is determined by the number of X/Y/Z scan steps. &amp;lt;b&amp;gt;You may still have &amp;gt; 1 loops in the &amp;quot;begin_ramp&amp;quot; loop of the PPG program, but they will all be taken with the same frequency&amp;lt;/b&amp;gt; (take care of this when doing analysis!). Having &amp;gt; 1 loops is the lowest-latency (most efficient) way of increasing your statistics as the DAQ won&#039;t do anything until all the loops have completed; only then will there be some deadtime as the DAQ moves to the next scan point.&lt;br /&gt;
&lt;br /&gt;
=== X/Y/Z scan ordering ===&lt;br /&gt;
&lt;br /&gt;
For a 2D scan, all the Y points are covered at a given X point before moving to the next X point.&lt;br /&gt;
&lt;br /&gt;
For a 3D scan, all the Z points are covered at a given X+Y point before moving to the next Y point. After all the Y points have been covered we move to the next X point.&lt;br /&gt;
&lt;br /&gt;
So for a 3D scan, the Z variable is changed a lot more often than the X variable. For maximum efficiency, it is recommended that you use the Z variable for the parameter that is quickest to react to the change (e.g. EPICS voltages can be slow to react, so changing EPICS in the X variable and the frequency in the Z variable is likely to be most efficient).&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=MUSR_Cluster&amp;diff=7786</id>
		<title>MUSR Cluster</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=MUSR_Cluster&amp;diff=7786"/>
		<updated>2024-05-24T17:24:02Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Links ==&lt;br /&gt;
&lt;br /&gt;
* http://musr00.triumf.ca/triumf_nodeinfo/config.html (node info)&lt;br /&gt;
* http://musr00.triumf.ca/quotareport/quota.html (musr00 disk quota report)&lt;br /&gt;
* http://ladd00.triumf.ca/ganglia/ (ganglia on ladd00)&lt;br /&gt;
&lt;br /&gt;
== DAQ machines ==&lt;br /&gt;
&lt;br /&gt;
* musr00: main server (NIS, home directories, central services, etc - see below)&lt;br /&gt;
* musr01: M15 user analysis&lt;br /&gt;
* musr02: M20 user analysis&lt;br /&gt;
* midm20: old M20 DAQ&lt;br /&gt;
* midm9a: inactive M9A DAQ, used for daq development&lt;br /&gt;
* midm15: M15 DAQ&lt;br /&gt;
* midm20c: M20C DAQ&lt;br /&gt;
* midm20d: M20D DAQ&lt;br /&gt;
* m15vw: M15 CAMP&lt;br /&gt;
* m9bvw: M20 CAMP (C or D)&lt;br /&gt;
* m20vw: M20 CAMP (D or C)&lt;br /&gt;
* lxm9a: Linux VME DAQ, dhcp: ladd00, tftp: ladd00, nfsroot: musr00&lt;br /&gt;
* lxm9b: Linux VME DAQ, dhcp: ladd00, tftp: ladd00, nfsroot: musr00&lt;br /&gt;
* lxm15: Linux VME DAQ, dhcp, tftp, nfsroot: midm15&lt;br /&gt;
* lxm20c: Linux VME DAQ, dhcp, tftp: ladd00, nfsroot: midm20c&lt;br /&gt;
* lxm20d: Linux VME DAQ, dhcp, tftp: ladd00, nfsroot: midm20d&lt;br /&gt;
&lt;br /&gt;
== MUSR00 services ==&lt;br /&gt;
&lt;br /&gt;
* NIS master (MUSR-NIS)&lt;br /&gt;
* home directories&lt;br /&gt;
* NFS for OS images of ISAC V7648/V7750 VME CPUs (lxEXPT machines)&lt;br /&gt;
* web server: http://musr00.triumf.ca&lt;br /&gt;
* nodeinfo for MUSR machines&lt;br /&gt;
&lt;br /&gt;
== NIS configuration ==&lt;br /&gt;
&lt;br /&gt;
* domainname MUSR-NIS&lt;br /&gt;
* master: xxx&lt;br /&gt;
* secondary: xxx&lt;br /&gt;
* autofs/automount configuration: musr00:/etc files auto.master, auto.home, auto.musr, auto.daq&lt;br /&gt;
** after editing autofs files, run:&lt;br /&gt;
** cd ~root&lt;br /&gt;
** make -C /var/yp&lt;br /&gt;
** ./all.perl service autofs reload&lt;br /&gt;
&lt;br /&gt;
== NFS configuration ==&lt;br /&gt;
&lt;br /&gt;
* /isdaq/dataNNN - shared data disks&lt;br /&gt;
* /musr/xxx - BNMR/BNQR data disks&lt;br /&gt;
&lt;br /&gt;
== MUSR account summary ==&lt;br /&gt;
&lt;br /&gt;
* /home for local disks, /home1 for NFS directories.&lt;br /&gt;
* musrdaq/msrorg are NIS but not NFS. Local directory in /home on each machine. msrorg exists on musr01/musr02 analysis machines as well!&lt;br /&gt;
* m15/m20c/eXXX/... are NIS and NFS. Most hosted on musr00, but m20c hosted on /home in midm20c etc. &lt;br /&gt;
* lx machines mount /home1 from relevant midm machine (vis fstab) to get access to musrdaq code. Nothing in /home for them.&lt;br /&gt;
&lt;br /&gt;
== CMMS VLAN ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
IP address range: 142.90.154.x, 1..253&lt;br /&gt;
gateway 142.90.154.254&lt;br /&gt;
subnet mask 255.255.255.0&lt;br /&gt;
prefix 24&lt;br /&gt;
DNS server: 142.90.100.19 (for now)&lt;br /&gt;
DHCP server: midm15&lt;br /&gt;
DHCP server: midm9a (for lxm9a and lxm9b in the daq lab)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Labeling:&lt;br /&gt;
&lt;br /&gt;
* network outlets and network switches are labeled &amp;quot;CMMS VLAN 142.90.152.x&amp;quot; using blue-on-white labeling tape&lt;br /&gt;
* network devices configured for use on the CMMS VLAN: &amp;quot;midm20c/142.90.154.195&amp;quot; using blue-on-white labeling tape&lt;br /&gt;
&lt;br /&gt;
== CMMS VLAN migration ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
DAQ LAB outlet 243-8&lt;br /&gt;
lxm9a      142.90.111.101 -&amp;gt; 142.90.154.101 - done&lt;br /&gt;
lxm9b      142.90.111.102 -&amp;gt; 142.90.154.102 - done&lt;br /&gt;
midm9a     142.90.101.163 -&amp;gt; 142.90.154.76  - done - added dhcp for lxm9a, lxm9b&lt;br /&gt;
(midm9b)   142.90.101.72 -&amp;gt;  142.90.154.72&lt;br /&gt;
&lt;br /&gt;
XXX&lt;br /&gt;
musr00     142.90.119.219 -&amp;gt; 142.90.154.219 - done&lt;br /&gt;
musr01     142.90.102.31&lt;br /&gt;
musr02     142.90.102.32&lt;br /&gt;
musr03     142.90.102.33  -&amp;gt; 142.90.154.33 - done&lt;br /&gt;
(midm20)   142.90.101.74&lt;br /&gt;
&lt;br /&gt;
muser1 .126.13 -&amp;gt; 142.90.154.113 - done renumbered .13 to .113, conflict with m15crtv&lt;br /&gt;
muser2 .126.19&lt;br /&gt;
muser3 .126.24&lt;br /&gt;
muser4 .126.28&lt;br /&gt;
jhb .112.43 -&amp;gt; 142.90.154.43 - done&lt;br /&gt;
&lt;br /&gt;
M15&lt;br /&gt;
midm15      142.90.101.73  -&amp;gt; 142.90.154.73  - done&lt;br /&gt;
lxm15       142.90.111.103 -&amp;gt; 142.90.154.103 - done&lt;br /&gt;
m15vw       142.90.102.3   -&amp;gt; 142.90.154.108 - done - renumbered .3 to .108&lt;br /&gt;
m15hv01     142.90.102.14  -&amp;gt; 142.90.154.14  - done&lt;br /&gt;
las14       142.90.126.7   -&amp;gt; 142.90.154.7   - done&lt;br /&gt;
muhtr1      142.90.109.122 -&amp;gt; 142.90.154.122 - done&lt;br /&gt;
mupress01   142.90.101.151 -&amp;gt; 142.90.154.151 - done&lt;br /&gt;
mulaket03   142.90.126.133 -&amp;gt; 142.90.154.133 - done&lt;br /&gt;
drtempm15   142.90.126.124 -&amp;gt; 142.90.154.124 - done&lt;br /&gt;
bnqrlt      142.90.126.53  -&amp;gt; 142.90.154.53  - done&lt;br /&gt;
m15crtv x -&amp;gt; 142.90.154.13 - done, in dns&lt;br /&gt;
&lt;br /&gt;
musoren01   142.90.101.141 -&amp;gt; 142.90.154.141 - done&lt;br /&gt;
musoren02   142.90.101.142 -&amp;gt; 142.90.154.142 - done&lt;br /&gt;
musoren03   142.90.101.143 -&amp;gt; 142.90.154.143 - done&lt;br /&gt;
musoren04   142.90.101.144 -&amp;gt; 142.90.154.144 - done&lt;br /&gt;
musoren05   142.90.101.145 -&amp;gt; 142.90.154.145 - done&lt;br /&gt;
musoren06   142.90.101.146 -&amp;gt; 142.90.154.146 - done&lt;br /&gt;
&lt;br /&gt;
mulaket01 142.90.126.131 -&amp;gt; .131 - done&lt;br /&gt;
mulaket02 142.90.126.132 -&amp;gt; .132 - done&lt;br /&gt;
mulaket03 142.90.126.133 -&amp;gt; .133 - done&lt;br /&gt;
mulaket04 .134 - bnmr/bnqr&lt;br /&gt;
mulaket05 .135 - bnmr/bnqr&lt;br /&gt;
mulaket06 .136 - &lt;br /&gt;
mulaket07 .137&lt;br /&gt;
mulaket08 .138&lt;br /&gt;
&lt;br /&gt;
mucamp2    142.90.126.39&lt;br /&gt;
&lt;br /&gt;
MUSR (RMC) CR&lt;br /&gt;
midm20c    142.90.101.195 -&amp;gt; 142.90.154.195 - done&lt;br /&gt;
midm20d    142.90.101.196 -&amp;gt; 142.90.154.196 - done&lt;br /&gt;
lxm20c     142.90.106.205 -&amp;gt; 142.90.154.205 - done&lt;br /&gt;
lxm20d     142.90.106.206 -&amp;gt; 142.90.154.206 - done&lt;br /&gt;
(m9avw)    142.90.109.166 -&amp;gt; 142.90.154.109 - done - renumbered&lt;br /&gt;
m9bvw      142.90.101.48  -&amp;gt; 142.90.154.110 - done - renumbered - crashes soon after boot&lt;br /&gt;
m20vw      142.90.101.27  -&amp;gt; 142.90.154.111 - done - renumbered&lt;br /&gt;
m9hv01     142.90.111.76  -&amp;gt; 142.90.154.17  - done - renumbered due to collision with midm9a&lt;br /&gt;
m20hv01    142.90.101.60  -&amp;gt; 142.90.154.60  - done&lt;br /&gt;
mutest     142.90.126.91  -&amp;gt; 142.90.154.91  - done&lt;br /&gt;
las77      142.90.111.25  -&amp;gt; 142.90.154.25  - done&lt;br /&gt;
muscopem20 142.90.126.50  -&amp;gt; 142.90.154.50  - done&lt;br /&gt;
m9 vme crate - m9vc .252 - done (not in DNS) -&amp;gt; .9 - done&lt;br /&gt;
m20 vme crate - m20vc .251 - done (not in DNS) -&amp;gt; .10 - done&lt;br /&gt;
m20crtv .253 - done (not in DNS) -&amp;gt; .11 - done&lt;br /&gt;
&lt;br /&gt;
BNMR/BNQR&lt;br /&gt;
lxbnmr     142.90.123.24  -&amp;gt; 104 renumber&lt;br /&gt;
lxbnqr     142.90.123.25  -&amp;gt; 105 renumber&lt;br /&gt;
polvw      142.90.127.139 -&amp;gt; 106 renumber&lt;br /&gt;
bnmrvw     142.90.127.48  -&amp;gt; 107 renumber&lt;br /&gt;
daqfire1   142.90.105.89 -&amp;gt; 89&lt;br /&gt;
daqfire2   142.90.105.90 -&amp;gt; 90&lt;br /&gt;
bnmrcon1   142.90.127.119 -&amp;gt; 119&lt;br /&gt;
polcon1    142.90.127.162 -&amp;gt; 162&lt;br /&gt;
&lt;br /&gt;
bnmrhv01 .127.118 -&amp;gt; 118&lt;br /&gt;
&lt;br /&gt;
bnmrexp .126.94 -&amp;gt; 94&lt;br /&gt;
bnqrexp .126.95 -&amp;gt; 95&lt;br /&gt;
&lt;br /&gt;
Newly allocated IP addresses:&lt;br /&gt;
&lt;br /&gt;
lxmusr3t 142.90.154.8 - done&lt;br /&gt;
m9vc 142.90.154.9 - done&lt;br /&gt;
m20vc 142.90.154.10 - done&lt;br /&gt;
m20crtv 142.90.154.11 - done&lt;br /&gt;
m9crtv 142.90.154.12 - done&lt;br /&gt;
muamips1 142.90.126.110 -&amp;gt; 142.90.154.127 - done&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Old IP addresses to be removed&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
midm15old&lt;br /&gt;
midm15x&lt;br /&gt;
midm15y&lt;br /&gt;
igeldaq&lt;br /&gt;
igelm15&lt;br /&gt;
igelm20&lt;br /&gt;
igelm9b&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=EBIT_DAQ&amp;diff=7607</id>
		<title>EBIT DAQ</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=EBIT_DAQ&amp;diff=7607"/>
		<updated>2024-02-07T22:21:25Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Links ==&lt;br /&gt;
&lt;br /&gt;
* [[TITAN DAQ General Documentation]] that explains the core principles of the DAQ system&lt;br /&gt;
* [http://titan05.triumf.ca:8089/?cmd=Status DAQ status]&lt;br /&gt;
* [http://titan05.triumf.ca:8089/?cmd=custom&amp;amp;page=Scan%20settings Main settings]&lt;br /&gt;
* [http://titan05.triumf.ca:8089/?cmd=custom&amp;amp;page=Web%20plots Online plots]&lt;br /&gt;
* [https://bitbucket.org/ttriumfdaq/titan_data/src/master/ titan_data repository] for user-friendly python tools for reading the data&lt;br /&gt;
* The EBIT DAQ system is based on the [https://midas.triumf.ca/MidasWiki/index.php/Midas_documentation MIDAS DAQ package]&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
EBIT has 2 main hardware components the PPG and the MCA4.&lt;br /&gt;
&lt;br /&gt;
=== PPG32 (Pulse Programmer) ===&lt;br /&gt;
&lt;br /&gt;
The PPG used by EBIT is a PPG32, built at TRIUMF (see [http://www.triumf.info/wiki/DAQwiki/index.php/VME-NIMIO32 manual]). The PPG32 is designed to be clocked at 10MHz, and an internal &amp;quot;divide down&amp;quot; is used to produce frequencies of up to 100MHz. Presently &#039;&#039;&#039;only the internal clock is used&#039;&#039;&#039;, and the PPG is clocked at 100MHz. In the future, the PPG may be clocked using the special TITAN 100MHz external clock, in a similar way to the MPET and CPET PPGs.&lt;br /&gt;
&lt;br /&gt;
Due to the requirement that the PPG32 be clocked externally by the special TITAN 100MHz &amp;quot;since wave&amp;quot; pulse generator, the firmware has been modified to allow this with a particular value of &amp;quot;divide downs&amp;quot;. This also requires that the module be set to TTL Input Clock and Trigger signals using an jumper on the board. It is planned to change the PPG to a newer version, where the individual PPG Outputs may also be set to NIM or TTL with jumpers.  &lt;br /&gt;
&lt;br /&gt;
The PPG32 supports up to 32 Output channels, and the minimal delay is 3 clock cycles. However, the PPG is only fitted with 16 NIM connectors, limiting the device to 16 channels. More NIM connectors may be added if required.  &lt;br /&gt;
&lt;br /&gt;
=== MCA4 / MCS4 (time-of-flight) ===&lt;br /&gt;
&lt;br /&gt;
The MCA4/MCS4 is a USB-based device that produces time-of-flight histograms. There is one BNC input that starts a clock, and two inputs that can &amp;quot;stop&amp;quot; the clock. The two &amp;quot;stop&amp;quot; channels work independently (i.e. you can measure the &amp;quot;stop&amp;quot; times of both channels even though the &amp;quot;start&amp;quot; signal was only sent once). The bin width of the histograms (aka the dwell time) and the number of bins is configurable. The minimum dwell time is 30ns if only one &amp;quot;stop&amp;quot; channel is being used, or 50ns if both &amp;quot;stop&amp;quot; channels are enabled. The maximum number of bins is 16 million, but reading out that much data would significantly degrade DAQ performance.&lt;br /&gt;
&lt;br /&gt;
If using the MCA4, ensure the &amp;quot;feebit_mca4&amp;quot; program is running (using the [http://titan05.triumf.ca:8089/?cmd=Programs Programs] webpage)&lt;br /&gt;
&lt;br /&gt;
The MCA4 is programmed to expect TTL (positive) signals!&lt;br /&gt;
&lt;br /&gt;
== Feature configuration ==&lt;br /&gt;
&lt;br /&gt;
The DAQ system is configured on the [http://titan05.triumf.ca:8089/?cmd=custom&amp;amp;page=Scan%20settings Scan settings] webpage.&lt;br /&gt;
&lt;br /&gt;
=== Scanning ===&lt;br /&gt;
&lt;br /&gt;
It is possible to automatically scan different EPICS variables and/or PPG variables (pulse widths and time offsets). See the [[TITAN_DAQ_General_Documentation#Core_principles]] for more information about 1D and 2D scans.&lt;br /&gt;
&lt;br /&gt;
=== Enabling/disabling the PPG program ===&lt;br /&gt;
&lt;br /&gt;
You can choose whether to run the PPG program or not during the run. Disabling the PPG program still allows you to record MCA4 data, and still allows you to scan EPICS variables and/or toggle the Faraday cup in/out of the beamline if desired. &lt;br /&gt;
&lt;br /&gt;
If the PPG is disable, you must choose how long each &amp;quot;cycle&amp;quot; is (i.e. how long to take data for before moving on to the next step); the default is 10 seconds. (When the PPG is enabled, the cycle duration is dictated by the length of the PPG program.) Even if you aren&#039;t scanning/toggling anything, you should still set a reasonable cycle length; data is only written to disk at the end of each cycle, so if your cycle length is set to many minutes you could lose a lot of data if the DAQ crashes during a run.&lt;br /&gt;
&lt;br /&gt;
=== MCA4 settings ===&lt;br /&gt;
&lt;br /&gt;
You can specify whether data is read out from the MCA4, and if so, whether to read out data just from STOP1 or also from STOP2. The histogram bin width (dwell time) is the same for both channels, but you may specify a different number of bins for each channel if desired.&lt;br /&gt;
&lt;br /&gt;
=== Faraday cup readout ===&lt;br /&gt;
&lt;br /&gt;
You can choose whether to read out the current measured by the TRFCBL:FC0 and ILE2T:FC3 Faraday cups. The values are currently read at the end of each supercycle.&lt;br /&gt;
&lt;br /&gt;
=== Faraday cup in/out toggling ===&lt;br /&gt;
&lt;br /&gt;
Three modes are available for controlling the TRFCBL:FC0 Faraday cup:&lt;br /&gt;
&lt;br /&gt;
* Automatically take data with the cup out and then the cup in, before moving on to the next step in the scan.&lt;br /&gt;
* Only take data with the cup in one position, and force the cup to that position at the start of the run.&lt;br /&gt;
* Only take data with the cup in one position, leaving the cup in its existing position at the start of the run.&lt;br /&gt;
&lt;br /&gt;
=== ZMQ announcement of the cycle state ===&lt;br /&gt;
&lt;br /&gt;
You can request that a [https://zeromq.org ZMQ] socket is opened, which will broadcast the start/end of each run and the start/end of each PPG cycle. For EBIT, a PUB (publisher) socket will be opened, which you should connect to with a SUB (subscriber) socket. Remember that SUB sockets MUST also subscribe to a topic after connecting (even if the messages being published don&#039;t specify a topic).&lt;br /&gt;
&lt;br /&gt;
  import zmq&lt;br /&gt;
    &lt;br /&gt;
  context = zmq.Context()&lt;br /&gt;
  socket = context.socket(zmq.SUB)&lt;br /&gt;
  socket.connect(&amp;quot;tcp://somewhere.triumf.ca:1234&amp;quot;)&lt;br /&gt;
  socket.subscribe(&amp;quot;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
All the messages are sent as serialized JSON. The exact format of the &amp;quot;new cycle&amp;quot; messages depends on what is being scanned/toggled during a run.&lt;br /&gt;
&lt;br /&gt;
All messages include the midas run number, and the message time as a UNIX timestamp in MILLISECONDS.&lt;br /&gt;
&lt;br /&gt;
==== Example messages ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Begin of run&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;command&amp;quot;: &amp;quot;begin_of_run&amp;quot;,&lt;br /&gt;
  &amp;quot;run_number&amp;quot;: 147,&lt;br /&gt;
  &amp;quot;scan_config&amp;quot;: {&lt;br /&gt;
    &amp;quot;EPICS&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;demand_dev&amp;quot;: &amp;quot;A:B:C&amp;quot;,&lt;br /&gt;
        &amp;quot;end&amp;quot;: 600.0,&lt;br /&gt;
        &amp;quot;human_name&amp;quot;: &amp;quot;Example&amp;quot;,&lt;br /&gt;
        &amp;quot;measured_dev&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;n_points&amp;quot;: 6,&lt;br /&gt;
        &amp;quot;scan_dimension&amp;quot;: &amp;quot;X&amp;quot;,&lt;br /&gt;
        &amp;quot;start&amp;quot;: 100.0,&lt;br /&gt;
        &amp;quot;use_formula&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;values&amp;quot;: [&lt;br /&gt;
          100.0,&lt;br /&gt;
          200.0,&lt;br /&gt;
          300.0,&lt;br /&gt;
          400.0,&lt;br /&gt;
          500.0,&lt;br /&gt;
          600.0&lt;br /&gt;
        ]&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;FC0InOut&amp;quot;: [&lt;br /&gt;
      &amp;quot;flip_when&amp;quot;: &amp;quot;every super-cycle&amp;quot;&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;PPG&amp;quot;: [],&lt;br /&gt;
    &amp;quot;nX&amp;quot;: 6,&lt;br /&gt;
    &amp;quot;nY&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;nZ&amp;quot;: 0&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;timestamp&amp;quot;: 1701477018928&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Start of cycle&#039;&#039;&#039;, EPICS value being scanned and Faraday cup being toggled in/out automatically. Note that multiple EPICS devices can be scanned, so that entry is an array. We include both the value that the user requested (100.0 in this example) and the actual physically measured value (99.97 in this example). There is only one toggle for whether the FC0 cup is in/out of the beamline, so that entry is not an array.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;command&amp;quot;: &amp;quot;new_cycle&amp;quot;,&lt;br /&gt;
  &amp;quot;cycle_number&amp;quot;: 0,&lt;br /&gt;
  &amp;quot;run_number&amp;quot;: 147,&lt;br /&gt;
  &amp;quot;scan_settings&amp;quot;: {&lt;br /&gt;
    &amp;quot;EPICS&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;demand_dev&amp;quot;: &amp;quot;A:B:C&amp;quot;,&lt;br /&gt;
        &amp;quot;demand_val&amp;quot;: 100.0,&lt;br /&gt;
        &amp;quot;human_name&amp;quot;: &amp;quot;Example&amp;quot;,&lt;br /&gt;
        &amp;quot;measured_dev&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;measured_val&amp;quot;: 0.0&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;FC0InOut&amp;quot;: {&lt;br /&gt;
      &amp;quot;as_boolean&amp;quot;: false,&lt;br /&gt;
      &amp;quot;as_string&amp;quot;: &amp;quot;false&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;PPG&amp;quot;: []&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;timestamp&amp;quot;: 1701477018935&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Start of cycle&#039;&#039;&#039;, 2D scan of EPICS and PPG, but no toggling of Faraday Cup. Again the PPG entry is an array.&lt;br /&gt;
&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;command&amp;quot;: &amp;quot;new_cycle&amp;quot;,&lt;br /&gt;
  &amp;quot;cycle_number&amp;quot;: 0,&lt;br /&gt;
  &amp;quot;run_number&amp;quot;: 152,&lt;br /&gt;
  &amp;quot;scan_settings&amp;quot;: {&lt;br /&gt;
    &amp;quot;EPICS&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;demand_dev&amp;quot;: &amp;quot;A:B:C&amp;quot;,&lt;br /&gt;
        &amp;quot;demand_val&amp;quot;: 100.0,&lt;br /&gt;
        &amp;quot;human_name&amp;quot;: &amp;quot;Example&amp;quot;,&lt;br /&gt;
        &amp;quot;measured_dev&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;measured_val&amp;quot;: 0.0&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;FC0InOut&amp;quot;: null,&lt;br /&gt;
    &amp;quot;PPG&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;odb_path&amp;quot;: &amp;quot;/Equipment/PPGCompiler/Programming/Pulse_beam/time offset (ms)&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: 0.0&lt;br /&gt;
      }&lt;br /&gt;
    ]&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;timestamp&amp;quot;: 1701478228205&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;End of cycle&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
  {&#039;command&#039;: &#039;end_of_cycle&#039;, &#039;cycle_number&#039;: 12, &#039;run_number&#039;: 113, &#039;timestamp&#039;: 1624392509388}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;End of run&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
  {&#039;command&#039;: &#039;end_of_run&#039;, &#039;run_number&#039;: 113, &#039;timestamp&#039;: 1624392523080}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Full run&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
  {&#039;command&#039;: &#039;begin_of_run&#039;, &#039;run_number&#039;: 113, &#039;scan_config&#039;: {.....}, &#039;timestamp&#039;: 1624392506190}&lt;br /&gt;
  {&#039;command&#039;: &#039;new_cycle&#039;, &#039;cycle_number&#039;: 0, &#039;run_number&#039;: 113, &#039;scan_settings&#039;: {.....}, &#039;timestamp&#039;: 1624392506385}&lt;br /&gt;
  {&#039;command&#039;: &#039;end_of_cycle&#039;, &#039;cycle_number&#039;: 0, &#039;run_number&#039;: 113, &#039;timestamp&#039;: 1624392509388}&lt;br /&gt;
  {&#039;command&#039;: &#039;new_cycle&#039;, &#039;cycle_number&#039;: 1, &#039;run_number&#039;: 113, &#039;scan_settings&#039;: {.....}, &#039;timestamp&#039;: 1624392509399}&lt;br /&gt;
  {&#039;command&#039;: &#039;end_of_cycle&#039;, &#039;cycle_number&#039;: 1, &#039;run_number&#039;: 113, &#039;timestamp&#039;: 1624392512402}&lt;br /&gt;
  {&#039;command&#039;: &#039;new_cycle&#039;, &#039;cycle_number&#039;: 2, &#039;run_number&#039;: 113, &#039;scan_settings&#039;: {.....}, &#039;timestamp&#039;: 1624392512413}&lt;br /&gt;
  {&#039;command&#039;: &#039;end_of_cycle&#039;, &#039;cycle_number&#039;: 2, &#039;run_number&#039;: 113, &#039;timestamp&#039;: 1624392515416}&lt;br /&gt;
  {&#039;command&#039;: &#039;new_cycle&#039;, &#039;cycle_number&#039;: 3, &#039;run_number&#039;: 113, &#039;scan_settings&#039;: {.....}, &#039;timestamp&#039;: 1624392515427}&lt;br /&gt;
  {&#039;command&#039;: &#039;end_of_cycle&#039;, &#039;cycle_number&#039;: 3, &#039;run_number&#039;: 113, &#039;timestamp&#039;: 1624392518045}&lt;br /&gt;
  {&#039;command&#039;: &#039;end_of_run&#039;, &#039;run_number&#039;: 113, &#039;timestamp&#039;: 1624392523080}&lt;br /&gt;
&lt;br /&gt;
== Data format ==&lt;br /&gt;
&lt;br /&gt;
In the final data file, each event contains data from a single scan configuration (i.e. X step, Y step, FC0 in/out). The data from all cycles within a supercycle are combined into a single event. The histograms contain only the data from that scan configuration. Each event also contains data explaining the scan configuration that applied to that event.&lt;br /&gt;
&lt;br /&gt;
If the run continued for many loops, there may be several events with the same scan configuration. E.g.&lt;br /&gt;
&lt;br /&gt;
  Event #1: Loop 0, X step 0, cup out&lt;br /&gt;
  Event #2: Loop 0, X step 0, cup in&lt;br /&gt;
  Event #3: Loop 0, X step 1, cup out&lt;br /&gt;
  Event #4: Loop 0, X step 1, cup in&lt;br /&gt;
  Event #5: Loop 1, X step 0, cup out&lt;br /&gt;
  Event #6: Loop 1, X step 0, cup in&lt;br /&gt;
  Event #7: Loop 1, X step 1, cup out&lt;br /&gt;
  Event #8: Loop 1, X step 1, cup in&lt;br /&gt;
&lt;br /&gt;
Offline analysis would need to sum the histograms in events #1 and #5 to get all the data for the &amp;quot;X step 0, cup out&amp;quot; configuration.&lt;br /&gt;
&lt;br /&gt;
Python tools for reading the data in a user-friendly manner can be found in the [https://bitbucket.org/ttriumfdaq/titan_data/src/master/ titan_data] repository.&lt;br /&gt;
&lt;br /&gt;
If you are logged-on to titan05 as the ebit user, you can run the &#039;&#039;&#039;ebitdump&#039;&#039;&#039; command to dump data to screen as it is being taken (it&#039;s only written at the end of each supercycle). Example output from this tool is:&lt;br /&gt;
&lt;br /&gt;
  Event # 6, at 2020-08-26 16:27:30&lt;br /&gt;
    Loop count 0, X point 3, Y point -1, FC0 Out&lt;br /&gt;
    PPG scanning:&lt;br /&gt;
      /Equipment/PPGCompiler/Programming/del_cycle_end/time offset (ms) =&amp;gt; 8.0&lt;br /&gt;
    Faraday cup readings:&lt;br /&gt;
      ILE2T:FC3:SCALECUR =&amp;gt; -9.765624723809263e-13&lt;br /&gt;
      TRFCBL:FC0:SCALECUR =&amp;gt; 7.019043007407133e-13&lt;br /&gt;
    MCA4 channel 1 has 8192 bins. Max bin is 1203&lt;br /&gt;
    MCA4 channel 2 has 0 bins. Max bin is None&lt;br /&gt;
  Event # 7, at 2020-08-26 16:27:36&lt;br /&gt;
    Loop count 0, X point 3, Y point -1, FC0 In&lt;br /&gt;
    PPG scanning:&lt;br /&gt;
      /Equipment/PPGCompiler/Programming/del_cycle_end/time offset (ms) =&amp;gt; 8.0&lt;br /&gt;
    Faraday cup readings:&lt;br /&gt;
      ILE2T:FC3:SCALECUR =&amp;gt; 0.0&lt;br /&gt;
      TRFCBL:FC0:SCALECUR =&amp;gt; 1.129150375631105e-12&lt;br /&gt;
    MCA4 channel 1 has 8192 bins. Max bin is 1205&lt;br /&gt;
    MCA4 channel 2 has 0 bins. Max bin is None&lt;br /&gt;
  Event # 8, at 2020-08-26 16:27:40&lt;br /&gt;
    Loop count 0, X point 4, Y point -1, FC0 Out&lt;br /&gt;
    PPG scanning:&lt;br /&gt;
      /Equipment/PPGCompiler/Programming/del_cycle_end/time offset (ms) =&amp;gt; 9.0&lt;br /&gt;
    Faraday cup readings:&lt;br /&gt;
      ILE2T:FC3:SCALECUR =&amp;gt; 9.765624723809263e-13&lt;br /&gt;
      TRFCBL:FC0:SCALECUR =&amp;gt; 8.239746233408562e-13&lt;br /&gt;
    MCA4 channel 1 has 8192 bins. Max bin is 1341&lt;br /&gt;
    MCA4 channel 2 has 0 bins. Max bin is None&lt;br /&gt;
&lt;br /&gt;
See [[TITAN_DAQ_General_Documentation#CPET.2FMPET.2FEBIT_data_format]] for the gory details of the file format.&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
&lt;br /&gt;
The DAQ system is based on the [https://midas.triumf.ca/MidasWiki/index.php/Midas_documentation MIDAS DAQ package]. Software written for EBIT is linked with the MIDAS libraries and uses common framework for MPET/CPET/EBIT. &lt;br /&gt;
&lt;br /&gt;
The EBIT software can be found at &#039;&#039;/home/ebit/packages/ebit&#039;&#039; on &#039;&#039;&#039;titan05&#039;&#039;&#039; (note that historical versions of the software were located in &#039;&#039;/home/ebit/online&#039;&#039;).  &lt;br /&gt;
&lt;br /&gt;
Run control is done using the MIDAS webserver [https://midas.triumf.ca/MidasWiki/index.php/Mhttpd mhttpd] with [https://midas.triumf.ca/MidasWiki/index.php/Custom_Page Custom Pages] written for &#039;&#039;ebit&#039;&#039; users so that they can easily enter the parameters required to program the PPG and to run the DAQ.&lt;br /&gt;
&lt;br /&gt;
=== Computers ===&lt;br /&gt;
&lt;br /&gt;
* titan05 is a &amp;quot;normal&amp;quot; PC that runs the main midas programs (mhttpd web server etc).&lt;br /&gt;
* lxebit is a PC that lives in the EBIT VME crate. It has direct access to the PPG (which runs a programmable sequence of pulses to other hardware) and any other hardware in the VME crate. lxebit uses an NFS mount and NIS accounts, so sees the same /home/ebit as titan05. This machine runs the &amp;quot;feebit_ppg&amp;quot; program.&lt;br /&gt;
* titan-pi04 is a raspberry pi that talks to the Fastcom MCA4. It can only be accessed from within TRIUMF (either on-site or via the TRIUMF VPN). It does not use NFS/NIS, and has its own /home/ebit. This machine runs the &amp;quot;feebit_mca4&amp;quot; program.&lt;br /&gt;
&lt;br /&gt;
=== Starting and stopping DAQ programs ===&lt;br /&gt;
Programs can be started/stopped from the [http://titan05.triumf.ca:8089/?cmd=Programs Midas programs page]. All programs that appear on that page should be running (green status).&lt;br /&gt;
&lt;br /&gt;
To start/stop everything (or if the programs page is inaccessible), you can use the following aliases after logging in as the &amp;quot;ebit&amp;quot; user on &#039;&#039;&#039;titan05&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
  kill-all (an alias of ~/packages/ebit/bin/kill-all.sh that stops all the DAQ programs)&lt;br /&gt;
  start-all (an alias of ~/packages/ebit/bin/start-all.sh that starts all the DAQ programs)&lt;br /&gt;
&lt;br /&gt;
=== Program listing ===&lt;br /&gt;
&lt;br /&gt;
In the order that programs appear on the [http://titan05.triumf.ca:8089/?cmd=Programs Programs page]:&lt;br /&gt;
* mhttpd - midas web server&lt;br /&gt;
* Logger - midas data logger&lt;br /&gt;
* feebit_ppg - main EBIT frontend that talks to the PPG, scans EPICS values etc. Runs on lxebit.&lt;br /&gt;
* PPGCompilerFrontend - converts a user-supplied PPG program into bytecode that can be loaded onto the PPG&lt;br /&gt;
* saveload - helps save and load scan settings&lt;br /&gt;
* mserver - midas RPC server that allows the programs on lxebit and titan-pi04 to talk to the main experiment on titan05&lt;br /&gt;
* feebit_mca4 - frontend that interacts with the MCA4 and sends the histogram data to feebit_ppg at the end of each supercycle&lt;br /&gt;
* ebitana - python analyzer that creates plots based on live data (plots are viewed via the [http://titan05.triumf.ca:8089/?cmd=custom&amp;amp;page=Web%20plots Web plots] page)&lt;br /&gt;
&lt;br /&gt;
=== Pulling the latest version of the EBIT DAQ software ===&lt;br /&gt;
  # On titan05 (which shares a /home/ebit with lxebit)&lt;br /&gt;
  cd ~/packages/ebit&lt;br /&gt;
  git pull&lt;br /&gt;
  git submodule update&lt;br /&gt;
&lt;br /&gt;
  # On lxebit (not titan05 - we can&#039;t cross-compile from titan05 as it doesn&#039;t have compatible 32-bit ZMQ libs)&lt;br /&gt;
  cd ~/packages/ebit/build&lt;br /&gt;
  make install&lt;br /&gt;
&lt;br /&gt;
  # On titan-pi04&lt;br /&gt;
  cd ~/packages/ebit&lt;br /&gt;
  git pull&lt;br /&gt;
  git submodule update&lt;br /&gt;
  cd build&lt;br /&gt;
  make install&lt;br /&gt;
&lt;br /&gt;
  # On titan05 - restart the DAQ&lt;br /&gt;
  kill-all&lt;br /&gt;
  start-all&lt;br /&gt;
&lt;br /&gt;
=== cmake configurations ===&lt;br /&gt;
&lt;br /&gt;
Different cmake configurations are used on titan05 and titan-pi04 when building the software. If cmake needs to be run again, use:&lt;br /&gt;
&lt;br /&gt;
  # On titan05 - default build creates 32-bit feebit_ppg for lxebit, plus 64-bit analyzer for titan05&lt;br /&gt;
  cd ~/packages/ebit/build&lt;br /&gt;
  cmake ..&lt;br /&gt;
&lt;br /&gt;
  # On titan-pi04 - build 64-bit feebit_mca4&lt;br /&gt;
  cd ~/packages/ebit/build&lt;br /&gt;
  cmake -DBUILD_MCA4_FE_ONLY=1 ..&lt;br /&gt;
&lt;br /&gt;
=== MCA4 frontend design rationale ===&lt;br /&gt;
&lt;br /&gt;
Fastcom provided USB code that only works on some versions of linux. In particular, it is not possible to reliably talk to the MCA4 from lxebit. Therefore, we use a raspberry pi running Ubuntu 20.04 for the MCA4 communications, and run the rest of the DAQ from lxebit as normal. Ubuntu 20.04 provides very stable interaction with the MCA4.&lt;br /&gt;
&lt;br /&gt;
The MCA4 takes several seconds to handle a &amp;quot;start acquisition&amp;quot; command. If this was not the case, we would stop and restart the MCA4 at the end of each supercycle, so that &amp;quot;fresh&amp;quot; histograms are created for each scan step. However, such high latency is unacceptable, so we leave the MCA4 running all the time, and do calculations in the frontend that subtracts the state of the histogram at the end of the previous supercycle from the current state.&lt;br /&gt;
&lt;br /&gt;
We only write data to disk at the end of each supercycle, so normally users would be left waiting for a long time to see what the data looks like. We therefore have 2 ways to send histogram data from feebit_mca4 to feebit_ppg. At the end of each supercycle, we send data with an event ID of 1 into the BUFMCA4 buffer. Within each cycle (every few hundred ms) we send data with an event ID of 0 into the BUFMCA4 buffer. Only the data from the former events are written to disk, but the latter events can be read by the rootana-based analyzers to show a more responsive visualization of the data. This works very well as the data read from the MCS4 is &#039;&#039;cumulative&#039;&#039;, and is only reset at the end of each supercycle.&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=MPET_DAQ&amp;diff=7606</id>
		<title>MPET DAQ</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=MPET_DAQ&amp;diff=7606"/>
		<updated>2024-02-07T22:18:35Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Links =&lt;br /&gt;
&amp;lt;div style=&amp;quot;column-count:3;-moz-column-count:3;-webkit-column-count:3&amp;quot;&amp;gt;&lt;br /&gt;
* [[TITAN]] TITAN Page&lt;br /&gt;
* [[TITAN DAQ General Documentation]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
MPET has:&lt;br /&gt;
&lt;br /&gt;
* A PPG for programming pulses&lt;br /&gt;
* A 2-channel Tektronix AFG for generating RF (was previously two Agilent AFGs)&lt;br /&gt;
* An 8-channel GSC 16ao16 to control the trap voltages (was previously an Alphi Softdac). There is a breakout box to convert to BNC connections. The breakout box has many connectors, but only 8 channels are actually controllable!&lt;br /&gt;
* An older VT2 TDC for recording timestamps&lt;br /&gt;
* A position analyzer to determine X/Y positions of ions&lt;br /&gt;
* A Lecroy LRS1190 memory buffer that records the X/Y position&lt;br /&gt;
* A newer CAEN V1290 25ps TDC for recording timestamps&lt;br /&gt;
&lt;br /&gt;
Note that the VT2/V1290 TDCs are enabled in different ways:&lt;br /&gt;
* The VT2 has a &amp;quot;gate&amp;quot; that is set to 1 for the entire period that timestamps should be recorded&lt;br /&gt;
* The V1290 has a &amp;quot;trigger&amp;quot; that is issued at the end of the desired period; the times of any hits within the &amp;quot;trigger window&amp;quot; (normally 50us) before the trigger are recorded&lt;br /&gt;
&lt;br /&gt;
The wiring diagram for the MPET DAQ is:&lt;br /&gt;
&lt;br /&gt;
[[Image:MPET wiring.png]]&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
&lt;br /&gt;
The DAQ system is based on the [https://midas.triumf.ca/MidasWiki/index.php/Midas_documentation MIDAS DAQ package]. Software written for MPET is linked with the MIDAS libraries and uses common framework for MPET/CPET/EBIT. &lt;br /&gt;
&lt;br /&gt;
The MPET software can be found at &#039;&#039;/home/mpet/packages/mpet&#039;&#039; on &#039;&#039;&#039;titan06&#039;&#039;&#039; (note that historical versions of the software were located in &#039;&#039;/home/mpet/online&#039;&#039;).  &lt;br /&gt;
&lt;br /&gt;
Run control is done using the MIDAS webserver [https://midas.triumf.ca/MidasWiki/index.php/Mhttpd mhttpd] with [https://midas.triumf.ca/MidasWiki/index.php/Custom_Page Custom Pages] written for &#039;&#039;mpet&#039;&#039; users so that they can easily enter the parameters required to program the PPG and to run the DAQ.&lt;br /&gt;
&lt;br /&gt;
The default login shell for the mpet user is now bash. If you want to use the legacy DAQ (which only supports the VT2/VT4 and Softdac, not the CAEN V1290 and GSC 16ao16), then change to the tcsh shell by typing &#039;tcsh&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Program listing ===&lt;br /&gt;
&lt;br /&gt;
In the order that programs appear on the [http://titan06.triumf.ca:8088/?cmd=Programs Programs page]:&lt;br /&gt;
* mserver - midas RPC server that allows the programs on lxebit to talk to the main experiment on titan06&lt;br /&gt;
* fempet - main MPET frontend that talks to the PPG, scans EPICS values etc. Runs on lxmpet.&lt;br /&gt;
* mhttpd - midas web server&lt;br /&gt;
* PPGCompilerFrontend - converts a user-supplied PPG program into bytecode that can be loaded onto the PPG&lt;br /&gt;
* saveload - helps save and load scan settings&lt;br /&gt;
* AfgFrontend - frontend that configures the Agilent Quad/Dipole AFGs at the start of each run (written in python)&lt;br /&gt;
* AfgTekFrontend - frontend that configures the Tektronix AFG at the start of each run (written in python)&lt;br /&gt;
* Logger - midas data logger&lt;br /&gt;
* mpetana - python analyzer that creates plots based on live data (plots are viewed via the [http://titan06.triumf.ca:8088/?cmd=custom&amp;amp;page=Web%20plots Web plots] page)&lt;br /&gt;
&lt;br /&gt;
=== Starting and stopping DAQ programs ===&lt;br /&gt;
Programs can be started/stopped from the [http://titan06.triumf.ca:8080/?cmd=Programs Midas programs page]. All programs that appear on that page should be running (green status).&lt;br /&gt;
&lt;br /&gt;
If the webpage is unavailable, log in to mpet@titan06, and type&lt;br /&gt;
&lt;br /&gt;
  mhttpd -D&lt;br /&gt;
&lt;br /&gt;
=== Pulling the latest version of the MPET DAQ software ===&lt;br /&gt;
  cd ~/packages/mpet&lt;br /&gt;
  git pull&lt;br /&gt;
  git submodule update&lt;br /&gt;
&lt;br /&gt;
=== Building the MPET DAQ software ===&lt;br /&gt;
 cd ~/packages/mpet/build&lt;br /&gt;
 cmake ..&lt;br /&gt;
 make install&lt;br /&gt;
&lt;br /&gt;
This will build the appropriate 32-bit frontend program that can be used by lxmpet.&lt;br /&gt;
&lt;br /&gt;
=== 16ao16 driver and software ===&lt;br /&gt;
&lt;br /&gt;
The [http://www.generalstandards.com/view-products2.php?BD_family=16ao16 16ao16] is used to control the trap voltages. It is mounted on lxmpet as a PMC board, and requires a kernel module and software. GSC seem very good at supporting this and continue releasing updates for newer linux versions.&lt;br /&gt;
&lt;br /&gt;
There is one tweak we need to make for the build to work vs what is documented in the manual. &lt;br /&gt;
&lt;br /&gt;
 1. Download the latest 16ao16.linux.******.tar.gz bundle from http://www.generalstandards.com/downloads/ and copy it to ~/packages. Extract it using tar. It should create the directory ~/packages/16ao16.&lt;br /&gt;
 &lt;br /&gt;
 2. Run `uname -r` to find your current kernel version.&lt;br /&gt;
 &lt;br /&gt;
 3. Check if a file exists called /usr/src/linux-headers-&amp;lt;kernel_version&amp;gt;-common/scripts/file-size.sh. &lt;br /&gt;
    If not, create it and fill it with this content:&lt;br /&gt;
    #!/bin/sh  &lt;br /&gt;
    #SPDX-License-Identifier: GPL-2.0  &lt;br /&gt;
    set -- $(ls -dn &amp;quot;$1&amp;quot;)  &lt;br /&gt;
    printf &#039;%s\n&#039; &amp;quot;$5&amp;quot;&lt;br /&gt;
   &lt;br /&gt;
 4. Build the software:&lt;br /&gt;
    cd ~/packages/16ao16&lt;br /&gt;
    ./make_all&lt;br /&gt;
 &lt;br /&gt;
 5. Do the final installation of library and driver as root:&lt;br /&gt;
    su - root&lt;br /&gt;
    cd ~/packages/16ao16&lt;br /&gt;
    ./make_all&lt;br /&gt;
 &lt;br /&gt;
 6. Verify that the driver has been loaded, by seeing if /proc/16ao16 exists.&lt;br /&gt;
 &lt;br /&gt;
 7. Configure things so the driver loads each time lxmpet boots, by adding the following line to /etc/rc.local:&lt;br /&gt;
    /home/mpet/packages/16ao16/driver/start&lt;br /&gt;
&lt;br /&gt;
The make_all script builds both the driver and the software libraries. The mpet software builds and links against the GSC library. By default it looks for the headers/libraries in /home/mpet/packages/16ao16, but if you&#039;ve built it elsewhere you can specify an alternate directory using the &amp;lt;code&amp;gt;-DGSC_16AO16_DIR=/path/to/somewhere&amp;lt;/code&amp;gt; argument when running cmake.&lt;br /&gt;
&lt;br /&gt;
== Agilent vs Tektronix AFGs ==&lt;br /&gt;
&lt;br /&gt;
In summer 2022, MPET bought a Tektronix 35052 2-channel AFG to replace two Agilent AFGs (both types of AFG are used to generate RF signals).&lt;br /&gt;
&lt;br /&gt;
The Agilent AFGs could be programmed with a list of frequencies, with the next frequency being loaded when a PPG signal was issued. This allowed the frequencies to be scanned within a single PPG loop. The Tektronix AFG does have a sequencing option (if you pay extra money), but has severe limitations that do not allow it to be used the way we need (especially if wanting to run both channels simultaneously).&lt;br /&gt;
&lt;br /&gt;
Therefore, when using the Tektronix AFG, the frequency must be scanned outside of the PPG loop (same as if you were scanning an EPICS PV or trap voltage).&lt;br /&gt;
&lt;br /&gt;
=== AfgFrontend vs AfgTekFrontend ===&lt;br /&gt;
&lt;br /&gt;
There are two separate programs that may be run:&lt;br /&gt;
* AfgFrontend is the program that controls the Agilent AFGs&lt;br /&gt;
* AfgTekFrontend is the program that controls the Tektronix AFG&lt;br /&gt;
&lt;br /&gt;
The code has some sanity-checks to make it easier for you to determine which AFG was being used when looking at the midas files:&lt;br /&gt;
* The run will not start if both the Agilent and Tektronix frontends are running&lt;br /&gt;
* The run will not start if an Agilent AFG is set as &amp;quot;enabled&amp;quot; in the ODB, but the Tektronix frontend is running (or vice-versa)&lt;br /&gt;
&lt;br /&gt;
=== Changing between the AFGs ===&lt;br /&gt;
&lt;br /&gt;
To change from using the Agilent to Agilent AFG:&lt;br /&gt;
* Stop the AfgFrontend program on the Programs page&lt;br /&gt;
* Start the AfgTekFrontend program on the Programs page&lt;br /&gt;
* Go to the &amp;quot;RF (Tek)&amp;quot; page and configure the frequencies&lt;br /&gt;
&lt;br /&gt;
To change from using the Tektronix to Agilent AFG:&lt;br /&gt;
* Stop the AfgTekFrontend program on the Programs page&lt;br /&gt;
* Start the AfgFrontend program on the Programs page&lt;br /&gt;
* Go to the &amp;quot;RF (Agilent)&amp;quot; page and configure the frequencies&lt;br /&gt;
&lt;br /&gt;
For the Agilent AFG, the number of frequencies is determined by the number of loops of the &amp;quot;begin_ramp&amp;quot; loop of the PPG program.&lt;br /&gt;
&lt;br /&gt;
For the Tektronix AFG, the number of frequencies is determined by the number of X/Y/Z scan steps. &amp;lt;b&amp;gt;You may still have &amp;gt; 1 loops in the &amp;quot;begin_ramp&amp;quot; loop of the PPG program, but they will all be taken with the same frequency&amp;lt;/b&amp;gt; (take care of this when doing analysis!). Having &amp;gt; 1 loops is the lowest-latency (most efficient) way of increasing your statistics as the DAQ won&#039;t do anything until all the loops have completed; only then will there be some deadtime as the DAQ moves to the next scan point.&lt;br /&gt;
&lt;br /&gt;
=== X/Y/Z scan ordering ===&lt;br /&gt;
&lt;br /&gt;
For a 2D scan, all the Y points are covered at a given X point before moving to the next X point.&lt;br /&gt;
&lt;br /&gt;
For a 3D scan, all the Z points are covered at a given X+Y point before moving to the next Y point. After all the Y points have been covered we move to the next X point.&lt;br /&gt;
&lt;br /&gt;
So for a 3D scan, the Z variable is changed a lot more often than the X variable. For maximum efficiency, it is recommended that you use the Z variable for the parameter that is quickest to react to the change (e.g. EPICS voltages can be slow to react, so changing EPICS in the X variable and the frequency in the Z variable is likely to be most efficient).&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=TITAN&amp;diff=7605</id>
		<title>TITAN</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=TITAN&amp;diff=7605"/>
		<updated>2024-02-07T22:15:30Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Information on TITAN DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== General info ===&lt;br /&gt;
&lt;br /&gt;
* [http://titan.triumf.ca TITAN Main Web page]&lt;br /&gt;
* [http://daq-plone.triumf.ca/ESI/titan TITAN Documentation on the DAQ plone site]&lt;br /&gt;
* https://titan00.triumf.ca/elog/ - TITAN ELOG&lt;br /&gt;
* https://titan00.triumf.ca/triumf_nodeinfo/config.html&lt;br /&gt;
&lt;br /&gt;
=== Contacts ===&lt;br /&gt;
&lt;br /&gt;
* TITAN general: amaudruz olchansk lindner bsmith aniak@triumf.ca&lt;br /&gt;
&lt;br /&gt;
=== Components ===&lt;br /&gt;
&lt;br /&gt;
* MPET http://titan06.triumf.ca:8080/&lt;br /&gt;
* EBIT http://titan05.triumf.ca:8089/&lt;br /&gt;
* EBIT2 (TITAN EC electron capture) https://titan01.triumf.ca:8444&lt;br /&gt;
* CPET  http://titan02.triumf.ca:8081/ - Decommissioned&lt;br /&gt;
* MRTOF (time of flight) - Not a midas DAQ; maintained by TITAN group&lt;br /&gt;
&lt;br /&gt;
=== TITAN Linux DAQ cluster ===&lt;br /&gt;
&lt;br /&gt;
Computers:&lt;br /&gt;
* titan00 - main file server for home directories and data disks, boot server for VME CPUs, runs CentOS7. Located in ISAC2 server room on UPS power.&lt;br /&gt;
* titan01 - EBIT2 DAQ, runs SL6, will soon be deprecated&lt;br /&gt;
* titan02 - will soon be deprecated&lt;br /&gt;
* titan03 - terminal on titan platform&lt;br /&gt;
* titan05 - EBIT DAQ, runs Ubuntu (replaced titan02)&lt;br /&gt;
* titan06 - MPET DAQ, runs Ubuntu (replaced titan01)&lt;br /&gt;
* titan07 - mini PC on titan platform that runs cryo/HV, managed by titan group not DAQ&lt;br /&gt;
* lxmpet - MPET VME DAQ&lt;br /&gt;
* lxebit - EBIT VME DAQ&lt;br /&gt;
* lxcpet - CPET VME DAQ&lt;br /&gt;
* lxebit2 - EBIT2 VME DAQ&lt;br /&gt;
* titan-pi04 - Raspberry pi for talking to EBIT&#039;s Fastcom MCA4, standalone, no mounts&lt;br /&gt;
&lt;br /&gt;
Disk space:&lt;br /&gt;
* home directories are on titan00 2x240GB SSD (RAID1), backups on amanda&lt;br /&gt;
* data disks are on titan00 2x4TB (RAID1) /titan/data0&lt;br /&gt;
* zfs mirror 2x240GB SSD (RAID1) on titan05&lt;br /&gt;
&lt;br /&gt;
Nodeinfo:&lt;br /&gt;
* https://titan00.triumf.ca/triumf_nodeinfo/config.html&lt;br /&gt;
&lt;br /&gt;
Disk quota report:&lt;br /&gt;
* https://titan00.triumf.ca/quotareport/quota.html&lt;br /&gt;
&lt;br /&gt;
== Links to DAQ Instructions ==&lt;br /&gt;
&lt;br /&gt;
* [[TITAN DAQ General Documentation]] &lt;br /&gt;
** [[MPET DAQ|MPET DAQ Instructions]]&lt;br /&gt;
** [[EBIT DAQ|EBIT DAQ instructions]]&lt;br /&gt;
** [[CPET DAQ|CPET DAQ Instructions]]&lt;br /&gt;
** [[EBIT2 DAQ|EBIT2 DAQ Instructions]]&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=TITAN&amp;diff=7578</id>
		<title>TITAN</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=TITAN&amp;diff=7578"/>
		<updated>2024-01-10T23:06:37Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Information on TITAN DAQ ==&lt;br /&gt;
&lt;br /&gt;
=== General info ===&lt;br /&gt;
&lt;br /&gt;
* [http://titan.triumf.ca TITAN Main Web page]&lt;br /&gt;
* [http://daq-plone.triumf.ca/ESI/titan TITAN Documentation on the DAQ plone site]&lt;br /&gt;
* https://titan00.triumf.ca/elog/ - TITAN ELOG&lt;br /&gt;
* https://titan00.triumf.ca/triumf_nodeinfo/config.html&lt;br /&gt;
&lt;br /&gt;
=== Contacts ===&lt;br /&gt;
&lt;br /&gt;
* TITAN general: amaudruz olchansk lindner bsmith aniak@triumf.ca&lt;br /&gt;
&lt;br /&gt;
=== Components ===&lt;br /&gt;
&lt;br /&gt;
* MPET http://titan01.triumf.ca:8080/&lt;br /&gt;
* EBIT http://titan02.triumf.ca:8089/&lt;br /&gt;
* EBIT2 (TITAN EC electron capture) https://titan01.triumf.ca:8444&lt;br /&gt;
* CPET  http://titan02.triumf.ca:8081/ - Decommissioned&lt;br /&gt;
* MRTOF (time of flight) - Not a midas DAQ; maintained by TITAN group&lt;br /&gt;
&lt;br /&gt;
=== TITAN Linux DAQ cluster ===&lt;br /&gt;
&lt;br /&gt;
Computers:&lt;br /&gt;
* titan00 - main file server for home directories and data disks, boot server for VME CPUs, runs CentOS7. Located in ISAC2 server room on UPS power.&lt;br /&gt;
* titan01 - MPET DAQ, EBIT2 DAQ, runs SL6, will soon be deprecated&lt;br /&gt;
* titan02 - CPET and EBIT DAQ, runs SL6, will soon be deprecated&lt;br /&gt;
* titan03 - terminal on titan platform&lt;br /&gt;
* titan05 - runs Ubuntu, will replace titan01&lt;br /&gt;
* titan06 - runs Ubuntu, will replace titan02&lt;br /&gt;
* titan07 - mini PC on titan platform that runs cryo/HV, managed by titan group not DAQ&lt;br /&gt;
* lxmpet - MPET VME DAQ&lt;br /&gt;
* lxebit - EBIT VME DAQ&lt;br /&gt;
* lxcpet - CPET VME DAQ&lt;br /&gt;
* lxebit2 - EBIT2 VME DAQ&lt;br /&gt;
* titan-pi04 - Raspberry pi for talking to EBIT&#039;s Fastcom MCA4, standalone, no mounts&lt;br /&gt;
&lt;br /&gt;
Disk space:&lt;br /&gt;
* home directories are on titan00 2x240GB SSD (RAID1), backups on amanda&lt;br /&gt;
* data disks are on titan00 2x4TB (RAID1) /titan/data0&lt;br /&gt;
* zfs mirror 2x240GB SSD (RAID1) on titan05&lt;br /&gt;
&lt;br /&gt;
Nodeinfo:&lt;br /&gt;
* https://titan00.triumf.ca/triumf_nodeinfo/config.html&lt;br /&gt;
&lt;br /&gt;
Disk quota report:&lt;br /&gt;
* https://titan00.triumf.ca/quotareport/quota.html&lt;br /&gt;
&lt;br /&gt;
== Links to DAQ Instructions ==&lt;br /&gt;
&lt;br /&gt;
* [[TITAN DAQ General Documentation]] &lt;br /&gt;
** [[MPET DAQ|MPET DAQ Instructions]]&lt;br /&gt;
** [[EBIT DAQ|EBIT DAQ instructions]]&lt;br /&gt;
** [[CPET DAQ|CPET DAQ Instructions]]&lt;br /&gt;
** [[EBIT2 DAQ|EBIT2 DAQ Instructions]]&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=PPG_Building_Blocks&amp;diff=7576</id>
		<title>PPG Building Blocks</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=PPG_Building_Blocks&amp;diff=7576"/>
		<updated>2024-01-09T23:44:37Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Links =&lt;br /&gt;
&amp;lt;div style=&amp;quot;column-count:3;-moz-column-count:3;-webkit-column-count:3&amp;quot;&amp;gt;&lt;br /&gt;
* [[TITAN]] page&lt;br /&gt;
* [[TITAN DAQ General Documentation]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
== Introduction ==&lt;br /&gt;
[[Image:PPG_page.png|250px|thumb|right|Example of PPG page showing user settings and preview of the timing scheme]] TITAN and other experiments use a Programmable Pulse Generator (PPG) to issue precise timing signals during their experiments. TITAN in particular require very flexible timing schemes, and users change these schemes often. A TITAN grad student initially implemented a way to program the PPGs via settings in an ODB directory. This concept has now been expanded and made more felxible and user-friendly. At the heart of the systems is a python-based compiler that converts the ODB settings into bytecode that the PPG hardware understands.&lt;br /&gt;
&lt;br /&gt;
This page explains the contents of the PPG Blocks stored in the ODB, how they are named and how they work.&lt;br /&gt;
&lt;br /&gt;
In general, the user does not need to know these details, as they are handled by the python/javascript provided in the [https://bitbucket.org/ttriumfdaq/cycling_framework/ cycling_framework].&lt;br /&gt;
&lt;br /&gt;
The structure of the user&#039;s PPG program is stored in the ODB as a set of sub-directories within {{Odbpath|path=/Equipment/PPGCompiler/Programming}}. The order of the sub-directories matters, as if no explicit &amp;quot;time reference&amp;quot; supplied, one block is assumed to start immediately after the previous one finishes. Sub-directories must be named according to the conventions listed in [[#Defined Block Types]]. Each sub-directory must have a unique name. The keys that must be present within each subdirectory are detailed below, and vary based on the block type (pulse, delay, loop etc).&lt;br /&gt;
&lt;br /&gt;
A python program (the PPG compiler, [https://bitbucket.org/ttriumfdaq/cycling_framework/src/master/ppg/ppg_compiler_fe.py ppg_compiler_fe.py]) runs as a midas frontend and converts the ODB structure into bytecode that can be loaded onto the PPG.&lt;br /&gt;
&lt;br /&gt;
== Compiler settings ==&lt;br /&gt;
&lt;br /&gt;
The compiler has some global settings in {{Odbpath|path=/Equipment/PPGCompiler/Settings}}:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Standard pulse width (ms)&#039;&#039; - see [[#Standard Pulse Widths]]&lt;br /&gt;
* &#039;&#039;PPG clock (MHz)&#039;&#039; - PPG clock frequency, so we can convert from ms to number of clock cycles&lt;br /&gt;
* &#039;&#039;Use external trigger&#039;&#039; - y/n for whether the PPG should use an external signal or a software command to start&lt;br /&gt;
* &#039;&#039;Use external clock&#039;&#039; - y/n for whether the PPG should use an external or internal clock&lt;br /&gt;
* &#039;&#039;Inverted channels bitmask&#039;&#039; - bitmask to invert output of any channels; not generally used&lt;br /&gt;
* &#039;&#039;Loadfile path&#039;&#039; - where to write the bytecode that is generated (note that the frontend can also ask for the bytecode to be sent to it directly, not via a written file)&lt;br /&gt;
* &#039;&#039;PPG uses pulseblaster - y/n for whether this is the older PulseBlaster PPG or newer TRIUMF PPG (as they have different bytecode requirements)&lt;br /&gt;
* &#039;&#039;Debug&#039;&#039; - y/n for whether to debug the compiler&lt;br /&gt;
* &#039;&#039;Compile at BOR&#039;&#039; - y/n for whether to automatically compile bytecode at begin-of-run (note that TITAN frontends ask the compiler themselves during their BOR transition, so this can safely be &#039;n&#039; for TITAN experiments)&lt;br /&gt;
* &#039;&#039;Enable extra 1-time BOR program&#039;&#039; - see [[#Begin-of-run program]]&lt;br /&gt;
* &#039;&#039;Wrap program in automatic loop&#039;&#039; - some experiments have very strict timing, and want to run the same program multiple times without delay. However, the user did not want to think about this as a loop in their own program. So we allow wrapping everything that the user provides in an automatic loop, and only ask the user how many time to run the loop before stopping. (In cycling_framework language, the user&#039;s code runs multiple times within a single cycle).&lt;br /&gt;
* &#039;&#039;Auto loop num iterations&#039;&#039; - if wrapping the user&#039;s program in an automatic loop, how many iterations to run.&lt;br /&gt;
* &#039;&#039;Record T0 offsets&#039;&#039; - y/n for whether to record timing offsets of each block in the ODB. This is useful for some experiments who need to know the time difference between 2 pulses for their analysis. Results are written to {{Odbpath|path=/Equipment/PPGCompiler/Computed/T0 offsets (ms)}}.&lt;br /&gt;
* &#039;&#039;Enable formulae&#039;&#039; - see [[#Specifying times with a formula]]&lt;br /&gt;
* &#039;&#039;Image path&#039;&#039; - legacy, for when webpage showing a static image of the cycle rather than an interactive plot&lt;br /&gt;
* &#039;&#039;Expanded image path&#039;&#039; - legacy, for when webpage showing a static image of the cycle rather than an interactive plot&lt;br /&gt;
&lt;br /&gt;
=== PPG clock ===&lt;br /&gt;
The internal clock of the PPG PulseBlaster (used on MPET) is determined by an on-board clock chip, which is removed when the PPG is run with an external clock. This is the case for MPET, where the PPG is clocked with an external 100MHz clock. It cannot be switched between internal and external clock by software.&lt;br /&gt;
&lt;br /&gt;
The PPG32 on the other hand can be switched between internal and external clock by software. It was designed to use a 20MHz internal or external clock, the actual frequency being programmed with divide-downs. The CPET PPG32 has been modified to use an external 100MHz clock (same clock as MPET). The EBIT PPG32 has not been modified, and currently runs with the internal clock programmed to produce 100MHz.&lt;br /&gt;
The maximum value supported by either board is 100MHz. &lt;br /&gt;
&lt;br /&gt;
The correct PPG Clock Frequency must be stored in the ODB at &amp;lt;code&amp;gt;/Equipment/PPGCompiler/Settings/PPG clock (MHz)&amp;lt;/code&amp;gt;, otherwise the timing of the output pulses will be incorrect, i.e.&lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 60%; background-color: white;&amp;quot; border=&amp;quot;0&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
! Input parameter name !! Value !! Type&lt;br /&gt;
|- &lt;br /&gt;
|PPG Clock (MHz)|| 100 || FLOAT &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Standard Pulse Widths ===&lt;br /&gt;
Other values are defined (also in the  input parameter area) which the user can change as required:&lt;br /&gt;
&lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 60%; background-color: white;&amp;quot; border=&amp;quot;0&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
! Input parameter name !! Value !! Type&lt;br /&gt;
|-&lt;br /&gt;
| standard pulse width (ms)|| 0.005 ||   DOUBLE&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;standard pulse width&#039;&#039; is used by the STDPULSE blocks. Using a STDPULSE reduces the number of different delays that need to be generated to program the PPG.&lt;br /&gt;
&lt;br /&gt;
== Optional features ==&lt;br /&gt;
&lt;br /&gt;
=== Begin-of-run program ===&lt;br /&gt;
&lt;br /&gt;
It is possible to run an extra program once at the start of a run, before running the &amp;quot;normal&amp;quot; program. This may be useful for resetting scalers or similar.&lt;br /&gt;
&lt;br /&gt;
The begin-of-run program is enabled with the PPGCompiler setting &#039;Enable extra 1-time BOR program&#039;. The program itself is stored in {{Odbpath|path=/Equipment/PPGCompiler/Programming BOR}}&lt;br /&gt;
&lt;br /&gt;
=== Scanning parameters ===&lt;br /&gt;
&lt;br /&gt;
The cycling framework allows for time offsets and pulse widths to be scanned during a run. If scanning is enabled, the experiment&#039;s frontend code sets the relevant parameters in the ODB blocks, then asks the compiler to re-produce the bytecode.&lt;br /&gt;
&lt;br /&gt;
=== Specifying times with a formula ===&lt;br /&gt;
&lt;br /&gt;
By default, the user specifies actual numbers for the time offsets and pulse widths. However, by setting &#039;/Equipment/PPGCompiler/Settings/Enable formulae&#039; to true, the user may specify variables and formulae for the timings.&lt;br /&gt;
&lt;br /&gt;
User-specified variables are stored in the &#039;/Equipment/PPGCompiler/Programming/Formula variables&#039; directory. Formulae are stored in the &#039;time offset formula&#039; and &#039;pulse width formula&#039; keys of each PPG block. When the compiler is asked to re-compile the bytecode, it first evaluates the formulae, putting the results in the &#039;time offset (ms)&#039; and &#039;pulse width (ms)&#039; keys as appropriate. The rest of the compilation then proceeds as normal.&lt;br /&gt;
&lt;br /&gt;
Formula evaluation is done in the python code in a safe way (using Abstract Syntax Tree parsing with a whitelist of allowed functions/variables, rather than simply calling &#039;eval()&#039;).&lt;br /&gt;
&lt;br /&gt;
User-specified variables may be scanned during a run.&lt;br /&gt;
&lt;br /&gt;
=== Adding an automatic loop ===&lt;br /&gt;
&lt;br /&gt;
Normally we run the program specified by the user once per &amp;quot;cycle&amp;quot;. In the cycling framework this means we do: start the PPG -&amp;gt; wait for cycle to finish -&amp;gt; do some work in software -&amp;gt; start the PPG again. Sometimes users want to run a program multiple times without any software delay between cycles. This is easily achieved by just wrapping the entire program in a loop. However, sometimes users don&#039;t want the &amp;quot;visual noise&amp;quot; of seeing the actual loop. So we allow an &amp;quot;automatic loop&amp;quot; to be added by the compiler. The user never sees the definition of this loop, but just says how many times to run the program before we do a software delay (e.g. to read out data, increase scan values etc).&lt;br /&gt;
&lt;br /&gt;
Enabling the automatic loop is done with the &#039;/Equipment/PPGCompiler/Settings/Wrap program in automatic loop&#039; key, and the number of iterations to run each time we start the PPF is specified with the &#039;/Equipment/PPGCompiler/Settings/Auto loop num iterations&#039; key. &lt;br /&gt;
&lt;br /&gt;
=== Muting blocks ===&lt;br /&gt;
&lt;br /&gt;
Users may mute and unmute blocks to disable the output of a block without affecting the timing of a sequence. This is particularly useful for taking signal and background measurements with an RFQ pulse unmuted and muted, for example. Muted blocks appear with a red background on the webpage.&lt;br /&gt;
&lt;br /&gt;
The cycling framework includes the ability to automatically toggle between muted and unmuted states during a run. You could configure it to run N cycles with a pulse muted, then N cycles unmuted, then increase a scan value, and start running N cycles with a pulse muted again etc... Multiple pulses can be muted/unmuted at the same time, and with opposite polarities if desired.&lt;br /&gt;
&lt;br /&gt;
== Defined PPG Block Types ==&lt;br /&gt;
A number of fundamental building blocks (PPG Blocks) have been defined. Many act on one or more of the PPG Output signals. They are listed in Table 1 below. Click on each Block Type for more information.&lt;br /&gt;
 &lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 100%; background-color: white&amp;quot; border=&amp;quot;3&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|+ TABLE 1  List of Block Types acting on PPG signals&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
! Block Type * &amp;lt;br&amp;gt; (click on links for definitions)&lt;br /&gt;
! Explanation&lt;br /&gt;
! style=&amp;quot;text-align:left;color:#b300b3;font-style:italic;&amp;quot;|Example &amp;lt;br&amp;gt;Blockname&lt;br /&gt;
|- &lt;br /&gt;
|[[#Transition Block|&#039;&#039;&#039;TRA&#039;&#039;&#039;&#039;&#039;NS&#039;&#039;]]&lt;br /&gt;
| cause a channel &#039;&#039;&#039;transition&#039;&#039;&#039; (toggle between on and off, depending on the current state)&lt;br /&gt;
|style=&amp;quot;text-align:left;color:#b300b3;font-style:italic;&amp;quot;| TRANS_EX&lt;br /&gt;
|-&lt;br /&gt;
|[[#Turnon Block|&#039;&#039;&#039;TURNON&#039;&#039;&#039;]]&lt;br /&gt;
| ensure a channel is &#039;&#039;&#039;on&#039;&#039;&#039;&lt;br /&gt;
|style=&amp;quot;text-align:left;color:#b300b3;font-style:italic;&amp;quot;| TURNON_EX&lt;br /&gt;
|-&lt;br /&gt;
|[[#Turnoff Block|&#039;&#039;&#039;TURNOFF&#039;&#039;&#039;]]&lt;br /&gt;
| ensure a channel is &#039;&#039;&#039;off&#039;&#039;&#039;&lt;br /&gt;
|style=&amp;quot;text-align:left;color:#b300b3;font-style:italic;&amp;quot;| TURNOFF_EX&lt;br /&gt;
|-&lt;br /&gt;
|[[#Pulse Block|&#039;&#039;&#039;PUL&#039;&#039;&#039;&#039;&#039;SE&#039;&#039;]]&lt;br /&gt;
|a &#039;&#039;&#039;pulse&#039;&#039;&#039; of user-defined width&lt;br /&gt;
|style=&amp;quot;text-align:left;color:#b300b3;font-style:italic;&amp;quot;|pulse_dac&lt;br /&gt;
|- &lt;br /&gt;
|[[#Multi Pulse Block|&#039;&#039;&#039;MUL&#039;&#039;&#039;&#039;&#039;TI&#039;&#039;]]&lt;br /&gt;
|multiple &#039;&#039;&#039;pulses&#039;&#039;&#039; on the same channel a fixed time apart&lt;br /&gt;
|style=&amp;quot;text-align:left;color:#b300b3;font-style:italic;&amp;quot;|multi_dac&lt;br /&gt;
|- &lt;br /&gt;
|[[#Stdpulse Block|&#039;&#039;&#039;STD&#039;&#039;&#039;&#039;&#039;PULSE&#039;&#039;]]&lt;br /&gt;
|  a &#039;&#039;&#039;pulse&#039;&#039;&#039; of a standard width&lt;br /&gt;
|style=&amp;quot;text-align:left;color:#b300b3;font-style:italic;&amp;quot;|stdpulse_5&lt;br /&gt;
|-&lt;br /&gt;
|[[#Pattern Block|&#039;&#039;&#039;PAT&#039;&#039;&#039;&#039;&#039;TERN]]&lt;br /&gt;
| sets a &#039;&#039;&#039;bit pattern&#039;&#039;&#039;&lt;br /&gt;
|style=&amp;quot;text-align:left;color:#b300b3;font-style:italic;&amp;quot;|PatFF0E&lt;br /&gt;
|-&lt;br /&gt;
|[[#Delay Block|&#039;&#039;&#039;DEL&#039;&#039;&#039;&#039;&#039;AY]]&lt;br /&gt;
|&#039;&#039;&#039;Delay&#039;&#039;&#039; for a time with existing bit pattern unchanged&lt;br /&gt;
|style=&amp;quot;text-align:left;color:#b300b3;font-style:italic;&amp;quot;|DEL10&lt;br /&gt;
|-&lt;br /&gt;
|[[#Time Reference Block|&#039;&#039;&#039;TIM&#039;&#039;&#039;&#039;&#039;E_REF]]&lt;br /&gt;
| defines a time reference from which other blocks can be offset&lt;br /&gt;
|style=&amp;quot;text-align:left;color:#b300b3;font-style:italic;&amp;quot;|timDacStart&lt;br /&gt;
|-&lt;br /&gt;
|[[#Begin Loop Block|&#039;&#039;&#039;BEGIN&#039;&#039;&#039;&#039;&#039;_LOOP]]&lt;br /&gt;
|&#039;&#039;&#039;begin&#039;&#039;&#039; a loop&lt;br /&gt;
|style=&amp;quot;text-align:left;color:#b300b3;font-style:italic;&amp;quot;|Begin_loop5&lt;br /&gt;
|-&lt;br /&gt;
|[[#End Loop Block|&#039;&#039;&#039;END&#039;&#039;&#039;&#039;&#039;_LOOP]]&lt;br /&gt;
|rowspan=&amp;quot;1&amp;quot;|&#039;&#039;&#039;end&#039;&#039;&#039; a loop&lt;br /&gt;
|style=&amp;quot;text-align:left;color:#b300b3;font-style:italic;&amp;quot; |End_loop5&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== PPG Signal Names ==&lt;br /&gt;
PPG Signal Names are &#039;&#039;&#039;required&#039;&#039;&#039; in PULSE, MULTI and TRANS PPG blocks. These blocks have a parameter &#039;&#039;PPG signal name&#039;&#039; which expects one of the defined PPG signal names, which are of the form &amp;quot;CH1&amp;quot;, &amp;quot;CH2&amp;quot; etc (for channel 1/2). This name defines which PPG Output Channel is to be acted on by the PULSE or TRANS PPG block.  Note that the PATTERN block acts on a bit pattern, not PPG signal names. For example,  0x2000 (EBIT) will act on PPG signal name TDCBLOCK (Channel 14).  Setting a pattern of 0xFFFF will set all 32 outputs ON.&lt;br /&gt;
&lt;br /&gt;
The user is able to specify human-readable names for each channel in the ODB at {{Odbpath|path=/Equipment/PPGCompiler/Programming/names}}.&lt;br /&gt;
&lt;br /&gt;
== Time references &amp;amp; Sequence of the blocks: T0  ==&lt;br /&gt;
The time when the PPG starts running is defined as &#039;&#039;&#039;T0&#039;&#039;&#039;. All blocks are ultimately referenced in time to T0, and they will be sorted (by the ppg compiler) in order of time offset from T0  before processing into the PPG load file.&lt;br /&gt;
&lt;br /&gt;
The ordering of the blocks is significant:&lt;br /&gt;
&lt;br /&gt;
* If a block does not specify a time reference, it we default to starting as soon as the block before it ends.&lt;br /&gt;
* If a block appears between a begin_ and end_ of a loop, it will be part of that loop. Blocks within a loop may not use a time reference of a block outside the loop.&lt;br /&gt;
&lt;br /&gt;
== Automatic and user-defined time references ==&lt;br /&gt;
Blocks automatically define at least one time reference. Variable-length blocks such as pulses and loops automatically define time references at the start and end of the block. Blocks such as transitions and patterns automatically define only one time reference since the start and end are identical.&lt;br /&gt;
&lt;br /&gt;
Users can also define a time reference, using a [[#Time Reference Block]]. This provides a way to synchronize several blocks to start at one time, or to produce a delay before the next block if relying on the default time reference.&lt;br /&gt;
&lt;br /&gt;
The automatic time reference names for variable-length blocks are of the form &amp;quot;_TSTART_&amp;lt;blockname&amp;gt;, &amp;quot;_TEND_&amp;lt;blockname&amp;gt;. For other blocks, they are mostly of the form  &amp;quot;_T&amp;lt;blockname&amp;gt;&amp;quot; .&lt;br /&gt;
They are shown below in Table 3 for each of the defined blocks. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 100%; background-color: white&amp;quot; border=&amp;quot;3&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|+ TABLE 3  Automatically generated time references for each block&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
! Block Type&lt;br /&gt;
! Example &amp;lt;br&amp;gt; Blockname&lt;br /&gt;
! Automatically defined &amp;lt;br&amp;gt; time reference names&lt;br /&gt;
! Example time&amp;lt;br&amp;gt; references&lt;br /&gt;
|- &lt;br /&gt;
|[[#Transition Block|Trans]]ition&lt;br /&gt;
| TRANS_EX&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;| _T&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;block name&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_T&amp;lt;span style=color:black&amp;gt;TRANS_EX&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|[[#Turnon Block|Turnon]]&lt;br /&gt;
| TURNON_EX&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;| _T&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;block name&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_T&amp;lt;span style=color:black&amp;gt;TURNON_EX&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|[[#Turnoff Block|Turnon]]&lt;br /&gt;
| TURNOFF_EX&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;| _T&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;block name&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_T&amp;lt;span style=color:black&amp;gt;TURNOFF_EX&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|[[#Pulse Block|Pulse]]&lt;br /&gt;
|style=&amp;quot;color:black&amp;quot;|pulse_dac&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_TSTART_&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;block name&amp;gt;&amp;lt;/span&amp;gt;,&amp;lt;br&amp;gt; _TEND_&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;block name&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
|style=&amp;quot;color:#7733ff&amp;quot;|_TSTART_&amp;lt;span style=color:black&amp;gt;pulse_dac&amp;lt;/span&amp;gt;&amp;lt;br&amp;gt;_TEND_&amp;lt;span style=color:black&amp;gt;pulse_dac&amp;lt;/span&amp;gt;&lt;br /&gt;
|- &lt;br /&gt;
|[[#Multi Pulse Block|Multi]]&lt;br /&gt;
|style=&amp;quot;color:black&amp;quot;|multi_dac&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_TSTART_&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;block name&amp;gt;&amp;lt;/span&amp;gt;,&amp;lt;br&amp;gt; _TEND_&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;block name&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
|style=&amp;quot;color:#7733ff&amp;quot;|_TSTART_&amp;lt;span style=color:black&amp;gt;multi_dac&amp;lt;/span&amp;gt;&amp;lt;br&amp;gt;_TEND_&amp;lt;span style=color:black&amp;gt;multi_dac&amp;lt;/span&amp;gt;&lt;br /&gt;
|- &lt;br /&gt;
|[[#Stdpulse Block|Stdpulse]]&lt;br /&gt;
|stdpulse_5&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_TSTART_&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;block name&amp;gt;&amp;lt;/span&amp;gt;,&amp;lt;br&amp;gt; _TEND_&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;block name&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
|style=&amp;quot;color:#7733ff&amp;quot;| _TSTART_&amp;lt;span style=color:black&amp;gt;stdpulse_5&amp;lt;/span&amp;gt;&amp;lt;br&amp;gt;_TEND_&amp;lt;span style=color:black&amp;gt;stdpulse_5&amp;lt;/span&amp;gt;&lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
|[[#Pattern Block|Pattern]]&lt;br /&gt;
|PatFF0E&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_T&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;block name&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
|style=&amp;quot;color:#7733ff&amp;quot;|_T&amp;lt;span style=&amp;quot;color:black&amp;quot;&amp;gt;PatFF0E&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|[[#Delay Block|Delay]]&lt;br /&gt;
|DEL10&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;| _T&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;block name&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_T&amp;lt;span style=color:black&amp;gt;DEL10&amp;lt;/span&amp;gt;&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
|[[#Time Reference Block|Time_Ref]]erence&lt;br /&gt;
|timDacStart&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;| _T&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;block name&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_T&amp;lt;span style=color:black&amp;gt;timDacStart&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|[[#Begin Loop Block|BEGIN_LOOP]]&lt;br /&gt;
|Begin_loop5&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_TBEG&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;loop name&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_TBEG&amp;lt;span style=color:black&amp;gt;loop5&amp;lt;/span&amp;gt;&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
|[[#End Loop Block|END_LOOP]]&lt;br /&gt;
|rowspan=&amp;quot;2&amp;quot; |End_loop5&lt;br /&gt;
|rowspan=&amp;quot;1&amp;quot; style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_TEND&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;loop name&amp;gt;&amp;lt;/span&amp;gt;_ONE&lt;br /&gt;
|rowspan=&amp;quot;1&amp;quot; style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_TEND&amp;lt;span style=color:black&amp;gt;loop5_ONE&amp;lt;/span&amp;gt;&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_TEND&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;loop name&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
|rowspan=&amp;quot;1&amp;quot; style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;| _TEND&amp;lt;span style=color:black&amp;gt;loop5&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Definitions of PPG Blocks ==&lt;br /&gt;
=== Time Reference Block ===&lt;br /&gt;
The PPG time zero (T0) is defined as the time when the PPG starts running after receiving a start signal (either software or hardware). All blocks are offset ultimately from T0.  The time reference T0 is defined &#039;&#039;&#039;automatically&#039;&#039;&#039;. A number of other time-references are defined automatically - see [[#Automatic and user-defined time references]]. &lt;br /&gt;
&lt;br /&gt;
The user may define other time references for convenience, using a &#039;&#039;TIME_REF&#039;&#039; PPG Block. User-defined time references, like automatic time references, can be used as time references for later PPG Blocks.  A time reference block may define a reference from T0 or from any previously defined time reference. &lt;br /&gt;
&lt;br /&gt;
When a TIME_REF Block is defined, the &#039;&#039;&#039;name&#039;&#039;&#039; of the time reference it defines is generated automatically. It is derived from the TIME_REF Block Name as indicated in [[#Automatic and user-defined time references|Table 3]], by adding the prefix &#039;&#039;_T&#039;&#039;. See [[#example 1]] below.&lt;br /&gt;
&lt;br /&gt;
Figure 1 shows two time references, T1 and T2, defined by the user using two time reference blocks. &lt;br /&gt;
[[Image:Timeref.png|frame|center|Figure 1: Defining a Time Reference]]&lt;br /&gt;
&amp;lt;br clear=all&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Time reference blocks take the following parameters (Table 4):&lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 80%; background-color: white;&amp;quot; border=&amp;quot;3&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|+ Table 4 :  Time Ref Block Parameters&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
!ODB Key Name !! Type !! Default Value !! Required/Optional&lt;br /&gt;
|-&lt;br /&gt;
|time offset (ms) || DOUBLE 	|| 0  || Optional&lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
|time reference 	 || STRING[20] ||	end of previous block || Optional&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
All &#039;&#039;TIME_REF&#039;&#039; blocks in ODB must have the first 3 letters  &amp;quot;tim&amp;quot;, e.g. {{ppgblock|block=TIME_2}}, t{{ppgblock|block=ime_reference_define_t3}}, {{ppgblock|block=Time1}} are all acceptable. The block names must be unique, since no two time references can have the same name.  Both parameters are optional. If not supplied, the default values will be used.&lt;br /&gt;
&lt;br /&gt;
==== Example 1: Time Reference Blocks ====&lt;br /&gt;
&lt;br /&gt;
The time references in Figure 1 (above) could be defined as PPG Blocks {{ppgblock|block=time_t1}}   and  {{ppgblock|block=time_t2}}, where {{ppgblock|block=time_t1}}  is referenced to T0, and automatically defines the time reference {{timeref|ref=_TTIME_T1}} (see [[#Automatic and user-defined time references|Table 3]]).  PPG Time Reference block {{ppgblock|block=time_t2}} is then referenced to  {{timeref|ref=_TTIME_T1}} i.e. &lt;br /&gt;
 $ odbedit&amp;gt;&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt;cd &amp;quot;/Equipment/Titan_acq/ppg cycle&amp;quot;&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt;ls ppg_cycle&lt;br /&gt;
    time_t1&lt;br /&gt;
    time_t2&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt;ls &amp;quot;ppg_cycle/time_t1&amp;quot; -lt&lt;br /&gt;
   time offset (ms)        0.25&lt;br /&gt;
   time reference          T0&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt;ls &amp;quot;ppg_cycle/time_t2&amp;quot; -lt&lt;br /&gt;
   time offset (ms)        0.75&lt;br /&gt;
   time reference       _TTIME_T1&lt;br /&gt;
Alternatively, {{ppgblock|block=time_t1}} could be referenced back to time T0, i.e.&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt;ls &amp;quot;ppg_cycle/time_t2&amp;quot; -lt&lt;br /&gt;
   time offset (ms)        1.0&lt;br /&gt;
   time reference          T0&lt;br /&gt;
If these were the only blocks present, it would not be necessary to specify the time references in the first example, because by default each block is time-referenced from the previous block.  The second example must include the time reference, because the time offset given is from T0, not from the previous block.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Transition Block ===&lt;br /&gt;
This block reverses the state of an output signal (Figure 2). Two transition blocks on the same PPG output signal is equivalent to a [[#Pulse Block]].&lt;br /&gt;
&lt;br /&gt;
[[Image:Trans.png|frame|center|Figure 2: Two Transitions]]&lt;br /&gt;
&amp;lt;br clear=all&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Transition blocks take the following parameters (Table 5):&lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 80%; background-color: white;&amp;quot; border=&amp;quot;3&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|+ Table 5 :  Transition Block Parameters&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
!ODB Key Name !! Type !! Default Value !! Required/Optional&lt;br /&gt;
|-&lt;br /&gt;
|time offset (ms) || DOUBLE 	|| 0  || Optional&lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
|time reference 	 || STRING[20] ||	end of previous block || Optional&lt;br /&gt;
|-&lt;br /&gt;
| ppg signal name  || STRING[15] ||	no default; must be supplied || Required&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
A Transition block automatically defines a &#039;&#039;time reference&#039;&#039; to the time when the transition occurs. This time reference may be used by subsequent blocks as their time reference. The name of the time reference is derived from the block&#039;s name by adding the prefix &#039;&#039;_T&#039;&#039;, so that a block named {{ppgblock|block=TRANS_tdc4}} will define a time reference {{timeref|ref=_TTRANS_TDC4}}.&lt;br /&gt;
TRANSITION  blocks must have unique names, with first 3 letters being &#039;&#039;&#039;TRA&#039;&#039;&#039;, e.g. {{ppgblock|block=TRANS_2}}, {{ppgblock|block=transition_RFGATE1}}, {{ppgblock|block=TraX}} are all acceptable.&lt;br /&gt;
&lt;br /&gt;
==== Example 2: Transition Block ====&lt;br /&gt;
This example shows a transition block with blockname  {{ppgblock|block=TRANS_5}}&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt; cd &amp;quot;/Equipment/Titan_acq/ppg cycle&amp;quot;&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt; ls trans5&lt;br /&gt;
         time offset (ms)                100&lt;br /&gt;
         time reference                  T0&lt;br /&gt;
         ppg signal name                 RFGATE2&lt;br /&gt;
&lt;br /&gt;
This example reverses the state of the PPG output signal &amp;quot;RFGATE2&amp;quot; at an offset of 100ms from T0. A time reference  {{timeref|ref=_TTRANS_5}} for this transition is automatically defined.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Turnon Block ===&lt;br /&gt;
This is exactly the same as a [[#Transition Block]], but ensures that a channel is ON (rather than toggling between on/off). If the channel was already on, the block has no effect (but can still be used as a time reference for other blocks).&lt;br /&gt;
&lt;br /&gt;
=== Turnoff Block ===&lt;br /&gt;
This is exactly the same as a [[#Transition Block]], but ensures that a channel is OFF (rather than toggling between on/off). If the channel was already off, the block has no effect (but can still be used as a time reference for other blocks).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Pulse Block ===&lt;br /&gt;
This block defines a pulse of user-defined width. Figure 3 shows two pulses, one offset from T0, one offset from time reference T1. The state of the PPG output signal will be reversed for the pulse width duration.&lt;br /&gt;
Two [[#Transition Block]]s could perform the same function as a pulse block.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Pulse.png|frame|center|Figure 3: Pulses]]&lt;br /&gt;
&amp;lt;br clear=all&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pulse&#039;&#039;&#039; blocks take the following parameters (Table 6):&lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 80%; background-color: white;&amp;quot; border=&amp;quot;3&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|+ Table 6 :  Pulse Block Parameters&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
!ODB Key Name !! Type !! Default Value !! Required/Optional&lt;br /&gt;
|-&lt;br /&gt;
|time offset (ms) || DOUBLE 	|| 0  || Optional&lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
|time reference 	 || STRING[20] ||	end of previous block || Optional&lt;br /&gt;
|- &lt;br /&gt;
| pulse width (ms)  || DOUBLE || minimal delay || Optional&lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
| ppg signal name  || STRING[15] ||	no default; must be supplied || Required&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
A Pulse block automatically defines two &#039;&#039;&#039;time references&#039;&#039;&#039;; one to the time when the pulse starts, the second to the time when pulse ends. This time reference may be used by subsequent blocks as their time reference. The name of the time reference is derived from the block&#039;s name by adding the prefixes &amp;quot;_TSTART_&amp;quot; and &amp;quot;_TEND_&amp;quot; so that a pulse block named {{ppgblock|block=PULSE_TDC}} will define the time references {{timeref|ref=_TSTART_PULSE_TDC}} and {{timeref|ref=_TEND_PULSE_TDC}}.&lt;br /&gt;
PULSE blocks must have unique names, with first 3 letters being &#039;&#039;&#039;PUL&#039;&#039;&#039;, e.g. {{ppgblock|block=PULSE_2}}, {{ppgblock|block=pulse_RFGATE1}}, {{ppgblock|block=PulX}} are all acceptable.&lt;br /&gt;
&lt;br /&gt;
==== Example 3: Pulse Block ====&lt;br /&gt;
This example shows a pulse block with blockname  {{ppgblock|block=PULSE_3}}&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt; cd &amp;quot;/Equipment/Titan_acq/ppg cycle&amp;quot;&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt; ls pulse3&lt;br /&gt;
         time offset (ms)                0.05&lt;br /&gt;
         time reference                  _TTRANS_5&lt;br /&gt;
         ppg signal name                 RFTRIG1&lt;br /&gt;
         pulse width (ms)                0.005&lt;br /&gt;
&lt;br /&gt;
This example reverses the state of the PPG output signal &amp;quot;RFTRIG1&amp;quot; at an offset of 0.05ms from time reference  {{timeref|ref=_TTRANS_5}} for a time of 0.005ms. It is assumed that  {{timeref|ref=_TTRANS_5}} has been defined by the transition block in Example 2.  A time references  {{timeref|ref=_TSTART_PULSE3}} and {{timeref|ref=_TEND_PULSE3}} for this pulse will be defined automatically.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multi Pulse Block ===&lt;br /&gt;
This block defines a sequence of multiple pulses of user-defined width and a user-defined period. It simplifies programming if you need multiple periodic pulses, but a LOOP isn&#039;t appropriate (e.g. because a LOOP affects all channels, and you only need periodic output on one channel while the others to non-periodic things).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Multi&#039;&#039;&#039; pulse blocks take the following parameters (Table 7):&lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 80%; background-color: white;&amp;quot; border=&amp;quot;3&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|+ Table 7 :   Multi Pulse Block Parameters&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
!ODB Key Name !! Type !! Default Value !! Required/Optional&lt;br /&gt;
|-&lt;br /&gt;
|time offset (ms) || DOUBLE 	|| 0  || Optional&lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
|time reference 	 || STRING[20] ||	end of previous block || Optional&lt;br /&gt;
|- &lt;br /&gt;
| pulse width (ms)  || DOUBLE || minimal delay || Optional&lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
| ppg signal name  || STRING[15] ||	no default; must be supplied || Required&lt;br /&gt;
|- &lt;br /&gt;
| rep count  || INTEGER || no default; must be supplied || Required&lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
| delay between reps (ms)  || DOUBLE ||	no default; must be supplied || Required&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note that &amp;quot;delay between reps&amp;quot; is the time between the START of each pulse, not the time between the end of one pulse and the start of the next!&lt;br /&gt;
&lt;br /&gt;
A Pulse block automatically defines two &#039;&#039;&#039;time references&#039;&#039;&#039;; one to the time when the FIRST pulse starts, the second to the time when the LAST pulse ends. These time references may be used by subsequent blocks as their time reference. The name of the time reference is derived from the block&#039;s name by adding the prefixes &amp;quot;_TSTART_&amp;quot; and &amp;quot;_TEND_&amp;quot; so that a multi-pulse block named {{ppgblock|block=MULTI_TDC}} will define the time references {{timeref|ref=_TSTART_MULTI_TDC}} and {{timeref|ref=_TEND_MULTI_TDC}}.&lt;br /&gt;
Multi-pulse blocks must have unique names, with first 3 letters being &#039;&#039;&#039;MUL&#039;&#039;&#039;, e.g. {{ppgblock|block=MULTI_2}}, {{ppgblock|block=multi_RFGATE1}}, {{ppgblock|block=MulX}} are all acceptable.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Stdpulse Block ===&lt;br /&gt;
&lt;br /&gt;
This block defines a pulse of standard width ([[#Pulse Block|Figure 3)]]. A Stdpulse Block is the same as a [[#Pulse Block]] except the width is a fixed value which is defined in the odb (see [[#Standard Pulse Widths]]). The state of the output signal will be reversed for the pulse width duration. &lt;br /&gt;
&lt;br /&gt;
Stdpulse blocks take the following parameters (Table 8):&lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 80%; background-color: white;&amp;quot; border=&amp;quot;3&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|+ Table 8 :  Pulse Block Parameters&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
!ODB Key Name !! Type !! Default Value !! Required/Optional&lt;br /&gt;
|-&lt;br /&gt;
|time offset (ms) || DOUBLE 	|| 0  || Optional&lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
|time reference 	 || STRING[20] ||	end of previous block || Optional&lt;br /&gt;
|-  &lt;br /&gt;
| ppg signal name  || STRING[15] ||	no default; must be supplied || Required&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Example 4: Standard Pulse Block ====&lt;br /&gt;
This example shows a standard pulse block with blockname  {{ppgblock|block=STDPULSE1}}&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt; cd &amp;quot;/Equipment/Titan_acq/ppg cycle&amp;quot;&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt; ls stdpulse1&lt;br /&gt;
         time offset (ms)                3.4&lt;br /&gt;
         time reference                  T0&lt;br /&gt;
         ppg signal name                 CH5&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This example reverses the state of the PPG output signal &amp;quot;CH5&amp;quot; at an offset of 3.4ms from time reference  {{timeref|ref=T0}} for a time given by the [[#Standard Pulse Widths|standard pulse width]]. Time references  {{timeref|ref=_TSTART_STDPULSE1}} and {{timeref|ref=_TEND_STDPULSE1}} for this pulse will be defined automatically.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Pattern Block ===&lt;br /&gt;
This block allows the user to set the PPG output signals to a &#039;&#039;&#039;bit pattern&#039;&#039;&#039;. It is be useful for example to set all the bits to zero at the end of the ppg cycle. Instead of 15 transition blocks, one pattern block could be used. Pattern blocks take the following parameters (Table 9):&lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 80%; background-color: white;&amp;quot; border=&amp;quot;3&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|+ Table 9 :  Pattern Block Parameters&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
!ODB Key Name !! Type !! Default Value !! Required/Optional&lt;br /&gt;
|-&lt;br /&gt;
|time offset (ms) || DOUBLE 	|| 0  || Optional&lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
|time reference 	 || STRING[20] ||	end of previous block || Optional&lt;br /&gt;
|-  &lt;br /&gt;
| bit pattern  || DWORD ||	no default; must be supplied || Required&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Example 5: Pattern Block ====&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt; cd &amp;quot;/Equipment/Titan_acq/ppg cycle&amp;quot;&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt; ls pattern_test -h&lt;br /&gt;
    time offset (ms)                120&lt;br /&gt;
   time reference                  T0&lt;br /&gt;
   bit pattern                     0xF0F0&lt;br /&gt;
&lt;br /&gt;
This example sets the PPG output signals to the bit pattern shown 120ms after [[#Time references &amp;amp; Sequence of the blocks: T0|T0]].  The time reference  {{timeref|ref=_TPATTERN_TEST}} will be defined automatically.&lt;br /&gt;
&lt;br /&gt;
=== Delay Block ===&lt;br /&gt;
This block allows the user to maintain a &#039;&#039;&#039;bit pattern&#039;&#039;&#039; for a certain amount of time. It may be useful when programming loops, which sometimes need a minimal delay as a separator.&lt;br /&gt;
Delay blocks take the following parameters (Table 10):&lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 80%; background-color: white;&amp;quot; border=&amp;quot;3&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|+ Table 10 :  Delay Block Parameters&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
!ODB Key Name !! Type !! Default Value !! Required/Optional&lt;br /&gt;
|-&lt;br /&gt;
|time offset (ms) || DOUBLE 	|| 0  || Required??  &lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
|time reference 	 || STRING[20] ||	end of previous block || Optional&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
The length of the delay is given by the time offset parameter.&lt;br /&gt;
&lt;br /&gt;
==== Example 6: Delay Block ====&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt; cd &amp;quot;/Equipment/Titan_acq/ppg cycle&amp;quot;&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt; ls delay_eoc &lt;br /&gt;
   time offset (ms)                1.5&lt;br /&gt;
   time reference                  _TENDSCLR&lt;br /&gt;
&lt;br /&gt;
This example provides a delay of 1.5ms after the end of the SCLR loop (referenced from {{timeref|ref=_TENDSCLR}}). The bit pattern remains unchanged.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Begin Loop Block ===&lt;br /&gt;
This block is the start of a loop. A loop name must be provided (i.e. BEGIN &amp;lt;loopname&amp;gt;). It MUST occur in the [[#Naming PPG Blocks|Block List]] BEFORE its associated END &amp;lt;loopname&amp;gt; block.&lt;br /&gt;
Every BEGIN &amp;lt;loopname&amp;gt; block must have an associated END &amp;lt;loopname&amp;gt; block. The loop name must be unique for each loop in the block list. Every BEGIN &amp;lt;loopname&amp;gt; block must have an associated END &amp;lt;loopname&amp;gt; block. The loop name must be unique for each loop in the block list.&lt;br /&gt;
&lt;br /&gt;
Begin Loop blocks take the following parameters (Table 11):&lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 80%; background-color: white;&amp;quot; border=&amp;quot;3&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|+ Table 11 :  Begin  Block Parameters&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
!ODB Key Name !! Type !! Default Value !! Required/Optional&lt;br /&gt;
|-&lt;br /&gt;
|time offset (ms) || DOUBLE 	|| 0  || Optional &lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
|time reference 	 || STRING[20] ||	end of previous block || Optional&lt;br /&gt;
|-&lt;br /&gt;
|loop count || INT || 1 || Required &lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
User must name BEGIN LOOP blocks in ODB with a unique loop name.  The first 5 letters must be &amp;quot;begin&amp;quot;, e.g. {{ppgblock|block=BEGIN_2, begin_loop0, Begin_hvlooping}} are all acceptable.  The loop name (which is required in the PPG file sent to the compiler) will be taken from the block name by stripping off the letters &amp;quot;BEGIN_&amp;quot;, e.g.  {{ppgblock|block=begin_hvlooping}} would have &amp;quot;hvlooping&amp;quot; as the loop name.&lt;br /&gt;
&lt;br /&gt;
=== Time Reference within the loop ===&lt;br /&gt;
All transitions within a loop should use the begin_loop time reference (L1 in Figure 4), or the end of a variable pulse within the loop. They should not use the T0 reference. &lt;br /&gt;
&lt;br /&gt;
=== End Loop Block ===&lt;br /&gt;
This block ends a loop. The &amp;lt;loopname&amp;gt; must be provided, matching that of the BEGIN &amp;lt;loopname&amp;gt;.  Every END &amp;lt;loopname&amp;gt; block must have an associated BEGIN &amp;lt;loopname&amp;gt; block. The loop name must be unique for each loop in the block list. END_LOOP blocks in ODB  are named with the first 3 letters being &amp;quot;end&amp;quot;, and the rest matching the begin loop block name. e.g.  {{ppgblock|block=END_2, end_loop0, End_start}} are all acceptable provided there exists a block named  {{ppgblock|block=BEGIN_2, begin_loop0}} or  {{ppgblock|block=begin_start}}.&lt;br /&gt;
&lt;br /&gt;
In Figure 4, the time reference for the begin loop occurs at label &amp;quot;L1&amp;quot;. This time reference would actually be called {{timeref|ref=_TBEG&amp;lt;loopname&amp;gt;}}, where loopname is the name of the loop.&lt;br /&gt;
&lt;br /&gt;
[[Image:Loop.png|frame|center|Figure 4: Diagram of a Loop]]&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;	&lt;br /&gt;
&lt;br /&gt;
The END &amp;lt;loopname&amp;gt; block MUST occur in the list of blocks in the ODB AFTER its associated BEGIN &amp;lt;loopname&amp;gt; block. &lt;br /&gt;
The time offset of the END block is assumed to be the end of the first loop (or if not supplied, is assumed to be at the end of the previous block.  Note that loops can be nested, but two END blocks must be separated by at least a minimal delay. This is also true for two BEGIN blocks. &lt;br /&gt;
&lt;br /&gt;
The automatic time-references generated are  {{timeref|ref=_TEND_&amp;lt;blockname&amp;gt;_ONE}} (at the end of ONE loop) and {{timeref|ref= _TEND_&amp;lt;blockname&amp;gt;}} is at the end of ALL loops (as calculated by the configuration program).  This time is shown as &amp;quot;E0&amp;quot; in Figure 4.  The time between the end of one loop and the end of all loops is designated the &amp;quot;RESERVED&amp;quot; time. Transitions occurring within the first loop are assumed to be within the loop - any transitions occurring within the &amp;quot;reserved&amp;quot; time during which the rest of the loops will be running is not allowed, and an error message will occur. Therefore do not use {{timeref|ref=_TEND_&amp;lt;blockname&amp;gt;_ONE}} as a time reference for another pulse or transition, or that transition may be in the reserved time, generating an error. {{timeref|ref=_TEND_&amp;lt;blockname&amp;gt;}} is generated for debugging purposes only.&lt;br /&gt;
&lt;br /&gt;
;NOTE: Users must be careful when ending a loop directly following a transition if [[#TDBLOCK pulses]] are enabled. In that case, transitions generate automatic TDCBLOCK pulses whose trailing edge follows a transition, but which do not generate automatic time references. Therefore a delay must be added by the user between a transition and the end loop block, to allow time for the TDCBLOCK pulse, otherwise the trailing edge of the TDCBLOCK pulse will occur during the reserved time, generating an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
End Loop blocks take the following parameters (Table 12):&lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 80%; background-color: white;&amp;quot; border=&amp;quot;3&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|+ Table 12 :  End  Block Parameters&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
!ODB Key Name !! Type !! Default Value !! Required/Optional&lt;br /&gt;
|-&lt;br /&gt;
|time offset (ms) || DOUBLE 	|| 0  || Optional &lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
|time reference 	 || STRING[20] ||	end of previous block || Optional&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For non-nested loops, the END&amp;lt;loopname&amp;gt; block should use the time-reference defined by the equivalent &amp;quot;BEGIN&amp;lt;loopname&amp;gt;&amp;quot; block (or one of the time-references defined within the loop). For nested loops, the time reference should be from the end of an inner loop.&lt;br /&gt;
 &lt;br /&gt;
An END&amp;lt;loopname&amp;gt; block automatically defines a time reference equivalent to the BEGIN&amp;lt;loopname&amp;gt; parameter. For example, if the BEGIN&amp;lt;loopname&amp;gt; defined {{timeref|ref=_TBEGL0}} the END&amp;lt;loopname&amp;gt; automatically defines {{timeref|ref=_TENDL0}}. This value is a time reference to the end of ALL the loops.&lt;br /&gt;
So placing transitions after the end of all loops is easy using {{timeref|ref=_TENDL0}} as the reference.&lt;br /&gt;
Any other transitions occuring within the time taken for all the loops is flagged as an error.&lt;br /&gt;
&lt;br /&gt;
==== Example 6: A Loop using PPG Blocks ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#e600e6; font-style:italic&amp;quot;&amp;gt;end_ramp&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following example shows the PPG Blocks making up a loop. The Blocks  {{ppgblock|block=begin_ramp}} and  {{ppgblock|block=end_ramp}} are the begin and end of the loop named &amp;quot;ramp&amp;quot;. {{ppgblock|block=begin_ramp}} is [[#Time references &amp;amp; Sequence of the blocks: T0|referenced by default]] from the end of the previous block (or T0 if there is no previous block).  The transition block  {{ppgblock|block=trans14A}} and pulse block  {{ppgblock|block=pulse25}} are both within the loop, referenced to the {{ppgblock|block=begin_ramp}} [[#Automatic and user-defined time references|automatic time reference]]  {{timeref|ref=_TBEGRAMP}}. The {{ppgblock|block=end_ramp}} is referenced by default from the end of the previous block, i.e. from  the automatic time reference {{timeref|ref=_TEND_PULSE25}}.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[local:cpet:S]Titan_acq&amp;gt;ls /Equipment/Titan_acq/ppg_cycle_32                                                      &lt;br /&gt;
begin_ramp                      &lt;br /&gt;
trans14A                        &lt;br /&gt;
pulse25                         &lt;br /&gt;
end_ramp         &lt;br /&gt;
&lt;br /&gt;
[local:cpet:S]Titan_acq&amp;gt;ls /Equipment/Titan_acq/ppg_cycle_32/begin_loop1&lt;br /&gt;
time offset (ms)                20&lt;br /&gt;
loop count                      20&lt;br /&gt;
&lt;br /&gt;
[local:cpet:S]Titan_acq&amp;gt;ls /Equipment/Titan_acq/ppg_cycle_32/trans14a    &lt;br /&gt;
time offset (ms)                0&lt;br /&gt;
time reference                  _TBEGRAMP&lt;br /&gt;
ppg signal name                 CH14&lt;br /&gt;
&lt;br /&gt;
[local:cpet:S]Titan_acq&amp;gt;ls /Equipment/Titan_acq/ppg_cycle_32/pulse25 &lt;br /&gt;
time offset (ms)                0.003&lt;br /&gt;
time reference                  _TBEGRAMP&lt;br /&gt;
pulse width (ms)                0.003&lt;br /&gt;
ppg signal name                 CH25&lt;br /&gt;
&lt;br /&gt;
[local:cpet:S]Titan_acq&amp;gt;ls /Equipment/Titan_acq/ppg_cycle_32/end_loop2&lt;br /&gt;
time offset (ms)                1&lt;br /&gt;
time reference    &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Names Block ===&lt;br /&gt;
&lt;br /&gt;
This block has been defined for use with EBIT or CPET&#039;s custom web page. It is usually placed after a SKIP block at the end of the Block List. &lt;br /&gt;
&lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 80%; background-color: white;&amp;quot; border=&amp;quot;3&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|+ Table 16 :  Name Block&lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
!Parameter (ODB key name) !!Type !!Default!! Required/Optional !! Explanation&lt;br /&gt;
|- &lt;br /&gt;
|Names[32] || STRING[32] Array|| none || Optional|| User-defined names of PPG Signals for Custom Webpage. Array length should reflect number of PPG Output signals used (max 32).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Example 10: Name Block ===&lt;br /&gt;
The following example shows the names array for ebit experiment :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[local:ebit:R]/&amp;gt;ls &amp;quot;/Equipment/TITAN_ACQ/ppg_cycle_mode_1f/names&amp;quot;    &lt;br /&gt;
names&lt;br /&gt;
                                RFQ extraction&lt;br /&gt;
                                TSYBL:XCB4 (Default INJ)&lt;br /&gt;
                                EBIT Beam Line(SL,Q,Y:Default EXT)&lt;br /&gt;
                                (not connected) DT6 -- default high&lt;br /&gt;
                                BNG&lt;br /&gt;
                                flexible trigger&lt;br /&gt;
                                DT4 -- default low&lt;br /&gt;
                                extra XCB4&lt;br /&gt;
                                evap AFG trigger&lt;br /&gt;
                                not used -- evap cooling&lt;br /&gt;
                                DT4&lt;br /&gt;
                                not used -- afg sweep top&lt;br /&gt;
                                TITAN EC time stamp&lt;br /&gt;
                                flexible 1&lt;br /&gt;
                                flexible &lt;br /&gt;
                                flexible &lt;br /&gt;
&amp;lt;/pre&amp;gt;                      &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Blocks added automatically ===&lt;br /&gt;
Some blocks are (or may be) added automatically. &lt;br /&gt;
&lt;br /&gt;
* A pattern block at T0 is added to set all the inputs initially to zero. This block will be removed if the user defines a pattern or other transition block at T0.  So if the user does not want all inputs to be automatically set to zero when the PPG starts, a pattern block or transition must be added at T0.&lt;br /&gt;
* A halt operation is added at the end of the program.&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=File:PPG_page.png&amp;diff=7575</id>
		<title>File:PPG page.png</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=File:PPG_page.png&amp;diff=7575"/>
		<updated>2024-01-09T23:44:05Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=PPG_Building_Blocks&amp;diff=7574</id>
		<title>PPG Building Blocks</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=PPG_Building_Blocks&amp;diff=7574"/>
		<updated>2024-01-09T23:43:10Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: /* Automatic and user-defined time references */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Links =&lt;br /&gt;
&amp;lt;div style=&amp;quot;column-count:3;-moz-column-count:3;-webkit-column-count:3&amp;quot;&amp;gt;&lt;br /&gt;
* [[TITAN]] page&lt;br /&gt;
* [[TITAN DAQ General Documentation]]&lt;br /&gt;
* [[PPG ODB Block Structure]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
== Introduction ==&lt;br /&gt;
[[Image:PPG_page.png|250px|thumb|right|Example of PPG page showing user settings and preview of the timing scheme]] TITAN and other experiments use a Programmable Pulse Generator (PPG) to issue precise timing signals during their experiments. TITAN in particular require very flexible timing schemes, and users change these schemes often. A TITAN grad student initially implemented a way to program the PPGs via settings in an ODB directory. This concept has now been expanded and made more felxible and user-friendly. At the heart of the systems is a python-based compiler that converts the ODB settings into bytecode that the PPG hardware understands.&lt;br /&gt;
&lt;br /&gt;
This page explains the contents of the PPG Blocks stored in the ODB, how they are named and how they work.&lt;br /&gt;
&lt;br /&gt;
In general, the user does not need to know these details, as they are handled by the python/javascript provided in the [https://bitbucket.org/ttriumfdaq/cycling_framework/ cycling_framework].&lt;br /&gt;
&lt;br /&gt;
The structure of the user&#039;s PPG program is stored in the ODB as a set of sub-directories within {{Odbpath|path=/Equipment/PPGCompiler/Programming}}. The order of the sub-directories matters, as if no explicit &amp;quot;time reference&amp;quot; supplied, one block is assumed to start immediately after the previous one finishes. Sub-directories must be named according to the conventions listed in [[#Defined Block Types]]. Each sub-directory must have a unique name. The keys that must be present within each subdirectory are detailed below, and vary based on the block type (pulse, delay, loop etc).&lt;br /&gt;
&lt;br /&gt;
A python program (the PPG compiler, [https://bitbucket.org/ttriumfdaq/cycling_framework/src/master/ppg/ppg_compiler_fe.py ppg_compiler_fe.py]) runs as a midas frontend and converts the ODB structure into bytecode that can be loaded onto the PPG.&lt;br /&gt;
&lt;br /&gt;
== Compiler settings ==&lt;br /&gt;
&lt;br /&gt;
The compiler has some global settings in {{Odbpath|path=/Equipment/PPGCompiler/Settings}}:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Standard pulse width (ms)&#039;&#039; - see [[#Standard Pulse Widths]]&lt;br /&gt;
* &#039;&#039;PPG clock (MHz)&#039;&#039; - PPG clock frequency, so we can convert from ms to number of clock cycles&lt;br /&gt;
* &#039;&#039;Use external trigger&#039;&#039; - y/n for whether the PPG should use an external signal or a software command to start&lt;br /&gt;
* &#039;&#039;Use external clock&#039;&#039; - y/n for whether the PPG should use an external or internal clock&lt;br /&gt;
* &#039;&#039;Inverted channels bitmask&#039;&#039; - bitmask to invert output of any channels; not generally used&lt;br /&gt;
* &#039;&#039;Loadfile path&#039;&#039; - where to write the bytecode that is generated (note that the frontend can also ask for the bytecode to be sent to it directly, not via a written file)&lt;br /&gt;
* &#039;&#039;PPG uses pulseblaster - y/n for whether this is the older PulseBlaster PPG or newer TRIUMF PPG (as they have different bytecode requirements)&lt;br /&gt;
* &#039;&#039;Debug&#039;&#039; - y/n for whether to debug the compiler&lt;br /&gt;
* &#039;&#039;Compile at BOR&#039;&#039; - y/n for whether to automatically compile bytecode at begin-of-run (note that TITAN frontends ask the compiler themselves during their BOR transition, so this can safely be &#039;n&#039; for TITAN experiments)&lt;br /&gt;
* &#039;&#039;Enable extra 1-time BOR program&#039;&#039; - see [[#Begin-of-run program]]&lt;br /&gt;
* &#039;&#039;Wrap program in automatic loop&#039;&#039; - some experiments have very strict timing, and want to run the same program multiple times without delay. However, the user did not want to think about this as a loop in their own program. So we allow wrapping everything that the user provides in an automatic loop, and only ask the user how many time to run the loop before stopping. (In cycling_framework language, the user&#039;s code runs multiple times within a single cycle).&lt;br /&gt;
* &#039;&#039;Auto loop num iterations&#039;&#039; - if wrapping the user&#039;s program in an automatic loop, how many iterations to run.&lt;br /&gt;
* &#039;&#039;Record T0 offsets&#039;&#039; - y/n for whether to record timing offsets of each block in the ODB. This is useful for some experiments who need to know the time difference between 2 pulses for their analysis. Results are written to {{Odbpath|path=/Equipment/PPGCompiler/Computed/T0 offsets (ms)}}.&lt;br /&gt;
* &#039;&#039;Enable formulae&#039;&#039; - see [[#Specifying times with a formula]]&lt;br /&gt;
* &#039;&#039;Image path&#039;&#039; - legacy, for when webpage showing a static image of the cycle rather than an interactive plot&lt;br /&gt;
* &#039;&#039;Expanded image path&#039;&#039; - legacy, for when webpage showing a static image of the cycle rather than an interactive plot&lt;br /&gt;
&lt;br /&gt;
=== PPG clock ===&lt;br /&gt;
The internal clock of the PPG PulseBlaster (used on MPET) is determined by an on-board clock chip, which is removed when the PPG is run with an external clock. This is the case for MPET, where the PPG is clocked with an external 100MHz clock. It cannot be switched between internal and external clock by software.&lt;br /&gt;
&lt;br /&gt;
The PPG32 on the other hand can be switched between internal and external clock by software. It was designed to use a 20MHz internal or external clock, the actual frequency being programmed with divide-downs. The CPET PPG32 has been modified to use an external 100MHz clock (same clock as MPET). The EBIT PPG32 has not been modified, and currently runs with the internal clock programmed to produce 100MHz.&lt;br /&gt;
The maximum value supported by either board is 100MHz. &lt;br /&gt;
&lt;br /&gt;
The correct PPG Clock Frequency must be stored in the ODB at &amp;lt;code&amp;gt;/Equipment/PPGCompiler/Settings/PPG clock (MHz)&amp;lt;/code&amp;gt;, otherwise the timing of the output pulses will be incorrect, i.e.&lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 60%; background-color: white;&amp;quot; border=&amp;quot;0&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
! Input parameter name !! Value !! Type&lt;br /&gt;
|- &lt;br /&gt;
|PPG Clock (MHz)|| 100 || FLOAT &lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Standard Pulse Widths ===&lt;br /&gt;
Other values are defined (also in the  input parameter area) which the user can change as required:&lt;br /&gt;
&lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 60%; background-color: white;&amp;quot; border=&amp;quot;0&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
! Input parameter name !! Value !! Type&lt;br /&gt;
|-&lt;br /&gt;
| standard pulse width (ms)|| 0.005 ||   DOUBLE&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;standard pulse width&#039;&#039; is used by the STDPULSE blocks. Using a STDPULSE reduces the number of different delays that need to be generated to program the PPG.&lt;br /&gt;
&lt;br /&gt;
== Optional features ==&lt;br /&gt;
&lt;br /&gt;
=== Begin-of-run program ===&lt;br /&gt;
&lt;br /&gt;
It is possible to run an extra program once at the start of a run, before running the &amp;quot;normal&amp;quot; program. This may be useful for resetting scalers or similar.&lt;br /&gt;
&lt;br /&gt;
The begin-of-run program is enabled with the PPGCompiler setting &#039;Enable extra 1-time BOR program&#039;. The program itself is stored in {{Odbpath|path=/Equipment/PPGCompiler/Programming BOR}}&lt;br /&gt;
&lt;br /&gt;
=== Scanning parameters ===&lt;br /&gt;
&lt;br /&gt;
The cycling framework allows for time offsets and pulse widths to be scanned during a run. If scanning is enabled, the experiment&#039;s frontend code sets the relevant parameters in the ODB blocks, then asks the compiler to re-produce the bytecode.&lt;br /&gt;
&lt;br /&gt;
=== Specifying times with a formula ===&lt;br /&gt;
&lt;br /&gt;
By default, the user specifies actual numbers for the time offsets and pulse widths. However, by setting &#039;/Equipment/PPGCompiler/Settings/Enable formulae&#039; to true, the user may specify variables and formulae for the timings.&lt;br /&gt;
&lt;br /&gt;
User-specified variables are stored in the &#039;/Equipment/PPGCompiler/Programming/Formula variables&#039; directory. Formulae are stored in the &#039;time offset formula&#039; and &#039;pulse width formula&#039; keys of each PPG block. When the compiler is asked to re-compile the bytecode, it first evaluates the formulae, putting the results in the &#039;time offset (ms)&#039; and &#039;pulse width (ms)&#039; keys as appropriate. The rest of the compilation then proceeds as normal.&lt;br /&gt;
&lt;br /&gt;
Formula evaluation is done in the python code in a safe way (using Abstract Syntax Tree parsing with a whitelist of allowed functions/variables, rather than simply calling &#039;eval()&#039;).&lt;br /&gt;
&lt;br /&gt;
User-specified variables may be scanned during a run.&lt;br /&gt;
&lt;br /&gt;
=== Adding an automatic loop ===&lt;br /&gt;
&lt;br /&gt;
Normally we run the program specified by the user once per &amp;quot;cycle&amp;quot;. In the cycling framework this means we do: start the PPG -&amp;gt; wait for cycle to finish -&amp;gt; do some work in software -&amp;gt; start the PPG again. Sometimes users want to run a program multiple times without any software delay between cycles. This is easily achieved by just wrapping the entire program in a loop. However, sometimes users don&#039;t want the &amp;quot;visual noise&amp;quot; of seeing the actual loop. So we allow an &amp;quot;automatic loop&amp;quot; to be added by the compiler. The user never sees the definition of this loop, but just says how many times to run the program before we do a software delay (e.g. to read out data, increase scan values etc).&lt;br /&gt;
&lt;br /&gt;
Enabling the automatic loop is done with the &#039;/Equipment/PPGCompiler/Settings/Wrap program in automatic loop&#039; key, and the number of iterations to run each time we start the PPF is specified with the &#039;/Equipment/PPGCompiler/Settings/Auto loop num iterations&#039; key. &lt;br /&gt;
&lt;br /&gt;
=== Muting blocks ===&lt;br /&gt;
&lt;br /&gt;
Users may mute and unmute blocks to disable the output of a block without affecting the timing of a sequence. This is particularly useful for taking signal and background measurements with an RFQ pulse unmuted and muted, for example. Muted blocks appear with a red background on the webpage.&lt;br /&gt;
&lt;br /&gt;
The cycling framework includes the ability to automatically toggle between muted and unmuted states during a run. You could configure it to run N cycles with a pulse muted, then N cycles unmuted, then increase a scan value, and start running N cycles with a pulse muted again etc... Multiple pulses can be muted/unmuted at the same time, and with opposite polarities if desired.&lt;br /&gt;
&lt;br /&gt;
== Defined PPG Block Types ==&lt;br /&gt;
A number of fundamental building blocks (PPG Blocks) have been defined. Many act on one or more of the PPG Output signals. They are listed in Table 1 below. Click on each Block Type for more information.&lt;br /&gt;
 &lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 100%; background-color: white&amp;quot; border=&amp;quot;3&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|+ TABLE 1  List of Block Types acting on PPG signals&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
! Block Type * &amp;lt;br&amp;gt; (click on links for definitions)&lt;br /&gt;
! Explanation&lt;br /&gt;
! style=&amp;quot;text-align:left;color:#b300b3;font-style:italic;&amp;quot;|Example &amp;lt;br&amp;gt;Blockname&lt;br /&gt;
|- &lt;br /&gt;
|[[#Transition Block|&#039;&#039;&#039;TRA&#039;&#039;&#039;&#039;&#039;NS&#039;&#039;]]&lt;br /&gt;
| cause a channel &#039;&#039;&#039;transition&#039;&#039;&#039; (toggle between on and off, depending on the current state)&lt;br /&gt;
|style=&amp;quot;text-align:left;color:#b300b3;font-style:italic;&amp;quot;| TRANS_EX&lt;br /&gt;
|-&lt;br /&gt;
|[[#Turnon Block|&#039;&#039;&#039;TURNON&#039;&#039;&#039;]]&lt;br /&gt;
| ensure a channel is &#039;&#039;&#039;on&#039;&#039;&#039;&lt;br /&gt;
|style=&amp;quot;text-align:left;color:#b300b3;font-style:italic;&amp;quot;| TURNON_EX&lt;br /&gt;
|-&lt;br /&gt;
|[[#Turnoff Block|&#039;&#039;&#039;TURNOFF&#039;&#039;&#039;]]&lt;br /&gt;
| ensure a channel is &#039;&#039;&#039;off&#039;&#039;&#039;&lt;br /&gt;
|style=&amp;quot;text-align:left;color:#b300b3;font-style:italic;&amp;quot;| TURNOFF_EX&lt;br /&gt;
|-&lt;br /&gt;
|[[#Pulse Block|&#039;&#039;&#039;PUL&#039;&#039;&#039;&#039;&#039;SE&#039;&#039;]]&lt;br /&gt;
|a &#039;&#039;&#039;pulse&#039;&#039;&#039; of user-defined width&lt;br /&gt;
|style=&amp;quot;text-align:left;color:#b300b3;font-style:italic;&amp;quot;|pulse_dac&lt;br /&gt;
|- &lt;br /&gt;
|[[#Multi Pulse Block|&#039;&#039;&#039;MUL&#039;&#039;&#039;&#039;&#039;TI&#039;&#039;]]&lt;br /&gt;
|multiple &#039;&#039;&#039;pulses&#039;&#039;&#039; on the same channel a fixed time apart&lt;br /&gt;
|style=&amp;quot;text-align:left;color:#b300b3;font-style:italic;&amp;quot;|multi_dac&lt;br /&gt;
|- &lt;br /&gt;
|[[#Stdpulse Block|&#039;&#039;&#039;STD&#039;&#039;&#039;&#039;&#039;PULSE&#039;&#039;]]&lt;br /&gt;
|  a &#039;&#039;&#039;pulse&#039;&#039;&#039; of a standard width&lt;br /&gt;
|style=&amp;quot;text-align:left;color:#b300b3;font-style:italic;&amp;quot;|stdpulse_5&lt;br /&gt;
|-&lt;br /&gt;
|[[#Pattern Block|&#039;&#039;&#039;PAT&#039;&#039;&#039;&#039;&#039;TERN]]&lt;br /&gt;
| sets a &#039;&#039;&#039;bit pattern&#039;&#039;&#039;&lt;br /&gt;
|style=&amp;quot;text-align:left;color:#b300b3;font-style:italic;&amp;quot;|PatFF0E&lt;br /&gt;
|-&lt;br /&gt;
|[[#Delay Block|&#039;&#039;&#039;DEL&#039;&#039;&#039;&#039;&#039;AY]]&lt;br /&gt;
|&#039;&#039;&#039;Delay&#039;&#039;&#039; for a time with existing bit pattern unchanged&lt;br /&gt;
|style=&amp;quot;text-align:left;color:#b300b3;font-style:italic;&amp;quot;|DEL10&lt;br /&gt;
|-&lt;br /&gt;
|[[#Time Reference Block|&#039;&#039;&#039;TIM&#039;&#039;&#039;&#039;&#039;E_REF]]&lt;br /&gt;
| defines a time reference from which other blocks can be offset&lt;br /&gt;
|style=&amp;quot;text-align:left;color:#b300b3;font-style:italic;&amp;quot;|timDacStart&lt;br /&gt;
|-&lt;br /&gt;
|[[#Begin Loop Block|&#039;&#039;&#039;BEGIN&#039;&#039;&#039;&#039;&#039;_LOOP]]&lt;br /&gt;
|&#039;&#039;&#039;begin&#039;&#039;&#039; a loop&lt;br /&gt;
|style=&amp;quot;text-align:left;color:#b300b3;font-style:italic;&amp;quot;|Begin_loop5&lt;br /&gt;
|-&lt;br /&gt;
|[[#End Loop Block|&#039;&#039;&#039;END&#039;&#039;&#039;&#039;&#039;_LOOP]]&lt;br /&gt;
|rowspan=&amp;quot;1&amp;quot;|&#039;&#039;&#039;end&#039;&#039;&#039; a loop&lt;br /&gt;
|style=&amp;quot;text-align:left;color:#b300b3;font-style:italic;&amp;quot; |End_loop5&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== PPG Signal Names ==&lt;br /&gt;
PPG Signal Names are &#039;&#039;&#039;required&#039;&#039;&#039; in PULSE, MULTI and TRANS PPG blocks. These blocks have a parameter &#039;&#039;PPG signal name&#039;&#039; which expects one of the defined PPG signal names, which are of the form &amp;quot;CH1&amp;quot;, &amp;quot;CH2&amp;quot; etc (for channel 1/2). This name defines which PPG Output Channel is to be acted on by the PULSE or TRANS PPG block.  Note that the PATTERN block acts on a bit pattern, not PPG signal names. For example,  0x2000 (EBIT) will act on PPG signal name TDCBLOCK (Channel 14).  Setting a pattern of 0xFFFF will set all 32 outputs ON.&lt;br /&gt;
&lt;br /&gt;
The user is able to specify human-readable names for each channel in the ODB at {{Odbpath|path=/Equipment/PPGCompiler/Programming/names}}.&lt;br /&gt;
&lt;br /&gt;
== Time references &amp;amp; Sequence of the blocks: T0  ==&lt;br /&gt;
The time when the PPG starts running is defined as &#039;&#039;&#039;T0&#039;&#039;&#039;. All blocks are ultimately referenced in time to T0, and they will be sorted (by the ppg compiler) in order of time offset from T0  before processing into the PPG load file.&lt;br /&gt;
&lt;br /&gt;
The ordering of the blocks is significant:&lt;br /&gt;
&lt;br /&gt;
* If a block does not specify a time reference, it we default to starting as soon as the block before it ends.&lt;br /&gt;
* If a block appears between a begin_ and end_ of a loop, it will be part of that loop. Blocks within a loop may not use a time reference of a block outside the loop.&lt;br /&gt;
&lt;br /&gt;
== Automatic and user-defined time references ==&lt;br /&gt;
Blocks automatically define at least one time reference. Variable-length blocks such as pulses and loops automatically define time references at the start and end of the block. Blocks such as transitions and patterns automatically define only one time reference since the start and end are identical.&lt;br /&gt;
&lt;br /&gt;
Users can also define a time reference, using a [[#Time Reference Block]]. This provides a way to synchronize several blocks to start at one time, or to produce a delay before the next block if relying on the default time reference.&lt;br /&gt;
&lt;br /&gt;
The automatic time reference names for variable-length blocks are of the form &amp;quot;_TSTART_&amp;lt;blockname&amp;gt;, &amp;quot;_TEND_&amp;lt;blockname&amp;gt;. For other blocks, they are mostly of the form  &amp;quot;_T&amp;lt;blockname&amp;gt;&amp;quot; .&lt;br /&gt;
They are shown below in Table 3 for each of the defined blocks. &lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 100%; background-color: white&amp;quot; border=&amp;quot;3&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|+ TABLE 3  Automatically generated time references for each block&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
! Block Type&lt;br /&gt;
! Example &amp;lt;br&amp;gt; Blockname&lt;br /&gt;
! Automatically defined &amp;lt;br&amp;gt; time reference names&lt;br /&gt;
! Example time&amp;lt;br&amp;gt; references&lt;br /&gt;
|- &lt;br /&gt;
|[[#Transition Block|Trans]]ition&lt;br /&gt;
| TRANS_EX&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;| _T&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;block name&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_T&amp;lt;span style=color:black&amp;gt;TRANS_EX&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|[[#Turnon Block|Turnon]]&lt;br /&gt;
| TURNON_EX&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;| _T&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;block name&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_T&amp;lt;span style=color:black&amp;gt;TURNON_EX&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|[[#Turnoff Block|Turnon]]&lt;br /&gt;
| TURNOFF_EX&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;| _T&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;block name&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_T&amp;lt;span style=color:black&amp;gt;TURNOFF_EX&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|[[#Pulse Block|Pulse]]&lt;br /&gt;
|style=&amp;quot;color:black&amp;quot;|pulse_dac&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_TSTART_&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;block name&amp;gt;&amp;lt;/span&amp;gt;,&amp;lt;br&amp;gt; _TEND_&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;block name&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
|style=&amp;quot;color:#7733ff&amp;quot;|_TSTART_&amp;lt;span style=color:black&amp;gt;pulse_dac&amp;lt;/span&amp;gt;&amp;lt;br&amp;gt;_TEND_&amp;lt;span style=color:black&amp;gt;pulse_dac&amp;lt;/span&amp;gt;&lt;br /&gt;
|- &lt;br /&gt;
|[[#Multi Pulse Block|Multi]]&lt;br /&gt;
|style=&amp;quot;color:black&amp;quot;|multi_dac&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_TSTART_&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;block name&amp;gt;&amp;lt;/span&amp;gt;,&amp;lt;br&amp;gt; _TEND_&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;block name&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
|style=&amp;quot;color:#7733ff&amp;quot;|_TSTART_&amp;lt;span style=color:black&amp;gt;multi_dac&amp;lt;/span&amp;gt;&amp;lt;br&amp;gt;_TEND_&amp;lt;span style=color:black&amp;gt;multi_dac&amp;lt;/span&amp;gt;&lt;br /&gt;
|- &lt;br /&gt;
|[[#Stdpulse Block|Stdpulse]]&lt;br /&gt;
|stdpulse_5&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_TSTART_&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;block name&amp;gt;&amp;lt;/span&amp;gt;,&amp;lt;br&amp;gt; _TEND_&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;block name&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
|style=&amp;quot;color:#7733ff&amp;quot;| _TSTART_&amp;lt;span style=color:black&amp;gt;stdpulse_5&amp;lt;/span&amp;gt;&amp;lt;br&amp;gt;_TEND_&amp;lt;span style=color:black&amp;gt;stdpulse_5&amp;lt;/span&amp;gt;&lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
|[[#Pattern Block|Pattern]]&lt;br /&gt;
|PatFF0E&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_T&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;block name&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
|style=&amp;quot;color:#7733ff&amp;quot;|_T&amp;lt;span style=&amp;quot;color:black&amp;quot;&amp;gt;PatFF0E&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|[[#Delay Block|Delay]]&lt;br /&gt;
|DEL10&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;| _T&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;block name&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_T&amp;lt;span style=color:black&amp;gt;DEL10&amp;lt;/span&amp;gt;&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
|[[#Time Reference Block|Time_Ref]]erence&lt;br /&gt;
|timDacStart&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;| _T&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;block name&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_T&amp;lt;span style=color:black&amp;gt;timDacStart&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|[[#Begin Loop Block|BEGIN_LOOP]]&lt;br /&gt;
|Begin_loop5&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_TBEG&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;loop name&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_TBEG&amp;lt;span style=color:black&amp;gt;loop5&amp;lt;/span&amp;gt;&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
|[[#End Loop Block|END_LOOP]]&lt;br /&gt;
|rowspan=&amp;quot;2&amp;quot; |End_loop5&lt;br /&gt;
|rowspan=&amp;quot;1&amp;quot; style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_TEND&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;loop name&amp;gt;&amp;lt;/span&amp;gt;_ONE&lt;br /&gt;
|rowspan=&amp;quot;1&amp;quot; style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_TEND&amp;lt;span style=color:black&amp;gt;loop5_ONE&amp;lt;/span&amp;gt;&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
|style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;|_TEND&amp;lt;span style=&amp;quot;color:black;&amp;quot;&amp;gt;&amp;lt;loop name&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
|rowspan=&amp;quot;1&amp;quot; style=&amp;quot;color:#7733ff;font-style:italic;&amp;quot;| _TEND&amp;lt;span style=color:black&amp;gt;loop5&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Definitions of PPG Blocks ==&lt;br /&gt;
=== Time Reference Block ===&lt;br /&gt;
The PPG time zero (T0) is defined as the time when the PPG starts running after receiving a start signal (either software or hardware). All blocks are offset ultimately from T0.  The time reference T0 is defined &#039;&#039;&#039;automatically&#039;&#039;&#039;. A number of other time-references are defined automatically - see [[#Automatic and user-defined time references]]. &lt;br /&gt;
&lt;br /&gt;
The user may define other time references for convenience, using a &#039;&#039;TIME_REF&#039;&#039; PPG Block. User-defined time references, like automatic time references, can be used as time references for later PPG Blocks.  A time reference block may define a reference from T0 or from any previously defined time reference. &lt;br /&gt;
&lt;br /&gt;
When a TIME_REF Block is defined, the &#039;&#039;&#039;name&#039;&#039;&#039; of the time reference it defines is generated automatically. It is derived from the TIME_REF Block Name as indicated in [[#Automatic and user-defined time references|Table 3]], by adding the prefix &#039;&#039;_T&#039;&#039;. See [[#example 1]] below.&lt;br /&gt;
&lt;br /&gt;
Figure 1 shows two time references, T1 and T2, defined by the user using two time reference blocks. &lt;br /&gt;
[[Image:Timeref.png|frame|center|Figure 1: Defining a Time Reference]]&lt;br /&gt;
&amp;lt;br clear=all&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Time reference blocks take the following parameters (Table 4):&lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 80%; background-color: white;&amp;quot; border=&amp;quot;3&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|+ Table 4 :  Time Ref Block Parameters&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
!ODB Key Name !! Type !! Default Value !! Required/Optional&lt;br /&gt;
|-&lt;br /&gt;
|time offset (ms) || DOUBLE 	|| 0  || Optional&lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
|time reference 	 || STRING[20] ||	end of previous block || Optional&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
All &#039;&#039;TIME_REF&#039;&#039; blocks in ODB must have the first 3 letters  &amp;quot;tim&amp;quot;, e.g. {{ppgblock|block=TIME_2}}, t{{ppgblock|block=ime_reference_define_t3}}, {{ppgblock|block=Time1}} are all acceptable. The block names must be unique, since no two time references can have the same name.  Both parameters are optional. If not supplied, the default values will be used.&lt;br /&gt;
&lt;br /&gt;
==== Example 1: Time Reference Blocks ====&lt;br /&gt;
&lt;br /&gt;
The time references in Figure 1 (above) could be defined as PPG Blocks {{ppgblock|block=time_t1}}   and  {{ppgblock|block=time_t2}}, where {{ppgblock|block=time_t1}}  is referenced to T0, and automatically defines the time reference {{timeref|ref=_TTIME_T1}} (see [[#Automatic and user-defined time references|Table 3]]).  PPG Time Reference block {{ppgblock|block=time_t2}} is then referenced to  {{timeref|ref=_TTIME_T1}} i.e. &lt;br /&gt;
 $ odbedit&amp;gt;&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt;cd &amp;quot;/Equipment/Titan_acq/ppg cycle&amp;quot;&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt;ls ppg_cycle&lt;br /&gt;
    time_t1&lt;br /&gt;
    time_t2&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt;ls &amp;quot;ppg_cycle/time_t1&amp;quot; -lt&lt;br /&gt;
   time offset (ms)        0.25&lt;br /&gt;
   time reference          T0&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt;ls &amp;quot;ppg_cycle/time_t2&amp;quot; -lt&lt;br /&gt;
   time offset (ms)        0.75&lt;br /&gt;
   time reference       _TTIME_T1&lt;br /&gt;
Alternatively, {{ppgblock|block=time_t1}} could be referenced back to time T0, i.e.&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt;ls &amp;quot;ppg_cycle/time_t2&amp;quot; -lt&lt;br /&gt;
   time offset (ms)        1.0&lt;br /&gt;
   time reference          T0&lt;br /&gt;
If these were the only blocks present, it would not be necessary to specify the time references in the first example, because by default each block is time-referenced from the previous block.  The second example must include the time reference, because the time offset given is from T0, not from the previous block.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Transition Block ===&lt;br /&gt;
This block reverses the state of an output signal (Figure 2). Two transition blocks on the same PPG output signal is equivalent to a [[#Pulse Block]].&lt;br /&gt;
&lt;br /&gt;
[[Image:Trans.png|frame|center|Figure 2: Two Transitions]]&lt;br /&gt;
&amp;lt;br clear=all&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Transition blocks take the following parameters (Table 5):&lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 80%; background-color: white;&amp;quot; border=&amp;quot;3&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|+ Table 5 :  Transition Block Parameters&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
!ODB Key Name !! Type !! Default Value !! Required/Optional&lt;br /&gt;
|-&lt;br /&gt;
|time offset (ms) || DOUBLE 	|| 0  || Optional&lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
|time reference 	 || STRING[20] ||	end of previous block || Optional&lt;br /&gt;
|-&lt;br /&gt;
| ppg signal name  || STRING[15] ||	no default; must be supplied || Required&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
A Transition block automatically defines a &#039;&#039;time reference&#039;&#039; to the time when the transition occurs. This time reference may be used by subsequent blocks as their time reference. The name of the time reference is derived from the block&#039;s name by adding the prefix &#039;&#039;_T&#039;&#039;, so that a block named {{ppgblock|block=TRANS_tdc4}} will define a time reference {{timeref|ref=_TTRANS_TDC4}}.&lt;br /&gt;
TRANSITION  blocks must have unique names, with first 3 letters being &#039;&#039;&#039;TRA&#039;&#039;&#039;, e.g. {{ppgblock|block=TRANS_2}}, {{ppgblock|block=transition_RFGATE1}}, {{ppgblock|block=TraX}} are all acceptable.&lt;br /&gt;
&lt;br /&gt;
==== Example 2: Transition Block ====&lt;br /&gt;
This example shows a transition block with blockname  {{ppgblock|block=TRANS_5}}&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt; cd &amp;quot;/Equipment/Titan_acq/ppg cycle&amp;quot;&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt; ls trans5&lt;br /&gt;
         time offset (ms)                100&lt;br /&gt;
         time reference                  T0&lt;br /&gt;
         ppg signal name                 RFGATE2&lt;br /&gt;
&lt;br /&gt;
This example reverses the state of the PPG output signal &amp;quot;RFGATE2&amp;quot; at an offset of 100ms from T0. A time reference  {{timeref|ref=_TTRANS_5}} for this transition is automatically defined.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Turnon Block ===&lt;br /&gt;
This is exactly the same as a [[#Transition Block]], but ensures that a channel is ON (rather than toggling between on/off). If the channel was already on, the block has no effect (but can still be used as a time reference for other blocks).&lt;br /&gt;
&lt;br /&gt;
=== Turnoff Block ===&lt;br /&gt;
This is exactly the same as a [[#Transition Block]], but ensures that a channel is OFF (rather than toggling between on/off). If the channel was already off, the block has no effect (but can still be used as a time reference for other blocks).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Pulse Block ===&lt;br /&gt;
This block defines a pulse of user-defined width. Figure 3 shows two pulses, one offset from T0, one offset from time reference T1. The state of the PPG output signal will be reversed for the pulse width duration.&lt;br /&gt;
Two [[#Transition Block]]s could perform the same function as a pulse block.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Pulse.png|frame|center|Figure 3: Pulses]]&lt;br /&gt;
&amp;lt;br clear=all&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pulse&#039;&#039;&#039; blocks take the following parameters (Table 6):&lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 80%; background-color: white;&amp;quot; border=&amp;quot;3&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|+ Table 6 :  Pulse Block Parameters&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
!ODB Key Name !! Type !! Default Value !! Required/Optional&lt;br /&gt;
|-&lt;br /&gt;
|time offset (ms) || DOUBLE 	|| 0  || Optional&lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
|time reference 	 || STRING[20] ||	end of previous block || Optional&lt;br /&gt;
|- &lt;br /&gt;
| pulse width (ms)  || DOUBLE || minimal delay || Optional&lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
| ppg signal name  || STRING[15] ||	no default; must be supplied || Required&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
A Pulse block automatically defines two &#039;&#039;&#039;time references&#039;&#039;&#039;; one to the time when the pulse starts, the second to the time when pulse ends. This time reference may be used by subsequent blocks as their time reference. The name of the time reference is derived from the block&#039;s name by adding the prefixes &amp;quot;_TSTART_&amp;quot; and &amp;quot;_TEND_&amp;quot; so that a pulse block named {{ppgblock|block=PULSE_TDC}} will define the time references {{timeref|ref=_TSTART_PULSE_TDC}} and {{timeref|ref=_TEND_PULSE_TDC}}.&lt;br /&gt;
PULSE blocks must have unique names, with first 3 letters being &#039;&#039;&#039;PUL&#039;&#039;&#039;, e.g. {{ppgblock|block=PULSE_2}}, {{ppgblock|block=pulse_RFGATE1}}, {{ppgblock|block=PulX}} are all acceptable.&lt;br /&gt;
&lt;br /&gt;
==== Example 3: Pulse Block ====&lt;br /&gt;
This example shows a pulse block with blockname  {{ppgblock|block=PULSE_3}}&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt; cd &amp;quot;/Equipment/Titan_acq/ppg cycle&amp;quot;&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt; ls pulse3&lt;br /&gt;
         time offset (ms)                0.05&lt;br /&gt;
         time reference                  _TTRANS_5&lt;br /&gt;
         ppg signal name                 RFTRIG1&lt;br /&gt;
         pulse width (ms)                0.005&lt;br /&gt;
&lt;br /&gt;
This example reverses the state of the PPG output signal &amp;quot;RFTRIG1&amp;quot; at an offset of 0.05ms from time reference  {{timeref|ref=_TTRANS_5}} for a time of 0.005ms. It is assumed that  {{timeref|ref=_TTRANS_5}} has been defined by the transition block in Example 2.  A time references  {{timeref|ref=_TSTART_PULSE3}} and {{timeref|ref=_TEND_PULSE3}} for this pulse will be defined automatically.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multi Pulse Block ===&lt;br /&gt;
This block defines a sequence of multiple pulses of user-defined width and a user-defined period. It simplifies programming if you need multiple periodic pulses, but a LOOP isn&#039;t appropriate (e.g. because a LOOP affects all channels, and you only need periodic output on one channel while the others to non-periodic things).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Multi&#039;&#039;&#039; pulse blocks take the following parameters (Table 7):&lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 80%; background-color: white;&amp;quot; border=&amp;quot;3&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|+ Table 7 :   Multi Pulse Block Parameters&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
!ODB Key Name !! Type !! Default Value !! Required/Optional&lt;br /&gt;
|-&lt;br /&gt;
|time offset (ms) || DOUBLE 	|| 0  || Optional&lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
|time reference 	 || STRING[20] ||	end of previous block || Optional&lt;br /&gt;
|- &lt;br /&gt;
| pulse width (ms)  || DOUBLE || minimal delay || Optional&lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
| ppg signal name  || STRING[15] ||	no default; must be supplied || Required&lt;br /&gt;
|- &lt;br /&gt;
| rep count  || INTEGER || no default; must be supplied || Required&lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
| delay between reps (ms)  || DOUBLE ||	no default; must be supplied || Required&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note that &amp;quot;delay between reps&amp;quot; is the time between the START of each pulse, not the time between the end of one pulse and the start of the next!&lt;br /&gt;
&lt;br /&gt;
A Pulse block automatically defines two &#039;&#039;&#039;time references&#039;&#039;&#039;; one to the time when the FIRST pulse starts, the second to the time when the LAST pulse ends. These time references may be used by subsequent blocks as their time reference. The name of the time reference is derived from the block&#039;s name by adding the prefixes &amp;quot;_TSTART_&amp;quot; and &amp;quot;_TEND_&amp;quot; so that a multi-pulse block named {{ppgblock|block=MULTI_TDC}} will define the time references {{timeref|ref=_TSTART_MULTI_TDC}} and {{timeref|ref=_TEND_MULTI_TDC}}.&lt;br /&gt;
Multi-pulse blocks must have unique names, with first 3 letters being &#039;&#039;&#039;MUL&#039;&#039;&#039;, e.g. {{ppgblock|block=MULTI_2}}, {{ppgblock|block=multi_RFGATE1}}, {{ppgblock|block=MulX}} are all acceptable.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Stdpulse Block ===&lt;br /&gt;
&lt;br /&gt;
This block defines a pulse of standard width ([[#Pulse Block|Figure 3)]]. A Stdpulse Block is the same as a [[#Pulse Block]] except the width is a fixed value which is defined in the odb (see [[#Standard Pulse Widths]]). The state of the output signal will be reversed for the pulse width duration. &lt;br /&gt;
&lt;br /&gt;
Stdpulse blocks take the following parameters (Table 8):&lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 80%; background-color: white;&amp;quot; border=&amp;quot;3&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|+ Table 8 :  Pulse Block Parameters&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
!ODB Key Name !! Type !! Default Value !! Required/Optional&lt;br /&gt;
|-&lt;br /&gt;
|time offset (ms) || DOUBLE 	|| 0  || Optional&lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
|time reference 	 || STRING[20] ||	end of previous block || Optional&lt;br /&gt;
|-  &lt;br /&gt;
| ppg signal name  || STRING[15] ||	no default; must be supplied || Required&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Example 4: Standard Pulse Block ====&lt;br /&gt;
This example shows a standard pulse block with blockname  {{ppgblock|block=STDPULSE1}}&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt; cd &amp;quot;/Equipment/Titan_acq/ppg cycle&amp;quot;&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt; ls stdpulse1&lt;br /&gt;
         time offset (ms)                3.4&lt;br /&gt;
         time reference                  T0&lt;br /&gt;
         ppg signal name                 CH5&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This example reverses the state of the PPG output signal &amp;quot;CH5&amp;quot; at an offset of 3.4ms from time reference  {{timeref|ref=T0}} for a time given by the [[#Standard Pulse Widths|standard pulse width]]. Time references  {{timeref|ref=_TSTART_STDPULSE1}} and {{timeref|ref=_TEND_STDPULSE1}} for this pulse will be defined automatically.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Pattern Block ===&lt;br /&gt;
This block allows the user to set the PPG output signals to a &#039;&#039;&#039;bit pattern&#039;&#039;&#039;. It is be useful for example to set all the bits to zero at the end of the ppg cycle. Instead of 15 transition blocks, one pattern block could be used. Pattern blocks take the following parameters (Table 9):&lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 80%; background-color: white;&amp;quot; border=&amp;quot;3&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|+ Table 9 :  Pattern Block Parameters&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
!ODB Key Name !! Type !! Default Value !! Required/Optional&lt;br /&gt;
|-&lt;br /&gt;
|time offset (ms) || DOUBLE 	|| 0  || Optional&lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
|time reference 	 || STRING[20] ||	end of previous block || Optional&lt;br /&gt;
|-  &lt;br /&gt;
| bit pattern  || DWORD ||	no default; must be supplied || Required&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Example 5: Pattern Block ====&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt; cd &amp;quot;/Equipment/Titan_acq/ppg cycle&amp;quot;&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt; ls pattern_test -h&lt;br /&gt;
    time offset (ms)                120&lt;br /&gt;
   time reference                  T0&lt;br /&gt;
   bit pattern                     0xF0F0&lt;br /&gt;
&lt;br /&gt;
This example sets the PPG output signals to the bit pattern shown 120ms after [[#Time references &amp;amp; Sequence of the blocks: T0|T0]].  The time reference  {{timeref|ref=_TPATTERN_TEST}} will be defined automatically.&lt;br /&gt;
&lt;br /&gt;
=== Delay Block ===&lt;br /&gt;
This block allows the user to maintain a &#039;&#039;&#039;bit pattern&#039;&#039;&#039; for a certain amount of time. It may be useful when programming loops, which sometimes need a minimal delay as a separator.&lt;br /&gt;
Delay blocks take the following parameters (Table 10):&lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 80%; background-color: white;&amp;quot; border=&amp;quot;3&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|+ Table 10 :  Delay Block Parameters&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
!ODB Key Name !! Type !! Default Value !! Required/Optional&lt;br /&gt;
|-&lt;br /&gt;
|time offset (ms) || DOUBLE 	|| 0  || Required??  &lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
|time reference 	 || STRING[20] ||	end of previous block || Optional&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
The length of the delay is given by the time offset parameter.&lt;br /&gt;
&lt;br /&gt;
==== Example 6: Delay Block ====&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt; cd &amp;quot;/Equipment/Titan_acq/ppg cycle&amp;quot;&lt;br /&gt;
 [local:test]TITAN_ACQ&amp;gt; ls delay_eoc &lt;br /&gt;
   time offset (ms)                1.5&lt;br /&gt;
   time reference                  _TENDSCLR&lt;br /&gt;
&lt;br /&gt;
This example provides a delay of 1.5ms after the end of the SCLR loop (referenced from {{timeref|ref=_TENDSCLR}}). The bit pattern remains unchanged.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Begin Loop Block ===&lt;br /&gt;
This block is the start of a loop. A loop name must be provided (i.e. BEGIN &amp;lt;loopname&amp;gt;). It MUST occur in the [[#Naming PPG Blocks|Block List]] BEFORE its associated END &amp;lt;loopname&amp;gt; block.&lt;br /&gt;
Every BEGIN &amp;lt;loopname&amp;gt; block must have an associated END &amp;lt;loopname&amp;gt; block. The loop name must be unique for each loop in the block list. Every BEGIN &amp;lt;loopname&amp;gt; block must have an associated END &amp;lt;loopname&amp;gt; block. The loop name must be unique for each loop in the block list.&lt;br /&gt;
&lt;br /&gt;
Begin Loop blocks take the following parameters (Table 11):&lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 80%; background-color: white;&amp;quot; border=&amp;quot;3&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|+ Table 11 :  Begin  Block Parameters&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
!ODB Key Name !! Type !! Default Value !! Required/Optional&lt;br /&gt;
|-&lt;br /&gt;
|time offset (ms) || DOUBLE 	|| 0  || Optional &lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
|time reference 	 || STRING[20] ||	end of previous block || Optional&lt;br /&gt;
|-&lt;br /&gt;
|loop count || INT || 1 || Required &lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
User must name BEGIN LOOP blocks in ODB with a unique loop name.  The first 5 letters must be &amp;quot;begin&amp;quot;, e.g. {{ppgblock|block=BEGIN_2, begin_loop0, Begin_hvlooping}} are all acceptable.  The loop name (which is required in the PPG file sent to the compiler) will be taken from the block name by stripping off the letters &amp;quot;BEGIN_&amp;quot;, e.g.  {{ppgblock|block=begin_hvlooping}} would have &amp;quot;hvlooping&amp;quot; as the loop name.&lt;br /&gt;
&lt;br /&gt;
=== Time Reference within the loop ===&lt;br /&gt;
All transitions within a loop should use the begin_loop time reference (L1 in Figure 4), or the end of a variable pulse within the loop. They should not use the T0 reference. &lt;br /&gt;
&lt;br /&gt;
=== End Loop Block ===&lt;br /&gt;
This block ends a loop. The &amp;lt;loopname&amp;gt; must be provided, matching that of the BEGIN &amp;lt;loopname&amp;gt;.  Every END &amp;lt;loopname&amp;gt; block must have an associated BEGIN &amp;lt;loopname&amp;gt; block. The loop name must be unique for each loop in the block list. END_LOOP blocks in ODB  are named with the first 3 letters being &amp;quot;end&amp;quot;, and the rest matching the begin loop block name. e.g.  {{ppgblock|block=END_2, end_loop0, End_start}} are all acceptable provided there exists a block named  {{ppgblock|block=BEGIN_2, begin_loop0}} or  {{ppgblock|block=begin_start}}.&lt;br /&gt;
&lt;br /&gt;
In Figure 4, the time reference for the begin loop occurs at label &amp;quot;L1&amp;quot;. This time reference would actually be called {{timeref|ref=_TBEG&amp;lt;loopname&amp;gt;}}, where loopname is the name of the loop.&lt;br /&gt;
&lt;br /&gt;
[[Image:Loop.png|frame|center|Figure 4: Diagram of a Loop]]&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;	&lt;br /&gt;
&lt;br /&gt;
The END &amp;lt;loopname&amp;gt; block MUST occur in the list of blocks in the ODB AFTER its associated BEGIN &amp;lt;loopname&amp;gt; block. &lt;br /&gt;
The time offset of the END block is assumed to be the end of the first loop (or if not supplied, is assumed to be at the end of the previous block.  Note that loops can be nested, but two END blocks must be separated by at least a minimal delay. This is also true for two BEGIN blocks. &lt;br /&gt;
&lt;br /&gt;
The automatic time-references generated are  {{timeref|ref=_TEND_&amp;lt;blockname&amp;gt;_ONE}} (at the end of ONE loop) and {{timeref|ref= _TEND_&amp;lt;blockname&amp;gt;}} is at the end of ALL loops (as calculated by the configuration program).  This time is shown as &amp;quot;E0&amp;quot; in Figure 4.  The time between the end of one loop and the end of all loops is designated the &amp;quot;RESERVED&amp;quot; time. Transitions occurring within the first loop are assumed to be within the loop - any transitions occurring within the &amp;quot;reserved&amp;quot; time during which the rest of the loops will be running is not allowed, and an error message will occur. Therefore do not use {{timeref|ref=_TEND_&amp;lt;blockname&amp;gt;_ONE}} as a time reference for another pulse or transition, or that transition may be in the reserved time, generating an error. {{timeref|ref=_TEND_&amp;lt;blockname&amp;gt;}} is generated for debugging purposes only.&lt;br /&gt;
&lt;br /&gt;
;NOTE: Users must be careful when ending a loop directly following a transition if [[#TDBLOCK pulses]] are enabled. In that case, transitions generate automatic TDCBLOCK pulses whose trailing edge follows a transition, but which do not generate automatic time references. Therefore a delay must be added by the user between a transition and the end loop block, to allow time for the TDCBLOCK pulse, otherwise the trailing edge of the TDCBLOCK pulse will occur during the reserved time, generating an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
End Loop blocks take the following parameters (Table 12):&lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 80%; background-color: white;&amp;quot; border=&amp;quot;3&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|+ Table 12 :  End  Block Parameters&lt;br /&gt;
|- style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
!ODB Key Name !! Type !! Default Value !! Required/Optional&lt;br /&gt;
|-&lt;br /&gt;
|time offset (ms) || DOUBLE 	|| 0  || Optional &lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: whitesmoke; font-weight: normal;&amp;quot;&lt;br /&gt;
|time reference 	 || STRING[20] ||	end of previous block || Optional&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For non-nested loops, the END&amp;lt;loopname&amp;gt; block should use the time-reference defined by the equivalent &amp;quot;BEGIN&amp;lt;loopname&amp;gt;&amp;quot; block (or one of the time-references defined within the loop). For nested loops, the time reference should be from the end of an inner loop.&lt;br /&gt;
 &lt;br /&gt;
An END&amp;lt;loopname&amp;gt; block automatically defines a time reference equivalent to the BEGIN&amp;lt;loopname&amp;gt; parameter. For example, if the BEGIN&amp;lt;loopname&amp;gt; defined {{timeref|ref=_TBEGL0}} the END&amp;lt;loopname&amp;gt; automatically defines {{timeref|ref=_TENDL0}}. This value is a time reference to the end of ALL the loops.&lt;br /&gt;
So placing transitions after the end of all loops is easy using {{timeref|ref=_TENDL0}} as the reference.&lt;br /&gt;
Any other transitions occuring within the time taken for all the loops is flagged as an error.&lt;br /&gt;
&lt;br /&gt;
==== Example 6: A Loop using PPG Blocks ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#e600e6; font-style:italic&amp;quot;&amp;gt;end_ramp&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following example shows the PPG Blocks making up a loop. The Blocks  {{ppgblock|block=begin_ramp}} and  {{ppgblock|block=end_ramp}} are the begin and end of the loop named &amp;quot;ramp&amp;quot;. {{ppgblock|block=begin_ramp}} is [[#Time references &amp;amp; Sequence of the blocks: T0|referenced by default]] from the end of the previous block (or T0 if there is no previous block).  The transition block  {{ppgblock|block=trans14A}} and pulse block  {{ppgblock|block=pulse25}} are both within the loop, referenced to the {{ppgblock|block=begin_ramp}} [[#Automatic and user-defined time references|automatic time reference]]  {{timeref|ref=_TBEGRAMP}}. The {{ppgblock|block=end_ramp}} is referenced by default from the end of the previous block, i.e. from  the automatic time reference {{timeref|ref=_TEND_PULSE25}}.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[local:cpet:S]Titan_acq&amp;gt;ls /Equipment/Titan_acq/ppg_cycle_32                                                      &lt;br /&gt;
begin_ramp                      &lt;br /&gt;
trans14A                        &lt;br /&gt;
pulse25                         &lt;br /&gt;
end_ramp         &lt;br /&gt;
&lt;br /&gt;
[local:cpet:S]Titan_acq&amp;gt;ls /Equipment/Titan_acq/ppg_cycle_32/begin_loop1&lt;br /&gt;
time offset (ms)                20&lt;br /&gt;
loop count                      20&lt;br /&gt;
&lt;br /&gt;
[local:cpet:S]Titan_acq&amp;gt;ls /Equipment/Titan_acq/ppg_cycle_32/trans14a    &lt;br /&gt;
time offset (ms)                0&lt;br /&gt;
time reference                  _TBEGRAMP&lt;br /&gt;
ppg signal name                 CH14&lt;br /&gt;
&lt;br /&gt;
[local:cpet:S]Titan_acq&amp;gt;ls /Equipment/Titan_acq/ppg_cycle_32/pulse25 &lt;br /&gt;
time offset (ms)                0.003&lt;br /&gt;
time reference                  _TBEGRAMP&lt;br /&gt;
pulse width (ms)                0.003&lt;br /&gt;
ppg signal name                 CH25&lt;br /&gt;
&lt;br /&gt;
[local:cpet:S]Titan_acq&amp;gt;ls /Equipment/Titan_acq/ppg_cycle_32/end_loop2&lt;br /&gt;
time offset (ms)                1&lt;br /&gt;
time reference    &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Names Block ===&lt;br /&gt;
&lt;br /&gt;
This block has been defined for use with EBIT or CPET&#039;s custom web page. It is usually placed after a SKIP block at the end of the Block List. &lt;br /&gt;
&lt;br /&gt;
{|  style=&amp;quot;text-align: left; width: 80%; background-color: white;&amp;quot; border=&amp;quot;3&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;2&amp;quot;&lt;br /&gt;
|+ Table 16 :  Name Block&lt;br /&gt;
|-  style=&amp;quot;vertical-align: top; background-color: aliceblue; font-weight: bold;&amp;quot;&lt;br /&gt;
!Parameter (ODB key name) !!Type !!Default!! Required/Optional !! Explanation&lt;br /&gt;
|- &lt;br /&gt;
|Names[32] || STRING[32] Array|| none || Optional|| User-defined names of PPG Signals for Custom Webpage. Array length should reflect number of PPG Output signals used (max 32).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Example 10: Name Block ===&lt;br /&gt;
The following example shows the names array for ebit experiment :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[local:ebit:R]/&amp;gt;ls &amp;quot;/Equipment/TITAN_ACQ/ppg_cycle_mode_1f/names&amp;quot;    &lt;br /&gt;
names&lt;br /&gt;
                                RFQ extraction&lt;br /&gt;
                                TSYBL:XCB4 (Default INJ)&lt;br /&gt;
                                EBIT Beam Line(SL,Q,Y:Default EXT)&lt;br /&gt;
                                (not connected) DT6 -- default high&lt;br /&gt;
                                BNG&lt;br /&gt;
                                flexible trigger&lt;br /&gt;
                                DT4 -- default low&lt;br /&gt;
                                extra XCB4&lt;br /&gt;
                                evap AFG trigger&lt;br /&gt;
                                not used -- evap cooling&lt;br /&gt;
                                DT4&lt;br /&gt;
                                not used -- afg sweep top&lt;br /&gt;
                                TITAN EC time stamp&lt;br /&gt;
                                flexible 1&lt;br /&gt;
                                flexible &lt;br /&gt;
                                flexible &lt;br /&gt;
&amp;lt;/pre&amp;gt;                      &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Blocks added automatically ===&lt;br /&gt;
Some blocks are (or may be) added automatically. &lt;br /&gt;
&lt;br /&gt;
* A pattern block at T0 is added to set all the inputs initially to zero. This block will be removed if the user defines a pattern or other transition block at T0.  So if the user does not want all inputs to be automatically set to zero when the PPG starts, a pattern block or transition must be added at T0.&lt;br /&gt;
* A halt operation is added at the end of the program.&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=File:Loop.png&amp;diff=7573</id>
		<title>File:Loop.png</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=File:Loop.png&amp;diff=7573"/>
		<updated>2024-01-09T23:41:18Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=File:Pulse.png&amp;diff=7572</id>
		<title>File:Pulse.png</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=File:Pulse.png&amp;diff=7572"/>
		<updated>2024-01-09T23:40:37Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=File:Trans.png&amp;diff=7571</id>
		<title>File:Trans.png</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=File:Trans.png&amp;diff=7571"/>
		<updated>2024-01-09T23:40:10Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
	<entry>
		<id>https://daq00.triumf.ca/DaqWiki/index.php?title=Template:Timeref&amp;diff=7570</id>
		<title>Template:Timeref</title>
		<link rel="alternate" type="text/html" href="https://daq00.triumf.ca/DaqWiki/index.php?title=Template:Timeref&amp;diff=7570"/>
		<updated>2024-01-09T23:39:37Z</updated>

		<summary type="html">&lt;p&gt;Bsmith: Created page with &amp;quot;&amp;lt;noinclude&amp;gt; == Purpose == Show timerefs in purple, italic font == Usage == The {{Timeref|ref=_TPULSE_5}} time reference ... &amp;lt;/noinclude&amp;gt; &amp;lt;span style=&amp;quot;color:#0099e6; font-style:italic;&amp;quot;&amp;gt;{{{ref|&amp;lt;time_ref&amp;gt;}}}&amp;lt;/span&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Purpose ==&lt;br /&gt;
Show timerefs in purple, italic font&lt;br /&gt;
== Usage ==&lt;br /&gt;
The {{Timeref|ref=_TPULSE_5}} time reference ...&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#0099e6; font-style:italic;&amp;quot;&amp;gt;{{{ref|&amp;lt;time_ref&amp;gt;}}}&amp;lt;/span&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bsmith</name></author>
	</entry>
</feed>