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