From b8ec02f1851e838e5a5c246857e2ba95cf1ebad1 Mon Sep 17 00:00:00 2001 From: "Kevin P. Fleming" Date: Sun, 1 Nov 2020 17:39:16 -0500 Subject: [PATCH] Refactor and improve PMIC configuration * Add PMIC.h and PMIC.cpp for general PMIC support in variants. * Add BQ24195.h with register addresses and definitions for BQ24195/BQ24195L devices. * Add setupPMIC function to provide consistent initialization, including: * Disable I2C watchdog timer to keep device in 'host' mode. * Disable charging when no battery present. * Disable charging system safety timer when no battery present. * Disable battery FET when no battery present. * Enable USB D+/D- on boards where they are connected to PMIC. * Enable 2A input current limit and 3.88V input voltage limit, to enable high-speed battery charging. * Update all variants with BQ24195 devices to use setupPMIC function. Results: * STAT LED no longer blinks on devices without batteries (was caused by charging system safety timer expiration). * Charging is actually disabled on boards without batteries (previously it was left as the default, which is 'enabled' in these PMICs). * Charging speed is dramatically increased (assumes 2A USB power supply is used to power board; MKR GSM 1400 previously assumed 3A power supply). --- cores/arduino/PMIC.cpp | 79 +++++++++++++ cores/arduino/PMIC.h | 24 ++++ cores/arduino/PMIC/BQ24195.h | 178 ++++++++++++++++++++++++++++++ variants/mkrgsm1400/variant.cpp | 70 ++---------- variants/mkrnb1500/variant.cpp | 69 ++---------- variants/mkrvidor4000/variant.cpp | 56 ++++------ variants/mkrwan1300/variant.cpp | 75 +++---------- variants/mkrwifi1010/variant.cpp | 53 ++------- 8 files changed, 348 insertions(+), 256 deletions(-) create mode 100644 cores/arduino/PMIC.cpp create mode 100644 cores/arduino/PMIC.h create mode 100644 cores/arduino/PMIC/BQ24195.h diff --git a/cores/arduino/PMIC.cpp b/cores/arduino/PMIC.cpp new file mode 100644 index 000000000..3ca46a9ab --- /dev/null +++ b/cores/arduino/PMIC.cpp @@ -0,0 +1,79 @@ +/* + 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 "Arduino.h" + +#ifdef USE_BQ24195L_PMIC + +#include "PMIC/BQ24195.h" + +#include "wiring_private.h" + +void setupPMIC(SERCOM& sercom, bool batteryPresent, bool USBDetect) { + BQ24195_REG00 reg00; + reg00.IINLIM = 0b110; // input current limit 2A + reg00.VINDPM = 0b0000; // input voltage limit 3.88V + reg00.EN_HIZ = 0b0; // disable + + sercom.startTransmissionWIRE(BQ24195_ADDRESS, WIRE_WRITE_FLAG); + sercom.sendDataMasterWIRE(BQ24195_REG00_ADDRESS); + sercom.sendDataMasterWIRE(reg00.val); + sercom.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); + + BQ24195_REG01 reg01; + reg01.RSVD = 0b1; + reg01.SYS_MIN = 0b101; // minimum system voltage 3.5V + reg01.CHG_CONFIG_ENABLE = (batteryPresent ? 0b1 : 0b0); // battery charge enable/disable + reg01.CHG_CONFIG_OTG = 0b0; + reg01.WATCHDOG_TIMER_RESET = 0b1; // reset watchdog timer + reg01.REGISTER_RESET = 0b0; // keep current register setting + + sercom.startTransmissionWIRE(BQ24195_ADDRESS, WIRE_WRITE_FLAG); + sercom.sendDataMasterWIRE(BQ24195_REG01_ADDRESS); + sercom.sendDataMasterWIRE(reg01.val); + sercom.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); + + BQ24195_REG05 reg05; + reg05.RSVD = 0b0; + reg05.CHG_TIMER = 0b01; // fast charge timer 8 hours + reg05.EN_TIMER = (batteryPresent ? 0b1 : 0b0); // enable/disable charge safety timer + reg05.WATCHDOG = 0b00; // disable watchdog timer to stay in host mode + reg05.TERM_STAT = 0b0; // charge termination indicator match ITERM + reg05.EN_TERM = 0b1; // enable charge termination + + sercom.startTransmissionWIRE(BQ24195_ADDRESS, WIRE_WRITE_FLAG); + sercom.sendDataMasterWIRE(BQ24195_REG05_ADDRESS); + sercom.sendDataMasterWIRE(reg05.val); + sercom.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); + + BQ24195_REG07 reg07; + reg07.INT_MASK_BAT = 0b1; // INT on battery fault + reg07.INT_MASK_CHG = 0b1; // INT on charge fault + reg07.RSVD = 0b010; + reg07.BATFET_DISABLE = (batteryPresent ? 0b0 : 0b1); // battery FET enable/disable + reg07.TMR2X_EN = 0b0; // safety timer not slowed by 2X + reg07.DPDM_EN = (USBDetect ? 0b1 : 0b0); // D+/D- detection enable/disable + + sercom.startTransmissionWIRE(BQ24195_ADDRESS, WIRE_WRITE_FLAG); + sercom.sendDataMasterWIRE(BQ24195_REG07_ADDRESS); + sercom.sendDataMasterWIRE(reg07.val); + sercom.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); +} + +#endif diff --git a/cores/arduino/PMIC.h b/cores/arduino/PMIC.h new file mode 100644 index 000000000..c859c0f01 --- /dev/null +++ b/cores/arduino/PMIC.h @@ -0,0 +1,24 @@ +/* + 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 +*/ + +#pragma once + +#include "Arduino.h" + +extern void setupPMIC(SERCOM& sercom, bool batteryPresent, bool USBDetect); diff --git a/cores/arduino/PMIC/BQ24195.h b/cores/arduino/PMIC/BQ24195.h new file mode 100644 index 000000000..f36e5e395 --- /dev/null +++ b/cores/arduino/PMIC/BQ24195.h @@ -0,0 +1,178 @@ +/* + 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 + +#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 diff --git a/variants/mkrgsm1400/variant.cpp b/variants/mkrgsm1400/variant.cpp index 2b25934b2..d3ca1fd31 100644 --- a/variants/mkrgsm1400/variant.cpp +++ b/variants/mkrgsm1400/variant.cpp @@ -177,76 +177,28 @@ SERCOM sercom3(SERCOM3); SERCOM sercom4(SERCOM4); SERCOM sercom5(SERCOM5); -#if defined(USE_BQ24195L_PMIC) - +#ifdef USE_BQ24195L_PMIC +#include "PMIC.h" #include "wiring_private.h" - -#define PMIC_ADDRESS 0x6B -#define PMIC_REG01 0x01 -#define PMIC_REG07 0x07 - -#define PMIC_REG00 0x00 - -static inline void set_voltage_current_thresholds() { - 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_REG00); - PERIPH_WIRE.sendDataMasterWIRE(0x07); // input voltage limit = 3.88V, input current limit = 3A - PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); - - PERIPH_WIRE.disableWIRE(); -} - -static inline void enable_battery_charging() { - 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); - - PERIPH_WIRE.disableWIRE(); -} - -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); - - PERIPH_WIRE.disableWIRE(); -} - #endif void initVariant() { -#if defined(USE_BQ24195L_PMIC) +#ifdef USE_BQ24195L_PMIC pinMode(ADC_BATTERY, OUTPUT); digitalWrite(ADC_BATTERY, LOW); delay(10); pinMode(ADC_BATTERY, INPUT); delay(100); + 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); + bool batteryPresent = analogRead(ADC_BATTERY) > 600; - if (batteryPresent) { - enable_battery_charging(); - } - disable_battery_fet(!batteryPresent); - set_voltage_current_thresholds(); + setupPMIC(PERIPH_WIRE, batteryPresent, true); + + PERIPH_WIRE.disableWIRE(); #endif // put GSM modem in reset on start to conserve power if it's not used diff --git a/variants/mkrnb1500/variant.cpp b/variants/mkrnb1500/variant.cpp index 5e61669e5..45a73d4e1 100644 --- a/variants/mkrnb1500/variant.cpp +++ b/variants/mkrnb1500/variant.cpp @@ -177,75 +177,28 @@ SERCOM sercom3(SERCOM3); SERCOM sercom4(SERCOM4); SERCOM sercom5(SERCOM5); -#if defined(USE_BQ24195L_PMIC) - +#ifdef USE_BQ24195L_PMIC +#include "PMIC.h" #include "wiring_private.h" - -#define PMIC_ADDRESS 0x6B -#define PMIC_REG00 0x00 -#define PMIC_REG01 0x01 -#define PMIC_REG07 0x07 - -static inline void enable_battery_charging() { - 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); - - PERIPH_WIRE.disableWIRE(); -} - -static inline void set_voltage_current_thresholds() { - 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_REG00); - PERIPH_WIRE.sendDataMasterWIRE(0x06); // 3.880 V + 2A ILIM - PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); - - PERIPH_WIRE.disableWIRE(); -} - -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); - - PERIPH_WIRE.disableWIRE(); -} - #endif void initVariant() { -#if defined(USE_BQ24195L_PMIC) +#ifdef USE_BQ24195L_PMIC pinMode(ADC_BATTERY, OUTPUT); digitalWrite(ADC_BATTERY, LOW); delay(10); pinMode(ADC_BATTERY, INPUT); delay(100); + 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); + bool batteryPresent = analogRead(ADC_BATTERY) > 600; - if (batteryPresent) { - enable_battery_charging(); - } - disable_battery_fet(!batteryPresent); - set_voltage_current_thresholds(); + setupPMIC(PERIPH_WIRE, batteryPresent, false); + + PERIPH_WIRE.disableWIRE(); #endif // power off the module diff --git a/variants/mkrvidor4000/variant.cpp b/variants/mkrvidor4000/variant.cpp index 3a4ece488..0ad45ec9a 100644 --- a/variants/mkrvidor4000/variant.cpp +++ b/variants/mkrvidor4000/variant.cpp @@ -168,59 +168,41 @@ extern "C" { } } -#if defined(USE_BQ24195L_PMIC) - +#ifdef USE_BQ24195L_PMIC +#include "PMIC.h" #include "wiring_private.h" -#define PMIC_ADDRESS 0x6B -#define PMIC_REG00 0x00 -#define PMIC_REG01 0x01 -#define PMIC_REG07 0x07 - -static inline void enable_battery_charging() { - 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); +static inline bool is_battery_present() { + BQ24195_REG08 reg08; - bool ret = PERIPH_WIRE.startTransmissionWIRE( PMIC_ADDRESS, WIRE_WRITE_FLAG ); - if (!ret) { - return; - } - PERIPH_WIRE.sendDataMasterWIRE(PMIC_REG01); - PERIPH_WIRE.sendDataMasterWIRE(0x1B); // Charge Battery + Minimum System Voltage 3.5V + PERIPH_WIRE.startTransmissionWIRE(BQ24195_ADDRESS, WIRE_WRITE_FLAG); + PERIPH_WIRE.sendDataMasterWIRE(BQ24195_REG08_ADDRESS); PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); - PERIPH_WIRE.disableWIRE(); + PERIPH_WIRE.startTransmissionWIRE(BQ24195_ADDRESS, WIRE_READ_FLAG); + reg08.val = PERIPH_WIRE.readDataWIRE(); + PERIPH_WIRE.prepareNackBitWIRE(); + PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); + return (reg08.DPM_STAT == 0b1); } +#endif -static inline void disable_battery_fet(bool disabled) { +void initVariant() { +#ifdef USE_BQ24195L_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_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); - - PERIPH_WIRE.startTransmissionWIRE( PMIC_ADDRESS, WIRE_WRITE_FLAG ); - PERIPH_WIRE.sendDataMasterWIRE(PMIC_REG00); - PERIPH_WIRE.sendDataMasterWIRE(0x6 | 0x30); - PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); + setupPMIC(PERIPH_WIRE, true, false); + delay(100); + if (!is_battery_present()) { + setupPMIC(PERIPH_WIRE, false, false); + } PERIPH_WIRE.disableWIRE(); -} - #endif -void initVariant() { -#if defined(USE_BQ24195L_PMIC) - enable_battery_charging(); -#endif startFPGA(); } diff --git a/variants/mkrwan1300/variant.cpp b/variants/mkrwan1300/variant.cpp index 447393d06..143f2aceb 100644 --- a/variants/mkrwan1300/variant.cpp +++ b/variants/mkrwan1300/variant.cpp @@ -175,86 +175,41 @@ extern "C" { const void* g_apTCInstances[TCC_INST_NUM + TC_INST_NUM]={ TCC0, TCC1, TCC2, TC3, TC4, TC5 }; -#if defined(USE_BQ24195L_PMIC) +#ifdef USE_BQ24195L_PMIC +#include "PMIC.h" #include "wiring_private.h" -#include "delay.h" - -#define PMIC_ADDRESS 0x6B -#define PMIC_REG01 0x01 -#define PMIC_REG07 0x07 -#define PMIC_REG08 0x08 - -static inline void enable_battery_charging() { - - bool ret = PERIPH_WIRE.startTransmissionWIRE( PMIC_ADDRESS, WIRE_WRITE_FLAG ); - if (!ret) { - return; - } - PERIPH_WIRE.sendDataMasterWIRE(PMIC_REG01); - PERIPH_WIRE.sendDataMasterWIRE(0x1B); // Charge Battery + Minimum System Voltage 3.5V - PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); -} - -static inline void disable_battery_charging() { - - bool ret = PERIPH_WIRE.startTransmissionWIRE( PMIC_ADDRESS, WIRE_WRITE_FLAG ); - if (!ret) { - return; - } - PERIPH_WIRE.sendDataMasterWIRE(PMIC_REG01); - PERIPH_WIRE.sendDataMasterWIRE(0x0B); // Charge Battery + Minimum System Voltage 3.5V - PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); -} - -static inline void disable_battery_fet(bool disabled) { - - bool ret = PERIPH_WIRE.startTransmissionWIRE( PMIC_ADDRESS, WIRE_WRITE_FLAG ); - if (!ret) { - return; - } - 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); -} static inline bool is_battery_present() { + BQ24195_REG08 reg08; - bool ret = PERIPH_WIRE.startTransmissionWIRE( PMIC_ADDRESS, WIRE_WRITE_FLAG ); - if (!ret) { - return false; - } - PERIPH_WIRE.sendDataMasterWIRE(PMIC_REG08); + PERIPH_WIRE.startTransmissionWIRE(BQ24195_ADDRESS, WIRE_WRITE_FLAG); + PERIPH_WIRE.sendDataMasterWIRE(BQ24195_REG08_ADDRESS); PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); - ret = PERIPH_WIRE.startTransmissionWIRE( PMIC_ADDRESS, WIRE_READ_FLAG ); - if (!ret) { - return false; - } - uint8_t res = PERIPH_WIRE.readDataWIRE(); + PERIPH_WIRE.startTransmissionWIRE(BQ24195_ADDRESS, WIRE_READ_FLAG); + reg08.val = PERIPH_WIRE.readDataWIRE(); PERIPH_WIRE.prepareNackBitWIRE(); PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); - return ((res & 0b1000) != 0); + return (reg08.DPM_STAT == 0b1); } +#endif void initVariant() { +#ifdef USE_BQ24195L_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); - enable_battery_charging(); - //disable_battery_fet(false); + setupPMIC(PERIPH_WIRE, true, false); delay(100); - bool batteryPresent = is_battery_present(); - if (!batteryPresent) { - disable_battery_charging(); + if (!is_battery_present()) { + setupPMIC(PERIPH_WIRE, false, false); } PERIPH_WIRE.disableWIRE(); -} #endif +} // Multi-serial objects instantiation SERCOM sercom0(SERCOM0); @@ -278,4 +233,4 @@ Uart Serial2(&sercom4, PIN_SERIAL2_RX, PIN_SERIAL2_TX, PAD_SERIAL2_RX, PAD_SERIA void SERCOM4_Handler() { Serial2.IrqHandler(); -} \ No newline at end of file +} diff --git a/variants/mkrwifi1010/variant.cpp b/variants/mkrwifi1010/variant.cpp index eb146fa59..bf8303f3b 100644 --- a/variants/mkrwifi1010/variant.cpp +++ b/variants/mkrwifi1010/variant.cpp @@ -177,59 +177,28 @@ SERCOM sercom3(SERCOM3); SERCOM sercom4(SERCOM4); SERCOM sercom5(SERCOM5); -#if defined(USE_BQ24195L_PMIC) - +#ifdef USE_BQ24195L_PMIC +#include "PMIC.h" #include "wiring_private.h" - -#define PMIC_ADDRESS 0x6B -#define PMIC_REG01 0x01 -#define PMIC_REG07 0x07 - -static inline void enable_battery_charging() { - 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); - - PERIPH_WIRE.disableWIRE(); -} - -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); - - PERIPH_WIRE.disableWIRE(); -} - #endif void initVariant() { -#if defined(USE_BQ24195L_PMIC) +#ifdef USE_BQ24195L_PMIC pinMode(ADC_BATTERY, OUTPUT); digitalWrite(ADC_BATTERY, LOW); delay(10); pinMode(ADC_BATTERY, INPUT); delay(100); + 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); + bool batteryPresent = analogRead(ADC_BATTERY) > 600; - if (batteryPresent) { - enable_battery_charging(); - } - disable_battery_fet(!batteryPresent); + setupPMIC(PERIPH_WIRE, batteryPresent, false); + + PERIPH_WIRE.disableWIRE(); #endif // NINA - SPI boot