SX1509 16 Output I/O Expander / LED Driver Library

Dependents:   SX1509_HelloWorld

Committer:
jjones646
Date:
Tue Oct 21 14:01:05 2014 +0000
Revision:
2:330355f546b0
Parent:
1:9ab20d13c44e
Adding documentation

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jjones646 0:893f387bda9f 1
jjones646 0:893f387bda9f 2 #include "SX1509.h"
jjones646 0:893f387bda9f 3 #include "mbed.h"
jjones646 0:893f387bda9f 4
jjones646 0:893f387bda9f 5
jjones646 0:893f387bda9f 6 // Constructors
jjones646 0:893f387bda9f 7 SX1509::SX1509()
jjones646 0:893f387bda9f 8 {
jjones646 0:893f387bda9f 9 error("You must supply 2 pin names. (Serial Data Pin [sda], Serial Clock Pin [scl])");
jjones646 0:893f387bda9f 10 }
jjones646 0:893f387bda9f 11
jjones646 0:893f387bda9f 12 SX1509::SX1509(PinName sda)
jjones646 0:893f387bda9f 13 {
jjones646 0:893f387bda9f 14 SX1509();
jjones646 0:893f387bda9f 15 }
jjones646 0:893f387bda9f 16
jjones646 0:893f387bda9f 17 SX1509::SX1509(PinName sda, PinName scl, PinName intN, PinName resetN)
jjones646 0:893f387bda9f 18 {
jjones646 0:893f387bda9f 19 init(sda, scl, intN, resetN);
jjones646 0:893f387bda9f 20 }
jjones646 0:893f387bda9f 21
jjones646 0:893f387bda9f 22 // initilization method here is called from the constructors
jjones646 0:893f387bda9f 23 void SX1509::init(PinName sda, PinName scl, PinName intN, PinName resetN)
jjones646 0:893f387bda9f 24 {
jjones646 0:893f387bda9f 25
jjones646 0:893f387bda9f 26 // if an interrupt pin was passed in, assign it
jjones646 0:893f387bda9f 27 if (intN != NC) {
jjones646 0:893f387bda9f 28 _intN = new DigitalIn(intN);
jjones646 0:893f387bda9f 29 hasInt = true;
jjones646 0:893f387bda9f 30 } else {
jjones646 0:893f387bda9f 31 hasInt = false;
jjones646 0:893f387bda9f 32 }
jjones646 0:893f387bda9f 33
jjones646 0:893f387bda9f 34 // if a reset pin was passed in, assign it
jjones646 0:893f387bda9f 35 if (resetN != NC) {
jjones646 0:893f387bda9f 36 _resetN = new DigitalOut(resetN);
jjones646 0:893f387bda9f 37 *_resetN = 1; // bring high to enable device
jjones646 0:893f387bda9f 38 hasReset = true;
jjones646 0:893f387bda9f 39 } else {
jjones646 0:893f387bda9f 40 hasReset = false;
jjones646 0:893f387bda9f 41 }
jjones646 0:893f387bda9f 42
jjones646 0:893f387bda9f 43 // setup the I2C data bus lines
jjones646 0:893f387bda9f 44 _i2c = new I2C(sda, scl);
jjones646 0:893f387bda9f 45 _i2c->frequency(SX1509_FREQUENCY);
jjones646 0:893f387bda9f 46
jjones646 0:893f387bda9f 47 // default to outputs
jjones646 0:893f387bda9f 48 directionA(OUT);
jjones646 0:893f387bda9f 49 directionB(OUT);
jjones646 0:893f387bda9f 50
jjones646 0:893f387bda9f 51 // initialize all the outputs by setting them all to zero
jjones646 0:893f387bda9f 52 setA(0x00);
jjones646 0:893f387bda9f 53 setB(0x00);
jjones646 0:893f387bda9f 54
jjones646 0:893f387bda9f 55 dirA = OUT;
jjones646 0:893f387bda9f 56 dirB = OUT;
jjones646 0:893f387bda9f 57 }
jjones646 0:893f387bda9f 58
jjones646 0:893f387bda9f 59 // generic method for sending data among the I2C bus
jjones646 0:893f387bda9f 60 int SX1509::transfer_data(char const reg_addr, char const reg_val, Transfer_t transfer)
jjones646 0:893f387bda9f 61 {
jjones646 0:893f387bda9f 62 int value = 0;
jjones646 0:893f387bda9f 63
jjones646 0:893f387bda9f 64 _i2c->start();
jjones646 0:893f387bda9f 65 if(_i2c->write(SX1509_ADDRESS_1<<1)) {
jjones646 0:893f387bda9f 66 if (_i2c->write(reg_addr)) {
jjones646 0:893f387bda9f 67 switch(transfer) {
jjones646 0:893f387bda9f 68 case WRITE:
jjones646 0:893f387bda9f 69 value = _i2c->write(reg_val);
jjones646 0:893f387bda9f 70 break;
jjones646 0:893f387bda9f 71 case READ:
jjones646 0:893f387bda9f 72 _i2c->start();
jjones646 0:893f387bda9f 73 if(_i2c->write((SX1509_ADDRESS_1<<1)|READ)) {
jjones646 0:893f387bda9f 74 value = _i2c->read(0);
jjones646 0:893f387bda9f 75 }
jjones646 0:893f387bda9f 76 break;
jjones646 0:893f387bda9f 77 default:
jjones646 0:893f387bda9f 78 break;
jjones646 0:893f387bda9f 79 }
jjones646 0:893f387bda9f 80
jjones646 0:893f387bda9f 81 } else {
jjones646 0:893f387bda9f 82 std::printf("Slave did not acknowledge the register's address.\r\n");
jjones646 0:893f387bda9f 83 }
jjones646 0:893f387bda9f 84 } else {
jjones646 0:893f387bda9f 85 std::printf("Nothing worked...\r\n");
jjones646 0:893f387bda9f 86 }
jjones646 0:893f387bda9f 87 _i2c->stop();
jjones646 0:893f387bda9f 88
jjones646 0:893f387bda9f 89 return value;
jjones646 0:893f387bda9f 90 }
jjones646 0:893f387bda9f 91
jjones646 0:893f387bda9f 92 // generic method for writing data to one of the chip's registers
jjones646 0:893f387bda9f 93 void SX1509::write_register(char const reg_addr, char const reg_val)
jjones646 0:893f387bda9f 94 {
jjones646 0:893f387bda9f 95 transfer_data(reg_addr, reg_val, WRITE);
jjones646 0:893f387bda9f 96 }
jjones646 0:893f387bda9f 97
jjones646 0:893f387bda9f 98 // generic method for reading a single char from one of the chip's registers
jjones646 0:893f387bda9f 99 int SX1509::read_register(char const reg_addr)
jjones646 0:893f387bda9f 100 {
jjones646 0:893f387bda9f 101 return transfer_data(reg_addr, NULL, READ);
jjones646 0:893f387bda9f 102 }
jjones646 0:893f387bda9f 103
jjones646 0:893f387bda9f 104 // generic method for setting the direction of a side's outputs
jjones646 0:893f387bda9f 105 void SX1509::direction(Direction_t dir, Side_t side)
jjones646 0:893f387bda9f 106 {
jjones646 0:893f387bda9f 107 char set_byte = 0;
jjones646 0:893f387bda9f 108 char address = 0;
jjones646 0:893f387bda9f 109
jjones646 0:893f387bda9f 110 // determine what bytes to write based on the passed inputs
jjones646 0:893f387bda9f 111 switch (dir) {
jjones646 0:893f387bda9f 112 case OUT:
jjones646 0:893f387bda9f 113 set_byte = 0x00;
jjones646 0:893f387bda9f 114 break;
jjones646 0:893f387bda9f 115 case IN:
jjones646 0:893f387bda9f 116 set_byte = 0xFF;
jjones646 0:893f387bda9f 117 break;
jjones646 0:893f387bda9f 118 default:
jjones646 0:893f387bda9f 119 break;
jjones646 0:893f387bda9f 120 }
jjones646 0:893f387bda9f 121
jjones646 0:893f387bda9f 122 // determine what side's registers to write to
jjones646 0:893f387bda9f 123 switch (side) {
jjones646 0:893f387bda9f 124 case A:
jjones646 0:893f387bda9f 125 address = REGDIRA;
jjones646 0:893f387bda9f 126 dirA = dir;
jjones646 0:893f387bda9f 127 break;
jjones646 0:893f387bda9f 128 case B:
jjones646 0:893f387bda9f 129 address = REGDIRB;
jjones646 0:893f387bda9f 130 dirB = dir;
jjones646 0:893f387bda9f 131 break;
jjones646 0:893f387bda9f 132 default:
jjones646 0:893f387bda9f 133 break;
jjones646 0:893f387bda9f 134 }
jjones646 0:893f387bda9f 135
jjones646 0:893f387bda9f 136 write_register(address, set_byte);
jjones646 0:893f387bda9f 137 }
jjones646 0:893f387bda9f 138
jjones646 0:893f387bda9f 139
jjones646 0:893f387bda9f 140 // Set the direction (IN or OUT) for side A
jjones646 0:893f387bda9f 141 void SX1509::directionA(Direction_t dir)
jjones646 0:893f387bda9f 142 {
jjones646 0:893f387bda9f 143 direction(dir,A);
jjones646 0:893f387bda9f 144 }
jjones646 0:893f387bda9f 145
jjones646 0:893f387bda9f 146 // Set the direction (IN or OUT) for side B
jjones646 0:893f387bda9f 147 void SX1509::directionB(Direction_t dir)
jjones646 0:893f387bda9f 148 {
jjones646 0:893f387bda9f 149 direction(dir,B);
jjones646 0:893f387bda9f 150 }
jjones646 0:893f387bda9f 151
jjones646 0:893f387bda9f 152 // Set a hex value to the I/O pins for side A
jjones646 0:893f387bda9f 153 void SX1509::setA(char const val)
jjones646 0:893f387bda9f 154 {
jjones646 0:893f387bda9f 155 transfer_data(REGDATAA, val, WRITE);
jjones646 0:893f387bda9f 156 }
jjones646 0:893f387bda9f 157
jjones646 0:893f387bda9f 158 // Set a hex value to the I/O pins for side B
jjones646 0:893f387bda9f 159 void SX1509::setB(char const val)
jjones646 0:893f387bda9f 160 {
jjones646 0:893f387bda9f 161 transfer_data(REGDATAB, val, WRITE);
jjones646 0:893f387bda9f 162 }
jjones646 0:893f387bda9f 163
jjones646 0:893f387bda9f 164 void SX1509::clearAll(Side_t side)
jjones646 0:893f387bda9f 165 {
jjones646 0:893f387bda9f 166 switch(side) {
jjones646 0:893f387bda9f 167 case A:
jjones646 0:893f387bda9f 168 setA(0x00);
jjones646 0:893f387bda9f 169 break;
jjones646 0:893f387bda9f 170 case B:
jjones646 0:893f387bda9f 171 setB(0x00);
jjones646 0:893f387bda9f 172 break;
jjones646 0:893f387bda9f 173 default:
jjones646 0:893f387bda9f 174 break;
jjones646 0:893f387bda9f 175 }
jjones646 0:893f387bda9f 176 }
jjones646 0:893f387bda9f 177
jjones646 0:893f387bda9f 178
jjones646 0:893f387bda9f 179 // Read a hex value from SideA
jjones646 0:893f387bda9f 180 int SX1509::readA()
jjones646 0:893f387bda9f 181 {
jjones646 0:893f387bda9f 182 int a = read_register(REGDATAA);
jjones646 0:893f387bda9f 183 return a;
jjones646 0:893f387bda9f 184 }
jjones646 0:893f387bda9f 185
jjones646 0:893f387bda9f 186 // Read a hex value from SideB
jjones646 0:893f387bda9f 187 int SX1509::readB()
jjones646 0:893f387bda9f 188 {
jjones646 0:893f387bda9f 189 return read_register(REGDATAB);
jjones646 0:893f387bda9f 190 }
jjones646 0:893f387bda9f 191
jjones646 0:893f387bda9f 192 bool SX1509::get(int const i)
jjones646 0:893f387bda9f 193 {
jjones646 0:893f387bda9f 194 uint8_t temp;
jjones646 0:893f387bda9f 195
jjones646 0:893f387bda9f 196 if (i>=0 && i<8) {
jjones646 0:893f387bda9f 197 temp = readA();
jjones646 0:893f387bda9f 198 temp &= (1<<i);
jjones646 0:893f387bda9f 199 } else if (i>=8 && i<16) {
jjones646 0:893f387bda9f 200 temp = readB();
jjones646 0:893f387bda9f 201 temp &= (1<<(i-8));
jjones646 0:893f387bda9f 202 }
jjones646 0:893f387bda9f 203
jjones646 0:893f387bda9f 204 return (temp > 0);
jjones646 0:893f387bda9f 205 }
jjones646 0:893f387bda9f 206
jjones646 0:893f387bda9f 207 void SX1509::set(int const i)
jjones646 0:893f387bda9f 208 {
jjones646 0:893f387bda9f 209 uint8_t temp;
jjones646 0:893f387bda9f 210
jjones646 0:893f387bda9f 211 if (i>=0 && i<8) {
jjones646 0:893f387bda9f 212 temp = readA();
jjones646 0:893f387bda9f 213 temp |= (1<<i);
jjones646 0:893f387bda9f 214 setA(temp);
jjones646 0:893f387bda9f 215 } else if (i>=8 && i<16) {
jjones646 0:893f387bda9f 216 temp = readB();
jjones646 0:893f387bda9f 217 temp |= (1<<(i-8));
jjones646 0:893f387bda9f 218 setB(temp);
jjones646 0:893f387bda9f 219 }
jjones646 0:893f387bda9f 220 }
jjones646 0:893f387bda9f 221
jjones646 0:893f387bda9f 222 void SX1509::clear(int const i)
jjones646 0:893f387bda9f 223 {
jjones646 0:893f387bda9f 224 uint8_t temp;
jjones646 0:893f387bda9f 225
jjones646 0:893f387bda9f 226 if (i>=0 && i<8) {
jjones646 0:893f387bda9f 227 temp = readA();
jjones646 0:893f387bda9f 228 temp &= ~(1<<i);
jjones646 0:893f387bda9f 229 setA(temp);
jjones646 0:893f387bda9f 230 } else if (i>=8 && i<16) {
jjones646 0:893f387bda9f 231 temp = readB();
jjones646 0:893f387bda9f 232 temp &= ~(1<<(i-8));
jjones646 0:893f387bda9f 233 setB(temp);
jjones646 0:893f387bda9f 234 }
jjones646 0:893f387bda9f 235 }
jjones646 0:893f387bda9f 236
jjones646 0:893f387bda9f 237 void SX1509::toggle(int const i)
jjones646 0:893f387bda9f 238 {
jjones646 0:893f387bda9f 239 uint8_t temp;
jjones646 0:893f387bda9f 240
jjones646 0:893f387bda9f 241 if (i>=0 && i<8) {
jjones646 0:893f387bda9f 242 temp = readA();
jjones646 0:893f387bda9f 243 temp ^= 1<<i;
jjones646 0:893f387bda9f 244 setA(temp);
jjones646 0:893f387bda9f 245 } else if (i>=8 && i<16) {
jjones646 0:893f387bda9f 246 temp = readB();
jjones646 0:893f387bda9f 247 temp ^= 1<<(i-8);
jjones646 0:893f387bda9f 248 setB(temp);
jjones646 0:893f387bda9f 249 }
jjones646 0:893f387bda9f 250 }
jjones646 0:893f387bda9f 251
jjones646 0:893f387bda9f 252 Direction_t SX1509::getDirection(Side_t side)
jjones646 0:893f387bda9f 253 {
jjones646 0:893f387bda9f 254 Direction_t dir;
jjones646 0:893f387bda9f 255
jjones646 0:893f387bda9f 256 switch(side) {
jjones646 0:893f387bda9f 257 case A:
jjones646 0:893f387bda9f 258 dir = dirA;
jjones646 0:893f387bda9f 259 case B:
jjones646 0:893f387bda9f 260 dir = dirB;
jjones646 0:893f387bda9f 261 default:
jjones646 0:893f387bda9f 262 break;
jjones646 0:893f387bda9f 263 }
jjones646 0:893f387bda9f 264 return dir;
jjones646 0:893f387bda9f 265 }
jjones646 0:893f387bda9f 266
jjones646 0:893f387bda9f 267 void SX1509::setBuffer(Side_t side, State_t state)
jjones646 0:893f387bda9f 268 {
jjones646 0:893f387bda9f 269 uint8_t invert = ~state;
jjones646 0:893f387bda9f 270
jjones646 0:893f387bda9f 271 switch (side) {
jjones646 0:893f387bda9f 272 case A:
jjones646 0:893f387bda9f 273 write_register(REGINPUTDISABLEA, invert);
jjones646 0:893f387bda9f 274 break;
jjones646 0:893f387bda9f 275 case B:
jjones646 0:893f387bda9f 276 write_register(REGINPUTDISABLEB, invert);
jjones646 0:893f387bda9f 277 break;
jjones646 0:893f387bda9f 278 default:
jjones646 0:893f387bda9f 279 break;
jjones646 0:893f387bda9f 280 }
jjones646 0:893f387bda9f 281 }
jjones646 0:893f387bda9f 282
jjones646 0:893f387bda9f 283 void SX1509::setPull(Side_t side, Pull_t pull, State_t state)
jjones646 0:893f387bda9f 284 {
jjones646 0:893f387bda9f 285 switch (side) {
jjones646 0:893f387bda9f 286 case A:
jjones646 0:893f387bda9f 287 if (pull == PULLUP) {
jjones646 0:893f387bda9f 288 write_register(REGPULLDOWNA, ~state);
jjones646 0:893f387bda9f 289 write_register(REGPULLUPA, state);
jjones646 0:893f387bda9f 290 } else if (pull == PULLDOWN) {
jjones646 0:893f387bda9f 291 write_register(REGPULLUPA, ~state);
jjones646 0:893f387bda9f 292 write_register(REGPULLDOWNA, state);
jjones646 0:893f387bda9f 293 }
jjones646 0:893f387bda9f 294 break;
jjones646 0:893f387bda9f 295
jjones646 0:893f387bda9f 296 case B:
jjones646 0:893f387bda9f 297 if (pull == PULLUP) {
jjones646 0:893f387bda9f 298 write_register(REGPULLDOWNB, ~state);
jjones646 0:893f387bda9f 299 write_register(REGPULLUPB, state);
jjones646 0:893f387bda9f 300 } else if (pull == PULLDOWN) {
jjones646 0:893f387bda9f 301 write_register(REGPULLUPB, ~state);
jjones646 0:893f387bda9f 302 write_register(REGPULLDOWNB, state);
jjones646 0:893f387bda9f 303 }
jjones646 0:893f387bda9f 304 break;
jjones646 0:893f387bda9f 305 default:
jjones646 0:893f387bda9f 306 break;
jjones646 0:893f387bda9f 307 }
jjones646 0:893f387bda9f 308 }
jjones646 0:893f387bda9f 309
jjones646 0:893f387bda9f 310 void SX1509::setOpenDrain(Side_t side, State_t state)
jjones646 0:893f387bda9f 311 {
jjones646 0:893f387bda9f 312 switch (side) {
jjones646 0:893f387bda9f 313 case A:
jjones646 0:893f387bda9f 314 write_register(REGOPENDRAINA, state);
jjones646 0:893f387bda9f 315 break;
jjones646 0:893f387bda9f 316 case B:
jjones646 0:893f387bda9f 317 write_register(REGOPENDRAINB, state);
jjones646 0:893f387bda9f 318 break;
jjones646 0:893f387bda9f 319 default:
jjones646 0:893f387bda9f 320 break;
jjones646 0:893f387bda9f 321 }
jjones646 0:893f387bda9f 322 }
jjones646 0:893f387bda9f 323
jjones646 0:893f387bda9f 324 void SX1509::setClock(State_t state)
jjones646 0:893f387bda9f 325 {
jjones646 0:893f387bda9f 326 uint8_t new_state = read_register(REGCLOCK);
jjones646 0:893f387bda9f 327
jjones646 0:893f387bda9f 328 if (state == ON) {
jjones646 0:893f387bda9f 329 new_state |= 0x40;
jjones646 0:893f387bda9f 330 } else if (state == OFF) {
jjones646 0:893f387bda9f 331 new_state &= ~(0x60);
jjones646 0:893f387bda9f 332 }
jjones646 0:893f387bda9f 333
jjones646 0:893f387bda9f 334 write_register(REGCLOCK, new_state);
jjones646 0:893f387bda9f 335 }
jjones646 0:893f387bda9f 336
jjones646 0:893f387bda9f 337 void SX1509::setFreq(Freq_t freq)
jjones646 0:893f387bda9f 338 {
jjones646 0:893f387bda9f 339 uint8_t new_state = read_register(REGMISC);
jjones646 0:893f387bda9f 340 new_state |= ((1<<4)<<freq);
jjones646 0:893f387bda9f 341 write_register(REGMISC, new_state);
jjones646 0:893f387bda9f 342 }
jjones646 0:893f387bda9f 343
jjones646 0:893f387bda9f 344 void SX1509::setLedDrive(Side_t side, State_t state)
jjones646 0:893f387bda9f 345 {
jjones646 0:893f387bda9f 346 switch (side) {
jjones646 0:893f387bda9f 347 case A:
jjones646 0:893f387bda9f 348 write_register(REGLEDDRIVERENABLEA, state);
jjones646 0:893f387bda9f 349 break;
jjones646 0:893f387bda9f 350 case B:
jjones646 0:893f387bda9f 351 write_register(REGLEDDRIVERENABLEB, state);
jjones646 0:893f387bda9f 352 break;
jjones646 0:893f387bda9f 353 default:
jjones646 0:893f387bda9f 354 break;
jjones646 0:893f387bda9f 355 }
jjones646 0:893f387bda9f 356 }
jjones646 0:893f387bda9f 357
jjones646 0:893f387bda9f 358 void SX1509::enableLED(Side_t side)
jjones646 0:893f387bda9f 359 {
jjones646 0:893f387bda9f 360 setBuffer(side, OFF);
jjones646 0:893f387bda9f 361 setPull(side, PULLUP, OFF);
jjones646 0:893f387bda9f 362 setOpenDrain(side, ON);
jjones646 0:893f387bda9f 363 setClock(ON);
jjones646 0:893f387bda9f 364 setFreq(MED);
jjones646 0:893f387bda9f 365 setLedDrive(side, ON);
jjones646 0:893f387bda9f 366 clearAll(side);
jjones646 0:893f387bda9f 367 }
jjones646 0:893f387bda9f 368
jjones646 0:893f387bda9f 369 void SX1509::setupLED(LED_t led)
jjones646 0:893f387bda9f 370 {
jjones646 0:893f387bda9f 371 int i = 0;
jjones646 2:330355f546b0 372 write_register(led + i++, 0x01); // T_on
jjones646 2:330355f546b0 373 write_register(led + i++, 0xFF); // Intensity
jjones646 2:330355f546b0 374 write_register(led + i++, (0x01<<3)|(0x02)); // T_off
jjones646 2:330355f546b0 375 write_register(led + i++, 0x04); // T_rise
jjones646 2:330355f546b0 376 write_register(led + i, 0x04); // T_fall
jjones646 0:893f387bda9f 377 }