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.
main.cpp
- Committer:
- user3736966508731826368
- Date:
- 2011-12-09
- Revision:
- 0:5e18eb7da208
- Child:
- 1:ee2692588275
File content as of revision 0:5e18eb7da208:
#include "mbed.h" #include "i2cmessages.h" #include "USBHID.h" //We declare a USBHID device. By default input and output reports are 64 bytes long. USBHID hid( 9, 1, 0x1Fc9, 0x0003, 0x0100, 1); //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; 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; RB_type Rainbow[] = { 255, 0, 0, 255, 23, 0, 255, 64, 0, 255, 127, 0, 255, 193, 0, 255, 255, 0, 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, 127, 0, 255, 193, 0, 255, 255, 0, 255, 255, 0, 193, 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 ); } 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; } 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; } 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(); } 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); } 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); } update_LED(); b++; } set_my_LED(0); rainbow_LED(); update_LED(); } void SetOutReport (void) { 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 } 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; } } tflag = 1; } } /*********************************************************************** 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(); // 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; } } }