From ff7b16c8d24f53fa43eaaa4ba35bdf9ac3928fa6 Mon Sep 17 00:00:00 2001 From: liamcottle Date: Sun, 15 Dec 2024 23:16:10 +1300 Subject: [PATCH] add button to read display from rnode --- index.html | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++ js/rnode.js | 16 +++++++++ 2 files changed, 116 insertions(+) diff --git a/index.html b/index.html index 4a357c7..c091bfd 100644 --- a/index.html +++ b/index.html @@ -242,6 +242,9 @@ + @@ -252,6 +255,11 @@
EEPROM dumps are shown in dev tools console.
+ +
+ +
+ @@ -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() { diff --git a/js/rnode.js b/js/rnode.js index c4a8c6b..9ce3d7a 100644 --- a/js/rnode.js +++ b/js/rnode.js @@ -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;