/*************************************************** This is a library for our I2C LED Backpacks Designed specifically to work with the Adafruit LED Matrix backpacks ----> http://www.adafruit.com/products/ ----> http://www.adafruit.com/products/ These displays use I2C to communicate, 2 pins are required to interface. There are multiple selectable I2C addresses. For backpacks with 2 Address Select pins: 0x70, 0x71, 0x72 or 0x73. For backpacks with 3 Address Select pins: 0x70 thru 0x77 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. MIT license, all text above must be included in any redistribution ****************************************************/ #include #include "Adafruit_LEDBackpack.h" #include "Adafruit_GFX.h" #ifndef _BV #define _BV(bit) (1<<(bit)) #endif #ifndef _swap_int16_t #define _swap_int16_t(a, b) { int16_t t = a; a = b; b = t; } #endif static const uint8_t numbertable[] = { 0x3F, /* 0 */ 0x06, /* 1 */ 0x5B, /* 2 */ 0x4F, /* 3 */ 0x66, /* 4 */ 0x6D, /* 5 */ 0x7D, /* 6 */ 0x07, /* 7 */ 0x7F, /* 8 */ 0x6F, /* 9 */ 0x77, /* a */ 0x7C, /* b */ 0x39, /* C */ 0x5E, /* d */ 0x79, /* E */ 0x71, /* F */ }; static const uint16_t alphafonttable[] PROGMEM = { 0b0000000000000001, 0b0000000000000010, 0b0000000000000100, 0b0000000000001000, 0b0000000000010000, 0b0000000000100000, 0b0000000001000000, 0b0000000010000000, 0b0000000100000000, 0b0000001000000000, 0b0000010000000000, 0b0000100000000000, 0b0001000000000000, 0b0010000000000000, 0b0100000000000000, 0b1000000000000000, 0b0000000000000000, 0b0000000000000000, 0b0000000000000000, 0b0000000000000000, 0b0000000000000000, 0b0000000000000000, 0b0000000000000000, 0b0000000000000000, 0b0001001011001001, 0b0001010111000000, 0b0001001011111001, 0b0000000011100011, 0b0000010100110000, 0b0001001011001000, 0b0011101000000000, 0b0001011100000000, 0b0000000000000000, // 0b0000000000000110, // ! 0b0000001000100000, // " 0b0001001011001110, // # 0b0001001011101101, // $ 0b0000110000100100, // % 0b0010001101011101, // & 0b0000010000000000, // ' 0b0010010000000000, // ( 0b0000100100000000, // ) 0b0011111111000000, // * 0b0001001011000000, // + 0b0000100000000000, // , 0b0000000011000000, // - 0b0000000000000000, // . 0b0000110000000000, // / 0b0000110000111111, // 0 0b0000000000000110, // 1 0b0000000011011011, // 2 0b0000000010001111, // 3 0b0000000011100110, // 4 0b0010000001101001, // 5 0b0000000011111101, // 6 0b0000000000000111, // 7 0b0000000011111111, // 8 0b0000000011101111, // 9 0b0001001000000000, // : 0b0000101000000000, // ; 0b0010010000000000, // < 0b0000000011001000, // = 0b0000100100000000, // > 0b0001000010000011, // ? 0b0000001010111011, // @ 0b0000000011110111, // A 0b0001001010001111, // B 0b0000000000111001, // C 0b0001001000001111, // D 0b0000000011111001, // E 0b0000000001110001, // F 0b0000000010111101, // G 0b0000000011110110, // H 0b0001001000000000, // I 0b0000000000011110, // J 0b0010010001110000, // K 0b0000000000111000, // L 0b0000010100110110, // M 0b0010000100110110, // N 0b0000000000111111, // O 0b0000000011110011, // P 0b0010000000111111, // Q 0b0010000011110011, // R 0b0000000011101101, // S 0b0001001000000001, // T 0b0000000000111110, // U 0b0000110000110000, // V 0b0010100000110110, // W 0b0010110100000000, // X 0b0001010100000000, // Y 0b0000110000001001, // Z 0b0000000000111001, // [ 0b0010000100000000, // 0b0000000000001111, // ] 0b0000110000000011, // ^ 0b0000000000001000, // _ 0b0000000100000000, // ` 0b0001000001011000, // a 0b0010000001111000, // b 0b0000000011011000, // c 0b0000100010001110, // d 0b0000100001011000, // e 0b0000000001110001, // f 0b0000010010001110, // g 0b0001000001110000, // h 0b0001000000000000, // i 0b0000000000001110, // j 0b0011011000000000, // k 0b0000000000110000, // l 0b0001000011010100, // m 0b0001000001010000, // n 0b0000000011011100, // o 0b0000000101110000, // p 0b0000010010000110, // q 0b0000000001010000, // r 0b0010000010001000, // s 0b0000000001111000, // t 0b0000000000011100, // u 0b0010000000000100, // v 0b0010100000010100, // w 0b0010100011000000, // x 0b0010000000001100, // y 0b0000100001001000, // z 0b0000100101001001, // { 0b0001001000000000, // | 0b0010010010001001, // } 0b0000010100100000, // ~ 0b0011111111111111, }; void Adafruit_LEDBackpack::setBrightness(uint8_t b) { if (b > 15) b = 15; Wire.beginTransmission(i2c_addr); Wire.write(HT16K33_CMD_BRIGHTNESS | b); Wire.endTransmission(); } void Adafruit_LEDBackpack::blinkRate(uint8_t b) { Wire.beginTransmission(i2c_addr); if (b > 3) b = 0; // turn off if not sure Wire.write(HT16K33_BLINK_CMD | HT16K33_BLINK_DISPLAYON | (b << 1)); Wire.endTransmission(); } Adafruit_LEDBackpack::Adafruit_LEDBackpack(void) { } void Adafruit_LEDBackpack::begin(uint8_t _addr = 0x70) { i2c_addr = _addr; Wire.begin(); Wire.beginTransmission(i2c_addr); Wire.write(0x21); // turn on oscillator Wire.endTransmission(); blinkRate(HT16K33_BLINK_OFF); setBrightness(15); // max brightness } void Adafruit_LEDBackpack::writeDisplay(void) { Wire.beginTransmission(i2c_addr); Wire.write((uint8_t)0x00); // start at address $00 for (uint8_t i=0; i<8; i++) { Wire.write(displaybuffer[i] & 0xFF); Wire.write(displaybuffer[i] >> 8); } Wire.endTransmission(); } void Adafruit_LEDBackpack::clear(void) { for (uint8_t i=0; i<8; i++) { displaybuffer[i] = 0; } } /******************************* QUAD ALPHANUM OBJECT */ Adafruit_AlphaNum4::Adafruit_AlphaNum4(void) { } void Adafruit_AlphaNum4::writeDigitRaw(uint8_t n, uint16_t bitmask) { displaybuffer[n] = bitmask; } void Adafruit_AlphaNum4::writeDigitAscii(uint8_t n, uint8_t a, boolean d) { uint16_t font = pgm_read_word(alphafonttable+a); displaybuffer[n] = font; /* Serial.print(a, DEC); Serial.print(" / '"); Serial.write(a); Serial.print("' = 0x"); Serial.println(font, HEX); */ if (d) displaybuffer[n] |= (1<<14); } /******************************* 24 BARGRAPH OBJECT */ Adafruit_24bargraph::Adafruit_24bargraph(void) { } void Adafruit_24bargraph::setBar(uint8_t bar, uint8_t color) { uint16_t a, c; if (bar < 12) c = bar / 4; else c = (bar - 12) / 4; a = bar % 4; if (bar >= 12) a += 4; //Serial.print("Ano = "); Serial.print(a); Serial.print(" Cath = "); Serial.println(c); if (color == LED_RED) { // Turn on red LED. displaybuffer[c] |= _BV(a); // Turn off green LED. displaybuffer[c] &= ~_BV(a+8); } else if (color == LED_YELLOW) { // Turn on red and green LED. displaybuffer[c] |= _BV(a) | _BV(a+8); } else if (color == LED_OFF) { // Turn off red and green LED. displaybuffer[c] &= ~_BV(a) & ~_BV(a+8); } else if (color == LED_GREEN) { // Turn on green LED. displaybuffer[c] |= _BV(a+8); // Turn off red LED. displaybuffer[c] &= ~_BV(a); } } /******************************* 16x8 MATRIX OBJECT */ Adafruit_8x16matrix::Adafruit_8x16matrix(void) : Adafruit_GFX(8, 16) { } void Adafruit_8x16matrix::drawPixel(int16_t x, int16_t y, uint16_t color) { // check rotation, move pixel around if necessary switch (getRotation()) { case 2: _swap_int16_t(x, y); x = 16 - x - 1; break; case 3: x = 16 - x - 1; y = 8 - y - 1; break; case 0: _swap_int16_t(x, y); y = 8 - y - 1; break; } /* Serial.print("("); Serial.print(x); Serial.print(","); Serial.print(y); Serial.println(")"); */ if ((y < 0) || (y >= 8)) return; if ((x < 0) || (x >= 16)) return; if (color) { displaybuffer[y] |= 1 << x; } else { displaybuffer[y] &= ~(1 << x); } } /******************************* 16x8 MINI MATRIX OBJECT */ Adafruit_8x16minimatrix::Adafruit_8x16minimatrix(void) : Adafruit_GFX(8, 16) { } void Adafruit_8x16minimatrix::drawPixel(int16_t x, int16_t y, uint16_t color) { if ((y < 0) || (x < 0)) return; if ((getRotation() % 2 == 0) && ((y >= 16) || (x >= 8))) return; if ((getRotation() % 2 == 1) && ((x >= 16) || (y >= 8))) return; // check rotation, move pixel around if necessary switch (getRotation()) { case 2: if (y >= 8) { x += 8; y -= 8; } _swap_int16_t(x, y); break; case 3: x = 16 - x - 1; if (x >= 8) { x -= 8; y += 8; } break; case 0: y = 16 - y - 1; x = 8 - x - 1; if (y >= 8) { x += 8; y -= 8; } _swap_int16_t(x, y); break; case 1: y = 8 - y - 1; if (x >= 8) { x -= 8; y += 8; } break; } if (color) { displaybuffer[x] |= 1 << y; } else { displaybuffer[x] &= ~(1 << y); } } /******************************* 8x8 MATRIX OBJECT */ Adafruit_8x8matrix::Adafruit_8x8matrix(void) : Adafruit_GFX(8, 8) { } void Adafruit_8x8matrix::drawPixel(int16_t x, int16_t y, uint16_t color) { if ((y < 0) || (y >= 8)) return; if ((x < 0) || (x >= 8)) return; // check rotation, move pixel around if necessary switch (getRotation()) { case 1: _swap_int16_t(x, y); x = 8 - x - 1; break; case 2: x = 8 - x - 1; y = 8 - y - 1; break; case 3: _swap_int16_t(x, y); y = 8 - y - 1; break; } // wrap around the x x += 7; x %= 8; if (color) { displaybuffer[y] |= 1 << x; } else { displaybuffer[y] &= ~(1 << x); } } /******************************* 8x8 BICOLOR MATRIX OBJECT */ Adafruit_BicolorMatrix::Adafruit_BicolorMatrix(void) : Adafruit_GFX(8, 8) { } void Adafruit_BicolorMatrix::drawPixel(int16_t x, int16_t y, uint16_t color) { if ((y < 0) || (y >= 8)) return; if ((x < 0) || (x >= 8)) return; switch (getRotation()) { case 1: _swap_int16_t(x, y); x = 8 - x - 1; break; case 2: x = 8 - x - 1; y = 8 - y - 1; break; case 3: _swap_int16_t(x, y); y = 8 - y - 1; break; } if (color == LED_GREEN) { // Turn on green LED. displaybuffer[y] |= 1 << x; // Turn off red LED. displaybuffer[y] &= ~(1 << (x+8)); } else if (color == LED_RED) { // Turn on red LED. displaybuffer[y] |= 1 << (x+8); // Turn off green LED. displaybuffer[y] &= ~(1 << x); } else if (color == LED_YELLOW) { // Turn on green and red LED. displaybuffer[y] |= (1 << (x+8)) | (1 << x); } else if (color == LED_OFF) { // Turn off green and red LED. displaybuffer[y] &= ~(1 << x) & ~(1 << (x+8)); } } /******************************* 7 SEGMENT OBJECT */ Adafruit_7segment::Adafruit_7segment(void) { position = 0; } void Adafruit_7segment::print(unsigned long n, int base) { if (base == 0) write(n); else printNumber(n, base); } void Adafruit_7segment::print(char c, int base) { print((long) c, base); } void Adafruit_7segment::print(unsigned char b, int base) { print((unsigned long) b, base); } void Adafruit_7segment::print(int n, int base) { print((long) n, base); } void Adafruit_7segment::print(unsigned int n, int base) { print((unsigned long) n, base); } void Adafruit_7segment::println(void) { position = 0; } void Adafruit_7segment::println(char c, int base) { print(c, base); println(); } void Adafruit_7segment::println(unsigned char b, int base) { print(b, base); println(); } void Adafruit_7segment::println(int n, int base) { print(n, base); println(); } void Adafruit_7segment::println(unsigned int n, int base) { print(n, base); println(); } void Adafruit_7segment::println(long n, int base) { print(n, base); println(); } void Adafruit_7segment::println(unsigned long n, int base) { print(n, base); println(); } void Adafruit_7segment::println(double n, int digits) { print(n, digits); println(); } void Adafruit_7segment::print(double n, int digits) { printFloat(n, digits); } size_t Adafruit_7segment::write(uint8_t c) { uint8_t r = 0; if (c == '\n') position = 0; if (c == '\r') position = 0; if ((c >= '0') && (c <= '9')) { writeDigitNum(position, c-'0'); r = 1; } position++; if (position == 2) position++; return r; } void Adafruit_7segment::writeDigitRaw(uint8_t d, uint8_t bitmask) { if (d > 4) return; displaybuffer[d] = bitmask; } void Adafruit_7segment::drawColon(boolean state) { if (state) displaybuffer[2] = 0x2; else displaybuffer[2] = 0; } void Adafruit_7segment::writeColon(void) { Wire.beginTransmission(i2c_addr); Wire.write((uint8_t)0x04); // start at address $02 Wire.write(displaybuffer[2] & 0xFF); Wire.write(displaybuffer[2] >> 8); Wire.endTransmission(); } void Adafruit_7segment::writeDigitNum(uint8_t d, uint8_t num, boolean dot) { if (d > 4) return; writeDigitRaw(d, numbertable[num] | (dot << 7)); } void Adafruit_7segment::print(long n, int base) { printNumber(n, base); } void Adafruit_7segment::printNumber(long n, uint8_t base) { printFloat(n, 0, base); } void Adafruit_7segment::printFloat(double n, uint8_t fracDigits, uint8_t base) { uint8_t numericDigits = 4; // available digits on display boolean isNegative = false; // true if the number is negative // is the number negative? if(n < 0) { isNegative = true; // need to draw sign later --numericDigits; // the sign will take up one digit n *= -1; // pretend the number is positive } // calculate the factor required to shift all fractional digits // into the integer part of the number double toIntFactor = 1.0; for(int i = 0; i < fracDigits; ++i) toIntFactor *= base; // create integer containing digits to display by applying // shifting factor and rounding adjustment uint32_t displayNumber = n * toIntFactor + 0.5; // calculate upper bound on displayNumber given // available digits on display uint32_t tooBig = 1; for(int i = 0; i < numericDigits; ++i) tooBig *= base; // if displayNumber is too large, try fewer fractional digits while(displayNumber >= tooBig) { --fracDigits; toIntFactor /= base; displayNumber = n * toIntFactor + 0.5; } // did toIntFactor shift the decimal off the display? if (toIntFactor < 1) { printError(); } else { // otherwise, display the number int8_t displayPos = 4; if (displayNumber) //if displayNumber is not 0 { for(uint8_t i = 0; displayNumber || i <= fracDigits; ++i) { boolean displayDecimal = (fracDigits != 0 && i == fracDigits); writeDigitNum(displayPos--, displayNumber % base, displayDecimal); if(displayPos == 2) writeDigitRaw(displayPos--, 0x00); displayNumber /= base; } } else { writeDigitNum(displayPos--, 0, false); } // display negative sign if negative if(isNegative) writeDigitRaw(displayPos--, 0x40); // clear remaining display positions while(displayPos >= 0) writeDigitRaw(displayPos--, 0x00); } } void Adafruit_7segment::printError(void) { for(uint8_t i = 0; i < SEVENSEG_DIGITS; ++i) { writeDigitRaw(i, (i == 2 ? 0x00 : 0x40)); } }