/*! * @file Adafruit_NeoMatrix.cpp * * @mainpage GFX-compatible layer for NeoPixel matrices. * * @section intro_sec Introduction * * Arduino library to control single and tiled matrices of WS2811- and * WS2812-based RGB LED devices such as the Adafruit NeoPixel Shield or * displays assembled from NeoPixel strips, making them compatible with * the Adafruit_GFX graphics library. * * Adafruit invests time and resources providing this open source code, * please support Adafruit and open-source hardware by purchasing * products from Adafruit! * * @section dependencies Dependencies * * This library depends on Adafruit_NeoPixel * and Adafruit_GFX * being present on your system. Please make sure you have installed the * latest versions before using this library. * * @section author Author * * Written by Phil Burgess / Paint Your Dragon for Adafruit Industries. * * @section license License * * This file is part of the Adafruit NeoMatrix library. * * NeoMatrix is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * NeoMatrix is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with NeoMatrix. If not, see * . * */ #include "gamma.h" #include "Adafruit_NeoMatrix.h" #ifdef __AVR__ #include #elif defined(ESP8266) #include #else #ifndef pgm_read_byte #define pgm_read_byte(addr) \ (*(const unsigned char *)(addr)) ///< PROGMEM concept doesn't apply on ESP8266 #endif #endif #ifndef _swap_uint16_t #define _swap_uint16_t(a, b) \ { \ uint16_t t = a; \ a = b; \ b = t; \ } ///< Swap contents of two uint16_t variables #endif // Constructor for single matrix: Adafruit_NeoMatrix::Adafruit_NeoMatrix(int w, int h, uint8_t pin, uint8_t matrixType, neoPixelType ledType) : Adafruit_GFX(w, h), NeoPixelBus_wrapper(w * h, pin, ledType), type(matrixType), matrixWidth(w), matrixHeight(h), tilesX(0), tilesY(0), remapFn(NULL) {} // Constructor for tiled matrices: Adafruit_NeoMatrix::Adafruit_NeoMatrix(uint8_t mW, uint8_t mH, uint8_t tX, uint8_t tY, uint8_t pin, uint8_t matrixType, neoPixelType ledType) : Adafruit_GFX(mW * tX, mH * tY), NeoPixelBus_wrapper(mW * mH * tX * tY, pin, ledType), type(matrixType), matrixWidth(mW), matrixHeight(mH), tilesX(tX), tilesY(tY), remapFn(NULL) { } // Expand 16-bit input color (Adafruit_GFX colorspace) to 24-bit (NeoPixel) // (w/gamma adjustment) static uint32_t expandColor(uint16_t color) { return ((uint32_t)pgm_read_byte(&gamma5[color >> 11]) << 16) | ((uint32_t)pgm_read_byte(&gamma6[(color >> 5) & 0x3F]) << 8) | pgm_read_byte(&gamma5[color & 0x1F]); } uint16_t Adafruit_NeoMatrix::Color(uint8_t r, uint8_t g, uint8_t b) { return ((uint16_t)(r & 0xF8) << 8) | ((uint16_t)(g & 0xFC) << 3) | (b >> 3); } // Pass raw color value to set/enable passthrough void Adafruit_NeoMatrix::setPassThruColor(uint32_t c) { passThruColor = c; passThruFlag = true; } // Call without a value to reset (disable passthrough) void Adafruit_NeoMatrix::setPassThruColor(void) { passThruFlag = false; } void Adafruit_NeoMatrix::drawPixel(int16_t x, int16_t y, uint16_t color) { if ((x < 0) || (y < 0) || (x >= _width) || (y >= _height)) return; int16_t t; switch (rotation) { case 1: t = x; x = WIDTH - 1 - y; y = t; break; case 2: x = WIDTH - 1 - x; y = HEIGHT - 1 - y; break; case 3: t = x; x = y; y = HEIGHT - 1 - t; break; } int tileOffset = 0, pixelOffset; if (remapFn) { // Custom X/Y remapping function pixelOffset = (*remapFn)(x, y); } else { // Standard single matrix or tiled matrices uint8_t corner = type & NEO_MATRIX_CORNER; uint16_t minor, major, majorScale; if (tilesX) { // Tiled display, multiple matrices uint16_t tile; minor = x / matrixWidth; // Tile # X/Y; presume row major to major = y / matrixHeight, // start (will swap later if needed) x = x - (minor * matrixWidth); // Pixel X/Y within tile y = y - (major * matrixHeight); // (-* is less math than modulo) // Determine corner of entry, flip axes if needed if (type & NEO_TILE_RIGHT) minor = tilesX - 1 - minor; if (type & NEO_TILE_BOTTOM) major = tilesY - 1 - major; // Determine actual major axis of tiling if ((type & NEO_TILE_AXIS) == NEO_TILE_ROWS) { majorScale = tilesX; } else { _swap_uint16_t(major, minor); majorScale = tilesY; } // Determine tile number if ((type & NEO_TILE_SEQUENCE) == NEO_TILE_PROGRESSIVE) { // All tiles in same order tile = major * majorScale + minor; } else { // Zigzag; alternate rows change direction. On these rows, // this also flips the starting corner of the matrix for the // pixel math later. if (major & 1) { corner ^= NEO_MATRIX_CORNER; tile = (major + 1) * majorScale - 1 - minor; } else { tile = major * majorScale + minor; } } // Index of first pixel in tile tileOffset = tile * matrixWidth * matrixHeight; } // else no tiling (handle as single tile) // Find pixel number within tile minor = x; // Presume row major to start (will swap later if needed) major = y; // Determine corner of entry, flip axes if needed if (corner & NEO_MATRIX_RIGHT) minor = matrixWidth - 1 - minor; if (corner & NEO_MATRIX_BOTTOM) major = matrixHeight - 1 - major; // Determine actual major axis of matrix if ((type & NEO_MATRIX_AXIS) == NEO_MATRIX_ROWS) { majorScale = matrixWidth; } else { _swap_uint16_t(major, minor); majorScale = matrixHeight; } // Determine pixel number within tile/matrix if ((type & NEO_MATRIX_SEQUENCE) == NEO_MATRIX_PROGRESSIVE) { // All lines in same order pixelOffset = major * majorScale + minor; } else { // Zigzag; alternate rows change direction. if (major & 1) pixelOffset = (major + 1) * majorScale - 1 - minor; else pixelOffset = major * majorScale + minor; } } setPixelColor(tileOffset + pixelOffset, passThruFlag ? passThruColor : expandColor(color)); } void Adafruit_NeoMatrix::fillScreen(uint16_t color) { uint16_t i, n; uint32_t c; c = passThruFlag ? passThruColor : expandColor(color); n = numPixels(); for (i = 0; i < n; i++) setPixelColor(i, c); } void Adafruit_NeoMatrix::setRemapFunction(uint16_t (*fn)(uint16_t, uint16_t)) { remapFn = fn; }