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;