Created
October 10, 2023 15:58
-
-
Save Alikberov/a694af6c8e3581041cab6e6f0f8b4c39 to your computer and use it in GitHub Desktop.
HCMS-201X / HCMS-231X / HCMS-235X / IPV72A-4/5X7 / ИПВ72А-4/5X7 emulator
This file contains 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>ИПВ72А-4/5x7</title> | |
<meta http-equiv="refresh" content="300; url=https://www.jameco.com/Jameco/Products/ProdDS/1548828.pdf"> | |
<script> | |
var hIPV; | |
var ctx; | |
var mtx; | |
var mask = 0; | |
var data = 0; | |
var tick = 0; | |
var time = 0; | |
var delay = 0; | |
var speed = 1; // ...?speed=1 | |
var fading = -1; // ...?fade=1 | |
var stream = [ // ...?stream=D1_8E-6E-4E_1F-7F-5F_15-75-55_1F-7F-5F_15-75-55_1B-7B-5B_0E-6E-4E | |
// 12 10 8 5 4 3 2 1 | |
// DI \C EN Y5 Y4 Y3 Y2 Y1 | |
// D7_D6_D5_D4_D3_D2_D1_D0 | |
// ----------------------- | |
// 1 1 0 <-- Prepare display start | |
// 1 0 0 <-- Strobe first line | |
// 0 1 1 <-- Display line | |
// 0 1 0 <-- Prepare next line | |
// 0 0 0 <-- Strobe next line | |
// 0 1 1 <-- Display line | |
// 0 1 0 <-- Prepare next line | |
// 0 0 0 <-- Strobe next line | |
0xD1, | |
0x91, 0x71, 0x51, | |
0x11, 0x71, 0x51, | |
0x11, 0x71, 0x51, | |
0x1F, 0x7F, 0x5F, | |
0x11, 0x71, 0x51, | |
0x11, 0x71, 0x51, | |
0x11, 0x71, 0x51, | |
0x1F, 0x7F, 0x5F, | |
0x10, 0x70, 0x50, | |
0x10, 0x70, 0x50, | |
0x1E, 0x7E, 0x5E, | |
0x10, 0x70, 0x50, | |
0x10, 0x70, 0x50, | |
0x1F, 0x7F, 0x5F, | |
0x10, 0x70, 0x50, | |
0x10, 0x70, 0x50, | |
0x10, 0x70, 0x50, | |
0x10, 0x70, 0x50, | |
0x10, 0x70, 0x50, | |
0x10, 0x70, 0x50, | |
0x1F, 0x7F, 0x5F, | |
0x0E, 0x6E, 0x4E, | |
0x11, 0x71, 0x51, | |
0x11, 0x71, 0x51, | |
0x11, 0x71, 0x51, | |
0x11, 0x71, 0x51, | |
0x11, 0x71, 0x51, | |
0x0E, 0x6E, 0x4E | |
]; | |
function main() { | |
const user_stream = window.location.href.match(/stream=([0-9_A-F+-]+)/i); | |
const user_speed = window.location.href.match(/speed=(\d+)/i); | |
const user_fade = window.location.href.match(/fade=(\d+)/i); | |
const pins = "Y1 Y2 Y3 Y4 Y5 CH DO EN +5 C 0V DI".split(/\s+/); | |
hIPV = document.getElementById("IPV"); | |
ctx = hIPV.getContext("2d"); | |
ctx.clearRect(0, 0, hIPV.width, hIPV.height); | |
mtx = ctx.getImageData(0, 0, 400, 128); | |
for(var i = 0; i < mtx.data.length; i += 4) { | |
mtx.data[i] = 255; | |
mtx.data[i + 1] = 0; | |
mtx.data[i + 2] = 0; | |
mtx.data[i + 3] = 0; | |
} | |
ctx.fillStyle = "white"; | |
ctx.fillRect(0, 0, 208, 256); | |
ctx.strokeStyle = "black"; | |
ctx.beginPath(); | |
ctx.lineWidth = 2; | |
ctx.rect(108, 7, 88, 240); | |
ctx.rect(148, 94, 40, 75); | |
ctx.rect(158, 130, 10, 20); | |
ctx.moveTo(128, 7); | |
ctx.lineTo(128, 247); | |
ctx.rect(7, 7, 20, 160); | |
for(var i = 0; i < 7; ++ i) { | |
ctx.moveTo(108, 28 + (i + 4) * 20); | |
ctx.lineTo(128, 28 + (i + 4) * 20); | |
ctx.moveTo(7, 28 + i * 20); | |
ctx.lineTo(27, 28 + i * 20); | |
} | |
ctx.stroke(); | |
ctx.beginPath(); | |
ctx.lineWidth = 1; | |
for(var i = 0; i < 12; ++ i) { | |
ctx.moveTo(88, 16 + i * 20); | |
ctx.lineTo(108, 16 + i * 20); | |
ctx.textAlign = "right"; | |
ctx.strokeText(String(i + 1), 104, 12 + i * 20); | |
ctx.textAlign = "left"; | |
ctx.strokeText(pins[i], 110, 20 + i * 20); | |
} | |
ctx.strokeText("4x", 132, 135); | |
ctx.textAlign = "center"; | |
ctx.strokeText("5x7", 168, 115); | |
for(var i = 0; i < 8; ++ i) { | |
ctx.moveTo(27, 16 + i * 20); | |
ctx.lineTo(88, 16 + (i < 5 ? i : (i - 5) * 2 + 7) * 20); | |
ctx.strokeText(`D${i}`, 17, 20 + i * 20); | |
} | |
ctx.stroke(); | |
if(user_stream) { | |
stream = []; | |
for(const data of user_stream[1].split(/[-_+]+/)) | |
stream.push(parseInt(data, 16)); | |
} | |
if(user_speed) | |
speed = parseInt(user_speed[1]); | |
if(user_fade) | |
fading = -parseInt(user_fade[1]); | |
show(); | |
} | |
function show() { | |
var digit; | |
var x, y; | |
var p, err; | |
var fire; | |
for(digit = 0; digit < 4; ++ digit) { | |
err = [-1, 0, 1/4, 1.4][digit]; | |
for(y = 0; y < 7; ++ y) { | |
for(x = 0; x < 5; ++ x) { | |
fire = ((data >> (4 - x)) & 1) > 0 && ((mask >> (digit * 7 + y)) & 1) > 0 && (data & 0x20) > 0 ? 255 : fading; | |
p = (100 * digit + 12 * 400 * y + x * 12 + 8 + Math.floor(err * y)) * 4; | |
mtx.data[p + 3] += fire; | |
mtx.data[p + 3 + 4] += fire; | |
mtx.data[p + 3 + 8] += fire; | |
mtx.data[p + 3 + 12] += fire; | |
mtx.data[p + 3 + 16] += fire; | |
mtx.data[p + 3 + 20] += fire; | |
mtx.data[p + 3 + 24] += fire; | |
mtx.data[p + 3 + 1600] += fire; | |
mtx.data[p + 3 + 1600 + 4] += fire; | |
mtx.data[p + 3 + 1600 + 8] += fire; | |
mtx.data[p + 3 + 1600 + 12] += fire; | |
mtx.data[p + 3 + 1600 + 16] += fire; | |
mtx.data[p + 3 + 1600 + 20] += fire; | |
mtx.data[p + 3 + 1600 + 24] += fire; | |
mtx.data[p + 3 + 3200] += fire; | |
mtx.data[p + 3 + 3200 + 4] += fire; | |
mtx.data[p + 3 + 3200 + 8] += fire; | |
mtx.data[p + 3 + 3200 + 12] += fire; | |
mtx.data[p + 3 + 3200 + 16] += fire; | |
mtx.data[p + 3 + 3200 + 20] += fire; | |
mtx.data[p + 3 + 3200 + 24] += fire; | |
mtx.data[p + 3 + 4800] += fire; | |
mtx.data[p + 3 + 4800 + 4] += fire; | |
mtx.data[p + 3 + 4800 + 8] += fire; | |
mtx.data[p + 3 + 4800 + 12] += fire; | |
mtx.data[p + 3 + 4800 + 16] += fire; | |
mtx.data[p + 3 + 4800 + 20] += fire; | |
mtx.data[p + 3 + 4800 + 24] += fire; | |
mtx.data[p + 3 + 6400] += fire; | |
mtx.data[p + 3 + 6400 + 4] += fire; | |
mtx.data[p + 3 + 6400 + 8] += fire; | |
mtx.data[p + 3 + 6400 + 12] += fire; | |
mtx.data[p + 3 + 6400 + 16] += fire; | |
mtx.data[p + 3 + 6400 + 20] += fire; | |
mtx.data[p + 3 + 6400 + 24] += fire; | |
mtx.data[p + 3 + 8000] += fire; | |
mtx.data[p + 3 + 8000 + 4] += fire; | |
mtx.data[p + 3 + 8000 + 8] += fire; | |
mtx.data[p + 3 + 8000 + 12] += fire; | |
mtx.data[p + 3 + 8000 + 16] += fire; | |
mtx.data[p + 3 + 8000 + 20] += fire; | |
mtx.data[p + 3 + 8000 + 24] += fire; | |
} | |
} | |
} | |
ctx.putImageData(mtx, 236, 76); | |
for(var z = 0; z < 2; ++ z) { | |
ctx.strokeStyle = ["blue", "red"][z]; | |
ctx.fillStyle = ["grey", "silver"][z]; | |
ctx.beginPath(); | |
for(var i = 0; i < 8; ++ i) { | |
if(((data >> i) & 1) == z) { | |
ctx.moveTo(27, 16 + i * 20); | |
ctx.lineTo(88, 16 + (i < 5 ? i : (i - 5) * 2 + 7) * 20); | |
ctx.fillRect(8, 8.5 + i * 20, 18, 17.5); | |
ctx.strokeText(`D${i}`, 17, 20 + i * 20); | |
} | |
} | |
ctx.stroke(); | |
} | |
if(tick == 1 && (data & 0x40) == 0) | |
mask = ((mask & 0x07FFFFFF) << 1) | ((data & 0x80) >> 7); | |
tick = (data & 0x40) >> 6; | |
data = stream[time]; | |
if(-- delay < 0) { | |
delay = speed; | |
if(++ time >= stream.length) | |
time = 0; | |
} | |
requestAnimationFrame(show); | |
} | |
</script> | |
<style> | |
body { | |
margin :0 0 0 0; | |
} | |
canvas { | |
background-image:url('https://optochip.org/docum/store/factory/series/140509/1487235592-2-4687.jpg'); | |
background-position: 178px -34px; | |
background-size :77%; | |
} | |
</style> | |
</head> | |
<body> | |
<canvas id=IPV width=640 height=256></canvas> | |
<script>setTimeout(main, 1);</script> | |
</body> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment