Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,5 @@ dmypy.json

db.sqlite3
ansible/inventory/host_vars/mk_secrets.sh
ansible_secrets.txt
ansible_secrets_notes.md
35 changes: 26 additions & 9 deletions ansible/roles/fixpi/tasks/tweeks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@
path: "{{ nfs_root }}/root/etc/hostname"
state: absent
tags:
- hostname
- hostname

- name: pi etc/hosts
lineinfile:
path: "{{ nfs_root }}/root/etc/hosts"
line: "127.0.1.1 pi{{ item.port }}"
with_items: "{{ switch.nos }}"
tags:
- hostname
- hostname

- name: set pistat_host in /etc/environment
lineinfile:
Expand All @@ -63,20 +63,36 @@
- name: add time to bash prompt
lineinfile:
dest: "{{ nfs_root }}/root/home/pi/.bashrc"
insertafter: '^unset color_prompt force_color_prompt'
insertafter: "^unset color_prompt force_color_prompt"
line: '{% raw %}PS1="\D{%T} $PS1"{% endraw %}'
when: true
tags:
- bashrc

- name: ensure update-motd.d exists
file:
path: "{{ nfs_root }}/root/etc/update-motd.d"
state: directory

- name: install dynamic motd script
template:
src: templates/99-pici-motd.j2
dest: "{{ nfs_root }}/root/etc/update-motd.d/99-pici"
mode: "0755"

- name: clear static motd
copy:
content: ""
dest: "{{ nfs_root }}/root/etc/motd"

# the rest of these tasks config the server to monitor client boot spew

- name: is server pi
stat:
path: /boot/firmware/config.txt
register: is_pi
tags:
- ispi
- ispi

- name: enable /dev/serial0
ansible.builtin.lineinfile:
Expand All @@ -87,7 +103,7 @@
- dtoverlay=disable-bt
when: is_pi.stat.exists
tags:
- ispi
- ispi

# https://bugs.debian.org/667616
# brltty greedily grabs serial ports, ftdi_sio loses connection
Expand Down Expand Up @@ -117,17 +133,18 @@
state: stopped
name: serial-getty@ttyAMA0.service
tags:
- ispi
- ispi

- name: Git checkout this repo for safer 2 hour onpi
ansible.builtin.git:
repo: 'https://github.com/CarlFK/pici.git'
repo: "https://github.com/CarlFK/pici.git"
dest: "/home/{{ user_name }}/pici"
depth: 1
single_branch: true
accept_hostkey: true
force: true
force:
true
# args:
# creates: "/home/{{ user_name }}/pici"

# ssh-keyscan -H remote_host.com >> /etc/ssh/ssh_known_hosts
# ssh-keyscan -H remote_host.com >> /etc/ssh/ssh_known_hosts
16 changes: 16 additions & 0 deletions ansible/roles/fixpi/templates/99-pici-motd.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/bash
# PICI FPGA Lab Welcome Message

# Get Pi Number from hostname (e.g. pi21 -> 21)
NUM=$(hostname | grep -o '[0-9]*')
# Calculate External Port (Prefix 100 + NUM + 22)
PREFIX=$((100 + NUM))
EXT_PORT="${PREFIX}22"

cat <<EOF
Connected to $(hostname)

Prefer your own tools? Use:
ssh -p ${EXT_PORT} pi@{{ domain_name }}

EOF
225 changes: 179 additions & 46 deletions ansible/roles/site/files/pib/pibfpgas/src/pibfpgas/static/demos.js
Original file line number Diff line number Diff line change
@@ -1,47 +1,180 @@
// demos.js
// https://github.com/huashengdun/webssh?tab=readme-ov-file#browser-console
// wssh.send('ls -l');

function wssh_run(e,cmd) {
e.preventDefault();
const wssh_if = document.getElementById("wssh_if").contentWindow;
wssh_if.wssh.send(cmd);
};

document.getElementById('blink_leds').onclick = function(e) {
wssh_run(e,'cd ~/Demos/counter_test')
wssh_run(e,'./run_demo.sh')
};

document.getElementById('boot_micro_python').onclick = function(e) {
wssh_run(e,'cd ~/Demos/micro_python')
wssh_run(e,'./run_demo.sh')
};

document.getElementById('boot_linux').onclick = function(e) {
wssh_run(e,'cd ~/Demos/linux_litex')
wssh_run(e,'./run_demo.sh')
};

document.getElementById('check_wire').onclick = function(e) {
wssh_run(e,'cd ~/ci/t1')
wssh_run(e,'openFPGALoader -b arty top.bit')
wssh_run(e,'python3 t1.py')
wssh_run(e,'echo $?')
};

document.getElementById('tt910').onclick = function(e) {
wssh_run(e,'cd ~/tt-commander-app/src/ttcontrol/cli')
wssh_run(e,'python bl.py --serial-port /dev/ttyACM0 --throttle 1 --debug')
wssh_run(e,'tio /dev/ttyACM0')
};

