// Infineon RGB LED Lighting Shield // Constant voltage LED load (e.g. LED strip) // by Attila Tomasovics // Pulse-density modulation on 3 channels with over-current limit at 900mA // Demonstrates directly accessing RGB LED Shield registers // Modified 01 April 2015 #define ADDRESS 0x15EUL #define INTENSITY_RED 0x11U #define INTENSITY_GREEN 0x12U #define INTENSITY_BLUE 0x13U #define INTENSITY_RGB 0x14U #define CURRENT_RED 0x21U #define CURRENT_GREEN 0x22U #define CURRENT_BLUE 0x23U #define CURRENT_RGB 0x24U #define DMXOFF 0x30U #define DMXON 0x31U #define DMXSLOT 0x32U #define DMX8BIT 0x33U #define DMX16BIT 0x34U #define OFFTIME_RED 0x41U #define OFFTIME_GREEN 0x42U #define OFFTIME_BLUE 0x43U #define WALKTIME 0x50U #define DIMMINGLEVEL 0x60U #define FADERATE 0x61U #define _CHANGE_ADDRESS 0x70U #define READ_INTENSITY_RED 0x81U #define READ_INTENSITY_GREEN 0x82U #define READ_INTENSITY_BLUE 0x83U #define READ_CURRENT_RED 0x84U #define READ_CURRENT_GREEN 0x85U #define READ_CURRENT_BLUE 0x86U #define READ_OFFTIME_RED 0x87U #define READ_OFFTIME_GREEN 0x88U #define READ_OFFTIME_BLUE 0x89U #define READ_WALKTIME 0x8AU #define READ_DIMMINGLEVEL 0x8BU #define READ_FADERATE 0x8CU #define READ_INTENSITY_RED 0x81U #define READ_INTENSITY_GREEN 0x82U #define READ_INTENSITY_BLUE 0x83U #define READ_CURRENT_RED 0x84U #define READ_CURRENT_GREEN 0x85U #define READ_CURRENT_BLUE 0x86U #define READ_OFFTIME_RED 0x87U #define READ_OFFTIME_GREEN 0x88U #define READ_OFFTIME_BLUE 0x89U #define READ_WALKTIME 0x8AU #define READ_DIMMINGLEVEL 0x8BU #define READ_FADERATE 0x8CU #define READ_DMX 0x8DU #define READ_DMXSLOT 0x8EU #define READ_DMXBIT 0x8FU #define READ_DMXREDH 0x94U #define READ_DMXREDL 0x95U #define READ_DMXGREENH 0x96U #define READ_DMXGREENL 0x97U #define READ_DMXBLUEH 0x98U #define READ_DMXBLUEL 0x99U #define DIRECTACCESS_READ 0x90U // read twice #define DIRECTACCESS_MOVE 0x91U #define DIRECTACCESS_AND 0x92U #define DIRECTACCESS_OR 0x93U #define SAVEPARAMETERS 0xA0U #include unsigned int c[14] = {0}; unsigned int d[4] = {0}; unsigned int on = 0; unsigned int message = 0; unsigned long redcurr = 0; unsigned long greencurr = 0; unsigned long bluecurr = 0; unsigned long redoff = 0; unsigned long greenoff = 0; unsigned long blueoff = 0; unsigned long redint = 0x00; unsigned long greenint = 0x00; unsigned long blueint = 0x00; unsigned long fadetime = 0x00; unsigned long walk = 0x00; unsigned long brightness = 1; unsigned long dmx_RedH = 0x00; unsigned long dmx_RedL = 0x00; unsigned long dmx_GreenH = 0x00; unsigned long dmx_GreenL = 0x00; unsigned long dmx_BlueH = 0x00; unsigned long dmx_BlueL = 0x00; unsigned long dmx_enable = 0x00; unsigned long dmx_starting = 0x00; unsigned long messageFourBytes = 0; void setup() { Serial.begin(9600); Wire.begin(); while (on != 1) // Wait for shield to respond { I2CDMX (ADDRESS, DMXOFF); // disable DMX512 interface I2CWRITE2BYTES (ADDRESS, FADERATE, 0x0000); // Immediate fade I2CWRITE2BYTES (ADDRESS, DIMMINGLEVEL, 0x0000); // 0% brightness level I2CWRITE2BYTES (ADDRESS, WALKTIME, 0); // immediate walk I2CWRITE6BYTES (ADDRESS, INTENSITY_RGB, 0x000, 0x000, 0x000); // turn off light on = I2CREAD(ADDRESS, READ_DIMMINGLEVEL); // Read brightness level if (message == 1 && on == 0) // If message received and brightness level = 0% { message = 0; on = 1; // break out of loop } } // make sure everything is off while (brightness != 0) { brightness = I2CREAD (ADDRESS, READ_DIMMINGLEVEL); I2CWRITE2BYTES (ADDRESS, DIMMINGLEVEL, 0x0000); } //------------------------------------------------------------------------------------------------------------------------------------------- // Reconfigure RGB LED Lighting Shield for constant voltage LED load (e.g. LED strip) // set current limit to 900mA (overcurrent) --> if the current goes above the limit, the LED channel will be shut down immediately (TRAP) I2CWRITE_DIRECTACCESS (ADDRESS, DIRECTACCESS_MOVE, 0x5003003C, 148); // BCCU0_INTS0 = 148; --> ~900mA I2CWRITE_DIRECTACCESS (ADDRESS, DIRECTACCESS_MOVE, 0x50030064, 148); // BCCU0_INTS2 = 148; --> ~900mA I2CWRITE_DIRECTACCESS (ADDRESS, DIRECTACCESS_MOVE, 0x500300B4, 148); // BCCU0_INTS6 = 148; I2CWRITE_DIRECTACCESS (ADDRESS, DIRECTACCESS_MOVE, 0x50030018, 0x00000045); // BCCU0_CHSTRCON = 0x00000045; // reprogram CCU4 inputs (no more peak-current control, overcurrent protection instead: TRAP) I2CWRITE_DIRECTACCESS (ADDRESS, DIRECTACCESS_MOVE, 0x48040200, 0x00100100); // CCU40_CC41INS = 0x00100100; I2CWRITE_DIRECTACCESS (ADDRESS, DIRECTACCESS_MOVE, 0x48040300, 0x00100100); // CCU40_CC42INS = 0x00100100; I2CWRITE_DIRECTACCESS (ADDRESS, DIRECTACCESS_MOVE, 0x48040400, 0x00100100); // CCU40_CC43INS = 0x00100100; I2CWRITE_DIRECTACCESS (ADDRESS, DIRECTACCESS_MOVE, 0x48040204, 0x00020000); // CCU40_CC41CMC = 0x00020000; I2CWRITE_DIRECTACCESS (ADDRESS, DIRECTACCESS_MOVE, 0x48040304, 0x00020000); // CCU40_CC42CMC = 0x00020000; I2CWRITE_DIRECTACCESS (ADDRESS, DIRECTACCESS_MOVE, 0x48040404, 0x00020000); // CCU40_CC43CMC = 0x00020000; I2CWRITE_DIRECTACCESS (ADDRESS, DIRECTACCESS_MOVE, 0x48040214, 0x03420100); // CCU40_CC41TC = 0x03420100; I2CWRITE_DIRECTACCESS (ADDRESS, DIRECTACCESS_MOVE, 0x48040314, 0x03420100); // CCU40_CC42TC = 0x03420100; I2CWRITE_DIRECTACCESS (ADDRESS, DIRECTACCESS_MOVE, 0x48040414, 0x03420100); // CCU40_CC43TC = 0x03420100; // 100% duty cycle (no off-time needs to be generated anymore) I2CWRITE_DIRECTACCESS (ADDRESS, DIRECTACCESS_MOVE, 0x4804023C, 0x00000000); // CCU40_CC41CRS = 0; I2CWRITE_DIRECTACCESS (ADDRESS, DIRECTACCESS_MOVE, 0x4804033C, 0x00000000); // CCU40_CC42CRS = 0; I2CWRITE_DIRECTACCESS (ADDRESS, DIRECTACCESS_MOVE, 0x4804043C, 0x00000000); // CCU40_CC43CRS = 0; I2CWRITE_DIRECTACCESS (ADDRESS, DIRECTACCESS_MOVE, 0x48040010, 0x00001110); // CCU40_GCSS = 0x00001110; // clear TRAP in all channels (in case it accidentally occurred while rewiring) I2CWRITE_DIRECTACCESS (ADDRESS, DIRECTACCESS_MOVE, 0x480402B0, 0x00000C00); // CCU40_CC41SWR = 0x00000C00; I2CWRITE_DIRECTACCESS (ADDRESS, DIRECTACCESS_MOVE, 0x480403B0, 0x00000C00); // CCU40_CC42SWR = 0x00000C00; I2CWRITE_DIRECTACCESS (ADDRESS, DIRECTACCESS_MOVE, 0x480404B0, 0x00000C00); // CCU40_CC43SWR = 0x00000C00; //------------------------------------------------------------------------------------------------------------------------------------------- I2CWRITE2BYTES (ADDRESS, WALKTIME, 97); // Set walktime to 998ms I2CWRITE2BYTES (ADDRESS, FADERATE, 20); // Fast dimming I2CWRITE2BYTES (ADDRESS, DIMMINGLEVEL, 0x0FFF); // Maximum Brightness I2CDMX(ADDRESS, DMXOFF); // Turn off DMX512 interface } // the loop routine runs over and over again forever: void loop() { // LED lamp colour: yellow I2CWRITE6BYTES (ADDRESS, INTENSITY_RGB, 0x800, 0x800, 0x000); delay(1000); // wait 1 s // LED lamp colour: magenta I2CWRITE6BYTES (ADDRESS, INTENSITY_RGB, 0x800, 0x000, 0x800); delay(1000); // wait 1 s // LEDd lamp colour: cyan I2CWRITE6BYTES (ADDRESS, INTENSITY_RGB, 0x000, 0x800, 0x800); delay(1000); // wait 1 s } /* Parameters (IN): int Address - Address of RGB LED Shield, Default 0x15E int Command - Defined I2C Commands i.e. INTENSITY_RED, INTENSITY_GREEN, INTENSITY_BLUE unsigned int Data - 16bit data to be written to slave Parameters (OUT): None Return Value: None Description: This function will write 2 bytes of word to the I2C bus line */ void I2CWRITE2BYTES (int Address, int Command, unsigned int Data) { unsigned int upperByte, lowerByte; // Separate 4 byte data into 2 byte values lowerByte = Data; upperByte = Data >> 8; unsigned int lowerSLAD = (unsigned int) (Address & 0x00FF); // Putting address into correct format unsigned int upperSLAD = Address >> 8; upperSLAD |= 0x79; // First 5 bits 11110 and last bit '1' for a write Wire.beginTransmission(byte(upperSLAD)); // Start I2C transmission Wire.write(byte(lowerSLAD)); // address lower 8 bits of i2c address Wire.write(byte(Command)); // write command Wire.write(byte(upperByte)); // write data Wire.write(byte(lowerByte)); Wire.endTransmission(true); } /* Parameters (IN): int Address - Address of RGB LED Shield, Default 0x15E int Command - Defined I2C Commands i.e. INTENSITY_RGB, CURRENT_RGB unsigned int DataOne, unsigned int DataTwo, unsigned int DataThree - Three 16bit data to be written to slave Parameters (OUT): None Return Value: None Description: This function will write 6 bytes of word to the I2C bus line */ void I2CWRITE6BYTES (unsigned int Address, unsigned int Command, unsigned int DataOne, unsigned int DataTwo, unsigned int DataThree) // DataOne: Red, DataTwo: Green, DataThree: Blue { unsigned int upperByte, lowerByte; // Split each Data parameter into upper and lower 8 bytes because I2C format sends 8 bytes of data each time lowerByte = DataOne; upperByte = DataOne >> 8; unsigned int lowerSLAD = (unsigned int) (Address & 0x00FF); unsigned int upperSLAD = Address >> 8; upperSLAD |= 0x79; // First 5 bits 11110 and last bit '1' for a write Wire.beginTransmission(byte(upperSLAD)); // Red Wire.write(byte(lowerSLAD)); Wire.write(byte(Command)); Wire.write(byte(upperByte)); Wire.write(byte(lowerByte)); lowerByte = DataTwo; upperByte = DataTwo >> 8; Wire.write(byte(upperByte)); Wire.write(byte(lowerByte)); lowerByte = DataThree; upperByte = DataThree >> 8; Wire.write(byte(upperByte)); Wire.write(byte(lowerByte)); Wire.endTransmission(true); } /* Parameters (IN): int Address - Address of RGB LED Shield, Default 0x15E int Command - Defined I2C Commands i.e. DMX16Bit unsigned int DataOne, unsigned int DataTwo, unsigned int DataThree, usigned int DataFour, unsigned int DataFive - Three 16bit data to be written to slave Parameters (OUT): None Return Value: None Description: This function will write 12 bytes of word to the I2C bus line */ void I2CWRITE12BYTES (unsigned int Address, unsigned int Command, unsigned int DataOne, unsigned int DataTwo, unsigned int DataThree, unsigned int DataFour, unsigned int DataFive, unsigned int DataSix) // DataOne: Red, DataTwo: Green, DataThree: Blue { unsigned int upperByte, lowerByte; lowerByte = DataOne; upperByte = DataOne >> 8; unsigned int lowerSLAD = (unsigned int) (Address & 0x00FF); unsigned int upperSLAD = Address >> 8; upperSLAD |= 0x79; // First 5 bits 11110 and last bit '1' for a write Wire.beginTransmission(byte(upperSLAD)); Wire.write(byte(lowerSLAD)); Wire.write(byte(Command)); // write command Wire.write(byte(upperByte)); // write 2 bytes Wire.write(byte(lowerByte)); lowerByte = DataTwo; upperByte = DataTwo >> 8; Wire.write(byte(upperByte)); // write next two bytes Wire.write(byte(lowerByte)); lowerByte = DataThree; upperByte = DataThree >> 8; Wire.write(byte(upperByte)); Wire.write(byte(lowerByte)); lowerByte = DataFour; upperByte = DataFour >> 8; Wire.write(byte(upperByte)); Wire.write(byte(lowerByte)); lowerByte = DataFive; upperByte = DataFive >> 8; Wire.write(byte(upperByte)); Wire.write(byte(lowerByte)); lowerByte = DataSix; upperByte = DataSix >> 8; Wire.write(byte(upperByte)); Wire.write(byte(lowerByte)); Wire.endTransmission(true); } /* Parameters (IN): int Address - Address of RGB LED Shield, Default 0x15E int Command - Defined read I2C Commands i.e. READ_INTENSITY_RED, READ_INTENSITY_GREEN, READ_INTENSITY_BLUE Parameters (OUT): None Return Value: Requested data from Shield will be sent back Description: This function will request 2 bytes of word from the shield */ unsigned int I2CREAD (unsigned int Address, unsigned int Command) // Returns data sent by slave { int i = 0; unsigned int lowerSLAD = (unsigned int) (Address & 0x00FF); unsigned int upperSLAD = Address >> 8; upperSLAD |= 0x79; Wire.beginTransmission(byte(upperSLAD)); // Red Wire.write(byte(lowerSLAD)); Wire.write(byte(Command)); Wire.endTransmission(false); // false for Repeated Start Wire.beginTransmission(byte(upperSLAD)); Wire.write(byte(lowerSLAD)); Wire.requestFrom(upperSLAD, 2, true); unsigned int data = 0; while(Wire.available()) // slave may send less than requested. Print out received data byte { message = 1; c[i] = Wire.read(); // receive a byte as character i++; } Wire.endTransmission(true); data = c[1]; // write data to serial monitor. c[1] is higher byte data = (data << 8) | c[0]; // shift left and combine with lower byte Serial.print("0x"); if (data < 0x1000) Serial.print("0"); Serial.println(data, HEX); return data; } /* Parameters (IN): int Address - Address of RGB LED Shield, Default 0x15E int Command - DIRECTACCESS_READ Parameters (OUT): None Return Value: Requested data from the Shield will be returned Description: This function will request 4 bytes of data from shield. */ unsigned long I2CREAD_DIRECTACCESS (unsigned int Address, unsigned int Command, unsigned long registerAddress) { int i = 0; unsigned int lowerSLAD = (unsigned int) (Address & 0x00FF); // sending command + address unsigned int upperSLAD = Address >> 8; upperSLAD |= 0x79; // First 5 bits 11110 and last bit '1' for a write Wire.beginTransmission(byte(upperSLAD)); Wire.write(byte(lowerSLAD)); Wire.write(byte(Command)); unsigned int firstByte, secondByte, thirdByte, fourthByte; firstByte = registerAddress >> 24; // top byte secondByte = registerAddress >> 16; thirdByte = registerAddress >> 8; fourthByte = registerAddress; // bottom byte Wire.write(byte(firstByte)); Wire.write(byte(secondByte)); Wire.write(byte(thirdByte)); Wire.write(byte(fourthByte)); Wire.endTransmission(false); // false for Repeated Start Wire.beginTransmission(byte(upperSLAD)); // request for read Wire.write(byte(lowerSLAD)); Wire.requestFrom(upperSLAD, 4, true); unsigned long data = 0; while(Wire.available()) // slave may send less than requested. Print out received data byte { d[i] = 0; d[i] = Wire.read(); // receive a byte as character i++; } Wire.endTransmission(true); data = d[3]; // combining into one variable. Highest byte received first data = (data << 8) | d[2]; data = (data << 8) | d[1]; data = (data << 8) | d[0]; Serial.print("0x"); if (data < 0x10000000) Serial.print("0"); Serial.println(data, HEX); return data; } /* Parameters (IN): int Address - Address of RGB LED Shield, Default 0x15E int Command - Defined I2C Commands i.e. DIRECTACCESS_OR, DIRECTACCESS_AND, DIRECTACCESS_MOVE unsigned long registerAddress - address of target register unsigned long Data - 32 bits data to be written to register Parameters (OUT): None Return Value: None Description: This function will write 4 bytes of data to specified register */ void I2CWRITE_DIRECTACCESS (unsigned int Address, unsigned int Command, unsigned long registerAddress, unsigned long Data) // For accessing registers directly { int i = 0; unsigned int lowerSLAD = (unsigned int) (Address & 0x00FF); // sending command + address unsigned int upperSLAD = Address >> 8; upperSLAD |= 0x79; // First 5 bits 11110 and last bit '1' for a write Wire.beginTransmission(byte(upperSLAD)); Wire.write(byte(lowerSLAD)); Wire.write(byte(Command)); unsigned int firstByte, secondByte, thirdByte, fourthByte; // Send address of register first firstByte = registerAddress >> 24; // top byte secondByte = registerAddress >> 16; thirdByte = registerAddress >> 8; fourthByte = registerAddress; // bottom byte Wire.write(byte(firstByte)); Wire.write(byte(secondByte)); Wire.write(byte(thirdByte)); Wire.write(byte(fourthByte)); firstByte = Data >> 24; // top byte secondByte = Data >> 16; thirdByte = Data >> 8; fourthByte = Data; // bottom byte Wire.write(byte(firstByte)); // send 4 bytes of data Wire.write(byte(secondByte)); Wire.write(byte(thirdByte)); Wire.write(byte(fourthByte)); Wire.endTransmission(true); } /* Parameters (IN): int Address - Address of RGB LED Shield, Default 0x15E unsigned int newAddress - Address the shield should change to Parameters (OUT): None Return Value: None Description: This function will change the I2C address of the slave */ void CHANGEADDRESS (unsigned int Address, unsigned int newAddress) { unsigned int lowerSLAD = (unsigned int) (Address & 0x00FF); unsigned int upperSLAD = Address >> 8; upperSLAD |= 0x79; // First 5 bits 11110 and last bit '1' for a write Wire.beginTransmission(byte(upperSLAD)); // Red Wire.write(byte(lowerSLAD)); Wire.write(byte(0x70)); // Command to change address lowerSLAD = (unsigned int) (newAddress & 0x00FF); upperSLAD = newAddress >> 7; // Split address into 2 bytes upperSLAD |= 0xF0; // 10 bit addressing: First 5 bits have to be 11110. upperSLAD &= 0xFE; Wire.write(byte(upperSLAD)); Wire.write(byte(lowerSLAD)); Wire.endTransmission(true); } /* Parameters (IN): int Address - Address of RGB LED Shield, Default 0x15E unsigned int Command - DMXON, DMXOFF Parameters (OUT): None Return Value: None Description: This function will enable or disable DMX512 control on shield */ void I2CDMX (unsigned int Address, unsigned int Command) // Switch off / on the DMX { unsigned int lowerSLAD = (unsigned int) (Address & 0x00FF); // Putting address into correct format unsigned int upperSLAD = Address >> 8; upperSLAD |= 0x79; Wire.beginTransmission(byte(upperSLAD)); // Start I2C transmission Wire.write(byte(lowerSLAD)); Wire.write(byte(Command)); Wire.endTransmission(true); } /* Parameters (IN): int Address - Address of RGB LED Shield, Default 0x15E Parameters (OUT): None Return Value: None Description: This function will request the shield to save configurations to flash memory */ void I2CSAVEPARAM (unsigned int Address) { int i = 0; unsigned int lowerSLAD = (unsigned int) (Address & 0x00FF); unsigned int upperSLAD = Address >> 8; upperSLAD |= 0x79; Wire.beginTransmission(byte(upperSLAD)); Wire.write(byte(lowerSLAD)); Wire.write(byte(SAVEPARAMETERS)); // write SAVEPARAMETERS command Wire.endTransmission(false); // false for Repeated Start Wire.beginTransmission(byte(upperSLAD)); Wire.write(byte(lowerSLAD)); // write to address lower 8 bits of slave address Wire.requestFrom(upperSLAD, 2, true); // send READ request with upper slave address unsigned int data = 0; while(Wire.available()) // slave may send less than requested. Print out received data byte { message = 1; c[i] = Wire.read(); // receive a byte as character i++; } Wire.endTransmission(true); // STOP condition data = c[1]; // print the data on serial monitor data = (data << 8) | c[0]; Serial.print("0x"); if (data < 0x1000) Serial.print("0"); Serial.println(data, HEX); }