add button to read display from rnode

This commit is contained in:
liamcottle
2024-12-15 23:16:10 +13:00
parent 252ee55a8a
commit ff7b16c8d2
2 changed files with 116 additions and 0 deletions

View File

@@ -242,6 +242,9 @@
<button @click="reboot" class="border border-gray-500 px-2 bg-gray-100 hover:bg-gray-200 rounded">
Reboot RNode
</button>
<button @click="readDisplay" class="border border-gray-500 px-2 bg-gray-100 hover:bg-gray-200 rounded">
Read Display
</button>
<button @click="dumpEeprom" class="border border-gray-500 px-2 bg-gray-100 hover:bg-gray-200 rounded">
Dump EEPROM
</button>
@@ -252,6 +255,11 @@
<div class="text-sm text-gray-500">EEPROM dumps are shown in dev tools console.</div>
<!-- show rnode display if available -->
<div v-if="rnodeDisplayImage">
<img :src="rnodeDisplayImage" class="h-28"/>
</div>
</div>
</div>
@@ -281,6 +289,8 @@
isFlashing: false,
flashingProgress: 0,
rnodeDisplayImage: null,
selectedProduct: null,
selectedModel: null,
products: [
@@ -1081,6 +1091,96 @@
// done
alert("Board is rebooting!");
},
frameBufferToCanvas(framebuffer, width, height, backgroundColour, foregroundColour) {
// create canvas
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
// fill the canvas with background colour
const ctx = canvas.getContext('2d');
ctx.fillStyle = backgroundColour;
ctx.fillRect(0, 0, width, height);
// draw foreground pixels where bits are 1
ctx.fillStyle = foregroundColour;
for(let y = 0; y < height; y++){
for(let x = 0; x < width; x++){
const byteIndex = Math.floor((y * width + x) / 8);
const bitIndex = x % 8;
const bit = (framebuffer[byteIndex] >> (7 - bitIndex)) & 1;
if(bit){
ctx.fillRect(x, y, 1, 1);
}
}
}
return canvas;
},
rnodeDisplayBufferToPng(displayBuffer) {
// get display area and stat area
const displayArea = displayBuffer.slice(0, 512);
const statArea = displayBuffer.slice(512, 1024);
// create canvas from frame buffers
const displayCanvasOriginal = this.frameBufferToCanvas(displayArea, 64, 64, "#000000", "#FFFFFF");
const statCanvasOriginal = this.frameBufferToCanvas(statArea, 64, 64, "#000000", "#FFFFFF");
// create horizontal canvas to show display area and stat area next to each other
const canvas = document.createElement('canvas');
canvas.width = 128;
canvas.height = 64;
// draw canvases to final canvas
const canvasCtx = canvas.getContext('2d');
canvasCtx.imageSmoothingEnabled = false;
canvasCtx.drawImage(displayCanvasOriginal, 0, 0, 64, 64);
canvasCtx.drawImage(statCanvasOriginal, 64, 0, 64, 64);
// create scaled canvas
const scaleFactor = 4;
const scaledCanvas = document.createElement('canvas');
scaledCanvas.width = canvas.width * scaleFactor;
scaledCanvas.height = canvas.height * scaleFactor;
// scale original canvas onto new canvas
const scaledCtx = scaledCanvas.getContext('2d');
scaledCtx.imageSmoothingEnabled = false;
scaledCtx.drawImage(canvas, 0, 0, scaledCanvas.width, scaledCanvas.height);
// convert canvas to png
return scaledCanvas.toDataURL("image/png");
},
async readDisplay() {
// ask for serial port
const serialPort = await this.askForSerialPort();
if(!serialPort){
return;
}
// check if device is an rnode
const rnode = await RNode.fromSerialPort(serialPort);
const isRNode = await rnode.detect();
if(!isRNode){
alert("Selected device is not an RNode!");
return;
}
// read display
const displayBuffer = await rnode.readDisplay();
// disconnect from rnode
await rnode.close();
// update ui
this.rnodeDisplayImage = this.rnodeDisplayBufferToPng(displayBuffer);
},
async dumpEeprom() {

View File

@@ -83,6 +83,8 @@ class RNode {
CMD_BT_CTRL = 0x46;
CMD_BT_PIN = 0x62;
CMD_DISP_READ = 0x66;
CMD_DETECT = 0x08;
DETECT_REQ = 0x73;
DETECT_RESP = 0x46;
@@ -567,6 +569,20 @@ class RNode {
}
async readDisplay() {
await this.sendKissCommand([
this.CMD_DISP_READ,
0x01,
]);
// read response from device
const [ command, ...displayBuffer ] = await this.readFromSerialPort();
return displayBuffer;
}
async setFrequency(frequencyInHz) {
const c1 = frequencyInHz >> 24;