obniz
Version:
obniz sdk for javascript
2,200 lines (2,199 loc) • 42.5 kB
JavaScript
"use strict";
/**
* @packageDocumentation
* @module Parts.ST7735S
*/
Object.defineProperty(exports, "__esModule", { value: true });
class ST7735S {
constructor() {
this.debugprint = false;
this.width = 0;
this.height = 0;
this.x_offset = 0;
this.y_offset = 0;
this.writeBuffer = [];
this.keys = ['sclk', 'mosi', 'cs', 'res', 'dc'];
this.requiredKeys = [];
}
static info() {
return {
name: 'ST7735S',
};
}
wired(obniz) {
this.debugprint = false;
this.obniz = obniz;
this.io_dc = obniz.getIO(this.params.dc);
this.io_res = obniz.getIO(this.params.res);
this.io_cs = obniz.getIO(this.params.cs);
this.params.frequency = 16 * 1000 * 1000; // 16MHz
this.params.mode = 'master';
this.params.clk = this.params.sclk;
this.params.drive = '3v';
this.spi = this.obniz.getSpiWithConfig(this.params);
this.io_dc.output(true);
this.io_cs.output(false);
this.width = ST7735S_TFTWIDTH;
this.height = ST7735S_TFTHEIGHT;
this.rotation = 0;
this.x_offset = 26;
this.y_offset = 2;
this.writeBuffer = []; // 1024bytes bufferring
this._setPresetColor();
this.init();
}
print_debug(v) {
if (this.debugprint) {
console.log(
// eslint-disable-next-line prefer-rest-params
'SainSmartTFT18LCD: ' + Array.prototype.slice.call(arguments).join(''));
}
}
_deadSleep(waitMsec) {
const startMsec = new Date();
while (new Date() - startMsec < waitMsec)
;
}
_reset() {
this.io_res.output(false);
this._deadSleep(10);
this.io_res.output(true);
this._deadSleep(10);
}
writeCommand(cmd) {
this.io_dc.output(false);
this.io_cs.output(false);
this.spi.write([cmd]);
this.io_cs.output(true);
}
writeData(data) {
this.io_dc.output(true);
this.io_cs.output(false);
this.spi.write(data);
this.io_cs.output(true);
}
write(cmd, data) {
if (data.length === 0) {
return;
}
this.writeCommand(cmd);
this.writeData(data);
}
async asyncwait() {
return await this.spi.writeWait([0x00]);
}
_writeFlush() {
while (this.writeBuffer.length > 0) {
if (this.writeBuffer.length > 1024) {
const data = this.writeBuffer.slice(0, 1024);
this.writeData(data);
this.writeBuffer.splice(0, 1024);
}
else {
if (this.writeBuffer.length > 0) {
this.writeData(this.writeBuffer);
}
this.writeBuffer = [];
}
}
}
_writeBuffer(data) {
if (data && data.length > 0) {
this.writeBuffer = this.writeBuffer.concat(data);
}
else {
this._writeFlush();
}
}
color16(r, g, b) {
// 1st byte (r & 0xF8 | g >> 5)
// 2nd byte (g & 0xFC << 3 | b >> 3)
return ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3);
}
complementaryColor16(color) {
const r = (color & 0xf800) >> 8;
const g = (color & 0x7e0) >> 3;
const b = (color & 0x1f) << 3;
const x = Math.max(r, g, b) + Math.min(r, g, b);
return this.color16(x - r, x - g, x - b);
}
reverseColor16(color) {
const r = (color & 0xf800) >> 8;
const g = (color & 0x7e0) >> 3;
const b = (color & 0x1f) << 3;
const x = 0xff;
return this.color16(x - r, x - g, x - b);
}
_initG() {
// initialize display
this.writeCommand(ST7735_SWRESET);
this.obniz.wait(150);
this.writeCommand(ST7735_SLPOUT); // Sleep out & booster on
this.obniz.wait(500);
this.write(ST7735_FRMCTR1, [0x01, 0x2c, 0x2d]);
this.write(ST7735_FRMCTR2, [0x01, 0x2c, 0x2d]);
this.write(ST7735_FRMCTR3, [0x01, 0x2c, 0x2d, 0x01, 0x2c, 0x2d]);
this.write(ST7735_INVCTR, [0x07]);
this.write(ST7735_PWCTR1, [0xa2, 0x02, 0x84]);
this.write(ST7735_PWCTR2, [0xc5]);
this.write(ST7735_PWCTR3, [0x0a, 0x00]);
this.write(ST7735_PWCTR4, [0x8a, 0x2a]);
this.write(ST7735_PWCTR5, [0x8a, 0xee]);
this.write(ST7735_VMCTR1, [0x0e]);
this.writeCommand(ST7735_INVOFF);
this.write(ST7735_MADCTL, [0xc8]);
this.write(ST7735_COLMOD, [0x05]);
this.write(ST7735_CASET, [0x00, 0x00, 0x00, 0x7f]);
this.write(ST7735_RASET, [0x00, 0x00, 0x00, 0x9f]);
this.writeCommand(ST7735_INVON);
this.write(ST7735_GMCTRP1, [
0x02,
0x1c,
0x07,
0x12,
0x37,
0x32,
0x29,
0x2d,
0x29,
0x25,
0x2b,
0x39,
0x00,
0x01,
0x03,
0x10,
]);
this.write(ST7735_GMCTRN1, [
0x03,
0x1d,
0x07,
0x06,
0x2e,
0x2c,
0x29,
0x2d,
0x2e,
0x2e,
0x37,
0x3f,
0x00,
0x00,
0x02,
0x10,
]);
}
init() {
this._reset();
this._initG();
this.setDisplayOn();
this.setRotation(0);
}
setDisplayOn() {
this.writeCommand(ST7735_DISPON);
}
setDisplayOff() {
this.writeCommand(ST7735_DISPOFF);
}
setDisplay(on) {
if (on === true) {
this.setDisplayOn();
}
else {
this.setDisplayOff();
}
}
setInversionOn() {
this.writeCommand(ST7735_INVON);
}
setInversionOff() {
this.writeCommand(ST7735_INVOFF);
}
setInversion(inversion) {
if (inversion === true) {
this.setInversionOn();
}
else {
this.setInversionOff();
}
}
setRotation(m) {
const MADCTL_MY = 0x80;
const MADCTL_MX = 0x40;
const MADCTL_MV = 0x20;
// const MADCTL_ML = 0x10;
const MADCTL_RGB = 0x00; // always RGB, never BGR
// const MADCTL_MH = 0x04;
let data = [];
this.rotation = m % 4; // can't be higher than 3
switch (this.rotation) {
case 0:
data = [MADCTL_MX | MADCTL_MY | MADCTL_RGB];
this.width = ST7735S_TFTWIDTH;
this.height = ST7735S_TFTHEIGHT;
break;
case 1:
data = [MADCTL_MY | MADCTL_MV | MADCTL_RGB];
this.width = ST7735S_TFTHEIGHT;
this.height = ST7735S_TFTWIDTH;
break;
case 2:
data = [MADCTL_RGB];
this.width = ST7735S_TFTWIDTH;
this.height = ST7735S_TFTHEIGHT;
break;
case 3:
data = [MADCTL_MX | MADCTL_MV | MADCTL_RGB];
this.width = ST7735S_TFTHEIGHT;
this.height = ST7735S_TFTWIDTH;
break;
}
this.write(ST7735_MADCTL, data);
this.setAddrWindow(0, 0, this.width - 1, this.height - 1);
}
setAddrWindow(x0, y0, x1, y1) {
this.print_debug(`setAddrWindow: (x0: ${x0}, y0: ${y0}) - (x1: ${x1}, y1: ${y1})`);
if (x0 < 0) {
x0 = 0;
}
if (y0 < 0) {
y0 = 0;
}
if (x1 < 0) {
x1 = 0;
}
if (y1 < 0) {
y1 = 0;
}
if (this.rotation === 0 || this.rotation === 2) {
x0 = x0 + this.x_offset;
x1 = x1 + this.x_offset;
y0 = y0 + this.y_offset;
y1 = y1 + this.y_offset;
}
else {
x0 = x0 + this.y_offset;
x1 = x1 + this.y_offset;
y0 = y0 + this.x_offset;
y1 = y1 + this.x_offset;
}
// column addr set
this.write(ST7735_CASET, [0x00, x0, 0x00, x1]); // XSTART-XEND
// row addr set
this.write(ST7735_RASET, [0x00, y0, 0x00, y1]); // YSTART-YEND
// write to RAM
this.writeCommand(ST7735_RAMWR);
this.writeBuffer = [];
}
// __swap(a, b) { let t = a; a = b; b = t; }
fillScreen(color) {
this.fillRect(0, 0, this.width, this.height, color);
}
fillRect(x, y, width, height, color) {
if (x >= this.width || y >= this.height) {
return;
}
if (x + width - 1 >= this.width) {
width = this.width - x;
}
if (y + height - 1 >= this.height) {
height = this.height - y;
}
const pixels = this._color2pixels(width, height, color);
this.rawBound16(x, y, width, height, pixels, true);
}
drawRect(x, y, width, height, color) {
this.drawHLine(x, y, width, color);
this.drawHLine(x, y + height - 1, width, color);
this.drawVLine(x, y, height, color);
this.drawVLine(x + width - 1, y, height, color);
}
drawCircle(center_x, center_y, radius, color) {
let f = 1 - radius;
let ddF_x = 1;
let ddF_y = -2 * radius;
let x = 0;
let y = radius;
this.drawPixel(center_x, center_y + radius, color);
this.drawPixel(center_x, center_y - radius, color);
this.drawPixel(center_x + radius, center_y, color);
this.drawPixel(center_x - radius, center_y, color);
while (x < y) {
if (f >= 0) {
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
this.drawPixel(center_x + x, center_y + y, color);
this.drawPixel(center_x - x, center_y + y, color);
this.drawPixel(center_x + x, center_y - y, color);
this.drawPixel(center_x - x, center_y - y, color);
this.drawPixel(center_x + y, center_y + x, color);
this.drawPixel(center_x - y, center_y + x, color);
this.drawPixel(center_x + y, center_y - x, color);
this.drawPixel(center_x - y, center_y - x, color);
}
}
fillCircle(center_x, center_y, radius, color) {
this.drawVLine(center_x, center_y - radius, 2 * radius + 1, color);
this._fillCircleHelper(center_x, center_y, radius, 3, 0, color);
}
_fillCircleHelper(x0, y0, r, cornername, delta, color) {
let f = 1 - r;
let ddF_x = 1;
let ddF_y = -2 * r;
let x = 0;
let y = r;
while (x < y) {
if (f >= 0) {
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
if (cornername & 0x1) {
this.drawVLine(x0 + x, y0 - y, 2 * y + 1 + delta, color);
this.drawVLine(x0 + y, y0 - x, 2 * x + 1 + delta, color);
}
if (cornername & 0x2) {
this.drawVLine(x0 - x, y0 - y, 2 * y + 1 + delta, color);
this.drawVLine(x0 - y, y0 - x, 2 * x + 1 + delta, color);
}
}
}
drawRoundRect(x, y, width, height, round, color) {
this.drawHLine(x + round, y, width - 2 * round, color); // Top
this.drawHLine(x + round, y + height - 1, width - 2 * round, color); // Bottom
this.drawVLine(x, y + round, height - 2 * round, color); // Left
this.drawVLine(x + width - 1, y + round, height - 2 * round, color); // Right
this._drawCircleHelper(x + round, y + round, round, 1, color);
this._drawCircleHelper(x + width - round - 1, y + round, round, 2, color);
this._drawCircleHelper(x + width - round - 1, y + height - round - 1, round, 4, color);
this._drawCircleHelper(x + round, y + height - round - 1, round, 8, color);
}
fillRoundRect(x, y, width, height, round, color) {
this.fillRect(x + round, y, width - 2 * round, height, color);
this._fillCircleHelper(x + width - round - 1, y + round, round, 1, height - 2 * round - 1, color);
this._fillCircleHelper(x + round, y + round, round, 2, height - 2 * round - 1, color);
}
drawTriangle(x0, y0, x1, y1, x2, y2, color) {
this.drawLine(x0, y0, x1, y1, color);
this.drawLine(x1, y1, x2, y2, color);
this.drawLine(x2, y2, x0, y0, color);
}
fillTriangle(x0, y0, x1, y1, x2, y2, color) {
let a;
let b;
let y;
let last;
// Sort coordinates by Y order (y2 >= y1 >= y0)
if (y0 > y1) {
y1 = [y0, (y0 = y1)][0]; // this._swap(y0, y1);
x1 = [x0, (x0 = x1)][0]; // this._swap(x0, x1);
}
if (y1 > y2) {
y2 = [y1, (y1 = y2)][0]; // this._swap(y2, y1);
x2 = [x1, (x1 = x2)][0]; // this._swap(x2, x1);
}
if (y0 > y1) {
y1 = [y0, (y0 = y1)][0]; // this._swap(y0, y1);
x1 = [x0, (x0 = x1)][0]; // this._swap(x0, x1);
}
if (y0 === y2) {
// Handle awkward all-on-same-line case as its own thing
a = b = x0;
if (x1 < a) {
a = x1;
}
else if (x1 > b) {
b = x1;
}
if (x2 < a) {
a = x2;
}
else if (x2 > b) {
b = x2;
}
this.drawHLine(a, y0, b - a + 1, color);
return;
}
const dx01 = x1 - x0;
const dy01 = y1 - y0;
const dx02 = x2 - x0;
const dy02 = y2 - y0;
const dx12 = x2 - x1;
const dy12 = y2 - y1;
let sa = 0;
let sb = 0;
if (y1 === y2) {
last = y1;
}
else {
last = y1 - 1;
} // skip it
for (y = y0; y <= last; y++) {
a = x0 + Math.floor(sa / dy01);
b = x0 + Math.floor(sb / dy02);
sa += dx01;
sb += dx02;
if (a > b) {
b = [a, (a = b)][0];
} // this._swap(a,b);
this.drawHLine(a, y, b - a + 1, color);
}
sa = dx12 * (y - y1);
sb = dx02 * (y - y0);
for (; y <= y2; y++) {
a = x1 + Math.floor(sa / dy12);
b = x0 + Math.floor(sb / dy02);
sa += dx12;
sb += dx02;
if (a > b) {
b = [a, (a = b)][0];
} // this._swap(a,b);
this.drawHLine(a, y, b - a + 1, color);
}
}
drawVLine(x, y, height, color) {
if (height < 0) {
height = -height;
y = y - height;
}
if (x >= this.width || y >= this.height) {
return;
}
if (y + height - 1 >= this.height) {
height = this.height - y;
}
const pixels = this._color2pixels(1, height, color);
this.rawBound16(x, y, 1, height, pixels, false);
}
drawHLine(x, y, width, color) {
if (width < 0) {
width = -width;
x = x - width;
}
if (x >= this.width || y >= this.height) {
return;
}
if (x + width - 1 >= this.width) {
width = this.width - x;
}
const pixels = this._color2pixels(width, 1, color);
this.rawBound16(x, y, width, 1, pixels, false);
}
drawLine(x0, y0, x1, y1, color) {
if (x0 === x1) {
this.drawVLine(x0, y0, y1 - y0, color);
return;
}
if (y0 === y1) {
this.drawHLine(x0, y0, x1 - x0, color);
return;
}
const step = Math.abs(y1 - y0) > Math.abs(x1 - x0);
if (step) {
y0 = [x0, (x0 = y0)][0]; // this._swap(x0, y0);
y1 = [x1, (x1 = y1)][0]; // this._swap(x1, y1);
}
if (x0 > x1) {
x1 = [x0, (x0 = x1)][0]; // this._swap(x0, x1);
y1 = [y0, (y0 = y1)][0]; // this._swap(y0, y1);
}
const dx = x1 - x0;
const dy = Math.abs(y1 - y0);
let err = dx / 2;
const ystep = y0 < y1 ? 1 : -1;
for (; x0 <= x1; x0++) {
if (step) {
this.drawPixel(y0, x0, color);
}
else {
this.drawPixel(x0, y0, color);
}
err -= dy;
if (err < 0) {
y0 += ystep;
err += dx;
}
}
}
drawPixel(x, y, color) {
if (x < 0 || x >= this.width || y < 0 || y >= this.height) {
return;
}
this.rawBound16(x, y, 1, 1, [color], false);
}
drawChar(x, y, char, color, backgroundColor, size) {
// bg = bg || color;
size = size || 1;
if (x >= this.width || // Clip right
y >= this.height || // Clip bottom
x + 6 * size - 1 < 0 || // Clip left
y + 8 * size - 1 < 0) {
// Clip top
return;
}
if (color !== backgroundColor) {
this.drawChar2(x, y, char, color, backgroundColor, size);
return;
}
const c = char.charCodeAt(0);
for (let i = 0; i < 6; i++) {
let line = i === 5 ? 0 : font[c * 5 + i];
for (let j = 0; j < 8; j++) {
if (line & 0x1) {
if (size === 1) {
// default size
this.drawPixel(x + i, y + j, color);
}
else {
// big size
this.fillRect(x + i * size, y + j * size, size, size, color);
}
}
else if (backgroundColor !== color) {
if (size === 1) {
// default size
this.drawPixel(x + i, y + j, backgroundColor);
}
else {
// big size
this.fillRect(x + i * size, y + j * size, size, size, backgroundColor);
}
}
line >>= 1;
}
}
}
drawChar2(x, y, ch, color, bg, size) {
// bg = bg || color;
size = size || 1;
if (x >= this.width || // Clip right
y >= this.height || // Clip bottom
x + 6 * size - 1 < 0 || // Clip left
y + 8 * size - 1 < 0 // Clip top
) {
return;
}
const pixels = new Array(6 * 8 * size * size);
const c = ch.charCodeAt(0);
for (let i = 0; i < 6; i++) {
let line = i === 5 ? 0 : font[c * 5 + i];
for (let j = 0; j < 8; j++) {
const cl = line & 0x1 ? color : bg;
for (let w = 0; w < size; w++) {
for (let h = 0; h < size; h++) {
pixels[i * (1 * size) + w + (j * (6 * size * size) + h * (6 * size))] = cl;
}
}
line >>= 1;
}
}
this.rawBound16(x, y, 6 * size, 8 * size, pixels);
}
rawBound16(x, y, width, height, pixels, flush) {
const rgb = [];
pixels.forEach((v) => {
const v2 = ((v & 0xf800) >> 11) | (v & 0x7e0) | ((v & 0x1f) << 11);
rgb.push((v2 & 0xff00) >> 8);
rgb.push(v2 & 0xff);
});
this.setAddrWindow(x, y, x + width - 1, y + height - 1);
if (flush) {
this._writeBuffer(rgb);
this._writeBuffer(); // for flush
}
else {
this.writeData(rgb);
}
}
drawString(x, y, string, color, backgroundColor, size, wrap) {
// bg = bg || color;
size = size || 1;
// wrap = wrap || true;
for (let n = 0; n < string.length; n++) {
const c = string.charAt(n);
if (c === '\n') {
y += size * 8;
x = 0;
}
else if (c === '\r') {
// skip em
}
else {
this.drawChar(x, y, c, color, backgroundColor, size);
x += size * 6;
if (wrap && x > this.width - size * 6) {
y += size * 8;
x = 0;
}
}
}
return [x, y];
}
drawContextBound(context, x0, y0, width, height, x1, y1, gray) {
x0 = x0 || 0;
y0 = y0 || 0;
width = width || context.canvas.clientWidth;
height = height || context.canvas.clientHeight;
x1 = x1 || 0;
y1 = y1 || 0;
gray = gray || false;
this.write(ST7735_COLMOD, [ST7735_18bit]); // 18bit/pixel
const imageData = context.getImageData(x0, y0, width, height).data;
const rgb = [];
for (let n = 0; n < imageData.length; n += 4) {
const r = imageData[n + 0];
const g = imageData[n + 1];
const b = imageData[n + 2];
if (!gray) {
rgb.push(b);
rgb.push(g);
rgb.push(r);
}
else {
const gs = Math.round(0.299 * r + 0.587 * g + 0.114 * b);
rgb.push(gs);
rgb.push(gs);
rgb.push(gs);
}
}
this.write(ST7735_COLMOD, [ST7735_18bit]); // 18bit/pixel
this.setAddrWindow(x1, y1, x1 + width - 1, y1 + height - 1);
this._writeBuffer(rgb);
this._writeBuffer(); // for flush
this.write(ST7735_COLMOD, [ST7735_16bit]); // 16bit/pixel
}
drawContext(context, gray) {
gray = gray || false;
this.drawContextBound(context, 0, 0, this.width, this.height, 0, 0, gray);
}
draw(context, gray) {
this.drawContext(context, gray);
}
rawBound(x, y, width, height, pixels) {
const rgb = [];
pixels.forEach((v) => {
rgb.push(v & 0xff);
rgb.push((v & 0xff00) >> 8);
rgb.push((v & 0xff0000) >> 16);
});
this.write(ST7735_COLMOD, [ST7735_18bit]); // 18bit/pixel
this.setAddrWindow(x, y, x + width - 1, y + height - 1);
this._writeBuffer(rgb);
this._writeBuffer(); // for flush
this.write(ST7735_COLMOD, [ST7735_16bit]); // 16bit/pixel
}
raw(pixels) {
this.rawBound16(0, 0, this.width, this.height, pixels, true);
}
_setPresetColor() {
this.color = {
AliceBlue: 0xf7df,
AntiqueWhite: 0xff5a,
Aqua: 0x07ff,
Aquamarine: 0x7ffa,
Azure: 0xf7ff,
Beige: 0xf7bb,
Bisque: 0xff38,
Black: 0x0000,
BlanchedAlmond: 0xff59,
Blue: 0x001f,
BlueViolet: 0x895c,
Brown: 0xa145,
BurlyWood: 0xddd0,
CadetBlue: 0x5cf4,
Chartreuse: 0x7fe0,
Chocolate: 0xd343,
Coral: 0xfbea,
CornflowerBlue: 0x64bd,
Cornsilk: 0xffdb,
Crimson: 0xd8a7,
Cyan: 0x07ff,
DarkBlue: 0x0011,
DarkCyan: 0x0451,
DarkGoldenRod: 0xbc21,
DarkGray: 0xad55,
DarkGreen: 0x0320,
DarkKhaki: 0xbdad,
DarkMagenta: 0x8811,
DarkOliveGreen: 0x5345,
DarkOrange: 0xfc60,
DarkOrchid: 0x9999,
DarkRed: 0x8800,
DarkSalmon: 0xecaf,
DarkSeaGreen: 0x8df1,
DarkSlateBlue: 0x49f1,
DarkSlateGray: 0x2a69,
DarkTurquoise: 0x067a,
DarkViolet: 0x901a,
DeepPink: 0xf8b2,
DeepSkyBlue: 0x05ff,
DimGray: 0x6b4d,
DodgerBlue: 0x1c9f,
FireBrick: 0xb104,
FloralWhite: 0xffde,
ForestGreen: 0x2444,
Fuchsia: 0xf81f,
Gainsboro: 0xdefb,
GhostWhite: 0xffdf,
Gold: 0xfea0,
GoldenRod: 0xdd24,
Gray: 0x8410,
Green: 0x0400,
GreenYellow: 0xafe5,
HoneyDew: 0xf7fe,
HotPink: 0xfb56,
IndianRed: 0xcaeb,
Indigo: 0x4810,
Ivory: 0xfffe,
Khaki: 0xf731,
Lavender: 0xe73f,
LavenderBlush: 0xff9e,
LawnGreen: 0x7fe0,
LemonChiffon: 0xffd9,
LightBlue: 0xaedc,
LightCoral: 0xf410,
LightCyan: 0xe7ff,
LightGoldenRodYellow: 0xffda,
LightGray: 0xd69a,
LightGreen: 0x9772,
LightPink: 0xfdb8,
LightSalmon: 0xfd0f,
LightSeaGreen: 0x2595,
LightSkyBlue: 0x867f,
LightSlateGray: 0x7453,
LightSteelBlue: 0xb63b,
LightYellow: 0xfffc,
Lime: 0x07e0,
LimeGreen: 0x3666,
Linen: 0xff9c,
Magenta: 0xf81f,
Maroon: 0x8000,
MediumAquaMarine: 0x6675,
MediumBlue: 0x0019,
MediumOrchid: 0xbaba,
MediumPurple: 0x939b,
MediumSeaGreen: 0x3d8e,
MediumSlateBlue: 0x7b5d,
MediumSpringGreen: 0x07d3,
MediumTurquoise: 0x4e99,
MediumVioletRed: 0xc0b0,
MidnightBlue: 0x18ce,
MintCream: 0xf7ff,
MistyRose: 0xff3c,
Moccasin: 0xff36,
NavajoWhite: 0xfef5,
Navy: 0x0010,
OldLace: 0xffbc,
Olive: 0x8400,
OliveDrab: 0x6c64,
Orange: 0xfd20,
OrangeRed: 0xfa20,
Orchid: 0xdb9a,
PaleGoldenRod: 0xef55,
PaleGreen: 0x9fd3,
PaleTurquoise: 0xaf7d,
PaleVioletRed: 0xdb92,
PapayaWhip: 0xff7a,
PeachPuff: 0xfed7,
Peru: 0xcc27,
Pink: 0xfe19,
Plum: 0xdd1b,
PowderBlue: 0xb71c,
Purple: 0x8010,
RebeccaPurple: 0x6193,
Red: 0xf800,
RosyBrown: 0xbc71,
RoyalBlue: 0x435c,
SaddleBrown: 0x8a22,
Salmon: 0xfc0e,
SandyBrown: 0xf52c,
SeaGreen: 0x2c4a,
SeaShell: 0xffbd,
Sienna: 0xa285,
Silver: 0xc618,
SkyBlue: 0x867d,
SlateBlue: 0x6ad9,
SlateGray: 0x7412,
Snow: 0xffdf,
SpringGreen: 0x07ef,
SteelBlue: 0x4416,
Tan: 0xd5b1,
Teal: 0x0410,
Thistle: 0xddfb,
Tomato: 0xfb08,
Turquoise: 0x471a,
Violet: 0xec1d,
Wheat: 0xf6f6,
White: 0xffff,
WhiteSmoke: 0xf7be,
Yellow: 0xffe0,
YellowGreen: 0x9e66,
};
}
_color2pixels(w, h, color) {
return Array.from(new Array(Math.abs(w * h))).map((v, i) => color);
}
_drawCircleHelper(x0, y0, r, cornername, color) {
let f = 1 - r;
let ddF_x = 1;
let ddF_y = -2 * r;
let x = 0;
let y = r;
while (x < y) {
if (f >= 0) {
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
if (cornername & 0x4) {
this.drawPixel(x0 + x, y0 + y, color);
this.drawPixel(x0 + y, y0 + x, color);
}
if (cornername & 0x2) {
this.drawPixel(x0 + x, y0 - y, color);
this.drawPixel(x0 + y, y0 - x, color);
}
if (cornername & 0x8) {
this.drawPixel(x0 - y, y0 + x, color);
this.drawPixel(x0 - x, y0 + y, color);
}
if (cornername & 0x1) {
this.drawPixel(x0 - y, y0 - x, color);
this.drawPixel(x0 - x, y0 - y, color);
}
}
}
}
exports.default = ST7735S;
// ----------------------------------------------------------
const ST7735S_TFTWIDTH = 80;
const ST7735S_TFTHEIGHT = 160;
// const ST7735_NOP = 0x00;
const ST7735_SWRESET = 0x01;
// const ST7735_RDDID = 0x04;
// const ST7735_RDDST = 0x09;
// const ST7735_RDDPM = 0x0a;
// const ST7735_SLPIN = 0x10;
const ST7735_SLPOUT = 0x11;
// const ST7735_PTLON = 0x12;
// const ST7735_NORON = 0x13;
const ST7735_INVOFF = 0x20;
const ST7735_INVON = 0x21;
const ST7735_DISPOFF = 0x28;
const ST7735_DISPON = 0x29;
const ST7735_CASET = 0x2a;
const ST7735_RASET = 0x2b;
const ST7735_RAMWR = 0x2c;
// const ST7735_RAMRD = 0x2e;
const ST7735_MADCTL = 0x36;
// const ST7735_PTLAR = 0x30;
const ST7735_COLMOD = 0x3a;
const ST7735_FRMCTR1 = 0xb1;
const ST7735_FRMCTR2 = 0xb2;
const ST7735_FRMCTR3 = 0xb3;
const ST7735_INVCTR = 0xb4;
// const ST7735_DISSET5 = 0xb6;
const ST7735_PWCTR1 = 0xc0;
const ST7735_PWCTR2 = 0xc1;
const ST7735_PWCTR3 = 0xc2;
const ST7735_PWCTR4 = 0xc3;
const ST7735_PWCTR5 = 0xc4;
const ST7735_VMCTR1 = 0xc5;
// const ST7735_RDID1 = 0xda;
// const ST7735_RDID2 = 0xdb;
// const ST7735_RDID3 = 0xdc;
// const ST7735_RDID4 = 0xdd;
// const ST7735_PWCTR6 = 0xfc;
const ST7735_GMCTRP1 = 0xe0;
const ST7735_GMCTRN1 = 0xe1;
const ST7735_18bit = 0x06; // 18bit/pixel
const ST7735_16bit = 0x05; // 16bit/pixel
// standard ascii 5x7 font
const font = [
0x00,
0x00,
0x00,
0x00,
0x00,
0x3e,
0x5b,
0x4f,
0x5b,
0x3e,
0x3e,
0x6b,
0x4f,
0x6b,
0x3e,
0x1c,
0x3e,
0x7c,
0x3e,
0x1c,
0x18,
0x3c,
0x7e,
0x3c,
0x18,
0x1c,
0x57,
0x7d,
0x57,
0x1c,
0x1c,
0x5e,
0x7f,
0x5e,
0x1c,
0x00,
0x18,
0x3c,
0x18,
0x00,
0xff,
0xe7,
0xc3,
0xe7,
0xff,
0x00,
0x18,
0x24,
0x18,
0x00,
0xff,
0xe7,
0xdb,
0xe7,
0xff,
0x30,
0x48,
0x3a,
0x06,
0x0e,
0x26,
0x29,
0x79,
0x29,
0x26,
0x40,
0x7f,
0x05,
0x05,
0x07,
0x40,
0x7f,
0x05,
0x25,
0x3f,
0x5a,
0x3c,
0xe7,
0x3c,
0x5a,
0x7f,
0x3e,
0x1c,
0x1c,
0x08,
0x08,
0x1c,
0x1c,
0x3e,
0x7f,
0x14,
0x22,
0x7f,
0x22,
0x14,
0x5f,
0x5f,
0x00,
0x5f,
0x5f,
0x06,
0x09,
0x7f,
0x01,
0x7f,
0x00,
0x66,
0x89,
0x95,
0x6a,
0x60,
0x60,
0x60,
0x60,
0x60,
0x94,
0xa2,
0xff,
0xa2,
0x94,
0x08,
0x04,
0x7e,
0x04,
0x08,
0x10,
0x20,
0x7e,
0x20,
0x10,
0x08,
0x08,
0x2a,
0x1c,
0x08,
0x08,
0x1c,
0x2a,
0x08,
0x08,
0x1e,
0x10,
0x10,
0x10,
0x10,
0x0c,
0x1e,
0x0c,
0x1e,
0x0c,
0x30,
0x38,
0x3e,
0x38,
0x30,
0x06,
0x0e,
0x3e,
0x0e,
0x06,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x5f,
0x00,
0x00,
0x00,
0x07,
0x00,
0x07,
0x00,
0x14,
0x7f,
0x14,
0x7f,
0x14,
0x24,
0x2a,
0x7f,
0x2a,
0x12,
0x23,
0x13,
0x08,
0x64,
0x62,
0x36,
0x49,
0x56,
0x20,
0x50,
0x00,
0x08,
0x07,
0x03,
0x00,
0x00,
0x1c,
0x22,
0x41,
0x00,
0x00,
0x41,
0x22,
0x1c,
0x00,
0x2a,
0x1c,
0x7f,
0x1c,
0x2a,
0x08,
0x08,
0x3e,
0x08,
0x08,
0x00,
0x80,
0x70,
0x30,
0x00,
0x08,
0x08,
0x08,
0x08,
0x08,
0x00,
0x00,
0x60,
0x60,
0x00,
0x20,
0x10,
0x08,
0x04,
0x02,
0x3e,
0x51,
0x49,
0x45,
0x3e,
0x00,
0x42,
0x7f,
0x40,
0x00,
0x72,
0x49,
0x49,
0x49,
0x46,
0x21,
0x41,
0x49,
0x4d,
0x33,
0x18,
0x14,
0x12,
0x7f,
0x10,
0x27,
0x45,
0x45,
0x45,
0x39,
0x3c,
0x4a,
0x49,
0x49,
0x31,
0x41,
0x21,
0x11,
0x09,
0x07,
0x36,
0x49,
0x49,
0x49,
0x36,
0x46,
0x49,
0x49,
0x29,
0x1e,
0x00,
0x00,
0x14,
0x00,
0x00,
0x00,
0x40,
0x34,
0x00,
0x00,
0x00,
0x08,
0x14,
0x22,
0x41,
0x14,
0x14,
0x14,
0x14,
0x14,
0x00,
0x41,
0x22,
0x14,
0x08,
0x02,
0x01,
0x59,
0x09,
0x06,
0x3e,
0x41,
0x5d,
0x59,
0x4e,
0x7c,
0x12,
0x11,
0x12,
0x7c,
0x7f,
0x49,
0x49,
0x49,
0x36,
0x3e,
0x41,
0x41,
0x41,
0x22,
0x7f,
0x41,
0x41,
0x41,
0x3e,
0x7f,
0x49,
0x49,
0x49,
0x41,
0x7f,
0x09,
0x09,
0x09,
0x01,
0x3e,
0x41,
0x41,
0x51,
0x73,
0x7f,
0x08,
0x08,
0x08,
0x7f,
0x00,
0x41,
0x7f,
0x41,
0x00,
0x20,
0x40,
0x41,
0x3f,
0x01,
0x7f,
0x08,
0x14,
0x22,
0x41,
0x7f,
0x40,
0x40,
0x40,
0x40,
0x7f,
0x02,
0x1c,
0x02,
0x7f,
0x7f,
0x04,
0x08,
0x10,
0x7f,
0x3e,
0x41,
0x41,
0x41,
0x3e,
0x7f,
0x09,
0x09,
0x09,
0x06,
0x3e,
0x41,
0x51,
0x21,
0x5e,
0x7f,
0x09,
0x19,
0x29,
0x46,
0x26,
0x49,
0x49,
0x49,
0x32,
0x03,
0x01,
0x7f,
0x01,
0x03,
0x3f,
0x40,
0x40,
0x40,
0x3f,
0x1f,
0x20,
0x40,
0x20,
0x1f,
0x3f,
0x40,
0x38,
0x40,
0x3f,
0x63,
0x14,
0x08,
0x14,
0x63,
0x03,
0x04,
0x78,
0x04,
0x03,
0x61,
0x59,
0x49,
0x4d,
0x43,
0x00,
0x7f,
0x41,
0x41,
0x41,
0x02,
0x04,
0x08,
0x10,
0x20,
0x00,
0x41,
0x41,
0x41,
0x7f,
0x04,
0x02,
0x01,
0x02,
0x04,
0x40,
0x40,
0x40,
0x40,
0x40,
0x00,
0x03,
0x07,
0x08,
0x00,
0x20,
0x54,
0x54,
0x78,
0x40,
0x7f,
0x28,
0x44,
0x44,
0x38,
0x38,
0x44,
0x44,
0x44,
0x28,
0x38,
0x44,
0x44,
0x28,
0x7f,
0x38,
0x54,
0x54,
0x54,
0x18,
0x00,
0x08,
0x7e,
0x09,
0x02,
0x18,
0xa4,
0xa4,
0x9c,
0x78,
0x7f,
0x08,
0x04,
0x04,
0x78,
0x00,
0x44,
0x7d,
0x40,
0x00,
0x20,
0x40,
0x40,
0x3d,
0x00,
0x7f,
0x10,
0x28,
0x44,
0x00,
0x00,
0x41,
0x7f,
0x40,
0x00,
0x7c,
0x04,
0x78,
0x04,
0x78,
0x7c,
0x08,
0x04,
0x04,
0x78,
0x38,
0x44,
0x44,
0x44,
0x38,
0xfc,
0x18,
0x24,
0x24,
0x18,
0x18,
0x24,
0x24,
0x18,
0xfc,
0x7c,
0x08,
0x04,
0x04,
0x08,
0x48,
0x54,
0x54,
0x54,
0x24,
0x04,
0x04,
0x3f,
0x44,
0x24,
0x3c,
0x40,
0x40,
0x20,
0x7c,
0x1c,
0x20,
0x40,
0x20,
0x1c,
0x3c,
0x40,
0x30,
0x40,
0x3c,
0x44,
0x28,
0x10,
0x28,
0x44,
0x4c,
0x90,
0x90,
0x90,
0x7c,
0x44,
0x64,
0x54,
0x4c,
0x44,
0x00,
0x08,
0x36,
0x41,
0x00,
0x00,
0x00,
0x77,
0x00,
0x00,
0x00,
0x41,
0x36,
0x08,
0x00,
0x02,
0x01,
0x02,
0x04,
0x02,
0x3c,
0x26,
0x23,
0x26,
0x3c,
0x1e,
0xa1,
0xa1,
0x61,
0x12,
0x3a,
0x40,
0x40,
0x20,
0x7a,
0x38,
0x54,
0x54,
0x55,
0x59,
0x21,
0x55,
0x55,
0x79,
0x41,
0x21,
0x54,
0x54,
0x78,
0x41,
0x21,
0x55,
0x54,
0x78,
0x40,
0x20,
0x54,
0x55,
0x79,
0x40,
0x0c,
0x1e,
0x52,
0x72,
0x12,
0x39,
0x55,
0x55,
0x55,
0x59,
0x39,
0x54,
0x54,
0x54,
0x59,
0x39,
0x55,
0x54,
0x54,
0x58,
0x00,
0x00,
0x45,
0x7c,
0x41,
0x00,
0x02,
0x45,
0x7d,
0x42,
0x00,
0x01,
0x45,
0x7c,
0x40,
0xf0,
0x29,
0x24,
0x29,
0xf0,
0xf0,
0x28,
0x25,
0x28,
0xf0,
0x7c,
0x54,
0x55,
0x45,
0x00,
0x20,
0x54,
0x54,
0x7c,
0x54,
0x7c,
0x0a,
0x09,
0x7f,
0x49,
0x32,
0x49,
0x49,
0x49,
0x32,
0x32,
0x48,
0x48,
0x48,
0x32,
0x32,
0x4a,
0x48,
0x48,
0x30,
0x3a,
0x41,
0x41,
0x21,
0x7a,
0x3a,
0x42,
0x40,
0x20,
0x78,
0x00,
0x9d,
0xa0,
0xa0,
0x7d,
0x39,
0x44,
0x44,
0x44,
0x39,
0x3d,
0x40,
0x40,
0x40,
0x3d,
0x3c,
0x24,
0xff,
0x24,
0x24,
0x48,
0x7e,
0x49,
0x43,
0x66,
0x2b,
0x2f,
0xfc,
0x2f,
0x2b,
0xff,
0x09,
0x29,
0xf6,
0x20,
0xc0,
0x88,
0x7e,
0x09,
0x03,
0x20,
0x54,
0x54,
0x79,
0x41,
0x00,
0x00,
0x44,
0x7d,
0x41,
0x30,
0x48,
0x48,
0x4a,
0x32,
0x38,
0x40,
0x40,
0x22,
0x7a,
0x00,
0x7a,
0x0a,
0x0a,
0x72,
0x7d,
0x0d,
0x19,
0x31,
0x7d,
0x26,
0x29,
0x29,
0x2f,
0x28,
0x26,
0x29,
0x29,
0x29,
0x26,
0x30,
0x48,
0x4d,
0x40,
0x20,
0x38,
0x08,
0x08,
0x08,
0x08,
0x08,
0x08,
0x08,
0x08,
0x38,
0x2f,
0x10,
0xc8,
0xac,
0xba,
0x2f,
0x10,
0x28,
0x34,
0xfa,
0x00,
0x00,
0x7b,
0x00,
0x00,
0x08,
0x14,
0x2a,
0x14,
0x22,
0x22,
0x14,
0x2a,
0x14,
0x08,
0xaa,
0x00,
0x55,
0x00,
0xaa,
0xaa,
0x55,
0xaa,
0x55,
0xaa,
0x00,
0x00,
0x00,
0xff,
0x00,
0x10,
0x10,
0x10,
0xff,
0x00,
0x14,
0x14,
0x14,
0xff,
0x00,
0x10,
0x10,
0xff,
0x00,
0xff,
0x10,
0x10,
0xf0,
0x10,
0xf0,
0x14,
0x14,
0x14,
0xfc,
0x00,
0x14,
0x14,
0xf7,
0x00,
0xff,
0x00,
0x00,
0xff,
0x00,
0xff,
0x14,
0x14,
0xf4,
0x04,
0xfc,
0x14,
0x14,
0x17,
0x10,
0x1f,
0x10,
0x10,
0x1f,
0x10,
0x1f,
0x14,
0x14,
0x14,
0x1f,
0x00,
0x10,
0x10,
0x10,
0xf0,
0x00,
0x00,
0x00,
0x00,
0x1f,
0x10,
0x10,
0x10,
0x10,
0x1f,
0x10,
0x10,
0x10,
0x10,
0xf0,
0x10,
0x00,
0x00,
0x00,
0xff,
0x10,
0x10,
0x10,
0x10,
0x10,
0x10,
0x10,
0x10,
0x10,
0xff,
0x10,
0x00,
0x00,
0x00,
0xff,
0x14,
0x00,
0x00,
0xff,
0x00,
0xff,
0x00,
0x00,
0x1f,
0x10,
0x17,
0x00,
0x00,
0xfc,
0x04,
0xf4,
0x14,
0x14,
0x17,
0x10,
0x17,
0x14,
0x14,
0xf4,
0x04,
0xf4,
0x00,
0x00,
0xff,
0x00,
0xf7,
0x14,
0x14,
0x14,
0x14,
0x14,
0x14,
0x14,
0xf7,
0x00,
0xf7,
0x14,
0x14,
0x14,
0x17,
0x14,
0x10,
0x10,
0x1f,
0x10,
0x1f,
0x14,
0x14,
0x14,
0xf4,
0x14,
0x10,
0x10,
0xf0,
0x10,
0xf0,
0x00,
0x00,
0x1f,
0x10,
0x1f,
0x00,
0x00,
0x00,
0x1f,
0x14,
0x00,
0x00,
0x00,
0xfc,
0x14,
0x00,
0x00,
0xf0,
0x10,
0xf0,
0x10,
0x10,
0xff,
0x10,
0xff,
0x14,
0x14,
0x14,
0xff,
0x14,
0x10,
0x10,
0x10,
0x1f,
0x00,
0x00,
0x00,
0x00,
0xf0,
0x10,
0xff,
0xff,
0xff,
0xff,
0xff,
0xf0,
0xf0,
0xf0,
0xf0,
0xf0,
0xff,
0xff,
0xff,
0x00,
0x00,
0x00,
0x00,
0x00,
0xff,
0xff,
0x0f,
0x0f,
0x0f,
0x0f,
0x0f,
0x38,
0x44,
0x44,
0x38,
0x44,
0x7c,
0x2a,
0x2a,
0x3e,
0x14,
0x7e,
0x02,
0x02,
0x06,
0x06,
0x02,
0x7e,
0x02,
0x7e,
0x02,
0x63,
0x55,
0x49,
0x41,
0x63,
0x38,
0x44,
0x44,
0x3c,
0x04,
0x40,
0x7e,
0x20,
0x1e,
0x20,
0x06,
0x02,
0x7e,
0x02,
0x02,
0x99,
0xa5,
0xe7,
0xa5,
0x99,
0x1c,
0x2a,
0x49,
0x2a,
0x1c,
0x4c,
0x72,
0x01,
0x72,
0x4c,
0x30,
0x4a,
0x4d,
0x4d,
0x30,
0x30,
0x48,
0x78,
0x48,
0x30,
0xbc,
0x62,
0x5a,
0x46,
0x3d,
0x3e,
0x49,
0x49,
0x49,
0x00,
0x7e,
0x01,
0x01,
0x01,
0x7e,
0x2a,
0x2a,
0x2a,
0x2a,
0x2a,
0x44,
0x44,
0x5f,
0x44,
0x44,
0x40,
0x51,
0x4a,
0x44,
0x40,
0x40,
0x44,
0x4a,
0x51,
0x40,
0x00,
0x00,
0xff,
0x01,
0x03,
0xe0,
0x80,
0xff,
0x00,
0x00,
0x08,
0x08,
0x6b,
0x6b,
0x08,
0x36,
0x12,
0x36,
0x24,
0x36,
0x06,
0x0f,
0x09,
0x0f,
0x06,
0x00,
0x00,
0x18,
0x18,
0x00,
0x00,
0x00,
0x10,
0x10,
0x00,
0x30,
0x40,
0xff,
0x01,
0x01,
0x00,
0x1f,
0x01,
0x01,
0x1e,
0x00,
0x19,
0x1d,
0x17,
0x12,
0x00,
0x3c,
0x3c,
0x3c,
0x3c,
0x00,
0x00,
0x00,
0x00,
0x00,
];