TLC59108 8-bit LED Sink Driver module (C) 2013 Christopher Smith <chrylis@gmail.com> GNU Lesser General Public License v3.0
tlc59108.h@0:8edf69cf40fc, 2017-01-04 (annotated)
- Committer:
- eisd
- Date:
- Wed Jan 04 06:15:55 2017 +0000
- Revision:
- 0:8edf69cf40fc
- Child:
- 1:b204db0e7687
Working TLC59108 driver library
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
eisd | 0:8edf69cf40fc | 1 | #ifndef __TLC59108_H__ |
eisd | 0:8edf69cf40fc | 2 | #define __TLC59108_H__ |
eisd | 0:8edf69cf40fc | 3 | |
eisd | 0:8edf69cf40fc | 4 | #include "mbed.h" |
eisd | 0:8edf69cf40fc | 5 | |
eisd | 0:8edf69cf40fc | 6 | class TLC59108 |
eisd | 0:8edf69cf40fc | 7 | { |
eisd | 0:8edf69cf40fc | 8 | public: |
eisd | 0:8edf69cf40fc | 9 | |
eisd | 0:8edf69cf40fc | 10 | typedef uint8_t byte; |
eisd | 0:8edf69cf40fc | 11 | |
eisd | 0:8edf69cf40fc | 12 | // default I2C addresses |
eisd | 0:8edf69cf40fc | 13 | // datasheet, pp 12-13 |
eisd | 0:8edf69cf40fc | 14 | struct I2C_ADDR |
eisd | 0:8edf69cf40fc | 15 | { |
eisd | 0:8edf69cf40fc | 16 | static const byte BASE = 0x80; |
eisd | 0:8edf69cf40fc | 17 | static const byte SWRESET = 0x4b; |
eisd | 0:8edf69cf40fc | 18 | static const byte ALLCALL = 0x90; |
eisd | 0:8edf69cf40fc | 19 | static const byte SUB1 = 0x92; |
eisd | 0:8edf69cf40fc | 20 | static const byte SUB2 = 0x94; |
eisd | 0:8edf69cf40fc | 21 | static const byte SUB3 = 0x98; |
eisd | 0:8edf69cf40fc | 22 | }; |
eisd | 0:8edf69cf40fc | 23 | |
eisd | 0:8edf69cf40fc | 24 | // register auto-increment modes for setting multiple registers |
eisd | 0:8edf69cf40fc | 25 | // datasheet, p 13 |
eisd | 0:8edf69cf40fc | 26 | struct AUTO_INCREMENT |
eisd | 0:8edf69cf40fc | 27 | { |
eisd | 0:8edf69cf40fc | 28 | static const byte ALL = 0x80; // increment through all registers (for initial setup) |
eisd | 0:8edf69cf40fc | 29 | static const byte IND = 0xa0; // increment through individual brightness registers |
eisd | 0:8edf69cf40fc | 30 | static const byte GLOBAL = 0xc0; // increment through global control registers |
eisd | 0:8edf69cf40fc | 31 | static const byte INDGLOBAL = 0xe0; // increment through individual and global registers |
eisd | 0:8edf69cf40fc | 32 | }; |
eisd | 0:8edf69cf40fc | 33 | |
eisd | 0:8edf69cf40fc | 34 | struct LED_MODE |
eisd | 0:8edf69cf40fc | 35 | { |
eisd | 0:8edf69cf40fc | 36 | static const byte OFF = 0; |
eisd | 0:8edf69cf40fc | 37 | static const byte FULL_ON = 1; |
eisd | 0:8edf69cf40fc | 38 | static const byte PWM_IND = 2; |
eisd | 0:8edf69cf40fc | 39 | static const byte PWM_INDGRP = 3; |
eisd | 0:8edf69cf40fc | 40 | }; |
eisd | 0:8edf69cf40fc | 41 | |
eisd | 0:8edf69cf40fc | 42 | // register names |
eisd | 0:8edf69cf40fc | 43 | // datasheet, p 16 |
eisd | 0:8edf69cf40fc | 44 | struct REGISTER |
eisd | 0:8edf69cf40fc | 45 | { |
eisd | 0:8edf69cf40fc | 46 | public: |
eisd | 0:8edf69cf40fc | 47 | struct MODE1 |
eisd | 0:8edf69cf40fc | 48 | { |
eisd | 0:8edf69cf40fc | 49 | static const byte ADDR = 0x00; |
eisd | 0:8edf69cf40fc | 50 | |
eisd | 0:8edf69cf40fc | 51 | static const byte OSC_OFF = 0x10; |
eisd | 0:8edf69cf40fc | 52 | static const byte SUB1 = 0x08; |
eisd | 0:8edf69cf40fc | 53 | static const byte SUB2 = 0x04; |
eisd | 0:8edf69cf40fc | 54 | static const byte SUB3 = 0x02; |
eisd | 0:8edf69cf40fc | 55 | static const byte ALLCALL = 0x01; |
eisd | 0:8edf69cf40fc | 56 | }; |
eisd | 0:8edf69cf40fc | 57 | |
eisd | 0:8edf69cf40fc | 58 | struct MODE2 |
eisd | 0:8edf69cf40fc | 59 | { |
eisd | 0:8edf69cf40fc | 60 | static const byte ADDR = 0x01; |
eisd | 0:8edf69cf40fc | 61 | |
eisd | 0:8edf69cf40fc | 62 | static const byte EFCLR = 0x80; |
eisd | 0:8edf69cf40fc | 63 | static const byte DMBLNK = 0x20; |
eisd | 0:8edf69cf40fc | 64 | static const byte OCH = 0x08; |
eisd | 0:8edf69cf40fc | 65 | }; |
eisd | 0:8edf69cf40fc | 66 | |
eisd | 0:8edf69cf40fc | 67 | struct PWM0 |
eisd | 0:8edf69cf40fc | 68 | { |
eisd | 0:8edf69cf40fc | 69 | static const byte ADDR = 0x02; |
eisd | 0:8edf69cf40fc | 70 | }; |
eisd | 0:8edf69cf40fc | 71 | |
eisd | 0:8edf69cf40fc | 72 | struct PWM1 |
eisd | 0:8edf69cf40fc | 73 | { |
eisd | 0:8edf69cf40fc | 74 | static const byte ADDR = 0x03; |
eisd | 0:8edf69cf40fc | 75 | }; |
eisd | 0:8edf69cf40fc | 76 | |
eisd | 0:8edf69cf40fc | 77 | struct PWM2 |
eisd | 0:8edf69cf40fc | 78 | { |
eisd | 0:8edf69cf40fc | 79 | static const byte ADDR = 0x04; |
eisd | 0:8edf69cf40fc | 80 | }; |
eisd | 0:8edf69cf40fc | 81 | |
eisd | 0:8edf69cf40fc | 82 | struct PWM3 |
eisd | 0:8edf69cf40fc | 83 | { |
eisd | 0:8edf69cf40fc | 84 | static const byte ADDR = 0x05; |
eisd | 0:8edf69cf40fc | 85 | }; |
eisd | 0:8edf69cf40fc | 86 | |
eisd | 0:8edf69cf40fc | 87 | struct PWM4 |
eisd | 0:8edf69cf40fc | 88 | { |
eisd | 0:8edf69cf40fc | 89 | static const byte ADDR = 0x06; |
eisd | 0:8edf69cf40fc | 90 | }; |
eisd | 0:8edf69cf40fc | 91 | |
eisd | 0:8edf69cf40fc | 92 | struct PWM5 |
eisd | 0:8edf69cf40fc | 93 | { |
eisd | 0:8edf69cf40fc | 94 | static const byte ADDR = 0x07; |
eisd | 0:8edf69cf40fc | 95 | }; |
eisd | 0:8edf69cf40fc | 96 | |
eisd | 0:8edf69cf40fc | 97 | struct PWM6 |
eisd | 0:8edf69cf40fc | 98 | { |
eisd | 0:8edf69cf40fc | 99 | static const byte ADDR = 0x08; |
eisd | 0:8edf69cf40fc | 100 | }; |
eisd | 0:8edf69cf40fc | 101 | |
eisd | 0:8edf69cf40fc | 102 | struct PWM7 |
eisd | 0:8edf69cf40fc | 103 | { |
eisd | 0:8edf69cf40fc | 104 | static const byte ADDR = 0x09; |
eisd | 0:8edf69cf40fc | 105 | }; |
eisd | 0:8edf69cf40fc | 106 | |
eisd | 0:8edf69cf40fc | 107 | struct GRPPWM |
eisd | 0:8edf69cf40fc | 108 | { |
eisd | 0:8edf69cf40fc | 109 | static const byte ADDR = 0x0a; |
eisd | 0:8edf69cf40fc | 110 | }; |
eisd | 0:8edf69cf40fc | 111 | |
eisd | 0:8edf69cf40fc | 112 | struct GRPFREQ |
eisd | 0:8edf69cf40fc | 113 | { |
eisd | 0:8edf69cf40fc | 114 | static const byte ADDR = 0x0b; |
eisd | 0:8edf69cf40fc | 115 | }; |
eisd | 0:8edf69cf40fc | 116 | |
eisd | 0:8edf69cf40fc | 117 | struct LEDOUT0 |
eisd | 0:8edf69cf40fc | 118 | { |
eisd | 0:8edf69cf40fc | 119 | static const byte ADDR = 0x0c; |
eisd | 0:8edf69cf40fc | 120 | }; |
eisd | 0:8edf69cf40fc | 121 | |
eisd | 0:8edf69cf40fc | 122 | struct LEDOUT1 |
eisd | 0:8edf69cf40fc | 123 | { |
eisd | 0:8edf69cf40fc | 124 | static const byte ADDR = 0x0d; |
eisd | 0:8edf69cf40fc | 125 | }; |
eisd | 0:8edf69cf40fc | 126 | |
eisd | 0:8edf69cf40fc | 127 | struct SUBADR1 |
eisd | 0:8edf69cf40fc | 128 | { |
eisd | 0:8edf69cf40fc | 129 | static const byte ADDR = 0x0e; |
eisd | 0:8edf69cf40fc | 130 | }; |
eisd | 0:8edf69cf40fc | 131 | |
eisd | 0:8edf69cf40fc | 132 | struct SUBADR2 |
eisd | 0:8edf69cf40fc | 133 | { |
eisd | 0:8edf69cf40fc | 134 | static const byte ADDR = 0x0f; |
eisd | 0:8edf69cf40fc | 135 | }; |
eisd | 0:8edf69cf40fc | 136 | |
eisd | 0:8edf69cf40fc | 137 | struct SUBADR3 |
eisd | 0:8edf69cf40fc | 138 | { |
eisd | 0:8edf69cf40fc | 139 | static const byte ADDR = 0x10; |
eisd | 0:8edf69cf40fc | 140 | }; |
eisd | 0:8edf69cf40fc | 141 | |
eisd | 0:8edf69cf40fc | 142 | struct ALLCALLADR |
eisd | 0:8edf69cf40fc | 143 | { |
eisd | 0:8edf69cf40fc | 144 | static const byte ADDR = 0x11; |
eisd | 0:8edf69cf40fc | 145 | }; |
eisd | 0:8edf69cf40fc | 146 | |
eisd | 0:8edf69cf40fc | 147 | struct IREF |
eisd | 0:8edf69cf40fc | 148 | { |
eisd | 0:8edf69cf40fc | 149 | static const byte ADDR = 0x12; |
eisd | 0:8edf69cf40fc | 150 | |
eisd | 0:8edf69cf40fc | 151 | static const byte CM = 0x80; // current multiplier |
eisd | 0:8edf69cf40fc | 152 | static const byte HC = 0x40; // subcurrent |
eisd | 0:8edf69cf40fc | 153 | }; |
eisd | 0:8edf69cf40fc | 154 | |
eisd | 0:8edf69cf40fc | 155 | struct EFLAG |
eisd | 0:8edf69cf40fc | 156 | { |
eisd | 0:8edf69cf40fc | 157 | static const byte ADDR = 0x13; |
eisd | 0:8edf69cf40fc | 158 | }; |
eisd | 0:8edf69cf40fc | 159 | }; |
eisd | 0:8edf69cf40fc | 160 | |
eisd | 0:8edf69cf40fc | 161 | struct ERROR |
eisd | 0:8edf69cf40fc | 162 | { |
eisd | 0:8edf69cf40fc | 163 | static const uint8_t EINVAL = 2; |
eisd | 0:8edf69cf40fc | 164 | }; |
eisd | 0:8edf69cf40fc | 165 | |
eisd | 0:8edf69cf40fc | 166 | TLC59108(const PinName sda, const PinName scl, const byte selectable_address = 0): |
eisd | 0:8edf69cf40fc | 167 | addr(I2C_ADDR::BASE | selectable_address), |
eisd | 0:8edf69cf40fc | 168 | i2c(sda, scl) { |
eisd | 0:8edf69cf40fc | 169 | setRegister(REGISTER::MODE1::ADDR, REGISTER::MODE1::ALLCALL); |
eisd | 0:8edf69cf40fc | 170 | } |
eisd | 0:8edf69cf40fc | 171 | |
eisd | 0:8edf69cf40fc | 172 | uint8_t setLedOutputMode(const uint8_t outputMode) |
eisd | 0:8edf69cf40fc | 173 | { |
eisd | 0:8edf69cf40fc | 174 | if(outputMode & 0xfc) |
eisd | 0:8edf69cf40fc | 175 | return ERROR::EINVAL; |
eisd | 0:8edf69cf40fc | 176 | |
eisd | 0:8edf69cf40fc | 177 | byte regValue = (outputMode << 6) | (outputMode << 4) | (outputMode << 2) | outputMode; |
eisd | 0:8edf69cf40fc | 178 | |
eisd | 0:8edf69cf40fc | 179 | uint8_t retVal = setRegister(REGISTER::LEDOUT0::ADDR, regValue); |
eisd | 0:8edf69cf40fc | 180 | retVal &= setRegister(REGISTER::LEDOUT1::ADDR, regValue); |
eisd | 0:8edf69cf40fc | 181 | return retVal; |
eisd | 0:8edf69cf40fc | 182 | } |
eisd | 0:8edf69cf40fc | 183 | |
eisd | 0:8edf69cf40fc | 184 | uint8_t setBrightness(const uint8_t pwmChannel, const uint8_t dutyCycle) |
eisd | 0:8edf69cf40fc | 185 | { |
eisd | 0:8edf69cf40fc | 186 | if(pwmChannel > 7) |
eisd | 0:8edf69cf40fc | 187 | return ERROR::EINVAL; |
eisd | 0:8edf69cf40fc | 188 | |
eisd | 0:8edf69cf40fc | 189 | return setRegister(REGISTER::PWM0::ADDR + pwmChannel, dutyCycle); |
eisd | 0:8edf69cf40fc | 190 | } |
eisd | 0:8edf69cf40fc | 191 | |
eisd | 0:8edf69cf40fc | 192 | uint8_t setBrightness(const uint8_t dutyCycle) |
eisd | 0:8edf69cf40fc | 193 | { |
eisd | 0:8edf69cf40fc | 194 | uint8_t status = 0; |
eisd | 0:8edf69cf40fc | 195 | i2c.start(); |
eisd | 0:8edf69cf40fc | 196 | status &= i2c.write(addr); |
eisd | 0:8edf69cf40fc | 197 | status &= i2c.write(REGISTER::PWM0::ADDR | AUTO_INCREMENT::IND); |
eisd | 0:8edf69cf40fc | 198 | for (uint8_t i = 0; i < NUM_CHANNELS; i++) |
eisd | 0:8edf69cf40fc | 199 | status &= i2c.write(dutyCycle); |
eisd | 0:8edf69cf40fc | 200 | i2c.stop(); |
eisd | 0:8edf69cf40fc | 201 | return status; |
eisd | 0:8edf69cf40fc | 202 | } |
eisd | 0:8edf69cf40fc | 203 | |
eisd | 0:8edf69cf40fc | 204 | uint8_t setBrightness(const byte dutyCycles[]) |
eisd | 0:8edf69cf40fc | 205 | { |
eisd | 0:8edf69cf40fc | 206 | return setRegisters(REGISTER::PWM0::ADDR, dutyCycles, NUM_CHANNELS); |
eisd | 0:8edf69cf40fc | 207 | } |
eisd | 0:8edf69cf40fc | 208 | |
eisd | 0:8edf69cf40fc | 209 | uint8_t setGroupBrightness(const uint8_t dutyCycle) |
eisd | 0:8edf69cf40fc | 210 | { |
eisd | 0:8edf69cf40fc | 211 | return setRegister(REGISTER::GRPPWM::ADDR, dutyCycle); |
eisd | 0:8edf69cf40fc | 212 | } |
eisd | 0:8edf69cf40fc | 213 | |
eisd | 0:8edf69cf40fc | 214 | int setRegister(const byte reg, const byte value) { |
eisd | 0:8edf69cf40fc | 215 | char cmd[2] = { reg, value }; |
eisd | 0:8edf69cf40fc | 216 | return i2c.write(addr, cmd, 2); |
eisd | 0:8edf69cf40fc | 217 | } |
eisd | 0:8edf69cf40fc | 218 | |
eisd | 0:8edf69cf40fc | 219 | int setRegisters(const byte reg, const byte values[], const uint8_t length) { |
eisd | 0:8edf69cf40fc | 220 | uint8_t status = 0; |
eisd | 0:8edf69cf40fc | 221 | i2c.start(); |
eisd | 0:8edf69cf40fc | 222 | status &= i2c.write(addr); |
eisd | 0:8edf69cf40fc | 223 | status &= i2c.write(reg | AUTO_INCREMENT::ALL); |
eisd | 0:8edf69cf40fc | 224 | for (uint8_t i = 0; i < length; i++) |
eisd | 0:8edf69cf40fc | 225 | status &= i2c.write(values[i]); |
eisd | 0:8edf69cf40fc | 226 | i2c.stop(); |
eisd | 0:8edf69cf40fc | 227 | return status; |
eisd | 0:8edf69cf40fc | 228 | } |
eisd | 0:8edf69cf40fc | 229 | |
eisd | 0:8edf69cf40fc | 230 | protected: |
eisd | 0:8edf69cf40fc | 231 | const static uint8_t NUM_CHANNELS = 8; |
eisd | 0:8edf69cf40fc | 232 | byte addr; |
eisd | 0:8edf69cf40fc | 233 | I2C i2c; |
eisd | 0:8edf69cf40fc | 234 | }; |
eisd | 0:8edf69cf40fc | 235 | |
eisd | 0:8edf69cf40fc | 236 | #endif |