From 3e59aff96731ebf32c19b7b2372407a28bd29fb6 Mon Sep 17 00:00:00 2001 From: Phillip Burgess Date: Fri, 30 Jun 2017 12:50:22 -0700 Subject: [PATCH] Handle GFX rotation correctly, plus some AVR optimizations & cleanup --- Adafruit_HT1632.cpp | 284 +++++++++++++------------ Adafruit_HT1632.h | 110 +++++----- examples/basicdemo/basicdemo.ino | 12 +- examples/matrixdemo/matrixdemo.ino | 64 +++--- examples/matrixshapes/matrixshapes.ino | 25 ++- library.properties | 2 +- 6 files changed, 254 insertions(+), 243 deletions(-) diff --git a/Adafruit_HT1632.cpp b/Adafruit_HT1632.cpp index 7ef8eb6..ebf173e 100644 --- a/Adafruit_HT1632.cpp +++ b/Adafruit_HT1632.cpp @@ -1,59 +1,58 @@ #include "Adafruit_HT1632.h" -#include "glcdfont.c" +#ifndef _swap_int16_t +#define _swap_int16_t(a, b) { int16_t t = a; a = b; b = t; } +#endif -#define ht1632swap(a, b) { uint16_t t = a; a = b; b = t; } - -Adafruit_HT1632LEDMatrix::Adafruit_HT1632LEDMatrix(uint8_t data, uint8_t wr, uint8_t cs1) : Adafruit_GFX(24, 16) { - matrices = (Adafruit_HT1632 *)malloc(sizeof(Adafruit_HT1632)); - - matrices[0] = Adafruit_HT1632(data, wr, cs1); - matrixNum = 1; - _width = 24 * matrixNum; - _height = 16; +// Constructor for single GFX matrix +Adafruit_HT1632LEDMatrix::Adafruit_HT1632LEDMatrix(uint8_t data, uint8_t wr, + uint8_t cs1) : Adafruit_GFX(24, 16), matrices(NULL), matrixNum(0) { + if((matrices = (Adafruit_HT1632 *)malloc(sizeof(Adafruit_HT1632)))) { + matrices[0] = Adafruit_HT1632(data, wr, cs1); + matrixNum = 1; + } } -Adafruit_HT1632LEDMatrix::Adafruit_HT1632LEDMatrix(uint8_t data, uint8_t wr, - uint8_t cs1, uint8_t cs2) : Adafruit_GFX(24, 32) { - matrices = (Adafruit_HT1632 *)malloc(2 * sizeof(Adafruit_HT1632)); - - matrices[0] = Adafruit_HT1632(data, wr, cs1); - matrices[1] = Adafruit_HT1632(data, wr, cs2); - matrixNum = 2; - _width = 24 * matrixNum; - _height = 16; +// Constructor for two matrices, tiled side-by-side for GFX +Adafruit_HT1632LEDMatrix::Adafruit_HT1632LEDMatrix(uint8_t data, uint8_t wr, + uint8_t cs1, uint8_t cs2) : Adafruit_GFX(48, 16), matrices(NULL), + matrixNum(0) { + if((matrices = (Adafruit_HT1632 *)malloc(2 * sizeof(Adafruit_HT1632)))) { + matrices[0] = Adafruit_HT1632(data, wr, cs1); + matrices[1] = Adafruit_HT1632(data, wr, cs2); + matrixNum = 2; + } } -Adafruit_HT1632LEDMatrix::Adafruit_HT1632LEDMatrix(uint8_t data, uint8_t wr, - uint8_t cs1, uint8_t cs2, uint8_t cs3) : Adafruit_GFX(24, 48) { - matrices = (Adafruit_HT1632 *)malloc(3 * sizeof(Adafruit_HT1632)); - - matrices[0] = Adafruit_HT1632(data, wr, cs1); - matrices[1] = Adafruit_HT1632(data, wr, cs2); - matrices[2] = Adafruit_HT1632(data, wr, cs3); - matrixNum = 3; - _width = 24 * matrixNum; - _height = 16; +// Constructor for three matrices, tiled side-by-side for GFX +Adafruit_HT1632LEDMatrix::Adafruit_HT1632LEDMatrix(uint8_t data, uint8_t wr, + uint8_t cs1, uint8_t cs2, uint8_t cs3) : Adafruit_GFX(72, 16), + matrices(NULL), matrixNum(0) { + if((matrices = (Adafruit_HT1632 *)malloc(3 * sizeof(Adafruit_HT1632)))) { + matrices[0] = Adafruit_HT1632(data, wr, cs1); + matrices[1] = Adafruit_HT1632(data, wr, cs2); + matrices[2] = Adafruit_HT1632(data, wr, cs3); + matrixNum = 3; + } } -Adafruit_HT1632LEDMatrix::Adafruit_HT1632LEDMatrix(uint8_t data, uint8_t wr, - uint8_t cs1, uint8_t cs2, - uint8_t cs3, uint8_t cs4) : Adafruit_GFX(24, 64) { - matrices = (Adafruit_HT1632 *)malloc(4 * sizeof(Adafruit_HT1632)); - - matrices[0] = Adafruit_HT1632(data, wr, cs1); - matrices[1] = Adafruit_HT1632(data, wr, cs2); - matrices[2] = Adafruit_HT1632(data, wr, cs3); - matrices[3] = Adafruit_HT1632(data, wr, cs4); - matrixNum = 4; - _width = 24 * matrixNum; - _height = 16; +// Constructor for four matrices, tiled side-by-side for GFX +Adafruit_HT1632LEDMatrix::Adafruit_HT1632LEDMatrix(uint8_t data, uint8_t wr, + uint8_t cs1, uint8_t cs2, uint8_t cs3, uint8_t cs4) : Adafruit_GFX(96, 16), + matrices(NULL), matrixNum(0) { + if((matrices = (Adafruit_HT1632 *)malloc(4 * sizeof(Adafruit_HT1632)))) { + matrices[0] = Adafruit_HT1632(data, wr, cs1); + matrices[1] = Adafruit_HT1632(data, wr, cs2); + matrices[2] = Adafruit_HT1632(data, wr, cs3); + matrices[3] = Adafruit_HT1632(data, wr, cs4); + matrixNum = 4; + } } - void Adafruit_HT1632LEDMatrix::setPixel(uint8_t x, uint8_t y) { drawPixel(x, y, 1); } + void Adafruit_HT1632LEDMatrix::clrPixel(uint8_t x, uint8_t y) { drawPixel(x, y, 0); } @@ -61,85 +60,75 @@ void Adafruit_HT1632LEDMatrix::clrPixel(uint8_t x, uint8_t y) { void Adafruit_HT1632LEDMatrix::drawPixel(int16_t x, int16_t y, uint16_t color) { if((x < 0) || (x >= _width) || (y < 0) || (y >= _height)) return; - uint8_t m; - // figure out which matrix controller it is - m = x / 24; - x %= 24; + switch(rotation) { // Rotate pixel into device-specific coordinates + case 1: + _swap_int16_t(x, y); + x = WIDTH - 1 - x; + break; + case 2: + x = WIDTH - 1 - x; + y = HEIGHT - 1 - y; + break; + case 3: + _swap_int16_t(x, y); + y = HEIGHT - 1 - y; + break; + } - uint16_t i; + uint8_t m = x / 24; // Which matrix controller is pixel on? + x %= 24; // Which column in matrix? - if (x < 8) { - i = 7; - } else if (x < 16) { - i = 128 + 7; - } else { - i = 256 + 7; - } - i -= (x % 8); + uint16_t i; - if (y < 8) { - y *= 2; - } else { - y = (y-8) * 2 + 1; - } + if(x < 8) i = 7; + else if(x < 16) i = 128 + 7; + else i = 256 + 7; + i -= (x & 7); + if(y < 8) y *= 2; + else y = (y-8) * 2 + 1; i += y * 8; - if (color) - matrices[m].setPixel(i); - else - matrices[m].clrPixel(i); + if(color) matrices[m].setPixel(i); + else matrices[m].clrPixel(i); } - -void Adafruit_HT1632LEDMatrix::begin(uint8_t type) { - for (uint8_t i=0; i= 0) { + + if(_rd >= 0) { pinMode(_rd, OUTPUT); digitalWrite(_rd, HIGH); } +#ifdef __AVR__ + csport = portOutputRegister(digitalPinToPort(_cs)); + csmask = digitalPinToBitMask(_cs); + wrport = portOutputRegister(digitalPinToPort(_wr)); + wrmask = digitalPinToBitMask(_wr); + dataport = portOutputRegister(digitalPinToPort(_data)); + datadir = portModeRegister(digitalPinToPort(_data)); + datamask = digitalPinToBitMask(_data); +#endif + sendcommand(ADA_HT1632_SYS_EN); sendcommand(ADA_HT1632_LED_ON); sendcommand(ADA_HT1632_BLINK_OFF); @@ -161,88 +160,87 @@ void Adafruit_HT1632::begin(uint8_t type) { sendcommand(ADA_HT1632_INT_RC); sendcommand(type); sendcommand(ADA_HT1632_PWM_CONTROL | 0xF); - - WIDTH = 24; - HEIGHT = 16; } void Adafruit_HT1632::setBrightness(uint8_t pwm) { - if (pwm > 15) pwm = 15; + if(pwm > 15) pwm = 15; sendcommand(ADA_HT1632_PWM_CONTROL | pwm); } void Adafruit_HT1632::blink(boolean blinky) { - if (blinky) - sendcommand(ADA_HT1632_BLINK_ON); - else - sendcommand(ADA_HT1632_BLINK_OFF); + sendcommand(blinky ? ADA_HT1632_BLINK_ON : ADA_HT1632_BLINK_OFF); } void Adafruit_HT1632::setPixel(uint16_t i) { - ledmatrix[i/8] |= _BV(i%8); + ledmatrix[i/8] |= (1 << (i & 7)); } void Adafruit_HT1632::clrPixel(uint16_t i) { - ledmatrix[i/8] &= ~_BV(i%8); + ledmatrix[i/8] &= ~(1 << (i & 7)); } void Adafruit_HT1632::dumpScreen() { - Serial.println("---------------------------------------"); + Serial.println(F("---------------------------------------")); - for (uint16_t i=0; i<(WIDTH*HEIGHT/8); i++) { + for (uint16_t i=0; i>= 1) { + *wrport &= ~wrmask; + if(d & bit) *dataport |= datamask; + else *dataport &= ~datamask; + *wrport |= wrmask; + } +#else pinMode(_data, OUTPUT); - for (uint8_t i=bits; i > 0; i--) { + for(uint16_t bit = 1<<(bits-1); bit; bit >>= 1) { digitalWrite(_wr, LOW); - if (d & _BV(i-1)) { - digitalWrite(_data, HIGH); - } else { - digitalWrite(_data, LOW); - } - digitalWrite(_wr, HIGH); + digitalWrite(_data, (d & bit) ? HIGH : LOW); + digitalWrite(_wr, HIGH); } pinMode(_data, INPUT); +#endif } - - - void Adafruit_HT1632::writeRAM(uint8_t addr, uint8_t data) { //Serial.print("Writing 0x"); Serial.print(data&0xF, HEX); //Serial.print(" to 0x"); Serial.println(addr & 0x7F, HEX); @@ -252,29 +250,33 @@ void Adafruit_HT1632::writeRAM(uint8_t addr, uint8_t data) { d |= addr & 0x7F; d <<= 4; d |= data & 0xF; - + +#ifdef __AVR__ + *csport &= ~csmask; + writedata(d, 14); + *csport |= csmask; +#else digitalWrite(_cs, LOW); writedata(d, 14); digitalWrite(_cs, HIGH); +#endif } - void Adafruit_HT1632::sendcommand(uint8_t cmd) { - uint16_t data = 0; - data = ADA_HT1632_COMMAND; - data <<= 8; - data |= cmd; - data <<= 1; - +#ifdef __AVR__ + *csport &= ~csmask; + *datadir |= datamask; // OUTPUT + writedata((((uint16_t)ADA_HT1632_COMMAND << 8) | cmd) << 1, 12); + *datadir &= ~datamask; // INPUT + *csport |= csmask; +#else digitalWrite(_cs, LOW); - writedata(data, 12); - digitalWrite(_cs, HIGH); + writedata((((uint16_t)ADA_HT1632_COMMAND << 8) | cmd) << 1, 12); + digitalWrite(_cs, HIGH); +#endif } - void Adafruit_HT1632::fillScreen() { - for (uint8_t i=0; i<(WIDTH*HEIGHT/8); i++) { - ledmatrix[i] = 0xFF; - } + memset(ledmatrix, 0xFF, sizeof(ledmatrix)); writeScreen(); } diff --git a/Adafruit_HT1632.h b/Adafruit_HT1632.h index 59d2cbe..f914bd8 100644 --- a/Adafruit_HT1632.h +++ b/Adafruit_HT1632.h @@ -9,78 +9,76 @@ #include #endif -#define ADA_HT1632_READ 0x6 -#define ADA_HT1632_WRITE 0x5 -#define ADA_HT1632_COMMAND 0x4 - -#define ADA_HT1632_SYS_DIS 0x00 -#define ADA_HT1632_SYS_EN 0x01 -#define ADA_HT1632_LED_OFF 0x02 -#define ADA_HT1632_LED_ON 0x03 -#define ADA_HT1632_BLINK_OFF 0x08 -#define ADA_HT1632_BLINK_ON 0x09 -#define ADA_HT1632_SLAVE_MODE 0x10 -#define ADA_HT1632_MASTER_MODE 0x14 -#define ADA_HT1632_INT_RC 0x18 -#define ADA_HT1632_EXT_CLK 0x1C -#define ADA_HT1632_PWM_CONTROL 0xA0 +#define ADA_HT1632_READ 0x06 +#define ADA_HT1632_WRITE 0x05 +#define ADA_HT1632_COMMAND 0x04 + +#define ADA_HT1632_SYS_DIS 0x00 +#define ADA_HT1632_SYS_EN 0x01 +#define ADA_HT1632_LED_OFF 0x02 +#define ADA_HT1632_LED_ON 0x03 +#define ADA_HT1632_BLINK_OFF 0x08 +#define ADA_HT1632_BLINK_ON 0x09 +#define ADA_HT1632_SLAVE_MODE 0x10 +#define ADA_HT1632_MASTER_MODE 0x14 +#define ADA_HT1632_INT_RC 0x18 +#define ADA_HT1632_EXT_CLK 0x1C +#define ADA_HT1632_PWM_CONTROL 0xA0 #define ADA_HT1632_COMMON_8NMOS 0x20 -#define ADA_HT1632_COMMON_16NMOS 0x24 +#define ADA_HT1632_COMMON_16NMOS 0x24 #define ADA_HT1632_COMMON_8PMOS 0x28 -#define ADA_HT1632_COMMON_16PMOS 0x2C +#define ADA_HT1632_COMMON_16PMOS 0x2C class Adafruit_HT1632 { public: Adafruit_HT1632(int8_t data, int8_t wr, int8_t cs, int8_t rd = -1); - void begin(uint8_t type); - - void clrPixel(uint16_t i); - void setPixel(uint16_t i); - - void blink(boolean state); - void setBrightness(uint8_t pwm); - - void clearScreen(); - void fillScreen(); - void writeScreen(); - void dumpScreen(); - - private: - int8_t WIDTH, HEIGHT; - int8_t _data, _cs, _wr, _rd; - uint8_t ledmatrix[48]; // 16 * 24 / 8 - void sendcommand(uint8_t c); - void writedata(uint16_t d, uint8_t bits); - void writeRAM(uint8_t addr, uint8_t data); + void begin(uint8_t type), + clrPixel(uint16_t i), + setPixel(uint16_t i), + blink(boolean state), + setBrightness(uint8_t pwm), + clearScreen(), + fillScreen(), + writeScreen(), + dumpScreen(); + + protected: + int8_t _data, _cs, _wr, _rd; + uint8_t ledmatrix[24 * 16 / 8]; + void sendcommand(uint8_t c), + writedata(uint16_t d, uint8_t bits), + writeRAM(uint8_t addr, uint8_t data); +#ifdef __AVR__ + volatile uint8_t *dataport, *csport, *wrport, *datadir; + uint8_t datamask, csmask, wrmask; +#endif }; class Adafruit_HT1632LEDMatrix : public Adafruit_GFX { public: Adafruit_HT1632LEDMatrix(uint8_t data, uint8_t wr, uint8_t cs1); Adafruit_HT1632LEDMatrix(uint8_t data, uint8_t wr, uint8_t cs1, uint8_t cs2); - Adafruit_HT1632LEDMatrix(uint8_t data, uint8_t wr, uint8_t cs1, - uint8_t cs, uint8_t cs3); - Adafruit_HT1632LEDMatrix(uint8_t data, uint8_t wr, uint8_t cs1, - uint8_t cs2, uint8_t cs3, uint8_t cs4); - - void begin(uint8_t type); - void clearScreen(void); - void fillScreen(void); - void blink(boolean b); - void setBrightness(uint8_t brightness); - void writeScreen(); - - void clrPixel(uint8_t x, uint8_t y); - void setPixel(uint8_t x, uint8_t y); - void drawPixel(int16_t x, int16_t y, uint16_t color); - - private: + Adafruit_HT1632LEDMatrix(uint8_t data, uint8_t wr, + uint8_t cs1, uint8_t cs, uint8_t cs3); + Adafruit_HT1632LEDMatrix(uint8_t data, uint8_t wr, + uint8_t cs1, uint8_t cs2, uint8_t cs3, uint8_t cs4); + + boolean begin(uint8_t type); + void clearScreen(void), + fillScreen(void), + blink(boolean b), + setBrightness(uint8_t brightness), + writeScreen(), + clrPixel(uint8_t x, uint8_t y), + setPixel(uint8_t x, uint8_t y), + drawPixel(int16_t x, int16_t y, uint16_t color); + + protected: Adafruit_HT1632 *matrices; - uint8_t matrixNum; + uint8_t matrixNum; }; - #endif /* Adafruit HT1632_H_ */ diff --git a/examples/basicdemo/basicdemo.ino b/examples/basicdemo/basicdemo.ino index 9d1b5ee..e7b2482 100644 --- a/examples/basicdemo/basicdemo.ino +++ b/examples/basicdemo/basicdemo.ino @@ -1,7 +1,7 @@ #include "Adafruit_GFX.h" #include "Adafruit_HT1632.h" -/* +/* This is a basic demo program showing how to write to a HT1632 These can be used for up to 16x24 LED matrix grids, with internal memory and using only 3 pins - data, write and select. @@ -17,7 +17,7 @@ Adafruit_HT1632 matrix = Adafruit_HT1632(HT_DATA, HT_WR, HT_CS); void setup() { Serial.begin(9600); matrix.begin(ADA_HT1632_COMMON_16NMOS); - + delay(100); matrix.clearScreen(); } @@ -27,13 +27,13 @@ void testMatrix(Adafruit_HT1632 matrix) { matrix.setPixel(i); matrix.writeScreen(); } - + // blink! matrix.blink(true); delay(2000); matrix.blink(false); - - // Adjust the brightness down + + // Adjust the brightness down for (int8_t i=15; i>=0; i--) { matrix.setBrightness(i); delay(100); @@ -53,4 +53,4 @@ void testMatrix(Adafruit_HT1632 matrix) { void loop() { testMatrix(matrix); -} \ No newline at end of file +} diff --git a/examples/matrixdemo/matrixdemo.ino b/examples/matrixdemo/matrixdemo.ino index daeae83..9931133 100644 --- a/examples/matrixdemo/matrixdemo.ino +++ b/examples/matrixdemo/matrixdemo.ino @@ -12,39 +12,51 @@ Adafruit_HT1632LEDMatrix matrix = Adafruit_HT1632LEDMatrix(HT_DATA, HT_WR, HT_CS void setup() { Serial.begin(9600); - matrix.begin(ADA_HT1632_COMMON_16NMOS); + matrix.begin(ADA_HT1632_COMMON_16NMOS); matrix.fillScreen(); delay(500); - matrix.clearScreen(); + matrix.clearScreen(); + matrix.setTextWrap(false); } void loop() { - for (uint8_t y=0; y=0; i--) { + matrix.setBrightness(i); + delay(100); + } + // then back up + for (uint8_t i=0; i<16; i++) { + matrix.setBrightness(i); + delay(100); } - } - // blink! - matrix.blink(true); - delay(2000); - matrix.blink(false); - - // Adjust the brightness down - for (int8_t i=15; i>=0; i--) { - matrix.setBrightness(i); - delay(100); - } - // then back up - for (uint8_t i=0; i<16; i++) { - matrix.setBrightness(i); - delay(100); - } - for (uint8_t y=0; y sentence=Arduino library code for HT1632(C) matrix panel driver chips, and the panels we have in the Adafruit shop