<!DOCTYPE html>
<!--
Author: Twily 2025
Website: twily.info
-->
<html>
<head>
<script>
var $=function(id) { return document.getElementById(id); };
var isOdd=function(number) { return Math.abs(number % 2) === 1; };
var letterC=[ // 65 - 90
[ // A
0b01110,
0b10001,
0b11111,
0b10001,
0b10001
],
[ // B
0b11110,
0b10001,
0b11111,
0b10001,
0b11110
],
[ // C
0b01110,
0b10001,
0b10000,
0b10001,
0b01110
],
[ // D
0b11110,
0b10001,
0b10001,
0b10001,
0b11110
],
[ // E
0b11111,
0b10000,
0b11100,
0b10000,
0b11111
],
[ // F
0b11111,
0b10000,
0b11100,
0b10000,
0b10000
],
[ // G
0b01110,
0b10000,
0b10111,
0b10001,
0b01110
],
[ // H
0b10001,
0b10001,
0b11111,
0b10001,
0b10001
],
[ // I
0b01110,
0b00100,
0b00100,
0b00100,
0b01110
],
[ // J
0b00001,
0b00001,
0b00001,
0b10001,
0b01110
],
[ // K
0b10001,
0b10010,
0b11100,
0b10010,
0b10001
],
[ // L
0b10000,
0b10000,
0b10000,
0b10000,
0b11111
],
[ // M
0b01010,
0b10101,
0b10101,
0b10101,
0b10101
],
[ // N
0b10001,
0b11001,
0b10101,
0b10011,
0b10001
],
[ // O
0b01110,
0b10001,
0b10001,
0b10001,
0b01110
],
[ // P
0b11110,
0b10001,
0b11110,
0b10000,
0b10000
],
[ // Q
0b01110,
0b10001,
0b10001,
0b10011,
0b01101
],
[ // R
0b11110,
0b10001,
0b11110,
0b10001,
0b10001
],
[ // S
0b01111,
0b10000,
0b01110,
0b00001,
0b11110
],
[ // T
0b11111,
0b00100,
0b00100,
0b00100,
0b00100
],
[ // U
0b10001,
0b10001,
0b10001,
0b10001,
0b01110
],
[ // V
0b10001, //17
0b10001, //17
0b10001, //17
0b01010, //10
0b00100 //5
],
[ // W
0b10101, //21
0b10101, //21
0b10101, //21
0b10101, //21
0b01010 //10
],
[ // X
0b10001, //17
0b01010, //10
0b00100, //5
0b01010, //10
0b10001 //17
],
[ // Y
0b10001, //17
0b01010, //10
0b00100, //5
0b00100, //5
0b00100 //5
],
[ // Z
0b11111, //31
0b00010, //2
0b00100, //5
0b01000, //8
0b11111 //31
],
];
var letterL=[ // 97 - 122
[ // a
0b01110,
0b00001,
0b00111,
0b01001,
0b00111
],
[ // b
0b01000,
0b01110,
0b01001,
0b01001,
0b01110
],
[ // c
0b00000,
0b00111,
0b01000,
0b01000,
0b00111
],
[ // d
0b00001,
0b00111,
0b01001,
0b01001,
0b00111
],
[ // e
0b00110,
0b01001,
0b01111,
0b01000,
0b00110
],
[ // f
0b00011,
0b00100,
0b01111,
0b00100,
0b00100
],
[ // g
0b00111,
0b01001,
0b00111,
0b00001,
0b00110
],
[ // h
0b01000,
0b01110,
0b01001,
0b01001,
0b01001
],
[ // i
0b00100,
0b00000,
0b00100,
0b00100,
0b00100
],
[ // j
0b00010,
0b00000,
0b00010,
0b10010,
0b01100
],
[ // k
0b01000,
0b01000,
0b01010,
0b01100,
0b01010
],
[ // l
0b00100,
0b00100,
0b00100,
0b00100,
0b00100
],
[ // m
0b00000,
0b11010,
0b10101,
0b10101,
0b10101
],
[ // n
0b00000,
0b01110,
0b01001,
0b01001,
0b01001
],
[ // o
0b00000,
0b00110,
0b01001,
0b01001,
0b00110
],
[ // p
0b00000,
0b01110,
0b01001,
0b01110,
0b01000
],
[ // q
0b00000,
0b00111,
0b01001,
0b00111,
0b00001
],
[ // r
0b00000,
0b01000,
0b01110,
0b01000,
0b01000
],
[ // s
0b01111,
0b10000,
0b01110,
0b00001,
0b11110
],
[ // t
0b00100,
0b01110,
0b00100,
0b00100,
0b00010
],
[ // u
0b00000,
0b10001,
0b10001,
0b10001,
0b01110
],
[ // v
0b00000,
0b10001,
0b10001,
0b01010,
0b00100
],
[ // w
0b00000,
0b10101,
0b10101,
0b10101,
0b01010
],
[ // x
0b00000,
0b10001,
0b01110,
0b01110,
0b10001
],
[ // y
0b00000,
0b10001,
0b01010,
0b00100,
0b01000
],
[ // z
0b00000,
0b11111,
0b00100,
0b01000,
0b11111
],
];
var numbin=[ // 48 - 57
[ // 0
0b01110,
0b10001,
0b10101,
0b10001,
0b01110
],
[ // 1
0b00100,
0b01100,
0b00100,
0b00100,
0b01110
],
[ // 2
0b11110,
0b00001,
0b01110,
0b10000,
0b11111
],
[ // 3
0b01111,
0b00001,
0b01110,
0b00001,
0b01110
],
[ // 4
0b10010,
0b10010,
0b11111,
0b00010,
0b00010
],
[ // 5
0b11111,
0b10000,
0b11110,
0b00001,
0b11110
],
[ // 6
0b01111,
0b10000,
0b11111,
0b10001,
0b01110
],
[ // 7
0b11111,
0b00010,
0b00100,
0b01000,
0b10000
],
[ // 8
0b01110,
0b10001,
0b01110,
0b10001,
0b01110
],
[ // 9
0b01110,
0b10001,
0b01111,
0b00001,
0b01110
],
];
var symbol0=[ // 32 - 47
[ // blank(space) -- tab = 4 spaces
0b00000,
0b00000,
0b00000,
0b00000,
0b00000
],
[ // !
0b00100,
0b00100,
0b00100,
0b00000,
0b00100
],
[ // "
0b01010,
0b01010,
0b00000,
0b00000,
0b00000
],
[ // # (hashtag)
0b01010,
0b11111,
0b01010,
0b11111,
0b01010
],
[ // $
0b01111,
0b10100,
0b01110,
0b00101,
0b11110
],
[ // %
0b11001,
0b11010,
0b00100,
0b01011,
0b10011
],
[ // &
0b00110,
0b01010,
0b01100,
0b10010,
0b01101
],
[ // '
0b00100,
0b00100,
0b00000,
0b00000,
0b00000
],
[ // (
0b00010,
0b00100,
0b00100,
0b00100,
0b00010
],
[ // )
0b01000,
0b00100,
0b00100,
0b00100,
0b01000
],
[ // *
0b10101,
0b01110,
0b11111,
0b01110,
0b10101
],
[ // +
0b00100,
0b00100,
0b11111,
0b00100,
0b00100
],
[ // , (comma)
0b00000,
0b00000,
0b00000,
0b00100,
0b01000
],
[ // - (dash)
0b00000,
0b00000,
0b01111,
0b00000,
0b00000
],
[ // . (dot)
0b00000,
0b00000,
0b00000,
0b00000,
0b01000
],
[ // /
0b00001,
0b00010,
0b00100,
0b01000,
0b10000
],
// --extras index 16 and 17
[ // full block
0b11111,
0b11111,
0b11111,
0b11111,
0b11111
],
[ // square block
0b00000,
0b01110,
0b01010,
0b01110,
0b00000
],
];
var symbol1=[ // 58 - 64
[ // :
0b00000,
0b00100,
0b00000,
0b00100,
0b00000
],
[ // ;
0b00000,
0b00100,
0b00000,
0b00100,
0b00100
],
[ // <
0b00010,
0b00100,
0b01000,
0b00100,
0b00010
],
[ // =
0b00000,
0b11111,
0b00000,
0b11111,
0b00000
],
[ // >
0b01000,
0b00100,
0b00010,
0b00100,
0b01000
],
[ // ?
0b01110,
0b10010,
0b00100,
0b00000,
0b00100
],
[ // @
0b01100,
0b11010,
0b11010,
0b10111,
0b01110
],
];
var symbol2=[ // 91 - 96
[ // [
0b00110,
0b00100,
0b00100,
0b00100,
0b00110
],
[ // \
0b10000,
0b01000,
0b00100,
0b00010,
0b00001
],
[ // ]
0b01100,
0b00100,
0b00100,
0b00100,
0b01100
],
[ // ^
0b00100,
0b01010,
0b10001,
0b00000,
0b00000
],
[ // _ (underline)
0b00000,
0b00000,
0b00000,
0b00000,
0b11111
],
[ // `
0b01000,
0b00100,
0b00000,
0b00000,
0b00000
],
];
var symbol3=[ // 123 - 126
[ // {
0b00010,
0b00100,
0b01100,
0b00100,
0b00010
],
[ // |
0b00100,
0b00100,
0b00100,
0b00100,
0b00100
],
[ // }
0b01000,
0b00100,
0b00110,
0b00100,
0b01000
],
[ // ~
0b00000,
0b00000,
0b01010,
0b10100,
0b00000
],
];
var allbintodec=[ // for debug
0b00000, // 0
0b00001,
0b00010,
0b00011,
0b00100,
0b00101,
0b00110,
0b00111,
0b01000,
0b01001,
0b01010,
0b01011,
0b01100,
0b01101,
0b01110,
0b01111,
0b10000,
0b10001,
0b10010,
0b10011,
0b10100,
0b10101,
0b10110,
0b10111,
0b11000,
0b11001,
0b11010,
0b11011,
0b11100,
0b11101,
0b11110,
0b11111 //31
];
// --letters (letterC[] | letterL[])
// A-Z = 65-90 (-65 = 0-25)
// a-z = 97-122 (-97 = 0-25)
//
// --numbers (numbin[])
// 0-9 = 48-57 (-48 = 0-9)
//
// space = 32 (symbol0[0])~
// extra block = (symbol0[16])
// extra block = (symbol0[17])
var lcdpixel={
width: 8,
height: 8,
gapV: 2,
gapH: 2,
cols: 5,
rows: 5,
}
// block width = (cols * width) + (cols * gapV)
// block height = (rows * height) + (rows * gapH)
var cString="Hello World! How far can we go?";
var cLen=cString.length;
var cPos=0;
var csPos=0;
var lcPos=0;
var s_cPos=0;
var s_csPos=0;
var cnv,ctx;
// fixed width
//var cnvW=602;
//var cnvH=52;
//var pixelW=Math.floor((cnvW - lcdpixel.gapV) / (lcdpixel.width + lcdpixel.gapV));
// dynamic width
var pixelH=5;
var pixelW=60;
var cnvW=(pixelW * (lcdpixel.width + lcdpixel.gapV)) + lcdpixel.gapV;
var cnvH=(pixelH * (lcdpixel.height + lcdpixel.gapH)) + lcdpixel.gapH;
var maxSlot=(cnvW / ((lcdpixel.width + lcdpixel.gapV) * lcdpixel.cols));
function init() {
//var html="binary dec<br /><br />";
//for(var i=0;i<allbintodec.length;i++) {
// var abtd=allbintodec[i];
// var ab=abtd.toString(2);
// while(ab.length<5) {
// ab="0"+ab;
// }
// html+=ab+" "+abtd+"<br />";
//}
//$('log').insertAdjacentHTML('beforeend',html);
cnv=$('cnv');
ctx=cnv.getContext('2d');
cnv.width=cnvW;
cnv.height=cnvH;
cnv.style.width=cnvW+"px";
cnv.style.height=cnvH+"px";
cnv.style.border="1px solid #f0f";
//ctx.clearRect(0,0,cnvW,cnvH);
//ctx.fillColor="#000"; // black
//ctx.fillRect(0,0,cnvW/2,cnvH); // x,y,w,h
animdraw();
}
var fps=1000/60; // render
var textfps=1000/12 // scroll (steps per second)
var fdiff=0;
var dT=null;
var ldT=null;
var adT;
var uiUpdate=5; // per sec
var uiWait=0;
var bCharLog="";
var bCharSplit=5;
function animdraw() {
clearTimeout(adT);
var delta=dT-ldT;
fdiff=delta-fps;
if(fdiff<0) fdiff=0; // sleep time is 60fps not counting
else if(fdiff>fps) fdiff=fps; // processing time, fdiff does~
lcPos-=delta;
if(uiWait<=0) {
//console.log("delta~"+delta);
$('fps').innerHTML=delta+" . "+(1000/(fps+fdiff));
$('char').innerHTML=bCharLog;
$('lit').innerHTML="s_cPos: "+s_cPos+", s_csPos: "+s_csPos+"<br />cPos: "+cPos+", csPos: "+csPos;
uiWait=1000/uiUpdate;
} else {
uiWait-=delta;
}
ldT=dT;
dT=Date.now();
bCharLog="";
ctx.clearRect(0,0,cnvW,cnvH);
ctx.fillStyle="#000"; // black
ctx.fillRect(0,0,cnvW,cnvH); // x,y,w,h
if(lcPos<=0) {
s_csPos++;
if(s_csPos>=5) {
s_csPos=0;
s_cPos++;
if(s_cPos>=cLen) {
s_cPos=-maxSlot; // reset
}
}
lcPos=textfps;
}
cPos=s_cPos;
csPos=s_csPos;
// draw grid~~
let posX=0;
let posY=0;
var bChar=[];
var blank=false;
for(var i=0;i<pixelW;i++) {
posX=(i * (lcdpixel.width + lcdpixel.gapV)) + lcdpixel.gapV;
if(!blank && cPos>=0) { // filter before and after string = empty
let charCode=cString.charCodeAt(cPos);
//let printed=0;
let selIdx=0;
if(charCode>=65 && charCode<=90) { // A-Z
selIdx=charCode-65; // starts 0
bChar=letterC[selIdx];
} else if(charCode>=97 && charCode<=122) { // a-z
selIdx=charCode-97;
bChar=letterL[selIdx];
} else if(charCode>=48 && charCode<=57) { // 0-9
selIdx=charCode-48;
bChar=numbin[selIdx];
} else if(charCode>=32 && charCode<=47) { // !"#$%&'()*+,-./
selIdx=charCode-32;
bChar=symbol0[selIdx];
} else if(charCode>=58 && charCode<=64) { // :;<=>?@
selIdx=charCode-58;
bChar=symbol1[selIdx];
} else if(charCode>=91 && charCode<=96) { // [\]^_`
selIdx=charCode-91;
bChar=symbol2[selIdx];
} else if(charCode>=123 && charCode<=126) { // {-~
selIdx=charCode-123;
bChar=symbol3[selIdx];
} else {
bChar=symbol0[17]; // square block not found
//let charC=cString.charAt(cPos);
//$('char').innerHTML=charCode+" "+charC;
//printed=1;
//switch(charCode) {
// case "-":
// selIdx=0;
// break;
// default:
//}
}
//if(!printed) {
// $('char').innerHTML=charCode+" "+selIdx;
//}
} else { // blank
//bChar=symbol0[17]; // square block not found
bChar=symbol0[0]; // empty space
}
bCharLog+="i="+i+": "+JSON.stringify(bChar)+", ";
bCharSplit--;
if(bCharSplit<=0) {
bCharLog+="<br />";
bCharSplit=5;
}
//if(i>=5) break;
if(bChar.length==0) {
bCharLog+="null";
break;
}
for(var j=0;j<pixelH;j++) {
posY=(j * (lcdpixel.height + lcdpixel.gapH)) + lcdpixel.gapH;
let lit=false;
if(csPos==0) {
if(bChar[j]>=16 && bChar[j]<=31) {
lit=true;
}
} else if(csPos==1) {
if((bChar[j]>=8 && bChar[j]<=15) || (bChar[j]>=24 && bChar[j]<=31)) {
lit=true;
}
} else if(csPos==2) {
if((bChar[j]>=4 && bChar[j]<=7) || (bChar[j]>=12 && bChar[j]<=15) ||
(bChar[j]>=20 && bChar[j]<=23) || (bChar[j]>=28 && bChar[j]<=31)) {
lit=true;
}
} else if(csPos==3) {
if((bChar[j]>=2 && bChar[j]<=3) || (bChar[j]>=6 && bChar[j]<=7) ||
(bChar[j]>=10 && bChar[j]<=11) || (bChar[j]>=14 && bChar[j]<=15) ||
(bChar[j]>=18 && bChar[j]<=19) || (bChar[j]>=22 && bChar[j]<=23) ||
(bChar[j]>=26 && bChar[j]<=27) || (bChar[j]>=30 && bChar[j]<=31)) {
lit=true;
}
} else if(csPos==4) {
if(isOdd(bChar[j])) {
lit=true;
}
}
if(lit) {
ctx.fillStyle="#0f0"; // green
} else {
ctx.fillStyle="#050"; // green
}
ctx.fillRect(posX,posY,lcdpixel.width,lcdpixel.height);
} // loop H
csPos++;
if(csPos>=5) {
csPos=0;
cPos++;
if(cPos>=cLen) {
blank=true;
}
}
//console.log("cPos: "+cPos+", csPos: "+csPos);
} // loop W
//console.log("new");
adT=setTimeout(function() { animdraw(); },fps-fdiff);
}
function setText(txt) {
cString=txt;
cLen=cString.length;
}
function setTFps(val) {
textfps=1000/val;
$('txttfps').innerHTML=val;
if(val>1000/fps) {
$('rngfps').value=val;
setFps(val);
}
}
function setFps(val) {
fps=1000/val;
$('txtfps').innerHTML=val;
if(val<1000/textfps) {
$('rngtfps').value=val;
setTFps(val);
}
}
function updatelcd() {
cnvW=(pixelW * (lcdpixel.width + lcdpixel.gapV)) + lcdpixel.gapV;
cnvH=(pixelH * (lcdpixel.height + lcdpixel.gapH)) + lcdpixel.gapH;
maxSlot=(cnvW / ((lcdpixel.width + lcdpixel.gapV) * lcdpixel.cols));
console.log("cnvW: "+cnvW);
console.log("lcdpixel.width+lcdpixel.gapV: "+(lcdpixel.width + lcdpixel.gapV));
console.log("maxSlot: "+maxSlot);
cnv.width=cnvW;
cnv.height=cnvH;
cnv.style.width=cnvW+"px";
cnv.style.height=cnvH+"px";
}
function setW(val) {
pixelW=val;
$('txtW').innerHTML=val;
updatelcd();
}
function setPW(val) {
lcdpixel.width=parseInt(val);
$('txtPW').innerHTML=val;
updatelcd();
}
function setPH(val) {
lcdpixel.height=parseInt(val);
$('txtPH').innerHTML=val;
updatelcd();
}
function setGV(val) {
lcdpixel.gapV=parseInt(val);
$('txtGV').innerHTML=val;
updatelcd();
}
function setGH(val) {
lcdpixel.gapH=parseInt(val);
$('txtGH').innerHTML=val;
updatelcd();
}
</script>
</head>
<body onload="init();">
<canvas id="cnv"></canvas>
<input type="text" value="" onchange="setText(this.value);" />
<br />
textFPS: <span id="txttfps">12</span> <input type="range" min="1" max="1000" value="12" step="1" onchange="setTFps(this.value);" id="rngtfps">
<br />
FPS: <span id="txtfps">60</span> <input type="range" min="1" max="1000" value="60" step="1" onchange="setFps(this.value);" id="rngfps">
<br />
stepW: <span id="txtW">60</span> <input type="range" min="0" max="255" value="60" step="1" onchange="setW(this.value);">
<br />
pixelW: <span id="txtPW">8</span> <input type="range" min="1" max="100" value="8" step="1" onchange="setPW(this.value);">
<br />
pixelH: <span id="txtPH">8</span> <input type="range" min="1" max="100" value="8" step="1" onchange="setPH(this.value);">
<br />
gapV: <span id="txtGV">2</span> <input type="range" min="0" max="100" value="2" step="1" onchange="setGV(this.value);">
<br />
gapH: <span id="txtGH">2</span> <input type="range" min="0" max="100" value="2" step="1" onchange="setGH(this.value);">
<div id="log"></div>
<div id="fps"></div>
<div id="char"></div>
<div id="lit"></div>
</body>
</html>
Top