Library for NXP MCU I2C RGB LED DEMO board (6 x PCA9635)

Dependents:   RGB2

PCA9635 board - schematic

Warning

When the original NXP demo board is connected to another mcu board : Disable the on-board 8051 mcu.

PCA9635_6.cpp

Committer:
frankvnk
Date:
2014-04-01
Revision:
1:b89b54759940
Parent:
0:1258ad754d9c

File content as of revision 1:b89b54759940:

/**************************************************************************************************
 *****                                                                                        *****
 *****  Name: PCA9635_6.cpp                                                                   *****
 *****  Date: 09/03/2014                                                                      *****
 *****  Auth: Frank Vannieuwkerke                                                             *****
 *****  Func: library for I2C RGB LED Demo board (6 x PCA9635)                                *****
 *****        Ported from http://mbed.org/users/JimCarver/code/RGB2/                          *****
 **************************************************************************************************/

//#include "mbed.h"
#include "PCA9635_6.h"

// TODO : check which variables are used - add const if they do not change.
#define    SW_RESET_I2C_ADDRESS   0x06
#define    ALL_CALL_I2C_ADDRESS   0xE0
#define    SUB_ADDRESS_1          0xE2
#define    SUB_ADDRESS_2          0xE4
#define    SUB_ADDRESS_3          0xE8

uint8_t SW_RESET[3] = {2,0xA5,0x5A};

uint8_t WAKE_UP_AND_INIT[4] = {3,0x80,0x81,0x01};

uint8_t GLOBAL_BLINK_SUB_ADDR_1[4] = {3,0x80,0x89,0x21};    // Blink + All Call/Sub-Addr1
uint8_t GLOBAL_BLINK_SUB_ADDR_2[4] = {3,0x80,0x85,0x21};    // Blink + All Call/Sub-Addr2
uint8_t GLOBAL_BLINK_SUB_ADDR_3[4] = {3,0x80,0x83,0x21};    // Blink + All Call/Sub-Addr3
uint8_t GLOBAL_DIM[3] = {2,0x01,0x01};
uint8_t GLOBAL_INTENSITY[3] = { 2, 0x92, 0};

uint8_t ALL_LED_FULL_PWM[18]={17,0x82,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};

uint8_t LED_ALL_ON[6]                            = {5,0x94,0x55,0x55,0x55,0x55};
uint8_t LED_ALL_OFF[6]                           = {5,0x94,0x00,0x00,0x00,0x00};
uint8_t LED_ALL_INDVDL_PLUS_GLOBL_PWM_CTRL[6]    = {5,0x94,0xFF,0xFF,0xFF,0xFF};

uint8_t LED_0_3_6_9_12_15_ON[6]  = {5,0x94,0x41,0x10,0x04,0x41};
uint8_t LED_1_4_7_10_13_ON[6]    = {5,0x94,0x10,0x04,0x41,0x10};
uint8_t LED_2_5_8_11_14_ON[6]    = {5,0x94,0x04,0x41,0x10,0x04};

//uint8_t dflag, tflag;

uint8_t Buffer1[18];
uint8_t Buffer2[18];
uint8_t Buffer3[18];
uint8_t Buffer4[18];
uint8_t Buffer5[18];
uint8_t Buffer6[18];

I2C_MESSAGE    I2C_Message;
//int dval;

/*typedef struct {
    uint32_t    LED;
    uint8_t     RED, GREEN, BLUE, INTENSITY;
} LED_Report_type ;

volatile LED_Report_type *LED_Report;*/

typedef struct {
// Definition for a LED location, buffer pointer, and index into that buffer
    uint8_t *buf, n;
} LED_type;

typedef struct {
    LED_type    RED;
    LED_type    GREEN;
    LED_type    BLUE;
} RGB_type;

// An array of structures that define the buffer and location in the buffer for all of the LEDs
// Due to the design of the RGB LED board this is easier than the convoluted calculation needed
//
RGB_type RGB_LED[32] = {
//  RED             GREEN           BLUE
//  LED1-16
    Buffer1, 2,     Buffer1, 3,     Buffer1, 4,
    Buffer1, 5,     Buffer1, 6,     Buffer1, 7,
    Buffer1, 8,     Buffer1, 9,     Buffer1, 10,
    Buffer1, 11,    Buffer1, 12,    Buffer1, 13,
    Buffer1, 14,    Buffer1, 15,    Buffer1, 16,
    Buffer1, 17,    Buffer3, 2,     Buffer3, 3,
    Buffer3, 4,     Buffer3, 5,     Buffer3, 6,
    Buffer3, 7,     Buffer3, 8,     Buffer3, 9,
    Buffer3, 10,    Buffer3, 11,    Buffer3, 12,
    Buffer3, 13,    Buffer3, 14,    Buffer3, 15,
    Buffer3, 16,    Buffer3, 17,    Buffer5, 2,
    Buffer5, 3,     Buffer5, 4,     Buffer5, 5,
    Buffer5, 6,     Buffer5, 7,     Buffer5, 8,
    Buffer5, 9,     Buffer5, 10,    Buffer5, 11,
    Buffer5, 12,    Buffer5, 13,    Buffer5, 14,
    Buffer5, 15,    Buffer5, 16,    Buffer5, 17,

//  LED17-32
    Buffer2, 2,     Buffer2, 3,     Buffer2, 4,
    Buffer2, 5,     Buffer2, 6,     Buffer2, 7,
    Buffer2, 8,     Buffer2, 9,     Buffer2, 10,
    Buffer2, 11,    Buffer2, 12,    Buffer2, 13,
    Buffer2, 14,    Buffer2, 15,    Buffer2, 16,
    Buffer2, 17,    Buffer4, 2,     Buffer4, 3,
    Buffer4, 4,     Buffer4, 5,     Buffer4, 6,
    Buffer4, 7,     Buffer4, 8,     Buffer4, 9,
    Buffer4, 10,    Buffer4, 11,    Buffer4, 12,
    Buffer4, 13,    Buffer4, 14,    Buffer4, 15,
    Buffer4, 16,    Buffer4, 17,    Buffer6, 2,
    Buffer6, 3,     Buffer6, 4,     Buffer6, 5,
    Buffer6, 6,     Buffer6, 7,     Buffer6, 8,
    Buffer6, 9,     Buffer6, 10,    Buffer6, 11,
    Buffer6, 12,    Buffer6, 13,    Buffer6, 14,
    Buffer6, 15,    Buffer6, 16,    Buffer6, 17
};

