SX1509 16 Output I/O Expander / LED Driver Library
SX1509.cpp
- Committer:
- jjones646
- Date:
- 2014-10-21
- Revision:
- 1:9ab20d13c44e
- Parent:
- 0:893f387bda9f
- Child:
- 2:330355f546b0
File content as of revision 1:9ab20d13c44e:
#include "SX1509.h" #include "mbed.h" // Constructors SX1509::SX1509() { error("You must supply 2 pin names. (Serial Data Pin [sda], Serial Clock Pin [scl])"); } SX1509::SX1509(PinName sda) { SX1509(); } SX1509::SX1509(PinName sda, PinName scl, PinName intN, PinName resetN) { init(sda, scl, intN, resetN); } // initilization method here is called from the constructors void SX1509::init(PinName sda, PinName scl, PinName intN, PinName resetN) { // if an interrupt pin was passed in, assign it if (intN != NC) { _intN = new DigitalIn(intN); hasInt = true; } else { hasInt = false; } // if a reset pin was passed in, assign it if (resetN != NC) { _resetN = new DigitalOut(resetN); *_resetN = 1; // bring high to enable device hasReset = true; } else { hasReset = false; } // setup the I2C data bus lines _i2c = new I2C(sda, scl); _i2c->frequency(SX1509_FREQUENCY); // default to outputs directionA(OUT); directionB(OUT); // initialize all the outputs by setting them all to zero setA(0x00); setB(0x00); dirA = OUT; dirB = OUT; } // generic method for sending data among the I2C bus int SX1509::transfer_data(char const reg_addr, char const reg_val, Transfer_t transfer) { int value = 0; _i2c->start(); if(_i2c->write(SX1509_ADDRESS_1<<1)) { if (_i2c->write(reg_addr)) { switch(transfer) { case WRITE: value = _i2c->write(reg_val); break; case READ: _i2c->start(); if(_i2c->write((SX1509_ADDRESS_1<<1)|READ)) { value = _i2c->read(0); } break; default: break; } } else { std::printf("Slave did not acknowledge the register's address.\r\n"); } } else { std::printf("Nothing worked...\r\n"); } _i2c->stop(); return value; } // generic method for writing data to one of the chip's registers void SX1509::write_register(char const reg_addr, char const reg_val) { transfer_data(reg_addr, reg_val, WRITE); } // generic method for reading a single char from one of the chip's registers int SX1509::read_register(char const reg_addr) { return transfer_data(reg_addr, NULL, READ); } // generic method for setting the direction of a side's outputs void SX1509::direction(Direction_t dir, Side_t side) { char set_byte = 0; char address = 0; // determine what bytes to write based on the passed inputs switch (dir) { case OUT: set_byte = 0x00; break; case IN: set_byte = 0xFF; break; default: break; } // determine what side's registers to write to switch (side) { case A: address = REGDIRA; dirA = dir; break; case B: address = REGDIRB; dirB = dir; break; default: break; } write_register(address, set_byte); } // Set the direction (IN or OUT) for side A void SX1509::directionA(Direction_t dir) { direction(dir,A); } // Set the direction (IN or OUT) for side B void SX1509::directionB(Direction_t dir) { direction(dir,B); } // Set a hex value to the I/O pins for side A void SX1509::setA(char const val) { transfer_data(REGDATAA, val, WRITE); } // Set a hex value to the I/O pins for side B void SX1509::setB(char const val) { transfer_data(REGDATAB, val, WRITE); } void SX1509::clearAll(Side_t side) { switch(side) { case A: setA(0x00); break; case B: setB(0x00); break; default: break; } } // Read a hex value from SideA int SX1509::readA() { int a = read_register(REGDATAA); return a; } // Read a hex value from SideB int SX1509::readB() { return read_register(REGDATAB); } bool SX1509::get(int const i) { uint8_t temp; if (i>=0 && i<8) { temp = readA(); temp &= (1<<i); } else if (i>=8 && i<16) { temp = readB(); temp &= (1<<(i-8)); } return (temp > 0); } void SX1509::set(int const i) { uint8_t temp; if (i>=0 && i<8) { temp = readA(); temp |= (1<<i); setA(temp); } else if (i>=8 && i<16) { temp = readB(); temp |= (1<<(i-8)); setB(temp); } } void SX1509::clear(int const i) { uint8_t temp; if (i>=0 && i<8) { temp = readA(); temp &= ~(1<<i); setA(temp); } else if (i>=8 && i<16) { temp = readB(); temp &= ~(1<<(i-8)); setB(temp); } } void SX1509::toggle(int const i) { uint8_t temp; if (i>=0 && i<8) { temp = readA(); temp ^= 1<<i; setA(temp); } else if (i>=8 && i<16) { temp = readB(); temp ^= 1<<(i-8); setB(temp); } } Direction_t SX1509::getDirection(Side_t side) { Direction_t dir; switch(side) { case A: dir = dirA; case B: dir = dirB; default: break; } return dir; } void SX1509::setBuffer(Side_t side, State_t state) { uint8_t invert = ~state; switch (side) { case A: write_register(REGINPUTDISABLEA, invert); break; case B: write_register(REGINPUTDISABLEB, invert); break; default: break; } } void SX1509::setPull(Side_t side, Pull_t pull, State_t state) { switch (side) { case A: if (pull == PULLUP) { write_register(REGPULLDOWNA, ~state); write_register(REGPULLUPA, state); } else if (pull == PULLDOWN) { write_register(REGPULLUPA, ~state); write_register(REGPULLDOWNA, state); } break; case B: if (pull == PULLUP) { write_register(REGPULLDOWNB, ~state); write_register(REGPULLUPB, state); } else if (pull == PULLDOWN) { write_register(REGPULLUPB, ~state); write_register(REGPULLDOWNB, state); } break; default: break; } } void SX1509::setOpenDrain(Side_t side, State_t state) { switch (side) { case A: write_register(REGOPENDRAINA, state); break; case B: write_register(REGOPENDRAINB, state); break; default: break; } } void SX1509::setClock(State_t state) { uint8_t new_state = read_register(REGCLOCK); if (state == ON) { new_state |= 0x40; } else if (state == OFF) { new_state &= ~(0x60); } write_register(REGCLOCK, new_state); } void SX1509::setFreq(Freq_t freq) { uint8_t new_state = read_register(REGMISC); new_state |= ((1<<4)<<freq); write_register(REGMISC, new_state); } void SX1509::setLedDrive(Side_t side, State_t state) { switch (side) { case A: write_register(REGLEDDRIVERENABLEA, state); break; case B: write_register(REGLEDDRIVERENABLEB, state); break; default: break; } } void SX1509::enableLED(Side_t side) { setBuffer(side, OFF); setPull(side, PULLUP, OFF); setOpenDrain(side, ON); setClock(ON); setFreq(MED); setLedDrive(side, ON); clearAll(side); } void SX1509::setupLED(LED_t led) { int i = 0; write_register(led + i++, 0x00); // T_on write_register(led + i++, 0x0A); // Intensity write_register(led + i++, (0x01<<3)|(0x00)); // T_off write_register(led + i++, 0x01); // T_rise write_register(led + i, 0x01); // T_fall }