i2c RGBW led driver push/pull or opendrain output

Fork of PCA9633 by Mederic Melard

PCA9633.cpp

Committer:
mederic
Date:
2018-06-26
Revision:
3:abc759c7c7bb
Parent:
2:651ace168465

File content as of revision 3:abc759c7c7bb:

#include "PCA9633.h"
#include <math.h>

//***********************************/************************************
//                              Constant                                //
//***********************************/************************************
#define PCA9633_ADD_SWRST   0x06 // Software Reset Call Address (0x03<<1)
#define PCA9633_REG_SWRST   0xa5 // Software Reset register
#define PCA9633_VAL_SWRST   0x5a // Software Reset register

// Register addr (with auto increment)
#define PCA9633_REG_MODE1   0x80  // Mode register 1
#define PCA9633_REG_MODE2   0x81  // Mode register 2
#define PCA9633_REG_PWM0    0x82  // brightness control LED0
#define PCA9633_REG_GRPPWM  0x86  // group duty cycle control
#define PCA9633_REG_GRPFREQ 0x87  // group frequency
#define PCA9633_REG_LEDOUT  0x88  // LED output state

//PCA9633 MODE2 register bit
#define PCA9633_BIT_DMBLNK  0x05
#define PCA9633_BIT_INVRT   0x04
#define PCA9633_BIT_OUTDRV  0x02

//***********************************/************************************
//                         Constructors                                 //
//***********************************/************************************
PCA9633::PCA9633(I2C *i2c, char addr, bool invert, bool openDrain):_i2c(i2c){
    _addr = addr<<1;
    softReset();
    /*  SLEEP=0 Normal Mode
        SUB1 =0 PCA9633 does not respond to I2C-bus subaddress 1.
        SUB2 =0 PCA9633 does not respond to I2C-bus subaddress 2.
        SUB3 =0 PCA9633 does not respond to I2C-bus subaddress 3.
        ALLCAL =0 PCA9633 does not respond to LED All Call I2C-bus address.*/
    char buf[2] = {PCA9633_REG_MODE1,0};
    _i2c->write(_addr,buf,2);
    config(invert, openDrain);
}

void PCA9633::config(bool invert, bool openDrain){    
    char buf[2] = {PCA9633_REG_MODE2,0};
    _i2c->write(_addr,buf,1);          //cmd to read mode2 
    _i2c->read(_addr, &buf[1],1);      //stock in buf[1]
    
    buf[1] &= ~((1<<PCA9633_BIT_INVRT)|(1<<PCA9633_BIT_OUTDRV));
    buf[1] |= ((invert<<PCA9633_BIT_INVRT )|((!openDrain)<<PCA9633_BIT_OUTDRV));
    _i2c->write(_addr,buf,2);
}

void PCA9633::softReset(void){
    char buf[2] = {PCA9633_REG_SWRST,PCA9633_VAL_SWRST};
    _i2c->write(0x06,buf,2);
}

void PCA9633::pwm(char bright, char pos){
    char buf[5] = {PCA9633_REG_PWM0,bright,bright,bright,bright};
    char len = 5;  
    if(pos<PCA9633::ALL){
        len=2;
        buf[0]+=pos;
    }
    _i2c->write(_addr,buf,len);
}

void PCA9633::dim(char val){;
    char buf[2] = {PCA9633_REG_MODE2,0};
     _i2c->write(_addr,buf,1);          //cmd to read mode2 
     _i2c->read(_addr, &buf[1],1);      //stock in buf[1]
     buf[1] &= ~(1<<PCA9633_BIT_DMBLNK); //set dimming in mode2
     _i2c->write(_addr,buf,2);          //write mode2
     
     buf[0] = PCA9633_REG_GRPPWM;
     buf[1] = val;
     _i2c->write(_addr,buf,2);          //dimming
}

void PCA9633::blink(char duty, float period){
    char buf[3] = {PCA9633_REG_MODE2,0,0};
    _i2c->write(_addr,buf,1);          //cmd to read mode2 
    _i2c->read(_addr, &buf[1],1);      //stock in buf[1]
    buf[1] |= (1<<PCA9633_BIT_DMBLNK); //set blink in mode2
    _i2c->write(_addr,buf,2);          //write mode2
    
    buf[0] = PCA9633_REG_GRPPWM;
    buf[1] = duty;
    buf[2] = char(rint((period*24.0)-1));
    _i2c->write(_addr,buf,3);
    
}

void PCA9633::ledout(char state, char pos){
    char buf[2] = {PCA9633_REG_LEDOUT,0};
    _i2c->write(_addr,buf,1);          //cmd to read ledout 
    _i2c->read(_addr, &buf[1],1);      //stock in buf[1]
     
    if(pos<PCA9633::ALL){
        buf[1] &= ~(0x03<<(pos<<1)); // erase 2 state bit of selected position
        buf[1] |= (state<<(pos<<1)); // set state at position
    }
    else{
        for(int i=0;i<PCA9633::ALL;i++){
            buf[1] &= ~(0x03<<(i<<1)); // erase 2 state bit of selected position
            buf[1] |= (state<<(i<<1)); // set state at position  
        }
    }
    _i2c->write(_addr,buf,2);          //write LEDOUT
}