A feature complete driver for the PCA9952/55 LED driver from NXP.
Dependents: PCA9955_HelloWorld
Diff: PCA9955.cpp
- Revision:
- 1:016f916c5579
- Parent:
- 0:7b3cbb5a53b8
- Child:
- 4:6ca7ab31c5fb
--- a/PCA9955.cpp Tue Nov 05 21:16:25 2013 +0000 +++ b/PCA9955.cpp Thu Nov 07 21:16:07 2013 +0000 @@ -16,17 +16,27 @@ #include "PCA9955.h" -PCA9955::PCA9955(PinName sda, PinName scl, Address addr) : m_I2C(sda, scl) +PCA9955::PCA9955(PinName sda, PinName scl, Address addr) : m_I2C(sda, scl), m_ADDR((int)addr) { - //Set the internal device address - m_Addr = (int)addr; + //Set the I2C bus frequency to 400kHz + m_I2C.frequency(400000); } -bool PCA9955::open(void) +bool PCA9955::open() { //Probe for the PCA9952/55 using a Zero Length Transfer - if (!m_I2C.write(m_Addr, NULL, 0)) { - //NOTE: We don't reset here as SWRST may reset other I2C devices as well + if (!m_I2C.write(m_ADDR, NULL, 0)) { + //NOTE: We don't issue a SWRST here since it might reset other I2C devices as well + + //Read the current 8-bit register value + char value = read(REG_MODE1); + + //Configure Auto-Increment for 0x00 to 0x41 + value &= ~(1 << 5); //AI0 bit + value &= ~(1 << 6); //AI1 bit + + //Write the value back out + write(REG_MODE1, value); //Return success return true; @@ -36,7 +46,7 @@ } } -void PCA9955::reset(void) +void PCA9955::reset() { //The SWRST magic data byte char data = 0x06; @@ -48,7 +58,7 @@ wait_ms(10); } -bool PCA9955::allCallEnabled(void) +bool PCA9955::allCallEnabled() { //Read the 8-bit register value char value = read(REG_MODE1); @@ -75,7 +85,7 @@ write(REG_MODE1, value); } -bool PCA9955::subCall3Enabled(void) +bool PCA9955::subCall3Enabled() { //Read the 8-bit register value char value = read(REG_MODE1); @@ -102,7 +112,7 @@ write(REG_MODE1, value); } -bool PCA9955::subCall2Enabled(void) +bool PCA9955::subCall2Enabled() { //Read the 8-bit register value char value = read(REG_MODE1); @@ -129,7 +139,7 @@ write(REG_MODE1, value); } -bool PCA9955::subCall1Enabled(void) +bool PCA9955::subCall1Enabled() { //Read the 8-bit register value char value = read(REG_MODE1); @@ -156,7 +166,7 @@ write(REG_MODE1, value); } -PCA9955::PowerMode PCA9955::powerMode(void) +PCA9955::PowerMode PCA9955::powerMode() { //Read the 8-bit register value char value = read(REG_MODE1); @@ -183,7 +193,7 @@ write(REG_MODE1, value); } -PCA9955::OutputChangeMode PCA9955::outputChangeMode(void) +PCA9955::OutputChangeMode PCA9955::outputChangeMode() { //Read the 8-bit register value char value = read(REG_MODE2); @@ -210,7 +220,7 @@ write(REG_MODE2, value); } -PCA9955::GroupMode PCA9955::groupMode(void) +PCA9955::GroupMode PCA9955::groupMode() { //Read the 8-bit register value char value = read(REG_MODE2); @@ -237,7 +247,7 @@ write(REG_MODE2, value); } -bool PCA9955::overTemp(void) +bool PCA9955::overTemp() { //Read the current 8-bit register value char value = read(REG_MODE2); @@ -322,7 +332,7 @@ write(reg, value); } -float PCA9955::groupDuty(void) +float PCA9955::groupDuty() { //Return the value as a float return groupDuty_char() / 255.0f; @@ -340,7 +350,7 @@ groupDuty_char((char)(duty * 255.0f)); } -char PCA9955::groupDuty_char(void) +char PCA9955::groupDuty_char() { //Return the 8-bit register value return read(REG_GRPPWM); @@ -352,7 +362,7 @@ write(REG_GRPPWM, duty); } -float PCA9955::groupBlinkPeriod(void) +float PCA9955::groupBlinkPeriod() { //Read the 8-bit register value char value = groupBlinkPeriod_char(); @@ -382,7 +392,7 @@ groupBlinkPeriod_char(value); } -char PCA9955::groupBlinkPeriod_char(void) +char PCA9955::groupBlinkPeriod_char() { //Return the 8-bit register value return read(REG_GRPFREQ); @@ -454,7 +464,7 @@ write(REG_IREF0 + (char)output, iref); } -char PCA9955::outputDelay(void) +char PCA9955::outputDelay() { //Return the 8-bit register value (minus the top 4 bits) return read(REG_OFFSET) & 0x0F; @@ -466,7 +476,7 @@ write(REG_OFFSET, clocks & 0x0F); } -char PCA9955::subCall1Addr(void) +char PCA9955::subCall1Addr() { //Return the 8-bit address return read(REG_SUBADR1); @@ -478,7 +488,7 @@ write(REG_SUBADR1, addr); } -char PCA9955::subCall2Addr(void) +char PCA9955::subCall2Addr() { //Return the 8-bit address return read(REG_SUBADR2); @@ -490,7 +500,7 @@ write(REG_SUBADR2, addr); } -char PCA9955::subCall3Addr(void) +char PCA9955::subCall3Addr() { //Return the 8-bit address return read(REG_SUBADR3); @@ -502,7 +512,7 @@ write(REG_SUBADR3, addr); } -char PCA9955::allCallAddr(void) +char PCA9955::allCallAddr() { //Return the 8-bit address return read(REG_ALLCALLADR); @@ -534,6 +544,19 @@ writeMulti(buff, 5); } +void PCA9955::getOutputDuties(float* duties) +{ + char buff[16]; + + //Read all of the duty cycles as unsigned chars first + getOutputDuties_char(buff); + + //Convert all of the duty cycles to percents + for (int i = 0; i < 16; i++) { + duties[i] = buff[i] / 255.0f; + } +} + void PCA9955::allOutputDuties(float duty) { //Range check the value @@ -546,12 +569,64 @@ allOutputDuties_char((char)(duty * 255.0f)); } +void PCA9955::allOutputDuties(float* duties) +{ + char buff[17]; + + //Assemble the sending array + buff[0] = REG_PWM0 | REG_AUTO_INC; + for (int i = 1; i < 17; i++) { + //Range check the value + if (duties[i - 1] < 0.0f) + duties[i - 1] = 0.0f; + if (duties[i - 1] > 1.0f) + duties[i - 1] = 1.0f; + + //Convert the value to a char and write it + buff[i] = duties[i - 1] * 255.0f; + } + + //Send the array + writeMulti(buff, 17); +} + +void PCA9955::getOutputDuties_char(char* duties) +{ + //Read all of the duty cycles at once + readMulti(REG_PWM0 | REG_AUTO_INC, duties, 16); +} + void PCA9955::allOutputDuties_char(char duty) { //Write the new 8-bit register value write(REG_PWMALL, duty); } +void PCA9955::allOutputDuties_char(char* duties) +{ + char buff[17]; + + //Assemble the sending array + buff[0] = REG_PWM0 | REG_AUTO_INC; + memcpy(buff + 1, duties, 16); + + //Send the array + writeMulti(buff, 17); +} + +void PCA9955::getOutputCurrents(float* irefs) +{ + char buff[16]; + + //Read all of the current references as unsigned chars first + getOutputCurrents_char(buff); + + //Convert all of the duty cycles to percents + for (int i = 0; i < 16; i++) { + irefs[i] = buff[i] / 255.0f; + } +} + void PCA9955::allOutputCurrents(float iref) { //Range check the value @@ -564,13 +639,52 @@ allOutputCurrents_char((char)(iref * 255.0f)); } +void PCA9955::allOutputCurrents(float* irefs) +{ + char buff[17]; + + //Assemble the sending array + buff[0] = REG_IREF0 | REG_AUTO_INC; + for (int i = 1; i < 17; i++) { + //Range check the value + if (irefs[i - 1] < 0.0f) + irefs[i - 1] = 0.0f; + if (irefs[i - 1] > 1.0f) + irefs[i - 1] = 1.0f; + + //Convert the value to a char and write it + buff[i] = irefs[i - 1] * 255.0f; + } + + //Send the array + writeMulti(buff, 17); +} + +void PCA9955::getOutputCurrents_char(char* irefs) +{ + //Read all of the current references at once + readMulti(REG_IREF0 | REG_AUTO_INC, irefs, 16); +} + void PCA9955::allOutputCurrents_char(char iref) { //Write the new 8-bit register value write(REG_IREFALL, iref); } -unsigned short PCA9955::faultTest(void) +void PCA9955::allOutputCurrents_char(char* irefs) +{ + char buff[17]; + + //Assemble the sending array + buff[0] = REG_IREF0 | REG_AUTO_INC; + memcpy(buff + 1, irefs, 16); + + //Send the array + writeMulti(buff, 17); +} + +unsigned short PCA9955::faultTest() { //Read the current 8-bit register value char value = read(REG_MODE2); @@ -594,27 +708,25 @@ return flags; } +PCA9955& PCA9955::operator=(float value) +{ + //Set all of the output duties + allOutputDuties(value); + return *this; +} + char PCA9955::read(char reg) { //Select the register - m_I2C.write(m_Addr, ®, 1); + m_I2C.write(m_ADDR, ®, 1, true); //Read the 8-bit register - m_I2C.read(m_Addr, ®, 1); + m_I2C.read(m_ADDR, ®, 1); //Return the byte return reg; } -void PCA9955::readMulti(char reg, char* data, int length) -{ - //Select the starting register - m_I2C.write(m_Addr, ®, 1); - - //Read the specified number of bytes - m_I2C.read(m_Addr, data, length); -} - void PCA9955::write(char reg, char data) { //Create a temporary buffer @@ -625,11 +737,20 @@ buff[1] = data; //Write the data - m_I2C.write(m_Addr, buff, 2); + m_I2C.write(m_ADDR, buff, 2); +} + +void PCA9955::readMulti(char startReg, char* data, int length) +{ + //Select the starting register + m_I2C.write(m_ADDR, &startReg, 1, true); + + //Read the specified number of bytes + m_I2C.read(m_ADDR, data, length); } void PCA9955::writeMulti(char* data, int length) { //Write the data - m_I2C.write(m_Addr, data, length); + m_I2C.write(m_ADDR, data, length); }