TLC59108 8-bit LED Sink Driver module (C) 2013 Christopher Smith <chrylis@gmail.com> GNU Lesser General Public License v3.0
Diff: tlc59108.h
- Revision:
- 0:8edf69cf40fc
- Child:
- 1:b204db0e7687
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tlc59108.h Wed Jan 04 06:15:55 2017 +0000 @@ -0,0 +1,236 @@ +#ifndef __TLC59108_H__ +#define __TLC59108_H__ + +#include "mbed.h" + +class TLC59108 +{ +public: + + typedef uint8_t byte; + + // default I2C addresses + // datasheet, pp 12-13 + struct I2C_ADDR + { + static const byte BASE = 0x80; + static const byte SWRESET = 0x4b; + static const byte ALLCALL = 0x90; + static const byte SUB1 = 0x92; + static const byte SUB2 = 0x94; + static const byte SUB3 = 0x98; + }; + + // register auto-increment modes for setting multiple registers + // datasheet, p 13 + struct AUTO_INCREMENT + { + static const byte ALL = 0x80; // increment through all registers (for initial setup) + static const byte IND = 0xa0; // increment through individual brightness registers + static const byte GLOBAL = 0xc0; // increment through global control registers + static const byte INDGLOBAL = 0xe0; // increment through individual and global registers + }; + + struct LED_MODE + { + static const byte OFF = 0; + static const byte FULL_ON = 1; + static const byte PWM_IND = 2; + static const byte PWM_INDGRP = 3; + }; + + // register names + // datasheet, p 16 + struct REGISTER + { + public: + struct MODE1 + { + static const byte ADDR = 0x00; + + static const byte OSC_OFF = 0x10; + static const byte SUB1 = 0x08; + static const byte SUB2 = 0x04; + static const byte SUB3 = 0x02; + static const byte ALLCALL = 0x01; + }; + + struct MODE2 + { + static const byte ADDR = 0x01; + + static const byte EFCLR = 0x80; + static const byte DMBLNK = 0x20; + static const byte OCH = 0x08; + }; + + struct PWM0 + { + static const byte ADDR = 0x02; + }; + + struct PWM1 + { + static const byte ADDR = 0x03; + }; + + struct PWM2 + { + static const byte ADDR = 0x04; + }; + + struct PWM3 + { + static const byte ADDR = 0x05; + }; + + struct PWM4 + { + static const byte ADDR = 0x06; + }; + + struct PWM5 + { + static const byte ADDR = 0x07; + }; + + struct PWM6 + { + static const byte ADDR = 0x08; + }; + + struct PWM7 + { + static const byte ADDR = 0x09; + }; + + struct GRPPWM + { + static const byte ADDR = 0x0a; + }; + + struct GRPFREQ + { + static const byte ADDR = 0x0b; + }; + + struct LEDOUT0 + { + static const byte ADDR = 0x0c; + }; + + struct LEDOUT1 + { + static const byte ADDR = 0x0d; + }; + + struct SUBADR1 + { + static const byte ADDR = 0x0e; + }; + + struct SUBADR2 + { + static const byte ADDR = 0x0f; + }; + + struct SUBADR3 + { + static const byte ADDR = 0x10; + }; + + struct ALLCALLADR + { + static const byte ADDR = 0x11; + }; + + struct IREF + { + static const byte ADDR = 0x12; + + static const byte CM = 0x80; // current multiplier + static const byte HC = 0x40; // subcurrent + }; + + struct EFLAG + { + static const byte ADDR = 0x13; + }; + }; + + struct ERROR + { + static const uint8_t EINVAL = 2; + }; + + TLC59108(const PinName sda, const PinName scl, const byte selectable_address = 0): + addr(I2C_ADDR::BASE | selectable_address), + i2c(sda, scl) { + setRegister(REGISTER::MODE1::ADDR, REGISTER::MODE1::ALLCALL); + } + + uint8_t setLedOutputMode(const uint8_t outputMode) + { + if(outputMode & 0xfc) + return ERROR::EINVAL; + + byte regValue = (outputMode << 6) | (outputMode << 4) | (outputMode << 2) | outputMode; + + uint8_t retVal = setRegister(REGISTER::LEDOUT0::ADDR, regValue); + retVal &= setRegister(REGISTER::LEDOUT1::ADDR, regValue); + return retVal; + } + + uint8_t setBrightness(const uint8_t pwmChannel, const uint8_t dutyCycle) + { + if(pwmChannel > 7) + return ERROR::EINVAL; + + return setRegister(REGISTER::PWM0::ADDR + pwmChannel, dutyCycle); + } + + uint8_t setBrightness(const uint8_t dutyCycle) + { + uint8_t status = 0; + i2c.start(); + status &= i2c.write(addr); + status &= i2c.write(REGISTER::PWM0::ADDR | AUTO_INCREMENT::IND); + for (uint8_t i = 0; i < NUM_CHANNELS; i++) + status &= i2c.write(dutyCycle); + i2c.stop(); + return status; + } + + uint8_t setBrightness(const byte dutyCycles[]) + { + return setRegisters(REGISTER::PWM0::ADDR, dutyCycles, NUM_CHANNELS); + } + + uint8_t setGroupBrightness(const uint8_t dutyCycle) + { + return setRegister(REGISTER::GRPPWM::ADDR, dutyCycle); + } + + int setRegister(const byte reg, const byte value) { + char cmd[2] = { reg, value }; + return i2c.write(addr, cmd, 2); + } + + int setRegisters(const byte reg, const byte values[], const uint8_t length) { + uint8_t status = 0; + i2c.start(); + status &= i2c.write(addr); + status &= i2c.write(reg | AUTO_INCREMENT::ALL); + for (uint8_t i = 0; i < length; i++) + status &= i2c.write(values[i]); + i2c.stop(); + return status; + } + +protected: + const static uint8_t NUM_CHANNELS = 8; + byte addr; + I2C i2c; +}; + +#endif \ No newline at end of file