Driver for the IO Expander/LED Driver

SX1509.cpp

Committer:
mwilkens241
Date:
2017-04-26
Revision:
2:0f4b9539feca
Parent:
1:0176ec93c3fe

File content as of revision 2:0f4b9539feca:

#include "SX1509.h"

const uint8_t onTReg[16] = {REGTON0, REGTON1, REGTON2, REGTON3, REGTON4, REGTON5, REGTON6, REGTON7, REGTON8, REGTON9, REGTON10, REGTON11, REGTON12, REGTON13, REGTON14, REGTON15};
            
const uint8_t onIReg[16] = {REGION0, REGION1, REGION2, REGION3, REGION4, REGION5, REGION6, REGION7, REGION8, REGION9, REGION10, REGION11, REGION12, REGION13, REGION14, REGION15};
            
const uint8_t offTReg[16] = {REGOFF0, REGOFF1, REGOFF2, REGOFF3, REGOFF4, REGOFF5, REGOFF6, REGOFF7, REGOFF8, REGOFF9, REGOFF10, REGOFF11, REGOFF12, REGOFF13, REGOFF14, REGOFF15};
          
const uint8_t riseTReg[16] = {0,0,0,0, REGTRISE4, REGTRISE5, REGTRISE6, REGTRISE7, 0,0,0,0, REGTRISE12, REGTRISE13, REGTRISE14, REGTRISE15};
        
const uint8_t fallTReg[16] = {0,0,0,0, REGTFALL4, REGTFALL5, REGTFALL6, REGTFALL7, 0,0,0,0, REGTFALL12, REGTFALL13, REGTFALL14, REGTFALL15};


SX1509::SX1509(PinName sda, PinName scl) : i2c(sda,scl) {}

void SX1509::i2cWrite8(char reg, char data){
    char packet[2] = {reg ,data & 0xFF}; 
    i2c.write(SX1509_ADDR,packet,2,false);
    wait(0.01);
}

uint8_t SX1509::i2cRead8(char reg){
    char packet[1] = {reg};
    char data[1] = {0};
    i2c.write(SX1509_ADDR,packet,1, true);
    i2c.read(SX1509_ADDR,data,1,false);
    wait(0.01);
    return (uint8_t)data[0];
}

uint16_t SX1509::i2cRead16(char reg){
    char packet[1] = {reg};
    char data[2] = {0,0};
    i2c.write(SX1509_ADDR,packet,1, true);
    i2c.read(SX1509_ADDR,data,2, false);
    wait(0.01);
    return ((uint16_t)data[1] << 8) | (uint16_t)data[0];
}

bool SX1509::init(){
    i2c.frequency(400000);
    uint8_t val = i2cRead8(REGINTERRUPTMASKA); //defaults to 0xFF
    if(val == 0xFF){
        val = i2cRead8(REGSENSEHIGHB); //defaults to 0x00
        if(val == 0x00){
            return 0;
        }
    }
    return 1;
}

void SX1509::enableLEDDriver(){
    enableLEDDriver(7, 0);
}

void SX1509::enableLEDDriver(uint8_t div, bool mode){
    if(div > 7)div=7;
    div_g = div;
    //REGCLOCK            (0x1E)
        // 6:5 10
        // 01000000 = 0x40
    
    //REGMISC             (0x1F)
        // 7 0/1
        // 6:4 div
        // 3 0/1
        // 2 1
        // 1 1
        // 0 0
        //00000110 | (div<<4)
        //00000110 = 0x06 or 0x8E for log mode
        
    i2cWrite8(REGCLOCK, 0x40);
    i2cWrite8(REGMISC, 0x06 | (div<<4) | (mode<<3) | (mode<<7));
}

void SX1509::setLEDMode(bool mode){
    uint8_t buf = i2cRead8(REGMISC);
    if(mode==LINEAR){
        buf &= ~(1<<3);
        buf &= ~(1<<7);
    } else {
        buf |= (1<<3);
        buf |= (1<<7);
    }
    i2cWrite8(REGMISC, buf);
}

void SX1509::setMode(uint8_t pin, mode_t mode){
    
    // REGINPUTDISABLEA 1 0 0
    // REGPULLUPA       0 0 0
    // REGOPENDRAINA    0 1 1
    // REGDIRA          1 0 0
    
    uint8_t inputReg, pullupReg, opendReg, dirReg, ledReg;
    
    if(pin < 8){
            inputReg = REGINPUTDISABLEA;
            pullupReg = REGPULLUPA;
            opendReg = REGOPENDRAINA;
            dirReg = REGDIRA;
            ledReg = REGLEDDRIVERENABLEA;
    } else {
            inputReg = REGINPUTDISABLEB;
            pullupReg = REGPULLUPB;
            opendReg = REGOPENDRAINB;
            dirReg = REGDIRB;
            ledReg = REGLEDDRIVERENABLEB;
            pin-=8;
    }
    
    uint8_t buf;
    
    switch(mode){
        case INPUT:
            //TODO: Finish this
            break;
        case OUTPUT:
            //TODO: Finish this
            break;
        case LED:
            buf = i2cRead8(inputReg);
            buf &= ~(1<<pin);
            i2cWrite8(inputReg, buf);
            buf = i2cRead8(pullupReg);
            buf &= ~(1<<pin);
            i2cWrite8(pullupReg, buf);
            buf = i2cRead8(opendReg);
            buf |= (1<<pin);
            i2cWrite8(opendReg, buf);
            buf = i2cRead8(dirReg);
            buf &= ~(1<<pin);
            i2cWrite8(dirReg, buf);
            buf = i2cRead8(ledReg);
            buf |= (1<<pin);
            i2cWrite8(ledReg, buf);
            break;
        default:
            break;
    }
}

void SX1509::setBreath(uint8_t pin, uint8_t fadeIn, uint8_t fadeOut){
    // Clamp these
    fadeIn &= 0x1F;
    fadeOut &= 0x1F;
    i2cWrite8(riseTReg[pin],fadeIn);
    i2cWrite8(fallTReg[pin],fadeOut);
}

void SX1509::setBlink(uint8_t pin, uint8_t tOn, uint8_t tOff, uint8_t iOff){
    tOn &= 0x1F;
    tOff &= 0x1F;
    iOff &= 0x07;
    i2cWrite8(onTReg[pin],tOn);
    uint8_t buf = i2cRead8(offTReg[pin]) & 0x07;
    i2cWrite8(offTReg[pin],tOff<<3 | buf | iOff);
}

void SX1509::writePin(uint8_t pin, uint8_t intensity){
    i2cWrite8(onIReg[pin], intensity&0xFF);
    uint8_t dataReg;
    if(pin < 8){
            dataReg = REGDATAA;
    } else {
            dataReg = REGDATAB;
            pin-=8;
    }
    uint8_t buf = i2cRead8(dataReg);
    if(intensity == 0)
        i2cWrite8(dataReg, buf | (1<<pin));
    else
        i2cWrite8(dataReg, buf & ~(1<<pin));
}

void SX1509::setReset(){
    uint8_t buf = i2cRead8(REGMISC);
    buf |= (1<<2);
    i2cWrite8(REGMISC, buf);
}

void SX1509::fullReset(){
    i2cWrite8(REGRESET, 0x12);
    i2cWrite8(REGRESET, 0x34);
}