581 lines
18 KiB
C++
581 lines
18 KiB
C++
/*@brief library to interact with IP5306 over I2C communication
|
|
*/
|
|
|
|
#ifndef _IP5306_I2C_H_
|
|
#define _IP5306_I2C_H_
|
|
|
|
#include <Wire.h> //I2C library
|
|
#include "Arduino.h"
|
|
#include <stdint.h>
|
|
|
|
/*macros definition*/
|
|
#define ENABLE 1
|
|
#define DISABLE 0
|
|
|
|
#define IP5306_ADDRESS 0x75 //7 bit slave address
|
|
|
|
/****************************Registers*****************************/
|
|
#define SYS_CTL0 0x00
|
|
#define SYS_CTL1 0x01
|
|
#define SYS_CTL2 0x02
|
|
|
|
#define Charger_CTL0 0x20
|
|
#define Charger_CTL1 0x21
|
|
#define Charger_CTL2 0x22
|
|
#define Charger_CTL3 0x23
|
|
|
|
#define CHG_DIG_CTL0 0x24
|
|
|
|
#define REG_READ0 0x70
|
|
#define REG_READ1 0x71
|
|
#define REG_READ2 0x72
|
|
#define REG_UNDEF1 0x75
|
|
#define REG_READ3 0x77
|
|
#define REG_UNDEF2 0x78
|
|
|
|
#define BAT_VADC_DAT0 0xA2
|
|
#define BAT_VADC_DAT1 0xA3
|
|
|
|
#define BAT_IADC_DAT0 0xA4
|
|
#define BAT_IADC_DAT1 0xA5
|
|
|
|
/************************bit definitions***************************/
|
|
union {
|
|
struct {
|
|
uint8_t BUTTON_SHUTDOWN : 1;
|
|
uint8_t SET_BOOST_OUTPUT_ENABLE : 1;
|
|
uint8_t POWER_ON_LOAD : 1;
|
|
uint8_t RSVD : 1;
|
|
uint8_t CHARGER_ENABLE : 1;
|
|
uint8_t BOOST_ENABLE : 1;
|
|
uint8_t RSVD2 : 2;
|
|
} bits;
|
|
|
|
uint8_t reg_byte;
|
|
} reg_SYS_CTL0_t;
|
|
|
|
union {
|
|
struct {
|
|
uint8_t LOW_BATTERY_SHUTDOWN_ENABLE : 1;
|
|
uint8_t RSVD : 1;
|
|
uint8_t BOOST_AFTER_VIN : 1;
|
|
uint8_t RSVD2 : 2;
|
|
uint8_t SHORT_PRESS_BOOST_SWITCH_ENABLE : 1;
|
|
uint8_t FLASHLIGHT_CTRL_SIGNAL_SELECTION : 1;
|
|
uint8_t BOOST_CTRL_SIGNAL_SELECTION : 1;
|
|
} bits;
|
|
uint8_t reg_byte;
|
|
} reg_SYS_CTL1_t;
|
|
|
|
union {
|
|
struct {
|
|
uint8_t RSVD : 2;
|
|
uint8_t LIGHT_LOAD_SHUTDOWN_TIME : 2;
|
|
uint8_t LONG_PRESS_TIME : 1;
|
|
uint8_t RSVD2 : 3;
|
|
} bits;
|
|
uint8_t reg_byte;
|
|
} reg_SYS_CTL2_t;
|
|
|
|
#define SHUTDOWN_8s 0
|
|
#define SHUTDOWN_32s 1
|
|
#define SHUTDOWN_16s 2
|
|
#define SHUTDOWN_64s 3
|
|
|
|
union {
|
|
struct {
|
|
uint8_t CHARGING_FULL_STOP_VOLTAGE : 2;
|
|
uint8_t RSVD : 6;
|
|
} bits;
|
|
uint8_t reg_byte;
|
|
} reg_Charger_CTL0_t;
|
|
|
|
#define CUT_OFF_VOLTAGE_0 0 // 4.14/4.26/4.305/4.35 V
|
|
#define CUT_OFF_VOLTAGE_1 1 // 4.17/4.275/4.32/4.365 V
|
|
#define CUT_OFF_VOLTAGE_2 2 // 4.185/4.29/4.335/4.38 V
|
|
#define CUT_OFF_VOLTAGE_3 3 // 4.2/4.305/4.35/4.395 V
|
|
|
|
union {
|
|
struct {
|
|
uint8_t RSVD : 2;
|
|
uint8_t CHARGE_UNDER_VOLTAGE_LOOP : 3;
|
|
uint8_t RSVD2 : 1;
|
|
uint8_t END_CHARGE_CURRENT_DETECTION : 2;
|
|
} bits;
|
|
uint8_t reg_byte;
|
|
} reg_Charger_CTL1_t;
|
|
|
|
#define CURRENT_200 0
|
|
#define CURRENT_400 1
|
|
#define CURRENT_500 2
|
|
#define CURRENT_600 3
|
|
|
|
#define VOUT_0 0 //4.45
|
|
#define VOUT_1 1 //4.5
|
|
#define VOUT_2 2 //4.55
|
|
#define VOUT_3 3 //4.6
|
|
#define VOUT_4 4 //4.65
|
|
#define VOUT_5 5 //4.7
|
|
#define VOUT_6 6 //4.75
|
|
#define VOUT_7 7 //4.8
|
|
|
|
union {
|
|
struct {
|
|
uint8_t VOLTAGE_PRESSURE : 2;
|
|
uint8_t BATTERY_VOLTAGE : 2;
|
|
uint8_t RSVD : 4;
|
|
} bits;
|
|
uint8_t reg_byte;
|
|
} reg_Charger_CTL2_t;
|
|
|
|
#define BATT_VOLTAGE_3 3 //4.4
|
|
#define BATT_VOLTAGE_2 2 //4.35
|
|
#define BATT_VOLTAGE_1 1 //4.3
|
|
#define BATT_VOLTAGE_0 0 //4.2
|
|
|
|
#define Pressurized_42 3
|
|
#define Pressurized_28 2
|
|
#define Pressurized_14 1
|
|
#define Not_pressurized 0
|
|
|
|
union {
|
|
struct {
|
|
uint8_t RSVD : 5;
|
|
uint8_t CHARGE_CC_LOOP : 1;
|
|
uint8_t RSVD2 : 2;
|
|
} bits;
|
|
uint8_t reg_byte;
|
|
} reg_Charger_CTL3_t;
|
|
|
|
union {
|
|
struct {
|
|
uint8_t VIN_CURRENT : 5;
|
|
uint8_t RSVD : 3;
|
|
} bits;
|
|
uint8_t reg_byte;
|
|
} reg_CHG_DIG_CTL0_t;
|
|
|
|
union {
|
|
struct {
|
|
uint8_t RSVD : 3;
|
|
uint8_t CHARGE_ENABLE : 1;
|
|
uint8_t RSVD2 : 4;
|
|
} bits;
|
|
uint8_t reg_byte;
|
|
} reg_READ0_t;
|
|
|
|
union {
|
|
struct {
|
|
uint8_t RSVD : 3;
|
|
uint8_t BATTERY_STATUS : 1;
|
|
uint8_t RSVD2 : 4;
|
|
} bits;
|
|
uint8_t reg_byte;
|
|
} reg_READ1_t;
|
|
|
|
union {
|
|
struct {
|
|
uint8_t RSVD : 2;
|
|
uint8_t LOAD_LEVEL : 1;
|
|
uint8_t RSVD2 : 5;
|
|
} bits;
|
|
uint8_t reg_byte;
|
|
} reg_READ2_t;
|
|
|
|
union {
|
|
struct {
|
|
uint8_t SHORT_PRESS_DETECT : 1;
|
|
uint8_t LONG_PRESS_DETECT : 1;
|
|
uint8_t DOUBLE_PRESS_DETECT : 1;
|
|
uint8_t RSVD : 5;
|
|
} bits;
|
|
uint8_t reg_byte;
|
|
} reg_READ3_t;
|
|
|
|
class IP5306{
|
|
public:
|
|
/*@brief initialize i2c
|
|
*/
|
|
IP5306(void) {
|
|
/*initialize register data*/
|
|
reg_SYS_CTL0_t.reg_byte = i2c_read(IP5306_ADDRESS,SYS_CTL0);
|
|
reg_SYS_CTL1_t.reg_byte = i2c_read(IP5306_ADDRESS,SYS_CTL1);
|
|
reg_SYS_CTL2_t.reg_byte = i2c_read(IP5306_ADDRESS,SYS_CTL2);
|
|
|
|
reg_Charger_CTL0_t.reg_byte = i2c_read(IP5306_ADDRESS,Charger_CTL0);
|
|
reg_Charger_CTL1_t.reg_byte = i2c_read(IP5306_ADDRESS,Charger_CTL1);
|
|
reg_Charger_CTL2_t.reg_byte = i2c_read(IP5306_ADDRESS,Charger_CTL2);
|
|
reg_Charger_CTL3_t.reg_byte = i2c_read(IP5306_ADDRESS,Charger_CTL3);
|
|
}
|
|
|
|
/*@brief write data to register
|
|
@param register address to write to,data to be written
|
|
and i2c address of the device
|
|
@retval None
|
|
*/
|
|
void i2c_write(uint8_t slave_address, uint8_t register_address, uint8_t data) {
|
|
|
|
Wire.beginTransmission(slave_address);
|
|
Wire.write(register_address);
|
|
Wire.write(data);
|
|
Wire.endTransmission();
|
|
}
|
|
|
|
/*@brief read the register value
|
|
@param register address to read,and i2c address of the device
|
|
@retval current register data
|
|
*/
|
|
uint8_t i2c_read(uint8_t slave_address, uint8_t register_address) {
|
|
|
|
uint8_t c = 0;
|
|
Wire.beginTransmission(slave_address);
|
|
Wire.write(register_address);
|
|
Wire.endTransmission();
|
|
|
|
Wire.requestFrom(slave_address, 1);
|
|
|
|
while (Wire.available()) { // slave may send less than requested
|
|
c = Wire.read(); // receive a byte as character
|
|
}
|
|
|
|
return c;
|
|
}
|
|
|
|
/*@brief select boost mode
|
|
@param enable or disable bit
|
|
@retval None
|
|
@note Default value - enable
|
|
*/
|
|
void boost_mode(uint8_t boost_en) {
|
|
reg_SYS_CTL0_t.bits.BOOST_ENABLE = boost_en;
|
|
|
|
i2c_write(IP5306_ADDRESS,SYS_CTL0,reg_SYS_CTL0_t.reg_byte);
|
|
}
|
|
|
|
/*@brief select charger mode
|
|
@param enable or disable bit
|
|
@retval None
|
|
@note Default value - enable
|
|
*/
|
|
void charger_mode(uint8_t charger_en) {
|
|
reg_SYS_CTL0_t.bits.CHARGER_ENABLE = charger_en;
|
|
|
|
i2c_write(IP5306_ADDRESS,SYS_CTL0,reg_SYS_CTL0_t.reg_byte);
|
|
}
|
|
|
|
/*@brief select auto power on once load detected
|
|
@param enable or disable bit
|
|
@retval None
|
|
@note Default value - enable
|
|
*/
|
|
void power_on_load(uint8_t power_on_en) {
|
|
reg_SYS_CTL0_t.bits.POWER_ON_LOAD = power_on_en;
|
|
|
|
i2c_write(IP5306_ADDRESS,SYS_CTL0,reg_SYS_CTL0_t.reg_byte);
|
|
}
|
|
|
|
/*@brief boost o/p normally open function
|
|
@param enable or disable bit
|
|
@retval None
|
|
@note Default value - enable
|
|
*/
|
|
void boost_output(uint8_t output_val) {
|
|
reg_SYS_CTL0_t.bits.SET_BOOST_OUTPUT_ENABLE = output_val;
|
|
|
|
i2c_write(IP5306_ADDRESS,SYS_CTL0,reg_SYS_CTL0_t.reg_byte);
|
|
}
|
|
|
|
/*@brief eneter shutdown mode using button
|
|
@param enable or disable bit
|
|
@retval None
|
|
@note Default value - disable
|
|
*/
|
|
void button_shutdown(uint8_t shutdown_val) {
|
|
reg_SYS_CTL0_t.bits.BUTTON_SHUTDOWN = shutdown_val;
|
|
|
|
i2c_write(IP5306_ADDRESS,SYS_CTL0,reg_SYS_CTL0_t.reg_byte);
|
|
}
|
|
|
|
/*@brief boost control mode using button
|
|
@param enable or disable bit
|
|
@retval None
|
|
@note Default value - disable
|
|
*/
|
|
void boost_ctrl_signal(uint8_t press_val) {
|
|
reg_SYS_CTL1_t.bits.BOOST_CTRL_SIGNAL_SELECTION = press_val;
|
|
|
|
i2c_write(IP5306_ADDRESS,SYS_CTL1,reg_SYS_CTL1_t.reg_byte);
|
|
}
|
|
|
|
/*@brief flashlight control mode using button
|
|
@param enable or disable bit
|
|
@retval None
|
|
@note Default value - disable
|
|
*/
|
|
void flashlight_ctrl_signal(uint8_t press_val) {
|
|
reg_SYS_CTL1_t.bits.FLASHLIGHT_CTRL_SIGNAL_SELECTION = press_val;
|
|
|
|
i2c_write(IP5306_ADDRESS,SYS_CTL1,reg_SYS_CTL1_t.reg_byte);
|
|
}
|
|
|
|
/*@brief
|
|
@param enable or disable bit
|
|
@retval None
|
|
@note Default value - disable
|
|
*/
|
|
void short_press_boost(uint8_t boost_en) {
|
|
reg_SYS_CTL1_t.bits.SHORT_PRESS_BOOST_SWITCH_ENABLE = boost_en;
|
|
|
|
i2c_write(IP5306_ADDRESS,SYS_CTL1,reg_SYS_CTL1_t.reg_byte);
|
|
}
|
|
|
|
/*@brief keep boost mode on after input supply removal
|
|
@param enable or disable bit
|
|
@retval None
|
|
@note Default value - enable
|
|
*/
|
|
void boost_after_vin(uint8_t val) {
|
|
reg_SYS_CTL1_t.bits.BOOST_AFTER_VIN = val;
|
|
|
|
i2c_write(IP5306_ADDRESS,SYS_CTL1,reg_SYS_CTL1_t.reg_byte);
|
|
}
|
|
|
|
/*@brief shutdown if battery voltage raches 3V
|
|
@param enable or disable bit
|
|
@retval None
|
|
@note Default value - enable
|
|
*/
|
|
void low_battery_shutdown(uint8_t shutdown_en) {
|
|
reg_SYS_CTL1_t.bits.LOW_BATTERY_SHUTDOWN_ENABLE = shutdown_en;
|
|
|
|
i2c_write(IP5306_ADDRESS,SYS_CTL1,reg_SYS_CTL1_t.reg_byte);
|
|
}
|
|
|
|
/*@brief set long press timing
|
|
@param long press time value - 0 for 2s , 1 for 3s
|
|
@retval None
|
|
@note Default value - disable
|
|
*/
|
|
void set_long_press_time(uint8_t press_time_val) {
|
|
reg_SYS_CTL2_t.bits.LONG_PRESS_TIME = press_time_val;
|
|
|
|
i2c_write(IP5306_ADDRESS,SYS_CTL2,reg_SYS_CTL2_t.reg_byte);
|
|
}
|
|
|
|
/*@brief set light load shutdown timing
|
|
@param shutdown time value - 0 for 8s, 1 for 32s, 2 for 16s and 3 for 64s
|
|
@retval None
|
|
@note Default value - disable
|
|
*/
|
|
void set_light_load_shutdown_time(uint8_t shutdown_time) {
|
|
reg_SYS_CTL2_t.bits.LIGHT_LOAD_SHUTDOWN_TIME = shutdown_time;
|
|
|
|
i2c_write(IP5306_ADDRESS,SYS_CTL2,reg_SYS_CTL2_t.reg_byte);
|
|
}
|
|
|
|
/*@brief set charging cutoff voltage range for battery
|
|
@param voltage range value - 0 for 4.14/4.26/4.305/4.35 V
|
|
1 for 4.17/4.275/4.32/4.365 V
|
|
2 for 4.185/4.29/4.335/4.38 V
|
|
3 for 4.2/4.305/4.35/4.395 V
|
|
@retval None
|
|
@note Default value - 2
|
|
*/
|
|
void set_charging_stop_voltage(uint8_t voltage_val) {
|
|
reg_Charger_CTL0_t.bits.CHARGING_FULL_STOP_VOLTAGE = voltage_val;
|
|
|
|
i2c_write(IP5306_ADDRESS,Charger_CTL0,reg_Charger_CTL0_t.reg_byte);
|
|
}
|
|
|
|
/*@brief set charging complete current detection
|
|
@param current value - 3 : 600mA
|
|
2 : 500mA
|
|
1 : 400mA
|
|
0 : 200mA
|
|
|
|
@retval None
|
|
@note Default value - 1
|
|
*/
|
|
void end_charge_current(uint8_t current_val) {
|
|
reg_Charger_CTL1_t.bits.END_CHARGE_CURRENT_DETECTION = current_val;
|
|
|
|
i2c_write(IP5306_ADDRESS,Charger_CTL1,reg_Charger_CTL1_t.reg_byte);
|
|
}
|
|
|
|
/*@brief set voltage Vout for charging
|
|
@param voltage value - 111:4.8
|
|
110:4.75
|
|
101:4.7
|
|
100:4.65
|
|
011:4.6
|
|
010:4.55
|
|
001:4.5
|
|
000:4.45
|
|
@retval None
|
|
@note Default value - 101
|
|
*/
|
|
void charger_under_voltage(uint8_t voltage_val) {
|
|
reg_Charger_CTL1_t.bits.CHARGE_UNDER_VOLTAGE_LOOP = voltage_val;
|
|
|
|
i2c_write(IP5306_ADDRESS,Charger_CTL1,reg_Charger_CTL1_t.reg_byte);
|
|
}
|
|
|
|
/*@brief set battery voltage
|
|
@param voltage value - 00:4.2
|
|
01:4.3
|
|
02:4.35
|
|
03:4.4
|
|
@retval None
|
|
@note Default value - 00
|
|
*/
|
|
void set_battery_voltage(uint8_t voltage_val) {
|
|
reg_Charger_CTL2_t.bits.BATTERY_VOLTAGE = voltage_val;
|
|
|
|
i2c_write(IP5306_ADDRESS,Charger_CTL2,reg_Charger_CTL2_t.reg_byte);
|
|
}
|
|
|
|
/*@brief set constant voltage charging setting
|
|
@param voltage value - 11: Pressurized 42mV
|
|
10: Pressurized 28mV
|
|
01: Pressurized 14mV
|
|
00: Not pressurized
|
|
@retval None
|
|
@note Default value - 01
|
|
@note :4.30V/4.35V/4.4V It is recommended to pressurize 14mV
|
|
4.2V It is recommended to pressurize 28mV
|
|
*/
|
|
void set_voltage_pressure(uint8_t voltage_val) {
|
|
reg_Charger_CTL2_t.bits.VOLTAGE_PRESSURE = voltage_val;
|
|
|
|
i2c_write(IP5306_ADDRESS,Charger_CTL2,reg_Charger_CTL2_t.reg_byte);
|
|
}
|
|
|
|
/*@brief set constant current charging setting
|
|
@param value - 1:VIN end CC Constant current
|
|
0:BAT end CC Constant current
|
|
@retval None
|
|
@note Default value - 1
|
|
*/
|
|
void set_cc_loop(uint8_t current_val) {
|
|
reg_Charger_CTL3_t.bits.CHARGE_CC_LOOP = current_val;
|
|
|
|
i2c_write(IP5306_ADDRESS,Charger_CTL3,reg_Charger_CTL3_t.reg_byte);
|
|
}
|
|
|
|
/*@brief get current charging status
|
|
@param None
|
|
@retval integer representation of charging status(1 - charging is on and 0 if charging is off)
|
|
*/
|
|
uint8_t check_charging_status(void) {
|
|
reg_READ0_t.reg_byte = i2c_read(IP5306_ADDRESS,REG_READ0);
|
|
|
|
return reg_READ0_t.bits.CHARGE_ENABLE;
|
|
}
|
|
|
|
/*@brief get current battery status
|
|
@param None
|
|
@retval integer representation of battery status(1 - fully charged and 0 if still charging)
|
|
*/
|
|
uint8_t check_battery_status(void) {
|
|
reg_READ1_t.reg_byte = i2c_read(IP5306_ADDRESS,REG_READ1);
|
|
|
|
return reg_READ1_t.bits.BATTERY_STATUS;
|
|
}
|
|
|
|
/*@brief get output load level
|
|
@param None
|
|
@retval integer representation of load status(1 - light load and 0 if heavy load)
|
|
*/
|
|
uint8_t check_load_level(void) {
|
|
reg_READ2_t.reg_byte = i2c_read(IP5306_ADDRESS,REG_READ2);
|
|
|
|
return reg_READ2_t.bits.LOAD_LEVEL;
|
|
}
|
|
|
|
/*@brief detect if a short press occurred
|
|
@param None
|
|
@retval button status
|
|
@note clear this bit after reading by writing 1
|
|
*/
|
|
uint8_t short_press_detect(void) {
|
|
reg_READ3_t.reg_byte = i2c_read(IP5306_ADDRESS,REG_READ3);
|
|
|
|
return reg_READ3_t.bits.SHORT_PRESS_DETECT;
|
|
}
|
|
|
|
/*@brief detect if a long press occurred
|
|
@param None
|
|
@retval button status
|
|
@note clear this bit after reading by writing 1
|
|
*/
|
|
uint8_t long_press_detect(void) {
|
|
reg_READ3_t.reg_byte = i2c_read(IP5306_ADDRESS,REG_READ3);
|
|
|
|
return reg_READ3_t.bits.LONG_PRESS_DETECT;
|
|
}
|
|
|
|
/*@brief detect if a double press occurred
|
|
@param None
|
|
@retval button status
|
|
@note clear this bit after reading by writing 1
|
|
*/
|
|
uint8_t double_press_detect(void) {
|
|
reg_READ3_t.reg_byte = i2c_read(IP5306_ADDRESS,REG_READ3);
|
|
|
|
return reg_READ3_t.bits.DOUBLE_PRESS_DETECT;
|
|
}
|
|
|
|
uint8_t get_battery_charge(void) {
|
|
uint8_t charge = i2c_read(IP5306_ADDRESS,REG_UNDEF2);
|
|
|
|
switch (charge & 0xF0) {
|
|
case 0xF0:
|
|
return 0;
|
|
case 0xE0:
|
|
return 25;
|
|
case 0xC0:
|
|
return 50;
|
|
case 0x80:
|
|
return 75;
|
|
case 0x00:
|
|
return 100;
|
|
default:
|
|
return charge & 0xF0;
|
|
}
|
|
}
|
|
|
|
double get_battery_voltage(void) {
|
|
uint8_t low = i2c_read(IP5306_ADDRESS,BAT_VADC_DAT0);
|
|
uint8_t high = i2c_read(IP5306_ADDRESS,BAT_VADC_DAT1);
|
|
double vadc;
|
|
|
|
if ((high & 0x20) == 0x20) {
|
|
vadc = 2600 - ((~low)+(~(high & 0x1F)) * 256 + 1) * 0.26855;
|
|
} else {
|
|
vadc = 2600 + (low+high * 256) * 0.26855;
|
|
}
|
|
|
|
return vadc;
|
|
}
|
|
|
|
double get_battery_current(void) {
|
|
uint8_t low = i2c_read(IP5306_ADDRESS,BAT_IADC_DAT0);
|
|
uint8_t high = i2c_read(IP5306_ADDRESS,BAT_IADC_DAT1);
|
|
double iadc;
|
|
|
|
if ((high & 0x20) == 0x20) {
|
|
char a = ~low;
|
|
char b = (~(high & 0x1F) & 0x1F);
|
|
int c = b * 256 + a + 1;
|
|
iadc = c * 0.745985;
|
|
} else {
|
|
iadc = (high * 256 + low) * 0.745985;
|
|
}
|
|
|
|
return iadc;
|
|
}
|
|
};
|
|
|
|
|
|
#endif
|