This is a project to replace the 8051 on a existing RGB LED board and add USB functionality. The original board relied on 8051 firmware to control the LEDs so any changes required software development. This version provides a USB interface for LED control. The USB interface is implemented as a HID with a 9 byte OutReport. In conjunction with a simple GUI the RGB LED board can now be controlled to set color patterns, intensity and pattern sequencing.

Dependencies:   PCA9635-6 mbed USBDevice

RGB GUI - Windows program to control the PCA9635 board.

/media/uploads/JimCarver/rgb_led.jpg

Revision:
1:ee2692588275
Parent:
0:5e18eb7da208
--- a/main.cpp	Fri Dec 09 21:40:36 2011 +0000
+++ b/main.cpp	Sat Apr 05 12:27:10 2014 +0000
@@ -1,69 +1,35 @@
+/************************************************************************************************
+*
+* NXP MCU I2C RGB LED DEMO (6 x PCA9635)
+* Code ported from http://mbed.org/users/JimCarver/code/RGB2/
+* Changes : Created a library for the LED DEMO board
+* LED control GUI : http://mbed.org/users/JimCarver/notebook/rgb-led-control-gui/
+*
+************************************************************************************************/
+
 #include "mbed.h"
-#include "i2cmessages.h"
 #include "USBHID.h"
+#include "PCA9635_6.h"
 
-//We declare a USBHID device. By default input and output reports are 64 bytes long.
-USBHID hid( 9, 1, 0x1Fc9, 0x0003, 0x0100, 1);
+// We declare a USBHID device. By default input and output reports are 64 bytes long.
+// Note : HID connection on the KL25Z board is marked with 'USB'
+USBHID hid( 9, 1, 0x1Fc9, 0x0003, 0x0100, 1); // output_report_length, input_report_length, vendor_id, product_id, product_release
+
+//Ledboard with 6 x PCA9635 - NXP MCU I2C RGB LED DEMO
+PCA9635_6 ledboard(PTE0, PTE1, PTD7); //SDA, SCL, EN
+
+DigitalIn SW6(PTD0);    // Pull low to run the test pattern at startup.
+DigitalIn SW5(PTD5);    // Status of this pin is written to send_report.data[0]
 
 //This report will contain data to be sent
 HID_REPORT send_report;
 HID_REPORT recv_report;
 
-Serial pc(USBTX, USBRX);
-
-DigitalOut myled1(LED1);
-DigitalOut myled2(LED2);
-DigitalOut myled3(LED3);
-DigitalOut myled4(LED4);
-DigitalOut led_en(p8);
-DigitalIn SW6(p11);
-DigitalIn SW5(p30);
-
-I2C i2c(p28, p27);
-
-Timer ms_timer;
-
-AnalogIn ain(p20);
- 
-/***************************************************************************
-NAME OF MODULE:        MAIN.C                                          
-DESCRIPTION:            Main file for the LED String Demoboard                  
-                                                                         
-(C) Copyright 2008 NXP Semiconductors               
-                                                                         
-****************************************************************************/
-BYTE dflag, tflag;
+uint8_t dflag, tflag;
 
-BYTE Buffer1[18];
-BYTE Buffer2[18];
-BYTE Buffer3[18];
-BYTE Buffer4[18];
-BYTE Buffer5[18];
-BYTE 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
-    BYTE *buf, n;
-    } LED_type;
-    
-typedef struct {
-    LED_type    RED;
-    LED_type    GREEN;
-    LED_type    BLUE;
-    } RGB_type;
-
-typedef struct {
     uint8_t r, g, b;
     } RB_type;
 
@@ -77,22 +43,22 @@
     193, 255,   0,
     127, 255,   0,
     127, 255,   0,
-     63, 255,   0,
-      0, 255,   0,
-      0, 255,   7,
-      0, 255,  15,
-      0, 255,  31,
-      0, 255,  63,
-      0, 255,  91,
-      0, 255, 127,
-      0, 255, 193,
-      0, 255, 255,
-      0, 193, 255,
-      0, 127, 255,
-      0,  63, 255,
-      0,   0, 255,
-     31,   0, 255,
-     63,   0, 255,
+    63, 255,   0,
+    0, 255,   0,
+    0, 255,   7,
+    0, 255,  15,
+    0, 255,  31,
+    0, 255,  63,
+    0, 255,  91,
+    0, 255, 127,
+    0, 255, 193,
+    0, 255, 255,
+    0, 193, 255,
+    0, 127, 255,
+    0,  63, 255,
+    0,   0, 255,
+    31,   0, 255,
+    63,   0, 255,
     127,   0, 255,
     193,   0, 255,
     255,   0, 255,