document.getElementById('usb_off').onclick = function(e) {
wssh_run(e,'/sbin/uhubctl -S --ports 2 --action off')
};


document.getElementById('usb_on').onclick = function(e) {
wssh_run(e,'/sbin/uhubctl -S --ports 2 --action on')
};
// demos.js - SSH Terminal Sidebar Controller

function wssh_run_raw(cmd) {
const wssh_if = document.getElementById("wssh_if");
if (wssh_if && wssh_if.contentWindow && wssh_if.contentWindow.wssh) {
wssh_if.contentWindow.wssh.send(cmd);
}
}

document.addEventListener('DOMContentLoaded', function() {

// --- Menu Controller ---
const menuContainer = document.getElementById('term-menu');
// If we are on a page without the menu (e.g. login), skip
if (!menuContainer) return;

function getVisibleItems() {
// Return only items that are not in a hidden container
return Array.from(menuContainer.querySelectorAll('.menu-item')).filter(item => {
return item.offsetParent !== null; // Checks visibility
});
}

function setActive(item) {
// Remove active from all
menuContainer.querySelectorAll('.menu-item').forEach(i => i.classList.remove('active'));
item.classList.add('active');
item.focus();
}

// Input Handling
menuContainer.addEventListener('keydown', function(e) {
const visibleItems = getVisibleItems();
const currentIndex = visibleItems.indexOf(document.activeElement);

if (e.key === 'ArrowDown') {
e.preventDefault();
const next = visibleItems[currentIndex + 1] || visibleItems[0];
setActive(next);
} else if (e.key === 'ArrowUp') {
e.preventDefault();
const prev = visibleItems[currentIndex - 1] || visibleItems[visibleItems.length - 1];
setActive(prev);
} else if (e.key === 'Enter') {
e.preventDefault();
triggerItem(document.activeElement);
}
});

// Click Handling
menuContainer.addEventListener('click', function(e) {
const item = e.target.closest('.menu-item');
if (!item) return;
setActive(item);
triggerItem(item);
});

function triggerItem(item) {
// 1. Expand/Collapse Categories
if (item.classList.contains('category-header')) {
const category = item.parentElement;
const children = category.querySelector('.menu-children');
const indicator = item.querySelector('.indicator');

// Special Case: BYO Category Button logic
if (category.dataset.category === 'byo') {
showBYO();
} else {
// Toggle children
if (children) {
if (children.style.display === 'none') {
children.style.display = 'block';
indicator.textContent = '▼';
} else {
children.style.display = 'none';
indicator.textContent = '▶';
}
}
// Ensure terminal is visible for demos/tutorials
showTerminal();
}
return;
}

// 2. Demo Execution
if (item.dataset.cmd) {
const cmd = item.dataset.cmd;
const desc = item.dataset.desc;
run_demo_flow(desc, cmd);
showTerminal(); // Ensure terminal is shown
return;
}

// 3. Command Line (Free Play)
if (item.id === 'btn-term-free') {
showTerminal();
return;
}

// 4. Contribute Guide
if (item.id === 'btn-contrib') {
showContrib();
}

// 5. Onboarding / Hello World
if (item.id === 'btn-hello-world') {
showTerminal();
run_onboarding();
return;
}
}

function run_demo_flow(desc, cmd) {
const script = `
echo
echo "---------------------------------------------------"
echo " DEMO: ${desc}"
echo "---------------------------------------------------"
echo "Command to run: ${cmd}"
echo
read -p "Proceed? (y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
${cmd}
else
echo "Cancelled."
fi
`;
wssh_run_raw(script);
}

function run_onboarding() {
const script = `
clear
echo "Initializing..."
sleep 1
echo "Connecting to FPGA Hardware..."
sleep 1
echo
echo "👋 HELLO WORLD!"
echo "I am your remote FPGA board."
echo
echo "I am going to wave at you now."
echo "Watch the video feed..."
sleep 2
echo
echo ">> Running Blinky (LED Test)..."
cd ~/01_simple_test/v && make load
echo
echo "--------------------------------------"
echo "See the LEDs flashing?"
echo "That was real code running on real hardware."
echo "--------------------------------------"
echo
echo "Welcome to the Lab."
echo "Use the sidebar to explore more demos."
echo
`;
wssh_run_raw(script);
}

// --- View Switchers ---
function showTerminal() {
document.getElementById('shared-terminal').style.display = 'block';
document.getElementById('view-byo').style.display = 'none';
document.getElementById('view-contrib').style.display = 'none';
}

function showBYO() {
document.getElementById('shared-terminal').style.display = 'none';
document.getElementById('view-byo').style.display = 'block';
document.getElementById('view-contrib').style.display = 'none';
}

function showContrib() {
document.getElementById('shared-terminal').style.display = 'none';
document.getElementById('view-byo').style.display = 'none';
document.getElementById('view-contrib').style.display = 'block';
}
});
Loading