Skip to content

Instantly share code, notes, and snippets.

@benfoxall
Created May 15, 2021 20:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benfoxall/44db79d35e964cef9e4b78c49b34e622 to your computer and use it in GitHub Desktop.
Save benfoxall/44db79d35e964cef9e4b78c49b34e622 to your computer and use it in GitHub Desktop.
A page for drawing on the Pi Pico Unicorn Pack over WebUSB – https://twitter.com/benjaminbenben/status/1379361185703849987
<html>
<head>
<title>
pico serial
</title>
<style>
body {
font-family: sans-serif;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.is-connected {
visibility: hidden
}
.connected .is-connected {
visibility: visible
}
table {
margin: 1em
}
input[type=color] {
height: 2rem;
width: 2rem;
border: none;
outline: none;
background-color: #fff;
}
td {
box-shadow: 0 0 3px #1115;
border-radius: 5px;
width: 20px;
height: 20px;
}
details {
margin-top: 4em
}
table.draw {
cursor: crosshair;
}
</style>
</head>
<body>
<h1><span class="is-connected">🎉</span> 🦄 <span class="is-connected">🎉</span></h1>
<table></table>
<input type="color" value="#ff0099">
<details open>
<summary>⚙️</summary>
<button id="connect">connect</button>
<hr />
<button onclick="py('import picounicorn\npicounicorn.init()')">import picounicorn</button>
<button onclick="py('import machine\nmachine.reset()')">machine.reset</button>
<button onclick="clearCells()">clear cells</button>
</details>
<script>
const qs = (selector) => document.querySelector(selector)
const qsa = (selector) => document.querySelectorAll(selector)
const el = (name, parent) => {
const child = document.createElement(name)
if (parent) parent.appendChild(child)
return child;
}
let draw = false
const width = 16;
const height = 7;
const table = qs('table')
for (let i = 0; i < height; i++) {
const row = el('tr', table)
for (let j = 0; j < width; j++) {
const cell = el('td', row)
const drawCell = () => {
if (draw) {
const color = qs('input').value
cell.style.background = color
if (port) {
const [_, r, g, b] = color.match(/#(..)(..)(..)/).map(c => parseInt(c, 16))
write(`picounicorn.set_pixel(${j}, ${i}, ${r}, ${g}, ${b})\r\n`)
}
}
}
cell.addEventListener('mouseover', drawCell)
cell.addEventListener('click', () => {
table.classList.toggle('draw', draw = !draw)
drawCell()
})
}
}
let port;
async function read() {
const reader = port.readable.getReader()
// Listen to data coming from the serial device.
while (true) {
const { value, done } = await reader.read()
if (done) {
// Allow the serial port to be closed later.
reader.releaseLock()
break
}
// value is a Uint8Array.
console.log('%c' + new TextDecoder().decode((value)), "color: aquamarine; background: #000;text-decoration: underline;")
}
console.log("has read")
}
async function write(str) {
const writer = port.writable.getWriter()
const data = new TextEncoder().encode(str)
await writer.write(data);
console.log('%c' + str, "color: red; background: #222;text-decoration: underline;")
// Allow the serial port to be closed later.
writer.releaseLock();
}
async function click() {
port = await navigator.serial.requestPort()
// await port.open({ baudRate: 9600 })
await port.open({ baudRate: 115200 })
read()
}
qs('#connect').addEventListener('click', click)
navigator.serial.addEventListener("connect", async (event) => {
// TODO: Automatically open event.target or warn user a port is available.
console.log("connect", event)
port = event.target;
await port.open({ baudRate: 115200 })
py('import picounicorn\npicounicorn.init()')
document.body.classList.add('connected')
});
navigator.serial.addEventListener("disconnect", (event) => {
// TODO: Remove |event.target| from the UI.
// If the serial port was opened, a stream error would be observed as well.
console.log("disconnect", event)
port = null;
});
function py(str) {
const code = str.replace(/\n/g, "\r\n")
return write(code + "\r\n");
}
function clearCells() {
for (const el of qsa('td')) {
el.style.background = ''
}
// fixme: seems to break
py(`picounicorn.clear()`)
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment