Skip to content

Commit

Permalink
Merge pull request #1 from MarkPash/master
Browse files Browse the repository at this point in the history
Add Eraser function
  • Loading branch information
Simon Struck authored Dec 17, 2020
2 parents ff434cd + 2e426e3 commit 76c7f71
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 123 deletions.
2 changes: 1 addition & 1 deletion Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Draw on a html canvas directly from your reMarkable 2.
1. SSH access to the reMarkable for installation
2. (when building from source) Rust

# Installation (from Binary)
# Installation (from Binary)

1. Download the [latest release](https://github.com/AnyTimeTraveler/pipes-and-rust/releases)
2. Set IP or hostname in `install.sh`
Expand Down
250 changes: 132 additions & 118 deletions res/index.html
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
<!DOCTYPE html>
<html lang="en">

<head>
<title>Remarkable Canvas</title>
<meta charset="UTF-8">
<title>Remarkable Canvas</title>
<meta charset="UTF-8">
</head>

<body>

<label>Address: <input type="text" id="address"></label>
<button onclick="connect()">Connect</button>
<div>Status:
<label>Address: <input type="text" id="address"></label>
<button onclick="connect()">Connect</button>
<div>Status:
<div id="status" style="display: inline">not yet connected</div>
</div>
<hr>
<div style="position: relative; width: 1176px; height: 750px;border: 1px solid #aaa">
</div>
<hr>
<div style="position: relative; width: 1176px; height: 750px;border: 1px solid #aaa">
<canvas width="1176" height="750" style="position: absolute; left: 0;top: 0" id="canvas-overlay"></canvas>
<canvas width="1176" height="750" style="position: absolute; left: 0;top: 0" id="canvas"></canvas>
</div>
<p>Enter to clear screen</p>
</div>
<p>Enter to clear screen</p>

<script>
<script>

// Found by finding the maximum values when experimenting
const MAX_X = 20966;
Expand Down Expand Up @@ -60,132 +62,144 @@
let lastY = null;

function connect() {
let address = document.getElementById("address").value;

document.getElementById("status").textContent = "connecting...";
console.log("Attempting to connect to ws://" + address);
let websocket = new WebSocket("ws://" + address);

websocket.onopen = function () {
console.log("Connected");
document.getElementById("status").textContent = "connected";
let address = document.getElementById("address").value;

document.getElementById("status").textContent = "connecting...";
console.log("Attempting to connect to ws://" + address);
let websocket = new WebSocket("ws://" + address);

websocket.onopen = function () {
console.log("Connected");
document.getElementById("status").textContent = "connected";
}

websocket.onerror = function () {
console.log("Error");
document.getElementById("status").textContent = "error";
}

websocket.onclose = function () {
console.log("Disconnected");
document.getElementById("status").textContent = "disconnected";
}

websocket.onmessage = function (event) {
// data is [x, y, pressure, mode]
let data = JSON.parse(event.data);

// Pre-increment rbI so we can use it in draw to refer to the current head.
rbI = (rbI + 1) % RINGBUFFER_SIZE;
ringbufferX[rbI] = data[0];
ringbufferY[rbI] = data[1];
ringbufferZ[rbI] = data[2];
mode = data[3];

overlay(data[0] * scaleX, data[1] * scaleY);

draw(mode);

if (debug) {
ctx.fillStyle = "red";
ctx.beginPath();
ctx.fillRect(data[0] * scaleX, data[1] * scaleY, 2, 2);
ctx.fill();
}

websocket.onerror = function () {
console.log("Error");
document.getElementById("status").textContent = "error";
}

websocket.onclose = function () {
console.log("Disconnected");
document.getElementById("status").textContent = "disconnected";
}

websocket.onmessage = function (event) {
// data is [x, y, pressure]
let data = JSON.parse(event.data);

// Pre-increment rbI so we can use it in draw to refer to the current head.
rbI = (rbI + 1) % RINGBUFFER_SIZE;
ringbufferX[rbI] = data[0];
ringbufferY[rbI] = data[1];
ringbufferZ[rbI] = data[2];

overlay(data[0] * scaleX, data[1] * scaleY);

draw();

if (debug) {
ctx.fillStyle = "red";
ctx.beginPath();
ctx.fillRect(data[0] * scaleX, data[1] * scaleY, 2, 2);
ctx.fill();
}

};
};

}

function draw() {
// Loop through ringbuffer elements...
// Average all ringbuffer elements where the pressure is nonzeroish.
let avgX = 0;
let avgY = 0;
let cnt = 0;
for (let i = 0; i < RINGBUFFER_SIZE; i++) {
// If this does look like the end of a stroke, still use the whole
// framebuffer. It's short enough to drain quickly without confusing
// this stroke with the next.
if (ringbufferZ[i] > 10) {
avgX += ringbufferX[i];
avgY += ringbufferY[i];
cnt += 1;
}
// Loop through ringbuffer elements...
// Average all ringbuffer elements where the pressure is nonzeroish.
let avgX = 0;
let avgY = 0;
let cnt = 0;
for (let i = 0; i < RINGBUFFER_SIZE; i++) {
// If this does look like the end of a stroke, still use the whole
// framebuffer. It's short enough to drain quickly without confusing
// this stroke with the next.
if (ringbufferZ[i] > 10) {
avgX += ringbufferX[i];
avgY += ringbufferY[i];
cnt += 1;
}

avgX /= cnt;
avgY /= cnt;
avgX *= scaleX;
avgY *= scaleY;

// If there were zero entries with nonzero pressure, that's the
// end of a stroke. Forget the last point.
if (cnt == 0) {
penState = false;
lastX = null;
lastY = null;
} else {
// Only start drawing if we already started a line.
if (penState) {
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(avgX, avgY);
ctx.stroke();
}
penState = true;

// Always assign last x and y when there's pen pressure,
// to mark the start of a line.
lastX = avgX;
lastY = avgY;
}

avgX /= cnt;
avgY /= cnt;
avgX *= scaleX;
avgY *= scaleY;

// If there were zero entries with nonzero pressure, that's the
// end of a stroke. Forget the last point.
if (cnt == 0) {
penState = false;
lastX = null;
lastY = null;
} else {
// Only start drawing if we already started a line.
if (penState) {
if (mode == 0) {
ctx.strokeStyle = "#000000";
ctx.lineWidth = 2;
ctx.globalCompositeOperation = "source-over";
ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(avgX, avgY);
ctx.stroke();
} else {
ctx.fillStyle = "#000000";
ctx.globalCompositeOperation = "destination-out";
ctx.beginPath();
ctx.arc(avgX, avgY, 20, 0, 2 * Math.PI);
ctx.fill();
}
}
penState = true;

// Always assign last x and y when there's pen pressure,
// to mark the start of a line.
lastX = avgX;
lastY = avgY;
}
}


function overlay(x, y) {
// Clear when hovering, but keep drawing for the duration of a stroke to highlight it.
if (!penState) {
ctxOverlay.clearRect(0, 0, canvasOverlay.width, canvasOverlay.height);
}
ctxOverlay.fillStyle = "rgb(200, 200, 255)";
ctxOverlay.beginPath();
ctxOverlay.arc(x, y, 10, 0, 2 * Math.PI);
ctxOverlay.fill();
// Clear when hovering, but keep drawing for the duration of a stroke to highlight it.
if (!penState) {
ctxOverlay.clearRect(0, 0, canvasOverlay.width, canvasOverlay.height);
}
ctxOverlay.fillStyle = "rgb(200, 200, 255)";
ctxOverlay.beginPath();
ctxOverlay.arc(x, y, 20, 0, 2 * Math.PI);
ctxOverlay.fill();
}

document.addEventListener('keydown', logKey);

function logKey(e) {
if (e.keyCode === 13) {
// enter for rotate
rotate = !rotate;

let oldWidth = canvas.width;
canvas.width = canvas.height;
canvas.height = oldWidth
} else if (e.keyCode === 32) {
// Space for clear.
canvas.dataset = null;
e.preventDefault();
} else if (e.keyCode == 68) {
// 'd' for debug
debug = !debug;
}
if (e.keyCode === 13) {
// enter for rotate
rotate = !rotate;

let oldWidth = canvas.width;
canvas.width = canvas.height;
canvas.height = oldWidth
} else if (e.keyCode === 32) {
// Space for clear.
canvas.dataset = null;
e.preventDefault();
} else if (e.keyCode == 68) {
// 'd' for debug
debug = !debug;
}
}

document.getElementById("address").value = window.location.hostname + ":55555";
connect();
</script>
</script>
</body>
</html>

</html>
24 changes: 20 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,24 @@ fn main() {
let mut x = 0;
let mut y = 0;
let mut pressure = 0;
let mut mode = 0;

while let Ok(()) = input.read_exact(&mut buf) {
// Using notes from https://github.com/ichaozi/RemarkableFramebuffer
let typ = buf[8];
let code = buf[10] as i32 + buf[11] as i32 * 0x100;
let value = buf[12] as i32 + buf[13] as i32 * 0x100 + buf[14] as i32 * 0x10000 + buf[15] as i32 * 0x1000000;
let value = buf[12] as i32
+ buf[13] as i32 * 0x100
+ buf[14] as i32 * 0x10000
+ buf[15] as i32 * 0x1000000;

if typ == 1 {
if code == 320 {
mode = 0;
} else if code == 321 {
mode = 1;
}
}
// Absolute position
if typ == 3 {
if code == 0 {
Expand All @@ -50,16 +61,21 @@ fn main() {
} else if code == 24 {
pressure = value
}
if let Err(value) = out.send(Message::text(format!("[{},{},{}]", x, y, pressure))) {
if let Err(value) = out.send(Message::text(format!(
"[{},{},{},{}]",
x, y, pressure, mode
))) {
eprintln!("Error: {:?}", value);
return;
};
}
}
}).expect("creating thread");
})
.expect("creating thread");
move |msg| {
println!("Got: {}", msg);
Ok(())
}
}).unwrap();
})
.unwrap();
}

0 comments on commit 76c7f71

Please sign in to comment.