SX1509 16 Output I/O Expander / LED Driver Library

Dependents:   SX1509_HelloWorld

Revision:
0:893f387bda9f
Child:
1:9ab20d13c44e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SX1509.cpp	Tue Oct 21 04:07:43 2014 +0000
@@ -0,0 +1,385 @@
+
+#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++, 0x03); // T_on
+    write_register(led + i++, 0xFF); // Intensity
+    write_register(led + i++, (0x01<<3)|(0x00)); // T_off
+    write_register(led + i++, 0x01); // T_rise
+    write_register(led + i, 0x01); // T_fall
+    */
+    
+    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
+}
\ No newline at end of file