@@ -100,390 +66,140 @@
     255,   0, 127,
     255,   0,  63,
     255,   0,  15
-    };
-
-// 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  };
-
-//
-// Lookup the buffer and index to set the desired values
-// in the appropriate locations within the I2C message buffers
-// update_LED() actually sends the buffers through I2C to the drivers
-//
-void set_LED(int LEDn, BYTE R, BYTE G, BYTE 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 set_my_LED(int c)
-{
-    if(c & 1) {       myled4 = 1;       } else {       myled4 = 0;       }
-    if(c & 2) {       myled3 = 1;       } else {       myled3 = 0;       }
-    if(c & 4) {       myled2 = 1;       } else {       myled2 = 0;       }
-    if(c & 8) {       myled1 = 1;       } else {       myled1 = 0;       }
-}
-
-/***********************************************************************
-DESCRIPTION:    Initalization of the buffers (Buffer1, buffer2, Buffer3)
-INPUT(S):        None
-RETURNS:            Nothing
-************************************************************************/
-void 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;
-}
-
-
-/***********************************************************************
-DESCRIPTION:    Fill all the PWM register of a device with a RGB setting
-INPUT(S):        A,B,C --> Primary colors
-RETURNS:            Nothing
-************************************************************************/
-void Set_Same_Color_Single_Device(BYTE A, BYTE B, BYTE 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 delay(int dd)
-{
-ms_timer.reset();
-ms_timer.start();
-while(ms_timer.read_ms() <= (dd));
-ms_timer.stop();
-}
-
-void i2cfail(void)
-{
-int c = 0;
-while(1) {
-    set_my_LED(c++);
-    delay(50);
-    }
-}
-
-void I2C_Write(I2C_MESSAGE *mp)
-{
-if(i2c.write(mp->address, (char *) &mp->buf[1], mp->buf[0])) i2cfail();
-}
-
-/***********************************************************************
-DESCRIPTION:    Set the I2C address to the ALL CALL Address and
-                    send the I2C_Write command
-INPUT(S):        None
-RETURNS:            Nothing
-************************************************************************/
-void Write_All_Devices(void)
-{
-    I2C_Message.address         = ALL_CALL_I2C_ADDRESS;
-    I2C_Write(&I2C_Message);
-}
-
-
-/***********************************************************************
-DESCRIPTION:    Set the I2C address to the required address and
-                    send the I2C_Write command
-INPUT(S):        I2C Address of the targetted device (LSB = 0)
-RETURNS:            Nothing
-************************************************************************/
-void Write_To_Device(BYTE I2C_Address)
-{
-    I2C_Message.address         = I2C_Address;
-    I2C_Write(&I2C_Message);
-}
-
-
-/***********************************************************************
-DESCRIPTION:    Set the I2C address to the required address and
-                    send the I2C_Write command
-                    Wait (delay) before moving to the next step
-INPUT(S):        I2C Address of the targetted device (LSB = 0)
-                    Delay = delay in ms / 10
-RETURNS:            Nothing
-************************************************************************/
-void Write_To_Device_And_Wait(BYTE I2C_Address, BYTE Delay_Value)
-{
-    I2C_Message.address         = I2C_Address;
-    I2C_Write(&I2C_Message);
-    delay(Delay_Value);
-}
-
-
-/***********************************************************************
-DESCRIPTION:    Swtich of ALL the LEDs using the ALL CALL address
-INPUT(S):        None
-RETURNS:            Nothing
-************************************************************************/
-void ALL_LED_OFF(void)        // Switch off all the LEDs
-{
-    I2C_Message.buf             = LED_ALL_OFF; 
-    Write_All_Devices();
-}
-
-
-void LED_INTENSITY(void)
-{
-    //GLOBAL_INTENSITY[2] = global_i;
-    I2C_Message.buf = GLOBAL_INTENSITY;
-    Write_All_Devices();
-}
-
-
-void 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 read_LED( int LEDn, BYTE *R, BYTE *G, BYTE *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 rainbow_LED( void)
 {
-int i;
-    for(i=0;i<32;i++) set_LED( i, Rainbow[i].r, Rainbow[i].g, Rainbow[i].b );
+    int i;
+    for(i=0; i<32; i++) ledboard.set_LED( i, Rainbow[i].r, Rainbow[i].g, Rainbow[i].b );
 }
 
 void ripple_LED( void )
 {
-uint32_t  m;
-uint8_t LEDn, R, G, B, tR, tG, tB;
-if( dflag) {   // Ripple LEDs to the right
-    read_LED( 0, &tR, &tG, &tB);    // Save the first LED value
-    for(LEDn = 0 , m = 1; LEDn < 31; LEDn++) {
-       read_LED( LEDn+1, &R, &G, &B);
-       set_LED(  LEDn, R, G, B); 
-        m = m << 1;
+    uint32_t  m;
+    uint8_t LEDn, R, G, B, tR, tG, tB;
+    if( dflag) {   // Ripple LEDs to the right
+        ledboard.read_LED( 0, &tR, &tG, &tB);    // Save the first LED value
+        for(LEDn = 0 , m = 1; LEDn < 31; LEDn++) {
+            ledboard.read_LED( LEDn+1, &R, &G, &B);
+            ledboard.set_LED(  LEDn, R, G, B);
+            m = m << 1;
         }
-    set_LED(  31, tR, tG, tB);
+        ledboard.set_LED(  31, tR, tG, tB);
     } else {  // Ripple LEDs to the left
-    read_LED( 31, &tR, &tG, &tB);
-    for(LEDn = 31, m = 0x80000000 ; LEDn > 0; LEDn--) {
-       read_LED( LEDn - 1, &R, &G, &B);
-       set_LED(  LEDn, R, G, B);
-        m = m >> 1;
+        ledboard.read_LED( 31, &tR, &tG, &tB);
+        for(LEDn = 31, m = 0x80000000 ; LEDn > 0; LEDn--) {
+            ledboard.read_LED( LEDn - 1, &R, &G, &B);
+            ledboard.set_LED(  LEDn, R, G, B);
+            m = m >> 1;
         }
-    set_LED(  0, tR, tG, tB);
+        ledboard.set_LED(  0, tR, tG, tB);
     }
-}    
-        
-        
+}
+
+
 void test_pattern(void)
 {
-int l, r, g, b;
-// Dim Blue Color (from min to max)
-Init_Buffers();
-set_my_LED(1);
-for (r = 0, g = 0, b = 0; b < 0xFF; b++) {
-    for(l = 0; l < 32; l++) {
-        set_LED( l, r, g, b);
-        }              
-    update_LED();    
+    int l, r, g, b;
+    // Dim Blue Color (from min to max)
+    ledboard.Init_Buffers();
+    for (r = 0, g = 0, b = 0; b < 0xFF; b++) {
+        for(l = 0; l < 32; l++) {
+            ledboard.set_LED( l, r, g, b);
+        }
+        ledboard.update_LED();
+    }
+    // Mix from Only Blue (Max going to off) to Only Green (off to Max)
+    for (r = 0, g = 0, b = 0xFF; b >= 0x00; b--) {
+        for(l = 0; l < 32; l++) {
+            ledboard.set_LED( l, r, g, b);
+        }
+        ledboard.update_LED();
+        g++;
     }
-set_my_LED(2);
-// Mix from Only Blue (Max going to off) to Only Green (off to Max) 
-for (r = 0, g = 0, b = 0xFF; b >= 0x00; b--) {
-    for(l = 0;l < 32; l++) {
-       set_LED( l, r, g, b);
-       }
-    update_LED();          
-    g++;                  
-    }        
-set_my_LED(4);
-// Mix from Only Green (Max going to off) to Only Red (off to Max) 
-for (r = 0, g = 0xFF, b = 0; g >= 0x00; g--)  {
-    for (l = 0;l < 32; l++) {
-        set_LED( l, r, g, b);
+    // Mix from Only Green (Max going to off) to Only Red (off to Max)
+    for (r = 0, g = 0xFF, b = 0; g >= 0x00; g--)  {
+        for (l = 0; l < 32; l++) {
+            ledboard.set_LED( l, r, g, b);
         }
-    update_LED();
-    r++;                
+        ledboard.update_LED();
+        r++;
     }
-set_my_LED(8);
-// Mix from Only Red (Max going to off) to Only Blue (off to Max) 
-for (r = 0xFF, g = 0, b = 0; r >= 0x00; r--) {
-    for (l = 0;l < 32; l++) {
-        set_LED( l, r, g, b);
+    // Mix from Only Red (Max going to off) to Only Blue (off to Max)
+    for (r = 0xFF, g = 0, b = 0; r >= 0x00; r--) {
+        for (l = 0; l < 32; l++) {
+            ledboard.set_LED( l, r, g, b);
         }
-    update_LED();
-    b++;
+        ledboard.update_LED();
+        b++;
     }
-set_my_LED(0);
-rainbow_LED();
-update_LED();  
+    rainbow_LED();
+    ledboard.update_LED();
 }
 
 void SetOutReport (void)
 {
-int LEDn;
-uint32_t    led, m;
-uint8_t        R, G, B, seq;
+    int LEDn;
+    uint32_t led, m;
+    uint8_t  R, G, B, seq;
 
     /* Check the bits of the "OutReport" data from the PC
      * and set the output port status. */
-seq = recv_report.data[0];
-//LED_Report = (LED_Report_type *) &recv_report.data[1];
-GLOBAL_INTENSITY[2] = recv_report.data[8];
-if(seq) {
-    tflag = 2;
-    dflag = seq & 1;
-    dval = (seq & 0xFC) >> 1; // sets a range from 0x00 to 0x7E
+    seq = recv_report.data[0];
+    //LED_Report = (LED_Report_type *) &recv_report.data[1];
+    ledboard.set_global_intensity(recv_report.data[8]);
+    if(seq) {
+        tflag = 2;
+        dflag = seq & 1;
+        dval = (seq & 0xFC) >> 1; // sets a range from 0x00 to 0x7E
     } else {
-    led = recv_report.data[4];
-    led <<= 8;
-    led |= recv_report.data[3];
-    led <<= 8;
-    led |= recv_report.data[2];
-    led <<= 8;
-    led |= recv_report.data[1];
-    
-    set_my_LED(led & 0xf);
-    R = recv_report.data[5];
-    G = recv_report.data[6];
-    B = recv_report.data[7];
-    for(LEDn=0, m=1;LEDn < 32; LEDn++, m <<= 1) {
-        if(led & m) {
-            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;
+        led = recv_report.data[4];
+        led <<= 8;
+        led |= recv_report.data[3];
+        led <<= 8;
+        led |= recv_report.data[2];
+        led <<= 8;
+        led |= recv_report.data[1];
+
+        R = recv_report.data[5];
+        G = recv_report.data[6];
+        B = recv_report.data[7];
+        for(LEDn=0, m=1; LEDn < 32; LEDn++, m <<= 1) {
+            if(led & m) {
+                ledboard.set_LED( LEDn, R, G, B);
             }
         }
-    tflag = 1;
+        tflag = 1;
     }
 }
 
-
-
-
-
-
 /***********************************************************************
-DESCRIPTION:    Main function
-INPUT(S):        None
-RETURNS:            Nothing
+DESCRIPTION:   Main function
+INPUT(S):      None
+RETURNS:       Nothing
 ************************************************************************/
 int main (void)
 {
-int l = 1;
-led_en = 0;
-set_my_LED(1);
-// 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();
+    if(!SW6) test_pattern();
+    dflag = 0;
+    dval = 10;
+    tflag = 0;
+    send_report.length = 1;
+    while (1) {
+        send_report.data[0] = SW5;
+        hid.send(&send_report);
+        if(hid.readNB(&recv_report)) SetOutReport();
+        if(tflag == 2) {
+            ripple_LED();
+            ledboard.update_LED();
+            ledboard.LED_INTENSITY();
+            wait_ms(dval);
+        }
 
-// 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();
-if(!SW6) test_pattern(); 
-dflag = 0;
-dval = 10;
-tflag = 0;
-set_my_LED(l++);
-send_report.length = 1;
-while (1) {
-      send_report.data[0] = SW5;
-      hid.send(&send_report);
-      if(hid.readNB(&recv_report)) SetOutReport();
-      if(tflag == 2) {
-          ripple_LED();
-          update_LED();
-          LED_INTENSITY();
-          delay(dval);
-          }
-        
-      if(tflag == 1) {
-          update_LED();
-          LED_INTENSITY();
-          tflag = 0;
-          }
+        if(tflag == 1) {
+            ledboard.update_LED();
+            ledboard.LED_INTENSITY();
+            tflag = 0;
+        }
     }
 }
\ No newline at end of file