You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

164 lines
4.1 KiB

#include "pca9685.h"
Pca9685::Pca9685(i2c_ch1_pImpL* i2c, ErrorHandler* err)
{
i2c_pca9685 = i2c;
errorHandling = err;
m_isExternalClock = 0;
m_oscillatorFreq = PCA9685_FREQUENCY_OSCILLATOR;
setPwmFreq(48);
m_currentLED = PCA9685_LED_PWM_REG_START;
errorHandling->addNewError(-1,__FILE__,"Selected duty cycle is too big",KILL);
errorHandling->addNewError(-2,__FILE__,"Selected duty cycle is too small",KILL);
errorHandling->addNewError(-3,__FILE__,"Selected PWM frequency is too fast",SPARE);
errorHandling->addNewError(-4,__FILE__,"Selected PWM frequency is too slow",SPARE);
errorHandling->addNewError(-5,__FILE__,"Oscillator frequency can't be 0 or inferior to 0",KILL);
errorHandling->addNewError(-6,__FILE__,"Oscillator frequency cant't be higher than 50 MHz",KILL);
errorHandling->addNewError(-7,__FILE__,"On Duty Cyle if greater than alowed maximum of 4095",SPARE);
errorHandling->addNewError(-8,__FILE__,"Off Duty Cyle if greater than alowed maximum of 4095",SPARE);
errorHandling->addNewError(-9,__FILE__,"Cumulation of the On & Off Duty Cyle if greater than alowed maximum of 4095",SPARE);
errorHandling->addNewError(-10,__FILE__,"On & Off Duty Cyle can't be equal to each other",SPARE);
}
/*Refere to datasheet page 25
*
*
* osc_clock
* prescale vlaue = _______________________ - 1
* 4096 * update_rate
*
*/
void Pca9685::setPwmFreq(uint16_t frequency)
{
if(frequency > 1526)
{
frequency = 1526;
errorHandling->handleError(-3,__FILE__);
}
else if (frequency == 1526) // Rounding correction
{
frequency -= 1;
}
if(frequency < 24)
{
frequency = 24;
errorHandling->handleError(-4,__FILE__);
}
m_currentPrescale = (m_oscillatorFreq / ( 4096 * frequency) ) -1;
std::cout << "Prescaler is set to: " << unsigned(m_currentPrescale) << std::endl;
sleep();
i2c_pca9685->writeWord(PCA9685_I2C_ADDRESS, PCA9685_REG_PRESCALE, m_currentPrescale);
wakeup();
}
void Pca9685::setPwmMicroSeconds(uint16_t microSeconds)
{
}
void Pca9685::setDutyPercent(uint8_t ledNo, uint8_t on, uint8_t off)
{
}
void Pca9685::setDutyRaw(uint8_t ledNo, uint16_t on, uint16_t off)
{
m_currentLED = PCA9685_LED_PWM_REG_START + (ledNo * PCA9685_LED_NEXT_OFFSET);
if(on > 4095)
{
on = 4095;
off = 0;
errorHandling->handleError(-7,__FILE__);
}
if(off > 4095)
{
off = 4095;
on = 0;
errorHandling->handleError(-8,__FILE__);
}
if(on + off > 4095)
{
off = 4095;
on = 0;
errorHandling->handleError(-9,__FILE__);
}
if(on == off)
{
off = 4095;
on = 0;
errorHandling->handleError(-10,__FILE__);
}
i2c_pca9685->writeWord(PCA9685_I2C_ADDRESS, m_currentLED, on & 0xFF);
i2c_pca9685->writeWord(PCA9685_I2C_ADDRESS, m_currentLED + PCA9685_PWM_ON_H_OFFSET, on >> 8);
i2c_pca9685->writeWord(PCA9685_I2C_ADDRESS, m_currentLED + PCA9685_PWM_OFF_L_OFFSET, off & 0xFF);
i2c_pca9685->writeWord(PCA9685_I2C_ADDRESS, m_currentLED + PCA9685_PWM_OFF_H_OFFSET, off >> 8);
}
void Pca9685::setDutyMicroSecond(uint8_t ledNo, uint16_t on, uint16_t off)
{
}
void Pca9685::setOnOff(uint8_t ledNo, bool onOff, bool invert)
{
}
void Pca9685::confClk(bool internExtern, uint32_t freq)
{
if(internExtern)
{
m_isExternalClock = 0;
}
else
{
m_isExternalClock = 1;
if(freq > 0)
{
if(freq <= 50000000)
{
m_oscillatorFreq = freq;
}
else
{
errorHandling->handleError(-6,__FILE__);
}
}
else
{
errorHandling->handleError(-5,__FILE__);
}
}
}
void Pca9685::setOutputMode(bool mode)
{
}
void Pca9685::reset()
{
i2c_pca9685->writeWord(PCA9685_I2C_ADDRESS, PCA9685_REG_MODE1, PCA9685_MODE1_RESTART);
}
void Pca9685::sleep()
{
m_curMode = i2c_pca9685->readByte(PCA9685_I2C_ADDRESS,PCA9685_REG_MODE1);
m_curMode = m_curMode | PCA9685_MODE1_SLEEP;
i2c_pca9685->writeWord(PCA9685_I2C_ADDRESS, PCA9685_REG_MODE1, m_curMode);
}
void Pca9685::wakeup()
{
m_curMode = i2c_pca9685->readByte(PCA9685_I2C_ADDRESS,PCA9685_REG_MODE1);
m_curMode = m_curMode & ~PCA9685_MODE1_SLEEP;
i2c_pca9685->writeWord(PCA9685_I2C_ADDRESS, PCA9685_REG_MODE1, m_curMode);
usleep(PCA9685_OSC_STAB_TIME_US); // refer to datasheet page 14
}