parent
e5179d632d
commit
36c91832ac
@ -0,0 +1,132 @@
|
|||||||
|
#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(200);
|
||||||
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Refere to datasheet page 52
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
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, uint8_t on, uint8_t off)
|
||||||
|
{
|
||||||
|
m_currentLED = PCA9685_LED_PWM_REG_START + (ledNo * PCA9685_LED_NEXT_OFFSET);
|
||||||
|
|
||||||
|
std::cout << "Led" <<unsigned(ledNo)<<" ON L : " << unsigned(m_currentLED) << std::endl;
|
||||||
|
std::cout << "Led" <<unsigned(ledNo)<<" ON H : " << unsigned(m_currentLED+PCA9685_PWM_ON_H_OFFSET) << std::endl;
|
||||||
|
std::cout << "Led" <<unsigned(ledNo)<<" OFF L : " << unsigned(m_currentLED+PCA9685_PWM_OFF_L_OFFSET) << std::endl;
|
||||||
|
std::cout << "Led" <<unsigned(ledNo)<<" 0FF H : " << unsigned(m_currentLED+PCA9685_PWM_OFF_H_OFFSET) << std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "../../periferals/i2c/i2c_ch1_pImpL.hpp"
|
||||||
|
#include "../../management/errorHandling.h"
|
||||||
|
|
||||||
|
// REGISTER ADDRESSES
|
||||||
|
#define PCA9685_REG_MODE1 0x00 /**< Mode Register 1 */
|
||||||
|
#define PCA9685_REG_MODE2 0x01 /**< Mode Register 2 */
|
||||||
|
#define PCA9685_SUBADR1 0x02 /**< I2C-bus subaddress 1 */
|
||||||
|
#define PCA9685_SUBADR2 0x03 /**< I2C-bus subaddress 2 */
|
||||||
|
#define PCA9685_SUBADR3 0x04 /**< I2C-bus subaddress 3 */
|
||||||
|
#define PCA9685_ALLCALLADR 0x05 /**< LED All Call I2C-bus address */
|
||||||
|
|
||||||
|
#define PCA9685_LED_PWM_REG_START 0x06 // Start register of the fisrt LED's PWM Register wich also corresponds to LED0_ON_L
|
||||||
|
#define PCA9685_PWM_ON_H_OFFSET 0x01 // PWM ON HIGH Register for the selected LED
|
||||||
|
#define PCA9685_PWM_OFF_L_OFFSET 0x02 // PWM OFF LOW Register for the selected LED
|
||||||
|
#define PCA9685_PWM_OFF_H_OFFSET 0x03 // PWM OFF HIGH Register for the selected LED
|
||||||
|
#define PCA9685_LED_NEXT_OFFSET 0x04 // Register ON LOW of the next LED
|
||||||
|
|
||||||
|
#define PCA9685_LED_FULL_OFF_BIT 0x04 // Bit no to set on the LED OFF HIGH gerister of the selected LED to turn the LED fully OFF
|
||||||
|
#define PCA9685_LED_FULL_ON_BIT 0x04 // Bit no to set on the LED ON HIGH gerister of the selected LED to turn the LED fully ON
|
||||||
|
|
||||||
|
#define PCA9685_ALL_ON_L 0xFA // load all the LEDn_ON registers, low
|
||||||
|
#define PCA9685_ALL_ON_H 0xFB // load all the LEDn_ON registers, high
|
||||||
|
#define PCA9685_ALL_OFF_L 0xFC // load all the LEDn_OFF registers, low
|
||||||
|
#define PCA9685_ALL_OFF_H 0xFD // load all the LEDn_OFF registers,high
|
||||||
|
#define PCA9685_REG_PRESCALE 0xFE // Prescaler Register for PWM output frequency
|
||||||
|
#define PCA9685_TESTMODE 0xFF // defines the test mode to be entered
|
||||||
|
|
||||||
|
// MODE1 bits
|
||||||
|
#define PCA9685_MODE1_ALLCAL 0x01 /**< respond to LED All Call I2C-bus address */
|
||||||
|
#define PCA9685_MODE1_SUB3 0x02 /**< respond to I2C-bus subaddress 3 */
|
||||||
|
#define PCA9685_MODE1_SUB2 0x04 /**< respond to I2C-bus subaddress 2 */
|
||||||
|
#define PCA9685_MODE1_SUB1 0x08 /**< respond to I2C-bus subaddress 1 */
|
||||||
|
#define PCA9685_MODE1_SLEEP 0x10 /**< Low power mode. Oscillator off */
|
||||||
|
#define PCA9685_MODE1_AI 0x20 /**< Auto-Increment enabled */
|
||||||
|
#define PCA9685_MODE1_EXTCLK 0x40 /**< Use EXTCLK pin clock */
|
||||||
|
#define PCA9685_MODE1_RESTART 0x80 /**< Restart enabled */
|
||||||
|
|
||||||
|
// MODE2 bits
|
||||||
|
#define PCA9685_MODE2_OUTNE_0 0x01 /**< Active LOW output enable input */
|
||||||
|
#define PCA9685_MODE2_OUTNE_1 0x02 /**< Active LOW output enable input - high impedience */
|
||||||
|
#define PCA9685_MODE2_OUTDRV 0x04 /**< totem pole structure vs open-drain */
|
||||||
|
#define PCA9685_MODE2_OCH 0x08 /**< Outputs change on ACK vs STOP */
|
||||||
|
#define PCA9685_MODE2_INVRT 0x10 /**< Output logic state inverted */
|
||||||
|
|
||||||
|
#define PCA9685_I2C_ADDRESS 0x40 /**< Default PCA9685 I2C Slave Address */
|
||||||
|
#define PCA9685_FREQUENCY_OSCILLATOR 25000000 /**< Int. osc. frequency in datasheet */
|
||||||
|
#define PCA9685_OSC_STAB_TIME_US 500 // Delay to allow time for oscillator to stabilize 500 us
|
||||||
|
#define PCA9685_PRESCALE_MIN 3 /**< minimum prescale value */
|
||||||
|
#define PCA9685_PRESCALE_MAX 255 /**< maximum prescale value */
|
||||||
|
#define PCA9685_PRESCALE_DEF 200 // Default prescaler value | Datasheet Page : 25
|
||||||
|
|
||||||
|
class Pca9685
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Pca9685(i2c_ch1_pImpL* i2c,ErrorHandler* err);
|
||||||
|
void setPwmFreq(uint16_t frequency);
|
||||||
|
void setPwmMicroSeconds(uint16_t microSeconds);
|
||||||
|
void setDutyPercent(uint8_t ledNo, uint8_t on, uint8_t off);
|
||||||
|
void setDutyRaw(uint8_t ledNo, uint8_t on, uint8_t off);
|
||||||
|
void setDutyMicroSecond(uint8_t ledNo, uint16_t on, uint16_t off);
|
||||||
|
void setOnOff(uint8_t ledNo, bool onOff, bool invert);
|
||||||
|
void confClk(bool internExtern, uint32_t freq);
|
||||||
|
void setOutputMode(bool mode);
|
||||||
|
void reset();
|
||||||
|
void sleep();
|
||||||
|
void wakeup();
|
||||||
|
private:
|
||||||
|
uint8_t m_currentLED;
|
||||||
|
uint8_t m_curMode;
|
||||||
|
uint16_t m_currentPwmFreq;
|
||||||
|
uint8_t m_currentPrescale;
|
||||||
|
uint8_t m_isExternalClock;
|
||||||
|
uint32_t m_oscillatorFreq;
|
||||||
|
ErrorHandler* errorHandling;
|
||||||
|
i2c_ch1_pImpL* i2c_pca9685;
|
||||||
|
};
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in new issue