PCA9635_6::PCA9635_6(PinName sda, PinName scl, PinName en) : _i2c(sda, scl), _en(en)
{    
    _i2c.frequency(800000);
    // enable PCA9635 board
    _en = 0;
    // Perform Software Reset - Set the PCA9635 in a known state
    I2C_Message.buf = SW_RESET;
    Write_To_Device(SW_RESET_I2C_ADDRESS);
    // Wake up and Init the PCA9635 using ALL CALL address
    I2C_Message.buf = WAKE_UP_AND_INIT;
    Write_All_Devices();
    Init_Buffers();
    // Program all LED outputs to Individual PWM + Global PWM using ALL CALL address
    I2C_Message.buf = LED_ALL_INDVDL_PLUS_GLOBL_PWM_CTRL;
    Write_All_Devices();
}
 
void PCA9635_6::set_LED(int LEDn, uint8_t R, uint8_t G, uint8_t B)
{
    RGB_LED[LEDn].RED.buf[RGB_LED[LEDn].RED.n] = R;
    RGB_LED[LEDn].GREEN.buf[RGB_LED[LEDn].GREEN.n] = G;
    RGB_LED[LEDn].BLUE.buf[RGB_LED[LEDn].BLUE.n] = B;
}

void PCA9635_6::Init_Buffers(void)
{
    int i = 0;
    for (i = 0; i<18; i++) {
        Buffer1[i] = 0;
        Buffer2[i] = 0;
        Buffer3[i] = 0;
        Buffer4[i] = 0;
        Buffer5[i] = 0;
        Buffer6[i] = 0;
    }

    Buffer1[0]    = 17;
    Buffer2[0]    = 17;
    Buffer3[0]    = 17;
    Buffer4[0]    = 17;
    Buffer5[0]    = 17;
    Buffer6[0]    = 17;
    Buffer1[1]    = 0x82;
    Buffer2[1]    = 0x82;
    Buffer3[1]    = 0x82;
    Buffer4[1]    = 0x82;
    Buffer5[1]    = 0x82;
    Buffer6[1]    = 0x82;
}


void PCA9635_6::Set_Same_Color_Single_Device(uint8_t A, uint8_t B, uint8_t C)
{
    int i;
    Buffer1[0]    = 17;
    Buffer1[1]    = 0x82;
    for (i = 0; i < 5; i++) {
        Buffer1[3*i+2] = A;
        Buffer1[3*i+3] = B;
        Buffer1[3*i+4] = C;
    }
    Buffer1[17] = A;
}


void PCA9635_6::i2cfail(void)
{
//    printf("-------> I2C error\r\n");
    while(1) {
    }
}

void PCA9635_6::I2C_Write(I2C_MESSAGE *mp)
{
    if(_i2c.write(mp->address, (char *) &mp->buf[1], mp->buf[0])) i2cfail();
}

void PCA9635_6::Write_All_Devices(void)
{
    I2C_Message.address         = ALL_CALL_I2C_ADDRESS;
    I2C_Write(&I2C_Message);
}

void PCA9635_6::Write_To_Device(uint8_t I2C_Address)
{
    I2C_Message.address         = I2C_Address;
    I2C_Write(&I2C_Message);
}

void PCA9635_6::Write_To_Device_And_Wait(uint8_t I2C_Address, uint8_t Delay_Value)
{
    I2C_Message.address         = I2C_Address;
    I2C_Write(&I2C_Message);
    wait_ms(Delay_Value);
}

void PCA9635_6::ALL_LED_OFF(void)        // Switch off all the LEDs
{
    I2C_Message.buf             = LED_ALL_OFF;
    Write_All_Devices();
}

void PCA9635_6::LED_INTENSITY(void)
{
    //GLOBAL_INTENSITY[2] = global_i;
    I2C_Message.buf = GLOBAL_INTENSITY;
    Write_All_Devices();
}

void PCA9635_6::update_LED(void)
{
    I2C_Message.buf = Buffer1;
    Write_To_Device(0x80);
    I2C_Message.buf = Buffer2;
    Write_To_Device(0x86);
    I2C_Message.buf = Buffer3;
    Write_To_Device(0x82);
    I2C_Message.buf = Buffer4;
    Write_To_Device(0x88);
    I2C_Message.buf = Buffer5;
    Write_To_Device(0x84);
    I2C_Message.buf = Buffer6;
    Write_To_Device(0x8A);
}

void PCA9635_6::read_LED( int LEDn, uint8_t *R, uint8_t *G, uint8_t *B)
{
    *R = RGB_LED[LEDn].RED.buf[RGB_LED[LEDn].RED.n];
    *G = RGB_LED[LEDn].GREEN.buf[RGB_LED[LEDn].GREEN.n];
    *B = RGB_LED[LEDn].BLUE.buf[RGB_LED[LEDn].BLUE.n];
}

void PCA9635_6::set_global_intensity(uint8_t globi)
{
    GLOBAL_INTENSITY[2] = globi;
}