Alright, this post has been a long time coming and as I keep getting hung up on going into how I control the text over WebSockets I’ve decided to just brain dump how I’m handling text parsing in ol’ stringless PBJS.
Credit for the font itself and character decoding goes to this hackaday.io post by PK (not that PK)
This code represents the 4th, maybe 5th attempt as I was unable to find a good way to render the text that was outside the color rendering, resulting in a display that wasn’t very dynamic.
In this iteration the text rendering is reduced to a single function call that takes an [X,Y] and returns true or false if the pixel should be lit. Two variables startx, starty represent where the text should start being drawn. The code has a bit of cruft left over in it (brain dump!) but should be pretty easy to follow and I’d be happy to answer any questions. Beyond the obvious cleanup I think there are some neat simple features to add (vertical next) and I’ll hopefully get to the next part of controlling the text over websockets soon. Once that is done I’ll start my relentless campaign of bugging @wizard until we get library includes, then some really cool things could be possible.
w = 30;
var alpha_len = 192;
var alpha = array(alpha_len);
alpha[0] = 0x00;
alpha[1] = 0x00; /*SPACE*/
alpha[2] = 0x49;
alpha[3] = 0x08; /*'!'*/
alpha[4] = 0xb4;
alpha[5] = 0x00; /*'"'*/
alpha[6] = 0xbe;
alpha[7] = 0xf6; /*'#'*/
alpha[8] = 0x7b;
alpha[9] = 0x7a; /*'$'*/
alpha[10] = 0xa5;
alpha[11] = 0x94; /*'%'*/
alpha[12] = 0x55;
alpha[13] = 0xb8; /*'&'*/
alpha[14] = 0x48;
alpha[15] = 0x00; /*''*/
alpha[16] = 0x29;
alpha[17] = 0x44; /*'('*/
alpha[18] = 0x44;
alpha[19] = 0x2a; /*')'*/
alpha[20] = 0x15;
alpha[21] = 0xa0; /*'*'*/
alpha[22] = 0x0b;
alpha[23] = 0x42; /*'+'*/
alpha[24] = 0x00;
alpha[25] = 0x51; /*','*/
alpha[26] = 0x03;
alpha[27] = 0x02; /*'-'*/
alpha[28] = 0x00;
alpha[29] = 0x08; /*'.'*/
alpha[30] = 0x25;
alpha[31] = 0x90; /*'/'*/
alpha[32] = 0x76;
alpha[33] = 0xba; /*'0'*/
alpha[34] = 0x59;
alpha[35] = 0x5c; /*'1'*/
alpha[36] = 0xc5;
alpha[37] = 0x9e; /*'2'*/
alpha[38] = 0xc5;
alpha[39] = 0x38; /*'3'*/
alpha[40] = 0x92;
alpha[41] = 0xe6; /*'4'*/
alpha[42] = 0xf3;
alpha[43] = 0x3a; /*'5'*/
alpha[44] = 0x73;
alpha[45] = 0xba; /*'6'*/
alpha[46] = 0xe5;
alpha[47] = 0x90; /*'7'*/
alpha[48] = 0x77;
alpha[49] = 0xba; /*'8'*/
alpha[50] = 0x77;
alpha[51] = 0x3a; /*'9'*/
alpha[52] = 0x08;
alpha[53] = 0x40; /*':'*/
alpha[54] = 0x08;
alpha[55] = 0x50; /*';'*/
alpha[56] = 0x2a;
alpha[57] = 0x44; /*'<'*/
alpha[58] = 0x1c;
alpha[59] = 0xe0; /*'='*/
alpha[60] = 0x88;
alpha[61] = 0x52; /*'>'*/
alpha[62] = 0xe5;
alpha[63] = 0x08; /*'?'*/
alpha[64] = 0x56;
alpha[65] = 0x8e; /*'@'*/
alpha[66] = 0x77;
alpha[67] = 0xb6; /*'A'*/
alpha[68] = 0x77;
alpha[69] = 0xb8; /*'B'*/
alpha[70] = 0x72;
alpha[71] = 0x8c; /*'C'*/
alpha[72] = 0xd6;
alpha[73] = 0xba; /*'D'*/
alpha[74] = 0x73;
alpha[75] = 0x9e; /*'E'*/
alpha[76] = 0x73;
alpha[77] = 0x92; /*'F'*/
alpha[78] = 0x72;
alpha[79] = 0xae; /*'G'*/
alpha[80] = 0xb7;
alpha[81] = 0xb6; /*'H'*/
alpha[82] = 0xe9;
alpha[83] = 0x5c; /*'I'*/
alpha[84] = 0x64;
alpha[85] = 0xaa; /*'J'*/
alpha[86] = 0xb7;
alpha[87] = 0xb4; /*'K'*/
alpha[88] = 0x92;
alpha[89] = 0x9c; /*'L'*/
alpha[90] = 0xbe;
alpha[91] = 0xb6; /*'M'*/
alpha[92] = 0xd6;
alpha[93] = 0xb6; /*'N'*/
alpha[94] = 0x56;
alpha[95] = 0xaa; /*'O'*/
alpha[96] = 0xd7;
alpha[97] = 0x92; /*'P'*/
alpha[98] = 0x76;
alpha[99] = 0xee; /*'Q'*/
alpha[100] = 0x77;
alpha[101] = 0xb4; /*'R'*/
alpha[102] = 0x71;
alpha[103] = 0x38; /*'S'*/
alpha[104] = 0xe9;
alpha[105] = 0x48; /*'T'*/
alpha[106] = 0xb6;
alpha[107] = 0xae; /*'U'*/
alpha[108] = 0xb6;
alpha[109] = 0xaa; /*'V'*/
alpha[110] = 0xb6;
alpha[111] = 0xf6; /*'W'*/
alpha[112] = 0xb5;
alpha[113] = 0xb4; /*'X'*/
alpha[114] = 0xb5;
alpha[115] = 0x48; /*'Y'*/
alpha[116] = 0xe5;
alpha[117] = 0x9c; /*'Z'*/
alpha[118] = 0x69;
alpha[119] = 0x4c; /*'['*/
alpha[120] = 0x91;
alpha[121] = 0x24; /*'\'*/
alpha[122] = 0x64;
alpha[123] = 0x2e; /*']'*/
alpha[124] = 0x54;
alpha[125] = 0x00; /*'^'*/
alpha[126] = 0x00;
alpha[127] = 0x1c; /*'_'*/
alpha[128] = 0x44;
alpha[129] = 0x00; /*'backtick'*/
alpha[130] = 0x0e;
alpha[131] = 0xae; /*'a'*/
alpha[132] = 0x9a;
alpha[133] = 0xba; /*'b'*/
alpha[134] = 0x0e;
alpha[135] = 0x8c; /*'c'*/
alpha[136] = 0x2e;
alpha[137] = 0xae; /*'d'*/
alpha[138] = 0x0e;
alpha[139] = 0xce; /*'e'*/
alpha[140] = 0x56;
alpha[141] = 0xd0; /*'f'*/
alpha[142] = 0x55;
alpha[143] = 0x3B; /*'g'*/
alpha[144] = 0x93;
alpha[145] = 0xb4; /*'h'*/
alpha[146] = 0x41;
alpha[147] = 0x44; /*'i'*/
alpha[148] = 0x41;
alpha[149] = 0x51; /*'j'*/
alpha[150] = 0x97;
alpha[151] = 0xb4; /*'k'*/
alpha[152] = 0x49;
alpha[153] = 0x44; /*'l'*/
alpha[154] = 0x17;
alpha[155] = 0xb6; /*'m'*/
alpha[156] = 0x1a;
alpha[157] = 0xb6; /*'n'*/
alpha[158] = 0x0a;
alpha[159] = 0xaa; /*'o'*/
alpha[160] = 0xd6;
alpha[161] = 0xd3; /*'p'*/
alpha[162] = 0x76;
alpha[163] = 0x67; /*'q'*/
alpha[164] = 0x17;
alpha[165] = 0x90; /*'r'*/
alpha[166] = 0x0f;
alpha[167] = 0x38; /*'s'*/
alpha[168] = 0x9a;
alpha[169] = 0x8c; /*'t'*/
alpha[170] = 0x16;
alpha[171] = 0xae; /*'u'*/
alpha[172] = 0x16;
alpha[173] = 0xba; /*'v'*/
alpha[174] = 0x16;
alpha[175] = 0xf6; /*'w'*/
alpha[176] = 0x15;
alpha[177] = 0xb4; /*'x'*/
alpha[178] = 0xb5;
alpha[179] = 0x2b; /*'y'*/
alpha[180] = 0x1c;
alpha[181] = 0x5e; /*'z'*/
alpha[182] = 0x6b;
alpha[183] = 0x4c; /*'{'*/
alpha[184] = 0x49;
alpha[185] = 0x48; /*'|'*/
alpha[186] = 0xc9;
alpha[187] = 0x5a; /*'}'*/
alpha[188] = 0x54;
alpha[189] = 0x00; /*'~'*/
alpha[190] = 0x56;
alpha[191] = 0xe2; /*''*/
export var strlen = 13;
export var helloworld = array(300)
helloworld[0] = 80
helloworld[1] = 74
helloworld[2] = 88
helloworld[3] = 88
helloworld[4] = 94
helloworld[5] = 24
helloworld[6] = 0
helloworld[7] = 110
helloworld[8] = 94
helloworld[9] = 100
helloworld[10] = 88
helloworld[11] = 72
helloworld[12] = 2
function indexOf(arr, val) {
for(var i = 0; i < alpha_len; i++)
if(arr[i] == val) return i;
return -1;
}
// used to hold current charecter being rendered
var chararr = array(2)
function getcharbytes(c) {
// grab the two bytes that represent this char
chararr[0] = alpha[c];
chararr[1] = alpha[c + 1];
return chararr;
}
export var color = 1;
export var startx = 1;
export var starty = 2;
var pWidth = 3;
var cWidth = pWidth + 1;
export var byte;
export var cIdx;
export var c;
export var line;
export var cPos;
var t1;
var z;
var timeout = 0;
export var scrolldir = 0;
export function beforeRender(t) {
timeout += t;
t1 = time(.05)*PI2
z = 1+ wave(time(.2))*5
// advance the text every 100ms
// startx +/- 1 depending on present direction
if(timeout > 100) {
if(!scrolldir)
startx -= 1;
else
startx += 1;
timeout = 0;
}
// moving <<<<<<<
if(scrolldir && startx == 3) {
scrolldir = !scrolldir;
} else if(!scrolldir && abs(startx) >= (strlen + 9)) {
scrolldir = !scrolldir;
} else {
}
}
function getPixelState(x, y) {
// TODO check upper bounds of X
if(x < startx || y < starty) return 0;
cIdx = floor((x - startx) / cWidth);
if(cIdx >= strlen) return 0;
c = getcharbytes(helloworld[cIdx]);
var py = y - starty;
var cx = x + 1 - startx;
if(c[1] & 1 == 1) py -= 1;
// fetch the line for this pixel
if(py == 0)
byte = c[0] >> 4;
else if(py == 1)
byte = c[0] >> 1;
else if(py == 2)
byte = (c[0] & 0x03) << 2 | (c[1] & 0x02);
else if(py == 3)
byte = c[1] >> 4;
else if(py == 4)
byte = c[1] >> 1;
else return 0;
line = byte & 0x0e;
// return if bit is set
return line & 1 << (4 - cx % 4);
}
export function render(index) {
y = floor(index / w)
x = index % w
x = (y % 2 == 1 ? x : w-1-x)
if(getPixelState(x,y)) {
hsv(sin(x/w*z + t1),1,1)
} else {
hsv(0,0,0);
}
}