Skip to content

added support for new pmic #665

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion boards.txt
Original file line number Diff line number Diff line change
@@ -208,7 +208,7 @@ mkrwifi1010.build.usb_product="Arduino MKR WiFi 1010"
mkrwifi1010.build.usb_manufacturer="Arduino LLC"
mkrwifi1010.build.board=SAMD_MKRWIFI1010
mkrwifi1010.build.core=arduino
mkrwifi1010.build.extra_flags=-DUSE_ARDUINO_MKR_PIN_LAYOUT -D__SAMD21G18A__ {build.usb_flags} -DUSE_BQ24195L_PMIC
mkrwifi1010.build.extra_flags=-DUSE_ARDUINO_MKR_PIN_LAYOUT -D__SAMD21G18A__ {build.usb_flags} -DUSE_BQ24195L_PMIC -DUSE_MP2629_PMIC
mkrwifi1010.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
mkrwifi1010.build.openocdscript=openocd_scripts/arduino_zero.cfg
mkrwifi1010.build.variant=mkrwifi1010
175 changes: 175 additions & 0 deletions cores/arduino/PMIC/BQ24195.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
/*
BQ24195.h - Register definitions for BQ24195/BQ24195L PMICs.
Copyright (c) 2020 Kevin P. Fleming. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#pragma once

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef union {
struct {
uint8_t IINLIM:3;
uint8_t VINDPM:4;
uint8_t EN_HIZ:1;
};
uint8_t val;
} BQ24195_REG00;

static_assert(sizeof(BQ24195_REG00) == 1, "BQ24195_REG00 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t RSVD:1;
uint8_t SYS_MIN:3;
uint8_t CHG_CONFIG_ENABLE:1;
uint8_t CHG_CONFIG_OTG:1;
uint8_t WATCHDOG_TIMER_RESET:1;
uint8_t REGISTER_RESET:1;
};
uint8_t val;
} BQ24195_REG01;

static_assert(sizeof(BQ24195_REG01) == 1, "BQ24195_REG01 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t FORCE_20PCT:1;
uint8_t RSVD:1;
uint8_t ICHG:6;
};
uint8_t val;
} BQ24195_REG02;

static_assert(sizeof(BQ24195_REG02) == 1, "BQ24195_REG02 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t ITERM:4;
uint8_t IPRECHG:4;
};
uint8_t val;
} BQ24195_REG03;

static_assert(sizeof(BQ24195_REG03) == 1, "BQ24195_REG03 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t VRECHG:1;
uint8_t BATLOWV:1;
uint8_t VREG:6;
};
uint8_t val;
} BQ24195_REG04;

static_assert(sizeof(BQ24195_REG04) == 1, "BQ24195_REG04 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t RSVD:1;
uint8_t CHG_TIMER:2;
uint8_t EN_TIMER:1;
uint8_t WATCHDOG:2;
uint8_t TERM_STAT:1;
uint8_t EN_TERM:1;
};
uint8_t val;
} BQ24195_REG05;

static_assert(sizeof(BQ24195_REG05) == 1, "BQ24195_REG05 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t VRECHG:1;
uint8_t BATLOWV:1;
uint8_t VREG:6;
};
uint8_t val;
} BQ24195_REG06;

static_assert(sizeof(BQ24195_REG06) == 1, "BQ24195_REG06 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t INT_MASK_BAT:1;
uint8_t INT_MASK_CHG:1;
uint8_t RSVD:3;
uint8_t BATFET_DISABLE:1;
uint8_t TMR2X_EN:1;
uint8_t DPDM_EN:1;
};
uint8_t val;
} BQ24195_REG07;

static_assert(sizeof(BQ24195_REG07) == 1, "BQ24195_REG07 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t VSYS_STAT:1;
uint8_t THERM_STAT:1;
uint8_t PG_STAT:1;
uint8_t DPM_STAT:1;
uint8_t CHRG_STAT:2;
uint8_t VBUS_STAT:2;
};
uint8_t val;
} BQ24195_REG08;

static_assert(sizeof(BQ24195_REG08) == 1, "BQ24195_REG08 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t NTC_FAULT:3;
uint8_t BAT_FAULT:1;
uint8_t CHRG_FAULT:2;
uint8_t RSVD:1;
uint8_t WATCHDOG_FAULT:1;
};
uint8_t val;
} BQ24195_REG09;

static_assert(sizeof(BQ24195_REG09) == 1, "BQ24195_REG09 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t DEV_REG:2;
uint8_t TS_PROFILE:1;
uint8_t PN:3;
uint8_t RSVD:2;
};
uint8_t val;
} BQ24195_REG0A;

static_assert(sizeof(BQ24195_REG0A) == 1, "BQ24195_REG0A union size is incorrect, should be 1 byte.");

#define BQ24195_ADDRESS 0x6B
#define BQ24195_REG00_ADDRESS 0x00
#define BQ24195_REG01_ADDRESS 0x01
#define BQ24195_REG02_ADDRESS 0x02
#define BQ24195_REG03_ADDRESS 0x03
#define BQ24195_REG04_ADDRESS 0x04
#define BQ24195_REG05_ADDRESS 0x05
#define BQ24195_REG06_ADDRESS 0x06
#define BQ24195_REG07_ADDRESS 0x07
#define BQ24195_REG08_ADDRESS 0x08
#define BQ24195_REG09_ADDRESS 0x09
#define BQ24195_REG0A_ADDRESS 0x0A

#ifdef __cplusplus
} // extern "C"
#endif
341 changes: 341 additions & 0 deletions cores/arduino/PMIC/MP2629.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,341 @@
/*
MP2629.h - Register definitions for MP2629/MP2629L PMICs.
Copyright (c) 2020 Kevin P. Fleming. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#pragma once

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef union {
struct {
uint8_t IIN_LIM:6;
uint8_t EN_LIM:1;
uint8_t EN_HIZ:1;
};
uint8_t val;
} MP2629_REG00;

static_assert(sizeof(MP2629_REG00) == 1, "MP2629_REG00 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t VIN_MIN:4;
uint8_t RSVD:3;
uint8_t REGISTER_RESET:1;
};
uint8_t val;
} MP2629_REG01;

static_assert(sizeof(MP2629_REG01) == 1, "MP2629_REG01 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t AICO_EN:1;
uint8_t NTC_OPTION:1;
uint8_t TJ_REG:2;
uint8_t EN_CHG_NTC:1;
uint8_t EN_OTG_NTC:1;
uint8_t NTC_TYPE:1;
uint8_t TSM_DLY:1;
};
uint8_t val;
} MP2629_REG02;

static_assert(sizeof(MP2629_REG02) == 1, "MP2629_REG02 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t IIN_DSCHG:3;
uint8_t VIN_DSCHG:3;
uint8_t ADC_RATE:1;
uint8_t ADC_START:1;
};
uint8_t val;
} MP2629_REG03;

static_assert(sizeof(MP2629_REG03) == 1, "MP2629_REG03 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t VTRACK:1;
uint8_t VSYS_MIN:3;
uint8_t CHG_CONFIG:2;
uint8_t STAT_EN:1;
uint8_t BAT_LOADEN:1;
};
uint8_t val;
} MP2629_REG04;

static_assert(sizeof(MP2629_REG04) == 1, "MP2629_REG04 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t ICC:7;
uint8_t VBATT_PRE:1;
};
uint8_t val;
} MP2629_REG05;

static_assert(sizeof(MP2629_REG05) == 1, "MP2629_REG05 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t ITERM:4;
uint8_t IPRE:4;
};
uint8_t val;
} MP2629_REG06;

static_assert(sizeof(MP2629_REG06) == 1, "MP2629_REG06 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t VRECH:1;
uint8_t VBATT_REG:7;
};
uint8_t val;
} MP2629_REG07;

static_assert(sizeof(MP2629_REG07) == 1, "MP2629_REG07 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t EN_TIMER:1;
uint8_t CHG_TMR:2;
uint8_t WATCHDOG_TIM_RST:1;
uint8_t WATCHDOG:2;
uint8_t RSVD:1;
uint8_t EN_TERM:1;
};
uint8_t val;
} MP2629_REG08;

static_assert(sizeof(MP2629_REG08) == 1, "MP2629_REG08 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t VCLAMP:3;
uint8_t RSVD:1;
uint8_t RBAT_CMP:4;
};
uint8_t val;
} MP2629_REG09;

static_assert(sizeof(MP2629_REG09) == 1, "MP2629_REG09 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t TDISC_L:2;
uint8_t TDISC_H:2;
uint8_t SYSRST_SEL:1;
uint8_t BATFET_DIS:1;
uint8_t TMR2X_EN:1;
uint8_t SW_FREQ:1;
};
uint8_t val;
} MP2629_REG0A;

static_assert(sizeof(MP2629_REG0A) == 1, "MP2629_REG0A union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t RSVD:6;
uint8_t USB_DET_EN:1;
uint8_t INT_MASK:1;
};
uint8_t val;
} MP2629_REG0B;

static_assert(sizeof(MP2629_REG0B) == 1, "MP2629_REG0B union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t VSYS_STAT:1;
uint8_t THERM_STAT:1;
uint8_t RNTC_FLOAT_STAT:1;
uint8_t CHG_STAT:2;
uint8_t VIN_STAT:3;
};
uint8_t val;
} MP2629_REG0C;

static_assert(sizeof(MP2629_REG0C) == 1, "MP2629_REG0C union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t NTC_FAULT:3;
uint8_t BAT_FAULT:1;
uint8_t THERMAL_SHUTDOWN:1;
uint8_t INPUT_FAULT:1;
uint8_t OTG_FAULT:1;
uint8_t WATCHDOG_FAULT:1;
};
uint8_t val;
} MP2629_REG0D;

static_assert(sizeof(MP2629_REG0D) == 1, "MP2629_REG0D union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t VBATT:8;
};
uint8_t val;
} MP2629_REG0E;

static_assert(sizeof(MP2629_REG0E) == 1, "MP2629_REG0E union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t VSYS:8;
};
uint8_t val;
} MP2629_REG0F;

static_assert(sizeof(MP2629_REG0F) == 1, "MP2629_REG0F union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t NTC:8;
};
uint8_t val;
} MP2629_REG10;

static_assert(sizeof(MP2629_REG10) == 1, "MP2629_REG10 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t VIN:7;
uint8_t RSVD:1;
};
uint8_t val;
} MP2629_REG11;

static_assert(sizeof(MP2629_REG11) == 1, "MP2629_REG11 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t ICHG:8;
};
uint8_t val;
} MP2629_REG12;

static_assert(sizeof(MP2629_REG12) == 1, "MP2629_REG12 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t IIN:8;
};
uint8_t val;
} MP2629_REG13;

static_assert(sizeof(MP2629_REG13) == 1, "MP2629_REG13 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t IIN_DPM:6;
uint8_t IINPPM_STAT:1;
uint8_t VINPPM_STAT:1;
};
uint8_t val;
} MP2629_REG14;

static_assert(sizeof(MP2629_REG14) == 1, "MP2629_REG14 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t RSVD:5;
uint8_t VINPPM_INT_MASK:2;
uint8_t AICO_STAT:1;
};
uint8_t val;
} MP2629_REG15;

static_assert(sizeof(MP2629_REG15) == 1, "MP2629_REG15 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t VCOLD:1;
uint8_t VCOOL:2;
uint8_t VWARM:2;
uint8_t VHOT:1;
uint8_t JEITA_ISET:1;
uint8_t JEITA_VSET:1;
};
uint8_t val;
} MP2629_REG16;

static_assert(sizeof(MP2629_REG16) == 1, "MP2629_REG16 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t RSVDL3_0:3;
uint8_t PN:3;
uint8_t RSVD7:1;
uint8_t SAFETY_TIMER:1;
};
uint8_t val;
} MP2629_REG17;

static_assert(sizeof(MP2629_REG17) == 1, "MP2629_REG17 union size is incorrect, should be 1 byte.");

typedef union {
struct {
uint8_t RSVD4_0:5;
uint8_t ADDRESS:1;
uint8_t RSVD7:1;
uint8_t IINLIM_VINMIN_RESET_EN:1;
};
uint8_t val;
} MP2629_REG18;

static_assert(sizeof(MP2629_REG18) == 1, "MP2629_REG18 union size is incorrect, should be 1 byte.");


#define MP2629_ADDRESS 0x4B
#define MP2629_REG00_ADDRESS 0x00
#define MP2629_REG01_ADDRESS 0x01
#define MP2629_REG02_ADDRESS 0x02
#define MP2629_REG03_ADDRESS 0x03
#define MP2629_REG04_ADDRESS 0x04
#define MP2629_REG05_ADDRESS 0x05
#define MP2629_REG06_ADDRESS 0x06
#define MP2629_REG07_ADDRESS 0x07
#define MP2629_REG08_ADDRESS 0x08
#define MP2629_REG09_ADDRESS 0x09
#define MP2629_REG0A_ADDRESS 0x0A
#define MP2629_REG0B_ADDRESS 0x0B
#define MP2629_REG0C_ADDRESS 0x0C
#define MP2629_REG0D_ADDRESS 0x0D
#define MP2629_REG0E_ADDRESS 0x0E
#define MP2629_REG0F_ADDRESS 0x0F
#define MP2629_REG0G_ADDRESS 0x0G
#define MP2629_REG10_ADDRESS 0x10
#define MP2629_REG11_ADDRESS 0x11
#define MP2629_REG12_ADDRESS 0x12
#define MP2629_REG13_ADDRESS 0x13
#define MP2629_REG14_ADDRESS 0x14
#define MP2629_REG15_ADDRESS 0x15
#define MP2629_REG16_ADDRESS 0x16
#define MP2629_REG17_ADDRESS 0x17
#define MP2629_REG18_ADDRESS 0x18


#ifdef __cplusplus
} // extern "C"
#endif
177 changes: 177 additions & 0 deletions cores/arduino/PMICClass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
/*
PMIC.cpp - initialization of Power Management ICs
Copyright (c) 2020 Kevin P. Fleming. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "PMICClass.h"

PMICClass::PMICClass(void) {
}

PMICClass::~PMICClass(void) {
}


void PMICClass::init(SERCOM * sercom) {
_sercom = sercom;
}

void PMICClass::setupBQ24195(bool batteryPresent, bool USBDetect) {
BQ24195_REG00 reg00;
reg00.IINLIM = _ilim; // input current limit 500 mA
reg00.VINDPM = 0x00; // input voltage limit 3.88V
reg00.EN_HIZ = 0x00; // disable

writereg(BQ24195_ADDRESS, BQ24195_REG00_ADDRESS, (reg00.val));

BQ24195_REG01 reg01;
reg01.RSVD = 0x01;
reg01.SYS_MIN = 0x05; // minimum system voltage 3.5V
reg01.CHG_CONFIG_ENABLE = (batteryPresent ? 0x01 : 0x00); // battery charge enable/disable
reg01.CHG_CONFIG_OTG = 0x00;
reg01.WATCHDOG_TIMER_RESET = 0x01; // reset watchdog timer
reg01.REGISTER_RESET = 0x00; // keep current register setting

writereg(BQ24195_ADDRESS, BQ24195_REG01_ADDRESS, (reg01.val));

BQ24195_REG05 reg05;
reg05.RSVD = 0x00;
reg05.CHG_TIMER = 0x01; // fast charge timer 8 hours
reg05.EN_TIMER = (batteryPresent ? 0x01 : 0x00); // enable/disable charge safety timer
reg05.WATCHDOG = 0x00; // disable watchdog timer to stay in host mode
reg05.TERM_STAT = 0x00; // charge termination indicator match ITERM
reg05.EN_TERM = 0x01; // enable charge termination

writereg(BQ24195_ADDRESS, BQ24195_REG05_ADDRESS, (reg05.val));

BQ24195_REG07 reg07;
reg07.INT_MASK_BAT = 0x01; // INT on battery fault
reg07.INT_MASK_CHG = 0x01; // INT on charge fault
reg07.RSVD = 0x02;
reg07.BATFET_DISABLE = (batteryPresent ? 0x00: 0x01); // battery FET enable/disable
reg07.TMR2X_EN = 0x00; // safety timer not slowed by 2X
reg07.DPDM_EN = 0x00; // D+/D- detection enable/disable

writereg(BQ24195_ADDRESS, BQ24195_REG07_ADDRESS, (reg07.val));

BQ24195_REG04 reg04;
reg04.VRECHG = 0x2C;
reg04.BATLOWV = 0x01;
reg04.VREG = 0x01;
writereg(BQ24195_ADDRESS, BQ24195_REG04_ADDRESS, (reg04.val));
}

void PMICClass::setupMP2629(bool batteryPresent) {
// disable or enable battery bat feet
MP2629_REG0A reg0A;
uint8_t byte = readFrom(MP2629_ADDRESS, MP2629_REG0A_ADDRESS);
reg0A.TDISC_L = byte & 0x03;
reg0A.TDISC_H = (byte & 0x0C) >> 2;
reg0A.SYSRST_SEL = (byte & 0x10) >> 5;
reg0A.BATFET_DIS = (batteryPresent ? 0b0 : 0b1);
reg0A.TMR2X_EN = (byte & 0x40) >> 6;
reg0A.SW_FREQ = byte >> 7;
writereg(MP2629_ADDRESS, MP2629_REG0A_ADDRESS, reg0A.val);
delay(300);

// disable watchdog timer reset
byte = readFrom(MP2629_ADDRESS, MP2629_REG08_ADDRESS);
MP2629_REG08 reg08;
reg08.EN_TIMER = byte & 0x01;
reg08.CHG_TMR = (byte & 0x06) >> 1;
reg08.WATCHDOG_TIM_RST = 0;
reg08.WATCHDOG = (byte & 0x30) >> 4;
reg08.RSVD = (byte & 0x40) >> 6;
reg08.EN_TIMER = byte >> 7;
writereg(MP2629_ADDRESS, MP2629_REG08_ADDRESS, reg08.val);

MP2629_REG0B reg0B;
reg0B.RSVD = byte & 0x3F;
reg0B.USB_DET_EN = 1;
reg0B.INT_MASK = 1;
writereg(MP2629_ADDRESS, MP2629_REG0B_ADDRESS, reg0B.val);

// set ICC
byte = readFrom(MP2629_ADDRESS, MP2629_REG05_ADDRESS);
MP2629_REG05 reg05;
reg05.ICC = 0x05;
reg05.VBATT_PRE = byte >> 7;
writereg(MP2629_ADDRESS, MP2629_REG05_ADDRESS, reg05.val);

// set the vbat voltage to 4.1 V
byte = readFrom(MP2629_ADDRESS, MP2629_REG07_ADDRESS);
MP2629_REG07 reg07;
reg07.VRECH = byte & 0x01;
reg07.VBATT_REG = 0x46;//set vbat charge threshold to 4.1 V
writereg(MP2629_ADDRESS, MP2629_REG07_ADDRESS, reg07.val);
}

bool PMICClass::isBatteryConnected() {
// reset bat feet to default value
MP2629_REG0A reg0A;
uint8_t byte = readFrom(MP2629_ADDRESS, MP2629_REG0A_ADDRESS);
reg0A.TDISC_L = byte & 0x03;
reg0A.TDISC_H = (byte & 0x0C) >> 2;
reg0A.SYSRST_SEL = (byte & 0x10) >> 5;
reg0A.BATFET_DIS = 0;
reg0A.TMR2X_EN = (byte & 0x40) >> 6;
reg0A.SW_FREQ = byte >> 7;
writereg(MP2629_ADDRESS, MP2629_REG0A_ADDRESS, reg0A.val);


MP2629_REG03 reg03;
// set MP2'S ADC in CONTINUOS acquision mode
byte = readFrom(MP2629_ADDRESS, MP2629_REG03_ADDRESS);
reg03.IIN_DSCHG = (byte & 0x07);
reg03.VIN_DSCHG = (byte & 0x56) >> 3;
reg03.ADC_RATE = 1;
reg03.ADC_START = byte >> 7;
writereg(MP2629_ADDRESS, MP2629_REG03_ADDRESS, reg03.val);
delay(10);

return readFrom(MP2629_ADDRESS, MP2629_REG12_ADDRESS) > 0;
}

bool PMICClass::isBQ24195() {
return (readFrom(BQ24195_ADDRESS, BQ24195_REG0A_ADDRESS) == 0x23);
}

void PMICClass::setIlim(uint8_t ilim){
_ilim = ilim;
}

uint8_t PMICClass::readFrom(uint8_t pmicAddress, uint8_t address) {
uint8_t readedValue = 0;

_sercom->startTransmissionWIRE(pmicAddress, WIRE_WRITE_FLAG);
_sercom->sendDataMasterWIRE(address);
_sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);

if (_sercom->startTransmissionWIRE(pmicAddress, WIRE_READ_FLAG))
{
readedValue = _sercom->readDataWIRE();
_sercom->prepareNackBitWIRE();
_sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
}
return readedValue;
}

void PMICClass::writereg(uint8_t pmicAddress, uint8_t address, uint8_t value) {
_sercom->startTransmissionWIRE(pmicAddress, WIRE_WRITE_FLAG );
_sercom->sendDataMasterWIRE(address);
_sercom->sendDataMasterWIRE(value);
_sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
}

PMICClass PMICArduino;
56 changes: 56 additions & 0 deletions cores/arduino/PMICClass.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
PMIC.h - initialization of Power Management ICs
Copyright (c) 2020 Kevin P. Fleming. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _PMIC_ARDUINO_H_
#define _PMIC_ARDUINO_H_

#include "Arduino.h"
#include "PMIC/BQ24195.h"
#include "PMIC/MP2629.h"
#include "wiring_private.h"

#define ILIM_100MA 0x00
#define ILIM_150MA 0x01
#define ILIM_500MA 0x02
#define ILIM_900MA 0x03
#define ILIM_1_2A 0x04
#define ILIM_1_5A 0x05
#define ILIM_2_0A 0x06
#define ILIM_3_0A 0x07




class PMICClass
{
public:
PMICClass(void);
~PMICClass(void);
void init(SERCOM * sercom);
void setupBQ24195(bool batteryPresent, bool USBDetect);
void setupMP2629(bool batteryPresent);
bool isBatteryConnected();
bool isBQ24195();
void setIlim(uint8_t ilim = ILIM_500MA);
private:
uint8_t readFrom(uint8_t pmicAdd, uint8_t address);
void writereg(uint8_t pmicAdd, uint8_t address, uint8_t value);
private:
SERCOM * _sercom;
uint8_t _ilim = ILIM_500MA;
};

extern PMICClass PMICArduino;
#endif
59 changes: 19 additions & 40 deletions variants/mkrwifi1010/variant.cpp
Original file line number Diff line number Diff line change
@@ -177,60 +177,39 @@ SERCOM sercom3(SERCOM3);
SERCOM sercom4(SERCOM4);
SERCOM sercom5(SERCOM5);

#if defined(USE_BQ24195L_PMIC)

#ifdef USE_BQ24195L_PMIC
#include "PMICClass.h"
#include "wiring_private.h"
#endif

#define PMIC_ADDRESS 0x6B
#define PMIC_REG01 0x01
#define PMIC_REG07 0x07
void initVariant() {

static inline void enable_battery_charging() {
#if defined(USE_BQ24195L_PMIC) or defined(USE_MP2629_PMIC)
PERIPH_WIRE.initMasterWIRE(100000);
PERIPH_WIRE.enableWIRE();
pinPeripheral(PIN_WIRE_SDA, g_APinDescription[PIN_WIRE_SDA].ulPinType);
pinPeripheral(PIN_WIRE_SCL, g_APinDescription[PIN_WIRE_SCL].ulPinType);

PERIPH_WIRE.startTransmissionWIRE( PMIC_ADDRESS, WIRE_WRITE_FLAG );
PERIPH_WIRE.sendDataMasterWIRE(PMIC_REG01);
PERIPH_WIRE.sendDataMasterWIRE(0x1B); // Charge Battery + Minimum System Voltage 3.5V
PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
PMICArduino.init(&PERIPH_WIRE);

PERIPH_WIRE.disableWIRE();
}
if(PMICArduino.isBQ24195()){// USE_BQ24195L_PMIC
pinMode(ADC_BATTERY, OUTPUT);
digitalWrite(ADC_BATTERY, LOW);
delay(10);
pinMode(ADC_BATTERY, INPUT);
delay(100);

static inline void disable_battery_fet(bool disabled) {
PERIPH_WIRE.initMasterWIRE(100000);
PERIPH_WIRE.enableWIRE();
pinPeripheral(PIN_WIRE_SDA, g_APinDescription[PIN_WIRE_SDA].ulPinType);
pinPeripheral(PIN_WIRE_SCL, g_APinDescription[PIN_WIRE_SCL].ulPinType);

PERIPH_WIRE.startTransmissionWIRE( PMIC_ADDRESS, WIRE_WRITE_FLAG );
PERIPH_WIRE.sendDataMasterWIRE(PMIC_REG07);
// No D+/D– detection + Safety timer not slowed by 2X during input DPM or thermal regulation +
// BAT fet disabled/enabled + charge and bat fault INT
PERIPH_WIRE.sendDataMasterWIRE(0x0B | (disabled ? 0x20 : 0x00));
PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
bool batteryConnected = analogRead(ADC_BATTERY) > 600;

PMICArduino.setupBQ24195(batteryConnected, false);
} else {;
bool batteryConnected = PMICArduino.isBatteryConnected();
PMICArduino.setupMP2629(batteryConnected);
}
PERIPH_WIRE.disableWIRE();
}

#endif

void initVariant() {
#if defined(USE_BQ24195L_PMIC)
pinMode(ADC_BATTERY, OUTPUT);
digitalWrite(ADC_BATTERY, LOW);
delay(10);
pinMode(ADC_BATTERY, INPUT);
delay(100);

bool batteryPresent = analogRead(ADC_BATTERY) > 600;
if (batteryPresent) {
enable_battery_charging();
}
disable_battery_fet(!batteryPresent);
#endif


// NINA - SPI boot
pinMode(NINA_GPIO0, OUTPUT);