Created
May 15, 2021 20:25
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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