PCA9955 16 channel current drive(sink) LED driver class library
Revision 0:2e6f5ac1b29b, committed 2012-08-10
- Comitter:
- nxp_ip
- Date:
- Fri Aug 10 01:39:02 2012 +0000
- Commit message:
- PCA9955 sample code
Changed in this revision
PCA9955.cpp | Show annotated file Show diff for this revision Revisions of this file |
PCA9955.h | Show annotated file Show diff for this revision Revisions of this file |
diff -r 000000000000 -r 2e6f5ac1b29b PCA9955.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PCA9955.cpp Fri Aug 10 01:39:02 2012 +0000 @@ -0,0 +1,145 @@ +/** PCA9955 constant current LED driver control library + * + * @class PCA9955 + * @author NXP Semiconductors Japan + * @version 0.5(15-Jun-2011) (publish 10-Aug-2012) + * + * Copyright: 2011 NXP Semiconductors + * Released under the MIT License: http://mbed.org/license/mit + * This is a library that controls PCA9955 a constant current LED driver + * Example: + * @code + * #include "mbed.h" + * #include "PCA9955.h" + * + * #define MAX_IREF 0x20 + * + * PCA9955 led_driver( p28, p27, 0xC0 ); // making an instance of PCA9955 + * + * main() + * { + * char v[ 16 ] = { 0xFF }; + * int sel; + * + * srand( 0 ); + * + * led_driver = 0xFFFF; + * led_driver.set_all_intensity( v ); // PWM + * led_driver.set_all_intensity( MAX_IREF, true ); // IREF + * + * while ( 1 ) { + * for ( sel = 0; sel < 16; sel++ ) { + * v[ sel ] = (char)((float)(v[ sel ]) * 0.8); + * } + * + * v[ rand() % 16 ] = 0xFF; + * + * led_driver.set_all_intensity( v ); // PWM + * wait( 0.05 ); + * } + * } + * @endcode + */ + +#include "mbed.h" +#include "PCA9955.h" + +PCA9955::PCA9955( + PinName I2C_sda, + PinName I2C_scl, + char I2C_address = PCA9955_ADDR +) : i2c( I2C_sda, I2C_scl ), i2c_addr( I2C_address ) { + + i2c.frequency( 400 * 1000 ); + write( init_array, sizeof( init_array[42] ) ); +} + +void PCA9955::set_single_individual_intensity( char port, char val, int iref ) { + write( (command_reg)((iref ? IREF_REGISTER_START : PWM_REGISTER_START) + port), val ); +} + +void PCA9955::set_all_intensity( char *p, int iref ) { + char pwm[ PCA9955_N_OF_PORTS + 1 ] = { AUTO_INCREMENT | (iref ? IREF_REGISTER_START : PWM_REGISTER_START) }; + + for ( int i = 1; i <= PCA9955_N_OF_PORTS; i++ ) + pwm[ i ] = *p++; + + write( pwm, PCA9955_N_OF_PORTS + 1 ); +} + +void PCA9955::set_all_intensity( char val, int iref ) { + char c[ PCA9955_N_OF_PORTS ]; + + for ( int i = 0; i < PCA9955_N_OF_PORTS; i++ ) + c[ i ] = val; + + set_all_intensity( c, iref ); +} + +void PCA9955::get_all_intensity( char *p, int iref ) { + read( (command_reg)(AUTO_INCREMENT | (iref ? IREF_REGISTER_START : PWM_REGISTER_START)), p, PCA9955_N_OF_PORTS ); +} + +void PCA9955::operator=( int c ) { + char a[ 1 + (PCA9955_N_OF_PORTS / 4) ] = { AUTO_INCREMENT | LEDOUT_REGISTER_START, 0x00, 0x00, 0x00, 0x00 }; + char out_val = 0x2; + + for ( int i = 0; i < PCA9955_N_OF_PORTS; i++ ) + a[ (i / 4) + 1 ] |= (((c >> i) & 0x1) ? out_val : 0x0) << ((i % 4) << 1); + + write( a, sizeof( a ) ); +} + +unsigned short PCA9955::fault_test( void ) +{ + char mode2_reg; + +#define FAULTTEST 0x40 + + mode2_reg = read( MODE2 ); + mode2_reg = 0; + write( MODE2, mode2_reg | FAULTTEST ); + + while ( read( MODE2 ) & FAULTTEST ) + ; + + return( ((unsigned short)(read( EFLAG1 )) << 8) | read( EFLAG0 ) ); +} + +void PCA9955::write( char *data, int length ) { + i2c.write( i2c_addr, data, length ); +} + +void PCA9955::write( command_reg reg_addr, char data ) { + char c[2]; + + c[0] = reg_addr; + c[1] = data; + + i2c.write( i2c_addr, c, 2 ); +} + +void PCA9955::read( command_reg reg_addr, char *data, int length ) { + i2c.write( i2c_addr, (char *)(®_addr), 1, true ); + i2c.read( i2c_addr, data, length ); +} + +char PCA9955::read( command_reg reg_addr ) { + i2c.write( i2c_addr, (char *)(®_addr), 1, true ); + i2c.read( i2c_addr, (char *)(®_addr), 1 ); + + return ( reg_addr ); +} + +char PCA9955::init_array[] = { + AUTO_INCREMENT | REGISTER_START, // Command + 0x00, 0x05, // MODE1, MODE2 + 0xAA, 0xAA, 0xAA, 0xAA, // LEDOUT[3:0] + 0x80, 0x00, // GRPPWM, GRPFREQ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // PWM[7:0] + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // PWM[15:8] + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, // IREF[7:0] + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, // IREF[15:8] + 0x08 // OFFSET: 1uS offsets +}; +
diff -r 000000000000 -r 2e6f5ac1b29b PCA9955.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PCA9955.h Fri Aug 10 01:39:02 2012 +0000 @@ -0,0 +1,161 @@ +/** PCA9955 constant current LED driver control library + * + * @class PCA9955 + * @author NXP Semiconductors Japan + * @version 0.5(15-Jun-2011) (publish 10-Aug-2012) + * + * Copyright: 2011 NXP Semiconductors + * Released under the MIT License: http://mbed.org/license/mit + * This is a library that controls PCA9955 a constant current LED driver + * Example: + * @code + * #include "mbed.h" + * #include "PCA9955.h" + * + * #define MAX_IREF 0x20 + * + * PCA9955 led_driver( p28, p27, 0xC0 ); // making an instance of PCA9955 + * + * main() + * { + * char v[ 16 ] = { 0xFF }; + * int sel; + * + * srand( 0 ); + * + * led_driver = 0xFFFF; + * led_driver.set_all_intensity( v ); // PWM + * led_driver.set_all_intensity( MAX_IREF, true ); // IREF + * + * while ( 1 ) { + * for ( sel = 0; sel < 16; sel++ ) { + * v[ sel ] = (char)((float)(v[ sel ]) * 0.8); + * } + * + * v[ rand() % 16 ] = 0xFF; + * + * led_driver.set_all_intensity( v ); // PWM + * wait( 0.05 ); + * } + * } + * @endcode + */ + +#ifndef MBED_PCA9955 +#define MBED_PCA9955 + +#include "mbed.h" + +// PCA9955 I2C address + +#if 0 +#define PCA9955_ADDR 0xC0 + +#define PCA9955_INIT_PWM 0xFF +#define PCA9955_N_OF_PORTS 16 + +#define AUTO_INCREMENT 0x80 +#define REGISTER_START 0x00 +#define LEDOUT_REGISTER_START 0x02 +#define PWM_REGISTER_START 0x0A +#define IREF_REGISTER_START 0x22 +#endif + +class PCA9955 { +public: + PCA9955( PinName I2C_sda, PinName I2C_scl, char I2C_address ); + void set_single_individual_intensity( char port, char val, int iref = false ); + void set_all_intensity( char *p, int iref = false ); + void set_all_intensity( char val, int iref = false ); + void get_all_intensity( char *p, int iref = false ); + void operator=( int c ); + unsigned short fault_test( void ); + +private: + + enum { + PCA9955_ADDR = 0xC0, + }; + + enum { + PCA9955_INIT_PWM = 0xFF, + PCA9955_N_OF_PORTS = 16, + }; + + typedef enum { + MODE1 = 0x00, + MODE2, + LEDOUT0, + LEDOUT1, + LEDOUT2, + LEDOUT3, + GRPPWM = 0x08, + GRPFREQ, + PWM0 = 0x0A, + PWM1, + PWM2, + PWM3, + PWM4, + PWM5, + PWM6, + PWM7, + PWM8, + PWM9, + PWM10, + PWM11, + PWM12, + PWM13, + PWM14, + PWM15, + IREF0 = 0x22, + IREF1, + IREF2, + IREF3, + IREF4, + IREF5, + IREF6, + IREF7, + IREF8, + IREF9, + IREF10, + IREF11, + IREF12, + IREF13, + IREF14, + IREF15, + OFFSET = 0x3A, + SUBADR1, + SUBADR2, + SUBADR3, + ALLCALLADR, + RESERVED1, + RESERVED2, + RESERVED3, + PWMALL, + IREFALL, + EFLAG0, + EFLAG1, + + REGISTER_START = MODE1, + LEDOUT_REGISTER_START = LEDOUT0, + PWM_REGISTER_START = PWM0, + IREF_REGISTER_START = IREF0, + } + command_reg; + + enum { + AUTO_INCREMENT = 0x80, + }; + + + I2C i2c; + char i2c_addr; + static char init_array[]; + void write( char *data, int length ); + void write( command_reg reg_addr, char data ); + void read( command_reg reg_addr, char *data, int length ); + char read( command_reg reg_addr ); +} +; + +#endif // MBED_PCA9955