UNPKG

@lynniemagoo/adafruit-st7735-library

Version:

NodeJS Promise-based port of C/C++ Adafruit-ST7735-Library from Github - Library for Family of ST77XX TFT displays including ST7735, ST7789.

508 lines (404 loc) 15.1 kB
/*************************************************** This set of common test scripts can be used for RGB565 TFT displays. These displays use SPI to communicate, 4 or 5 pins are required to interface Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! Written by Limor Fried/Ladyada for Adafruit Industries. BSD license, all text above must be included in any redistribution Code ported to NodeJS by Lyndel R. McGee Original source of this code was: https://github.com/adafruit/Adafruit-SSD1351-library The Adafruit GFX Graphics core library is also required https://github.com/adafruit/Adafruit-GFX-Library Be sure to install it! ****************************************************/ 'use strict'; const Adafruit_GFX_Library = require("@lynniemagoo/adafruit-gfx-library"); const delay = Adafruit_GFX_Library.Utils.sleepMs; const os = require("os"); const toInt = Math.trunc, fMax = Math.max, fMin = Math.min, fFloor = Math.floor, fRandom = Math.random; // Random Number Helper method // See https://stackoverflow.com/questions/4959975/generate-random-number-between-two-numbers-in-javascript function randomInteger(min, max) { return fFloor(fRandom() * (max - min + 1)) + min; } // Color definitions const BLACK = 0x0000; const BLUE = 0x001F; const RED = 0xF800; const GREEN = 0x07E0; const CYAN = 0x07FF; const MAGENTA = 0xF81F; const YELLOW = 0xFFE0; const WHITE = 0xFFFF; /**************************************************************************/ /*! @brief Renders a simple test pattern on the screen */ /**************************************************************************/ async function lcdTestPattern(canvas, display) { const w = canvas.width(), h = canvas.height(), localColors = [RED, YELLOW, GREEN, CYAN, BLUE, MAGENTA, BLACK, WHITE]; for(let c=0; c<8; c++) { await canvas.fillRect(0, h * c / 8, w, h / 8, localColors[c]); } await display.fastRenderGFXcanvas16(canvas); await delay(500); } async function testLines(canvas, display, color) { const w = canvas.width(), h = canvas.height(); let x, y; await canvas.fillScreen(BLACK); for(x=0; x < w-1; x+=6) { // the JS version of this canvas is chainable so we can chain methods // that modify the buffer or canvas. await canvas.drawLine(0, 0, x, h-1, color); } for (y=0; y < h-1; y+=6) { // the JS version of this canvas is chainable so we can chain methods // that modify the buffer or canvas. await canvas.drawLine(0, 0, w-1, y, color); } await display.fastRenderGFXcanvas16(canvas); await delay(500); await canvas.fillScreen(BLACK); for (x=0; x < w-1; x+=6) { await canvas.drawLine(w-1, 0, x, h-1, color); } for (y=0; y < h-1; y+=6) { await canvas.drawLine(w-1, 0, 0, y, color); } await display.fastRenderGFXcanvas16(canvas); await delay(500); await canvas.fillScreen(BLACK); for (x=0; x < w-1; x+=6) { await canvas.drawLine(0, h-1, x, 0, color); } for (y=0; y < h-1; y+=6) { await canvas.drawLine(0, h-1, w-1, y, color); } await display.fastRenderGFXcanvas16(canvas); await delay(500); await canvas.fillScreen(BLACK); for (x=0; x < w-1; x+=6) { await canvas.drawLine(w-1, h-1, x, 0, color); } for (y=0; y < h-1; y+=6) { await canvas.drawLine(w-1, h-1, 0, y, color); } await display.fastRenderGFXcanvas16(canvas); await delay(500); } async function testDrawText(canvas, display, text, color) { const previousWrap = canvas.getTextWrap(); await canvas.setCursor(0,0) .setTextWrap(true) .setTextColor(color) .print(text) .setTextWrap(previousWrap); await display.fastRenderGFXcanvas16(canvas); await delay(500); } async function testFastLines(canvas, display, color1, color2) { const w = canvas.width(), h = canvas.height(); await canvas.fillScreen(BLACK); for (let y=0; y < h-1; y+=5) { await canvas.drawFastHLine(0, y, w-1, color1); } for (let x=0; x < w-1; x+=5) { await canvas.drawFastVLine(x, 0, h-1, color2); } await display.fastRenderGFXcanvas16(canvas); await delay(500); } async function tftPrintTest(canvas, display, colors = [WHITE], loop_delay = 1) { await canvas.fillScreen(BLACK); await canvas.setCursor(0, 5) .setTextColor(RED) .setTextSize(1) .println("Hello World!"); await delay(1500); await canvas.setTextColor(YELLOW) .setTextSize(2) .println("Hello World!"); await delay(1500); await canvas.setTextColor(BLUE) .setTextSize(3) .print(1234.567); await display.fastRenderGFXcanvas16(canvas); await delay(1500); await canvas.fillScreen(BLACK); await canvas.setCursor(0, 5) .setTextColor(WHITE) .setTextSize(0) .println("Hello World!"); await canvas.setTextSize(1) .setTextColor(GREEN) .print(Math.PI.toFixed(6)) .println(" Want pi?") .println(" "); //await canvas.print(8675309, HEX); // print 8,675,309 out in HEX! const value = 8675309; await canvas.print("0x" + value.toString(16).toUpperCase().padStart(8, "0")) // print 8,675,309 out in HEX! .println(" Print HEX!") .println(" ") .setTextColor(WHITE) .println("System has been") .println("running for: ") .setTextColor(MAGENTA) .print(os.uptime()) .setTextColor(WHITE) .print(" seconds."); await display.fastRenderGFXcanvas16(canvas); await delay(1500); } async function testDrawRects(canvas, display, color) { const w = canvas.width(), h = canvas.height(); await canvas.fillScreen(BLACK); for(let x=0; x < h -1; x+=6) { await canvas.drawRect((w-1)/2 - x/2, (h-1)/2 - x/2, x, x, color); await display.fastRenderGFXcanvas16(canvas); await delay(10); } await delay(1500); } async function testFillRects(canvas, display, color1, color2) { const w = canvas.width(), h = canvas.height(); await canvas.fillScreen(BLACK); for(let x=h-1; x>6; x-=6) { await canvas.fillRect(toInt((w-1)/2 - x/2), toInt((h-1)/2 - x/2), x, x, color1) .drawRect(toInt((w-1)/2 - x/2), toInt((h-1)/2 - x/2), x, x, color2); await display.fastRenderGFXcanvas16(canvas); await delay(10); } await delay(1500); } async function testFillCircles(canvas, display, radius, color) { const w = canvas.width(), h = canvas.height(); for(let x=radius; x<w-1; x+=radius*2) { for(let y=radius; y < h-1; y+=radius*2) { await canvas.fillCircle(x, y, radius, color) } } await display.fastRenderGFXcanvas16(canvas); await delay(1500); } async function testDrawCircles(canvas, display, radius, color) { const w = canvas.width(), h = canvas.height(); for(let x=0; x<w-1+radius; x+=radius*2) { for(let y=0; y<h-1+radius; y+=radius*2) { await canvas.drawCircle(x, y, radius, color) } } await display.fastRenderGFXcanvas16(canvas); await delay(1500); } async function testRoundRects(canvas, display) { let w = canvas.width(), h = canvas.height(); let x=0, y=0, color = 100; await canvas.fillScreen(BLACK); for(let i = 0 ; i <= 24; i++) { await canvas.drawRoundRect(x, y, w, h, 5, color); x+=2; y+=3; w-=4; h-=6; color+=1100; //console.log(i); } await display.fastRenderGFXcanvas16(canvas); await delay(1500); } async function testTriangles(canvas, display) { const ow = canvas.width(), oh = canvas.height(); let color = RED, w = ow/2, x = oh, y = 0, z = ow; await canvas.fillScreen(BLACK); for(let t = 0 ; t <= 15; t+=1) { await canvas.drawTriangle(w, y, y, x, z, x, color); x-=4; y+=4; z-=4; color+=100; } await display.fastRenderGFXcanvas16(canvas); await delay(1500); } async function testMediaButtons(canvas, display) { await canvas.fillScreen(BLACK); // play await canvas.fillRoundRect(25, 10, 78, 60, 8, WHITE); await canvas.fillTriangle(42, 20, 42, 60, 90, 40, RED); await display.fastRenderGFXcanvas16(canvas); await delay(500); // pause await canvas.fillRoundRect(25, 90, 78, 60, 8, WHITE); await canvas.fillRoundRect(39, 98, 20, 45, 5, GREEN); await canvas.fillRoundRect(69, 98, 20, 45, 5, GREEN); await display.fastRenderGFXcanvas16(canvas); await delay(500); // play color await canvas.fillTriangle(42, 20, 42, 60, 90, 40, BLUE); await display.fastRenderGFXcanvas16(canvas); await delay(50); // pause color await canvas.fillRoundRect(39, 98, 20, 45, 5, RED); await canvas.fillRoundRect(69, 98, 20, 45, 5, RED); // play color await canvas.fillTriangle(42, 20, 42, 60, 90, 40, GREEN); await display.fastRenderGFXcanvas16(canvas); await delay(1500); } async function testCP437CharacterSet(canvas, display, color) { const previousWrap = canvas.getTextWrap(); const previousCP437 = canvas.getCP437(); await canvas.fillScreen(BLACK); await canvas.setTextSize(1) // Normal 1:1 pixel scale .setTextWrap(false) .setTextColor(color) // Draw colored text .setCursor(0, 0) // Start at top-left corner .setCP437(true); // Use full 256 char 'Code Page 437' font // Not all the characters will fit on the canvas. This is normal. // Library will draw what it can and the rest will be clipped. for(let i=0; i<256; i++) { // canvas.write will simply chain work onto the queue if needed. // Don't have to await each step as this is done below with final // canvas.wait. if (i === 0x0A) continue; canvas.write(i); if ((i > 0) && (i % 21 == 0)) canvas.println(); } // await require here to ensure that all write operations in loop have finished // as we did not await within the loop. await canvas.setCP437(previousCP437) .setTextWrap(previousWrap); await display.fastRenderGFXcanvas16(canvas); await delay(500); } async function testTextStyles(canvas, display, color1, color2) { // Canvas supports chaining and operations are added to a queue. // Therefore, one can do multiple operations as needed using 'dot' chaining. // At the end of one's work, one can simply await the canvas to complete all operations. canvas.setTextSize(1) // Normal 1:1 pixel scale .setTextColor(color1) // Draw colored text .setCursor(0,0) // Start at top-left corner .println("Hello, world!"); canvas.setTextColor(color1, color2) // Draw with background. .println(3.141592); canvas.setTextSize(2) // Draw 2X-scale text .setTextColor(color1) .println("0x%s", 0xDEADBEEF.toString(16).padStart(8,"0").toUpperCase()); // Wait for canvas to complete all work. await canvas; await display.fastRenderGFXcanvas16(canvas); await delay(500); }; async function testAnimate(canvas, display, bitmap, bitmapWidth, bitmapHeight, animateTimeMs = 30000) { const NUMFLAKES=10, // Indexes into the 'icons' array XPOS = 0, YPOS = 1, DELTAY = 2; const w = canvas.width(), h = canvas.height(); let f, icons = [], color = 100; // Initialize 'snowflake' positions for(f=0; f< NUMFLAKES; f++) { const icon = []; // Create a random integer between 1 - LOGO_WIDTH and w. icon[XPOS] = randomInteger(1 - LOGO_WIDTH, w); icon[YPOS] = -LOGO_HEIGHT; // Create a random between 1 and 6. icon[DELTAY] = randomInteger(1, 6); //console.log(" x:%o", icon[XPOS]); //console.log(" y:%o", icon[YPOS]); //console.log("dy:%o", icon[DELTAY]); icons.push(icon); } const startTimeMs = new Date().valueOf(); while ((new Date().valueOf() - startTimeMs) <= animateTimeMs) { canvas.fillScreen(BLACK); // Draw each snowflake: for(f=0; f< NUMFLAKES; f++) { //canvas.drawBitmap( await canvas.draw1BitBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, bitmapWidth, bitmapHeight, color); color += 1100; } await display.fastRenderGFXcanvas16(canvas); await delay(5); // Pause for 5ms // Then update coordinates of each flake... for(f=0; f< NUMFLAKES; f++) { icons[f][YPOS] += icons[f][DELTAY]; // If snowflake is off the bottom of the screen... if (icons[f][YPOS] >= h) { // Reinitialize to a random position, just off the top icons[f][XPOS] = randomInteger(1 - LOGO_WIDTH, w); icons[f][YPOS] = 0; icons[f][DELTAY] = randomInteger(1, 6); } } } await delay(500); } async function testDrawBitmap(canvas, display, color) { const w = canvas.width(), h = canvas.height(); //canvas.drawBitmap( await canvas.draw1BitBitmap((w - LOGO_WIDTH ) / 2, (h - LOGO_HEIGHT) / 2, LOGO_BMP, LOGO_WIDTH, LOGO_HEIGHT, color); await display.fastRenderGFXcanvas16(canvas); await delay(1500); }; const LOGO_HEIGHT = 16; const LOGO_WIDTH = 16; const LOGO_BMP = [ 0b00000000, 0b11000000, 0b00000001, 0b11000000, 0b00000001, 0b11000000, 0b00000011, 0b11100000, 0b11110011, 0b11100000, 0b11111110, 0b11111000, 0b01111110, 0b11111111, 0b00110011, 0b10011111, 0b00011111, 0b11111100, 0b00001101, 0b01110000, 0b00011011, 0b10100000, 0b00111111, 0b11100000, 0b00111111, 0b11110000, 0b01111100, 0b11110000, 0b01110000, 0b01110000, 0b00000000, 0b00110000 ]; module.exports = { lcdTestPattern, testDrawText, tftPrintTest, testLines, testFastLines, testDrawRects, testFillRects, testFillCircles, testDrawCircles, testRoundRects, testTriangles, testMediaButtons, testCP437CharacterSet, testTextStyles, testDrawBitmap, /* exported for use with testAnimate */ LOGO_BMP, LOGO_HEIGHT, LOGO_WIDTH, testAnimate // suggest only run if using a buffer-backed display/canvas such as SSD1327 or SSD1306. };