#include #ifndef _swap_int16_t #define _swap_int16_t(a, b) \ { \ int16_t t = a; \ a = b; \ b = t; \ } #endif /**************************************************************************/ /*! @brief Constructor for breakout version @param width Desired width of led display @param height Desired height of led display */ /**************************************************************************/ Adafruit_IS31FL3731::Adafruit_IS31FL3731(uint8_t width, uint8_t height) : Adafruit_GFX(width, height) {} /**************************************************************************/ /*! @brief Constructor for FeatherWing version (15x7 LEDs) */ /**************************************************************************/ Adafruit_IS31FL3731_Wing::Adafruit_IS31FL3731_Wing(void) : Adafruit_IS31FL3731(15, 7) {} /**************************************************************************/ /*! @brief Initialize hardware and clear display @param addr The I2C address we expect to find the chip at @param theWire The TwoWire I2C bus device to use, defaults to &Wire @returns True on success, false if chip isnt found */ /**************************************************************************/ bool Adafruit_IS31FL3731::begin(uint8_t addr, TwoWire *theWire) { if (_i2c_dev) { delete _i2c_dev; } _i2c_dev = new Adafruit_I2CDevice(addr, theWire); if (!_i2c_dev->begin()) { return false; } _i2c_dev->setSpeed(400000); _frame = 0; // shutdown writeRegister8(ISSI_BANK_FUNCTIONREG, ISSI_REG_SHUTDOWN, 0x00); delay(10); // out of shutdown writeRegister8(ISSI_BANK_FUNCTIONREG, ISSI_REG_SHUTDOWN, 0x01); // picture mode writeRegister8(ISSI_BANK_FUNCTIONREG, ISSI_REG_CONFIG, ISSI_REG_CONFIG_PICTUREMODE); displayFrame(_frame); // all LEDs on & 0 PWM clear(); // set each led to 0 PWM for (uint8_t f = 0; f < 8; f++) { for (uint8_t i = 0; i <= 0x11; i++) writeRegister8(f, i, 0xff); // each 8 LEDs on } audioSync(false); return true; } /**************************************************************************/ /*! @brief Sets all LEDs on & 0 PWM for current frame. */ /**************************************************************************/ void Adafruit_IS31FL3731::clear(void) { selectBank(_frame); uint8_t erasebuf[25]; memset(erasebuf, 0, 25); for (uint8_t i = 0; i < 6; i++) { erasebuf[0] = 0x24 + i * 24; _i2c_dev->write(erasebuf, 25); } } /**************************************************************************/ /*! @brief Low level accesssor - sets a 8-bit PWM pixel value to a bank location does not handle rotation, x/y or any rearrangements! @param lednum The offset into the bank that corresponds to the LED @param bank The bank/frame we will set the data in @param pwm brightnes, from 0 (off) to 255 (max on) */ /**************************************************************************/ void Adafruit_IS31FL3731::setLEDPWM(uint8_t lednum, uint8_t pwm, uint8_t bank) { if (lednum >= 144) return; writeRegister8(bank, 0x24 + lednum, pwm); } /**************************************************************************/ /*! @brief Adafruit GFX low level accesssor - sets a 8-bit PWM pixel value handles rotation and pixel arrangement, unlike setLEDPWM @param x The x position, starting with 0 for left-most side @param y The y position, starting with 0 for top-most side @param color Despite being a 16-bit value, takes 0 (off) to 255 (max on) */ /**************************************************************************/ void Adafruit_IS31FL3731_Wing::drawPixel(int16_t x, int16_t y, uint16_t color) { // check rotation, move pixel around if necessary switch (getRotation()) { case 1: _swap_int16_t(x, y); x = 15 - x - 1; break; case 2: x = 15 - x - 1; y = 7 - y - 1; break; case 3: _swap_int16_t(x, y); y = 9 - y - 1; break; } // charlie wing is smaller: if ((x < 0) || (x >= 16) || (y < 0) || (y >= 7)) return; if (x > 7) { x = 15 - x; y += 8; } else { y = 7 - y; } _swap_int16_t(x, y); if (color > 255) color = 255; // PWM 8bit max setLEDPWM(x + y * 16, color, _frame); return; } /**************************************************************************/ /*! @brief Adafruit GFX low level accesssor - sets a 8-bit PWM pixel value handles rotation and pixel arrangement, unlike setLEDPWM @param x The x position, starting with 0 for left-most side @param y The y position, starting with 0 for top-most side @param color Despite being a 16-bit value, takes 0 (off) to 255 (max on) */ /**************************************************************************/ void Adafruit_IS31FL3731::drawPixel(int16_t x, int16_t y, uint16_t color) { // check rotation, move pixel around if necessary switch (getRotation()) { case 1: _swap_int16_t(x, y); x = 16 - x - 1; break; case 2: x = 16 - x - 1; y = 9 - y - 1; break; case 3: _swap_int16_t(x, y); y = 9 - y - 1; break; } if ((x < 0) || (x >= 16)) return; if ((y < 0) || (y >= 9)) return; if (color > 255) color = 255; // PWM 8bit max setLEDPWM(x + y * 16, color, _frame); return; } /**************************************************************************/ /*! @brief Set's this object's frame tracker (does not talk to the chip) @param frame Ranges from 0 - 7 for the 8 frames */ /**************************************************************************/ void Adafruit_IS31FL3731::setFrame(uint8_t frame) { _frame = frame; } /**************************************************************************/ /*! @brief Have the chip set the display to the contents of a frame @param frame Ranges from 0 - 7 for the 8 frames */ /**************************************************************************/ void Adafruit_IS31FL3731::displayFrame(uint8_t frame) { if (frame > 7) frame = 0; writeRegister8(ISSI_BANK_FUNCTIONREG, ISSI_REG_PICTUREFRAME, frame); } /**************************************************************************/ /*! @brief Switch to a given bank in the chip memory for future reads @param bank The IS31 bank to switch to @returns False if I2C command failed to be ack'd */ /**************************************************************************/ bool Adafruit_IS31FL3731::selectBank(uint8_t bank) { uint8_t cmd[2] = {ISSI_COMMANDREGISTER, bank}; return _i2c_dev->write(cmd, 2); } /**************************************************************************/ /*! @brief Enable the audio 'sync' for brightness pulsing (not really tested) @param sync True to enable, False to disable */ /**************************************************************************/ void Adafruit_IS31FL3731::audioSync(bool sync) { if (sync) { writeRegister8(ISSI_BANK_FUNCTIONREG, ISSI_REG_AUDIOSYNC, 0x1); } else { writeRegister8(ISSI_BANK_FUNCTIONREG, ISSI_REG_AUDIOSYNC, 0x0); } } /**************************************************************************/ /*! @brief Write one byte to a register located in a given bank @param bank The IS31 bank to write the register location @param reg the offset into the bank to write @param data The byte value @returns False if I2C command failed to be ack'd */ /**************************************************************************/ bool Adafruit_IS31FL3731::writeRegister8(uint8_t bank, uint8_t reg, uint8_t data) { selectBank(bank); uint8_t cmd[2] = {reg, data}; return _i2c_dev->write(cmd, 2); } /**************************************************************************/ /*! @brief Read one byte from a register located in a given bank @param bank The IS31 bank to read the register location @param reg the offset into the bank to read @return 1 byte value */ /**************************************************************************/ uint8_t Adafruit_IS31FL3731::readRegister8(uint8_t bank, uint8_t reg) { uint8_t val = 0xFF; selectBank(bank); _i2c_dev->write_then_read(®, 1, &val, 1); return val; }