Using the I2C LED driver on the Embedded Artists baseboard to control the LEDS.

Dependencies:   mbed

PCA9532.cpp

Committer:
chris
Date:
2010-03-02
Revision:
0:5d07670e5b83

File content as of revision 0:5d07670e5b83:

/*
PCA9532
(c) 2009, cstyles
*/

#include "PCA9532.h"
#include "mbed.h"

/*
 Constructor, pin names for I2C and the I2C addrss of the device
 */


PCA9532::PCA9532(PinName scl, PinName sda, int addr) 
  : _i2c(scl, sda) {    

  _addr = addr;
  
}





/*
 force the LEDs on or off according to thier corresponding bits
 in the vector
 */

void PCA9532::write (int leds) {

    // cycle through the array
    for (int i=0; i < 16; i++) {

        // if the ith bit is '1'
        if (leds & (0x1 << i)) {
            _rmw(i,PCA9532_MODE_SET);
        }

        else {
            _rmw(i,PCA9532_MODE_CLEAR);
        }    
    }
}



/*
 this is one hot encoding for the LED array
 any bit set will have it's corresponding LED switched on
 */

void PCA9532::set (int leds) {
    for (int i=0; i < 16; i++) {
        if (leds & (0x1 << i)) {
            _rmw(i,PCA9532_MODE_SET);
        }
    }
}


void PCA9532::clear (int leds) {
    for (int i=0; i < 16; i++) {
        if (leds & (0x1 << i)) {
            _rmw(i,PCA9532_MODE_CLEAR);
        }
    }
}


void PCA9532::pwm0 (int leds) {
    for (int i=0; i < 16; i++) {
        if (leds & (0x1 << i)) {
            _rmw(i,PCA9532_MODE_PWM0);
        }
    }
}


void PCA9532::pwm1 (int leds) {
    for (int i=0; i < 16; i++) {
        if (leds & (0x1 << i)) {
            _rmw(i,PCA9532_MODE_PWM1);
        }
    }
}


void PCA9532::duty0 (float d) {

char duty = 0;

if (d > 1.0) { duty = 255; }
else if ( d < 0.0 ) { duty = 0; }
else { duty = 256 * d; }

_write(PCA9532_REG_PWM0,duty);
   
}


void PCA9532::duty1 (float d) {

char duty = 0;

if (d > 1.0) { duty = 255; }
else if ( d < 0.0 ) { duty = 0; }
else { duty = 256 * d; }

_write(PCA9532_REG_PWM1,duty);
   
}







/*
 led is in the range 0-15
 mode is inthe range 0-3
 */

void PCA9532::_rmw(int led, int mode) {

   int reg = 0;
   int offset = (led % 4);

   // makesure mode is within bounds
   if ( (mode < 0) || (mode > 3) ) {
       return;
   }


    // determine which register this is, 
    if (led < 4) {
        reg = PCA9532_REG_LS0;}

    else if ( (led > 3) && (led < 8) ) {
        reg = PCA9532_REG_LS1;}

    else if ( (led > 7) && (led < 12) ) {
        reg = PCA9532_REG_LS2;}

    else if ( (led > 11) && (led < 16) ) {
        reg = PCA9532_REG_LS3;}
        
    else { return; }

    // read the current status of the register
    char regval = _read(reg);
    
    // clear the two bit slice at the calculated offset
    regval &= ~(0x3 << (2 * offset));
    
    // now OR in the mode, shifted by 2 8 offset
    regval |= (mode << (2 * offset));
    
    // write this back
    
    _write(reg,regval);
    
    return;
}


void PCA9532::_write(int reg, int data) {
    char args[2];
    args[0] = reg;
    args[1] = data;
    _i2c.write(_addr,args,2);
}


int PCA9532::_read(int reg) {
    char args[2];
    args[0] = reg;
    _i2c.write(_addr,args,2);
    return(args[1]);
}