28 #include <wiringPiI2C.h> 34 #define LED0_ON_LOW 0x06 35 #define LED0_ON_HIGH 0x07 36 #define LED0_OFF_LOW 0x08 37 #define LED0_OFF_HIGH 0x09 39 #define CLOCKFREQ 25000000.0 40 #define PCA9685_RESOLUTION 4095 41 #define PCA9685_RANGE 4096 48 m_channelNumber(Number),
56 LOG(VB_GENERAL, LOG_WARNING, QStringLiteral(
"Ignoring user defined resolution for PCA9685 channel - defaulting to %1").arg(
m_maxResolution));
59 m_parent->
SetPWM(m_channelNumber, m_channelValue);
70 return QStringList() << tr(
"I2C") << tr(
"PCA9685 16 Channel PWM") << QStringLiteral(
"%1 %2").arg(tr(
"Channel")).arg(m_channelNumber) << tr(
"Resolution %1").arg(
m_resolution);
75 QMutexLocker locker(&
lock);
79 double newvalue = Value;
85 if (channelvalue == m_channelValue)
88 m_channelValue = channelvalue;
89 m_parent->
SetPWM(m_channelNumber, m_channelValue);
103 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Failed to open I2C device at address 0x%1").arg(
m_address, 0, 16));
107 LOG(VB_GENERAL, LOG_INFO, QStringLiteral(
"Opened %1 I2C device at address 0x%2")
111 if (wiringPiI2CWriteReg8(
m_fd,
MODE1, 0x00) < 0 || wiringPiI2CWriteReg8(
m_fd,
MODE2, 0x04) < 0)
113 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Failed to reset PCA9685 device"));
119 success &= wiringPiI2CWriteReg8(
m_fd,
MODE1, 0x01) > -1;
121 success &= wiringPiI2CWriteReg8(
m_fd,
MODE1, 0x80) > -1;
122 success &= wiringPiI2CWriteReg8(
m_fd,
MODE2, 0x04) > -1;
125 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Failed to set up PCA9685 device"));
129 QVariantMap::const_iterator it = Details.begin();
130 for ( ; it != Details.constEnd(); ++it)
132 if (it.key() == QStringLiteral(
"channel"))
135 QVariantMap channel = it.value().toMap();
136 if (!channel.contains(QStringLiteral(
"number")))
138 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"PCA9685 channel has no number"));
143 int channelnum = channel.value(QStringLiteral(
"number")).toInt(&ok);
145 if (!ok || channelnum < 0 || channelnum >= 16)
147 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Failed to parse valid PCA9685 channel number from '%1'").arg(channel.value(QStringLiteral(
"number")).toString()));
151 if (m_outputs[channelnum])
153 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"PCA9685 channel '%1' is already in use").arg(channelnum));
165 for (
int i = 0; i < 16; i++)
169 TorcOutputs::gOutputs->RemoveOutput(m_outputs[i]);
171 m_outputs[i] =
nullptr;
184 if (
m_fd < 0 || Channel < 0 || Channel > 15)
194 LOG(VB_GENERAL, LOG_INFO, QStringLiteral(
"Channel %1 turned completely OFF").arg(Channel));
199 LOG(VB_GENERAL, LOG_INFO, QStringLiteral(
"Channel %1 turned completely ON").arg(Channel));
204 success &= wiringPiI2CWriteReg8(
m_fd,
LED0_ON_LOW + (4 * Channel), ontime & 0xFF) > -1;
205 success &= wiringPiI2CWriteReg8(
m_fd,
LED0_ON_HIGH + (4 * Channel), ontime >> 8) > -1;
206 success &= wiringPiI2CWriteReg8(
m_fd,
LED0_OFF_LOW + (4 * Channel), offtime & 0xFF) > -1;
207 success &= wiringPiI2CWriteReg8(
m_fd,
LED0_OFF_HIGH + (4 * Channel), offtime >> 8) > -1;
210 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Error writing to channel %1").arg(Channel));
216 TorcI2CDevice* Create(
int Address,
const QString &Name,
const QVariantMap &Details)
virtual bool DownRef(void)
bool ValueIsDifferent(double &NewValue)
TorcI2CPCA9685Factory TorcI2CPCA9685Factory
virtual void SetValue(double Value)
#define PCA9685_RESOLUTION
TorcI2CPCA9685(int Address, const QVariantMap &Details)
QStringList GetDescription(void)
#define LOG(_MASK_, _LEVEL_, _STRING_)
void SetValue(double Value)
friend class TorcI2CPCA9685Channel
bool SetPWM(int Channel, int Value)
Set the hardware PWM for given channel.
TorcI2CPCA9685Channel(int Number, TorcI2CPCA9685 *Parent, const QVariantMap &Details)