web: add prototype web terminal

This commit is contained in:
Fischer Moseley 2024-04-14 17:23:59 -07:00
parent 7957e5d74e
commit 7fb9d8bebc
7 changed files with 183 additions and 0 deletions

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 KiB

65
doc/javascripts/serial.js Normal file
View File

@ -0,0 +1,65 @@
// serial.js
let port;
async function connect() {
try {
port = await navigator.serial.requestPort();
await port.open({ baudRate: 115200 });
console.log('Connected to serial device:', port);
} catch (error) {
console.error('Error connecting to serial device:', error);
}
}
async function write(addr, data) {
try {
if (!port) {
console.error('Serial port not connected');
return;
}
// Format the data to be sent
const sendData = `W${addr.toString(16).padStart(4, '0')}${data.toString(16).padStart(4, '0')}\r\n`;
// Example: Sending data to the device
const writer = port.writable.getWriter();
await writer.write(new TextEncoder().encode(sendData));
await writer.releaseLock();
console.log('Sent:', sendData);
} catch (error) {
console.error('Error sending data:', error);
}
}
async function read(addr) {
try {
if (!port) {
console.error('Serial port not connected');
return;
}
// Format the read command
const readCmd = `R${addr.toString(16).padStart(4, '0')}\r\n`;
// Send the read command to the device
const writer = port.writable.getWriter();
await writer.write(new TextEncoder().encode(readCmd));
await writer.releaseLock();
console.log('Sent:', readCmd);
// Read back the response
const reader = port.readable.getReader(); // Create a new reader
const { value, done } = await reader.read(); // Read from the stream
reader.releaseLock(); // Release the reader's lock
if (!done) {
const responseData = new TextDecoder().decode(value);
console.log('Received:', responseData);
return responseData;
}
} catch (error) {
console.error('Error reading data:', error);
}
}
document.getElementById('connectButton').addEventListener('click', connect);

24
doc/javascripts/upload.js Normal file
View File

@ -0,0 +1,24 @@
let data;
let fileUploaded = false;
document.getElementById('fileInput').addEventListener('change', function(event) {
const file = event.target.files[0];
const reader = new FileReader();
reader.onload = function(e) {
data = e.target.result;
fileUploaded = true; // Set the flag to indicate file upload completion
};
reader.readAsText(file);
});
function runAfterUpload() {
if (!fileUploaded) {
setTimeout(runAfterUpload, 100); // Check again after 100ms
return;
}
// Your additional JavaScript code to run after file upload
web_terminal(data);
}
runAfterUpload(); // Start checking for file upload completion

View File

@ -0,0 +1,57 @@
async function web_terminal(data){
let pyodide = await loadPyodide();
// Load Manta.yaml into pyodide's file system
pyodide.FS.writeFile("/manta.yaml", data, { encoding: "utf8" });
// Load micropip, setuptools, manta
await pyodide.loadPackage("micropip");
await pyodide.loadPackage("setuptools");
const micropip = pyodide.pyimport("micropip");
await micropip.install('../assets/manta-1.0.0-py3-none-any.whl');
pyodide.runPythonAsync(`
import asyncio
import time
from js import read, write
from manta.utils import value_to_words
from manta import Manta
m = Manta("/manta.yaml")
print(m.my_io_core)
async def set_probe(name, value):
# Write value to core
probe = m.my_io_core._memory_map.get(name)
addrs = probe["addrs"]
datas = value_to_words(value, len(addrs))
for a, d in zip(addrs, datas):
await write(a, d)
# Pulse strobe register
await write(m.my_io_core._base_addr, 0)
await write(m.my_io_core._base_addr, 1)
await write(m.my_io_core._base_addr, 0)
async def foobar():
for i in range(10):
await set_probe(f"LED{i%4}", 1)
await set_probe(f"LED{i%4}", 0)
print(i)
#loop = asyncio.get_event_loop()
#loop.run_until_complete(foobar())
async def barfoo():
print("entering barfoo")
print(await read(m.my_io_core._base_addr))
print(await read(m.my_io_core._base_addr + 1))
loop = asyncio.get_event_loop()
loop.run_until_complete(barfoo())
#asyncio.run(foobar()) # doesn't work! asyncio.run() cannot be called from a running event loop
#await foobar() # doesn't work either! await outside function
#await barfoo() # doesn't work either! await outside function
`);
}

36
doc/web_terminal.md Normal file
View File

@ -0,0 +1,36 @@
## Open Serial Port
<button class="md-button" id="connectButton">Connect</button>
## Load Manta Configuration File
<button class="md-button" id="uploadButton">Upload File</button>
<input type="file" id="fileInput" accept=".yaml,.yml" style="display: none">
<div id="filePath"></div>
<!-- Load Javascript -->
<script src="../javascripts/web_terminal.js"></script>
<script src="../javascripts/serial.js"></script>
<script src="../javascripts/upload.js"></script>
<script src="https://cdn.jsdelivr.net/pyodide/v0.25.1/full/pyodide.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function() {
const uploadButton = document.getElementById("uploadButton");
const fileInput = document.getElementById("fileInput");
const filePathDisplay = document.getElementById("filePath");
uploadButton.addEventListener("click", function() {
fileInput.click();
});
fileInput.addEventListener("change", function() {
const filePath = fileInput.value; // Get the file path from the file input
filePathDisplay.textContent = "Loaded " + filePath; // Display the file path
});
});
</script>
<!-- <iframe src="https://app.surfer-project.org/?load_url=https://app.surfer-project.org/picorv32.vcd&amp;startup_commands=show_quick_start;module_add%20testbench.top;toggle_menu" ,="" style="width: 100%; height: 100%"></iframe> -->

View File

@ -66,6 +66,7 @@ nav:
- Getting Started: getting_started.md
- Alternatives: alternatives.md
- Architecture: architecture.md
- Web Terminal: web_terminal.md
- Usage:
- IO Core: io_core.md
- Logic Analyzer Core: logic_analyzer_core.md