diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000..6f7fe39e4 --- /dev/null +++ b/.clang-format @@ -0,0 +1,46 @@ +BasedOnStyle: LLVM +UseTab: Never +IndentWidth: 4 +TabWidth: 2 +BreakBeforeBraces: Allman +IncludeBlocks: Regroup +ColumnLimit: 0 +AccessModifierOffset: -4 +NamespaceIndentation: All +FixNamespaceComments: true +BitFieldColonSpacingStyle: Both +AllowShortIfStatementsOnASingleLine: false +AllowShortEnumsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Inline +AllowShortNamespacesOnASingleLine: true +AllowShortLoopsOnASingleLine: true +AlignConsecutiveDeclarations: true +AlignArrayOfStructures: Left +AlignConsecutiveBitFields: + Enabled: true + AcrossEmptyLines: true + AcrossComments: true +AlignConsecutiveMacros: + Enabled: true + AcrossEmptyLines: true + AcrossComments: false +AlignConsecutiveShortCaseStatements: + Enabled: true + AcrossEmptyLines: false + AcrossComments: true + AlignCaseColons: true +AlignConsecutiveTableGenDefinitionColons: true +AlignTrailingComments: true +AlignConsecutiveAssignments: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: true +SortUsingDeclarations: LexicographicNumeric +SpaceBeforeCaseColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeCtorInitializerColon: true +SpaceBeforeJsonColon: true +IndentCaseLabels: true +IndentPPDirectives: BeforeHash +IndentExternBlock: Indent \ No newline at end of file diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 000000000..4c54e744e --- /dev/null +++ b/.clang-tidy @@ -0,0 +1 @@ +Checks: '-*,clang-analyzer-cplusplus*,llvm-header-guard' diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 000000000..f0f405ca2 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,3 @@ +3208150197b1bd422021c608f57b9b3e4e7040f9 + +1b84d09669504d4c0c6ab25678ed7c15bd610432 diff --git a/.github/workflows/buil_parallel.yml b/.github/workflows/buil_parallel.yml index e7be91806..86cd3de20 100644 --- a/.github/workflows/buil_parallel.yml +++ b/.github/workflows/buil_parallel.yml @@ -101,6 +101,13 @@ jobs: family: "ESP32", partitions: { bootloader_addr: "0x1000" }, } + - { + vendor: "CYD", + name: "CYD-2432W328R", + env: "CYD-2432W328R", + family: "ESP32", + partitions: { bootloader_addr: "0x1000" }, + } - { vendor: "CYD", name: "CYD-2432W328C(inv_colors)_and_CYD-2432S024C", diff --git a/.gitignore b/.gitignore index a4a51e4bb..368830975 100644 --- a/.gitignore +++ b/.gitignore @@ -4,8 +4,10 @@ .vscode/launch.json .vscode/extensions.json .vscode/ipch +.vscode/settings.json Bruce3_*.bin bruce.conf _*.sh tmp -ISSUES.md \ No newline at end of file +ISSUES.md +.vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json index 9aaf82792..502c32ed3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,6 @@ { - "idf.portWin": "COM4", "files.associations": { + "*.k": "kamailio", "iosfwd": "cpp", "iostream": "cpp", "array": "cpp", @@ -57,10 +57,16 @@ "iomanip": "cpp", "chrono": "cpp", "ratio": "cpp", - "*.tpp": "cpp" + "*.tpp": "cpp", + "condition_variable": "cpp", + "mutex": "cpp", + "thread": "cpp", + "esp_log.h": "c" }, "githubPullRequests.ignoredPullRequestBranches": [ "main" ], - "cmake.sourceDirectory": "C:/Projetos/Bruce/lib/M5GFX" + "yaml.schemas": { + "https://json.schemastore.org/clang-tidy.json": "file:///c%3A/Users/cardoin/Documents/Repo/Forks/Bruce/.clang-tidy" + } } \ No newline at end of file diff --git a/boards/CYD-2432S028.ini b/boards/CYD-2432S028.ini index 010819505..d98bc8910 100644 --- a/boards/CYD-2432S028.ini +++ b/boards/CYD-2432S028.ini @@ -117,7 +117,7 @@ build_flags = -DILI9341_2_DRIVER=1 -DUSE_HSPI_PORT=1 -DTFT_HEIGHT=320 - -DTFT_WIDTH=240 ;240-20 lower margin + -DTFT_WIDTH=240 -DTFT_MISO=12 -DTFT_MOSI=13 -DTFT_SCLK=14 @@ -213,21 +213,39 @@ build_flags = -DLITE_VERSION=1 +[env:CYD-2432W328R] +extends = env:CYD-2432S028 +build_flags = + ${env:CYD-2432S028.build_flags} + -DTFT_INVERSION_ON # TFT is not color inverted + -DTFT_BL=27 + # from https://github.com/pr3y/Bruce/issues/690#issuecomment-2602933450 + # uses the same driver as CYD-2432S024R, but with different calibration Data, trying same as 2432S028R + -DESP32DMA + -DTOUCH_OFFSET_ROTATION=1 + -DSPI_FREQUENCY=55000000 + -DSPI_READ_FREQUENCY=20000000 + -DSPI_TOUCH_FREQUENCY=2500000 + -DUSE_TFT_eSPI_TOUCH + -DTOUCH_CONFIG_INT_GPIO_NUM=36 + -DCYD2432W328R [env:CYD-2432S024R] # CYD-2432S024R extends = env:CYD-2432S028 build_flags = ${env:CYD-2432S028.build_flags} - ;-DTFT_INVERSION_ON TFT is not color inverted + -DTFT_INVERSION_ON # TFT is not color inverted -DTFT_BL=27 - - -DTOUCH_XPT2046_SPI - -DXPT2046_SPI_BUS_MOSI_IO_NUM=13 - -DXPT2046_SPI_BUS_MISO_IO_NUM=12 - -DXPT2046_SPI_BUS_SCLK_IO_NUM=14 - -DXPT2046_SPI_CONFIG_CS_GPIO_NUM=33 - -DXPT2046_TOUCH_CONFIG_INT_GPIO_NUM=36 + # https://github.com/Fr4nkFletcher/ESP32-Marauder-Cheap-Yellow-Display/blob/master/User_Setup_cyd24.h + -DESP32DMA + -DTOUCH_OFFSET_ROTATION=1 + -DSPI_FREQUENCY=55000000 + -DSPI_READ_FREQUENCY=20000000 + -DSPI_TOUCH_FREQUENCY=2500000 + -DUSE_TFT_eSPI_TOUCH + -DTOUCH_CONFIG_INT_GPIO_NUM=36 + -DCYD2432S024R ################################# END OF CYD MODELS #################################################### diff --git a/boards/CYD-2432S028/interface.cpp b/boards/CYD-2432S028/interface.cpp index adb4e5cad..771e0dd99 100644 --- a/boards/CYD-2432S028/interface.cpp +++ b/boards/CYD-2432S028/interface.cpp @@ -1,12 +1,19 @@ #include "interface.h" #include "core/powerSave.h" #include "core/utils.h" +#include #if defined(HAS_CAPACITIVE_TOUCH) #include "CYD28_TouchscreenC.h" #define CYD28_DISPLAY_HOR_RES_MAX 240 #define CYD28_DISPLAY_VER_RES_MAX 320 CYD28_TouchC touch(CYD28_DISPLAY_HOR_RES_MAX, CYD28_DISPLAY_VER_RES_MAX); +#elif defined(USE_TFT_eSPI_TOUCH) + #define XPT2046_CS TOUCH_CS + bool _IH_touched = false; + void IRAM_ATTR _IH_touch(void){ + _IH_touched=true; + } #else #include "CYD28_TouchscreenR.h" #define CYD28_DISPLAY_HOR_RES_MAX 320 @@ -24,20 +31,23 @@ ** Location: main.cpp ** Description: initial setup for the device ***************************************************************************************/ +SPIClass touchSPI; void _setup_gpio() { #ifndef HAS_CAPACITIVE_TOUCH // Capacitive Touchscreen uses I2C to communicate pinMode(XPT2046_CS, OUTPUT); + digitalWrite(XPT2046_CS, HIGH); #endif - //touchSPI.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS); + + #if !defined(USE_TFT_eSPI_TOUCH) // Use libraries if(!touch.begin()) { Serial.println("Touch IC not Started"); log_i("Touch IC not Started"); } else log_i("Touch IC Started"); - - #ifndef HAS_CAPACITIVE_TOUCH // Capacitive Touchscreen uses I2C to communicate - digitalWrite(XPT2046_CS, LOW); #endif - + #if defined(USE_TFT_eSPI_TOUCH) + pinMode(TOUCH_CS, OUTPUT); + attachInterrupt(TOUCH_CONFIG_INT_GPIO_NUM,_IH_touch,FALLING); + #endif } /*************************************************************************************** @@ -76,9 +86,44 @@ void _setBrightness(uint8_t brightval) { ** Handles the variables PrevPress, NextPress, SelPress, AnyKeyPress and EscPress **********************************************************************/ void InputHandler(void) { - if (touch.touched()) { //touch.tirqTouched() && + static long tmp=0; + if (millis()-tmp>200) { // I know R3CK.. I Should NOT nest if statements.. + // but it is needed to not keep SPI bus used without need, it save resources + + #if defined(USE_TFT_eSPI_TOUCH) + #if defined(CYD2432S024R) + //uint16_t calData[5] = { 481, 3053, 433, 3296, 3 }; // from https://github.com/Fr4nkFletcher/ESP32-Marauder-Cheap-Yellow-Display/blob/3eed991e9336d3e711e3eb5d6ece7ba023132fef/esp32_marauder/Display.cpp#L43 + #elif defined(CYD2432W328R) + //uint16_t calData[5] = { 350, 3465, 188, 3431, 2 }; // from https://github.com/Fr4nkFletcher/ESP32-Marauder-Cheap-Yellow-Display/blob/3eed991e9336d3e711e3eb5d6ece7ba023132fef/esp32_marauder/Display.cpp#L40 + #endif + uint16_t calData[5] = { 391, 3491, 266, 3505, 7 }; + tft.setTouch(calData); + TouchPoint t; + checkPowerSaveTime(); + + if(_IH_touched) { + NextPress=false; + PrevPress=false; + UpPress=false; + DownPress=false; + SelPress=false; + EscPress=false; + AnyKeyPress=false; + NextPagePress=false; + PrevPagePress=false; + touchPoint.pressed=false; + _IH_touched=false; + digitalWrite(TFT_CS,HIGH); + digitalWrite(TOUCH_CS,LOW); + tft.getTouch(&t.x, &t.y,50); + digitalWrite(TOUCH_CS,HIGH); + Serial.printf("Touched with Z=%d", tft.getTouchRawZ()); + #else + if(touch.touched()) { auto t = touch.getPointScaled(); t = touch.getPointScaled(); + #endif + if(bruceConfig.rotation==3) { t.y = (tftHeight+20)-t.y; t.x = tftWidth-t.x; @@ -93,6 +138,7 @@ void InputHandler(void) { t.x = t.y; t.y = (tftHeight+20)-tmp; } + Serial.printf("Touch Pressed on x=%d, y=%d\n",t.x, t.y); if(!wakeUpScreen()) AnyKeyPress = true; else goto END; @@ -103,12 +149,11 @@ void InputHandler(void) { touchPoint.pressed=true; touchHeatMap(touchPoint); + tmp=millis(); + } } END: - if(AnyKeyPress) { - long tmp=millis(); - while((millis()-tmp)<200 && (touch.touched())); - } + delay(0); } /********************************************************************* diff --git a/boards/lilygo-t-embed-cc1101.ini b/boards/lilygo-t-embed-cc1101.ini index bf1f6e175..677b7c272 100644 --- a/boards/lilygo-t-embed-cc1101.ini +++ b/boards/lilygo-t-embed-cc1101.ini @@ -18,6 +18,5 @@ build_flags = lib_deps = ${env.lib_deps} - lewisxhe/XPowersLib @0.2.6 mathertel/RotaryEncoder @1.5.3 fastled/FastLED @3.9.4 diff --git a/boards/lilygo-t-embed-cc1101/interface.cpp b/boards/lilygo-t-embed-cc1101/interface.cpp index ea2493570..34fcd2c2a 100644 --- a/boards/lilygo-t-embed-cc1101/interface.cpp +++ b/boards/lilygo-t-embed-cc1101/interface.cpp @@ -11,9 +11,9 @@ IRAM_ATTR void checkPosition(); #if defined(T_EMBED_1101) // Power handler for battery detection #include - #include + #include #include - XPowersPPM PPM; + PMIC pmic; #elif defined(T_EMBED) #include #include @@ -25,6 +25,7 @@ IRAM_ATTR void checkPosition(); #include BQ27220 bq; #endif +TwoWire* myWire = &Wire; /*************************************************************************************** ** Function name: _setup_gpio() ** Description: initial setup for the device @@ -47,22 +48,22 @@ void _setup_gpio() { pinMode(PIN_POWER_ON, OUTPUT); digitalWrite(PIN_POWER_ON, HIGH); // Power on CC1101 and LED bool pmu_ret = false; - Wire.begin(GROVE_SDA, GROVE_SCL); - pmu_ret = PPM.init(Wire, GROVE_SDA, GROVE_SCL, BQ25896_SLAVE_ADDRESS); + myWire->begin(GROVE_SDA, GROVE_SCL); + pmu_ret = pmic.init(Wire, GROVE_SDA, GROVE_SCL, BQ25896_SLAVE_ADDRESS); if(pmu_ret) { - PPM.setSysPowerDownVoltage(3300); - PPM.setInputCurrentLimit(3250); - Serial.printf("getInputCurrentLimit: %d mA\n",PPM.getInputCurrentLimit()); - PPM.disableCurrentLimitPin(); - PPM.setChargeTargetVoltage(4208); - PPM.setPrechargeCurr(64); - PPM.setChargerConstantCurr(832); - PPM.getChargerConstantCurr(); - Serial.printf("getChargerConstantCurr: %d mA\n",PPM.getChargerConstantCurr()); - PPM.enableADCMeasure(); - PPM.enableCharge(); - PPM.enableOTG(); - PPM.disableOTG(); + pmic.setSysPowerDownVoltage(3300); + pmic.setInputCurrentLimit(3250); + Serial.printf("getInputCurrentLimit: %d mA\n",pmic.getInputCurrentLimit()); + pmic.disableCurrentLimitPin(); + pmic.setChargeTargetVoltage(4208); + pmic.setPrechargeCurr(64); + pmic.setChargerConstantCurr(832); + pmic.getChargerConstantCurr(); + Serial.printf("getChargerConstantCurr: %d mA\n",pmic.getChargerConstantCurr()); + pmic.enableMeasure(HAL::PMIC::MeasureMode::CONTINUOUS); + pmic.enableCharge(); + pmic.enableOTG(); + pmic.disableOTG(); } #else pinMode(BAT_PIN,INPUT); // Battery value @@ -92,7 +93,8 @@ void _setup_gpio() { int getBattery() { int percent=0; #if defined(USE_BQ27220_VIA_I2C) - percent=bq.getChargePcnt(); + //percent=bq.getChargePcnt(); // this function runs bq.getRemainCap()/bq.getFullChargeCap().... bq.getFullChargeCap() is hardcoded int 3000. + percent=bq.getRemainCap()/10.7; // My battery is 1300mAh and bq.getRemainCap() doesn't go upper than 1083, that is why i'm dividing by 10.7 (var/1070)*100 #elif defined(T_EMBED) uint8_t _batAdcCh = ADC1_GPIO4_CHANNEL; uint8_t _batAdcUnit = 1; diff --git a/boards/lilygo-t-embed.ini b/boards/lilygo-t-embed.ini index f8c449cc2..da497cf85 100644 --- a/boards/lilygo-t-embed.ini +++ b/boards/lilygo-t-embed.ini @@ -19,6 +19,5 @@ build_flags = lib_deps = ${env.lib_deps} - lewisxhe/XPowersLib @0.2.6 mathertel/RotaryEncoder @1.5.3 fastled/FastLED @3.9.4 diff --git a/boards/m5stack-core.ini b/boards/m5stack-core.ini index 92339a88b..fdc9e9f26 100644 --- a/boards/m5stack-core.ini +++ b/boards/m5stack-core.ini @@ -124,7 +124,7 @@ build_flags = lib_deps = ${env.lib_deps} - m5stack/M5Unified @ ^0.2.2 + m5stack/M5Unified @ 0.2.2 [env:m5stack-core4mb] extends=m5stack-core_base diff --git a/boards/m5stack-core2.ini b/boards/m5stack-core2.ini index 3df42bf3a..082765847 100644 --- a/boards/m5stack-core2.ini +++ b/boards/m5stack-core2.ini @@ -128,4 +128,4 @@ build_flags = lib_deps = ${env.lib_deps} - m5stack/M5Unified @ ^0.2.2 + m5stack/M5Unified @ 0.2.2 diff --git a/boards/m5stack-cores3.ini b/boards/m5stack-cores3.ini index 8ac36d51b..a227b5975 100644 --- a/boards/m5stack-cores3.ini +++ b/boards/m5stack-cores3.ini @@ -25,5 +25,5 @@ build_flags = -DRF_RX_PINS='{{"M5 RF433R", GROVE_SCL}, {"Groove W", GROVE_SCL}, {"GROVE Y", GROVE_SDA}}' lib_deps = ${env.lib_deps} - m5stack/M5Unified @ ^0.2.2 + m5stack/M5Unified @ 0.2.2 diff --git a/boards/m5stack-cores3/interface.cpp b/boards/m5stack-cores3/interface.cpp index 9e5fbfb66..ebddd5f7d 100644 --- a/boards/m5stack-cores3/interface.cpp +++ b/boards/m5stack-cores3/interface.cpp @@ -3,6 +3,8 @@ #include "core/utils.h" #include +#include +PMIC pmic; /*************************************************************************************** ** Function name: _setup_gpio() @@ -21,7 +23,7 @@ void _setup_gpio() { ***************************************************************************************/ int getBattery() { int percent; - percent = M5.Power.getBatteryLevel(); + percent = pmic.getBatteryPercent(); return (percent < 0) ? 0 : (percent >= 100) ? 100 : percent; @@ -88,7 +90,9 @@ void InputHandler(void) { ** location: mykeyboard.cpp ** Turns off the device (or try to) **********************************************************************/ -void powerOff() { } +void powerOff() { + pmic.shutdown(); +} /********************************************************************* diff --git a/boards/m5stack-cplus1_1/interface.cpp b/boards/m5stack-cplus1_1/interface.cpp index 3c1ee81d1..45d652869 100644 --- a/boards/m5stack-cplus1_1/interface.cpp +++ b/boards/m5stack-cplus1_1/interface.cpp @@ -41,24 +41,26 @@ void _setBrightness(uint8_t brightval) { ** Handles the variables PrevPress, NextPress, SelPress, AnyKeyPress and EscPress **********************************************************************/ void InputHandler(void) { - if(digitalRead(UP_BTN)==LOW || digitalRead(SEL_BTN)==LOW || digitalRead(DW_BTN)==LOW) { + if(axp192.GetBtnPress()) { if(!wakeUpScreen()) AnyKeyPress = true; else goto END; - } - if(digitalRead(UP_BTN)==LOW) { PrevPress = true; EscPress = true; } if(digitalRead(DW_BTN)==LOW) { + if(!wakeUpScreen()) AnyKeyPress = true; + else goto END; NextPress = true; } if(digitalRead(SEL_BTN)==LOW) { + if(!wakeUpScreen()) AnyKeyPress = true; + else goto END; SelPress = true; } END: if(AnyKeyPress) { long tmp=millis(); - while((millis()-tmp)<200 && (digitalRead(UP_BTN)==LOW || digitalRead(SEL_BTN)==LOW || digitalRead(DW_BTN)==LOW)); + while((millis()-tmp)<200 && (axp192.GetBtnPress() || digitalRead(SEL_BTN)==LOW || digitalRead(DW_BTN)==LOW)); } } diff --git a/boards/pinouts/lilygo-t-display-s3.h b/boards/pinouts/lilygo-t-display-s3.h index d525df5ef..27a934951 100644 --- a/boards/pinouts/lilygo-t-display-s3.h +++ b/boards/pinouts/lilygo-t-display-s3.h @@ -87,7 +87,7 @@ static const uint8_t SCL = GROVE_SCL; // Buttons & Navigation #define BTN_ALIAS '"OK"' #define HAS_3_BUTTONS -#define SEL_BTN 1 +#define SEL_BTN 16 #define UP_BTN 0 #define DW_BTN 14 #define BK_BTN 3 diff --git a/boards/pinouts/lilygo-t-embed-cc1101.h b/boards/pinouts/lilygo-t-embed-cc1101.h index d93832858..1231dbe22 100644 --- a/boards/pinouts/lilygo-t-embed-cc1101.h +++ b/boards/pinouts/lilygo-t-embed-cc1101.h @@ -5,6 +5,10 @@ #include #include "soc/soc_caps.h" +//HAL Definitions +#define HAL_PMIC +#define PMIC_BQ25896 + // Main I2C Bus #define SPI_SS_PIN 8 #define SPI_MOSI_PIN 9 diff --git a/boards/pinouts/m5stack-cores3.h b/boards/pinouts/m5stack-cores3.h index a8d89529b..549dcc996 100644 --- a/boards/pinouts/m5stack-cores3.h +++ b/boards/pinouts/m5stack-cores3.h @@ -60,6 +60,9 @@ static const uint8_t G46 = 46; static const uint8_t ADC = 10; +#define HAL_PMIC +#define PMIC_AXP2101 + #define HAS_RTC #define USB_as_HID diff --git a/boards/pinouts/m5stack-cplus1_1.h b/boards/pinouts/m5stack-cplus1_1.h index d35bf5054..73ef107bd 100644 --- a/boards/pinouts/m5stack-cplus1_1.h +++ b/boards/pinouts/m5stack-cplus1_1.h @@ -35,4 +35,6 @@ static const uint8_t DAC2 = 26; static const uint8_t ADC1 = 35; static const uint8_t ADC2 = 36; +#define PMIC_AXP192 + #endif /* Pins_Arduino_h */ diff --git a/boards/pinouts/smoochiee-board.h b/boards/pinouts/smoochiee-board.h index 02382a26b..d649b5a66 100644 --- a/boards/pinouts/smoochiee-board.h +++ b/boards/pinouts/smoochiee-board.h @@ -1,5 +1,5 @@ -#ifndef Pins_Arduino_h -#define Pins_Arduino_h +#ifndef __SMOOCHIEE_BOARD__ +#define __SMOOCHIEE_BOARD__ #include #include "soc/soc_caps.h" @@ -46,6 +46,10 @@ static const uint8_t G46 = 46; static const uint8_t ADC1 = 7; static const uint8_t ADC2 = 8; +// HAL Definitions +#define HAL_PMIC +#define PMIC_BQ25896 + #define SERIAL_RX 2 #define SERIAL_TX 1 #define BAD_RX SERIAL_RX @@ -121,4 +125,4 @@ static const uint8_t ADC2 = 8; #define SPI_MISO_PIN 11 #define SPI_SS_PIN 43 -#endif /* Pins_Arduino_h */ +#endif /* __SMOOCHIEE_BOARD__ */ diff --git a/boards/smoochiee-board.ini b/boards/smoochiee-board.ini index cc446e277..dca845d3c 100644 --- a/boards/smoochiee-board.ini +++ b/boards/smoochiee-board.ini @@ -25,5 +25,4 @@ build_flags = -DRF_RX_PINS='{{"M5 RF433R", GROVE_SCL}, {"Groove W", GROVE_SCL}, {"GROVE Y", GROVE_SDA}, {"GPIO 1", 1}, {"GPIO 2", 2}}' lib_deps = - ${env.lib_deps} - lewisxhe/XPowersLib @0.2.6 \ No newline at end of file + ${env.lib_deps} \ No newline at end of file diff --git a/boards/smoochiee-board/interface.cpp b/boards/smoochiee-board/interface.cpp index 03f90a4ce..bc7934eb9 100644 --- a/boards/smoochiee-board/interface.cpp +++ b/boards/smoochiee-board/interface.cpp @@ -14,8 +14,8 @@ // Power handler for battery detection #include -#include -XPowersPPM PPM; +#include +PMIC pmic; void _setup_gpio() { @@ -42,21 +42,21 @@ void _setup_gpio() { bool pmu_ret = false; Wire.begin(GROVE_SDA, GROVE_SCL); - pmu_ret = PPM.init(Wire, GROVE_SDA, GROVE_SCL, BQ25896_SLAVE_ADDRESS); + pmu_ret = pmic.init(Wire, GROVE_SDA, GROVE_SCL, BQ25896_SLAVE_ADDRESS); if(pmu_ret) { - PPM.setSysPowerDownVoltage(3300); - PPM.setInputCurrentLimit(3250); - Serial.printf("getInputCurrentLimit: %d mA\n",PPM.getInputCurrentLimit()); - PPM.disableCurrentLimitPin(); - PPM.setChargeTargetVoltage(4208); - PPM.setPrechargeCurr(64); - PPM.setChargerConstantCurr(832); - PPM.getChargerConstantCurr(); - Serial.printf("getChargerConstantCurr: %d mA\n",PPM.getChargerConstantCurr()); - PPM.enableADCMeasure(); - PPM.enableCharge(); - PPM.enableOTG(); - PPM.disableOTG(); + pmic.setSysPowerDownVoltage(3300); + pmic.setInputCurrentLimit(3250); + Serial.printf("getInputCurrentLimit: %d mA\n",pmic.getInputCurrentLimit()); + pmic.disableCurrentLimitPin(); + pmic.setChargeTargetVoltage(4208); + pmic.setPrechargeCurr(64); + pmic.setChargerConstantCurr(832); + pmic.getChargerConstantCurr(); + Serial.printf("getChargerConstantCurr: %d mA\n",pmic.getChargerConstantCurr()); + pmic.enableMeasure(HAL::PMIC::MeasureMode::CONTINUOUS); + pmic.enableCharge(); + pmic.enableOTG(); + pmic.disableOTG(); } } @@ -69,7 +69,7 @@ void _setup_gpio() { ***************************************************************************************/ int getBattery() { uint8_t percent=0; - percent=(PPM.getSystemVoltage()-3300)*100/(float)(4150-3350); + percent=(pmic.getSystemVoltage()-3300)*100/(float)(4150-3350); return (percent < 0) ? 0 : (percent >= 100) ? 100 diff --git a/include/globals.h b/include/globals.h index e2724a06c..08be34bc2 100644 --- a/include/globals.h +++ b/include/globals.h @@ -159,6 +159,8 @@ extern volatile bool PrevPagePress; extern TaskHandle_t xHandle; extern inline bool check(volatile bool &btn) { + +#ifndef USE_TFT_eSPI_TOUCH if(!btn) return false; vTaskSuspend( xHandle ); btn=false; @@ -166,6 +168,15 @@ extern inline bool check(volatile bool &btn) { delay(10); vTaskResume( xHandle ); return true; +#else + + InputHandler(); + if(!btn) return false; + btn=false; + AnyKeyPress=false; + return true; + +#endif } #endif \ No newline at end of file diff --git a/lib/Bad_Usb_Lib/KeyboardLayout_en_UK.cpp b/lib/Bad_Usb_Lib/KeyboardLayout_en_UK.cpp index ba60fd730..bffc45aea 100644 --- a/lib/Bad_Usb_Lib/KeyboardLayout_en_UK.cpp +++ b/lib/Bad_Usb_Lib/KeyboardLayout_en_UK.cpp @@ -2,7 +2,7 @@ * Standard US keyboard layout. */ -#include "Keyboard_en_UK.h" +#include "KeyboardLayout.h" extern const uint8_t KeyboardLayout_en_UK[128] PROGMEM = { diff --git a/lib/Bad_Usb_Lib/Keyboard_da_DK.h b/lib/Bad_Usb_Lib/Keyboard_da_DK.h deleted file mode 100644 index d1eba61f5..000000000 --- a/lib/Bad_Usb_Lib/Keyboard_da_DK.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - Keyboard_da_DK.h - - Copyright (c) 2021, Peter John - - 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 KEYBOARD_DA_DK_h -#define KEYBOARD_DA_DK_h - -#include "HID.h" - -#if !defined(_USING_HID) - -#warning "Using legacy HID core (non pluggable)" - -#else - -//================================================================================ -//================================================================================ -// Keyboard - -// DA_DK keys -#define KEY_A_RING (136+0x2f) -#define KEY_SLASHED_O (136+0x34) -#define KEY_ASH (136+0x33) -#define KEY_UMLAUT (136+0x30) -#define KEY_ACUTE_ACC (136+0x2e) - -#endif -#endif diff --git a/lib/Bad_Usb_Lib/Keyboard_de_DE.h b/lib/Bad_Usb_Lib/Keyboard_de_DE.h deleted file mode 100644 index f1e92b218..000000000 --- a/lib/Bad_Usb_Lib/Keyboard_de_DE.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - Keyboard_de_DE.h - - Copyright (c) 2022, Edgar Bonet - - 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 KEYBOARD_DE_DE_h -#define KEYBOARD_DE_DE_h - -#include "HID.h" - -#if !defined(_USING_HID) - -#warning "Using legacy HID core (non pluggable)" - -#else - -//================================================================================ -//================================================================================ -// Keyboard - -// de_DE keys -#define KEY_CIRCUMFLEX (136+0x35) -#define KEY_ESZETT (136+0x2d) -#define KEY_ACUTE (136+0x2e) -#define KEY_U_UMLAUT (136+0x2f) -#define KEY_O_UMLAUT (136+0x33) -#define KEY_A_UMLAUT (136+0x34) - -#endif -#endif diff --git a/lib/Bad_Usb_Lib/Keyboard_en_UK.h b/lib/Bad_Usb_Lib/Keyboard_en_UK.h deleted file mode 100644 index a01cdec81..000000000 --- a/lib/Bad_Usb_Lib/Keyboard_en_UK.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - KeyboardLayout.h - - This file is not part of the public API. It is meant to be included - only in Keyboard.cpp and the keyboard layout files. Layout files map - ASCII character codes to keyboard scan codes (technically, to USB HID - Usage codes), possibly altered by the SHIFT or ALT_GR modifiers. - Non-ACSII characters (anything outside the 7-bit range NUL..DEL) are - not supported. - - == Creating your own layout == - - In order to create your own layout file, copy an existing layout that - is similar to yours, then modify it to use the correct keys. The - layout is an array in ASCII order. Each entry contains a scan code, - possibly modified by "|SHIFT" or "|ALT_GR", as in this excerpt from - the Italian layout: - - 0x35, // bslash - 0x30|ALT_GR, // ] - 0x2e|SHIFT, // ^ - - Do not change the control characters (those before scan code 0x2c, - corresponding to space). Do not attempt to grow the table past DEL. Do - not use both SHIFT and ALT_GR on the same character: this is not - supported. Unsupported characters should have 0x00 as scan code. - - For a keyboard with an ISO physical layout, use the scan codes below: - - +---+---+---+---+---+---+---+---+---+---+---+---+---+-------+ - |35 |1e |1f |20 |21 |22 |23 |24 |25 |26 |27 |2d |2e |BackSp | - +---+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-----+ - | Tab |14 |1a |08 |15 |17 |1c |18 |0c |12 |13 |2f |30 | Ret | - +-----++--++--++--++--++--++--++--++--++--++--++--++--++ | - |CapsL |04 |16 |07 |09 |0a |0b |0d |0e |0f |33 |34 |31 | | - +----+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+---+----+ - |Shi.|32 |1d |1b |06 |19 |05 |11 |10 |36 |37 |38 | Shift | - +----+---++--+-+-+---+---+---+---+---+--++---+---++----+----+ - |Ctrl|Win |Alt | |AlGr|Win |Menu|Ctrl| - +----+----+----+------------------------+----+----+----+----+ - - The ANSI layout is identical except that key 0x31 is above (rather - than next to) Return, and there is not key 0x32. - - Give a unique name to the layout array, then declare it in Keyboard.h - with a line of the form: - - extern const uint8_t KeyboardLayout_xx_YY[]; - - == Encoding details == - - All scan codes are less than 0x80, which makes bit 7 available to - signal that a modifier (Shift or AltGr) is needed to generate the - character. With only one exception, keys that are used with modifiers - have scan codes that are less than 0x40. This makes bit 6 available - to signal whether the modifier is Shift or AltGr. The exception is - 0x64, the key next next to Left Shift on the ISO layout (and absent - from the ANSI layout). We handle it by replacing its value by 0x32 in - the layout arrays. -*/ - -#include - -#define SHIFT 0x80 -#define ALT_GR 0xc0 -#define ISO_KEY 0x64 -#define ISO_REPLACEMENT 0x32 diff --git a/lib/Bad_Usb_Lib/Keyboard_es_ES.h b/lib/Bad_Usb_Lib/Keyboard_es_ES.h deleted file mode 100644 index 1d808edbc..000000000 --- a/lib/Bad_Usb_Lib/Keyboard_es_ES.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - Keyboard_es_ES.h - - Copyright (c) 2022, Edgar Bonet - - 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 KEYBOARD_ES_ES_h -#define KEYBOARD_ES_ES_h - -#include "HID.h" - -#if !defined(_USING_HID) - -#warning "Using legacy HID core (non pluggable)" - -#else - -//================================================================================ -//================================================================================ -// Keyboard - -// es_ES keys -#define KEY_MASCULINE_ORDINAL (136+0x35) -#define KEY_INVERTED_EXCLAMATION (136+0x2e) -#define KEY_GRAVE (136+0x2f) -#define KEY_N_TILDE (136+0x33) -#define KEY_ACUTE (136+0x34) -#define KEY_C_CEDILLA (136+0x31) - -#endif -#endif diff --git a/lib/Bad_Usb_Lib/Keyboard_fr_FR.h b/lib/Bad_Usb_Lib/Keyboard_fr_FR.h deleted file mode 100644 index faef422e5..000000000 --- a/lib/Bad_Usb_Lib/Keyboard_fr_FR.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - Keyboard_fr_FR.h - - Copyright (c) 2022, Edgar Bonet - - 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 KEYBOARD_FR_FR_h -#define KEYBOARD_FR_FR_h - -#include "HID.h" - -#if !defined(_USING_HID) - -#warning "Using legacy HID core (non pluggable)" - -#else - -//================================================================================ -//================================================================================ -// Keyboard - -// fr_FR keys -#define KEY_SUPERSCRIPT_TWO (136+0x35) -#define KEY_E_ACUTE (136+0x1f) -#define KEY_E_GRAVE (136+0x24) -#define KEY_C_CEDILLA (136+0x26) -#define KEY_A_GRAVE (136+0x27) -#define KEY_CIRCUMFLEX (136+0x2f) -#define KEY_U_GRAVE (136+0x34) - -#endif -#endif diff --git a/lib/Bad_Usb_Lib/Keyboard_hu_HU.h b/lib/Bad_Usb_Lib/Keyboard_hu_HU.h deleted file mode 100644 index 0d8cf44bb..000000000 --- a/lib/Bad_Usb_Lib/Keyboard_hu_HU.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - Keyboard_hu_HU.h - - Copyright (c) 2023, Barab(0x34)si Rich(0x34)rd - - 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 KEYBOARD_HU_HU_h -#define KEYBOARD_HU_HU_h - -#include "HID.h" - -#if !defined(_USING_HID) - -#warning "Using legacy HID core (non pluggable)" - -#else - -//================================================================================ -//================================================================================ -// Keyboard - -// hu_HU keys -#define KEY_O_ACUTE (136+0x2e) -#define KEY_O_UMLAUT (136+0x27) -#define KEY_O_DOUBLE_ACUTE (136+0x2f) - -#define KEY_U_ACUTE (136+0x30) -#define KEY_U_UMLAUT (136+0x2d) -#define KEY_U_DOUBLE_ACUTE (136+0x31) - -#define KEY_A_ACUTE (136+0x34) - -#define KEY_E_ACUTE (136+0x33) - -#define KEY_I_ACUTE (136+0x32) - -#endif -#endif diff --git a/lib/Bad_Usb_Lib/Keyboard_it_IT.h b/lib/Bad_Usb_Lib/Keyboard_it_IT.h deleted file mode 100644 index 7d5e3545d..000000000 --- a/lib/Bad_Usb_Lib/Keyboard_it_IT.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - Keyboard_it_IT.h - - Copyright (c) 2022, Edgar Bonet - - 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 KEYBOARD_IT_IT_h -#define KEYBOARD_IT_IT_h - -#include "HID.h" - -#if !defined(_USING_HID) - -#warning "Using legacy HID core (non pluggable)" - -#else - -//================================================================================ -//================================================================================ -// Keyboard - -// it_IT keys -#define KEY_I_GRAVE (136+0x2e) -#define KEY_E_GRAVE (136+0x2f) -#define KEY_O_GRAVE (136+0x33) -#define KEY_A_GRAVE (136+0x34) -#define KEY_U_GRAVE (136+0x31) - -#endif -#endif diff --git a/lib/Bad_Usb_Lib/Keyboard_pt_PT-BR.h b/lib/Bad_Usb_Lib/Keyboard_pt_PT-BR.h deleted file mode 100644 index 0d956c2a6..000000000 --- a/lib/Bad_Usb_Lib/Keyboard_pt_PT-BR.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - Keyboard_pt_PT.h - - Copyright (c) 2022, Edgar Bonet - - 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 KEYBOARD_PT_PT_h -#define KEYBOARD_PT_PT_h - -#include "HID.h" - -#if !defined(_USING_HID) - -#warning "Using legacy HID core (non pluggable)" - -#else - -//================================================================================ -//================================================================================ -// Keyboard - -// pt_PT keys -#define KEY_LEFT_GUILLEMET (136+0x2e) -#define KEY_ACUTE (136+0x30) -#define KEY_C_CEDILLA (136+0x33) -#define KEY_MASCULINE_ORDINAL (136+0x34) -#define KEY_TILDE (136+0x31) - -#endif -#endif diff --git a/lib/Bad_Usb_Lib/Keyboard_pt_PT.h b/lib/Bad_Usb_Lib/Keyboard_pt_PT.h deleted file mode 100644 index 0d956c2a6..000000000 --- a/lib/Bad_Usb_Lib/Keyboard_pt_PT.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - Keyboard_pt_PT.h - - Copyright (c) 2022, Edgar Bonet - - 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 KEYBOARD_PT_PT_h -#define KEYBOARD_PT_PT_h - -#include "HID.h" - -#if !defined(_USING_HID) - -#warning "Using legacy HID core (non pluggable)" - -#else - -//================================================================================ -//================================================================================ -// Keyboard - -// pt_PT keys -#define KEY_LEFT_GUILLEMET (136+0x2e) -#define KEY_ACUTE (136+0x30) -#define KEY_C_CEDILLA (136+0x33) -#define KEY_MASCULINE_ORDINAL (136+0x34) -#define KEY_TILDE (136+0x31) - -#endif -#endif diff --git a/lib/Bad_Usb_Lib/Keyboard_sv_SE.h b/lib/Bad_Usb_Lib/Keyboard_sv_SE.h deleted file mode 100644 index 7d1f42aab..000000000 --- a/lib/Bad_Usb_Lib/Keyboard_sv_SE.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - Keyboard_sv_SE.h - - Copyright (c) 2021, Peter John - - 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 KEYBOARD_SV_SE_h -#define KEYBOARD_SV_SE_h - -#include "HID.h" - -#if !defined(_USING_HID) - -#warning "Using legacy HID core (non pluggable)" - -#else - -//================================================================================ -//================================================================================ -// Keyboard - -// SV_SE keys -#define KEY_A_RING (136+0x2f) -#define KEY_A_UMLAUT (136+0x34) -#define KEY_O_UMLAUT (136+0x33) -#define KEY_UMLAUT (136+0x30) -#define KEY_ACUTE_ACC (136+0x2e) - -#endif -#endif diff --git a/lib/Bad_Usb_Lib/Keyboard_tr_TR.h b/lib/Bad_Usb_Lib/Keyboard_tr_TR.h deleted file mode 100644 index 278d24d52..000000000 --- a/lib/Bad_Usb_Lib/Keyboard_tr_TR.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - Keyboard_tr_TR.h - - Copyright (c) 2021, [Your Name] - - 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 KEYBOARD_TR_TR_h -#define KEYBOARD_TR_TR_h - -#include "HID.h" - -#if !defined(_USING_HID) - -#warning "Using legacy HID core (non pluggable)" - -#else - -//================================================================================ -//================================================================================ -// Keyboard - -// TR_TR keys -#define KEY_A_RING (136+0x2f) // ğ -#define KEY_A_UMLAUT (136+0x34) // ö -#define KEY_O_UMLAUT (136+0x33) // ü -#define KEY_UMLAUT (136+0x30) // ş -#define KEY_ACUTE_ACC (136+0x2e) // ç -#define KEY_DOTLESS_I (136+0x3a) // ı -#define KEY_DOTTED_I (136+0x3b) // İ -#define KEY_Y_DOTTED (136+0x3c) // Y (dotted) -#define KEY_Y_DOTLESS (136+0x3d) // y (dotless) - -#endif -#endif \ No newline at end of file diff --git a/lib/CYD-touch/CYD28_TouchscreenR.cpp b/lib/CYD-touch/CYD28_TouchscreenR.cpp index 827751db3..59341892f 100644 --- a/lib/CYD-touch/CYD28_TouchscreenR.cpp +++ b/lib/CYD-touch/CYD28_TouchscreenR.cpp @@ -27,9 +27,11 @@ */ #include "CYD28_TouchscreenR.h" +#include #define ISR_PREFIX IRAM_ATTR #define MSEC_THRESHOLD 3 +#define SPI_SETTING SPISettings(2000000, MSBFIRST, SPI_MODE0) static CYD28_TouchR *isrPinptr; void isrPin(void); @@ -47,6 +49,19 @@ bool CYD28_TouchR::begin() isrPinptr = this; return true; } + +bool CYD28_TouchR::begin(SPIClass *wspi) +{ + _pspi = wspi; + //_pspi->begin(); + pinMode(CYD28_TouchR_CS, OUTPUT); + digitalWrite(CYD28_TouchR_CS, HIGH); + pinMode(CYD28_TouchR_IRQ, INPUT ); + attachInterrupt(digitalPinToInterrupt(CYD28_TouchR_IRQ), isrPin, FALLING); + isrPinptr = this; + + return true; +} // ------------------------------------------------------------ ISR_PREFIX void isrPin(void) @@ -57,28 +72,33 @@ void isrPin(void) // ------------------------------------------------------------ uint8_t CYD28_TouchR::transfer(uint8_t val) { - uint8_t out = 0; - uint8_t del = _delay >> 1; - uint8_t bval = 0; - int sck = LOW; + if(_pspi==nullptr) { + uint8_t out = 0; + uint8_t del = _delay >> 1; + uint8_t bval = 0; + int sck = LOW; - int8_t bit = 8; - while (bit) - { - bit--; - digitalWrite(CYD28_TouchR_MOSI, ((val & (1 << bit)) ? HIGH : LOW)); // Write bit - wait(del); - sck ^= 1u; - digitalWrite(CYD28_TouchR_CLK, sck); - /* ... Read bit */ - bval = digitalRead(CYD28_TouchR_MISO); - out <<= 1; - out |= bval; - wait(del); - sck ^= 1u; - digitalWrite(CYD28_TouchR_CLK, sck); + int8_t bit = 8; + while (bit) + { + bit--; + digitalWrite(CYD28_TouchR_MOSI, ((val & (1 << bit)) ? HIGH : LOW)); // Write bit + wait(del); + sck ^= 1u; + digitalWrite(CYD28_TouchR_CLK, sck); + /* ... Read bit */ + bval = digitalRead(CYD28_TouchR_MISO); + out <<= 1; + out |= bval; + wait(del); + sck ^= 1u; + digitalWrite(CYD28_TouchR_CLK, sck); + } + return out; + } else { + uint8_t out =_pspi->transfer(val); + return out; } - return out; } // ------------------------------------------------------------ uint16_t CYD28_TouchR::transfer16(uint16_t data) @@ -92,11 +112,17 @@ uint16_t CYD28_TouchR::transfer16(uint16_t data) uint8_t msb; }; } in, out; - in.val = data; - out.msb = transfer(in.msb); - out.lsb = transfer(in.lsb); - return out.val; + + if(_pspi==nullptr) { + out.msb = transfer(in.msb); + out.lsb = transfer(in.lsb); + return out.val; + } else { + out.msb =_pspi->transfer(in.msb); + out.lsb =_pspi->transfer(in.lsb); + return out.val; + } } // ------------------------------------------------------------ void CYD28_TouchR::wait(uint_fast8_t del) @@ -164,6 +190,9 @@ void CYD28_TouchR::update() return; digitalWrite(CYD28_TouchR_CS, LOW); + + if(_pspi!=nullptr) _pspi->beginTransaction(SPI_SETTING); + transfer(0xB1 /* Z1 */); int16_t z1 = transfer16(0xC1 /* Z2 */) >> 3; z = z1 + 4095; @@ -180,6 +209,9 @@ void CYD28_TouchR::update() else data[0] = data[1] = data[2] = data[3] = 0; data[4] = transfer16(0xD0 /* Y */) >> 3; data[5] = transfer16(0) >> 3; + + if(_pspi!=nullptr) _pspi->endTransaction(); + digitalWrite(CYD28_TouchR_CS, HIGH); if (z < 0) z = 0; diff --git a/lib/CYD-touch/CYD28_TouchscreenR.h b/lib/CYD-touch/CYD28_TouchscreenR.h index 7fb30a827..a4bf76c42 100644 --- a/lib/CYD-touch/CYD28_TouchscreenR.h +++ b/lib/CYD-touch/CYD28_TouchscreenR.h @@ -28,7 +28,8 @@ #ifndef _CYD28_TOUCHSCREENR_H_ #define _CYD28_TOUCHSCREENR_H_ -#include "Arduino.h" +#include +#include #define CYD28_TouchR_Z_THRESH 300 #define CYD28_TouchR_Z_THRES_INT 75 @@ -69,6 +70,7 @@ class CYD28_TouchR { constexpr CYD28_TouchR(int32_t w, int32_t h) : _delay(2), sizeX_px(w), sizeY_px(h){ } bool begin(); + bool begin(SPIClass *tspi); CYD28_TS_Point getPointScaled(); CYD28_TS_Point getPointRaw(); @@ -92,6 +94,8 @@ class CYD28_TouchR { uint8_t _delay; const int32_t sizeX_px; const int32_t sizeY_px; + SPIClass *_pspi = nullptr; + }; #endif diff --git a/lib/HAL/BUS/I2C/I2C_Device.tpp b/lib/HAL/BUS/I2C/I2C_Device.tpp new file mode 100644 index 000000000..04ed17cab --- /dev/null +++ b/lib/HAL/BUS/I2C/I2C_Device.tpp @@ -0,0 +1,84 @@ +#include +#include +namespace HAL::BUS +{ + template + class I2C_Device + { + public: + int readRegister(uint8_t reg) + { + uint8_t val = 0; + return readRegister(reg, &val, 1) == -1 ? -1 : val; + } + + int writeRegister(uint8_t reg, uint8_t val) + { + return writeRegister(reg, &val, 1); + } + + int readRegister(uint8_t reg, uint8_t *buf, uint8_t length = 1) + { + if (myWire) + { + myWire->beginTransmission(myADDR); + myWire->write(reg); + if (myWire->endTransmission() != 0) + { + return -1; + } + myWire->requestFrom(myADDR, length); + return myWire->readBytes(buf, length) == length ? 0 : -1; + } + return -1; + } + + int writeRegister(uint8_t reg, uint8_t *buf, uint8_t length) + { + if (myWire) + { + myWire->beginTransmission(myADDR); + myWire->write(reg); + myWire->write(buf, length); + return (myWire->endTransmission() == 0) ? 0 : -1; + } + return -1; + } + + bool inline clrRegisterBit(uint8_t registers, uint8_t bit) + { + int val = readRegister(registers); + if (val == -1) + { + return false; + } + return writeRegister(registers, (val & (~_BV(bit)))) == 0; + } + + bool inline setRegisterBit(uint8_t registers, uint8_t bit) + { + int val = readRegister(registers); + if (val == -1) + { + return false; + } + return writeRegister(registers, (val | (_BV(bit)))) == 0; + } + + bool inline getRegisterBit(uint8_t registers, uint8_t bit) + { + int val = readRegister(registers); + if (val == -1) + { + return false; + } + return val & _BV(bit); + } + + protected: + TwoWire *myWire = NULL; + int mySDA = -1; + int mySCL = -1; + uint8_t myADDR = 0xFF; + }; +} \ No newline at end of file diff --git a/lib/HAL/BUS/SMBUS/SMBus.cpp b/lib/HAL/BUS/SMBUS/SMBus.cpp new file mode 100644 index 000000000..cfece64ec --- /dev/null +++ b/lib/HAL/BUS/SMBUS/SMBus.cpp @@ -0,0 +1,400 @@ +/* + * MIT License + * + * Copyright (c) 2017 David Antliff + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file smbus.c + * + * SMBus diagrams are represented as a chain of "piped" symbols, using the following symbols: + * + * - ADDR : the 7-bit I2C address of a bus slave. + * - S : the START condition sent by a bus master. + * - Sr : the REPEATED START condition sent by a master. + * - P : the STOP condition sent by a master. + * - Wr : bit 0 of the address byte indicating a write operation. Value is 0. + * - Rd : bit 0 of the address byte indicating a read operation. Value is 1. + * - R/W : bit 0 of the address byte, indicating a read or write operation. + * - A : ACKnowledge bit sent by a master. + * - N : Not ACKnowledge bit set by a master. + * - As : ACKnowledge bit sent by a slave. + * - Ns : Not ACKnowledge bit set by a slave. + * - DATA : data byte sent by a master. + * - DATAs : data byte sent by a slave. + */ + +// TODO: add proper error checking around all i2c functions + +#include "SMBus.h" + +#include "esp_log.h" +#include "esp_system.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include +#include +#include + +static const char *TAG = "smbus"; + +#define WRITE_BIT I2C_MASTER_WRITE +#define READ_BIT I2C_MASTER_READ +#define ACK_CHECK true +#define NO_ACK_CHECK false +#define ACK_VALUE (i2c_ack_type_t)0x0 +#define NACK_VALUE (i2c_ack_type_t)0x1 +#define MAX_BLOCK_LEN 255 // SMBus v3.0 increases this from 32 to 255 +// #define MEASURE // enable measurement and reporting of I2C transaction duration + +static bool _is_init(const smbus_info_t *smbus_info) +{ + bool ok = false; + if (smbus_info != NULL) + { + if (smbus_info->init) + { + ok = true; + } + else + { + ESP_LOGE(TAG, "smbus_info is not initialised"); + } + } + else + { + ESP_LOGE(TAG, "smbus_info is NULL"); + } + return ok; +} + +static esp_err_t _check_i2c_error(esp_err_t err) +{ + switch (err) + { + case ESP_OK : // Success + break; + case ESP_ERR_INVALID_ARG : // Parameter error + ESP_LOGE(TAG, "I2C parameter error"); + break; + case ESP_FAIL : // Sending command error, slave doesn't ACK the transfer. + ESP_LOGE(TAG, "I2C no slave ACK"); + break; + case ESP_ERR_INVALID_STATE : // I2C driver not installed or not in master mode. + ESP_LOGE(TAG, "I2C driver not installed or not master"); + break; + case ESP_ERR_TIMEOUT : // Operation timeout because the bus is busy. + ESP_LOGE(TAG, "I2C timeout"); + break; + default : + ESP_LOGE(TAG, "I2C error %d", err); + } + return err; +} + +esp_err_t _write_bytes(const smbus_info_t *smbus_info, uint8_t command, uint8_t *data, size_t len) +{ + // Protocol: [S | ADDR | Wr | As | COMMAND | As | (DATA | As){*len} | P] + esp_err_t err = ESP_FAIL; + if (_is_init(smbus_info) && data) + { + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, smbus_info->address << 1 | WRITE_BIT, ACK_CHECK); + i2c_master_write_byte(cmd, command, ACK_CHECK); + i2c_master_write(cmd, data, len, ACK_CHECK); + i2c_master_stop(cmd); +#ifdef MEASURE + uint64_t start_time = esp_timer_get_time(); +#endif + err = _check_i2c_error(i2c_master_cmd_begin(smbus_info->i2c_port, cmd, smbus_info->timeout)); +#ifdef MEASURE + ESP_LOGI(TAG, "_write_bytes: i2c_master_cmd_begin took %" PRIu64 " us", esp_timer_get_time() - start_time); +#endif + i2c_cmd_link_delete(cmd); + } + return err; +} + +esp_err_t _read_bytes(const smbus_info_t *smbus_info, uint8_t command, uint8_t *data, size_t len) +{ + // Protocol: [S | ADDR | Wr | As | COMMAND | As | Sr | ADDR | Rd | As | (DATAs | A){*len-1} | DATAs | N | P] + esp_err_t err = ESP_FAIL; + if (_is_init(smbus_info) && data) + { + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, smbus_info->address << 1 | WRITE_BIT, ACK_CHECK); + i2c_master_write_byte(cmd, command, ACK_CHECK); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, smbus_info->address << 1 | READ_BIT, ACK_CHECK); + if (len > 1) + { + i2c_master_read(cmd, data, len - 1, ACK_VALUE); + } + i2c_master_read_byte(cmd, &data[len - 1], NACK_VALUE); + i2c_master_stop(cmd); +#ifdef MEASURE + uint64_t start_time = esp_timer_get_time(); +#endif + err = _check_i2c_error(i2c_master_cmd_begin(smbus_info->i2c_port, cmd, smbus_info->timeout)); +#ifdef MEASURE + ESP_LOGI(TAG, "_read_bytes: i2c_master_cmd_begin took %" PRIu64 " us", esp_timer_get_time() - start_time); +#endif + i2c_cmd_link_delete(cmd); + } + return err; +} + +// Public API + +smbus_info_t *smbus_malloc(void) +{ + smbus_info_t *smbus_info = (smbus_info_t*)malloc(sizeof(*smbus_info)); + if (smbus_info != NULL) + { + memset(smbus_info, 0, sizeof(*smbus_info)); + ESP_LOGD(TAG, "malloc smbus_info_t %p", smbus_info); + } + else + { + ESP_LOGE(TAG, "malloc smbus_info_t failed"); + } + return smbus_info; +} + +void smbus_free(smbus_info_t **smbus_info) +{ + if (smbus_info != NULL && (*smbus_info != NULL)) + { + ESP_LOGD(TAG, "free smbus_info_t %p", *smbus_info); + free(*smbus_info); + *smbus_info = NULL; + } + else + { + ESP_LOGE(TAG, "free smbus_info_t failed"); + } +} + +esp_err_t smbus_init(smbus_info_t *smbus_info, i2c_port_t i2c_port, i2c_address_t address) +{ + if (smbus_info != NULL) + { + smbus_info->i2c_port = i2c_port; + smbus_info->address = address; + smbus_info->timeout = SMBUS_DEFAULT_TIMEOUT; + smbus_info->init = true; + } + else + { + ESP_LOGE(TAG, "smbus_info is NULL"); + return ESP_FAIL; + } + return ESP_OK; +} + +esp_err_t smbus_set_timeout(smbus_info_t *smbus_info, portBASE_TYPE timeout) +{ + esp_err_t err = ESP_FAIL; + if (_is_init(smbus_info)) + { + smbus_info->timeout = timeout; + err = ESP_OK; + } + return err; +} + +esp_err_t smbus_quick(const smbus_info_t *smbus_info, bool bit) +{ + // Protocol: [S | ADDR | R/W | As | P] + esp_err_t err = ESP_FAIL; + if (_is_init(smbus_info)) + { + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, smbus_info->address << 1 | bit, ACK_CHECK); + i2c_master_stop(cmd); + err = _check_i2c_error(i2c_master_cmd_begin(smbus_info->i2c_port, cmd, smbus_info->timeout)); + i2c_cmd_link_delete(cmd); + } + return err; +} + +esp_err_t smbus_send_byte(const smbus_info_t *smbus_info, uint8_t data) +{ + // Protocol: [S | ADDR | Wr | As | DATA | As | P] + esp_err_t err = ESP_FAIL; + if (_is_init(smbus_info)) + { + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, smbus_info->address << 1 | WRITE_BIT, ACK_CHECK); + i2c_master_write_byte(cmd, data, ACK_CHECK); + i2c_master_stop(cmd); + err = _check_i2c_error(i2c_master_cmd_begin(smbus_info->i2c_port, cmd, smbus_info->timeout)); + i2c_cmd_link_delete(cmd); + } + return err; +} + +esp_err_t smbus_receive_byte(const smbus_info_t *smbus_info, uint8_t *data) +{ + // Protocol: [S | ADDR | Rd | As | DATAs | N | P] + esp_err_t err = ESP_FAIL; + if (_is_init(smbus_info)) + { + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, smbus_info->address << 1 | READ_BIT, ACK_CHECK); + i2c_master_read_byte(cmd, data, NACK_VALUE); + i2c_master_stop(cmd); + err = _check_i2c_error(i2c_master_cmd_begin(smbus_info->i2c_port, cmd, smbus_info->timeout)); + i2c_cmd_link_delete(cmd); + } + return err; +} + +esp_err_t smbus_write_byte(const smbus_info_t *smbus_info, uint8_t command, uint8_t data) +{ + // Protocol: [S | ADDR | Wr | As | COMMAND | As | DATA | As | P] + return _write_bytes(smbus_info, command, &data, 1); +} + +esp_err_t smbus_write_word(const smbus_info_t *smbus_info, uint8_t command, uint16_t data) +{ + // Protocol: [S | ADDR | Wr | As | COMMAND | As | DATA-LOW | As | DATA-HIGH | As | P] + uint8_t temp[2] = {data & 0xff, (data >> 8) & 0xff}; + return _write_bytes(smbus_info, command, temp, 2); +} + +esp_err_t smbus_read_byte(const smbus_info_t *smbus_info, uint8_t command, uint8_t *data) +{ + // Protocol: [S | ADDR | Wr | As | COMMAND | As | Sr | ADDR | Rd | As | DATA | N | P] + return _read_bytes(smbus_info, command, data, 1); +} + +esp_err_t smbus_read_word(const smbus_info_t *smbus_info, uint8_t command, uint16_t *data) +{ + // Protocol: [S | ADDR | Wr | As | COMMAND | As | Sr | ADDR | Rd | As | DATA-LOW | A | DATA-HIGH | N | P] + esp_err_t err = ESP_FAIL; + uint8_t temp[2] = {0}; + if (data) + { + err = _read_bytes(smbus_info, command, temp, 2); + if (err == ESP_OK) + { + *data = (temp[1] << 8) + temp[0]; + } + else + { + *data = 0; + } + } + return err; +} + +esp_err_t smbus_write_block(const smbus_info_t *smbus_info, uint8_t command, uint8_t *data, uint8_t len) +{ + // Protocol: [S | ADDR | Wr | As | COMMAND | As | LEN | As | DATA-1 | As | DATA-2 | As ... | DATA-LEN | As | P] + esp_err_t err = ESP_FAIL; + if (_is_init(smbus_info) && data) + { + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, smbus_info->address << 1 | WRITE_BIT, ACK_CHECK); + i2c_master_write_byte(cmd, command, ACK_CHECK); + i2c_master_write_byte(cmd, len, ACK_CHECK); + for (size_t i = 0; i < len; ++i) + { + i2c_master_write_byte(cmd, data[i], ACK_CHECK); + } + i2c_master_stop(cmd); + err = _check_i2c_error(i2c_master_cmd_begin(smbus_info->i2c_port, cmd, smbus_info->timeout)); + i2c_cmd_link_delete(cmd); + } + return err; +} + +esp_err_t smbus_read_block(const smbus_info_t *smbus_info, uint8_t command, uint8_t *data, uint8_t *len) +{ + // Protocol: [S | ADDR | Wr | As | COMMAND | As | Sr | ADDR | Rd | As | LENs | A | DATA-1 | A | DATA-2 | A ... | DATA-LEN | N | P] + esp_err_t err = ESP_FAIL; + + if (_is_init(smbus_info) && data && len) + { + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, smbus_info->address << 1 | WRITE_BIT, ACK_CHECK); + i2c_master_write_byte(cmd, command, ACK_CHECK); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, smbus_info->address << 1 | READ_BIT, ACK_CHECK); + uint8_t slave_len = 0; + i2c_master_read_byte(cmd, &slave_len, ACK_VALUE); + err = _check_i2c_error(i2c_master_cmd_begin(smbus_info->i2c_port, cmd, smbus_info->timeout)); + i2c_cmd_link_delete(cmd); + + if (err != ESP_OK) + { + *len = 0; + return err; + } + + if (slave_len > *len) + { + ESP_LOGW(TAG, "slave data length %d exceeds data len %d bytes", slave_len, *len); + slave_len = *len; + } + + cmd = i2c_cmd_link_create(); + for (size_t i = 0; i < slave_len - 1; ++i) + { + i2c_master_read_byte(cmd, &data[i], ACK_VALUE); + } + i2c_master_read_byte(cmd, &data[slave_len - 1], NACK_VALUE); + i2c_master_stop(cmd); + err = _check_i2c_error(i2c_master_cmd_begin(smbus_info->i2c_port, cmd, smbus_info->timeout)); + i2c_cmd_link_delete(cmd); + + if (err == ESP_OK) + { + *len = slave_len; + } + else + { + *len = 0; + } + } + return err; +} + +esp_err_t smbus_i2c_write_block(const smbus_info_t *smbus_info, uint8_t command, uint8_t *data, size_t len) +{ + // Protocol: [S | ADDR | Wr | As | COMMAND | As | (DATA | As){*len} | P] + return _write_bytes(smbus_info, command, data, len); +} + +esp_err_t smbus_i2c_read_block(const smbus_info_t *smbus_info, uint8_t command, uint8_t *data, size_t len) +{ + // Protocol: [S | ADDR | Wr | As | COMMAND | As | Sr | ADDR | Rd | As | (DATAs | A){*len-1} | DATAs | N | P] + return _read_bytes(smbus_info, command, data, len); +} \ No newline at end of file diff --git a/lib/HAL/BUS/SMBUS/SMBus.h b/lib/HAL/BUS/SMBUS/SMBus.h new file mode 100644 index 000000000..ee0f53f71 --- /dev/null +++ b/lib/HAL/BUS/SMBUS/SMBus.h @@ -0,0 +1,212 @@ + +/* + * MIT License + * + * Copyright (c) 2017 David Antliff + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file smbus.h + * @brief Interface definitions for the ESP32-compatible SMBus Protocol component. + * + * This component provides structures and functions that are useful for communicating + * with SMBus-compatible I2C slave devices. + */ + +#ifndef __SMBUS__ +#define __SMBUS__ + +#include "driver/i2c.h" + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define SMBUS_DEFAULT_TIMEOUT (1000 / portTICK_RATE_MS) ///< Default transaction timeout in ticks + /** + * @brief 7-bit or 10-bit I2C slave address. + */ + typedef uint16_t i2c_address_t; + + /** + * @brief Structure containing information related to the SMBus protocol. + */ + typedef struct + { + bool init; ///< True if struct has been initialised, otherwise false + i2c_port_t i2c_port; ///< ESP-IDF I2C port number + i2c_address_t address; ///< I2C address of slave device + portBASE_TYPE timeout; ///< Number of ticks until I2C operation timeout + } smbus_info_t; + + /** + * @brief Construct a new SMBus info instance. + * New instance should be initialised before calling other functions. + * @return Pointer to new device info instance, or NULL if it cannot be created. + */ + smbus_info_t *smbus_malloc(void); + + /** + * @brief Delete an existing SMBus info instance. + * @param[in,out] smbus_info Pointer to SMBus info instance that will be freed and set to NULL. + */ + void smbus_free(smbus_info_t **smbus_info); + + /** + * @brief Initialise a SMBus info instance with the specified I2C information. + * The I2C timeout defaults to approximately 1 second. + * @param[in] smbus_info Pointer to SMBus info instance. + * @param[in] i2c_port I2C port to associate with this SMBus instance. + * @param[in] address Address of I2C slave device. + */ + esp_err_t smbus_init(smbus_info_t *smbus_info, i2c_port_t i2c_port, i2c_address_t address); + + /** + * @brief Set the I2C timeout. + * I2C transactions that do not complete within this period are considered an error. + * @param[in] smbus_info Pointer to initialised SMBus info instance. + * @param[in] timeout Number of ticks to wait until the transaction is considered in error. + * @return ESP_OK if successful, ESP_FAIL or ESP_ERR_* if an error occurred. + */ + esp_err_t smbus_set_timeout(smbus_info_t *smbus_info, portBASE_TYPE timeout); + + /** + * @brief Send a single bit to a slave device in the place of the read/write bit. + * May be used to simply turn a device function on or off, or enable or disable + * a low-power standby mode. There is no data sent or received. + * @param[in] smbus_info Pointer to initialised SMBus info instance. + * @param[in] bit Data bit to send. + * @return ESP_OK if successful, ESP_FAIL or ESP_ERR_* if an error occurred. + */ + esp_err_t smbus_quick(const smbus_info_t *smbus_info, bool bit); + + /** + * @brief Send a single byte to a slave device. + * @param[in] smbus_info Pointer to initialised SMBus info instance. + * @param[in] data Data byte to send to slave. + * @return ESP_OK if successful, ESP_FAIL or ESP_ERR_* if an error occurred. + */ + esp_err_t smbus_send_byte(const smbus_info_t *smbus_info, uint8_t data); + + /** + * @brief Receive a single byte from a slave device. + * @param[in] smbus_info Pointer to initialised SMBus info instance. + * @param[out] data Data byte received from slave. + * @return ESP_OK if successful, ESP_FAIL or ESP_ERR_* if an error occurred. + */ + esp_err_t smbus_receive_byte(const smbus_info_t *smbus_info, uint8_t *data); + + /** + * @brief Write a single byte to a slave device with a command code. + * @param[in] smbus_info Pointer to initialised SMBus info instance. + * @param[in] command Device-specific command byte. + * @param[in] data Data byte to send to slave. + * @return ESP_OK if successful, ESP_FAIL or ESP_ERR_* if an error occurred. + */ + esp_err_t smbus_write_byte(const smbus_info_t *smbus_info, uint8_t command, uint8_t data); + + /** + * @brief Write a single word (two bytes) to a slave device with a command code. + * The least significant byte is transmitted first. + * @param[in] smbus_info Pointer to initialised SMBus info instance. + * @param[in] command Device-specific command byte. + * @param[in] data Data word to send to slave. + * @return ESP_OK if successful, ESP_FAIL or ESP_ERR_* if an error occurred. + */ + esp_err_t smbus_write_word(const smbus_info_t *smbus_info, uint8_t command, uint16_t data); + + /** + * @brief Read a single byte from a slave device with a command code. + * @param[in] smbus_info Pointer to initialised SMBus info instance. + * @param[in] command Device-specific command byte. + * @param[out] data Data byte received from slave. + * @return ESP_OK if successful, ESP_FAIL or ESP_ERR_* if an error occurred. + */ + esp_err_t smbus_read_byte(const smbus_info_t *smbus_info, uint8_t command, uint8_t *data); + + /** + * @brief Read a single word (two bytes) from a slave device with a command code. + * The first byte received is the least significant byte. + * @param[in] smbus_info Pointer to initialised SMBus info instance. + * @param[in] command Device-specific command byte. + * @param[out] data Data byte received from slave. + * @return ESP_OK if successful, ESP_FAIL or ESP_ERR_* if an error occurred. + */ + esp_err_t smbus_read_word(const smbus_info_t *smbus_info, uint8_t command, uint16_t *data); + + /** + * @brief Write up to 255 bytes to a slave device with a command code. + * This uses a byte count to negotiate the length of the transaction. + * The first byte in the data array is transmitted first. + * @param[in] smbus_info Pointer to initialised SMBus info instance. + * @param[in] command Device-specific command byte. + * @param[in] data Data bytes to send to slave. + * @param[in] len Number of bytes to send to slave. + * @return ESP_OK if successful, ESP_FAIL or ESP_ERR_* if an error occurred. + */ + esp_err_t smbus_write_block(const smbus_info_t *smbus_info, uint8_t command, uint8_t *data, uint8_t len); + + /** + * @brief Read up to 255 bytes from a slave device with a command code. + * This uses a byte count to negotiate the length of the transaction. + * The first byte received is placed in the first array location. + * @param[in] smbus_info Pointer to initialised SMBus info instance. + * @param[in] command Device-specific command byte. + * @param[out] data Data bytes received from slave. + * @param[in/out] len Size of data array, and number of bytes actually received. + * @return ESP_OK if successful, ESP_FAIL or ESP_ERR_* if an error occurred. + */ + esp_err_t smbus_read_block(const smbus_info_t *smbus_info, uint8_t command, uint8_t *data, uint8_t *len); + + /** + * @brief Write bytes to a slave device with a command code. + * No byte count is used - the transaction lasts as long as the master requires. + * The first byte in the data array is transmitted first. + * This operation is not defined by the SMBus specification. + * @param[in] smbus_info Pointer to initialised SMBus info instance. + * @param[in] command Device-specific command byte. + * @param[in] data Data bytes to send to slave. + * @param[in] len Number of bytes to send to slave. + * @return ESP_OK if successful, ESP_FAIL or ESP_ERR_* if an error occurred. + */ + esp_err_t smbus_i2c_write_block(const smbus_info_t *smbus_info, uint8_t command, uint8_t *data, size_t len); + + /** + * @brief Read bytes from a slave device with a command code (combined format). + * No byte count is used - the transaction lasts as long as the master requires. + * The first byte received is placed in the first array location. + * This operation is not defined by the SMBus specification. + * @param[in] smbus_info Pointer to initialised SMBus info instance. + * @param[in] command Device-specific command byte. + * @param[out] data Data bytes received from slave. + * @param[in/out] len Size of data array. If the slave fails to provide sufficient bytes, ESP_ERR_TIMEOUT will be returned. + * @return ESP_OK if successful, ESP_FAIL or ESP_ERR_* if an error occurred. + */ + esp_err_t smbus_i2c_read_block(const smbus_info_t *smbus_info, uint8_t command, uint8_t *data, size_t len); + +#ifdef __cplusplus +} +#endif + +#endif /* __SMBUS__ */ diff --git a/lib/HAL/BUS/THREEWIRE/ThreeWire.tpp b/lib/HAL/BUS/THREEWIRE/ThreeWire.tpp new file mode 100644 index 000000000..38fc6274f --- /dev/null +++ b/lib/HAL/BUS/THREEWIRE/ThreeWire.tpp @@ -0,0 +1,137 @@ +/*------------------------------------------------------------------------- +RTC library + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/Rtc) + +------------------------------------------------------------------------- +This file is part of the Makuna/Rtc library. + +Rtc 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 3 of +the License, or (at your option) any later version. + +Rtc 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 Rtc. If not, see +. +-------------------------------------------------------------------------*/ + +#include + +#pragma once + +// ThreeWire command Read/Write flag +const uint8_t THREEWIRE_READFLAG = 0x01; + +class ThreeWire +{ +public: + ThreeWire(uint8_t ioPin, uint8_t clkPin, uint8_t cePin) + : _ioPin(ioPin), + _clkPin(clkPin), + _cePin(cePin) + { + } + + void begin() + { + resetPins(); + } + + void end() + { + resetPins(); + } + + void beginTransmission(uint8_t command) + { + digitalWrite(_cePin, LOW); // default, not enabled + pinMode(_cePin, OUTPUT); + + digitalWrite(_clkPin, LOW); // default, clock low + pinMode(_clkPin, OUTPUT); + + pinMode(_ioPin, OUTPUT); + + digitalWrite(_cePin, HIGH); // start the session + delayMicroseconds(4); // tCC = 4us + + write(command, (command & THREEWIRE_READFLAG) == THREEWIRE_READFLAG); + } + + void endTransmission() + { + digitalWrite(_cePin, LOW); + delayMicroseconds(4); // tCWH = 4us + } + + void write(uint8_t value, bool isDataRequestCommand = false) + { + for (uint8_t bit = 0; bit < 8; bit++) + { + digitalWrite(_ioPin, value & 0x01); + delayMicroseconds(1); // tDC = 200ns + + // clock up, data is read by DS1302 + digitalWrite(_clkPin, HIGH); + delayMicroseconds(1); // tCH = 1000ns, tCDH = 800ns + + // for the last bit before a read + // Set IO line for input before the clock down + if (bit == 7 && isDataRequestCommand) + { + pinMode(_ioPin, INPUT); + } + + digitalWrite(_clkPin, LOW); + delayMicroseconds(1); // tCL=1000ns, tCDD=800ns + + value >>= 1; + } + } + + uint8_t read() + { + uint8_t value = 0; + + for (uint8_t bit = 0; bit < 8; bit++) + { + // first bit is present on io pin, so only clock the other + // bits + value |= (digitalRead(_ioPin) << bit); + + // Clock up, prepare for next + digitalWrite(_clkPin, HIGH); + delayMicroseconds(1); + + // Clock down, value is ready after some time. + digitalWrite(_clkPin, LOW); + delayMicroseconds(1); // tCL=1000ns, tCDD=800ns + } + + return value; + } + +private: + const uint8_t _ioPin; + const uint8_t _clkPin; + const uint8_t _cePin; + + void resetPins() + { + // just making sure they are in a default low power use state + // as required state is set when transmissions are started + // three wire devices have internal pull downs so they will be low + pinMode(_clkPin, INPUT); + pinMode(_ioPin, INPUT); + pinMode(_cePin, INPUT); + } +}; \ No newline at end of file diff --git a/lib/HAL/FUEL/DATASHEETS/BQ7220.pdf b/lib/HAL/FUEL/DATASHEETS/BQ7220.pdf new file mode 100644 index 000000000..7e52c21f0 Binary files /dev/null and b/lib/HAL/FUEL/DATASHEETS/BQ7220.pdf differ diff --git a/lib/HAL/FUEL/DRIVER/BQ7220.tpp b/lib/HAL/FUEL/DRIVER/BQ7220.tpp new file mode 100644 index 000000000..545ed8297 --- /dev/null +++ b/lib/HAL/FUEL/DRIVER/BQ7220.tpp @@ -0,0 +1,36 @@ +#include "../REG/BQ7220.hpp" +#include +namespace HAL::FUEL +{ + class BQ27220 + { + public: + BQ27220(); + bool unseal(); + bool seal(); + uint16_t getTemp(); + uint16_t getBatterySt(void); + bool getIsCharging(void); + uint16_t getRemainCap(); + uint16_t getTimeToEmpty(); + uint16_t getFullChargeCap(void); + uint16_t getChargePcnt(void); + uint16_t getAvgPower(void); + uint16_t getStandbyCur(void); + uint16_t getVolt(VOLT_MODE type); + int16_t getCurr(CURR_MODE type); + uint16_t getId(); + + private: + TwoWire *wire; + uint8_t addr; + int scl; + int sda; + union battery_state bat_st; + bool i2cReadBytes(uint8_t subAddress, uint8_t *dest, uint8_t count); + bool i2cWriteBytes(uint8_t subAddress, uint8_t *src, uint8_t count); + uint16_t readWord(uint16_t subAddress); + uint16_t readCtrlWord(uint16_t fun); + uint16_t writeCtrlWord(uint16_t fun); + }; +} \ No newline at end of file diff --git a/lib/HAL/FUEL/REG/BQ7220.hpp b/lib/HAL/FUEL/REG/BQ7220.hpp new file mode 100644 index 000000000..3ed1c1d5e --- /dev/null +++ b/lib/HAL/FUEL/REG/BQ7220.hpp @@ -0,0 +1,122 @@ +#ifndef __BQ7220__ +#define __BQ7220__ + +#define BQ27220_I2C_ADDRESS 0x55 // device addr +#define BQ27220_I2C_SDA +#define BQ27220_I2C_SCL +#define BQ27220_DEVICE_ID 0x0220 // device id + +// commands +#define BQ27220_COMMAND_CONTROL 0X00 +#define BQ27220_COMMAND_TEMP 0X06 +#define BQ27220_COMMAND_BATTERY_ST 0X0A +#define BQ27220_COMMAND_VOLT 0X08 +#define BQ27220_COMMAND_BAT_STA 0X0A +#define BQ27220_COMMAND_CURR 0X0C +#define BQ27220_COMMAND_REMAIN_CAPACITY 0X10 +#define BQ27220_COMMAND_FCHG_CAPATICY 0X12 +#define BQ27220_COMMAND_AVG_CURR 0x14 +#define BQ27220_COMMAND_TTE 0X16 +#define BQ27220_COMMAND_TTF 0X18 +#define BQ27220_COMMAND_STANDBY_CURR 0X1A +#define BQ27220_COMMAND_STTE 0X1C +#define BQ27220_COMMAND_MAX_LOAD_CURR 0x1E +#define BQ27220_COMMAND_MAX_LOAD_TTE 0x20 +#define BQ27220_COMMAND_RAW_COULOMB_CNT 0x22 +#define BQ27220_COMMAND_AVG_PWR 0x24 +#define BQ27220_COMMAND_INT_TEMP 0x28 +#define BQ27220_COMMAND_STATE_CHARGE 0X2C +#define BQ27220_COMMAND_STATE_HEALTH 0X2E +#define BQ27220_COMMAND_CHARGING_VOLT 0X30 +#define BQ27220_COMMAND_CHARGING_CURR 0X32 +#define BQ27220_COMMAND_ANALOG_CURR 0x79 +#define BQ27220_COMMAND_RAW_CURR 0X7A +#define BQ27220_COMMAND_RAW_VOLT 0X7C +#define BQ27220_COMMAND_RAW_TEMP 0x7E + +#define BQ27220_CONTROL_CONTROL_STATUS 0x0000 +#define BQ27220_CONTROL_DEVICE_NUMBER 0x0001 +#define BQ27220_CONTROL_FW_VERSION 0x0002 +#define BQ27220_CONTROL_HW_VERSION 0x0003 +#define BQ27220_CONTROL_BOARD_OFFSET 0x0009 +#define BQ27220_CONTROL_CC_OFFSET 0x000A +#define BQ27220_CONTROL_CC_OFFSET_SAVE 0x000B +#define BQ27220_CONTROL_OCV_CMD 0x000C +#define BQ27220_CONTROL_BAT_INSERT 0x000D +#define BQ27220_CONTROL_BAT_REMOVE 0x000E +#define BQ27220_CONTROL_SET_SNOOZE 0x0013 +#define BQ27220_CONTROL_CLEAR_SNOOZE 0x0014 +#define BQ27220_CONTROL_SET_PROFILE_1 0x0015 +#define BQ27220_CONTROL_SET_PROFILE_2 0x0016 +#define BQ27220_CONTROL_SET_PROFILE_3 0x0017 +#define BQ27220_CONTROL_SET_PROFILE_4 0x0018 +#define BQ27220_CONTROL_SET_PROFILE_5 0x0019 +#define BQ27220_CONTROL_SET_PROFILE_6 0x001A +#define BQ27220_CONTROL_CAL_TOGGLE 0x002D +#define BQ27220_CONTROL_SEALED 0x0030 +#define BQ27220_CONTROL_RESET 0x0041 +#define BQ27220_CONTROL_OERATION_STATUS 0x0054 +#define BQ27220_CONTROL_GAUGING_STATUS 0x0056 +#define BQ27220_CONTROL_EXIT_CAL 0x0080 +#define BQ27220_CONTROL_ENTER_CAL 0x0081 +#define BQ27220_CONTROL_ENTER_CFG_UPDATE 0x0090 +#define BQ27220_CONTROL_EXIT_CFG_UPDATE_REINIT 0x0091 +#define BQ27220_CONTROL_EXIT_CFG_UPDATE 0x0092 +#define BQ27220_CONTROL_RETURN_TO_ROM 0x0F00 + +#define BQ27220_UNSEAL_KEY1 0x0414 +#define BQ27220_UNSEAL_KEY2 0x3672 +#define BQ27220_SUPER_KEY 0xffff + +#include +namespace HAL::FUEL +{ + typedef enum OP_STATUS + { + SEALED = 0b11, + UNSEALED = 0b10, + FULL = 0b01, + }; + + enum CURR_MODE + { + CURR_RAW, + CURR_INSTANT, + CURR_STANDBY, + CURR_CHARGING, + CURR_AVERAGE, + }; + + enum VOLT_MODE + { + VOLT, + VOLT_CHARGING, + VOLT_RWA + }; + + union battery_state + { + struct __st + { + uint16_t DSG : 1; + uint16_t SYSDWN : 1; + uint16_t TDA : 1; + uint16_t BATTPRES : 1; + uint16_t AUTH_GD : 1; + uint16_t OCVGD : 1; + uint16_t TCA : 1; + uint16_t RSVD : 1; + uint16_t CHGING : 1; + uint16_t FC : 1; + uint16_t OTD : 1; + uint16_t OTC : 1; + uint16_t SLEEP : 1; + uint16_t OCVFALL : 1; + uint16_t OCVCOMP : 1; + uint16_t FD : 1; + } st; + uint16_t full; + }; +} + +#endif /* __BQ7220__ */ diff --git a/lib/HAL/HAL.hpp b/lib/HAL/HAL.hpp new file mode 100644 index 000000000..a5a94853b --- /dev/null +++ b/lib/HAL/HAL.hpp @@ -0,0 +1,12 @@ +#ifndef __HAL__ +#define __HAL__ + +#ifdef HAL_PMIC +#include "PMIC/PMIC.h" +#endif + +#ifdef HAL_RTC +#include "RTC/RTC.h" +#endif + +#endif /* __HAL__ */ diff --git a/lib/HAL/NOTES.md b/lib/HAL/NOTES.md new file mode 100644 index 000000000..e69de29bb diff --git a/lib/HAL/PMIC/DATASHEETS/AXP192.pdf b/lib/HAL/PMIC/DATASHEETS/AXP192.pdf new file mode 100644 index 000000000..80dfbf5ac Binary files /dev/null and b/lib/HAL/PMIC/DATASHEETS/AXP192.pdf differ diff --git a/lib/HAL/PMIC/DATASHEETS/AXP202.pdf b/lib/HAL/PMIC/DATASHEETS/AXP202.pdf new file mode 100644 index 000000000..64edb421d Binary files /dev/null and b/lib/HAL/PMIC/DATASHEETS/AXP202.pdf differ diff --git a/lib/HAL/PMIC/DATASHEETS/AXP209.pdf b/lib/HAL/PMIC/DATASHEETS/AXP209.pdf new file mode 100644 index 000000000..0095f4527 Binary files /dev/null and b/lib/HAL/PMIC/DATASHEETS/AXP209.pdf differ diff --git a/lib/HAL/PMIC/DATASHEETS/AXP2101.pdf b/lib/HAL/PMIC/DATASHEETS/AXP2101.pdf new file mode 100644 index 000000000..202df83fc Binary files /dev/null and b/lib/HAL/PMIC/DATASHEETS/AXP2101.pdf differ diff --git a/lib/HAL/PMIC/DATASHEETS/AXP223.pdf b/lib/HAL/PMIC/DATASHEETS/AXP223.pdf new file mode 100644 index 000000000..56bcbc142 Binary files /dev/null and b/lib/HAL/PMIC/DATASHEETS/AXP223.pdf differ diff --git a/lib/HAL/PMIC/DATASHEETS/BQ25896.pdf b/lib/HAL/PMIC/DATASHEETS/BQ25896.pdf new file mode 100644 index 000000000..106e5e403 Binary files /dev/null and b/lib/HAL/PMIC/DATASHEETS/BQ25896.pdf differ diff --git a/lib/HAL/PMIC/DATASHEETS/SY6970.pdf b/lib/HAL/PMIC/DATASHEETS/SY6970.pdf new file mode 100644 index 000000000..4bf3c1727 Binary files /dev/null and b/lib/HAL/PMIC/DATASHEETS/SY6970.pdf differ diff --git a/lib/HAL/PMIC/DRIVER/AXP173.tpp b/lib/HAL/PMIC/DRIVER/AXP173.tpp new file mode 100644 index 000000000..e69de29bb diff --git a/lib/HAL/PMIC/DRIVER/AXP192.tpp b/lib/HAL/PMIC/DRIVER/AXP192.tpp new file mode 100644 index 000000000..8ff0193a3 --- /dev/null +++ b/lib/HAL/PMIC/DRIVER/AXP192.tpp @@ -0,0 +1,1962 @@ +#include "../REG/AXP192.hpp" +#include "../IMPL/XPOWERS.tpp" +namespace HAL::PMIC +{ + class AXP192 : public XPOWERS + { + friend class Base; + + public: + AXP192(TwoWire &w, int sda = SDA, int scl = SCL, uint8_t addr = AXP192_SLAVE_ADDRESS) + { + myWire = &w; + mySDA = sda; + mySCL = scl; + myADDR = addr; + } + + AXP192() + { + myWire = &Wire; + mySDA = SDA; + mySCL = SCL; + myADDR = AXP192_SLAVE_ADDRESS; + } + + ~AXP192() + { + log_i("~XPowersAXP192"); + end(); + } + + bool init(TwoWire &w, int sda = SDA, int scl = SCL, uint8_t addr = AXP192_SLAVE_ADDRESS) + { + myWire = &w; + mySDA = sda; + mySCL = scl; + myADDR = addr; + return begin(); + } + + bool init() + { + return begin(); + } + + void deinit() + { + end(); + } + + uint16_t status() + { + return readRegister(AXP192_STATUS); + } + + bool isAcinVbusStart() + { + return getRegisterBit(AXP192_STATUS, 0); + } + + bool isDischarge() + { + return !getRegisterBit(AXP192_STATUS, 2); + } + + bool isVbusIn(void) + { + return getRegisterBit(AXP192_STATUS, 5); + } + + bool isAcinEfficient() + { + return getRegisterBit(AXP192_STATUS, 6); + } + + bool isAcinIn() + { + return getRegisterBit(AXP192_STATUS, 7); + } + + bool isOverTemperature() + { + return getRegisterBit(AXP192_MODE_CHGSTATUS, 7); + } + + bool isCharging(void) + { + return getRegisterBit(AXP192_MODE_CHGSTATUS, 6); + } + + bool isBatteryConnect(void) + { + return getRegisterBit(AXP192_MODE_CHGSTATUS, 5); + } + + bool isBattInActiveMode() + { + return getRegisterBit(AXP192_MODE_CHGSTATUS, 3); + } + + bool isChargeCurrLessPreset() + { + return getRegisterBit(AXP192_MODE_CHGSTATUS, 2); + } + + void enableVbusVoltageLimit() + { + setRegisterBit(AXP192_IPS_SET, 6); + } + + void disableVbusVoltageLimit() + { + clrRegisterBit(AXP192_IPS_SET, 6); + } + + /** + * @brief Set VBUS Voltage Input Limit. + * @param opt: View the related chip type pmic_vbus_vol_limit enumeration + * parameters in "XPowersParams.hpp" + */ + void setVbusVoltageLimit(pmic_vbus_vol_limit opt) + { + int val = readRegister(AXP192_IPS_SET); + if (val == -1) + return; + val &= 0xC7; + writeRegister(AXP192_IPS_SET, val | (opt << 3)); + } + + /** + * @brief Get VBUS Voltage Input Limit. + * @retval View the related chip type pmic_vbus_vol_limit enumeration + * parameters in "XPowersParams.hpp" + */ + pmic_vbus_vol_limit getVbusVoltageLimit(void) + { + int val = (readRegister(AXP192_IPS_SET) >> 3) & 0x7; + return static_cast(val); + } + + /** + * @brief Set VBUS Current Input Limit. + * @param opt: View the related chip type pmic_vbus_cur_limit enumeration + * parameters in "XPowersParams.hpp" + * @retval true valid false invalid + */ + bool setVbusCurrentLimit(pmic_vbus_cur_limit opt) + { + switch (opt) + { + case AXP192_VBUS_CUR_LIM_500MA: + setRegisterBit(AXP192_IPS_SET, 1); + return clrRegisterBit(AXP192_IPS_SET, 0); + case AXP192_VBUS_CUR_LIM_100MA: + setRegisterBit(AXP192_IPS_SET, 1); + return setRegisterBit(AXP192_IPS_SET, 0); + case AXP192_VBUS_CUR_LIM_OFF: + return clrRegisterBit(AXP192_IPS_SET, 1); + default: + break; + } + return false; + } + + /** + * @brief Get VBUS Current Input Limit. + * @retval View the related chip type pmic_vbus_cur_limit enumeration + * parameters in "XPowersParams.hpp" + */ + pmic_vbus_cur_limit getVbusCurrentLimit(void) + { + if (getRegisterBit(AXP192_IPS_SET, 1) == 0) + { + return AXP192_VBUS_CUR_LIM_OFF; + } + if (getRegisterBit(AXP192_IPS_SET, 0)) + { + return AXP192_VBUS_CUR_LIM_100MA; + } + return AXP192_VBUS_CUR_LIM_500MA; + } + + // Set the minimum system operating voltage inside the PMU, + // below this value will shut down the PMU,Adjustment range 2600mV ~ 3300mV + bool setSysPowerDownVoltage(uint16_t millivolt) + { + if (millivolt % AXP192_SYS_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", AXP192_SYS_VOL_STEPS); + return false; + } + if (millivolt < AXP192_VOFF_VOL_MIN) + { + log_e("Mistake ! SYS minimum output voltage is %umV", AXP192_VOFF_VOL_MIN); + return false; + } + else if (millivolt > AXP192_VOFF_VOL_MAX) + { + log_e("Mistake ! SYS maximum output voltage is %umV", AXP192_VOFF_VOL_MAX); + return false; + } + + int val = readRegister(AXP192_VOFF_SET); + if (val == -1) + return false; + val &= 0xF8; + val |= (millivolt - AXP192_VOFF_VOL_MIN) / AXP192_SYS_VOL_STEPS; + return 0 == writeRegister(AXP192_VOFF_SET, val); + } + + uint16_t getSysPowerDownVoltage() + { + int val = readRegister(AXP192_VOFF_SET); + if (val == -1) + return 0; + val &= 0x07; + return (val * AXP192_SYS_VOL_STEPS) + AXP192_VOFF_VOL_MIN; + } + + /** + * @brief Set shutdown, calling shutdown will turn off all power channels, + * only VRTC belongs to normal power supply + * @retval None + */ + void shutdown() + { + setRegisterBit(AXP192_OFF_CTL, 7); + } + + /* + * Charge setting + */ + void enableCharge() + { + setRegisterBit(AXP192_CHARGE1, 7); + } + + void disableCharge() + { + clrRegisterBit(AXP192_CHARGE1, 7); + } + + /** + * @brief Set charge target voltage. + * @param opt: See axp192_chg_vol enum for details. + * @retval Sucessful: bool + */ + bool setChargeTargetVoltage(pmic_chg_vol opt) + { + if (opt >= AXP192_CHG_VOL_MAX) + return false; + int val = readRegister(AXP192_CHARGE1); + if (val == -1) + return false; + val &= 0x9F; + return 0 == writeRegister(AXP192_CHARGE1, val | (opt << 5)); + } + + /** + * @brief Get charge target voltage settings. + * @retval See axp192_chg_vol enum for details. + */ + pmic_chg_vol getChargeTargetVoltage() + { + int val = readRegister(AXP192_CHARGE1); + if (val == -1) + return static_cast(0); + return static_cast((val & 0x60) >> 5); + } + + /** + * @brief Set charge current settings. + * @param opt: see pmic_chg_curr for details. + */ + bool setChargerConstantCurr(pmic_chg_curr opt) + { + if (opt > 0x0F) + return false; + int val = readRegister(AXP192_CHARGE1); + if (val == -1) + { + return false; + } + val &= 0xF0; + return 0 == writeRegister(AXP192_CHARGE1, val | opt); + } + + /** + * @brief Get charge current settings. + * @retval See pmic_chg_curr enum for details. + */ + pmic_chg_curr getChargerConstantCurr() + { + int val = readRegister(AXP192_CHARGE1) & 0x0F; + if (val == -1) + return pmic_chg_curr::AXP192_CHG_CUR_780MA; + return static_cast(val); + } + + void setChargerTerminationCurr(pmic_chg_iterm opt) + { + switch (opt) + { + case AXP192_CHG_ITERM_LESS_10_PERCENT: + clrRegisterBit(AXP192_CHARGE1, 0); + break; + case AXP192_CHG_ITERM_LESS_15_PERCENT: + setRegisterBit(AXP192_CHARGE1, 0); + break; + default: + break; + } + } + + pmic_chg_iterm getChargerTerminationCurr() + { + int val = getRegisterBit(AXP192_CHARGE1, 4); + return static_cast(val); + } + + bool setPrechargeTimeout(pmic_prechg_to opt) + { + int val = readRegister(AXP192_CHARGE2); + if (val == -1) + return false; + val &= 0x3F; + return 0 == writeRegister(AXP192_CHARGE2, val | (opt << 6)); + } + + // External channel charge current setting,Range:300~1000mA + bool setChargerExternChannelCurr(uint16_t milliampere) + { + if (milliampere % AXP192_CHG_EXT_CURR_STEP) + { + log_e("Mistake ! The steps is must %u mV", AXP192_CHG_EXT_CURR_STEP); + return false; + } + if (milliampere < AXP192_CHG_EXT_CURR_MIN) + { + log_e("Mistake ! The minimum external path charge current setting is: %umA", AXP192_CHG_EXT_CURR_MIN); + return false; + } + else if (milliampere > AXP192_CHG_EXT_CURR_MAX) + { + log_e("Mistake ! The maximum external channel charge current setting is: %umA", AXP192_CHG_EXT_CURR_MAX); + return false; + } + int val = readRegister(AXP192_CHARGE2); + if (val == -1) + return false; + val &= 0xC7; + val |= ((milliampere - AXP192_CHG_EXT_CURR_MIN) / AXP192_CHG_EXT_CURR_STEP); + return 0 == writeRegister(AXP192_CHARGE2, val); + } + + bool enableChargerExternChannel() + { + return setRegisterBit(AXP192_CHARGE2, 2); + } + + bool disableChargerExternChannel() + { + return clrRegisterBit(AXP192_CHARGE2, 2); + } + + // Timeout setting in constant current mode + bool setChargerConstantTimeout(pmic_chg_cons_to opt) + { + int val = readRegister(AXP192_CHARGE2); + if (val == -1) + return false; + val &= 0xFC; + return 0 == writeRegister(AXP192_CHARGE2, val | opt); + } + + bool enableBackupBattCharger() + { + return setRegisterBit(AXP192_BACKUP_CHG, 7); + } + + bool disableBackupBattCharger() + { + return clrRegisterBit(AXP192_BACKUP_CHG, 7); + } + + bool isEnableBackupCharger() + { + return getRegisterBit(AXP192_BACKUP_CHG, 7); + } + + bool setBackupBattChargerVoltage(pmic_backup_batt_vol opt) + { + int val = readRegister(AXP192_BACKUP_CHG); + if (val == -1) + return false; + val &= 0x9F; + return 0 == writeRegister(AXP192_BACKUP_CHG, val | (opt << 5)); + } + + bool setBackupBattChargerCurr(pmic_backup_batt_curr opt) + { + int val = readRegister(AXP192_BACKUP_CHG); + if (val == -1) + return false; + val &= 0xFC; + return 0 == writeRegister(AXP192_BACKUP_CHG, val | opt); + } + + /* + * Temperature + */ + float getTemperature() + { + return readRegisterH8L4(AXP192_INTERNAL_TEMP_H8, AXP192_INTERNAL_TEMP_L4) * AXP192_INTERNAL_TEMP_STEP - AXP192_INERNAL_TEMP_OFFSET; + } + + bool enableTemperatureMeasure() + { + return setRegisterBit(AXP192_ADC_EN2, 7); + } + + bool disableTemperatureMeasure() + { + return clrRegisterBit(AXP192_ADC_EN2, 7); + } + + /* + * Power control LDOio functions + */ + bool isEnableLDOio(void) + { + int val = readRegister(AXP192_GPIO0_CTL); + return (val & 0x02); + } + + bool enableLDOio(void) + { + int val = readRegister(AXP192_GPIO0_CTL) & 0xF8; + return 0 == writeRegister(AXP192_GPIO0_CTL, val | 0x02); + } + + bool disableLDOio(void) + { + int val = readRegister(AXP192_GPIO0_CTL) & 0xF8; + return 0 == writeRegister(AXP192_GPIO0_CTL, val); + } + + bool setLDOioVoltage(uint16_t millivolt) + { + if (millivolt % AXP192_LDOIO_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", AXP192_LDOIO_VOL_STEPS); + return false; + } + if (millivolt < AXP192_LDOIO_VOL_MIN) + { + log_e("Mistake ! LDOIO minimum output voltage is %umV", AXP192_LDOIO_VOL_MIN); + return false; + } + else if (millivolt > AXP192_LDOIO_VOL_MAX) + { + log_e("Mistake ! LDOIO maximum output voltage is %umV", AXP192_LDOIO_VOL_MAX); + return false; + } + int val = readRegister(AXP192_GPIO0_VOL); + if (val == -1) + return false; + val |= (((millivolt - AXP192_LDOIO_VOL_MIN) / AXP192_LDOIO_VOL_STEPS) << 4); + return 0 == writeRegister(AXP192_GPIO0_VOL, val); + } + + uint16_t getLDOioVoltage(void) + { + int val = readRegister(AXP192_GPIO0_VOL); + if (val == -1) + return 0; + val >>= 4; + val *= AXP192_LDOIO_VOL_STEPS; + val += AXP192_LDOIO_VOL_MIN; + return val; + } + + /* + * Power control LDO2 functions + */ + bool isEnableLDO2(void) + { + return getRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 2); + } + + bool enableLDO2(void) + { + return setRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 2); + } + + bool disableLDO2(void) + { + return clrRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 2); + } + + bool setLDO2Voltage(uint16_t millivolt) + { + if (millivolt % AXP192_LDO2_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", AXP192_LDO2_VOL_STEPS); + return false; + } + if (millivolt < AXP192_LDO2_VOL_MIN) + { + log_e("Mistake ! LDO2 minimum output voltage is %umV", AXP192_LDO2_VOL_MIN); + return false; + } + else if (millivolt > AXP192_LDO2_VOL_MAX) + { + log_e("Mistake ! LDO2 maximum output voltage is %umV", AXP192_LDO2_VOL_MAX); + return false; + } + + int val = readRegister(AXP192_LDO23OUT_VOL); + if (val == -1) + return false; + val &= 0x0F; + return 0 == writeRegister(AXP192_LDO23OUT_VOL, val | (((millivolt - AXP192_LDO2_VOL_MIN) / AXP192_LDO2_VOL_STEPS) << AXP192_LDO2_VOL_BIT_MASK)); + } + + uint16_t getLDO2Voltage(void) + { + int val = readRegister(AXP192_LDO23OUT_VOL) & 0xF0; + return (val >> AXP192_LDO2_VOL_BIT_MASK) * AXP192_LDO2_VOL_STEPS + AXP192_LDO2_VOL_MIN; + } + + /* + * Power control LDO3 functions + */ + bool isEnableLDO3(void) + { + return getRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 3); + } + + bool enableLDO3(void) + { + return setRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 3); + } + + bool disableLDO3(void) + { + return clrRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 3); + } + + bool setLDO3Voltage(uint16_t millivolt) + { + if (millivolt % AXP192_LDO3_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", AXP192_LDO3_VOL_STEPS); + return false; + } + if (millivolt < AXP192_LDO3_VOL_MIN) + { + log_e("Mistake ! LDO3 minimum output voltage is %umV", AXP192_LDO3_VOL_MIN); + return false; + } + else if (millivolt > AXP192_LDO3_VOL_MAX) + { + log_e("Mistake ! LDO3 maximum output voltage is %umV", AXP192_LDO3_VOL_MAX); + return false; + } + + int val = readRegister(AXP192_LDO23OUT_VOL) & 0xF0; + return 0 == writeRegister(AXP192_LDO23OUT_VOL, val | ((millivolt - AXP192_LDO3_VOL_MIN) / AXP192_LDO3_VOL_STEPS)); + } + + uint16_t getLDO3Voltage(void) + { + int val = readRegister(AXP192_LDO23OUT_VOL); + if (val == -1) + return 0; + val &= 0x0F; + return (val * AXP192_LDO3_VOL_STEPS) + AXP192_LDO3_VOL_MIN; + } + + /* + * Power control DCDC1 functions + */ + void setDC1PwmMode(void) + { + int val = readRegister(AXP192_DCDC_MODESET) & 0xF7; + writeRegister(AXP192_DCDC_MODESET, val | 0x08); + } + + void setDC1AutoMode(void) + { + int val = readRegister(AXP192_DCDC_MODESET) & 0xF7; + writeRegister(AXP192_DCDC_MODESET, val); + } + + bool isEnableDC1(void) + { + return getRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 0); + } + + bool enableDC1(void) + { + return setRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 0); + } + + bool disableDC1(void) + { + return clrRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 0); + } + + bool setDC1Voltage(uint16_t millivolt) + { + if (millivolt % AXP192_DC1_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", AXP192_DC1_VOL_STEPS); + return false; + } + if (millivolt < AXP192_DC1_VOL_STEPS) + { + log_e("Mistake ! DCDC1 minimum output voltage is %umV", AXP192_DC1_VOL_STEPS); + return false; + } + else if (millivolt > AXP192_DC1_VOL_MAX) + { + log_e("Mistake ! DCDC1 maximum output voltage is %umV", AXP192_DC1_VOL_MAX); + return false; + } + + int val = readRegister(AXP192_DC1_VLOTAGE); + if (val == -1) + return false; + val &= 0x80; + val |= (millivolt - AXP192_DC1_VOL_MIN) / AXP192_DC1_VOL_STEPS; + return 0 == writeRegister(AXP192_DC1_VLOTAGE, val); + } + + uint16_t getDC1Voltage(void) + { + int val = readRegister(AXP192_DC1_VLOTAGE) & 0x7F; + return val * AXP192_DC1_VOL_STEPS + AXP192_DC1_VOL_MIN; + } + + /* + * Power control DCDC2 functions + */ + void setDC2PwmMode(void) + { + int val = readRegister(AXP192_DCDC_MODESET) & 0xFB; + writeRegister(AXP192_DCDC_MODESET, val | 0x04); + } + + void setDC2AutoMode(void) + { + int val = readRegister(AXP192_DCDC_MODESET) & 0xFB; + writeRegister(AXP192_DCDC_MODESET, val); + } + + void enableDC2VRC(void) + { + int val = readRegister(AXP192_DC2_DVM); + writeRegister(AXP192_DC2_DVM, val | 0x04); + } + + void disableDC2VRC(void) + { + int val = readRegister(AXP192_DC2_DVM); + writeRegister(AXP192_DC2_DVM, val & 0xFB); + } + + bool setDC2VRC(uint8_t opts) + { + if (opts > 1) + { + return false; + } + int val = readRegister(AXP192_DC2_DVM) & 0xFE; + writeRegister(AXP192_DC2_DVM, val | opts); + } + + bool isEnableDC2VRC(void) + { + return (readRegister(AXP192_DC2_DVM) & 0x04) == 0x04; + } + + bool isEnableDC2(void) + { + return getRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 4); + } + + bool enableDC2(void) + { + return setRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 4); + } + + bool disableDC2(void) + { + return clrRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 4); + } + + bool setDC2Voltage(uint16_t millivolt) + { + if (millivolt % AXP192_DC2_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", AXP192_DC2_VOL_STEPS); + return false; + } + if (millivolt < AXP192_DC2_VOL_MIN) + { + log_e("Mistake ! DCDC2 minimum output voltage is %umV", AXP192_DC2_VOL_MIN); + return false; + } + else if (millivolt > AXP192_DC2_VOL_MAX) + { + log_e("Mistake ! DCDC2 maximum output voltage is %umV", AXP192_DC2_VOL_MAX); + return false; + } + int val = readRegister(AXP192_DC2OUT_VOL); + if (val == -1) + return false; + val &= 0x80; + val |= (millivolt - AXP192_DC2_VOL_MIN) / AXP192_DC2_VOL_STEPS; + return 0 == writeRegister(AXP192_DC2OUT_VOL, val); + } + + uint16_t getDC2Voltage(void) + { + int val = readRegister(AXP192_DC2OUT_VOL); + if (val == -1) + return 0; + return (val * AXP192_DC2_VOL_STEPS) + AXP192_DC2_VOL_MIN; + } + + /* + * Power control DCDC3 functions + */ + void setDC3PwmMode(void) + { + int val = readRegister(AXP192_DCDC_MODESET) & 0xFD; + writeRegister(AXP192_DCDC_MODESET, val | 0x02); + } + + void setDC3AutoMode(void) + { + int val = readRegister(AXP192_DCDC_MODESET) & 0xFD; + writeRegister(AXP192_DCDC_MODESET, val); + } + + bool isEnableDC3(void) + { + return getRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 1); + } + + bool enableDC3(void) + { + return setRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 1); + } + + bool disableDC3(void) + { + return clrRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 1); + } + + bool setDC3Voltage(uint16_t millivolt) + { + if (millivolt % AXP192_DC3_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", AXP192_DC3_VOL_STEPS); + return false; + } + if (millivolt < AXP192_DC3_VOL_MIN) + { + log_e("Mistake ! DCDC3 minimum output voltage is %umV", AXP192_DC3_VOL_MIN); + return false; + } + else if (millivolt > AXP192_DC3_VOL_MAX) + { + log_e("Mistake ! DCDC3 maximum output voltage is %umV", AXP192_DC3_VOL_MAX); + return false; + } + return 0 == writeRegister(AXP192_DC3OUT_VOL, (millivolt - AXP192_DC3_VOL_MIN) / AXP192_DC3_VOL_STEPS); + } + + uint16_t getDC3Voltage(void) + { + int val = readRegister(AXP192_DC3OUT_VOL); + if (val == -1) + return 0; + return (val * AXP192_DC3_VOL_STEPS) + AXP192_DC3_VOL_MIN; + } + + /* + * Power control EXTEN functions + */ + bool enableExternalPin(void) + { + return setRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 6); + } + + bool disableExternalPin(void) + { + return clrRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 6); + } + + bool isEnableExternalPin(void) + { + return getRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 6); + } + + /* + * Interrupt status functions + */ + + /** + * @brief Get the interrupt controller mask value. + * @retval Mask value corresponds to pmic_irq , + */ + uint64_t getIrqStatus(void) + { + statusRegister[0] = readRegister(AXP192_INTSTS1); + statusRegister[1] = readRegister(AXP192_INTSTS2); + statusRegister[2] = readRegister(AXP192_INTSTS3); + statusRegister[3] = readRegister(AXP192_INTSTS4); + statusRegister[4] = readRegister(AXP192_INTSTS5); + return ((uint64_t)statusRegister[4]) << 32 | + ((uint64_t)statusRegister[3]) << 24 | + ((uint64_t)statusRegister[2]) << 16 | + ((uint64_t)statusRegister[1]) << 8 | + ((uint64_t)statusRegister[0]); + } + + /** + * @brief Clear interrupt controller state. + */ + void clearIrqStatus(void) + { + for (int i = 0; i < 4; i++) + { + writeRegister(AXP192_INTSTS1 + i, 0xFF); + statusRegister[i] = 0; + } + writeRegister(AXP192_INTSTS5, 0xFF); + } + + /** + * @brief Enable PMU interrupt control mask . + * @param opt: View the related chip type pmic_irq enumeration + * parameters in "XPowersParams.hpp" + * @retval + */ + bool enableIRQ(pmic_irq opt) + { + return setInterruptImpl(opt, true); + } + + /** + * @brief Disable PMU interrupt control mask . + * @param opt: View the related chip type pmic_irq enumeration + * parameters in "XPowersParams.hpp" + * @retval + */ + bool disableIRQ(pmic_irq opt) + { + return setInterruptImpl(opt, false); + } + + bool isAcinOverVoltageIrq(void) + { + return (bool)(statusRegister[0] & _BV(7)); + } + + bool isAcinInserIrq(void) + { + return (bool)(statusRegister[0] & _BV(6)); + } + + bool isAcinRemoveIrq(void) + { + return (bool)(statusRegister[0] & _BV(5)); + } + + bool isVbusOverVoltageIrq(void) + { + return (bool)(statusRegister[0] & _BV(4)); + } + + bool isVbusInsertIrq(void) + { + return (bool)(statusRegister[0] & _BV(3)); + } + + bool isVbusRemoveIrq(void) + { + return (bool)(statusRegister[0] & _BV(2)); + } + + bool isVbusLowVholdIrq(void) + { + return (bool)(statusRegister[0] & _BV(1)); + } + + bool isBatInsertIrq(void) + { + return (bool)(statusRegister[1] & _BV(7)); + } + + bool isBatRemoveIrq(void) + { + return (bool)(statusRegister[1] & _BV(6)); + } + + bool isBattEnterActivateIrq(void) + { + return (bool)(statusRegister[1] & _BV(5)); + } + + bool isBattExitActivateIrq(void) + { + return (bool)(statusRegister[1] & _BV(4)); + } + + bool isBatChargeStartIrq(void) + { + return (bool)(statusRegister[1] & _BV(3)); + } + + bool isBatChargeDoneIrq(void) + { + return (bool)(statusRegister[1] & _BV(2)); + } + + bool isBattTempHighIrq(void) + { + return (bool)(statusRegister[1] & _BV(1)); + } + + bool isBattTempLowIrq(void) + { + return (bool)(statusRegister[1] & _BV(0)); + } + + bool isChipOverTemperatureIrq(void) + { + return (bool)(statusRegister[2] & _BV(7)); + } + + bool isChargingCurrentLessIrq(void) + { + return (bool)(statusRegister[2] & _BV(6)); + } + + bool isDC1VoltageLessIrq(void) + { + return (bool)(statusRegister[2] & _BV(5)); + } + + bool isDC2VoltageLessIrq(void) + { + return (bool)(statusRegister[2] & _BV(4)); + } + + bool isDC3VoltageLessIrq(void) + { + return (bool)(statusRegister[2] & _BV(3)); + } + + bool isPekeyShortPressIrq(void) + { + return (bool)(statusRegister[2] & _BV(1)); + } + + bool isPekeyLongPressIrq(void) + { + return (bool)(statusRegister[2] & _BV(0)); + } + + bool isNOEPowerOnIrq(void) + { + return (bool)(statusRegister[3] & _BV(7)); + } + + bool isNOEPowerDownIrq(void) + { + return (bool)(statusRegister[3] & _BV(6)); + } + + bool isVbusEffectiveIrq(void) + { + return (bool)(statusRegister[3] & _BV(5)); + } + + bool isVbusInvalidIrq(void) + { + return (bool)(statusRegister[3] & _BV(4)); + } + + bool isVbusSessionIrq(void) + { + return (bool)(statusRegister[3] & _BV(3)); + } + + bool isVbusSessionEndIrq(void) + { + return (bool)(statusRegister[3] & _BV(2)); + } + + bool isLowVoltageLevel2Irq(void) + { + return (bool)(statusRegister[3] & _BV(0)); + } + + // IRQ5 REGISTER : + bool isWdtExpireIrq(void) + { + return (bool)(statusRegister[4] & _BV(7)); + } + + bool isGpio2EdgeTriggerIrq(void) + { + return (bool)(statusRegister[4] & _BV(2)); + } + + bool isGpio1EdgeTriggerIrq(void) + { + return (bool)(statusRegister[4] & _BV(1)); + } + + bool isGpio0EdgeTriggerIrq(void) + { + return (bool)(statusRegister[4] & _BV(0)); + } + + /* + * ADC Functions + */ + + bool enableBattDetection() + { + return setRegisterBit(AXP192_OFF_CTL, 6); + } + + bool disableBattDetection() + { + return clrRegisterBit(AXP192_OFF_CTL, 6); + } + + bool enableVbusVoltageMeasure() + { + return setSignalCaptureImpl(MONITOR_USB_CURRENT | MONITOR_USB_VOLTAGE, true); + } + + bool disableVbusVoltageMeasure() + { + return setSignalCaptureImpl(MONITOR_USB_CURRENT | MONITOR_USB_VOLTAGE, false); + } + + bool enableBattVoltageMeasure() + { + return setSignalCaptureImpl(MONITOR_BAT_CURRENT | MONITOR_BAT_VOLTAGE, true); + } + + bool disableBattVoltageMeasure() + { + return setSignalCaptureImpl(MONITOR_BAT_CURRENT | MONITOR_BAT_VOLTAGE, false); + } + + bool enableSystemVoltageMeasure() + { + return setSignalCaptureImpl(MONITOR_APS_VOLTAGE, true); + } + + bool disableSystemVoltageMeasure() + { + return setSignalCaptureImpl(MONITOR_APS_VOLTAGE, false); + } + + bool enableTSPinMeasure() + { + return setSignalCaptureImpl(MONITOR_TS_PIN, true); + } + + bool disableTSPinMeasure() + { + return setSignalCaptureImpl(MONITOR_TS_PIN, false); + } + + bool enableAdcChannel(uint32_t opts) + { + return setSignalCaptureImpl(opts, true); + } + + bool disableAdcChannel(uint32_t opts) + { + return setSignalCaptureImpl(opts, false); + } + + uint16_t getVbusVoltage() + { + if (!isVbusIn()) + { + return 0; + } + return readRegisterH8L4(AXP192_VBUS_VOL_H8, + AXP192_VBUS_VOL_L4) * + AXP192_VBUS_VOLTAGE_STEP; + } + + float getVbusCurrent() + { + if (!isVbusIn()) + { + return 0; + } + return readRegisterH8L4(AXP192_VBUS_CUR_H8, + AXP192_VBUS_CUR_L4) * + AXP192_VBUS_CUR_STEP; + } + + uint16_t getBattVoltage() + { + if (!isBatteryConnect()) + { + return 0; + } + return readRegisterH8L4(AXP192_BAT_AVERVOL_H8, + AXP192_BAT_AVERVOL_L4) * + AXP192_BATT_VOLTAGE_STEP; + } + + float getBattDischargeCurrent() + { + if (!isBatteryConnect()) + { + return 0; + } + return readRegisterH8L5(AXP192_BAT_AVERDISCHGCUR_H8, + AXP192_BAT_AVERDISCHGCUR_L5) * + AXP192_BATT_DISCHARGE_CUR_STEP; + } + + uint16_t getAcinVoltage() + { + if (!isAcinIn()) + { + return 0; + } + return readRegisterH8L4(AXP192_ACIN_VOL_H8, AXP192_ACIN_VOL_L4) * AXP192_ACIN_VOLTAGE_STEP; + } + + float getAcinCurrent() + { + if (!isAcinIn()) + { + return 0; + } + return readRegisterH8L4(AXP192_ACIN_CUR_H8, AXP192_ACIN_CUR_L4) * AXP192_ACIN_CUR_STEP; + } + + uint16_t getSystemVoltage() + { + return readRegisterH8L4(AXP192_APS_AVERVOL_H8, AXP192_APS_AVERVOL_L4) * AXP192_APS_VOLTAGE_STEP; + } + + /* + * Timer Control + */ + void setTimerout(uint8_t minute) + { + writeRegister(AXP192_TIMER_CTL, 0x80 | minute); + } + + void disableTimer() + { + writeRegister(AXP192_TIMER_CTL, 0x80); + } + + void clearTimerFlag() + { + setRegisterBit(AXP192_TIMER_CTL, 7); + } + + /* + * Data Buffer + */ + bool writeDataBuffer(uint8_t *data, uint8_t size) + { + if (size > AXP192_DATA_BUFFER_SIZE) + return false; + for (int i = 0; i < size; ++i) + { + writeRegister(AXP192_DATA_BUFFER1 + i, data[i]); + } + return true; + } + + bool readDataBuffer(uint8_t *data, uint8_t size) + { + if (size > AXP192_DATA_BUFFER_SIZE) + return false; + for (int i = 0; i < size; ++i) + { + data[i] = readRegister(AXP192_DATA_BUFFER1 + i); + } + return true; + } + + /* + * Charge led functions + */ + + /** + * @brief Set charging led mode. + * @retval See chg_led_mode_t enum for details. + */ + void setChargingLedMode(pmic_chg_led_mode mode) + { + int val; + switch (mode) + { + case CHG_LED_OFF: + case CHG_LED_BLINK_1HZ: + case CHG_LED_BLINK_4HZ: + case CHG_LED_ON: + val = readRegister(AXP192_OFF_CTL); + if (val == -1) + return; + val &= 0xC7; + val |= 0x08; // use manual ctrl + val |= (mode << 4); + writeRegister(AXP192_OFF_CTL, val); + break; + case CHG_LED_CTRL_CHG: + clrRegisterBit(AXP192_OFF_CTL, 3); + break; + default: + break; + } + } + + pmic_chg_led_mode getChargingLedMode() + { + if (!getRegisterBit(AXP192_OFF_CTL, 3)) + { + return CHG_LED_CTRL_CHG; + } + int val = readRegister(AXP192_OFF_CTL); + if (val == -1) + return CHG_LED_OFF; + val &= 0x30; + return static_cast(val >> 4); + } + + /* + * Coulomb counter control + */ + void enableCoulomb() + { + setRegisterBit(AXP192_COULOMB_CTL, 7); + } + + void disableCoulomb() + { + clrRegisterBit(AXP192_COULOMB_CTL, 7); + } + + void stopCoulomb() + { + setRegisterBit(AXP192_COULOMB_CTL, 6); + } + + void clearCoulomb() + { + setRegisterBit(AXP192_COULOMB_CTL, 5); + } + + uint32_t getBattChargeCoulomb() + { + int data[4]; + data[0] = readRegister(AXP192_BAT_CHGCOULOMB3); + data[1] = readRegister(AXP192_BAT_CHGCOULOMB2); + data[2] = readRegister(AXP192_BAT_CHGCOULOMB1); + data[3] = readRegister(AXP192_BAT_CHGCOULOMB0); + for (int i = 0; i < 4; ++i) + { + if (data[i] == -1) + return 0; + } + return ((uint32_t)data[0] << 24) | ((uint32_t)data[1] << 16) | ((uint32_t)data[2] << 8) | (uint32_t)data[3]; + } + + uint32_t getBattDischargeCoulomb() + { + int data[4]; + data[0] = readRegister(AXP192_BAT_DISCHGCOULOMB3); + data[1] = readRegister(AXP192_BAT_DISCHGCOULOMB2); + data[2] = readRegister(AXP192_BAT_DISCHGCOULOMB1); + data[3] = readRegister(AXP192_BAT_DISCHGCOULOMB0); + for (int i = 0; i < 4; ++i) + { + if (data[i] == -1) + return 0; + } + return ((uint32_t)data[0] << 24) | ((uint32_t)data[1] << 16) | ((uint32_t)data[2] << 8) | (uint32_t)data[3]; + } + + uint8_t getAdcSamplingRate(void) + { + int val = readRegister(AXP192_ADC_SPEED); + if (val == -1) + return 0; + return 25 * (int)pow(2, (val & 0xC0) >> 6); + } + + float getCoulombData(void) + { + uint32_t charge = getBattChargeCoulomb(), discharge = getBattDischargeCoulomb(); + uint8_t rate = getAdcSamplingRate(); + float result = 65536.0 * 0.5 * ((float)charge - (float)discharge) / 3600.0 / rate; + return result; + } + + /* + * GPIO control functions + */ + float getBatteryChargeCurrent(void) + { + return readRegisterH8L5( + AXP192_BAT_AVERCHGCUR_H8, + AXP192_BAT_AVERCHGCUR_L5) * + AXP192_BATT_CHARGE_CUR_STEP; + } + + uint16_t getGpio0Voltage() + { + return readRegisterH8L4(AXP192_GPIO0_VOL_ADC_H8, AXP192_GPIO0_VOL_ADC_L4) * AXP192_GPIO0_STEP * 1000; + } + + uint16_t getGpio1Voltage() + { + return readRegisterH8L4(AXP192_GPIO1_VOL_ADC_H8, AXP192_GPIO1_VOL_ADC_L4) * AXP192_GPIO1_STEP * 1000; + } + + int8_t pwmSetup(uint8_t channel, uint8_t freq, uint16_t duty) + { + // PWM输出频率 = 2.25MHz / (X+1) / Y1 + // PWM输出占空比 = Y2 / Y1 + switch (channel) + { + case 0: + writeRegister(AXP192_PWM1_FREQ_SET, freq); + writeRegister(AXP192_PWM1_DUTY_SET1, duty >> 8); + writeRegister(AXP192_PWM1_DUTY_SET2, duty & 0xFF); + break; + case 1: + writeRegister(AXP192_PWM2_FREQ_SET, freq); + writeRegister(AXP192_PWM2_DUTY_SET1, duty >> 8); + writeRegister(AXP192_PWM2_DUTY_SET2, duty & 0xFF); + break; + default: + return -1; + break; + } + return 0; + } + + int8_t pwmEnable(uint8_t channel) + { + int val = 0; + switch (channel) + { + case 0: + val = readRegister(AXP192_GPIO1_CTL) & 0xF8; + writeRegister(AXP192_GPIO1_CTL, val | 0x02); + return 0; + case 1: + val = readRegister(AXP192_GPIO2_CTL) & 0xF8; + writeRegister(AXP192_GPIO2_CTL, val | 0x02); + return 0; + default: + break; + } + return -1; + } + + uint8_t getBatteryPercent(void) + { + if (!isBatteryConnect()) + { + return -1; + } + const static int table[11] = { + 3000, 3650, 3700, 3740, 3760, 3795, + 3840, 3910, 3980, 4070, 4150}; + uint16_t voltage = getBattVoltage(); + if (voltage < table[0]) + return 0; + for (int i = 0; i < 11; i++) + { + if (voltage < table[i]) + return i * 10 - (10UL * (int)(table[i] - voltage)) / + (int)(table[i] - table[i - 1]); + ; + } + return 100; + } + + uint8_t getChipID(void) + { + return readRegister(AXP192_IC_TYPE); + } + + /* + * GPIO setting + */ + int8_t pinMode(uint8_t pin, uint8_t mode) + { + int val = 0; + switch (pin) + { + case PMU_GPIO0: + /* + * 000: NMOS open-drain output + * 001: Universal input function + * 010: Low noise LDO + * 011: reserved + * 100: ADC input + * 101: Low output + * 11X: Floating + * * */ + if (mode == INPUT || mode == INPUT_PULLDOWN) + { + if (gpio[pin].mode != INPUT) + { + gpio[pin].mode = INPUT; + } + val = readRegister(AXP192_GPIO0_CTL) & 0xF8; + writeRegister(AXP192_GPIO0_CTL, val | 0x01); + // Set pull-down mode + val = readRegister(AXP192_GPIO012_PULLDOWN) & 0xFE; + if (mode == INPUT_PULLDOWN) + { + writeRegister(AXP192_GPIO012_PULLDOWN, val | 0x01); + } + else + { + writeRegister(AXP192_GPIO012_PULLDOWN, val); + } + } + break; + + case PMU_GPIO1: + /* + * 000: NMOS open-drain output + * 001: Universal input function + * 010: PWM1 output, high level is VINT, not Can add less than 100K pull-down resistance + * 011: reserved + * 100: ADC input + * 101: Low output + * 11X: Floating + * * */ + if (mode == INPUT || mode == INPUT_PULLDOWN) + { + if (gpio[pin].mode != INPUT) + { + gpio[pin].mode = INPUT; + } + val = readRegister(AXP192_GPIO1_CTL) & 0xF8; + writeRegister(AXP192_GPIO1_CTL, val | 0x01); + + // Set pull-down mode + val = readRegister(AXP192_GPIO012_PULLDOWN) & 0xFD; + if (mode == INPUT_PULLDOWN) + { + writeRegister(AXP192_GPIO012_PULLDOWN, val | 0x02); + } + else + { + writeRegister(AXP192_GPIO012_PULLDOWN, val); + } + } + break; + + case PMU_GPIO2: + /* + * 000: NMOS open-drain output + * 001: Universal input function + * 010: PWM2 output, high level is VINT, not Can add less than 100K pull-down resistance + * 011: reserved + * 100: ADC input + * 101: Low output + * 11X: Floating + * */ + if (mode == INPUT || mode == INPUT_PULLDOWN) + { + if (gpio[pin].mode != INPUT) + { + gpio[pin].mode = INPUT; + } + val = readRegister(AXP192_GPIO2_CTL) & 0xF8; + writeRegister(AXP192_GPIO2_CTL, val | 0x01); + + // Set pull-down mode + val = readRegister(AXP192_GPIO012_PULLDOWN) & 0xFB; + if (mode == INPUT_PULLDOWN) + { + writeRegister(AXP192_GPIO012_PULLDOWN, val | 0x04); + } + else + { + writeRegister(AXP192_GPIO012_PULLDOWN, val); + } + } + break; + + case PMU_GPIO3: + /* + * 00: External charging control + * 01: NMOS open-drain output port 3 + * 10: Universal input port 3 + * 11: ADC input + * * */ + if (mode == INPUT) + { + if (gpio[pin].mode != INPUT) + { + gpio[pin].mode = INPUT; + } + val = readRegister(AXP192_GPIO34_CTL) & 0xFC; + writeRegister(AXP192_GPIO34_CTL, val | 0x82); + } + break; + + case PMU_GPIO4: + /* + * 00: External charging control + * 01: NMOS open-drain output port 4 + * 10: Universal input port 4 + * 11: undefined + * * */ + if (mode == INPUT) + { + if (gpio[pin].mode != INPUT) + { + gpio[pin].mode = INPUT; + } + val = readRegister(AXP192_GPIO34_CTL) & 0xF3; + writeRegister(AXP192_GPIO34_CTL, val | 0x88); + } + break; + case PMU_GPIO5: + if (mode == INPUT) + { + if (gpio[pin].mode != INPUT) + { + gpio[pin].mode = INPUT; + } + val = readRegister(AXP192_GPIO5_CTL) & 0xBF; + writeRegister(AXP192_GPIO5_CTL, val | 0x40); + } + break; + default: + break; + } + return 0; + } + + uint8_t digitalRead(pmic_num pin) + { + switch (pin) + { + case PMU_GPIO0: + return getRegisterBit(AXP192_GPIO012_SIGNAL, 4); + case PMU_GPIO1: + return getRegisterBit(AXP192_GPIO012_SIGNAL, 5); + case PMU_GPIO2: + return getRegisterBit(AXP192_GPIO012_SIGNAL, 6); + case PMU_GPIO3: + return getRegisterBit(AXP192_GPIO34_SIGNAL, 4); + case PMU_GPIO4: + return getRegisterBit(AXP192_GPIO34_SIGNAL, 5); + case PMU_GPIO5: + return getRegisterBit(AXP192_GPIO5_CTL, 4); + default: + break; + } + return 0; + } + + void digitalWrite(pmic_num pin, uint8_t val) + { + int reg = 0; + switch (pin) + { + case PMU_GPIO0: + if (gpio[pin].mode != OUTPUT) + { + gpio[pin].mode = OUTPUT; + } + reg = readRegister(AXP192_GPIO0_CTL) & 0xFE; + writeRegister(AXP192_GPIO0_CTL, val ? (reg | 0x01) : reg); + break; + case PMU_GPIO1: + if (gpio[pin].mode != OUTPUT) + { + gpio[pin].mode = OUTPUT; + } + reg = readRegister(AXP192_GPIO1_CTL) & 0xFD; + writeRegister(AXP192_GPIO1_CTL, val ? (reg | 0x01) : reg); + break; + case PMU_GPIO2: + if (gpio[pin].mode != OUTPUT) + { + gpio[pin].mode = OUTPUT; + } + reg = readRegister(AXP192_GPIO2_CTL) & 0xFB; + writeRegister(AXP192_GPIO2_CTL, val ? (reg | 0x01) : reg); + break; + case PMU_GPIO3: + if (gpio[pin].mode != OUTPUT) + { + gpio[pin].mode = OUTPUT; + reg = readRegister(AXP192_GPIO34_CTL) & 0xFC; + writeRegister(AXP192_GPIO34_CTL, reg | 0x01); + } + reg = readRegister(AXP192_GPIO34_SIGNAL) & 0xF7; + writeRegister(AXP192_GPIO34_SIGNAL, val ? (val | 0x08) : reg); + break; + case PMU_GPIO4: + if (gpio[pin].mode != OUTPUT) + { + gpio[pin].mode = OUTPUT; + reg = readRegister(AXP192_GPIO34_CTL) & 0xF3; + writeRegister(AXP192_GPIO34_CTL, reg | 0x04); + } + reg = readRegister(AXP192_GPIO34_SIGNAL) & 0xEF; + writeRegister(AXP192_GPIO34_SIGNAL, val ? (val | 0x10) : reg); + break; + case PMU_GPIO5: + if (gpio[pin].mode != OUTPUT) + { + gpio[pin].mode = OUTPUT; + reg = readRegister(AXP192_GPIO5_CTL) & 0xBF; + writeRegister(AXP192_GPIO5_CTL, reg); + } + reg = readRegister(AXP192_GPIO5_CTL) & 0xDF; + writeRegister(AXP192_GPIO5_CTL, val ? (reg | 0x20) : reg); + break; + default: + break; + } + } + + /** + * Sleep function + */ + bool enableSleep() + { + return setRegisterBit(AXP192_VOFF_SET, 3); + } + + /* + * Pekey function + */ + + /** + * @brief Set the PEKEY power-on long press time. + * @param opt: See pmic_press_on_time enum for details. + * @retval + */ + bool setPowerKeyPressOnTime(pmic_press_on_time opt) + { + int val = readRegister(AXP192_POK_SET); + if (val == -1) + return false; + return 0 == writeRegister(AXP192_POK_SET, (val & 0x3F) | (opt << 6)); + } + + /** + * @brief Get the PEKEY power-on long press time. + * @retval See press_on_time_t enum for details. + */ + pmic_press_on_time getPowerKeyPressOnTime() + { + int val = readRegister(AXP192_POK_SET); + if (val == -1) + return pmic_press_on_time(0); + return static_cast((val & 0xC0) >> 6); + } + + /** + * @brief Set the PEKEY power-off long press time. + * @param opt: See pmic_press_off_time enum for details. + * @retval + */ + bool setPowerKeyPressOffTime(pmic_press_off_time opt) + { + int val = readRegister(AXP192_POK_SET); + if (val == -1) + return false; + return 0 == writeRegister(AXP192_POK_SET, (val & 0xFC) | opt); + } + + /** + * @brief Get the PEKEY power-off long press time. + * @retval See pmic_press_off_time enum for details. + */ + pmic_press_off_time getPowerKeyPressOffTime() + { + int val = readRegister(AXP192_POK_SET); + if (val == -1) + return pmic_press_off_time(0); + return static_cast(val & 0x03); + } + + void setPowerKeyLongPressOnTime(pmic_pekey_long_press opt) + { + int val = readRegister(AXP192_POK_SET); + if (val == -1) + return; + writeRegister(AXP192_POK_SET, (val & 0xCF) | (opt << 4)); + } + + void enablePowerKeyLongPressPowerOff() + { + setRegisterBit(AXP192_POK_SET, 3); + } + + void disablePowerKeyLongPressPowerOff() + { + clrRegisterBit(AXP192_POK_SET, 3); + } + + protected: + uint16_t getPowerChannelVoltage(PMICPowerChannel channel) + { + switch (channel) + { + case DCDC1: + return getDC1Voltage(); + case DCDC2: + return getDC2Voltage(); + case DCDC3: + return getDC3Voltage(); + case LDO2: + return getLDO2Voltage(); + case LDO3: + return getLDO3Voltage(); + case LDOIO: + return getLDOioVoltage(); + default: + break; + } + return 0; + } + + bool inline enablePowerOutput(PMICPowerChannel channel) + { + /* + return 0 == writeRegister(AXP192_LDO23_DC123_EXT_CTL, + val | readRegister(AXP192_LDO23_DC123_EXT_CTL)); + */ + switch (channel) + { + case DCDC1: + return enableDC1(); + case DCDC2: + return enableDC2(); + case DCDC3: + return enableDC3(); + case LDO2: + return enableLDO2(); + case LDO3: + return enableLDO3(); + case LDOIO: + return enableLDOio(); + case VBACKUP: + return enableBackupBattCharger(); + default: + break; + } + return false; + } + + bool inline disablePowerOutput(PMICPowerChannel channel) + { + /* + return 0 == writeRegister(AXP192_LDO23_DC123_EXT_CTL, + val & readRegister(AXP192_LDO23_DC123_EXT_CTL)); + */ + if (getProtectedChannel(channel)) + { + log_e("Failed to disable the power channel, the power channel has been protected"); + return false; + } + switch (channel) + { + case DCDC1: + return disableDC1(); + case DCDC2: + return disableDC2(); + case DCDC3: + return disableDC3(); + case LDO2: + return disableLDO2(); + case LDO3: + return disableLDO3(); + case LDOIO: + return disableLDOio(); + case VBACKUP: + return disableBackupBattCharger(); + default: + break; + } + return false; + } + + bool inline isPowerChannelEnable(PMICPowerChannel channel) + { + switch (channel) + { + case DCDC1: + return isEnableDC1(); + case DCDC2: + return isEnableDC2(); + case DCDC3: + return isEnableDC3(); + case LDO2: + return isEnableLDO2(); + case LDO3: + return isEnableLDO3(); + case LDOIO: + return isEnableLDOio(); + case VBACKUP: + return isEnableBackupCharger(); + default: + break; + } + return false; + } + + bool inline setPowerChannelVoltage(PMICPowerChannel channel, uint16_t millivolt) + { + if (getProtectedChannel(channel)) + { + log_e("Failed to set the power channel, the power channel has been protected"); + return false; + } + switch (channel) + { + case DCDC1: + return setDC1Voltage(millivolt); + case DCDC2: + return setDC2Voltage(millivolt); + case DCDC3: + return setDC3Voltage(millivolt); + case LDO2: + return setLDO2Voltage(millivolt); + case LDO3: + return setLDO3Voltage(millivolt); + case LDOIO: + return setLDOioVoltage(millivolt); + case VBACKUP: + // TODO: + // return setBackupBattChargerVoltage(millivolt); + default: + break; + } + return false; + } + + bool inline getPowerEnable(uint8_t val) + { + return (bool)(readRegister(AXP192_LDO23_DC123_EXT_CTL) & val); + } + + bool initImpl() + { + if (getChipID() == AXP192_CHIP_ID) + { + setChipModel(PMICChipModel::AXP192); + return true; + } + return false; + } + + /* + * Interrupt control functions + */ + bool setInterruptImpl(uint64_t opts, bool enable) + { + int res = 0; + int data = 0, value = 0; + + log_d("%s %s - 0x%llx\n", __func__, enable ? "ENABLE" : "DISABLE", opts); + + if (opts & 0xFF) + { + value = opts & 0xFF; + data = readRegister(AXP192_INTEN1); + res |= writeRegister(AXP192_INTEN1, enable ? (data | value) : (data & (~value))); + } + + if (opts & 0xFF00) + { + value = opts >> 8; + data = readRegister(AXP192_INTEN2); + res |= writeRegister(AXP192_INTEN2, enable ? (data | value) : (data & (~value))); + } + + if (opts & 0xFF0000) + { + value = opts >> 16; + data = readRegister(AXP192_INTEN3); + res |= writeRegister(AXP192_INTEN3, enable ? (data | value) : (data & (~value))); + } + + if (opts & 0xFF000000) + { + value = opts >> 24; + data = readRegister(AXP192_INTEN4); + res |= writeRegister(AXP192_INTEN4, enable ? (data | value) : (data & (~value))); + } + + if (opts & 0xFF00000000) + { + value = opts >> 32; + data = readRegister(AXP192_INTEN5); + res |= writeRegister(AXP192_INTEN5, enable ? (data | value) : (data & (~value))); + } + return res == 0; + } + + /* + * Signal Capture control functions + */ + bool setSignalCaptureImpl(uint32_t opts, bool enable) + { + int value = 0; + if (opts & 0xFF) + { + value = readRegister(AXP192_ADC_EN1); + writeRegister(AXP192_ADC_EN1, enable ? (value | opts) : (value & (~opts))); + } + if (opts & 0xFF00) + { + opts >>= 8; + value = readRegister(AXP192_ADC_EN2); + writeRegister(AXP192_ADC_EN2, enable ? (value | opts) : (value & (~opts))); + } + return true; + } + + const char *getChipNameImpl(void) + { + return "AXP192"; + } + + private: + const uint16_t chargeTargetVol[4] = {4100, 4150, 4200, 4360}; + uint8_t statusRegister[AXP192_INTSTS_CNT]; + gpio_t gpio[AXP192_GPIO_CNT]; + }; +} // namespace HAL::PMIC \ No newline at end of file diff --git a/lib/HAL/PMIC/DRIVER/AXP202.tpp b/lib/HAL/PMIC/DRIVER/AXP202.tpp new file mode 100644 index 000000000..d2d148088 --- /dev/null +++ b/lib/HAL/PMIC/DRIVER/AXP202.tpp @@ -0,0 +1,1871 @@ +#include "../REG/AXP202.hpp" +#include "../IMPL/XPOWERS.tpp" +namespace HAL +{ + namespace PMIC + { + class AXP202 : public XPOWERS + { + friend class XPOWERS; + + typedef enum + { + MONITOR_TS_PIN = _BV(0), + MONITOR_APS_VOLTAGE = _BV(1), + MONITOR_USB_CURRENT = _BV(2), + MONITOR_USB_VOLTAGE = _BV(3), + MONITOR_AC_CURRENT = _BV(4), + MONITOR_AC_VOLTAGE = _BV(5), + MONITOR_BAT_CURRENT = _BV(6), + MONITOR_BAT_VOLTAGE = _BV(7), + MONITOR_ADC_IO3 = _BV(8), + MONITOR_ADC_IO2 = _BV(9), + MONITOR_ADC_IO1 = _BV(10), + MONITOR_ADC_IO0 = _BV(11), + MONITOR_TEMPERATURE = _BV(16), + } axp202_adc_func; + + public: + AXP202(TwoWire &w, int sda = SDA, int scl = SCL, uint8_t addr = AXP202_SLAVE_ADDRESS) + { + myWire = &w; + mySDA = sda; + mySCL = scl; + myADDR = addr; + } + + AXP202() + { + myWire = &Wire; + mySDA = SDA; + mySCL = SCL; + myADDR = AXP202_SLAVE_ADDRESS; + } + + ~AXP202() + { + log_i("~AXP202"); + deinit(); + } + + bool init(TwoWire &w, int sda = SDA, int scl = SCL, uint8_t addr = AXP202_SLAVE_ADDRESS) + { + myWire = &w; + mySDA = sda; + mySCL = scl; + myADDR = addr; + return begin(); + } + + bool init() + { + return begin(); + } + + void deinit() + { + end(); + } + + uint16_t status() + { + return readRegister(AXP202_STATUS); + } + + bool isAcinVbusStart() + { + return getRegisterBit(AXP202_STATUS, 0); + } + + bool isDischarge() + { + return !getRegisterBit(AXP202_STATUS, 2); + } + + bool isVbusIn(void) + { + return getRegisterBit(AXP202_STATUS, 5); + } + + bool isAcinEfficient() + { + return getRegisterBit(AXP202_STATUS, 6); + } + + bool isAcinIn() + { + return getRegisterBit(AXP202_STATUS, 7); + } + + bool isOverTemperature() + { + return getRegisterBit(AXP202_MODE_CHGSTATUS, 7); + } + + bool isCharging(void) + { + return getRegisterBit(AXP202_MODE_CHGSTATUS, 6); + } + + bool isBatteryConnect(void) + { + return getRegisterBit(AXP202_MODE_CHGSTATUS, 5); + } + + bool isBattInActiveMode() + { + return getRegisterBit(AXP202_MODE_CHGSTATUS, 3); + } + + bool isChargeCurrLessPreset() + { + return getRegisterBit(AXP202_MODE_CHGSTATUS, 2); + } + + void enableVbusVoltageLimit() + { + setRegisterBit(AXP202_IPS_SET, 6); + } + + void disableVbusVoltageLimit() + { + clrRegisterBit(AXP202_IPS_SET, 6); + } + + /** + * @brief Set VBUS Voltage Input Limit. + * @param opt: View the related chip type pmic_vbus_vol_limit enumeration + * parameters in the registries + */ + void setVbusVoltageLimit(pmic_vbus_vol_limit opt) + { + int val = readRegister(AXP202_IPS_SET); + if (val == -1) + return; + val &= 0xC7; + writeRegister(AXP202_IPS_SET, val | (opt << 3)); + } + + /** + * @brief Get VBUS Voltage Input Limit. + * @retval View the related chip type pmic_vbus_vol_limit enumeration + * parameters in the Registries + */ + pmic_vbus_vol_limit getVbusVoltageLimit(void) + { + return static_cast((readRegister(AXP202_IPS_SET) >> 3) & 0x7); + } + + /** + * @brief Set VBUS Current Input Limit. + * @param opt: View the related chip type pmic_vbus_cur_limit enumeration + * parameters in the registries + * @retval true valid false invalid + */ + bool setVbusCurrentLimit(pmic_vbus_cur_limit opt) + { + int val = readRegister(AXP202_IPS_SET); + if (val == -1) + return false; + val &= 0xFC; + switch (opt) + { + case AXP202_VBUS_CUR_LIM_900MA: + return writeRegister(AXP202_IPS_SET, val); + case AXP202_VBUS_CUR_LIM_500MA: + return writeRegister(AXP202_IPS_SET, val | 0x01); + case AXP202_VBUS_CUR_LIM_100MA: + return writeRegister(AXP202_IPS_SET, val | 0x02); + case AXP202_VBUS_CUR_LIM_OFF: + return writeRegister(AXP202_IPS_SET, val | 0x03); + default: + break; + } + return false; + } + + /** + * @brief Get VBUS Current Input Limit. + * @retval View the related chip type axp202_vbus_cur_limit_t enumeration + * parameters in the registries + */ + pmic_vbus_cur_limit getVbusCurrentLimit(void) + { + int val = readRegister(AXP202_IPS_SET); + if (val == -1) + return pmic_vbus_cur_limit(0); + val &= 0x03; + return static_cast(val); + } + + // Set the minimum system operating voltage inside the PMU, + // below this value will shut down the PMU,Adjustment range 2600mV ~ 3300mV + bool setSysPowerDownVoltage(uint16_t millivolt) + { + if (millivolt % AXP202_SYS_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", AXP202_SYS_VOL_STEPS); + return false; + } + if (millivolt < AXP202_VOFF_VOL_MIN) + { + log_e("Mistake ! SYS minimum output voltage is %umV", AXP202_VOFF_VOL_MIN); + return false; + } + else if (millivolt > AXP202_VOFF_VOL_MAX) + { + log_e("Mistake ! SYS maximum output voltage is %umV", AXP202_VOFF_VOL_MAX); + return false; + } + + int val = readRegister(AXP202_VOFF_SET); + if (val == -1) + return false; + val &= 0xF8; + val |= (millivolt - AXP202_VOFF_VOL_MIN) / AXP202_SYS_VOL_STEPS; + return 0 == writeRegister(AXP202_VOFF_SET, val); + } + + uint16_t getSysPowerDownVoltage() + { + int val = readRegister(AXP202_VOFF_SET); + if (val == -1) + return 0; + val &= 0x07; + return (val * AXP202_SYS_VOL_STEPS) + AXP202_VOFF_VOL_MIN; + } + + /** + * @brief Set shutdown, calling shutdown will turn off all power channels, + * only VRTC belongs to normal power supply + * @retval None + */ + void shutdown() + { + setRegisterBit(AXP202_OFF_CTL, 7); + } + + /* + * Charge setting + */ + void enableCharge() + { + setRegisterBit(AXP202_CHARGE1, 7); + } + + void disableCharge() + { + clrRegisterBit(AXP202_CHARGE1, 7); + } + + /** + * @brief Set charge target voltage. + * @param opt: See pmic_chg_vol enum for details. + * @retval + */ + bool setChargeTargetVoltage(pmic_chg_vol opt) + { + if (opt >= AXP202_CHG_VOL_MAX) + return false; + int val = readRegister(AXP202_CHARGE1); + if (val == -1) + return false; + val &= 0x9F; + return 0 == writeRegister(AXP202_CHARGE1, val | (opt << 5)); + } + + /** + * @brief Get charge target voltage settings. + * @retval See pmic_chg_vol enum for details. + */ + pmic_chg_vol getChargeTargetVoltage() + { + int val = readRegister(AXP202_CHARGE1); + if (val == -1) + return pmic_chg_vol(0); + return static_cast((val & 0x60) >> 5); + } + + /** + * @brief Set charge current settings. + * @retval See pmic_chg_curr enum for details. + */ + bool setChargerConstantCurr(pmic_chg_curr opt) + { + if (opt > 0x0F) + return false; + int val = readRegister(AXP202_CHARGE1); + if (val == -1) + { + return false; + } + val &= 0xF0; + return 0 == writeRegister(AXP202_CHARGE1, val | opt); + } + + /** + * @brief Get charge current settings. + * @retval See pmic_chg_curr enum for details. + */ + pmic_chg_curr getChargerConstantCurr(void) + { + int val = readRegister(AXP202_CHARGE1) & 0x0F; + // if (val == -1)return AXP202_CHG_CUR_780MA; + // todo: + return static_cast(val); + } + + void setChargerTerminationCurr(pmic_chg_iterm opt) + { + switch (opt) + { + case AXP202_CHG_ITERM_LESS_10_PERCENT: + clrRegisterBit(AXP202_CHARGE1, 0); + break; + case AXP202_CHG_ITERM_LESS_15_PERCENT: + setRegisterBit(AXP202_CHARGE1, 0); + break; + default: + break; + } + } + + pmic_chg_iterm getChargerTerminationCurr() + { + return static_cast(getRegisterBit(AXP202_CHARGE1, 4)); + } + + bool setPrechargeTimeout(pmic_prechg_to opt) + { + int val = readRegister(AXP202_CHARGE2); + if (val == -1) + return false; + val &= 0x3F; + return 0 == writeRegister(AXP202_CHARGE2, val | (opt << 6)); + } + + // External channel charge current setting,Range:300~1000mA + bool setChargerExternChannelCurr(uint16_t milliampere) + { + if (milliampere % AXP202_CHG_EXT_CURR_STEP) + { + log_e("Mistake ! The steps is must %u mV", AXP202_CHG_EXT_CURR_STEP); + return false; + } + if (milliampere < AXP202_CHG_EXT_CURR_MIN) + { + log_e("Mistake ! The minimum external path charge current setting is: %umA", AXP202_CHG_EXT_CURR_MIN); + return false; + } + else if (milliampere > AXP202_CHG_EXT_CURR_MAX) + { + log_e("Mistake ! The maximum external channel charge current setting is: %umA", AXP202_CHG_EXT_CURR_MAX); + return false; + } + int val = readRegister(AXP202_CHARGE2); + if (val == -1) + return false; + val &= 0xC7; + val |= ((milliampere - AXP202_CHG_EXT_CURR_MIN) / AXP202_CHG_EXT_CURR_STEP); + return 0 == writeRegister(AXP202_CHARGE2, val); + } + + bool enableChargerExternChannel() + { + return setRegisterBit(AXP202_CHARGE2, 2); + } + + bool disableChargerExternChannel() + { + return clrRegisterBit(AXP202_CHARGE2, 2); + } + + // Timeout setting in constant current mode + bool setChargerConstantTimeout(pmic_chg_cons_to opt) + { + int val = readRegister(AXP202_CHARGE2); + if (val == -1) + return false; + val &= 0xFC; + return 0 == writeRegister(AXP202_CHARGE2, val | opt); + } + + bool enableBackupBattCharger() + { + return setRegisterBit(AXP202_BACKUP_CHG, 7); + } + + bool disableBackupBattCharger() + { + return clrRegisterBit(AXP202_BACKUP_CHG, 7); + } + + bool isEnableBackupCharger() + { + return getRegisterBit(AXP202_BACKUP_CHG, 7); + } + + bool setBackupBattChargerVoltage(pmic_backup_batt_vol opt) + { + int val = readRegister(AXP202_BACKUP_CHG); + if (val == -1) + return false; + val &= 0x9F; + return 0 == writeRegister(AXP202_BACKUP_CHG, val | (opt << 5)); + } + + bool setBackupBattChargerCurr(pmic_backup_batt_curr opt) + { + int val = readRegister(AXP202_BACKUP_CHG); + if (val == -1) + return false; + val &= 0xFC; + return 0 == writeRegister(AXP202_BACKUP_CHG, val | opt); + } + + /* + * Temperature + */ + float getTemperature() + { + return readRegisterH8L4(AXP202_INTERNAL_TEMP_H8, AXP202_INTERNAL_TEMP_L4) * AXP202_INTERNAL_TEMP_STEP - AXP202_INERNAL_TEMP_OFFSET; + } + + bool enableTemperatureMeasure() + { + return setRegisterBit(AXP202_ADC_EN2, 7); + } + + bool disableTemperatureMeasure() + { + return clrRegisterBit(AXP202_ADC_EN2, 7); + } + + /* + * Power control LDOio functions + */ + bool isEnableLDOio(void) + { + int val = readRegister(AXP202_GPIO0_CTL); + return (val & 0x02); + } + + bool enableLDOio(void) + { + int val = readRegister(AXP202_GPIO0_CTL) & 0xF8; + return 0 == writeRegister(AXP202_GPIO0_CTL, val | 0x02); + } + + bool disableLDOio(void) + { + int val = readRegister(AXP202_GPIO0_CTL) & 0xF8; + return 0 == writeRegister(AXP202_GPIO0_CTL, val); + } + + bool setLDOioVoltage(uint16_t millivolt) + { + if (millivolt % AXP202_LDOIO_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", AXP202_LDOIO_VOL_STEPS); + return false; + } + if (millivolt < AXP202_LDOIO_VOL_MIN) + { + log_e("Mistake ! LDOIO minimum output voltage is %umV", AXP202_LDOIO_VOL_MIN); + return false; + } + else if (millivolt > AXP202_LDOIO_VOL_MAX) + { + log_e("Mistake ! LDOIO maximum output voltage is %umV", AXP202_LDOIO_VOL_MAX); + return false; + } + int val = readRegister(AXP202_GPIO0_VOL); + if (val == -1) + return false; + val |= (((millivolt - AXP202_LDOIO_VOL_MIN) / AXP202_LDOIO_VOL_STEPS) << 4); + return 0 == writeRegister(AXP202_GPIO0_VOL, val); + } + + uint16_t getLDOioVoltage(void) + { + int val = readRegister(AXP202_GPIO0_VOL); + if (val == -1) + return 0; + val >>= 4; + val *= AXP202_LDOIO_VOL_STEPS; + val += AXP202_LDOIO_VOL_MIN; + return val; + } + + /* + * Power control LDO2 functions + */ + bool isEnableLDO2(void) + { + return getRegisterBit(AXP202_LDO234_DC23_CTL, 2); + } + + bool enableLDO2(void) + { + return setRegisterBit(AXP202_LDO234_DC23_CTL, 2); + } + + bool disableLDO2(void) + { + return clrRegisterBit(AXP202_LDO234_DC23_CTL, 2); + } + + bool setLDO2Voltage(uint16_t millivolt) + { + if (millivolt % AXP202_LDO2_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", AXP202_LDO2_VOL_STEPS); + return false; + } + if (millivolt < AXP202_LDO2_VOL_MIN) + { + log_e("Mistake ! LDO2 minimum output voltage is %umV", AXP202_LDO2_VOL_MIN); + return false; + } + else if (millivolt > AXP202_LDO2_VOL_MAX) + { + log_e("Mistake ! LDO2 maximum output voltage is %umV", AXP202_LDO2_VOL_MAX); + return false; + } + + int val = readRegister(AXP202_LDO24OUT_VOL); + if (val == -1) + return false; + val &= 0x0F; + return 0 == writeRegister(AXP202_LDO24OUT_VOL, val | (((millivolt - AXP202_LDO2_VOL_MIN) / AXP202_LDO2_VOL_STEPS) << AXP202_LDO2_VOL_BIT_MASK)); + } + + uint16_t getLDO2Voltage(void) + { + int val = readRegister(AXP202_LDO24OUT_VOL) & 0xF0; + return (val >> AXP202_LDO2_VOL_BIT_MASK) * AXP202_LDO2_VOL_STEPS + AXP202_LDO2_VOL_MIN; + } + + /* + * Power control LDO3 functions + */ + bool isEnableLDO3(void) + { + return getRegisterBit(AXP202_LDO234_DC23_CTL, 6); + } + + bool enableLDO3(void) + { + return setRegisterBit(AXP202_LDO234_DC23_CTL, 6); + } + + bool disableLDO3(void) + { + return clrRegisterBit(AXP202_LDO234_DC23_CTL, 6); + } + + bool setLDO3Voltage(uint16_t millivolt) + { + if (millivolt % AXP202_LDO3_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", AXP202_LDO3_VOL_STEPS); + return false; + } + if (millivolt < AXP202_LDO3_VOL_MIN) + { + log_e("Mistake ! LDO3 minimum output voltage is %umV", AXP202_LDO3_VOL_MIN); + return false; + } + else if (millivolt > AXP202_LDO3_VOL_MAX) + { + log_e("Mistake ! LDO3 maximum output voltage is %umV", AXP202_LDO3_VOL_MAX); + return false; + } + int val = readRegister(AXP202_LDO3OUT_VOL) & 0x80; + return 0 == writeRegister(AXP202_LDO3OUT_VOL, val | ((millivolt - AXP202_LDO3_VOL_MIN) / AXP202_LDO3_VOL_STEPS)); + } + + uint16_t getLDO3Voltage(void) + { + int val = readRegister(AXP202_LDO3OUT_VOL); + if (val == -1) + return 0; + // Returns the voltage value of VBUS if in pass-through mode + if (val & 0x80) + { + log_i("ldo3 pass-through mode"); + return getVbusVoltage(); + } + val &= 0x7F; + return (val * AXP202_LDO3_VOL_STEPS) + AXP202_LDO3_VOL_MIN; + } + + /* + * Power control LDO4 functions + */ + bool isEnableLDO4(void) + { + return getRegisterBit(AXP202_LDO234_DC23_CTL, 3); + } + + bool enableLDO4(void) + { + return setRegisterBit(AXP202_LDO234_DC23_CTL, 3); + } + + bool disableLDO4(void) + { + return clrRegisterBit(AXP202_LDO234_DC23_CTL, 3); + } + + // Support setting voltage + // 1.25 + // 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 + // 2.5 2.7 2.8 3.0 3.1 3.2 3.3 + bool setLDO4Voltage(uint16_t millivolt) + { + int index = -1; + for (int i = 0; i < 16; ++i) + { + if (ldo4_table[i] == millivolt) + { + index = i; + break; + } + } + if (index == -1) + { + log_e("Mistake ! Out of adjustment range"); + return false; + } + int val = readRegister(AXP202_LDO24OUT_VOL); + if (val == -1) + { + return false; + } + return 0 == writeRegister(AXP202_LDO24OUT_VOL, (val & 0xF0) | index); + } + + uint16_t getLDO4Voltage(void) + { + int val = readRegister(AXP202_LDO24OUT_VOL); + if (val == -1) + return 0; + val &= 0x0F; + return ldo4_table[val]; + } + + /* + * Power control DCDC2 functions + */ + void setDC2PwmMode(void) + { + int val = readRegister(AXP202_DCDC_MODESET) & 0xFB; + writeRegister(AXP202_DCDC_MODESET, val | 0x04); + } + + void setDC2AutoMode(void) + { + int val = readRegister(AXP202_DCDC_MODESET) & 0xFB; + writeRegister(AXP202_DCDC_MODESET, val); + } + + void enableDC2VRC(void) + { + // int val = readRegister(AXP202_DC2_DVM); + // writeRegister(AXP202_DC2_DVM, val | 0x04); + } + + void disableDC2VRC(void) + { + // int val = readRegister(AXP202_DC2_DVM); + // writeRegister(AXP202_DC2_DVM, val & 0xFB); + } + + bool setDC2VRC(uint8_t opts) + { + // if (opts > 1) { + // return false; + // } + // int val = readRegister(AXP202_DC2_DVM) & 0xFE; + // writeRegister(AXP202_DC2_DVM, val | opts); + return false; + } + + bool isEnableDC2VRC(void) + { + // return (readRegister(AXP202_DC2_DVM) & 0x04) == 0x04; + return 0; + } + + bool isEnableDC2(void) + { + return getRegisterBit(AXP202_LDO234_DC23_CTL, 4); + } + + bool enableDC2(void) + { + return setRegisterBit(AXP202_LDO234_DC23_CTL, 4); + } + + bool disableDC2(void) + { + return clrRegisterBit(AXP202_LDO234_DC23_CTL, 4); + } + + bool setDC2Voltage(uint16_t millivolt) + { + if (millivolt % AXP202_DC2_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", AXP202_DC2_VOL_STEPS); + return false; + } + if (millivolt < AXP202_DC2_VOL_MIN) + { + log_e("Mistake ! DCDC2 minimum output voltage is %umV", AXP202_DC2_VOL_MIN); + return false; + } + else if (millivolt > AXP202_DC2_VOL_MAX) + { + log_e("Mistake ! DCDC2 maximum output voltage is %umV", AXP202_DC2_VOL_MAX); + return false; + } + int val = readRegister(AXP202_DC2OUT_VOL); + if (val == -1) + return false; + val &= 0x80; + val |= (millivolt - AXP202_DC2_VOL_MIN) / AXP202_DC2_VOL_STEPS; + return 0 == writeRegister(AXP202_DC2OUT_VOL, val); + } + + uint16_t getDC2Voltage(void) + { + int val = readRegister(AXP202_DC2OUT_VOL); + if (val == -1) + return 0; + return (val * AXP202_DC2_VOL_STEPS) + AXP202_DC2_VOL_MIN; + } + + /* + * Power control DCDC3 functions + */ + void setDC3PwmMode(void) + { + int val = readRegister(AXP202_DCDC_MODESET) & 0xFD; + writeRegister(AXP202_DCDC_MODESET, val | 0x02); + } + + void setDC3AutoMode(void) + { + int val = readRegister(AXP202_DCDC_MODESET) & 0xFD; + writeRegister(AXP202_DCDC_MODESET, val); + } + + bool isEnableDC3(void) + { + return getRegisterBit(AXP202_LDO234_DC23_CTL, 1); + } + + bool enableDC3(void) + { + return setRegisterBit(AXP202_LDO234_DC23_CTL, 1); + } + + bool disableDC3(void) + { + return clrRegisterBit(AXP202_LDO234_DC23_CTL, 1); + } + + bool setDC3Voltage(uint16_t millivolt) + { + if (millivolt % AXP202_DC3_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", AXP202_DC3_VOL_STEPS); + return false; + } + if (millivolt < AXP202_DC3_VOL_MIN) + { + log_e("Mistake ! DCDC3 minimum output voltage is %umV", AXP202_DC3_VOL_MIN); + return false; + } + else if (millivolt > AXP202_DC3_VOL_MAX) + { + log_e("Mistake ! DCDC3 maximum output voltage is %umV", AXP202_DC3_VOL_MAX); + return false; + } + return 0 == writeRegister(AXP202_DC3OUT_VOL, (millivolt - AXP202_DC3_VOL_MIN) / AXP202_DC3_VOL_STEPS); + } + + uint16_t getDC3Voltage(void) + { + int val = readRegister(AXP202_DC3OUT_VOL); + if (val == -1) + return 0; + return (val * AXP202_DC3_VOL_STEPS) + AXP202_DC3_VOL_MIN; + } + + /* + * Power control EXTEN functions + */ + bool enableExternalPin(void) + { + return setRegisterBit(AXP202_LDO234_DC23_CTL, 6); + } + + bool disableExternalPin(void) + { + return clrRegisterBit(AXP202_LDO234_DC23_CTL, 6); + } + + bool isEnableExternalPin(void) + { + return getRegisterBit(AXP202_LDO234_DC23_CTL, 6); + } + + /* + * Interrupt status functions + */ + + /** + * @brief Get the interrupt controller mask value. + * @retval Mask value corresponds to axp202_irq , + */ + uint64_t getIrqStatus(void) + { + statusRegister[0] = readRegister(AXP202_INTSTS1); + statusRegister[1] = readRegister(AXP202_INTSTS2); + statusRegister[2] = readRegister(AXP202_INTSTS3); + statusRegister[3] = readRegister(AXP202_INTSTS4); + statusRegister[4] = readRegister(AXP202_INTSTS5); + return ((uint64_t)statusRegister[4]) << 32 | + ((uint64_t)statusRegister[3]) << 24 | + ((uint64_t)statusRegister[2]) << 16 | + ((uint64_t)statusRegister[1]) << 8 | + ((uint64_t)statusRegister[0]); + } + + /** + * @brief Clear interrupt controller state. + */ + void clearIrqStatus(void) + { + for (int i = 0; i < 4; i++) + { + writeRegister(AXP202_INTSTS1 + i, 0xFF); + statusRegister[i] = 0; + } + writeRegister(AXP202_INTSTS5, 0xFF); + } + + /** + * @brief Enable PMU interrupt control mask . + * @param opt: View the related chip type axp202_irq_t enumeration + * parameters in the registries + * @retval + */ + bool enableIRQ(pmic_irq opt) + { + return setInterruptImpl(opt, true); + } + + /** + * @brief Disable PMU interrupt control mask . + * @param opt: View the related chip type axp202_irq_t enumeration + * parameters in the registries + * @retval + */ + bool disableIRQ(pmic_irq opt) + { + return setInterruptImpl(opt, false); + } + + bool isAcinOverVoltageIrq(void) + { + uint8_t mask = AXP202_ACIN_OVER_VOL_IRQ; + if (intRegister[0] & mask) + { + return IS_BIT_SET(statusRegister[0], mask); + } + return false; + } + + bool isAcinInserIrq(void) + { + uint8_t mask = AXP202_ACIN_CONNECT_IRQ; + if (intRegister[0] & mask) + { + return IS_BIT_SET(statusRegister[0], mask); + } + return false; + } + + bool isAcinRemoveIrq(void) + { + uint8_t mask = AXP202_ACIN_REMOVED_IRQ; + if (intRegister[0] & mask) + { + return IS_BIT_SET(statusRegister[0], mask); + } + return false; + } + + bool isVbusOverVoltageIrq(void) + { + uint8_t mask = AXP202_VBUS_OVER_VOL_IRQ; + if (intRegister[0] & mask) + { + return IS_BIT_SET(statusRegister[0], mask); + } + return false; + } + + bool isVbusInsertIrq(void) + { + uint8_t mask = AXP202_VBUS_INSERT_IRQ; + if (intRegister[0] & mask) + { + return IS_BIT_SET(statusRegister[0], mask); + } + return false; + } + + bool isVbusRemoveIrq(void) + { + uint8_t mask = AXP202_VBUS_REMOVE_IRQ; + if (intRegister[0] & mask) + { + return IS_BIT_SET(statusRegister[0], mask); + } + return false; + } + + bool isVbusLowVholdIrq(void) + { + uint8_t mask = AXP202_VBUS_VHOLD_LOW_IRQ; + if (intRegister[0] & mask) + { + return IS_BIT_SET(statusRegister[0], mask); + } + return false; + } + + bool isBatInsertIrq(void) + { + uint8_t mask = AXP202_BAT_INSERT_IRQ >> 8; + if (intRegister[1] & mask) + { + return IS_BIT_SET(statusRegister[1], mask); + } + return false; + } + + bool isBatRemoveIrq(void) + { + uint8_t mask = AXP202_BAT_REMOVE_IRQ >> 8; + if (intRegister[1] & mask) + { + return IS_BIT_SET(statusRegister[1], mask); + } + return false; + } + + bool isBattEnterActivateIrq(void) + { + uint8_t mask = AXP202_BATT_ACTIVATE_IRQ >> 8; + if (intRegister[1] & mask) + { + return IS_BIT_SET(statusRegister[1], mask); + } + return false; + } + + bool isBattExitActivateIrq(void) + { + uint8_t mask = AXP202_BATT_EXIT_ACTIVATE_IRQ >> 8; + if (intRegister[1] & mask) + { + return IS_BIT_SET(statusRegister[1], mask); + } + return false; + } + + bool isBatChargeStartIrq(void) + { + uint8_t mask = AXP202_BAT_CHG_START_IRQ >> 8; + if (intRegister[1] & mask) + { + return IS_BIT_SET(statusRegister[1], mask); + } + return false; + } + + bool isBatChargeDoneIrq(void) + { + uint8_t mask = AXP202_BAT_CHG_DONE_IRQ >> 8; + if (intRegister[1] & mask) + { + return IS_BIT_SET(statusRegister[1], mask); + } + return false; + } + + bool isBattTempHighIrq(void) + { + uint8_t mask = AXP202_BATT_OVER_TEMP_IRQ >> 8; + if (intRegister[1] & mask) + { + return IS_BIT_SET(statusRegister[1], mask); + } + return false; + } + + bool isBattTempLowIrq(void) + { + uint8_t mask = AXP202_BATT_LOW_TEMP_IRQ >> 8; + if (intRegister[1] & mask) + { + return IS_BIT_SET(statusRegister[1], mask); + } + return false; + } + + bool isChipOverTemperatureIrq(void) + { + uint8_t mask = AXP202_CHIP_TEMP_HIGH_IRQ >> 16; + if (intRegister[2] & mask) + { + return IS_BIT_SET(statusRegister[2], mask); + } + return false; + } + + bool isChargingCurrentLessIrq(void) + { + uint8_t mask = AXP202_CHARGE_LOW_CUR_IRQ >> 16; + if (intRegister[2] & mask) + { + return IS_BIT_SET(statusRegister[2], mask); + } + return false; + } + + bool isDC2VoltageLessIrq(void) + { + uint8_t mask = AXP202_DC2_LOW_VOL_IRQ >> 16; + if (intRegister[2] & mask) + { + return IS_BIT_SET(statusRegister[2], mask); + } + return false; + } + + bool isDC3VoltageLessIrq(void) + { + uint8_t mask = AXP202_DC3_LOW_VOL_IRQ >> 16; + if (intRegister[2] & mask) + { + return IS_BIT_SET(statusRegister[2], mask); + } + return false; + } + + bool isLDO3VoltageLessIr1(void) + { + uint8_t mask = AXP202_LDO3_LOW_VOL_IRQ >> 16; + if (intRegister[2] & mask) + { + return IS_BIT_SET(statusRegister[2], mask); + } + return false; + } + + bool isPekeyShortPressIrq(void) + { + uint8_t mask = AXP202_PKEY_SHORT_IRQ >> 16; + if (intRegister[2] & mask) + { + return IS_BIT_SET(statusRegister[2], mask); + } + return false; + } + + bool isPekeyLongPressIrq(void) + { + uint8_t mask = AXP202_PKEY_LONG_IRQ >> 16; + if (intRegister[2] & mask) + { + return IS_BIT_SET(statusRegister[2], mask); + } + return false; + } + + bool isNOEPowerOnIrq(void) + { + uint8_t mask = AXP202_NOE_ON_IRQ >> 24; + if (intRegister[3] & mask) + { + return IS_BIT_SET(statusRegister[3], mask); + } + return false; + } + + bool isNOEPowerDownIrq(void) + { + uint8_t mask = AXP202_NOE_OFF_IRQ >> 24; + if (intRegister[3] & mask) + { + return IS_BIT_SET(statusRegister[3], mask); + } + return false; + } + + bool isVbusEffectiveIrq(void) + { + uint8_t mask = AXP202_VBUS_VAILD_IRQ >> 24; + if (intRegister[3] & mask) + { + return IS_BIT_SET(statusRegister[3], mask); + } + return false; + } + + bool isVbusInvalidIrq(void) + { + uint8_t mask = AXP202_VBUS_INVALID_IRQ >> 24; + if (intRegister[3] & mask) + { + return IS_BIT_SET(statusRegister[3], mask); + } + return false; + } + + bool isVbusSessionIrq(void) + { + uint8_t mask = AXP202_VBUS_SESSION_AB_IRQ >> 24; + if (intRegister[3] & mask) + { + return IS_BIT_SET(statusRegister[3], mask); + } + return false; + } + + bool isVbusSessionEndIrq(void) + { + uint8_t mask = AXP202_VBUS_SESSION_END_IRQ >> 24; + if (intRegister[3] & mask) + { + return IS_BIT_SET(statusRegister[3], mask); + } + return false; + } + + bool isLowVoltageLevel1Irq(void) + { + uint8_t mask = APX202_APS_LOW_VOL_LEVEL1_IRQ >> 24; + if (intRegister[3] & mask) + { + return IS_BIT_SET(statusRegister[3], mask); + } + return false; + } + + bool isLowVoltageLevel2Irq(void) + { + uint8_t mask = AXP202_APS_LOW_VOL_LEVEL2_IRQ >> 24; + if (intRegister[3] & mask) + { + return IS_BIT_SET(statusRegister[3], mask); + } + return false; + } + + // IRQ5 REGISTER : + bool isWdtExpireIrq(void) + { + uint8_t mask = AXP202_GPIO3_EDGE_TRIGGER_IRQ >> 32; + if (intRegister[4] & mask) + { + return IS_BIT_SET(statusRegister[4], mask); + } + return false; + } + + bool isGpio2EdgeTriggerIrq(void) + { + uint8_t mask = AXP202_GPIO2_EDGE_TRIGGER_IRQ >> 32; + if (intRegister[4] & mask) + { + return IS_BIT_SET(statusRegister[4], mask); + } + return false; + } + + bool isGpio1EdgeTriggerIrq(void) + { + uint8_t mask = AXP202_GPIO1_EDGE_TRIGGER_IRQ >> 32; + if (intRegister[2] & mask) + { + return IS_BIT_SET(statusRegister[2], mask); + } + return false; + } + + bool isGpio0EdgeTriggerIrq(void) + { + uint8_t mask = AXP202_GPIO0_EDGE_TRIGGER_IRQ >> 32; + if (intRegister[4] & mask) + { + return IS_BIT_SET(statusRegister[4], mask); + } + return false; + } + + /* + * ADC Functions + */ + + bool enableBattDetection() + { + return setRegisterBit(AXP202_OFF_CTL, 6); + } + + bool disableBattDetection() + { + return clrRegisterBit(AXP202_OFF_CTL, 6); + } + + bool enableVbusVoltageMeasure() + { + return setSignalCaptureImpl(MONITOR_USB_CURRENT | MONITOR_USB_VOLTAGE, true); + } + + bool disableVbusVoltageMeasure() + { + return setSignalCaptureImpl(MONITOR_USB_CURRENT | MONITOR_USB_VOLTAGE, false); + } + + bool enableBattVoltageMeasure() + { + return setSignalCaptureImpl(MONITOR_BAT_CURRENT | MONITOR_BAT_VOLTAGE, true); + } + + bool disableBattVoltageMeasure() + { + return setSignalCaptureImpl(MONITOR_BAT_CURRENT | MONITOR_BAT_VOLTAGE, false); + } + + bool enableSystemVoltageMeasure() + { + return setSignalCaptureImpl(MONITOR_APS_VOLTAGE, true); + } + + bool disableSystemVoltageMeasure() + { + return setSignalCaptureImpl(MONITOR_APS_VOLTAGE, false); + } + + bool enableTSPinMeasure() + { + return setSignalCaptureImpl(MONITOR_TS_PIN, true); + } + + bool disableTSPinMeasure() + { + return setSignalCaptureImpl(MONITOR_TS_PIN, false); + } + + bool enableAdcChannel(uint32_t opts) + { + return setSignalCaptureImpl(opts, true); + } + + bool disableAdcChannel(uint32_t opts) + { + return setSignalCaptureImpl(opts, false); + } + + uint16_t getVbusVoltage() + { + if (!isVbusIn()) + { + return 0; + } + return readRegisterH8L4(AXP202_VBUS_VOL_H8, + AXP202_VBUS_VOL_L4) * + AXP202_VBUS_VOLTAGE_STEP; + } + + float getVbusCurrent() + { + if (!isVbusIn()) + { + return 0; + } + return readRegisterH8L4(AXP202_VBUS_CUR_H8, + AXP202_VBUS_CUR_L4) * + AXP202_VBUS_CUR_STEP; + } + + uint16_t getBattVoltage() + { + if (!isBatteryConnect()) + { + return 0; + } + return readRegisterH8L4(AXP202_BAT_AVERVOL_H8, + AXP202_BAT_AVERVOL_L4) * + AXP202_BATT_VOLTAGE_STEP; + } + + float getBattDischargeCurrent() + { + if (!isBatteryConnect()) + { + return 0; + } + return readRegisterH8L5(AXP202_BAT_AVERDISCHGCUR_H8, + AXP202_BAT_AVERDISCHGCUR_L5) * + AXP202_BATT_DISCHARGE_CUR_STEP; + } + + uint16_t getAcinVoltage() + { + if (!isAcinIn()) + { + return 0; + } + return readRegisterH8L4(AXP202_ACIN_VOL_H8, AXP202_ACIN_VOL_L4) * AXP202_ACIN_VOLTAGE_STEP; + } + + float getAcinCurrent() + { + if (!isAcinIn()) + { + return 0; + } + return readRegisterH8L4(AXP202_ACIN_CUR_H8, AXP202_ACIN_CUR_L4) * AXP202_ACIN_CUR_STEP; + } + + uint16_t getSystemVoltage() + { + return readRegisterH8L4(AXP202_APS_AVERVOL_H8, AXP202_APS_AVERVOL_L4) * AXP202_APS_VOLTAGE_STEP; + } + + /* + * Timer Control + */ + void setTimerout(uint8_t minute) + { + writeRegister(AXP202_TIMER_CTL, 0x80 | minute); + } + + void disableTimer() + { + writeRegister(AXP202_TIMER_CTL, 0x80); + } + + void clearTimerFlag() + { + setRegisterBit(AXP202_TIMER_CTL, 7); + } + + /* + * Data Buffer + */ + bool writeDataBuffer(uint8_t *data, uint8_t size) + { + if (size > AXP202_DATA_BUFFER_SIZE) + return false; + for (int i = 0; i < size; ++i) + { + writeRegister(AXP202_DATA_BUFFER1 + i, data[i]); + } + return true; + } + + bool readDataBuffer(uint8_t *data, uint8_t size) + { + if (size > AXP202_DATA_BUFFER_SIZE) + return false; + for (int i = 0; i < size; ++i) + { + data[i] = readRegister(AXP202_DATA_BUFFER1 + i); + } + return true; + } + + /* + * Charge led functions + */ + + /** + * @brief Set charging led mode. + * @retval See chg_led_mode_t enum for details. + */ + void setChargingLedMode(pmic_chg_led_mode mode) + { + int val; + switch (mode) + { + case CHG_LED_OFF: + case CHG_LED_BLINK_1HZ: + case CHG_LED_BLINK_4HZ: + case CHG_LED_ON: + val = readRegister(AXP202_OFF_CTL); + if (val == -1) + return; + val &= 0xC7; + val |= 0x08; // use manual ctrl + val |= (mode << 4); + writeRegister(AXP202_OFF_CTL, val); + break; + case CHG_LED_CTRL_CHG: + clrRegisterBit(AXP202_OFF_CTL, 3); + break; + default: + break; + } + } + + pmic_chg_led_mode getChargingLedMode() + { + if (!getRegisterBit(AXP202_OFF_CTL, 3)) + { + return CHG_LED_CTRL_CHG; + } + int val = readRegister(AXP202_OFF_CTL); + if (val == -1) + return CHG_LED_OFF; + val &= 0x30; + return static_cast(val >> 4); + } + + /* + * Coulomb counter control + */ + void enableCoulomb() + { + setRegisterBit(AXP202_COULOMB_CTL, 7); + } + + void disableCoulomb() + { + clrRegisterBit(AXP202_COULOMB_CTL, 7); + } + + void stopCoulomb() + { + setRegisterBit(AXP202_COULOMB_CTL, 6); + } + + void clearCoulomb() + { + setRegisterBit(AXP202_COULOMB_CTL, 5); + } + + uint32_t getBattChargeCoulomb() + { + int data[4]; + data[0] = readRegister(AXP202_BAT_CHGCOULOMB3); + data[1] = readRegister(AXP202_BAT_CHGCOULOMB2); + data[2] = readRegister(AXP202_BAT_CHGCOULOMB1); + data[3] = readRegister(AXP202_BAT_CHGCOULOMB0); + for (int i = 0; i < 4; ++i) + { + if (data[i] == -1) + return 0; + } + return ((uint32_t)data[0] << 24) | ((uint32_t)data[1] << 16) | ((uint32_t)data[2] << 8) | (uint32_t)data[3]; + } + + uint32_t getBattDischargeCoulomb() + { + int data[4]; + data[0] = readRegister(AXP202_BAT_DISCHGCOULOMB3); + data[1] = readRegister(AXP202_BAT_DISCHGCOULOMB2); + data[2] = readRegister(AXP202_BAT_DISCHGCOULOMB1); + data[3] = readRegister(AXP202_BAT_DISCHGCOULOMB0); + for (int i = 0; i < 4; ++i) + { + if (data[i] == -1) + return 0; + } + return ((uint32_t)data[0] << 24) | ((uint32_t)data[1] << 16) | ((uint32_t)data[2] << 8) | (uint32_t)data[3]; + } + + uint8_t getAdcSamplingRate(void) + { + int val = readRegister(AXP202_ADC_SPEED); + if (val == -1) + return 0; + return 25 * (int)pow(2, (val & 0xC0) >> 6); + } + + float getCoulombData(void) + { + uint32_t charge = getBattChargeCoulomb(), discharge = getBattDischargeCoulomb(); + uint8_t rate = getAdcSamplingRate(); + float result = 65536.0 * 0.5 * ((float)charge - (float)discharge) / 3600.0 / rate; + return result; + } + + /* + * GPIO control functions + */ + float getBatteryChargeCurrent(void) + { + return readRegisterH8L5( + AXP202_BAT_AVERCHGCUR_H8, + AXP202_BAT_AVERCHGCUR_L5) * + AXP202_BATT_CHARGE_CUR_STEP; + } + + uint16_t getGpio0Voltage() + { + return readRegisterH8L4(AXP202_GPIO0_VOL_ADC_H8, AXP202_GPIO0_VOL_ADC_L4) * AXP202_GPIO0_STEP * 1000; + } + + uint16_t getGpio1Voltage() + { + return readRegisterH8L4(AXP202_GPIO1_VOL_ADC_H8, AXP202_GPIO1_VOL_ADC_L4) * AXP202_GPIO1_STEP * 1000; + } + + uint8_t getBatteryPercent(void) + { + if (!isBatteryConnect()) + { + return -1; + } + const static int table[11] = { + 3000, 3650, 3700, 3740, 3760, 3795, + 3840, 3910, 3980, 4070, 4150}; + uint16_t voltage = getBattVoltage(); + if (voltage < table[0]) + return 0; + for (int i = 0; i < 11; i++) + { + if (voltage < table[i]) + return i * 10 - (10UL * (int)(table[i] - voltage)) / + (int)(table[i] - table[i - 1]); + ; + } + return 100; + } + + uint8_t getChipID(void) + { + return readRegister(AXP202_IC_TYPE); + } + + /** + * Sleep function + */ + bool enableSleep() + { + return setRegisterBit(AXP202_VOFF_SET, 3); + } + + /* + * Pekey function + */ + + /** + * @brief Set the PEKEY power-on long press time. + * @param opt: See pmic_press_on_time enum for details. + * @retval + */ + bool setPowerKeyPressOnTime(pmic_press_on_time opt) + { + int val = readRegister(AXP202_POK_SET); + if (val == -1) + return false; + return 0 == writeRegister(AXP202_POK_SET, (val & 0x3F) | (opt << 6)); + } + + /** + * @brief Get the PEKEY power-on long press time. + * @retval See pmic_press_on_time enum for details. + */ + pmic_press_on_time getPowerKeyPressOnTime() + { + int val = readRegister(AXP202_POK_SET); + if (val == -1) + return pmic_press_on_time(0); + return pmic_press_on_time((val & 0xC0) >> 6); + } + + /** + * @brief Set the PEKEY power-off long press time. + * @param opt: See pmic_press_off_time enum for details. + * @retval + */ + bool setPowerKeyPressOffTime(pmic_press_off_time opt) + { + int val = readRegister(AXP202_POK_SET); + if (val == -1) + return false; + return 0 == writeRegister(AXP202_POK_SET, (val & 0xFC) | opt); + } + + /** + * @brief Get the PEKEY power-off long press time. + * @retval See pmic_press_off_time enum for details. + */ + pmic_press_off_time getPowerKeyPressOffTime() + { + int val = readRegister(AXP202_POK_SET); + if (val == -1) + return pmic_press_off_time(0); + return static_cast(val & 0x03); + } + + void setPowerKeyLongPressOnTime(pmic_pekey_long_press opt) + { + int val = readRegister(AXP202_POK_SET); + if (val == -1) + return; + writeRegister(AXP202_POK_SET, (val & 0xCF) | (opt << 4)); + } + + void enablePowerKeyLongPressPowerOff() + { + setRegisterBit(AXP202_POK_SET, 3); + } + + void disablePowerKeyLongPressPowerOff() + { + clrRegisterBit(AXP202_POK_SET, 3); + } + + protected: + uint16_t getPowerChannelVoltage(PMICPowerChannel channel) + { + switch (channel) + { + case DCDC2: + return getDC2Voltage(); + case DCDC3: + return getDC3Voltage(); + case LDO2: + return getLDO2Voltage(); + case LDO3: + return getLDO3Voltage(); + case LDO4: + return getLDO4Voltage(); + case LDOIO: + return getLDOioVoltage(); + default: + break; + } + return 0; + } + + bool inline enablePowerOutput(PMICPowerChannel channel) + { + switch (channel) + { + case DCDC2: + return enableDC2(); + case DCDC3: + return enableDC3(); + case LDO2: + return enableLDO2(); + case LDO3: + return enableLDO3(); + case LDO4: + return enableLDO4(); + case LDOIO: + return enableLDOio(); + case VBACKUP: + return enableBackupBattCharger(); + default: + break; + } + return false; + } + + bool inline disablePowerOutput(PMICPowerChannel channel) + { + if (getProtectedChannel(channel)) + { + log_e("Failed to disable the power channel, the power channel has been protected"); + return false; + } + switch (channel) + { + case DCDC2: + return disableDC2(); + case DCDC3: + return disableDC3(); + case LDO2: + return disableLDO2(); + case LDO3: + return disableLDO3(); + case LDO4: + return disableLDO4(); + case LDOIO: + return disableLDOio(); + case VBACKUP: + return disableBackupBattCharger(); + default: + break; + } + return false; + } + + bool inline isPowerChannelEnable(PMICPowerChannel channel) + { + switch (channel) + { + case DCDC2: + return isEnableDC2(); + case DCDC3: + return isEnableDC3(); + case LDO2: + return isEnableLDO2(); + case LDO3: + return isEnableLDO3(); + case LDO4: + return isEnableLDO4(); + case LDOIO: + return isEnableLDOio(); + case VBACKUP: + return isEnableBackupCharger(); + default: + break; + } + return false; + } + + bool inline setPowerChannelVoltage(PMICPowerChannel channel, uint16_t millivolt) + { + if (getProtectedChannel(channel)) + { + log_e("Failed to set the power channel, the power channel has been protected"); + return false; + } + switch (channel) + { + case DCDC2: + return setDC2Voltage(millivolt); + case DCDC3: + return setDC3Voltage(millivolt); + case LDO2: + return setLDO2Voltage(millivolt); + case LDO3: + return setLDO3Voltage(millivolt); + case LDO4: + return setLDO4Voltage(millivolt); + case LDOIO: + return setLDOioVoltage(millivolt); + case VBACKUP: + // TODO: + // return setBackupBattChargerVoltage(millivolt); + default: + break; + } + return false; + } + + bool initImpl() + { + if (getChipID() == AXP202_CHIP_ID) + { + setChipModel(PMICChipModel::AXP202); + return true; + } + return false; + } + + /* + * Interrupt control functions + */ + bool setInterruptImpl(pmic_irq opts, bool enable) + { + int res = 0; + uint8_t data = 0, value = 0; + + log_d("%s %s - 0x%llx\n", __func__, enable ? "ENABLE" : "DISABLE", opts); + + if (opts & 0x00000000FF) + { + value = opts & 0xFF; + // log_d("Write INT0: %x\n", value); + data = readRegister(AXP202_INTEN1); + intRegister[0] = enable ? (data | value) : (data & (~value)); + res |= writeRegister(AXP202_INTEN1, intRegister[0]); + } + + if (opts & 0x000000FF00) + { + value = opts >> 8; + // log_d("Write INT1: %x\n", value); + data = readRegister(AXP202_INTEN2); + intRegister[1] = enable ? (data | value) : (data & (~value)); + res |= writeRegister(AXP202_INTEN2, intRegister[1]); + } + + if (opts & 0x0000FF0000) + { + value = opts >> 16; + // log_d("Write INT1: %x\n", value); + data = readRegister(AXP202_INTEN3); + intRegister[2] = enable ? (data | value) : (data & (~value)); + res |= writeRegister(AXP202_INTEN3, intRegister[2]); + } + + if (opts & 0x00FF000000) + { + value = opts >> 24; + // log_d("Write INT1: %x\n", value); + data = readRegister(AXP202_INTEN4); + intRegister[3] = enable ? (data | value) : (data & (~value)); + res |= writeRegister(AXP202_INTEN4, intRegister[3]); + } + + if (opts & 0xFF00000000) + { + value = opts >> 32; + // log_d("Write INT1: %x\n", value); + data = readRegister(AXP202_INTEN4); + intRegister[4] = enable ? (data | value) : (data & (~value)); + res |= writeRegister(AXP202_INTEN4, intRegister[4]); + } + return res == 0; + } + + /* + * Signal Capture control functions + */ + bool setSignalCaptureImpl(uint32_t opts, bool enable) + { + int value = 0; + if (opts & 0xFF) + { + value = readRegister(AXP202_ADC_EN1); + writeRegister(AXP202_ADC_EN1, enable ? (value | opts) : (value & (~opts))); + } + if (opts & 0xFF00) + { + opts >>= 8; + value = readRegister(AXP202_ADC_EN2); + writeRegister(AXP202_ADC_EN2, enable ? (value | opts) : (value & (~opts))); + } + return true; + } + + const char *getChipNameImpl(void) + { + return "AXP202"; + } + + private: + const uint16_t chargeTargetVol[4] = {4100, 4150, 4200, 4360}; + uint8_t statusRegister[AXP202_INTSTS_CNT]; + uint8_t intRegister[AXP202_INTSTS_CNT]; + const uint16_t ldo4_table[16] = { + 1250, 1300, 1400, 1500, 1600, 1700, 1800, 1900, + 2000, 2500, 2700, 2800, 3000, 3100, 3200, 3300}; + }; + } // namespace PMIC +} // namespace HAL \ No newline at end of file diff --git a/lib/HAL/PMIC/DRIVER/AXP209.tpp b/lib/HAL/PMIC/DRIVER/AXP209.tpp new file mode 100644 index 000000000..e69de29bb diff --git a/lib/HAL/PMIC/DRIVER/AXP2101.tpp b/lib/HAL/PMIC/DRIVER/AXP2101.tpp new file mode 100644 index 000000000..0626b735c --- /dev/null +++ b/lib/HAL/PMIC/DRIVER/AXP2101.tpp @@ -0,0 +1,3036 @@ +#include "../REG/AXP2101.hpp" +#include "../IMPL/XPOWERS.tpp" +namespace HAL::PMIC +{ + class AXP2101 : public XPOWERS + { + friend class Base; + + public: + AXP2101(TwoWire &wire = Wire, int sda = SDA, int scl = SCL, uint8_t addr = AXP2101_SLAVE_ADDRESS) + { + myWire = &wire; + mySDA = sda; + mySCL = scl; + myADDR = addr; + } + + ~AXP2101() + { + log_i("~AXP2101"); + deinit(); + } + + bool init(TwoWire &wire = Wire, int sda = SDA, int scl = SCL, uint8_t addr = AXP2101_SLAVE_ADDRESS) + { + myWire = &wire; + mySDA = sda; + mySCL = scl; + myADDR = addr; + return begin(); + } + + bool init() + { + return begin(); + } + + void deinit() + { + end(); + } + + /* + * PMU status functions + */ + uint16_t status() + { + uint16_t status1 = readRegister(AXP2101_STATUS1) & 0x1F; + uint16_t status2 = readRegister(AXP2101_STATUS2) & 0x1F; + ; + return (status1 << 8) | (status2); + } + + bool isVbusGood(void) + { + return getRegisterBit(AXP2101_STATUS1, 5); + } + + bool getBatfetState(void) + { + return getRegisterBit(AXP2101_STATUS1, 4); + } + + // getBatPresentState + bool isBatteryConnect(void) + { + return getRegisterBit(AXP2101_STATUS1, 3); + } + + bool isBatInActiveModeState(void) + { + return getRegisterBit(AXP2101_STATUS1, 2); + } + + bool getThermalRegulationStatus(void) + { + return getRegisterBit(AXP2101_STATUS1, 1); + } + + bool getCurrentLimitStatus(void) + { + return getRegisterBit(AXP2101_STATUS1, 0); + } + + bool isCharging(void) + { + return (readRegister(AXP2101_STATUS2) >> 5) == 0x01; + } + + bool isDischarge(void) + { + return (readRegister(AXP2101_STATUS2) >> 5) == 0x02; + } + + bool isStandby(void) + { + return (readRegister(AXP2101_STATUS2) >> 5) == 0x00; + } + + bool isPowerOn(void) + { + return getRegisterBit(AXP2101_STATUS2, 4); + } + + bool isPowerOff(void) + { + return getRegisterBit(AXP2101_STATUS2, 4); + } + + bool isVbusIn(void) + { + return getRegisterBit(AXP2101_STATUS2, 3) == 0 && isVbusGood(); + } + + pmic_chg_status getChargerStatus(void) + { + int val = readRegister(AXP2101_STATUS2); + if (val == -1) + return AXP2101_CHG_STOP_STATE; + val &= 0x07; + return (pmic_chg_status)val; + } + + /* + * Data Buffer + */ + + bool writeDataBuffer(uint8_t *data, uint8_t size) + { + if (size > AXP2101_DATA_BUFFER_SIZE) + return false; + return writeRegister(AXP2101_DATA_BUFFER1, data, size); + } + + bool readDataBuffer(uint8_t *data, uint8_t size) + { + if (size > AXP2101_DATA_BUFFER_SIZE) + return false; + return readRegister(AXP2101_DATA_BUFFER1, data, size); + } + + /* + * PMU common configuration + */ + + /** + * @brief Internal off-discharge enable for DCDC & LDO & SWITCH + */ + + void enableInternalDischarge(void) + { + setRegisterBit(AXP2101_COMMON_CONFIG, 5); + } + + void disableInternalDischarge(void) + { + clrRegisterBit(AXP2101_COMMON_CONFIG, 5); + } + + /** + * @brief PWROK PIN pull low to Restart + */ + void enablePwrOkPinPullLow(void) + { + setRegisterBit(AXP2101_COMMON_CONFIG, 3); + } + + void disablePwrOkPinPullLow(void) + { + clrRegisterBit(AXP2101_COMMON_CONFIG, 3); + } + + void enablePwronShutPMIC(void) + { + setRegisterBit(AXP2101_COMMON_CONFIG, 2); + } + + void disablePwronShutPMIC(void) + { + clrRegisterBit(AXP2101_COMMON_CONFIG, 2); + } + + /** + * @brief Restart the SoC System, POWOFF/POWON and reset the related registers + * @retval None + */ + void reset(void) + { + setRegisterBit(AXP2101_COMMON_CONFIG, 1); + } + + /** + * @brief Set shutdown, calling shutdown will turn off all power channels, + * only VRTC belongs to normal power supply + * @retval None + */ + void shutdown(void) + { + setRegisterBit(AXP2101_COMMON_CONFIG, 0); + } + + /** + * @brief BATFET control / REG 12H + * @note DIE Over Temperature Protection Level1 Configuration + * @param opt: 0:115 , 1:125 , 2:135 + * @retval None + */ + void setBatfetDieOverTempLevel1(uint8_t opt) + { + int val = readRegister(AXP2101_BATFET_CTRL); + if (val == -1) + return; + val &= 0xF9; + writeRegister(AXP2101_BATFET_CTRL, val | (opt << 1)); + } + + uint8_t getBatfetDieOverTempLevel1(void) + { + return (readRegister(AXP2101_BATFET_CTRL) & 0x06); + } + + void enableBatfetDieOverTempDetect(void) + { + setRegisterBit(AXP2101_BATFET_CTRL, 0); + } + + void disableBatfetDieOverTempDetect(void) + { + clrRegisterBit(AXP2101_BATFET_CTRL, 0); + } + + /** + * @param opt: 0:115 , 1:125 , 2:135 + */ + void setDieOverTempLevel1(uint8_t opt) + { + int val = readRegister(AXP2101_DIE_TEMP_CTRL); + if (val == -1) + return; + val &= 0xF9; + writeRegister(AXP2101_DIE_TEMP_CTRL, val | (opt << 1)); + } + + uint8_t getDieOverTempLevel1(void) + { + return (readRegister(AXP2101_DIE_TEMP_CTRL) & 0x06); + } + + void enableDieOverTempDetect(void) + { + setRegisterBit(AXP2101_DIE_TEMP_CTRL, 0); + } + + void disableDieOverTempDetect(void) + { + clrRegisterBit(AXP2101_DIE_TEMP_CTRL, 0); + } + + // Linear Charger Vsys voltage dpm + void setLinearChargerVsysDpm(pmic_chg_dpm opt) + { + int val = readRegister(AXP2101_MIN_SYS_VOL_CTRL); + if (val == -1) + return; + val &= 0x8F; + writeRegister(AXP2101_MIN_SYS_VOL_CTRL, val | (opt << 4)); + } + + uint8_t getLinearChargerVsysDpm(void) + { + int val = readRegister(AXP2101_MIN_SYS_VOL_CTRL); + if (val == -1) + return 0; + val &= 0x70; + return (val & 0x70) >> 4; + } + + /** + * @brief Set VBUS Voltage Input Limit. + * @param opt: View the related chip type pmic_vbus_vol_limit enumeration + * parameters in "XPowersParams.hpp" + */ + void setVbusVoltageLimit(pmic_vbus_vol_limit opt) + { + int val = readRegister(AXP2101_INPUT_VOL_LIMIT_CTRL); + if (val == -1) + return; + val &= 0xF0; + writeRegister(AXP2101_INPUT_VOL_LIMIT_CTRL, val | (opt & 0x0F)); + } + + /** + * @brief Get VBUS Voltage Input Limit. + * @retval View the related chip type pmic_vbus_vol_limit enumeration + * parameters in "XPowersParams.hpp" + */ + pmic_vbus_vol_limit getVbusVoltageLimit(void) + { + return (pmic_vbus_vol_limit)(readRegister(AXP2101_INPUT_VOL_LIMIT_CTRL) & 0x0F); + } + + /** + * @brief Set VBUS Current Input Limit. + * @param opt: View the related chip type pmic_vbus_cur_limit enumeration + * parameters in "XPowersParams.hpp" + * @retval true valid false invalid + */ + bool setVbusCurrentLimit(pmic_vbus_cur_limit opt) + { + int val = readRegister(AXP2101_INPUT_CUR_LIMIT_CTRL); + if (val == -1) + return false; + val &= 0xF8; + return 0 == writeRegister(AXP2101_INPUT_CUR_LIMIT_CTRL, val | (opt & 0x07)); + } + + /** + * @brief Get VBUS Current Input Limit. + * @retval View the related chip type pmic_vbus_cur_limit_t enumeration + * parameters in "XPowersParams.hpp" + */ + pmic_vbus_cur_limit getVbusCurrentLimit(void) + { + return (pmic_vbus_cur_limit)(readRegister(AXP2101_INPUT_CUR_LIMIT_CTRL) & 0x07); + } + + /** + * @brief Reset the fuel gauge + */ + void resetGauge(void) + { + setRegisterBit(AXP2101_RESET_FUEL_GAUGE, 3); + } + + /** + * @brief reset the gauge besides reset + */ + void resetGaugeBesides(void) + { + setRegisterBit(AXP2101_RESET_FUEL_GAUGE, 2); + } + + /** + * @brief Gauge Module + */ + void enableGauge(void) + { + setRegisterBit(AXP2101_CHARGE_GAUGE_WDT_CTRL, 3); + } + + void disableGauge(void) + { + clrRegisterBit(AXP2101_CHARGE_GAUGE_WDT_CTRL, 3); + } + + /** + * @brief Button Battery charge + */ + bool enableButtonBatteryCharge(void) + { + return setRegisterBit(AXP2101_CHARGE_GAUGE_WDT_CTRL, 2); + } + + bool disableButtonBatteryCharge(void) + { + return clrRegisterBit(AXP2101_CHARGE_GAUGE_WDT_CTRL, 2); + } + + bool isEnableButtonBatteryCharge() + { + return getRegisterBit(AXP2101_CHARGE_GAUGE_WDT_CTRL, 2); + } + + // Button battery charge termination voltage setting + bool setButtonBatteryChargeVoltage(uint16_t millivolt) + { + if (millivolt % AXP2101_BTN_VOL_STEPS) + { + log_e("Mistake ! Button battery charging step voltage is %u mV", AXP2101_BTN_VOL_STEPS); + return false; + } + if (millivolt < AXP2101_BTN_VOL_MIN) + { + log_e("Mistake ! The minimum charge termination voltage of the coin cell battery is %u mV", AXP2101_BTN_VOL_MIN); + return false; + } + else if (millivolt > AXP2101_BTN_VOL_MAX) + { + log_e("Mistake ! The minimum charge termination voltage of the coin cell battery is %u mV", AXP2101_BTN_VOL_MAX); + return false; + } + int val = readRegister(AXP2101_BTN_BAT_CHG_VOL_SET); + if (val == -1) + return 0; + val &= 0xF8; + val |= (millivolt - AXP2101_BTN_VOL_MIN) / AXP2101_BTN_VOL_STEPS; + return 0 == writeRegister(AXP2101_BTN_BAT_CHG_VOL_SET, val); + } + + uint16_t getButtonBatteryVoltage(void) + { + int val = readRegister(AXP2101_BTN_BAT_CHG_VOL_SET); + if (val == -1) + return 0; + return (val & 0x07) * AXP2101_BTN_VOL_STEPS + AXP2101_BTN_VOL_MIN; + } + + /** + * @brief Cell Battery charge + */ + void enableCellbatteryCharge(void) + { + setRegisterBit(AXP2101_CHARGE_GAUGE_WDT_CTRL, 1); + } + + void disableCellbatteryCharge(void) + { + clrRegisterBit(AXP2101_CHARGE_GAUGE_WDT_CTRL, 1); + } + + /** + * @brief Watchdog Module + */ + void enableWatchdog(void) + { + setRegisterBit(AXP2101_CHARGE_GAUGE_WDT_CTRL, 0); + enableIRQ(AXP2101_WDT_EXPIRE_IRQ); + } + + void disableWatchdog(void) + { + disableIRQ(AXP2101_WDT_EXPIRE_IRQ); + clrRegisterBit(AXP2101_CHARGE_GAUGE_WDT_CTRL, 0); + } + + /** + * @brief Watchdog Config + * @note + * @param opt: 0: IRQ Only 1: IRQ and System reset 2: IRQ, System Reset and Pull down PWROK 1s 3: IRQ, System Reset, DCDC/LDO PWROFF & PWRON + * @retval None + */ + void setWatchdogConfig(pmic_wdt_config opt) + { + int val = readRegister(AXP2101_WDT_CTRL); + if (val == -1) + return; + val &= 0xCF; + writeRegister(AXP2101_WDT_CTRL, val | (opt << 4)); + } + + pmic_wdt_config getWatchConfig(void) + { + return (pmic_wdt_config)((readRegister(AXP2101_WDT_CTRL) & 0x30) >> 4); + } + + void clrWatchdog(void) + { + setRegisterBit(AXP2101_WDT_CTRL, 3); + } + + void setWatchdogTimeout(pmic_wdt_timeout opt) + { + int val = readRegister(AXP2101_WDT_CTRL); + if (val == -1) + return; + val &= 0xF8; + writeRegister(AXP2101_WDT_CTRL, val | opt); + } + + pmic_wdt_timeout getWatchdogTimerout(void) + { + return (pmic_wdt_timeout)(readRegister(AXP2101_WDT_CTRL) & 0x07); + } + + /** + * @brief Low battery warning threshold 5-20%, 1% per step + * @param percentage: 5 ~ 20 + * @retval None + */ + void setLowBatWarnThreshold(uint8_t percentage) + { + if (percentage < 5 || percentage > 20) + return; + int val = readRegister(AXP2101_LOW_BAT_WARN_SET); + if (val == -1) + return; + val &= 0x0F; + writeRegister(AXP2101_LOW_BAT_WARN_SET, val | ((percentage - 5) << 4)); + } + + uint8_t getLowBatWarnThreshold(void) + { + int val = readRegister(AXP2101_LOW_BAT_WARN_SET); + if (val == -1) + return 0; + val &= 0xF0; + val >>= 4; + return val; + } + + /** + * @brief Low battery shutdown threshold 0-15%, 1% per step + * @param opt: 0 ~ 15 + * @retval None + */ + void setLowBatShutdownThreshold(uint8_t opt) + { + if (opt > 15) + { + opt = 15; + } + int val = readRegister(AXP2101_LOW_BAT_WARN_SET); + if (val == -1) + return; + val &= 0xF0; + writeRegister(AXP2101_LOW_BAT_WARN_SET, val | opt); + } + + uint8_t getLowBatShutdownThreshold(void) + { + return (readRegister(AXP2101_LOW_BAT_WARN_SET) & 0x0F); + } + + //! PWRON statu 20 + // POWERON always high when EN Mode as POWERON Source + bool isPoweronAlwaysHighSource() + { + return getRegisterBit(AXP2101_PWRON_STATUS, 5); + } + + // Battery Insert and Good as POWERON Source + bool isBattInsertOnSource() + { + return getRegisterBit(AXP2101_PWRON_STATUS, 4); + } + + // Battery Voltage > 3.3V when Charged as Source + bool isBattNormalOnSource() + { + return getRegisterBit(AXP2101_PWRON_STATUS, 3); + } + + // Vbus Insert and Good as POWERON Source + bool isVbusInsertOnSource() + { + return getRegisterBit(AXP2101_PWRON_STATUS, 2); + } + + // IRQ PIN Pull-down as POWERON Source + bool isIrqLowOnSource() + { + return getRegisterBit(AXP2101_PWRON_STATUS, 1); + } + + // POWERON low for on level when POWERON Mode as POWERON Source + bool isPwronLowOnSource() + { + return getRegisterBit(AXP2101_PWRON_STATUS, 0); + } + + pmic_power_on_source getPowerOnSource() + { + int val = readRegister(AXP2101_PWRON_STATUS); + if (val == -1) + return AXP2101_POWERON_SRC_UNKONW; + return (pmic_power_on_source)val; + } + + //! PWROFF status 21 + // Die Over Temperature as POWEROFF Source + bool isOverTemperatureOffSource() + { + return getRegisterBit(AXP2101_PWROFF_STATUS, 7); + } + + // DCDC Over Voltage as POWEROFF Source + bool isDcOverVoltageOffSource() + { + return getRegisterBit(AXP2101_PWROFF_STATUS, 6); + } + + // DCDC Under Voltage as POWEROFF Source + bool isDcUnderVoltageOffSource() + { + return getRegisterBit(AXP2101_PWROFF_STATUS, 5); + } + + // VBUS Over Voltage as POWEROFF Source + bool isVbusOverVoltageOffSource() + { + return getRegisterBit(AXP2101_PWROFF_STATUS, 4); + } + + // Vsys Under Voltage as POWEROFF Source + bool isVsysUnderVoltageOffSource() + { + return getRegisterBit(AXP2101_PWROFF_STATUS, 3); + } + + // POWERON always low when EN Mode as POWEROFF Source + bool isPwronAlwaysLowOffSource() + { + return getRegisterBit(AXP2101_PWROFF_STATUS, 2); + } + + // Software configuration as POWEROFF Source + bool isSwConfigOffSource() + { + return getRegisterBit(AXP2101_PWROFF_STATUS, 1); + } + + // POWERON Pull down for off level when POWERON Mode as POWEROFF Source + bool isPwrSourcePullDown() + { + return getRegisterBit(AXP2101_PWROFF_STATUS, 0); + } + + pmic_power_off_source getPowerOffSource() + { + int val = readRegister(AXP2101_PWROFF_STATUS); + if (val == -1) + return AXP2101_POWEROFF_SRC_UNKONW; + return (pmic_power_off_source)val; + } + + //! REG 22H + void enableOverTemperatureLevel2PowerOff() + { + setRegisterBit(AXP2101_PWROFF_EN, 2); + } + + void disableOverTemperaturePowerOff() + { + clrRegisterBit(AXP2101_PWROFF_EN, 2); + } + + // CHANGE: void enablePwrOnOverVolOffLevelPowerOff() + void enableLongPressShutdown() + { + setRegisterBit(AXP2101_PWROFF_EN, 1); + } + + // CHANGE: void disablePwrOnOverVolOffLevelPowerOff() + void disableLongPressShutdown() + { + clrRegisterBit(AXP2101_PWROFF_EN, 1); + } + + // CHANGE: void enablePwrOffSelectFunction() + void setLongPressRestart() + { + setRegisterBit(AXP2101_PWROFF_EN, 0); + } + + // CHANGE: void disablePwrOffSelectFunction() + void setLongPressPowerOFF() + { + clrRegisterBit(AXP2101_PWROFF_EN, 0); + } + + //! REG 23H + // DCDC 120%(130%) high voltage turn off PMIC function + void enableDCHighVoltageTurnOff() + { + setRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 5); + } + + void disableDCHighVoltageTurnOff() + { + clrRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 5); + } + + // DCDC5 85% low voltage turn Off PMIC function + void enableDC5LowVoltageTurnOff() + { + setRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 4); + } + + void disableDC5LowVoltageTurnOff() + { + clrRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 4); + } + + // DCDC4 85% low voltage turn Off PMIC function + void enableDC4LowVoltageTurnOff() + { + setRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 3); + } + + void disableDC4LowVoltageTurnOff() + { + clrRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 3); + } + + // DCDC3 85% low voltage turn Off PMIC function + void enableDC3LowVoltageTurnOff() + { + setRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 2); + } + + void disableDC3LowVoltageTurnOff() + { + clrRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 2); + } + + // DCDC2 85% low voltage turn Off PMIC function + void enableDC2LowVoltageTurnOff() + { + setRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 1); + } + + void disableDC2LowVoltageTurnOff() + { + clrRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 1); + } + + // DCDC1 85% low voltage turn Off PMIC function + void enableDC1LowVoltageTurnOff() + { + setRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 0); + } + + void disableDC1LowVoltageTurnOff() + { + clrRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 0); + } + + // Set the minimum system operating voltage inside the PMU, + // below this value will shut down the PMU,Adjustment range 2600mV~3300mV + bool setSysPowerDownVoltage(uint16_t millivolt) + { + if (millivolt % AXP2101_VSYS_VOL_THRESHOLD_STEPS) + { + log_e("Mistake ! The steps is must %u mV", AXP2101_VSYS_VOL_THRESHOLD_STEPS); + return false; + } + if (millivolt < AXP2101_VSYS_VOL_THRESHOLD_MIN) + { + log_e("Mistake ! The minimum settable voltage of VSYS is %u mV", AXP2101_VSYS_VOL_THRESHOLD_MIN); + return false; + } + else if (millivolt > AXP2101_VSYS_VOL_THRESHOLD_MAX) + { + log_e("Mistake ! The maximum settable voltage of VSYS is %u mV", AXP2101_VSYS_VOL_THRESHOLD_MAX); + return false; + } + int val = readRegister(AXP2101_VOFF_SET); + if (val == -1) + return false; + val &= 0xF8; + return 0 == writeRegister(AXP2101_VOFF_SET, val | ((millivolt - AXP2101_VSYS_VOL_THRESHOLD_MIN) / AXP2101_VSYS_VOL_THRESHOLD_STEPS)); + } + + uint16_t getSysPowerDownVoltage(void) + { + int val = readRegister(AXP2101_VOFF_SET); + if (val == -1) + return false; + return (val & 0x07) * AXP2101_VSYS_VOL_THRESHOLD_STEPS + AXP2101_VSYS_VOL_THRESHOLD_MIN; + } + + // PWROK setting and PWROFF sequence control 25. + // Check the PWROK Pin enable after all dcdc/ldo output valid 128ms + void enablePwrOk() + { + setRegisterBit(AXP2101_PWROK_SEQU_CTRL, 4); + } + + void disablePwrOk() + { + clrRegisterBit(AXP2101_PWROK_SEQU_CTRL, 4); + } + + // POWEROFF Delay 4ms after PWROK enable + void enablePowerOffDelay() + { + setRegisterBit(AXP2101_PWROK_SEQU_CTRL, 3); + } + + // POWEROFF Delay 4ms after PWROK disable + void disablePowerOffDelay() + { + clrRegisterBit(AXP2101_PWROK_SEQU_CTRL, 3); + } + + // POWEROFF Sequence Control the reverse of the Startup + void enablePowerSequence() + { + setRegisterBit(AXP2101_PWROK_SEQU_CTRL, 2); + } + + // POWEROFF Sequence Control at the same time + void disablePowerSequence() + { + clrRegisterBit(AXP2101_PWROK_SEQU_CTRL, 2); + } + + // Delay of PWROK after all power output good + bool setPwrOkDelay(pmic_pwrok_delay opt) + { + int val = readRegister(AXP2101_PWROK_SEQU_CTRL); + if (val == -1) + return false; + val &= 0xFC; + return 0 == writeRegister(AXP2101_PWROK_SEQU_CTRL, val | opt); + } + + pmic_pwrok_delay getPwrOkDelay() + { + int val = readRegister(AXP2101_PWROK_SEQU_CTRL); + if (val == -1) + return AXP2101_PWROK_DELAY_8MS; + return (pmic_pwrok_delay)(val & 0x03); + } + + // Sleep and 26 + void wakeupControl(pmic_wakeup opt, bool enable) + { + int val = readRegister(AXP2101_SLEEP_WAKEUP_CTRL); + if (val == -1) + return; + enable ? (val |= opt) : (val &= (~opt)); + writeRegister(AXP2101_SLEEP_WAKEUP_CTRL, val); + } + + bool enableWakeup(void) + { + return setRegisterBit(AXP2101_SLEEP_WAKEUP_CTRL, 1); + } + + bool disableWakeup(void) + { + return clrRegisterBit(AXP2101_SLEEP_WAKEUP_CTRL, 1); + } + + bool enableSleep(void) + { + return setRegisterBit(AXP2101_SLEEP_WAKEUP_CTRL, 0); + } + + bool disableSleep(void) + { + return clrRegisterBit(AXP2101_SLEEP_WAKEUP_CTRL, 0); + } + + // RQLEVEL/OFFLEVEL/ONLEVEL setting 27 + /** + * @brief IRQLEVEL configur + * @param opt: 0:1s 1:1.5s 2:2s 3:2.5s + */ + void setIrqLevel(uint8_t opt) + { + int val = readRegister(AXP2101_IRQ_OFF_ON_LEVEL_CTRL); + if (val == -1) + return; + val &= 0xFC; + writeRegister(AXP2101_IRQ_OFF_ON_LEVEL_CTRL, val | (opt << 4)); + } + + /** + * @brief OFFLEVEL configuration + * @param opt: 0:4s 1:6s 2:8s 3:10s + */ + void setOffLevel(uint8_t opt) + { + int val = readRegister(AXP2101_IRQ_OFF_ON_LEVEL_CTRL); + if (val == -1) + return; + writeRegister(AXP2101_IRQ_OFF_ON_LEVEL_CTRL, val | (opt << 2)); + } + + /** + * @brief ONLEVEL configuration + * @param opt: 0:128ms 1:512ms 2:1s 3:2s + */ + void setOnLevel(uint8_t opt) + { + int val = readRegister(AXP2101_IRQ_OFF_ON_LEVEL_CTRL); + if (val == -1) + return; + writeRegister(AXP2101_IRQ_OFF_ON_LEVEL_CTRL, val | opt); + } + + // Fast pwron setting 0 28 + // Fast Power On Start Sequence + void setDc4FastStartSequence(pmic_start_sequence opt) + { + int val = readRegister(AXP2101_FAST_PWRON_SET0); + if (val == -1) + return; + writeRegister(AXP2101_FAST_PWRON_SET0, val | ((opt & 0x3) << 6)); + } + + void setDc3FastStartSequence(pmic_start_sequence opt) + { + int val = readRegister(AXP2101_FAST_PWRON_SET0); + if (val == -1) + return; + writeRegister(AXP2101_FAST_PWRON_SET0, val | ((opt & 0x3) << 4)); + } + void setDc2FastStartSequence(pmic_start_sequence opt) + { + int val = readRegister(AXP2101_FAST_PWRON_SET0); + if (val == -1) + return; + writeRegister(AXP2101_FAST_PWRON_SET0, val | ((opt & 0x3) << 2)); + } + void setDc1FastStartSequence(pmic_start_sequence opt) + { + int val = readRegister(AXP2101_FAST_PWRON_SET0); + if (val == -1) + return; + writeRegister(AXP2101_FAST_PWRON_SET0, val | (opt & 0x3)); + } + + // Fast pwron setting 1 29 + void setAldo3FastStartSequence(pmic_start_sequence opt) + { + int val = readRegister(AXP2101_FAST_PWRON_SET1); + if (val == -1) + return; + writeRegister(AXP2101_FAST_PWRON_SET1, val | ((opt & 0x3) << 6)); + } + void setAldo2FastStartSequence(pmic_start_sequence opt) + { + int val = readRegister(AXP2101_FAST_PWRON_SET1); + if (val == -1) + return; + writeRegister(AXP2101_FAST_PWRON_SET1, val | ((opt & 0x3) << 4)); + } + void setAldo1FastStartSequence(pmic_start_sequence opt) + { + int val = readRegister(AXP2101_FAST_PWRON_SET1); + if (val == -1) + return; + writeRegister(AXP2101_FAST_PWRON_SET1, val | ((opt & 0x3) << 2)); + } + + void setDc5FastStartSequence(pmic_start_sequence opt) + { + int val = readRegister(AXP2101_FAST_PWRON_SET1); + if (val == -1) + return; + writeRegister(AXP2101_FAST_PWRON_SET1, val | (opt & 0x3)); + } + + // Fast pwron setting 2 2A + void setCpuldoFastStartSequence(pmic_start_sequence opt) + { + int val = readRegister(AXP2101_FAST_PWRON_SET2); + if (val == -1) + return; + writeRegister(AXP2101_FAST_PWRON_SET2, val | ((opt & 0x3) << 6)); + } + + void setBldo2FastStartSequence(pmic_start_sequence opt) + { + int val = readRegister(AXP2101_FAST_PWRON_SET2); + if (val == -1) + return; + writeRegister(AXP2101_FAST_PWRON_SET2, val | ((opt & 0x3) << 4)); + } + + void setBldo1FastStartSequence(pmic_start_sequence opt) + { + int val = readRegister(AXP2101_FAST_PWRON_SET2); + if (val == -1) + return; + writeRegister(AXP2101_FAST_PWRON_SET2, val | ((opt & 0x3) << 2)); + } + + void setAldo4FastStartSequence(pmic_start_sequence opt) + { + int val = readRegister(AXP2101_FAST_PWRON_SET2); + if (val == -1) + return; + writeRegister(AXP2101_FAST_PWRON_SET2, val | (opt & 0x3)); + } + + // Fast pwron setting 3 2B + void setDldo2FastStartSequence(pmic_start_sequence opt) + { + int val = readRegister(AXP2101_FAST_PWRON_CTRL); + if (val == -1) + return; + writeRegister(AXP2101_FAST_PWRON_CTRL, val | ((opt & 0x3) << 2)); + } + + void setDldo1FastStartSequence(pmic_start_sequence opt) + { + int val = readRegister(AXP2101_FAST_PWRON_CTRL); + if (val == -1) + return; + writeRegister(AXP2101_FAST_PWRON_CTRL, val | (opt & 0x3)); + } + + /** + * @brief Setting Fast Power On Start Sequence + */ + void setFastPowerOnLevel(pmic_fast_on_opt opt, pmic_start_sequence seq_level) + { + uint8_t val = 0; + switch (opt) + { + case AXP2101_FAST_DCDC1: + val = readRegister(AXP2101_FAST_PWRON_SET0); + writeRegister(AXP2101_FAST_PWRON_SET0, val | seq_level); + break; + case AXP2101_FAST_DCDC2: + val = readRegister(AXP2101_FAST_PWRON_SET0); + writeRegister(AXP2101_FAST_PWRON_SET0, val | (seq_level << 2)); + break; + case AXP2101_FAST_DCDC3: + val = readRegister(AXP2101_FAST_PWRON_SET0); + writeRegister(AXP2101_FAST_PWRON_SET0, val | (seq_level << 4)); + break; + case AXP2101_FAST_DCDC4: + val = readRegister(AXP2101_FAST_PWRON_SET0); + writeRegister(AXP2101_FAST_PWRON_SET0, val | (seq_level << 6)); + break; + case AXP2101_FAST_DCDC5: + val = readRegister(AXP2101_FAST_PWRON_SET1); + writeRegister(AXP2101_FAST_PWRON_SET1, val | seq_level); + break; + case AXP2101_FAST_ALDO1: + val = readRegister(AXP2101_FAST_PWRON_SET1); + writeRegister(AXP2101_FAST_PWRON_SET1, val | (seq_level << 2)); + break; + case AXP2101_FAST_ALDO2: + val = readRegister(AXP2101_FAST_PWRON_SET1); + writeRegister(AXP2101_FAST_PWRON_SET1, val | (seq_level << 4)); + break; + case AXP2101_FAST_ALDO3: + val = readRegister(AXP2101_FAST_PWRON_SET1); + writeRegister(AXP2101_FAST_PWRON_SET1, val | (seq_level << 6)); + break; + case AXP2101_FAST_ALDO4: + val = readRegister(AXP2101_FAST_PWRON_SET2); + writeRegister(AXP2101_FAST_PWRON_SET2, val | seq_level); + break; + case AXP2101_FAST_BLDO1: + val = readRegister(AXP2101_FAST_PWRON_SET2); + writeRegister(AXP2101_FAST_PWRON_SET2, val | (seq_level << 2)); + break; + case AXP2101_FAST_BLDO2: + val = readRegister(AXP2101_FAST_PWRON_SET2); + writeRegister(AXP2101_FAST_PWRON_SET2, val | (seq_level << 4)); + break; + case AXP2101_FAST_CPUSLDO: + val = readRegister(AXP2101_FAST_PWRON_SET2); + writeRegister(AXP2101_FAST_PWRON_SET2, val | (seq_level << 6)); + break; + case AXP2101_FAST_DLDO1: + val = readRegister(AXP2101_FAST_PWRON_CTRL); + writeRegister(AXP2101_FAST_PWRON_CTRL, val | seq_level); + break; + case AXP2101_FAST_DLDO2: + val = readRegister(AXP2101_FAST_PWRON_CTRL); + writeRegister(AXP2101_FAST_PWRON_CTRL, val | (seq_level << 2)); + break; + default: + break; + } + } + + void disableFastPowerOn(pmic_fast_on_opt opt) + { + uint8_t val = 0; + switch (opt) + { + case AXP2101_FAST_DCDC1: + val = readRegister(AXP2101_FAST_PWRON_SET0); + writeRegister(AXP2101_FAST_PWRON_SET0, val & 0xFC); + break; + case AXP2101_FAST_DCDC2: + val = readRegister(AXP2101_FAST_PWRON_SET0); + writeRegister(AXP2101_FAST_PWRON_SET0, val & 0xF3); + break; + case AXP2101_FAST_DCDC3: + val = readRegister(AXP2101_FAST_PWRON_SET0); + writeRegister(AXP2101_FAST_PWRON_SET0, val & 0xCF); + break; + case AXP2101_FAST_DCDC4: + val = readRegister(AXP2101_FAST_PWRON_SET0); + writeRegister(AXP2101_FAST_PWRON_SET0, val & 0x3F); + break; + case AXP2101_FAST_DCDC5: + val = readRegister(AXP2101_FAST_PWRON_SET1); + writeRegister(AXP2101_FAST_PWRON_SET1, val & 0xFC); + break; + case AXP2101_FAST_ALDO1: + val = readRegister(AXP2101_FAST_PWRON_SET1); + writeRegister(AXP2101_FAST_PWRON_SET1, val & 0xF3); + break; + case AXP2101_FAST_ALDO2: + val = readRegister(AXP2101_FAST_PWRON_SET1); + writeRegister(AXP2101_FAST_PWRON_SET1, val & 0xCF); + break; + case AXP2101_FAST_ALDO3: + val = readRegister(AXP2101_FAST_PWRON_SET1); + writeRegister(AXP2101_FAST_PWRON_SET1, val & 0x3F); + break; + case AXP2101_FAST_ALDO4: + val = readRegister(AXP2101_FAST_PWRON_SET2); + writeRegister(AXP2101_FAST_PWRON_SET2, val & 0xFC); + break; + case AXP2101_FAST_BLDO1: + val = readRegister(AXP2101_FAST_PWRON_SET2); + writeRegister(AXP2101_FAST_PWRON_SET2, val & 0xF3); + break; + case AXP2101_FAST_BLDO2: + val = readRegister(AXP2101_FAST_PWRON_SET2); + writeRegister(AXP2101_FAST_PWRON_SET2, val & 0xCF); + break; + case AXP2101_FAST_CPUSLDO: + val = readRegister(AXP2101_FAST_PWRON_SET2); + writeRegister(AXP2101_FAST_PWRON_SET2, val & 0x3F); + break; + case AXP2101_FAST_DLDO1: + val = readRegister(AXP2101_FAST_PWRON_CTRL); + writeRegister(AXP2101_FAST_PWRON_CTRL, val & 0xFC); + break; + case AXP2101_FAST_DLDO2: + val = readRegister(AXP2101_FAST_PWRON_CTRL); + writeRegister(AXP2101_FAST_PWRON_CTRL, val & 0xF3); + break; + default: + break; + } + } + + void enableFastPowerOn(void) + { + setRegisterBit(AXP2101_FAST_PWRON_CTRL, 7); + } + + void disableFastPowerOn(void) + { + clrRegisterBit(AXP2101_FAST_PWRON_CTRL, 7); + } + + void enableFastWakeup(void) + { + setRegisterBit(AXP2101_FAST_PWRON_CTRL, 6); + } + + void disableFastWakeup(void) + { + clrRegisterBit(AXP2101_FAST_PWRON_CTRL, 6); + } + + // DCDC 120%(130%) high voltage turn off PMIC function + void setDCHighVoltagePowerDown(bool en) + { + en ? setRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 5) : clrRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 5); + } + + bool getDCHighVoltagePowerDownEn() + { + return getRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 5); + } + + // DCDCS force PWM control + void setDcUVPDebounceTime(uint8_t opt) + { + int val = readRegister(AXP2101_DC_FORCE_PWM_CTRL); + val &= 0xFC; + writeRegister(AXP2101_DC_FORCE_PWM_CTRL, val | opt); + } + + void settDC1WorkModeToPwm(uint8_t enable) + { + enable ? setRegisterBit(AXP2101_DC_FORCE_PWM_CTRL, 2) + : clrRegisterBit(AXP2101_DC_FORCE_PWM_CTRL, 2); + } + + void settDC2WorkModeToPwm(uint8_t enable) + { + enable ? setRegisterBit(AXP2101_DC_FORCE_PWM_CTRL, 3) + : clrRegisterBit(AXP2101_DC_FORCE_PWM_CTRL, 3); + } + + void settDC3WorkModeToPwm(uint8_t enable) + { + enable ? setRegisterBit(AXP2101_DC_FORCE_PWM_CTRL, 4) + : clrRegisterBit(AXP2101_DC_FORCE_PWM_CTRL, 4); + } + + void settDC4WorkModeToPwm(uint8_t enable) + { + enable ? setRegisterBit(AXP2101_DC_FORCE_PWM_CTRL, 5) + : clrRegisterBit(AXP2101_DC_FORCE_PWM_CTRL, 5); + } + + // 1 = 100khz 0=50khz + void setDCFreqSpreadRange(uint8_t opt) + { + opt ? setRegisterBit(AXP2101_DC_FORCE_PWM_CTRL, 6) + : clrRegisterBit(AXP2101_DC_FORCE_PWM_CTRL, 6); + } + + void setDCFreqSpreadRangeEn(bool en) + { + en ? setRegisterBit(AXP2101_DC_FORCE_PWM_CTRL, 7) + : clrRegisterBit(AXP2101_DC_FORCE_PWM_CTRL, 7); + } + + void enableCCM() + { + setRegisterBit(AXP2101_DC_ONOFF_DVM_CTRL, 6); + } + + void disableCCM() + { + clrRegisterBit(AXP2101_DC_ONOFF_DVM_CTRL, 6); + } + + bool isenableCCM() + { + return getRegisterBit(AXP2101_DC_ONOFF_DVM_CTRL, 6); + } + + // args:enum DVMRamp + void setDVMRamp(DVMRamp opt) + { + if (opt > 2) + return; + opt == 0 ? clrRegisterBit(AXP2101_DC_ONOFF_DVM_CTRL, 5) : setRegisterBit(AXP2101_DC_ONOFF_DVM_CTRL, 5); + } + + /* + * Power control DCDC1 functions + */ + bool isEnableDC1(void) + { + return getRegisterBit(AXP2101_DC_ONOFF_DVM_CTRL, 0); + } + + bool enableDC1(void) + { + return setRegisterBit(AXP2101_DC_ONOFF_DVM_CTRL, 0); + } + + bool disableDC1(void) + { + return clrRegisterBit(AXP2101_DC_ONOFF_DVM_CTRL, 0); + } + + bool setDC1Voltage(uint16_t millivolt) + { + if (millivolt % AXP2101_DCDC1_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", AXP2101_DCDC1_VOL_STEPS); + return false; + } + if (millivolt < AXP2101_DCDC1_VOL_MIN) + { + log_e("Mistake ! DC1 minimum voltage is %u mV", AXP2101_DCDC1_VOL_MIN); + return false; + } + else if (millivolt > AXP2101_DCDC1_VOL_MAX) + { + log_e("Mistake ! DC1 maximum voltage is %u mV", AXP2101_DCDC1_VOL_MAX); + return false; + } + return 0 == writeRegister(AXP2101_DC_VOL0_CTRL, (millivolt - AXP2101_DCDC1_VOL_MIN) / AXP2101_DCDC1_VOL_STEPS); + } + + uint16_t getDC1Voltage(void) + { + return (readRegister(AXP2101_DC_VOL0_CTRL) & 0x1F) * AXP2101_DCDC1_VOL_STEPS + AXP2101_DCDC1_VOL_MIN; + } + + // DCDC1 85% low voltage turn off PMIC function + void setDC1LowVoltagePowerDown(bool en) + { + en ? setRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 0) : clrRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 0); + } + + bool getDC1LowVoltagePowerDownEn() + { + return getRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 0); + } + + /* + * Power control DCDC2 functions + */ + bool isEnableDC2(void) + { + return getRegisterBit(AXP2101_DC_ONOFF_DVM_CTRL, 1); + } + + bool enableDC2(void) + { + return setRegisterBit(AXP2101_DC_ONOFF_DVM_CTRL, 1); + } + + bool disableDC2(void) + { + return clrRegisterBit(AXP2101_DC_ONOFF_DVM_CTRL, 1); + } + + bool setDC2Voltage(uint16_t millivolt) + { + int val = readRegister(AXP2101_DC_VOL1_CTRL); + if (val == -1) + return 0; + val &= 0x80; + if (millivolt >= AXP2101_DCDC2_VOL1_MIN && millivolt <= AXP2101_DCDC2_VOL1_MAX) + { + if (millivolt % AXP2101_DCDC2_VOL_STEPS1) + { + log_e("Mistake ! The steps is must %umV", AXP2101_DCDC2_VOL_STEPS1); + return false; + } + return 0 == writeRegister(AXP2101_DC_VOL1_CTRL, val | (millivolt - AXP2101_DCDC2_VOL1_MIN) / AXP2101_DCDC2_VOL_STEPS1); + } + else if (millivolt >= AXP2101_DCDC2_VOL2_MIN && millivolt <= AXP2101_DCDC2_VOL2_MAX) + { + if (millivolt % AXP2101_DCDC2_VOL_STEPS2) + { + log_e("Mistake ! The steps is must %umV", AXP2101_DCDC2_VOL_STEPS2); + return false; + } + val |= (((millivolt - AXP2101_DCDC2_VOL2_MIN) / AXP2101_DCDC2_VOL_STEPS2) + AXP2101_DCDC2_VOL_STEPS2_BASE); + return 0 == writeRegister(AXP2101_DC_VOL1_CTRL, val); + } + return false; + } + + uint16_t getDC2Voltage(void) + { + int val = readRegister(AXP2101_DC_VOL1_CTRL); + if (val == -1) + return 0; + val &= 0x7F; + if (val < AXP2101_DCDC2_VOL_STEPS2_BASE) + { + return (val * AXP2101_DCDC2_VOL_STEPS1) + AXP2101_DCDC2_VOL1_MIN; + } + else + { + return (val * AXP2101_DCDC2_VOL_STEPS2) - 200; + } + return 0; + } + + uint8_t getDC2WorkMode(void) + { + return getRegisterBit(AXP2101_DCDC2_VOL_STEPS2, 7); + } + + void setDC2LowVoltagePowerDown(bool en) + { + en ? setRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 1) : clrRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 1); + } + + bool getDC2LowVoltagePowerDownEn() + { + return getRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 1); + } + + /* + * Power control DCDC3 functions + */ + + bool isEnableDC3(void) + { + return getRegisterBit(AXP2101_DC_ONOFF_DVM_CTRL, 2); + } + + bool enableDC3(void) + { + return setRegisterBit(AXP2101_DC_ONOFF_DVM_CTRL, 2); + } + + bool disableDC3(void) + { + return clrRegisterBit(AXP2101_DC_ONOFF_DVM_CTRL, 2); + } + + /** + 0.5~1.2V,10mV/step,71steps + 1.22~1.54V,20mV/step,17steps + 1.6~3.4V,100mV/step,19steps + */ + bool setDC3Voltage(uint16_t millivolt) + { + int val = readRegister(AXP2101_DC_VOL2_CTRL); + if (val == -1) + return false; + val &= 0x80; + if (millivolt >= AXP2101_DCDC3_VOL1_MIN && millivolt <= AXP2101_DCDC3_VOL1_MAX) + { + if (millivolt % AXP2101_DCDC3_VOL_STEPS1) + { + log_e("Mistake ! The steps is must %umV", AXP2101_DCDC3_VOL_STEPS1); + return false; + } + return 0 == writeRegister(AXP2101_DC_VOL2_CTRL, val | (millivolt - AXP2101_DCDC3_VOL_MIN) / AXP2101_DCDC3_VOL_STEPS1); + } + else if (millivolt >= AXP2101_DCDC3_VOL2_MIN && millivolt <= AXP2101_DCDC3_VOL2_MAX) + { + if (millivolt % AXP2101_DCDC3_VOL_STEPS2) + { + log_e("Mistake ! The steps is must %umV", AXP2101_DCDC3_VOL_STEPS2); + return false; + } + val |= (((millivolt - AXP2101_DCDC3_VOL2_MIN) / AXP2101_DCDC3_VOL_STEPS2) + AXP2101_DCDC3_VOL_STEPS2_BASE); + return 0 == writeRegister(AXP2101_DC_VOL2_CTRL, val); + } + else if (millivolt >= AXP2101_DCDC3_VOL3_MIN && millivolt <= AXP2101_DCDC3_VOL3_MAX) + { + if (millivolt % AXP2101_DCDC3_VOL_STEPS3) + { + log_e("Mistake ! The steps is must %umV", AXP2101_DCDC3_VOL_STEPS3); + return false; + } + val |= (((millivolt - AXP2101_DCDC3_VOL3_MIN) / AXP2101_DCDC3_VOL_STEPS3) + AXP2101_DCDC3_VOL_STEPS3_BASE); + return 0 == writeRegister(AXP2101_DC_VOL2_CTRL, val); + } + return false; + } + + uint16_t getDC3Voltage(void) + { + int val = readRegister(AXP2101_DC_VOL2_CTRL) & 0x7F; + if (val == -1) + return 0; + if (val < AXP2101_DCDC3_VOL_STEPS2_BASE) + { + return (val * AXP2101_DCDC3_VOL_STEPS1) + AXP2101_DCDC3_VOL_MIN; + } + else if (val >= AXP2101_DCDC3_VOL_STEPS2_BASE && val < AXP2101_DCDC3_VOL_STEPS3_BASE) + { + return (val * AXP2101_DCDC3_VOL_STEPS2) - 200; + } + else + { + return (val * AXP2101_DCDC3_VOL_STEPS3) - 7200; + } + return 0; + } + + uint8_t getDC3WorkMode(void) + { + return getRegisterBit(AXP2101_DC_VOL2_CTRL, 7); + } + + // DCDC3 85% low voltage turn off PMIC function + void setDC3LowVoltagePowerDown(bool en) + { + en ? setRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 2) : clrRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 2); + } + + bool getDC3LowVoltagePowerDownEn() + { + return getRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 2); + } + + /* + * Power control DCDC4 functions + */ + /** + 0.5~1.2V,10mV/step,71steps + 1.22~1.84V,20mV/step,32steps + */ + bool isEnableDC4(void) + { + return getRegisterBit(AXP2101_DC_ONOFF_DVM_CTRL, 3); + } + + bool enableDC4(void) + { + return setRegisterBit(AXP2101_DC_ONOFF_DVM_CTRL, 3); + } + + bool disableDC4(void) + { + return clrRegisterBit(AXP2101_DC_ONOFF_DVM_CTRL, 3); + } + + bool setDC4Voltage(uint16_t millivolt) + { + int val = readRegister(AXP2101_DC_VOL3_CTRL); + if (val == -1) + return false; + val &= 0x80; + if (millivolt >= AXP2101_DCDC4_VOL1_MIN && millivolt <= AXP2101_DCDC4_VOL1_MAX) + { + if (millivolt % AXP2101_DCDC4_VOL_STEPS1) + { + log_e("Mistake ! The steps is must %umV", AXP2101_DCDC4_VOL_STEPS1); + return false; + } + return 0 == writeRegister(AXP2101_DC_VOL3_CTRL, val | (millivolt - AXP2101_DCDC4_VOL1_MIN) / AXP2101_DCDC4_VOL_STEPS1); + } + else if (millivolt >= AXP2101_DCDC4_VOL2_MIN && millivolt <= AXP2101_DCDC4_VOL2_MAX) + { + if (millivolt % AXP2101_DCDC4_VOL_STEPS2) + { + log_e("Mistake ! The steps is must %umV", AXP2101_DCDC4_VOL_STEPS2); + return false; + } + val |= (((millivolt - AXP2101_DCDC4_VOL2_MIN) / AXP2101_DCDC4_VOL_STEPS2) + AXP2101_DCDC4_VOL_STEPS2_BASE); + return 0 == writeRegister(AXP2101_DC_VOL3_CTRL, val); + } + return false; + } + + uint16_t getDC4Voltage(void) + { + int val = readRegister(AXP2101_DC_VOL3_CTRL); + if (val == -1) + return 0; + val &= 0x7F; + if (val < AXP2101_DCDC4_VOL_STEPS2_BASE) + { + return (val * AXP2101_DCDC4_VOL_STEPS1) + AXP2101_DCDC4_VOL1_MIN; + } + else + { + return (val * AXP2101_DCDC4_VOL_STEPS2) - 200; + } + return 0; + } + + // DCDC4 85% low voltage turn off PMIC function + void setDC4LowVoltagePowerDown(bool en) + { + en ? setRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 3) : clrRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 3); + } + + bool getDC4LowVoltagePowerDownEn() + { + return getRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 3); + } + + /* + * Power control DCDC5 functions,Output to gpio pin + */ + bool isEnableDC5(void) + { + return getRegisterBit(AXP2101_DC_ONOFF_DVM_CTRL, 4); + } + + bool enableDC5(void) + { + return setRegisterBit(AXP2101_DC_ONOFF_DVM_CTRL, 4); + } + + bool disableDC5(void) + { + return clrRegisterBit(AXP2101_DC_ONOFF_DVM_CTRL, 4); + } + + bool setDC5Voltage(uint16_t millivolt) + { + if (millivolt % AXP2101_DCDC5_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", AXP2101_DCDC5_VOL_STEPS); + return false; + } + if (millivolt != AXP2101_DCDC5_VOL_1200MV && millivolt < AXP2101_DCDC5_VOL_MIN) + { + log_e("Mistake ! DC5 minimum voltage is %umV ,%umV", AXP2101_DCDC5_VOL_1200MV, AXP2101_DCDC5_VOL_MIN); + return false; + } + else if (millivolt > AXP2101_DCDC5_VOL_MAX) + { + log_e("Mistake ! DC5 maximum voltage is %umV", AXP2101_DCDC5_VOL_MAX); + return false; + } + + int val = readRegister(AXP2101_DC_VOL4_CTRL); + if (val == -1) + return false; + val &= 0xE0; + if (millivolt == AXP2101_DCDC5_VOL_1200MV) + { + return 0 == writeRegister(AXP2101_DC_VOL4_CTRL, val | AXP2101_DCDC5_VOL_VAL); + } + val |= (millivolt - AXP2101_DCDC5_VOL_MIN) / AXP2101_DCDC5_VOL_STEPS; + return 0 == writeRegister(AXP2101_DC_VOL4_CTRL, val); + } + + uint16_t getDC5Voltage(void) + { + int val = readRegister(AXP2101_DC_VOL4_CTRL); + if (val == -1) + return 0; + val &= 0x1F; + if (val == AXP2101_DCDC5_VOL_VAL) + return AXP2101_DCDC5_VOL_1200MV; + return (val * AXP2101_DCDC5_VOL_STEPS) + AXP2101_DCDC5_VOL_MIN; + } + + bool isDC5FreqCompensationEn(void) + { + return getRegisterBit(AXP2101_DC_VOL4_CTRL, 5); + } + + void enableDC5FreqCompensation() + { + setRegisterBit(AXP2101_DC_VOL4_CTRL, 5); + } + + void disableFreqCompensation() + { + clrRegisterBit(AXP2101_DC_VOL4_CTRL, 5); + } + + // DCDC4 85% low voltage turn off PMIC function + void setDC5LowVoltagePowerDown(bool en) + { + en ? setRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 4) : clrRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 4); + } + + bool getDC5LowVoltagePowerDownEn() + { + return getRegisterBit(AXP2101_DC_OVP_UVP_CTRL, 4); + } + + /* + * Power control ALDO1 functions + */ + bool isEnableALDO1(void) + { + return getRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 0); + } + + bool enableALDO1(void) + { + return setRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 0); + } + + bool disableALDO1(void) + { + return clrRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 0); + } + + bool setALDO1Voltage(uint16_t millivolt) + { + if (millivolt % AXP2101_ALDO1_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", AXP2101_ALDO1_VOL_STEPS); + return false; + } + if (millivolt < AXP2101_ALDO1_VOL_MIN) + { + log_e("Mistake ! ALDO1 minimum output voltage is %umV", AXP2101_ALDO1_VOL_MIN); + return false; + } + else if (millivolt > AXP2101_ALDO1_VOL_MAX) + { + log_e("Mistake ! ALDO1 maximum output voltage is %umV", AXP2101_ALDO1_VOL_MAX); + return false; + } + uint16_t val = readRegister(AXP2101_LDO_VOL0_CTRL) & 0xE0; + val |= (millivolt - AXP2101_ALDO1_VOL_MIN) / AXP2101_ALDO1_VOL_STEPS; + return 0 == writeRegister(AXP2101_LDO_VOL0_CTRL, val); + } + + uint16_t getALDO1Voltage(void) + { + uint16_t val = readRegister(AXP2101_LDO_VOL0_CTRL) & 0x1F; + return val * AXP2101_ALDO1_VOL_STEPS + AXP2101_ALDO1_VOL_MIN; + } + + /* + * Power control ALDO2 functions + */ + bool isEnableALDO2(void) + { + return getRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 1); + } + + bool enableALDO2(void) + { + return setRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 1); + } + + bool disableALDO2(void) + { + return clrRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 1); + } + + bool setALDO2Voltage(uint16_t millivolt) + { + if (millivolt % AXP2101_ALDO2_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", AXP2101_ALDO2_VOL_STEPS); + return false; + } + if (millivolt < AXP2101_ALDO2_VOL_MIN) + { + log_e("Mistake ! ALDO2 minimum output voltage is %umV", AXP2101_ALDO2_VOL_MIN); + return false; + } + else if (millivolt > AXP2101_ALDO2_VOL_MAX) + { + log_e("Mistake ! ALDO2 maximum output voltage is %umV", AXP2101_ALDO2_VOL_MAX); + return false; + } + uint16_t val = readRegister(AXP2101_LDO_VOL1_CTRL) & 0xE0; + val |= (millivolt - AXP2101_ALDO2_VOL_MIN) / AXP2101_ALDO2_VOL_STEPS; + return 0 == writeRegister(AXP2101_LDO_VOL1_CTRL, val); + } + + uint16_t getALDO2Voltage(void) + { + uint16_t val = readRegister(AXP2101_LDO_VOL1_CTRL) & 0x1F; + return val * AXP2101_ALDO2_VOL_STEPS + AXP2101_ALDO2_VOL_MIN; + } + + /* + * Power control ALDO3 functions + */ + bool isEnableALDO3(void) + { + return getRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 2); + } + + bool enableALDO3(void) + { + return setRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 2); + } + + bool disableALDO3(void) + { + return clrRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 2); + } + + bool setALDO3Voltage(uint16_t millivolt) + { + if (millivolt % AXP2101_ALDO3_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", AXP2101_ALDO3_VOL_STEPS); + return false; + } + if (millivolt < AXP2101_ALDO3_VOL_MIN) + { + log_e("Mistake ! ALDO3 minimum output voltage is %umV", AXP2101_ALDO3_VOL_MIN); + return false; + } + else if (millivolt > AXP2101_ALDO3_VOL_MAX) + { + log_e("Mistake ! ALDO3 maximum output voltage is %umV", AXP2101_ALDO3_VOL_MAX); + return false; + } + uint16_t val = readRegister(AXP2101_LDO_VOL2_CTRL) & 0xE0; + val |= (millivolt - AXP2101_ALDO3_VOL_MIN) / AXP2101_ALDO3_VOL_STEPS; + return 0 == writeRegister(AXP2101_LDO_VOL2_CTRL, val); + } + + uint16_t getALDO3Voltage(void) + { + uint16_t val = readRegister(AXP2101_LDO_VOL2_CTRL) & 0x1F; + return val * AXP2101_ALDO3_VOL_STEPS + AXP2101_ALDO3_VOL_MIN; + } + + /* + * Power control ALDO4 functions + */ + bool isEnableALDO4(void) + { + return getRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 3); + } + + bool enableALDO4(void) + { + return setRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 3); + } + + bool disableALDO4(void) + { + return clrRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 3); + } + + bool setALDO4Voltage(uint16_t millivolt) + { + if (millivolt % AXP2101_ALDO4_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", AXP2101_ALDO4_VOL_STEPS); + return false; + } + if (millivolt < AXP2101_ALDO4_VOL_MIN) + { + log_e("Mistake ! ALDO4 minimum output voltage is %umV", AXP2101_ALDO4_VOL_MIN); + return false; + } + else if (millivolt > AXP2101_ALDO4_VOL_MAX) + { + log_e("Mistake ! ALDO4 maximum output voltage is %umV", AXP2101_ALDO4_VOL_MAX); + return false; + } + uint16_t val = readRegister(AXP2101_LDO_VOL3_CTRL) & 0xE0; + val |= (millivolt - AXP2101_ALDO4_VOL_MIN) / AXP2101_ALDO4_VOL_STEPS; + return 0 == writeRegister(AXP2101_LDO_VOL3_CTRL, val); + } + + uint16_t getALDO4Voltage(void) + { + uint16_t val = readRegister(AXP2101_LDO_VOL3_CTRL) & 0x1F; + return val * AXP2101_ALDO4_VOL_STEPS + AXP2101_ALDO4_VOL_MIN; + } + + /* + * Power control BLDO1 functions + */ + bool isEnableBLDO1(void) + { + return getRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 4); + } + + bool enableBLDO1(void) + { + return setRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 4); + } + + bool disableBLDO1(void) + { + return clrRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 4); + } + + bool setBLDO1Voltage(uint16_t millivolt) + { + if (millivolt % AXP2101_BLDO1_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", AXP2101_BLDO1_VOL_STEPS); + return false; + } + if (millivolt < AXP2101_BLDO1_VOL_MIN) + { + log_e("Mistake ! BLDO1 minimum output voltage is %umV", AXP2101_BLDO1_VOL_MIN); + return false; + } + else if (millivolt > AXP2101_BLDO1_VOL_MAX) + { + log_e("Mistake ! BLDO1 maximum output voltage is %umV", AXP2101_BLDO1_VOL_MAX); + return false; + } + int val = readRegister(AXP2101_LDO_VOL4_CTRL); + if (val == -1) + return false; + val &= 0xE0; + val |= (millivolt - AXP2101_BLDO1_VOL_MIN) / AXP2101_BLDO1_VOL_STEPS; + return 0 == writeRegister(AXP2101_LDO_VOL4_CTRL, val); + } + + uint16_t getBLDO1Voltage(void) + { + int val = readRegister(AXP2101_LDO_VOL4_CTRL); + if (val == -1) + return 0; + val &= 0x1F; + return val * AXP2101_BLDO1_VOL_STEPS + AXP2101_BLDO1_VOL_MIN; + } + + /* + * Power control BLDO2 functions + */ + bool isEnableBLDO2(void) + { + return getRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 5); + } + + bool enableBLDO2(void) + { + return setRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 5); + } + + bool disableBLDO2(void) + { + return clrRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 5); + } + + bool setBLDO2Voltage(uint16_t millivolt) + { + if (millivolt % AXP2101_BLDO2_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", AXP2101_BLDO2_VOL_STEPS); + return false; + } + if (millivolt < AXP2101_BLDO2_VOL_MIN) + { + log_e("Mistake ! BLDO2 minimum output voltage is %umV", AXP2101_BLDO2_VOL_MIN); + return false; + } + else if (millivolt > AXP2101_BLDO2_VOL_MAX) + { + log_e("Mistake ! BLDO2 maximum output voltage is %umV", AXP2101_BLDO2_VOL_MAX); + return false; + } + uint16_t val = readRegister(AXP2101_LDO_VOL5_CTRL) & 0xE0; + val |= (millivolt - AXP2101_BLDO2_VOL_MIN) / AXP2101_BLDO2_VOL_STEPS; + return 0 == writeRegister(AXP2101_LDO_VOL5_CTRL, val); + } + + uint16_t getBLDO2Voltage(void) + { + int val = readRegister(AXP2101_LDO_VOL5_CTRL); + if (val == -1) + return 0; + val &= 0x1F; + return val * AXP2101_BLDO2_VOL_STEPS + AXP2101_BLDO2_VOL_MIN; + } + + /* + * Power control CPUSLDO functions + */ + bool isEnableCPUSLDO(void) + { + return getRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 6); + } + + bool enableCPUSLDO(void) + { + return setRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 6); + } + + bool disableCPUSLDO(void) + { + return clrRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 6); + } + + bool setCPUSLDOVoltage(uint16_t millivolt) + { + if (millivolt % AXP2101_CPUSLDO_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", AXP2101_CPUSLDO_VOL_STEPS); + return false; + } + if (millivolt < AXP2101_CPUSLDO_VOL_MIN) + { + log_e("Mistake ! CPULDO minimum output voltage is %umV", AXP2101_CPUSLDO_VOL_MIN); + return false; + } + else if (millivolt > AXP2101_CPUSLDO_VOL_MAX) + { + log_e("Mistake ! CPULDO maximum output voltage is %umV", AXP2101_CPUSLDO_VOL_MAX); + return false; + } + uint16_t val = readRegister(AXP2101_LDO_VOL6_CTRL) & 0xE0; + val |= (millivolt - AXP2101_CPUSLDO_VOL_MIN) / AXP2101_CPUSLDO_VOL_STEPS; + return 0 == writeRegister(AXP2101_LDO_VOL6_CTRL, val); + } + + uint16_t getCPUSLDOVoltage(void) + { + int val = readRegister(AXP2101_LDO_VOL6_CTRL); + if (val == -1) + return 0; + val &= 0x1F; + return val * AXP2101_CPUSLDO_VOL_STEPS + AXP2101_CPUSLDO_VOL_MIN; + } + + /* + * Power control DLDO1 functions + */ + bool isEnableDLDO1(void) + { + return getRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 7); + } + + bool enableDLDO1(void) + { + return setRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 7); + } + + bool disableDLDO1(void) + { + return clrRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 7); + } + + bool setDLDO1Voltage(uint16_t millivolt) + { + if (millivolt % AXP2101_DLDO1_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", AXP2101_DLDO1_VOL_STEPS); + return false; + } + if (millivolt < AXP2101_DLDO1_VOL_MIN) + { + log_e("Mistake ! DLDO1 minimum output voltage is %umV", AXP2101_DLDO1_VOL_MIN); + return false; + } + else if (millivolt > AXP2101_DLDO1_VOL_MAX) + { + log_e("Mistake ! DLDO1 maximum output voltage is %umV", AXP2101_DLDO1_VOL_MAX); + return false; + } + uint16_t val = readRegister(AXP2101_LDO_VOL7_CTRL) & 0xE0; + val |= (millivolt - AXP2101_DLDO1_VOL_MIN) / AXP2101_DLDO1_VOL_STEPS; + return 0 == writeRegister(AXP2101_LDO_VOL7_CTRL, val); + } + + uint16_t getDLDO1Voltage(void) + { + int val = readRegister(AXP2101_LDO_VOL7_CTRL); + if (val == -1) + return 0; + val &= 0x1F; + return val * AXP2101_DLDO1_VOL_STEPS + AXP2101_DLDO1_VOL_MIN; + } + + /* + * Power control DLDO2 functions + */ + bool isEnableDLDO2(void) + { + return getRegisterBit(AXP2101_LDO_ONOFF_CTRL1, 0); + } + + bool enableDLDO2(void) + { + return setRegisterBit(AXP2101_LDO_ONOFF_CTRL1, 0); + } + + bool disableDLDO2(void) + { + return clrRegisterBit(AXP2101_LDO_ONOFF_CTRL1, 0); + } + + bool setDLDO2Voltage(uint16_t millivolt) + { + if (millivolt % AXP2101_DLDO2_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", AXP2101_DLDO2_VOL_STEPS); + return false; + } + if (millivolt < AXP2101_DLDO2_VOL_MIN) + { + log_e("Mistake ! DLDO2 minimum output voltage is %umV", AXP2101_DLDO2_VOL_MIN); + return false; + } + else if (millivolt > AXP2101_DLDO2_VOL_MAX) + { + log_e("Mistake ! DLDO2 maximum output voltage is %umV", AXP2101_DLDO2_VOL_MAX); + return false; + } + uint16_t val = readRegister(AXP2101_LDO_VOL8_CTRL) & 0xE0; + val |= (millivolt - AXP2101_DLDO2_VOL_MIN) / AXP2101_DLDO2_VOL_STEPS; + return 0 == writeRegister(AXP2101_LDO_VOL8_CTRL, val); + } + + uint16_t getDLDO2Voltage(void) + { + int val = readRegister(AXP2101_LDO_VOL8_CTRL); + if (val == -1) + return 0; + val &= 0x1F; + return val * AXP2101_DLDO2_VOL_STEPS + AXP2101_DLDO2_VOL_MIN; + } + + /* + * Power ON OFF IRQ TIMMING Control method + */ + + void setIrqLevelTime(pmic_irq_time opt) + { + int val = readRegister(AXP2101_IRQ_OFF_ON_LEVEL_CTRL); + if (val == -1) + return; + val &= 0xCF; + writeRegister(AXP2101_IRQ_OFF_ON_LEVEL_CTRL, val | (opt << 4)); + } + + pmic_irq_time getIrqLevelTime(void) + { + return (pmic_irq_time)((readRegister(AXP2101_IRQ_OFF_ON_LEVEL_CTRL) & 0x30) >> 4); + } + + /** + * @brief Set the PEKEY power-on long press time. + * @param opt: See pmic_press_on_time_t enum for details. + * @retval + */ + bool setPowerKeyPressOnTime(pmic_press_on_time opt) + { + int val = readRegister(AXP2101_IRQ_OFF_ON_LEVEL_CTRL); + if (val == -1) + return false; + val &= 0xFC; + return 0 == writeRegister(AXP2101_IRQ_OFF_ON_LEVEL_CTRL, val | opt); + } + + /** + * @brief Get the PEKEY power-on long press time. + * @retval See pmic_press_on_time_t enum for details. + */ + pmic_press_on_time getPowerKeyPressOnTime(void) + { + int val = readRegister(AXP2101_IRQ_OFF_ON_LEVEL_CTRL); + if (val == -1) + return pmic_press_on_time(0); + return static_cast(val & 0x03); + } + + /** + * @brief Set the PEKEY power-off long press time. + * @param opt: See pmic_press_off_time_t enum for details. + * @retval + */ + bool setPowerKeyPressOffTime(pmic_press_off_time opt) + { + int val = readRegister(AXP2101_IRQ_OFF_ON_LEVEL_CTRL); + if (val == -1) + return false; + val &= 0xF3; + return 0 == writeRegister(AXP2101_IRQ_OFF_ON_LEVEL_CTRL, val | (opt << 2)); + } + + /** + * @brief Get the PEKEY power-off long press time. + * @retval See pmic_press_off_time_t enum for details. + */ + pmic_press_off_time getPowerKeyPressOffTime(void) + { + return (pmic_press_off_time)((readRegister(AXP2101_IRQ_OFF_ON_LEVEL_CTRL) & 0x0C) >> 2); + } + + /* + * ADC Control method + */ + bool enableGeneralAdcChannel(void) + { + return setRegisterBit(AXP2101_ADC_CHANNEL_CTRL, 5); + } + + bool disableGeneralAdcChannel(void) + { + return clrRegisterBit(AXP2101_ADC_CHANNEL_CTRL, 5); + } + + bool enableTemperatureMeasure(void) + { + return setRegisterBit(AXP2101_ADC_CHANNEL_CTRL, 4); + } + + bool disableTemperatureMeasure(void) + { + return clrRegisterBit(AXP2101_ADC_CHANNEL_CTRL, 4); + } + + float getTemperature(void) + { + uint16_t raw = readRegisterH6L8(AXP2101_ADC_DATA_RELUST8, AXP2101_ADC_DATA_RELUST9); + return AXP2101_CONVERSION(raw); + } + + bool enableSystemVoltageMeasure(void) + { + return setRegisterBit(AXP2101_ADC_CHANNEL_CTRL, 3); + } + + bool disableSystemVoltageMeasure(void) + { + return clrRegisterBit(AXP2101_ADC_CHANNEL_CTRL, 3); + } + + uint16_t getSystemVoltage(void) + { + return readRegisterH6L8(AXP2101_ADC_DATA_RELUST6, AXP2101_ADC_DATA_RELUST7); + } + + bool enableVbusVoltageMeasure(void) + { + return setRegisterBit(AXP2101_ADC_CHANNEL_CTRL, 2); + } + + bool disableVbusVoltageMeasure(void) + { + return clrRegisterBit(AXP2101_ADC_CHANNEL_CTRL, 2); + } + + uint16_t getVbusVoltage(void) + { + if (!isVbusIn()) + { + return 0; + } + return readRegisterH6L8(AXP2101_ADC_DATA_RELUST4, AXP2101_ADC_DATA_RELUST5); + } + + bool enableTSPinMeasure(void) + { + return setRegisterBit(AXP2101_ADC_CHANNEL_CTRL, 1); + } + + bool disableTSPinMeasure(void) + { + return clrRegisterBit(AXP2101_ADC_CHANNEL_CTRL, 1); + } + + bool enableTSPinLowFreqSample(void) + { + return setRegisterBit(AXP2101_ADC_CHANNEL_CTRL, 7); + } + + bool disableTSPinLowFreqSample(void) + { + return clrRegisterBit(AXP2101_ADC_DATA_RELUST2, 7); + } + + uint16_t getTsTemperature(void) + { + return readRegisterH6L8(AXP2101_ADC_DATA_RELUST2, AXP2101_ADC_DATA_RELUST3); + } + + bool enableBattVoltageMeasure(void) + { + return setRegisterBit(AXP2101_ADC_CHANNEL_CTRL, 0); + } + + bool disableBattVoltageMeasure(void) + { + return clrRegisterBit(AXP2101_ADC_CHANNEL_CTRL, 0); + } + + bool enableBattDetection(void) + { + return setRegisterBit(AXP2101_BAT_DET_CTRL, 0); + } + + bool disableBattDetection(void) + { + return clrRegisterBit(AXP2101_BAT_DET_CTRL, 0); + } + + uint16_t getBattVoltage(void) + { + if (!isBatteryConnect()) + { + return 0; + } + return readRegisterH5L8(AXP2101_ADC_DATA_RELUST0, AXP2101_ADC_DATA_RELUST1); + } + + uint8_t getBatteryPercent(void) + { + if (!isBatteryConnect()) + { + return -1; + } + return readRegister(AXP2101_BAT_PERCENT_DATA); + } + + /* + * CHG LED setting and control + */ + // void enableChargingLed(void) + // { + // setRegisterBit(AXP2101_CHGLED_SET_CTRL, 0); + // } + + // void disableChargingLed(void) + // { + // clrRegisterBit(AXP2101_CHGLED_SET_CTRL, 0); + // } + + /** + * @brief Set charging led mode. + * @retval See pmic_chg_led_mode_t enum for details. + */ + void setChargingLedMode(pmic_chg_led_mode mode) + { + int val; + switch (mode) + { + case CHG_LED_OFF: + // clrRegisterBit(AXP2101_CHGLED_SET_CTRL, 0); + // break; + case CHG_LED_BLINK_1HZ: + case CHG_LED_BLINK_4HZ: + case CHG_LED_ON: + val = readRegister(AXP2101_CHGLED_SET_CTRL); + if (val == -1) + return; + val &= 0xC8; + val |= 0x05; // use manual ctrl + val |= (mode << 4); + writeRegister(AXP2101_CHGLED_SET_CTRL, val); + break; + case CHG_LED_CTRL_CHG: + val = readRegister(AXP2101_CHGLED_SET_CTRL); + if (val == -1) + return; + val &= 0xF9; + writeRegister(AXP2101_CHGLED_SET_CTRL, val | 0x01); // use type A mode + // writeRegister(AXP2101_CHGLED_SET_CTRL, val | 0x02); // use type B mode + break; + default: + break; + } + } + + pmic_chg_led_mode getChargingLedMode() + { + int val = readRegister(AXP2101_CHGLED_SET_CTRL); + if (val == -1) + return CHG_LED_OFF; + val >>= 1; + if ((val & 0x02) == 0x02) + { + val >>= 4; + return static_cast(val & 0x03); + } + return CHG_LED_CTRL_CHG; + } + + /** + * @brief 预充电充电电流限制 + * @note Precharge current limit 25*N mA + * @param opt: 25 * opt + * @retval None + */ + void setPrechargeCurr(pmic_prechg opt) + { + int val = readRegister(AXP2101_IPRECHG_SET); + if (val == -1) + return; + val &= 0xFC; + writeRegister(AXP2101_IPRECHG_SET, val | opt); + } + + pmic_prechg getPrechargeCurr(void) + { + return (pmic_prechg)(readRegister(AXP2101_IPRECHG_SET) & 0x03); + } + + /** + * @brief Set charge current. + * @param opt: See pmic_chg_curr_t enum for details. + * @retval + */ + bool setChargerConstantCurr(pmic_chg_curr opt) + { + if (opt > AXP2101_CHG_CUR_1000MA) + return false; + int val = readRegister(AXP2101_ICC_CHG_SET); + if (val == -1) + return false; + val &= 0xE0; + return 0 == writeRegister(AXP2101_ICC_CHG_SET, val | opt); + } + + /** + * @brief Get charge current settings. + * @retval See pmic_chg_curr_t enum for details. + */ + pmic_chg_curr getChargerConstantCurr(void) + { + int val = readRegister(AXP2101_ICC_CHG_SET); + if (val == -1) + return pmic_chg_curr(0); + return static_cast(val & 0x1F); + } + + /** + * @brief 充电终止电流限制 + * @note Charging termination of current limit + * @retval + */ + void setChargerTerminationCurr(pmic_chg_iterm opt) + { + int val = readRegister(AXP2101_ITERM_CHG_SET_CTRL); + if (val == -1) + return; + val &= 0xF0; + writeRegister(AXP2101_ITERM_CHG_SET_CTRL, val | opt); + } + + pmic_chg_iterm getChargerTerminationCurr(void) + { + return (pmic_chg_iterm)(readRegister(AXP2101_ITERM_CHG_SET_CTRL) & 0x0F); + } + + void enableChargerTerminationLimit(void) + { + int val = readRegister(AXP2101_ITERM_CHG_SET_CTRL); + if (val == -1) + return; + writeRegister(AXP2101_ITERM_CHG_SET_CTRL, val | 0x10); + } + + void disableChargerTerminationLimit(void) + { + int val = readRegister(AXP2101_ITERM_CHG_SET_CTRL); + if (val == -1) + return; + writeRegister(AXP2101_ITERM_CHG_SET_CTRL, val & 0xEF); + } + + bool isChargerTerminationLimit(void) + { + return getRegisterBit(AXP2101_ITERM_CHG_SET_CTRL, 4); + } + + /** + * @brief Set charge target voltage. + * @param opt: See pmic_chg_vol enum for details. + * @retval + */ + bool setChargeTargetVoltage(pmic_chg_vol opt) + { + if (opt >= AXP2101_CHG_VOL_MAX) + return false; + int val = readRegister(AXP2101_CV_CHG_VOL_SET); + if (val == -1) + return false; + val &= 0xF8; + return 0 == writeRegister(AXP2101_CV_CHG_VOL_SET, val | opt); + } + + /** + * @brief Get charge target voltage settings. + * @retval See pmic_chg_vol enum for details. + */ + pmic_chg_vol getChargeTargetVoltage(void) + { + return (pmic_chg_vol)(readRegister(AXP2101_CV_CHG_VOL_SET) & 0x07); + } + + /** + * @brief 设定热阈值 + * @note Thermal regulation threshold setting + */ + void setThermaThreshold(pmic_thermal opt) + { + int val = readRegister(AXP2101_THE_REGU_THRES_SET); + if (val == -1) + return; + val &= 0xFC; + writeRegister(AXP2101_THE_REGU_THRES_SET, val | opt); + } + + pmic_thermal getThermaThreshold(void) + { + return (pmic_thermal)(readRegister(AXP2101_THE_REGU_THRES_SET) & 0x03); + } + + uint8_t getBatteryParameter() + { + return readRegister(AXP2101_BAT_PARAME); + } + + void fuelGaugeControl(bool writeROM, bool enable) + { + if (writeROM) + { + clrRegisterBit(AXP2101_FUEL_GAUGE_CTRL, 4); + } + else + { + setRegisterBit(AXP2101_FUEL_GAUGE_CTRL, 4); + } + if (enable) + { + setRegisterBit(AXP2101_FUEL_GAUGE_CTRL, 0); + } + else + { + clrRegisterBit(AXP2101_FUEL_GAUGE_CTRL, 0); + } + } + + /* + * Interrupt status/control functions + */ + + /** + * @brief Get the interrupt controller mask value. + * @retval Mask value corresponds to pmic_irq , + */ + uint64_t getIrqStatus(void) + { + statusRegister[0] = readRegister(AXP2101_INTSTS1); + statusRegister[1] = readRegister(AXP2101_INTSTS2); + statusRegister[2] = readRegister(AXP2101_INTSTS3); + return (uint32_t)(statusRegister[0] << 16) | (uint32_t)(statusRegister[1] << 8) | (uint32_t)(statusRegister[2]); + } + + /** + * @brief Clear interrupt controller state. + */ + void clearIrqStatus() + { + for (int i = 0; i < AXP2101_INTSTS_CNT; i++) + { + writeRegister(AXP2101_INTSTS1 + i, 0xFF); + statusRegister[i] = 0; + } + } + + /* + * @brief Debug interrupt setting register + * */ + void printIntRegister(Stream *stream) + { + for (int i = 0; i < AXP2101_INTSTS_CNT; i++) + { + uint8_t val = readRegister(AXP2101_INTEN1 + i); + stream->print("INT["); + stream->print(i); + stream->print(']'); + stream->print(" HEX: "); + stream->print(val, HEX); + stream->print(" BIN:0b"); + stream->println(val, BIN); + } + } + + /** + * @brief Enable PMU interrupt control mask . + * @param opt: View the related chip type pmic_irq enumeration + * parameters in "XPowersParams.hpp" + * @retval + */ + bool enableIRQ(pmic_irq opt) + { + return setInterruptImpl(opt, true); + } + + /** + * @brief Disable PMU interrupt control mask . + * @param opt: View the related chip type pmic_irq enumeration + * parameters in "XPowersParams.hpp" + * @retval + */ + bool disableIRQ(pmic_irq opt) + { + return setInterruptImpl(opt, false); + } + + // IRQ STATUS 0 + bool isDropWarningLevel2Irq(void) + { + uint8_t mask = AXP2101_WARNING_LEVEL2_IRQ; + if (intRegister[0] & mask) + { + return IS_BIT_SET(statusRegister[0], mask); + } + return false; + } + + bool isDropWarningLevel1Irq(void) + { + uint8_t mask = AXP2101_WARNING_LEVEL1_IRQ; + if (intRegister[0] & mask) + { + return IS_BIT_SET(statusRegister[0], mask); + } + return false; + } + + bool isGaugeWdtTimeoutIrq() + { + uint8_t mask = AXP2101_WDT_TIMEOUT_IRQ; + if (intRegister[0] & mask) + { + return IS_BIT_SET(statusRegister[0], mask); + } + return false; + } + + bool isBatChargerOverTemperatureIrq(void) + { + uint8_t mask = AXP2101_BAT_CHG_OVER_TEMP_IRQ; + if (intRegister[0] & mask) + { + return IS_BIT_SET(statusRegister[0], mask); + } + return false; + } + + bool isBatChargerUnderTemperatureIrq(void) + { + uint8_t mask = AXP2101_BAT_CHG_UNDER_TEMP_IRQ; + if (intRegister[0] & mask) + { + return IS_BIT_SET(statusRegister[0], mask); + } + return false; + } + + bool isBatWorkOverTemperatureIrq(void) + { + uint8_t mask = AXP2101_BAT_NOR_OVER_TEMP_IRQ; + if (intRegister[0] & mask) + { + return IS_BIT_SET(statusRegister[0], mask); + } + return false; + } + + bool isBatWorkUnderTemperatureIrq(void) + { + uint8_t mask = AXP2101_BAT_NOR_UNDER_TEMP_IRQ; + if (intRegister[0] & mask) + { + return IS_BIT_SET(statusRegister[0], mask); + } + return false; + } + + // IRQ STATUS 1 + bool isVbusInsertIrq(void) + { + uint8_t mask = AXP2101_VBUS_INSERT_IRQ >> 8; + if (intRegister[1] & mask) + { + return IS_BIT_SET(statusRegister[1], mask); + } + return false; + } + + bool isVbusRemoveIrq(void) + { + uint8_t mask = AXP2101_VBUS_REMOVE_IRQ >> 8; + if (intRegister[1] & mask) + { + return IS_BIT_SET(statusRegister[1], mask); + } + return false; + } + + bool isBatInsertIrq(void) + { + uint8_t mask = AXP2101_BAT_INSERT_IRQ >> 8; + if (intRegister[1] & mask) + { + return IS_BIT_SET(statusRegister[1], mask); + } + return false; + } + + bool isBatRemoveIrq(void) + { + uint8_t mask = AXP2101_BAT_REMOVE_IRQ >> 8; + if (intRegister[1] & mask) + { + return IS_BIT_SET(statusRegister[1], mask); + } + return false; + } + + bool isPekeyShortPressIrq(void) + { + uint8_t mask = AXP2101_PKEY_SHORT_IRQ >> 8; + if (intRegister[1] & mask) + { + return IS_BIT_SET(statusRegister[1], mask); + } + return false; + } + + bool isPekeyLongPressIrq(void) + { + uint8_t mask = AXP2101_PKEY_LONG_IRQ >> 8; + if (intRegister[1] & mask) + { + return IS_BIT_SET(statusRegister[1], mask); + } + return false; + } + + bool isPekeyNegativeIrq(void) + { + uint8_t mask = AXP2101_PKEY_NEGATIVE_IRQ >> 8; + if (intRegister[1] & mask) + { + return IS_BIT_SET(statusRegister[1], mask); + } + return false; + } + + bool isPekeyPositiveIrq(void) + { + uint8_t mask = AXP2101_PKEY_POSITIVE_IRQ >> 8; + if (intRegister[1] & mask) + { + return IS_BIT_SET(statusRegister[1], mask); + } + return false; + } + + // IRQ STATUS 2 + bool isWdtExpireIrq(void) + { + uint8_t mask = AXP2101_WDT_EXPIRE_IRQ >> 16; + if (intRegister[2] & mask) + { + return IS_BIT_SET(statusRegister[2], mask); + } + return false; + } + + bool isLdoOverCurrentIrq(void) + { + uint8_t mask = AXP2101_LDO_OVER_CURR_IRQ >> 16; + if (intRegister[2] & mask) + { + return IS_BIT_SET(statusRegister[2], mask); + } + return false; + } + + bool isBatfetOverCurrentIrq(void) + { + uint8_t mask = AXP2101_BATFET_OVER_CURR_IRQ >> 16; + if (intRegister[2] & mask) + { + return IS_BIT_SET(statusRegister[2], mask); + } + return false; + } + + bool isBatChargeDoneIrq(void) + { + uint8_t mask = AXP2101_BAT_CHG_DONE_IRQ >> 16; + if (intRegister[2] & mask) + { + return IS_BIT_SET(statusRegister[2], mask); + } + return false; + } + + bool isBatChargeStartIrq(void) + { + uint8_t mask = AXP2101_BAT_CHG_START_IRQ >> 16; + if (intRegister[2] & mask) + { + return IS_BIT_SET(statusRegister[2], mask); + } + return false; + } + + bool isBatDieOverTemperatureIrq(void) + { + uint8_t mask = AXP2101_DIE_OVER_TEMP_IRQ >> 16; + if (intRegister[2] & mask) + { + return IS_BIT_SET(statusRegister[2], mask); + } + return false; + } + + bool isChargeOverTimeoutIrq(void) + { + uint8_t mask = AXP2101_CHAGER_TIMER_IRQ >> 16; + if (intRegister[2] & mask) + { + return IS_BIT_SET(statusRegister[2], mask); + } + return false; + } + + bool isBatOverVoltageIrq(void) + { + uint8_t mask = AXP2101_BAT_OVER_VOL_IRQ >> 16; + if (intRegister[2] & mask) + { + return IS_BIT_SET(statusRegister[2], mask); + } + return false; + } + + uint8_t getChipID(void) + { + return readRegister(AXP2101_IC_TYPE); + } + + protected: + uint16_t getPowerChannelVoltage(PMICPowerChannel channel) + { + switch (channel) + { + case DCDC1: + return getDC1Voltage(); + case DCDC2: + return getDC2Voltage(); + case DCDC3: + return getDC3Voltage(); + case DCDC4: + return getDC4Voltage(); + case DCDC5: + return getDC5Voltage(); + case ALDO1: + return getALDO1Voltage(); + case ALDO2: + return getALDO2Voltage(); + case ALDO3: + return getALDO3Voltage(); + case ALDO4: + return getALDO4Voltage(); + case BLDO1: + return getBLDO1Voltage(); + case BLDO2: + return getBLDO2Voltage(); + case DLDO1: + return getDLDO1Voltage(); + case DLDO2: + return getDLDO2Voltage(); + case VBACKUP: + return getButtonBatteryVoltage(); + default: + break; + } + return 0; + } + + bool inline enablePowerOutput(PMICPowerChannel channel) + { + switch (channel) + { + case DCDC1: + return enableDC1(); + case DCDC2: + return enableDC2(); + case DCDC3: + return enableDC3(); + case DCDC4: + return enableDC4(); + case DCDC5: + return enableDC5(); + case ALDO1: + return enableALDO1(); + case ALDO2: + return enableALDO2(); + case ALDO3: + return enableALDO3(); + case ALDO4: + return enableALDO4(); + case BLDO1: + return enableBLDO1(); + case BLDO2: + return enableBLDO2(); + case DLDO1: + return enableDLDO1(); + case DLDO2: + return enableDLDO2(); + case VBACKUP: + return enableButtonBatteryCharge(); + default: + break; + } + return false; + } + + bool inline disablePowerOutput(PMICPowerChannel channel) + { + if (getProtectedChannel(channel)) + { + log_e("Failed to disable the power channel, the power channel has been protected"); + return false; + } + switch (channel) + { + case DCDC1: + return disableDC1(); + case DCDC2: + return disableDC2(); + case DCDC3: + return disableDC3(); + case DCDC4: + return disableDC4(); + case DCDC5: + return disableDC5(); + case ALDO1: + return disableALDO1(); + case ALDO2: + return disableALDO2(); + case ALDO3: + return disableALDO3(); + case ALDO4: + return disableALDO4(); + case BLDO1: + return disableBLDO1(); + case BLDO2: + return disableBLDO2(); + case DLDO1: + return disableDLDO1(); + case DLDO2: + return disableDLDO2(); + case VBACKUP: + return disableButtonBatteryCharge(); + case CPULDO: + return disableCPUSLDO(); + default: + break; + } + return false; + } + + bool inline isPowerChannelEnable(PMICPowerChannel channel) + { + switch (channel) + { + case DCDC1: + return isEnableDC1(); + case DCDC2: + return isEnableDC2(); + case DCDC3: + return isEnableDC3(); + case DCDC4: + return isEnableDC4(); + case DCDC5: + return isEnableDC5(); + case ALDO1: + return isEnableALDO1(); + case ALDO2: + return isEnableALDO2(); + case ALDO3: + return isEnableALDO3(); + case ALDO4: + return isEnableALDO4(); + case BLDO1: + return isEnableBLDO1(); + case BLDO2: + return isEnableBLDO2(); + case DLDO1: + return isEnableDLDO1(); + case DLDO2: + return isEnableDLDO2(); + case VBACKUP: + return isEnableButtonBatteryCharge(); + case CPULDO: + return isEnableCPUSLDO(); + default: + break; + } + return false; + } + + bool inline setPowerChannelVoltage(PMICPowerChannel channel, uint16_t millivolt) + { + if (getProtectedChannel(channel)) + { + log_e("Failed to set the power channel, the power channel has been protected"); + return false; + } + switch (channel) + { + case DCDC1: + return setDC1Voltage(millivolt); + case DCDC2: + return setDC2Voltage(millivolt); + case DCDC3: + return setDC3Voltage(millivolt); + case DCDC4: + return setDC4Voltage(millivolt); + case DCDC5: + return setDC5Voltage(millivolt); + case ALDO1: + return setALDO1Voltage(millivolt); + case ALDO2: + return setALDO2Voltage(millivolt); + case ALDO3: + return setALDO3Voltage(millivolt); + case ALDO4: + return setALDO4Voltage(millivolt); + case BLDO1: + return setBLDO1Voltage(millivolt); + case BLDO2: + return setBLDO1Voltage(millivolt); + case DLDO1: + return setDLDO1Voltage(millivolt); + case DLDO2: + return setDLDO1Voltage(millivolt); + case VBACKUP: + return setButtonBatteryChargeVoltage(millivolt); + case CPULDO: + return setCPUSLDOVoltage(millivolt); + default: + break; + } + return false; + } + + bool initImpl() + { + if (getChipID() == AXP2101_CHIP_ID) + { + setChipModel(PMICChipModel::AXP2101); + disableTSPinMeasure(); // Disable NTC temperature detection by default + return true; + } + return false; + } + + /* + * Interrupt control functions + */ + bool setInterruptImpl(uint32_t opts, bool enable) + { + int res = 0; + uint8_t data = 0, value = 0; + log_d("%s - HEX:0x%x \n", enable ? "ENABLE" : "DISABLE", opts); + if (opts & 0x0000FF) + { + value = opts & 0xFF; + // log_d("Write INT0: %x\n", value); + data = readRegister(AXP2101_INTEN1); + intRegister[0] = enable ? (data | value) : (data & (~value)); + res |= writeRegister(AXP2101_INTEN1, intRegister[0]); + } + if (opts & 0x00FF00) + { + value = opts >> 8; + // log_d("Write INT1: %x\n", value); + data = readRegister(AXP2101_INTEN2); + intRegister[1] = enable ? (data | value) : (data & (~value)); + res |= writeRegister(AXP2101_INTEN2, intRegister[1]); + } + if (opts & 0xFF0000) + { + value = opts >> 16; + // log_d("Write INT2: %x\n", value); + data = readRegister(AXP2101_INTEN3); + intRegister[2] = enable ? (data | value) : (data & (~value)); + res |= writeRegister(AXP2101_INTEN3, intRegister[2]); + } + return res == 0; + } + + const char *getChipNameImpl(void) + { + return "AXP2101"; + } + + private: + uint8_t statusRegister[AXP2101_INTSTS_CNT]; + uint8_t intRegister[AXP2101_INTSTS_CNT]; + }; +} // namespace HAL::PMIC \ No newline at end of file diff --git a/lib/HAL/PMIC/DRIVER/AXP216.tpp b/lib/HAL/PMIC/DRIVER/AXP216.tpp new file mode 100644 index 000000000..e69de29bb diff --git a/lib/HAL/PMIC/DRIVER/AXP223.tpp b/lib/HAL/PMIC/DRIVER/AXP223.tpp new file mode 100644 index 000000000..e69de29bb diff --git a/lib/HAL/PMIC/DRIVER/BQ25896.tpp b/lib/HAL/PMIC/DRIVER/BQ25896.tpp new file mode 100644 index 000000000..31097decd --- /dev/null +++ b/lib/HAL/PMIC/DRIVER/BQ25896.tpp @@ -0,0 +1,1005 @@ +#include "../IMPL/TYPE2.tpp" +#include "../REG/BQ25896.hpp" +namespace HAL::PMIC +{ + class BQ25896 : public Type2 + { + friend class Base; + + public: + BQ25896(TwoWire &wire = Wire, int sda = SDA, int scl = SCL, uint8_t addr = BQ25896_SLAVE_ADDRESS) + { + myWire = &wire; + mySDA = sda; + mySCL = scl; + myADDR = addr; + } + + ~BQ25896() + { + log_d("~PowersBQ25896"); + end(); + } + + bool init(TwoWire &wire = Wire, int sda = SDA, int scl = SCL, uint8_t addr = BQ25896_SLAVE_ADDRESS) + { + myWire = &wire; + mySDA = sda; + mySCL = scl; + myADDR = addr; + r0C.reg = 0; + return begin(); + } + + const char *getChipName() + { + return getChipID() == BQ25896_DEV_REV ? "BQ25896" : "Unkown"; + } + + // VBUS Good Status + bool isVbusIn() + { + return getRegisterBit(POWERS_PPM_REG_11H, 7); + } + /*************************************************** + * POWERS_PPM_REG_00H ✅ + **************************************************/ + + // Input Current Limit + // Offset: 100mA + // Range: 100mA (000000) – 3.25A (111111) + // Default:0001000 (500mA) + // (Actual input current limit is the lower of I2C or ILIM pin) + // IINLIM bits are changed automaticallly after input source + // type detection is completed + // bq25896 + // PSEL = Hi (USB500) = 500mA + // PSEL = Lo = 3.25A + bool setInputCurrentLimit(uint16_t milliampere) + { + if (milliampere % BQ25896_IN_CURRENT_STEP) + { + log_e("Mistake ! The steps is must %u mA", BQ25896_IN_CURRENT_STEP); + return false; + } + if (milliampere < BQ25896_IN_CURRENT_MIN) + { + milliampere = BQ25896_IN_CURRENT_MIN; + } + if (milliampere > BQ25896_IN_CURRENT_MAX) + { + milliampere = BQ25896_IN_CURRENT_MAX; + } + int val = readRegister(POWERS_PPM_REG_00H); + if (val == -1) + return false; + val &= 0xC0; + milliampere = ((milliampere - BQ25896_IN_CURRENT_MIN) / BQ25896_IN_CURRENT_STEP); + val |= milliampere; + return writeRegister(POWERS_PPM_REG_00H, val) != -1; + } + + uint32_t getInputCurrentLimit() + { + int val = readRegister(POWERS_PPM_REG_00H); + if (val == -1) + return false; + val &= 0x3F; + return (val * BQ25896_IN_CURRENT_STEP) + BQ25896_IN_CURRENT_MIN; + } + + /*************************************************** + * POWERS_PPM_REG_01H ✅ + **************************************************/ + + // Boost Mode Hot Temperature Monitor Threshold + // 0x0 – VBHOT1 Threshold (34.75%) (default) + // 0x01 – VBHOT0 Threshold (Typ. 37.75%) + // 0x02 – VBHOT2 Threshold (Typ. 31.25%) + // 0x03 – Disable boost mode thermal protection + void setBoostModeHotTemperatureMonitorThreshold(uint8_t params) + { + int val = readRegister(POWERS_PPM_REG_01H); + if (val == -1) + return; + val &= 0x3F; + val |= (params << 6); + writeRegister(POWERS_PPM_REG_01H, val); + } + + // Boost Mode Cold Temperature Monitor Threshold + // 0 – VBCOLD0 Threshold (Typ. 77%) (default) + // 1 – VBCOLD1 Threshold (Typ. 80%) + void setBoostModeColdTemperatureMonitorThreshold(uint8_t params) + { + int val = readRegister(POWERS_PPM_REG_01H); + if (val == -1) + return; + val &= 0xDF; + val |= ((params & 0x01) << 5); + writeRegister(POWERS_PPM_REG_01H, val); + } + + // Input Voltage Limit Offset + // Default: 600mV (00110) + // Range: 0mV – 3100mV + // Minimum VINDPM threshold is clamped at 3.9V + // Maximum VINDPM threshold is clamped at 15.3V + // When VBUS at noLoad is ≤ 6V, the VINDPM_OS is used to calculate VINDPM threhold + // When VBUS at noLoad is > 6V, the VINDPM_OS multiple by 2 is used to calculate VINDPM threshold. + void setInputVoltageLimitOffset(uint16_t millivolt) + { + if (millivolt % BQ25896_IN_CURRENT_OFFSET_STEP) + { + log_e("Mistake ! The steps is must %u mA", BQ25896_IN_CURRENT_OFFSET_STEP); + return; + } + if (millivolt > BQ25896_IN_CURRENT_OFFSET_MAX) + { + millivolt = BQ25896_IN_CURRENT_OFFSET_MAX; + } + int val = readRegister(POWERS_PPM_REG_01H); + val &= 0xE0; + millivolt = (millivolt / BQ25896_IN_CURRENT_OFFSET_STEP); + val |= millivolt; + writeRegister(POWERS_PPM_REG_01H, val); + } + + // Input Current Optimizer (ICO) Enable + void enableInputCurrentOptimizer() + { + setRegisterBit(POWERS_PPM_REG_02H, 4); + } + + // Input Current Optimizer (ICO) Disable + void disableInputCurrentOptimizer() + { + clrRegisterBit(POWERS_PPM_REG_02H, 4); + } + + /*************************************************** + * POWERS_PPM_REG_03H ✅ + **************************************************/ + + bool setSysPowerDownVoltage(uint16_t millivolt) + { + if (millivolt % BQ25896_SYS_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", BQ25896_SYS_VOL_STEPS); + return false; + } + if (millivolt < BQ25896_SYS_VOFF_VOL_MIN) + { + log_e("Mistake ! SYS minimum output voltage is %umV", BQ25896_SYS_VOFF_VOL_MIN); + return false; + } + else if (millivolt > BQ25896_SYS_VOFF_VOL_MAX) + { + log_e("Mistake ! SYS maximum output voltage is %umV", BQ25896_SYS_VOFF_VOL_MAX); + return false; + } + int val = readRegister(POWERS_PPM_REG_03H); + if (val == -1) + return false; + val &= 0xF1; + val |= (millivolt - BQ25896_SYS_VOFF_VOL_MIN) / BQ25896_SYS_VOL_STEPS; + val <<= 1; + return 0 == writeRegister(POWERS_PPM_REG_03H, val); + } + + uint16_t getSysPowerDownVoltage() + { + int val = readRegister(POWERS_PPM_REG_03H); + if (val == -1) + return 0; + val &= 0x0E; + val >>= 1; + return (val * BQ25896_SYS_VOL_STEPS) + BQ25896_SYS_VOFF_VOL_MIN; + } + + // Minimum Battery Voltage (falling) to exit boost mode + void setExitBoostModeVoltage(ExitBoostModeVolt params) + { + switch (params) + { + case MINI_VOLT_2V9 : + clrRegisterBit(POWERS_PPM_REG_03H, 0); + break; + case MINI_VOLT_2V5 : + setRegisterBit(POWERS_PPM_REG_03H, 0); + break; + default : + break; + } + } + + /*************************************************** + * POWERS_PPM_REG_04H ✅ + **************************************************/ + + void enableCurrentPulseControl() + { + setRegisterBit(POWERS_PPM_REG_04H, 7); + } + + void disableCurrentPulseControl() + { + clrRegisterBit(POWERS_PPM_REG_04H, 7); + } + + uint16_t getChargerConstantCurr() + { + int val = readRegister(POWERS_PPM_REG_04H); + val &= 0x7F; + return val * BQ25896_FAST_CHG_CUR_STEP; + } + + /** + * @brief setChargerConstantCurr + * @note + * @param milliampere: Range:0~3008 mA / step:64mA + * @retval true : success false : failed + */ + bool setChargerConstantCurr(uint16_t milliampere) + { + if (milliampere % BQ25896_FAST_CHG_CUR_STEP) + { + log_e("Mistake ! The steps is must %u mA", BQ25896_FAST_CHG_CUR_STEP); + return false; + } + if (milliampere > BQ25896_FAST_CHG_CURRENT_MAX) + { + milliampere = BQ25896_FAST_CHG_CURRENT_MAX; + } + int val = readRegister(POWERS_PPM_REG_04H); + val &= 0x80; + val |= (milliampere / BQ25896_FAST_CHG_CUR_STEP); + return writeRegister(POWERS_PPM_REG_04H, val) != -1; + } + + /*************************************************** + * POWERS_PPM_REG_05H ✅ + **************************************************/ + + // Precharge Current Limit Range: 64mA ~ 1024mA ,step:64mA + bool setPrechargeCurr(uint16_t milliampere) + { + if (milliampere % BQ25896_PRE_CHG_CUR_STEP) + { + log_e("Mistake ! The steps is must %u mA", BQ25896_PRE_CHG_CUR_STEP); + return false; + } + if (milliampere < BQ25896_PRE_CHG_CURRENT_MIN) + { + milliampere = BQ25896_PRE_CHG_CURRENT_MIN; + } + if (milliampere > BQ25896_PRE_CHG_CURRENT_MAX) + { + milliampere = BQ25896_PRE_CHG_CURRENT_MAX; + } + int val = readRegister(POWERS_PPM_REG_05H); + val &= 0x0F; + milliampere = ((milliampere - BQ25896_PRE_CHG_CUR_BASE) / BQ25896_PRE_CHG_CUR_STEP); + val |= milliampere << 4; + return writeRegister(POWERS_PPM_REG_05H, val) != -1; + } + + uint16_t getPrechargeCurr(void) + { + int val = readRegister(POWERS_PPM_REG_05H); + val &= 0xF0; + val >>= 4; + return BQ25896_PRE_CHG_CUR_STEP + (val * BQ25896_PRE_CHG_CUR_STEP); + } + + // Precharge Current Limit Range: 64mA ~ 1024mA ,step:64mA + bool setTerminationCurr(uint16_t milliampere) + { + if (milliampere % BQ25896_TERM_CHG_CUR_STEP) + { + log_e("Mistake ! The steps is must %u mA", BQ25896_TERM_CHG_CUR_STEP); + return false; + } + if (milliampere < BQ25896_TERM_CHG_CURRENT_MIN) + { + milliampere = BQ25896_TERM_CHG_CURRENT_MIN; + } + if (milliampere > BQ25896_TERM_CHG_CURRENT_MAX) + { + milliampere = BQ25896_TERM_CHG_CURRENT_MAX; + } + int val = readRegister(POWERS_PPM_REG_05H); + val &= 0xF0; + milliampere = ((milliampere - BQ25896_TERM_CHG_CUR_BASE) / BQ25896_TERM_CHG_CUR_STEP); + val |= milliampere; + return writeRegister(POWERS_PPM_REG_05H, val) != -1; + } + + uint16_t getTerminationCurr(void) + { + int val = readRegister(POWERS_PPM_REG_05H); + val &= 0x0F; + return BQ25896_TERM_CHG_CUR_STEP + (val * BQ25896_TERM_CHG_CUR_STEP); + } + + /*************************************************** + * POWERS_PPM_REG_06H ✅ + **************************************************/ + uint16_t getChargeTargetVoltage() + { + int val = readRegister(POWERS_PPM_REG_06H); + val = (val & 0xFC) >> 2; + if (val > 0x30) + { + return BQ25896_FAST_CHG_VOL_MAX; + } + return val * BQ25896_CHG_VOL_STEP + BQ25896_CHG_VOL_BASE; + } + + // Charge Voltage Limit Range:3840 ~ 4608mV ,step:16 mV + bool setChargeTargetVoltage(uint16_t millivolt) + { + if (millivolt % BQ25896_CHG_VOL_STEP) + { + log_e("Mistake ! The steps is must %u mV", BQ25896_CHG_VOL_STEP); + return false; + } + if (millivolt < BQ25896_FAST_CHG_VOL_MIN) + { + millivolt = BQ25896_FAST_CHG_VOL_MIN; + } + if (millivolt > BQ25896_FAST_CHG_VOL_MAX) + { + millivolt = BQ25896_FAST_CHG_VOL_MAX; + } + int val = readRegister(POWERS_PPM_REG_06H); + val &= 0x03; + val |= (((millivolt - BQ25896_CHG_VOL_BASE) / BQ25896_CHG_VOL_STEP) << 2); + return writeRegister(POWERS_PPM_REG_06H, val) != -1; + } + + // Battery Precharge to Fast Charge Threshold + void setFastChargeThreshold(FastChargeThreshold threshold) + { + switch (threshold) + { + case FAST_CHG_THR_2V8 : + clrRegisterBit(POWERS_PPM_REG_06H, 1); + break; + case FAST_CHG_THR_3V0 : + setRegisterBit(POWERS_PPM_REG_06H, 1); + break; + default : + break; + } + } + + // Battery Recharge Threshold Offset(below Charge Voltage Limit) + void setBatteryRechargeThresholdOffset(RechargeThresholdOffset offset) + { + switch (offset) + { + case RECHARGE_OFFSET_100MV : + clrRegisterBit(POWERS_PPM_REG_06H, 0); + break; + case RECHARGE_OFFSET_200MV : + setRegisterBit(POWERS_PPM_REG_06H, 0); + break; + default : + break; + } + } + + /*************************************************** + * POWERS_PPM_REG_07H ✅ + **************************************************/ + + // JEITA Low Temperature Current Setting + // JEITA(Japan Electronics and Information Technology Industries Association) + // https://en.wikipedia.org/wiki/Japan_Electronics_and_Information_Technology_Industries_Association + void setJeitaLowTemperatureCurrent(enum REG07_00 params) + { + switch (params) + { + case JEITA_LOW_TEMP_50 : + clrRegisterBit(POWERS_PPM_REG_07H, 0); + break; + case JEITA_LOW_TEMP_20 : + setRegisterBit(POWERS_PPM_REG_07H, 0); + break; + default : + break; + } + } + + /*************************************************** + * POWERS_PPM_REG_08H ✅ + **************************************************/ + // IR Compensation Resistor Setting + // Range: 0 – 140mΩ + // Default: 0Ω (000) (i.e. Disable IRComp) + void setIRCompensationResistor(uint16_t params) + { + if (params % BQ25896_BAT_COMP_STEPS) + { + log_e("Mistake ! The steps is must %u mA", BQ25896_BAT_COMP_STEPS); + return; + } + if (params > BQ25896_TERM_CHG_CURRENT_MAX) + { + params = BQ25896_TERM_CHG_CURRENT_MAX; + } + int val = readRegister(POWERS_PPM_REG_08H); + if (val == -1) + return; + val &= 0x1F; + params = (params / BQ25896_BAT_COMP_STEPS); + val |= (params << 5); + writeRegister(POWERS_PPM_REG_08H, val); + } + + // IR Compensation Voltage Clamp + // above VREG (REG06[7:2]) + // Offset: 0mV + // Range: 0-224mV + // Default: 0mV (000) + void setIRCompensationVoltageClamp(uint16_t params) + { + if (params % BQ25896_VCLAMP_STEPS) + { + log_e("Mistake ! The steps is must %u mA", BQ25896_VCLAMP_STEPS); + return; + } + if (params > BQ25896_TERM_CHG_CURRENT_MAX) + { + params = BQ25896_TERM_CHG_CURRENT_MAX; + } + int val = readRegister(POWERS_PPM_REG_08H); + if (val == -1) + return; + val &= 0xE3; + params = (params / BQ25896_VCLAMP_STEPS); + val |= (params << 2); + writeRegister(POWERS_PPM_REG_08H, val); + } + + // Thermal Regulation Threshold + // 0x0 – 60°C + // 0x1 – 80°C + // 0x2 – 100°C + // 0x3 – 120°C (default) + void setThermalRegulationThreshold(uint8_t params) + { + int val = readRegister(POWERS_PPM_REG_08H); + if (val == -1) + return; + val &= 0xE3; + val |= (params); + writeRegister(POWERS_PPM_REG_08H, val); + } + + /*************************************************** + * POWERS_PPM_REG_09H + **************************************************/ + // Force Start Input Current Optimizer (ICO) + // 0 – Do not force ICO (default) + // 1 – Force ICO + // Note: This bit is can only be set only and always returns to 0 after ICO starts + void forceInputCurrentOptimizer(bool force) + { + force ? setRegisterBit(POWERS_PPM_REG_09H, 7) : clrRegisterBit(POWERS_PPM_REG_09H, 7); + } + + // Safety Timer Setting during DPM or Thermal Regulation + // 0 – Safety timer not slowed by 2X during input DPM or thermal regulation + // 1 – Safety timer slowed by 2X during input DPM or thermal regulation (default) + void setThermalRegulation(uint8_t params) + { + params ? setRegisterBit(POWERS_PPM_REG_09H, 6) : clrRegisterBit(POWERS_PPM_REG_09H, 6); + } + + // JEITA High Temperature Voltage Setting + // JEITA(Japan Electronics and Information Technology Industries Association) + // https://en.wikipedia.org/wiki/Japan_Electronics_and_Information_Technology_Industries_Association + // 0 – Set Charge Voltage to VREG-200mV during JEITA hig temperature(default) + // 1 – Set Charge Voltage to VREG during JEITA high temperature + void setJeitaHighTemperature(uint8_t params) + { + params ? setRegisterBit(POWERS_PPM_REG_09H, 4) : clrRegisterBit(POWERS_PPM_REG_09H, 4); + } + + // BATFET turn off delay control + // 0 – BATFET turn off immediately when BATFET_DIS bit is set (default) + // 1 – BATFET turn off delay by tSM_DLY when BATFET_DIS bit is set + void setTurnOffDelay(uint8_t params) + { + params ? setRegisterBit(POWERS_PPM_REG_09H, 3) : clrRegisterBit(POWERS_PPM_REG_09H, 3); + } + + // BATFET full system reset enable + // 0 – Disable BATFET full system reset + // 1 – Enable BATFET full system reset (default) + void setFullSystemReset(uint8_t params) + { + params ? setRegisterBit(POWERS_PPM_REG_09H, 2) : clrRegisterBit(POWERS_PPM_REG_09H, 2); + } + + // Current pulse control voltage up enable + // 0 – Disable (default) + // 1 – Enable + // Note: This bit is can only be set when EN_PUMPX bit is set and returns to 0 after current pulse control sequence is completed + void setCurrentPulseControlVoltageUp(uint8_t params) + { + params ? setRegisterBit(POWERS_PPM_REG_09H, 1) : clrRegisterBit(POWERS_PPM_REG_09H, 1); + } + + // Current pulse control voltage down enable + // 0 – Disable (default) + // 1 – Enable + // Note: This bit is can only be set when EN_PUMPX bit is set and returns to 0 after current pulse control sequence is completed + void setCurrentPulseControlVoltageDown(uint8_t params) + { + params ? setRegisterBit(POWERS_PPM_REG_09H, 0) : clrRegisterBit(POWERS_PPM_REG_09H, 0); + } + + /*************************************************** + * POWERS_PPM_REG_0AH ✅ + **************************************************/ + + // Boost Mode Voltage Regulation: 4550mV ~ 5510mV + bool setBoostVoltage(uint16_t millivolt) + { + if (millivolt % BQ25896_BOOTS_VOL_STEP) + { + log_e("Mistake ! The steps is must %u mV", BQ25896_BOOTS_VOL_STEP); + return false; + } + if (millivolt < BQ25896_BOOST_VOL_MIN) + { + millivolt = BQ25896_BOOST_VOL_MIN; + } + if (millivolt > BQ25896_BOOST_VOL_MAX) + { + millivolt = BQ25896_BOOST_VOL_MAX; + } + int val = readRegister(POWERS_PPM_REG_0AH); + val &= 0xF0; + val |= (((millivolt - BQ25896_BOOTS_VOL_BASE) / BQ25896_BOOTS_VOL_STEP) << 4); + return writeRegister(POWERS_PPM_REG_0AH, val) != -1; + } + + // Boost Current Limit: 500mA ~ 150 mA + bool setBoostCurrentLimit(BoostCurrentLimit milliampere) + { + if (milliampere > BOOST_CUR_LIMIT_2150MA) + { + return false; + } + int val = readRegister(POWERS_PPM_REG_0AH); + val &= 0x03; + val |= milliampere; + return writeRegister(POWERS_PPM_REG_0AH, val) != -1; + } + + // PFM mode allowed in boost mode + // 0 – Allow PFM in boost mode (default) + // 1 – Disable PFM in boost mode + void setBoostModeUsePFM(bool enable) + { + enable ? clrRegisterBit(POWERS_PPM_REG_0AH, 3) : setRegisterBit(POWERS_PPM_REG_0AH, 3); + } + + /*************************************************** + * POWERS_PPM_REG_0BH ✅ + **************************************************/ + + bool isPowerGood() + { + return getRegisterBit(POWERS_PPM_REG_0BH, 2); + } + + const char *getBusStatusString() + { + BusStatus status = getBusStatus(); + switch (status) + { + case BUS_STATE_NOINPUT : + return "No input"; + case BUS_STATE_USB_SDP : + return "USB Host SDP"; + case BUS_STATE_ADAPTER : + return "Adapter"; + case BUS_STATE_OTG : + return "OTG"; + default : + return "Unknown"; + } + } + + const char *getChargeStatusString() + { + ChargeStatus status = chargeStatus(); + switch (status) + { + case CHARGE_STATE_NO_CHARGE : + return "Not Charging"; + case CHARGE_STATE_PRE_CHARGE : + return "Pre-charge"; + case CHARGE_STATE_FAST_CHARGE : + return "Fast Charging"; + case CHARGE_STATE_DONE : + return "Charge Termination Done"; + default : + return "Unknown"; + } + } + + // VSYS Regulation Status + // 0 – Not in VSYSMIN regulation (BAT > VSYSMIN) + // 1 – In VSYSMIN regulation (BAT < VSYSMIN) + bool getVsysRegulationStatus() + { + return getRegisterBit(POWERS_PPM_REG_0BH, 0); + } + + const char *getVsysRegulationStatusString() + { + if (getVsysRegulationStatus()) + { + return "BAT < VSYSMIN"; + } + return "BAT > VSYSMIN"; + } + + /*************************************************** + * POWERS_PPM_REG_0CH ✅ + **************************************************/ + + // After reading the register, all will be cleared + uint8_t getFaultStatus(void) + { + readRegister(POWERS_PPM_REG_0CH, &r0C.reg); + return r0C.reg; + } + + // Watchdog Fault Status + // 0 – Normal + // 1- Watchdog timer expiration + bool isWatchdogFault() + { + return r0C.bits.WATCHDOG; + } + + // Boost Mode Fault Status + // 0 – Normal + // 1 – VBUS overloaded in OTG, or VBUS OVP, or battery is too low in boost mode + bool isBoostFault() + { + return r0C.bits.BOOST; + } + + // Charge Fault Status + // 00 – Normal + // 01 – Input fault (VBUS > VACOV or VBAT < VBUS < VVBUSMIN(typical 3.8V) + // 10 - Thermal shutdown + // 11 – Charge Safety Timer Expiration + uint8_t isChargeFault() + { + return r0C.bits.CHRG; + } + + // Battery Fault Status + // 0 – Normal + // 1 – BATOVP (VBAT > VBATOVP) + bool isBatteryFault() + { + return r0C.bits.BAT; + } + + // NTC Fault Status + bool isNTCFault() + { + return !(r0C.bits.NTC = REG0C_20::BUCK_NTC_NORMAL); + } + + // NTC Fault Status string + uint8_t getNTCStatus() + { + return r0C.bits.NTC; + } + + const char *getNTCStatusString() + { + uint8_t status = getNTCStatus(); + if (isOTG()) + { + // Boost mode + switch (status) + { + case BOOST_NTC_NORMAL : + return "Boost mode NTC normal"; + case BOOST_NTC_COLD : + return "Boost mode NTC cold"; + case BOOST_NTC_HOT : + return "Boost mode NTC hot"; + default : + break; + } + } + else + { + // Buck mode + switch (status) + { + case BUCK_NTC_NORMAL : + return "Buck mode NTC normal"; + case BUCK_NTC_WARM : + return "Buck mode NTC warm"; + case BUCK_NTC_COOL : + case BUCK_NTC_COLD : + return "Buck mode NTC cold"; + case BUCK_NTC_HOT : + return "Buck mode NTC hot"; + default : + break; + } + } + return "Unknown"; + } + + // Debug + void getReadOnlyRegisterValue() + { +#ifdef ARDUINO // debug .. + static uint8_t last_val[8] = {0}; + const uint8_t regis[] = { + POWERS_PPM_REG_0BH, + POWERS_PPM_REG_0CH, + // POWERS_PPM_REG_0EH, //BATTERY VOLTAGE + // POWERS_PPM_REG_0FH, //SYSTEM VOLTAGE + // POWERS_PPM_REG_10H, //NTC PERCENTAGE + // POWERS_PPM_REG_11H, //VBUS VOLTAGE + POWERS_PPM_REG_12H, + POWERS_PPM_REG_13H}; + Serial.println(); + Serial.println("-------------------------"); + for (uint32_t i = 0; i < sizeof(regis) / sizeof(regis[0]); ++i) + { + int val = readRegister(regis[i]); + if (val == -1) + { + continue; + } + if (last_val[i] != val) + { + Serial.printf("\t---> REG%02X Prev:0x%02X ", regis[i], last_val[i]); + Serial.print(" BIN:"); + Serial.print(last_val[i], BIN); + Serial.printf(" Curr: 0x%02X", val); + Serial.print(" BIN:"); + Serial.println(val, BIN); + last_val[i] = val; + } + Serial.printf("\tREG%02XH:0x%X BIN:0b", regis[i], val); + Serial.println(val, BIN); + } + Serial.println("-------------------------"); +#endif + } + + /*************************************************** + * POWERS_PPM_REG_0DH ✅ + **************************************************/ + // VINDPM Threshold Setting Method + // 0 – Run Relative VINDPM Threshold (default) + // 1 – Run Absolute VINDPM Threshold + // Note: Register is reset to default value when input source is plugged-in + void setVinDpmThresholdSetting(bool relative) + { + relative ? clrRegisterBit(POWERS_PPM_REG_0DH, 7) : setRegisterBit(POWERS_PPM_REG_0DH, 7); + } + + // Absolute VINDPM Threshold + bool setVinDpmThreshold(uint16_t millivolt) + { + if (millivolt % BQ25896_VINDPM_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", BQ25896_VINDPM_VOL_STEPS); + return false; + } + if (millivolt < BQ25896_VINDPM_VOL_MIN) + { + millivolt = BQ25896_VINDPM_VOL_MIN; + } + if (millivolt > BQ25896_VINDPM_VOL_MAX) + { + millivolt = BQ25896_VINDPM_VOL_MAX; + } + int val = readRegister(POWERS_PPM_REG_0DH); + val &= 0x80; + val |= (((millivolt - BQ25896_VINDPM_VOL_BASE) / BQ25896_VINDPM_VOL_STEPS)); + return writeRegister(POWERS_PPM_REG_0DH, val) != -1; + } + + /*************************************************** + * POWERS_PPM_REG_0EH ✅ + **************************************************/ + // Thermal Regulation Status + // true – Normal + // false – In Thermal Regulation + bool isThermalRegulationNormal() + { + return getRegisterBit(POWERS_PPM_REG_0EH, 7) == false; + } + + // ADC conversion of Battery Voltage /mv + uint16_t getBattVoltage() + { + int val = readRegister(POWERS_PPM_REG_0EH); + if (val == -1) + return 0; + val = BQ25896_VBAT_MASK_VAL(val); + if (val == 0) + return 0; + return (val * BQ25896_VBAT_VOL_STEP) + BQ25896_VBAT_BASE_VAL; + } + + /*************************************************** + * POWERS_PPM_REG_0FH ✅ + **************************************************/ + + // ADC conversion of System Voltage (VSYS) + uint16_t getSystemVoltage() + { + int val = readRegister(POWERS_PPM_REG_0FH); + if (val == -1 || val == 0) + return 0; + return (BQ25896_VSYS_MASK_VAL(val) * BQ25896_VSYS_VOL_STEP) + BQ25896_VSYS_BASE_VAL; + } + + /*************************************************** + * POWERS_PPM_REG_10H ✅ + **************************************************/ + + // ADC conversion of TS Voltage (TS) as percentage of REGN + float getNTCPercentage() + { + int val = readRegister(POWERS_PPM_REG_10H); + if (val == -1) + return 0; + return (BQ25896_NTC_MASK_VAL(val) * BQ25896_NTC_VOL_STEP) + BQ25896_NTC_BASE_VAL; + } + + /*************************************************** + * POWERS_PPM_REG_11H ✅ + **************************************************/ + + // ADC conversion of VBUS voltage (VBUS) + uint16_t getVbusVoltage() + { + if (!isVbusIn()) + { + return 0; + } + int val = readRegister(POWERS_PPM_REG_11H); + return (BQ25896_VBUS_MASK_VAL(val) * BQ25896_VBUS_VOL_STEP) + BQ25896_VBUS_BASE_VAL; + } + + /*************************************************** + * POWERS_PPM_REG_12H ✅ + **************************************************/ + + // ADC conversion of Charge Current (IBAT) when VBAT > VBATSHORT + //* If the charger is disconnected, the value in the register + //* will remain the last value and will not be updated to 0. + uint16_t getChargeCurrent() + { + ChargeStatus status = chargeStatus(); + if (status == CHARGE_STATE_NO_CHARGE) + { + log_e("CHARGE_STATE_NO_CHARGE..."); + return 0; + } + int val = readRegister(POWERS_PPM_REG_12H); + if (val == 0 || val == -1) + { + log_e("read reg failed !..."); + return 0; + } + val = (val & 0x7F); + return (val * BQ25896_CHG_STEP_VAL); + } + + /*************************************************** + * POWERS_PPM_REG_13H ✅ + **************************************************/ + // VINDPM Status : DynamicPower-Path Management and Dynamic Power Management + bool isDynamicPowerManagement() + { + return getRegisterBit(POWERS_PPM_REG_13H, 7); + } + + // IINDPM Status + bool isInputCurrentLimit() + { + return getRegisterBit(POWERS_PPM_REG_13H, 6); + } + + // Input Current Limit in effect while Input Current Optimizer (ICO) is enabled + // Range: 100 ~ 3250 mA + bool setInputCurrentLimitOptimizer(uint16_t milliampere) + { + if (milliampere % BQ25896_IN_CURRENT_OPT_STEP) + { + log_e("Mistake ! The steps is must %u mA", BQ25896_IN_CURRENT_OPT_STEP); + return false; + } + if (milliampere < BQ25896_IN_CURRENT_OPT_MIN) + { + milliampere = BQ25896_IN_CURRENT_OPT_MIN; + } + if (milliampere > BQ25896_IN_CURRENT_OPT_MAX) + { + milliampere = BQ25896_IN_CURRENT_OPT_MAX; + } + int val = readRegister(POWERS_PPM_REG_13H); + if (val == -1) + return false; + val &= 0x3F; + milliampere = ((milliampere - BQ25896_IN_CURRENT_OPT_MIN) / BQ25896_IN_CURRENT_STEP); + val |= milliampere; + return writeRegister(POWERS_PPM_REG_13H, val) != -1; + } + + /*************************************************** + * POWERS_PPM_REG_14H ✅ + **************************************************/ + + // Input Current Optimizer (ICO) Status + // true – Optimization is in progress + // false – Maximum Input Current Detected + bool isInputCurrentOptimizer() + { + return getRegisterBit(POWERS_PPM_REG_14H, 6); + } + + // Device Configuration + uint8_t getDeviceConfig() + { + int val = readRegister(POWERS_PPM_REG_14H); + if (val == -1) + return 0; + return (val >> 3) & 0x03; + } + + protected: + bool initImpl() + { + __user_disable_charge = false; + setChipModel(PMICChipModel::BQ25896); + + uint8_t rev = getChipID(); + if (rev != BQ25896_DEV_REV) + { + return false; + } + // Set the minimum operating voltage. Below this voltage, the PMU will protect + // setSysPowerDownVoltage(3300); + + // Default disable Watchdog + disableWatchdog(); + + return true; + } + + union REG0C r0C; + union REG07 r07; + union REG0B r0B; + union REG0E r0E; + union REG0F r0F; + union REG10 r10; + union REG11 r11; + union REG12 r12; + union REG13 r13; + }; +} // namespace HAL::PMIC \ No newline at end of file diff --git a/lib/HAL/PMIC/DRIVER/SY6970.tpp b/lib/HAL/PMIC/DRIVER/SY6970.tpp new file mode 100644 index 000000000..7b5da0bcc --- /dev/null +++ b/lib/HAL/PMIC/DRIVER/SY6970.tpp @@ -0,0 +1,554 @@ +#include "../REG/SY6970.hpp" +#include "../IMPL/TYPE2.tpp" +namespace HAL::PMIC +{ + class SY6970 : public Type2 + { + friend class Base; + + public: + SY6970(TwoWire &wire = Wire, int sda = SDA, int scl = SCL, uint8_t addr = SY6970_SLAVE_ADDRESS) + { + myWire = &wire; + mySDA = sda; + mySCL = scl; + myADDR = addr; + } + + ~SY6970() + { + log_i("~PowersSY6970"); + end(); + } + + bool init(TwoWire &wire = Wire, int sda = SDA, int scl = SCL, uint8_t addr = SY6970_SLAVE_ADDRESS) + { + myWire = &wire; + mySDA = sda; + mySCL = scl; + myADDR = addr; + __irq_mask = 0; + return begin(); + } + + const char *getChipName() + { + return getChipID() == SY6970_DEV_REV ? "SY6970" : "Unknown"; + } + + /// REG0B + bool isVbusIn() + { + return getBusStatus() != BUS_STATE_NOINPUT; + } + + bool isBatteryConnect(void) __attribute__((error("Not implemented"))) + { + // TODO: + return false; + } + + bool isPowerGood() + { + return getRegisterBit(POWERS_PPM_REG_0BH, 2); + } + + bool setSysPowerDownVoltage(uint16_t millivolt) + { + if (millivolt % SY6970_SYS_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", SY6970_SYS_VOL_STEPS); + return false; + } + if (millivolt < SY6970_SYS_VOFF_VOL_MIN) + { + log_e("Mistake ! SYS minimum output voltage is %umV", SY6970_SYS_VOFF_VOL_MIN); + return false; + } + else if (millivolt > SY6970_SYS_VOFF_VOL_MAX) + { + log_e("Mistake ! SYS maximum output voltage is %umV", SY6970_SYS_VOFF_VOL_MAX); + return false; + } + int val = readRegister(POWERS_PPM_REG_03H); + if (val == -1) + return false; + val &= 0xF1; + val |= (millivolt - SY6970_SYS_VOFF_VOL_MIN) / SY6970_SYS_VOL_STEPS; + val <<= 1; + return 0 == writeRegister(POWERS_PPM_REG_03H, val); + } + + uint16_t getSysPowerDownVoltage() + { + int val = readRegister(POWERS_PPM_REG_03H); + if (val == -1) + return 0; + val &= 0x0E; + val >>= 1; + return (val * SY6970_SYS_VOL_STEPS) + SY6970_SYS_VOFF_VOL_MIN; + } + + const char *getBusStatusString() + { + BusStatus status = getBusStatus(); + switch (status) + { + case BUS_STATE_NOINPUT: + return "No input"; + case BUS_STATE_USB_SDP: + return "USB Host SDP"; + case BUS_STATE_USB_CDP: + return "USB CDP"; + case BUS_STATE_USB_DCP: + return "USB DCP"; + case BUS_STATE_HVDCP: + return "HVDCP"; + case BUS_STATE_ADAPTER: + case BUS_STATE_NO_STANDARD_ADAPTER: + return "Adapter"; + case BUS_STATE_OTG: + return "OTG"; + default: + return "Unknown"; + } + } + + const char *getChargeStatusString() + { + ChargeStatus status = chargeStatus(); + switch (status) + { + case CHARGE_STATE_NO_CHARGE: + return "Not Charging"; + case CHARGE_STATE_PRE_CHARGE: + return "Pre-charge"; + case CHARGE_STATE_FAST_CHARGE: + return "Fast Charging"; + case CHARGE_STATE_DONE: + return "Charge Termination Done"; + default: + return "Unknown"; + } + } + + uint8_t getNTCStatus() + { + return (__irq_mask & 0x07); + } + + const char *getNTCStatusString() + { + uint8_t status = getNTCStatus(); + + if (isOTG()) + { + // Boost mode + switch (status) + { + case BOOST_NTC_NORMAL: + return "Boost mode NTC normal"; + case BOOST_NTC_COLD: + return "Boost mode NTC cold"; + case BOOST_NTC_HOT: + return "Boost mode NTC hot"; + default: + break; + } + } + else + { + // Buck mode + switch (status) + { + case BUCK_NTC_NORMAL: + return "Buck mode NTC normal"; + case BUCK_NTC_WARM: + return "Buck mode NTC warm"; + case BUCK_NTC_COOL: + case BUCK_NTC_COLD: + return "Buck mode NTC cold"; + case BUCK_NTC_HOT: + return "Buck mode NTC hot"; + default: + break; + } + } + return "Unknown"; + } + + void enableInputCurrentLimit() + { + setRegisterBit(POWERS_PPM_REG_02H, 4); + } + + void disableInputCurrentLimit() + { + clrRegisterBit(POWERS_PPM_REG_02H, 4); + } + + void enableHVDCP() + { + setRegisterBit(POWERS_PPM_REG_02H, 3); + } + + void disableHVDCP() + { + clrRegisterBit(POWERS_PPM_REG_02H, 3); + } + + bool isEnableHVDCP() + { + return getRegisterBit(POWERS_PPM_REG_02H, 3); + } + + void setHighVoltageRequestedRange(RequestRange range) + { + switch (range) + { + case REQUEST_9V: + clrRegisterBit(POWERS_PPM_REG_02H, 2); + break; + case REQUEST_12V: + setRegisterBit(POWERS_PPM_REG_02H, 2); + break; + default: + break; + } + } + + RequestRange getHighVoltageRequestedRange() + { + return getRegisterBit(POWERS_PPM_REG_02H, 2) ? REQUEST_12V : REQUEST_9V; + } + + bool setInputCurrentLimit(uint16_t milliampere) + { + if (milliampere % SY6970_IN_CURRENT_STEP) + { + log_e("Mistake ! The steps is must %u mA", SY6970_IN_CURRENT_STEP); + return false; + } + if (milliampere < SY6970_IN_CURRENT_MIN) + { + milliampere = SY6970_IN_CURRENT_MIN; + } + if (milliampere > SY6970_IN_CURRENT_MAX) + { + milliampere = SY6970_IN_CURRENT_MAX; + } + int val = readRegister(POWERS_PPM_REG_00H); + if (val == -1) + return false; + val &= 0xC0; + milliampere = ((milliampere - SY6970_IN_CURRENT_MIN) / SY6970_IN_CURRENT_STEP); + val |= milliampere; + return writeRegister(POWERS_PPM_REG_00H, val) != -1; + } + + uint32_t getInputCurrentLimit() + { + int val = readRegister(POWERS_PPM_REG_00H); + if (val == -1) + return false; + val &= 0x3F; + return (val * SY6970_IN_CURRENT_STEP) + SY6970_IN_CURRENT_MIN; + } + + uint16_t getVbusVoltage() + { + if (!isVbusIn()) + { + return 0; + } + int val = readRegister(POWERS_PPM_REG_11H); + return (SY6970_VBUS_MASK_VAL(val) * SY6970_VBUS_VOL_STEP) + SY6970_VBUS_BASE_VAL; + } + + uint16_t getBattVoltage() + { + int val = readRegister(POWERS_PPM_REG_0EH); + val = SY6970_VBAT_MASK_VAL(val); + if (val == 0) + return 0; + return (val * SY6970_VBAT_VOL_STEP) + SY6970_VBAT_BASE_VAL; + } + + uint16_t getSystemVoltage() + { + int val = readRegister(POWERS_PPM_REG_0FH); + return (SY6970_VSYS_MASK_VAL(val) * SY6970_VSYS_VOL_STEP) + SY6970_VSYS_BASE_VAL; + } + + float getNTCPercentage() + { + int val = readRegister(POWERS_PPM_REG_10H); + return (SY6970_NTC_MASK_VAL(val) * SY6970_NTC_VOL_STEP) + SY6970_NTC_BASE_VAL; + } + + uint16_t getChargeCurrent() + { + ChargeStatus status = chargeStatus(); + if (status == CHARGE_STATE_NO_CHARGE) + { + return 0; + } + //* If the charger is disconnected, the value in the register + //* will remain the last value and will not be updated to 0. + int val = readRegister(POWERS_PPM_REG_12H); + if (val == 0) + return 0; + val = (val & 0x7F); + return (val * SY6970_CHG_STEP_VAL); + } + + // Range: 64mA ~ 1024 mA ,step:64mA + bool setPrechargeCurr(uint16_t milliampere) + { + if (milliampere % SY6970_PRE_CHG_CUR_STEP) + { + log_e("Mistake ! The steps is must %u mA", SY6970_PRE_CHG_CUR_STEP); + return false; + } + if (milliampere < SY6970_PRE_CHG_CURRENT_MIN) + { + milliampere = SY6970_PRE_CHG_CURRENT_MIN; + } + if (milliampere > SY6970_PRE_CHG_CURRENT_MAX) + { + milliampere = SY6970_PRE_CHG_CURRENT_MAX; + } + int val = readRegister(POWERS_PPM_REG_05H); + val &= 0x0F; + milliampere = ((milliampere - SY6970_PRE_CHG_CUR_BASE) / SY6970_PRE_CHG_CUR_STEP); + val |= milliampere << 4; + return writeRegister(POWERS_PPM_REG_05H, val) != -1; + } + + uint16_t getPrechargeCurr(void) + { + int val = readRegister(POWERS_PPM_REG_05H); + val &= 0xF0; + val >>= 4; + return SY6970_PRE_CHG_CUR_STEP + (val * SY6970_PRE_CHG_CUR_STEP); + } + + uint16_t getChargerConstantCurr() + { + int val = readRegister(POWERS_PPM_REG_04H); + val &= 0x7F; + return val * SY6970_FAST_CHG_CUR_STEP; + } + + /** + * @brief setChargerConstantCurr + * @note + * @param milliampere: SY6970 Range:0~5056 mA / step:64mA + * @retval true : success false : failed + */ + bool setChargerConstantCurr(uint16_t milliampere) + { + if (milliampere % SY6970_FAST_CHG_CUR_STEP) + { + log_e("Mistake ! The steps is must %u mA", SY6970_FAST_CHG_CUR_STEP); + return false; + } + if (milliampere > SY6970_FAST_CHG_CURRENT_MAX) + { + milliampere = SY6970_FAST_CHG_CURRENT_MAX; + } + int val = readRegister(POWERS_PPM_REG_04H); + val &= 0x80; + val |= (milliampere / SY6970_FAST_CHG_CUR_STEP); + return writeRegister(POWERS_PPM_REG_04H, val) != -1; + } + + uint16_t getChargeTargetVoltage() + { + int val = readRegister(POWERS_PPM_REG_06H); + val = (val & 0xFC) >> 2; + if (val > 0x30) + { + return SY6970_FAST_CHG_VOL_MAX; + } + return val * SY6970_CHG_VOL_STEP + SY6970_CHG_VOL_BASE; + } + + // Range:3840 ~ 4608mV ,step:16 mV + bool setChargeTargetVoltage(uint16_t millivolt) + { + if (millivolt % SY6970_CHG_VOL_STEP) + { + log_e("Mistake ! The steps is must %u mV", SY6970_CHG_VOL_STEP); + return false; + } + if (millivolt < SY6970_FAST_CHG_VOL_MIN) + { + millivolt = SY6970_FAST_CHG_VOL_MIN; + } + if (millivolt > SY6970_FAST_CHG_VOL_MAX) + { + millivolt = SY6970_FAST_CHG_VOL_MAX; + } + int val = readRegister(POWERS_PPM_REG_06H); + val &= 0x03; + val |= (((millivolt - SY6970_CHG_VOL_BASE) / SY6970_CHG_VOL_STEP) << 2); + return writeRegister(POWERS_PPM_REG_06H, val) != -1; + } + + // Turn off the battery power supply path. It can only be turned off when the + // battery is powered. It cannot be turned off when USB is connected. + // The device can only be powered on by pressing the PWR button or by connecting the power supply. + + // Boost Mode Voltage Regulation: 4550 mV ~ 5510 mV + bool setBoostVoltage(uint16_t millivolt) + { + if (millivolt % SY6970_BOOTS_VOL_STEP) + { + log_e("Mistake ! The steps is must %u mV", SY6970_BOOTS_VOL_STEP); + return false; + } + if (millivolt < SY6970_BOOST_VOL_MIN) + { + millivolt = SY6970_BOOST_VOL_MIN; + } + if (millivolt > SY6970_BOOST_VOL_MAX) + { + millivolt = SY6970_BOOST_VOL_MAX; + } + int val = readRegister(POWERS_PPM_REG_0AH); + val &= 0xF0; + val |= (((millivolt - SY6970_BOOTS_VOL_BASE) / SY6970_BOOTS_VOL_STEP) << 4); + return writeRegister(POWERS_PPM_REG_0AH, val) != -1; + } + + // Boost Current Limit: 500mA ~ 2450mA + bool setBoostCurrentLimit(BoostCurrentLimit milliampere) + { + if (milliampere > BOOST_CUR_LIMIT_2450MA) + { + return false; + } + int val = readRegister(POWERS_PPM_REG_0AH); + val &= 0x03; + val |= milliampere; + return writeRegister(POWERS_PPM_REG_0AH, val) != -1; + } + + uint8_t getFaultStatus(void) + { + int val = readRegister(POWERS_PPM_REG_0CH); + if (val == -1) + { + return 0; + } + __irq_mask = val; + return __irq_mask; + } + + void getReadOnlyRegisterValue() + { + static uint8_t last_val[8] = {0}; + const uint8_t regis[] = { + POWERS_PPM_REG_0BH, + POWERS_PPM_REG_0CH, + // POWERS_PPM_REG_0EH, //BATTERY VOLTAGE + // POWERS_PPM_REG_0FH, //SYSTEM VOLTAGE + // POWERS_PPM_REG_10H, //NTC PERCENTAGE + // POWERS_PPM_REG_11H, //VBUS VOLTAGE + POWERS_PPM_REG_12H, + POWERS_PPM_REG_13H}; + Serial.println(); + Serial.println("-------------------------"); + for (uint32_t i = 0; i < sizeof(regis) / sizeof(regis[0]); ++i) + { + int val = readRegister(regis[i]); + if (val == -1) + { + continue; + } + if (last_val[i] != val) + { + Serial.printf("\t---> REG%02X Prev:0x%02X ", regis[i], last_val[i]); + Serial.print(" BIN:"); + Serial.print(last_val[i], BIN); + Serial.printf(" Curr: 0x%02X", val); + Serial.print(" BIN:"); + Serial.println(val, BIN); + last_val[i] = val; + } + Serial.printf("\tREG%02XH:0x%X BIN:0b", regis[i], val); + Serial.println(val, BIN); + } + Serial.println("-------------------------"); + } + + bool isWatchdogFault() + { + return SY6970_IRQ_WTD_FAULT(__irq_mask); + } + + bool isBoostFault() + { + return SY6970_IRQ_BOOST_FAULT(__irq_mask); + } + + bool isChargeFault() + { + return SY6970_IRQ_CHG_FAULT(__irq_mask); + } + + bool isBatteryFault() + { + return SY6970_IRQ_BAT_FAULT(__irq_mask); + } + + bool isNTCFault() + { + return SY6970_IRQ_NTC_FAULT(__irq_mask); + } + + bool setVinDpmThreshold(uint16_t millivolt) + { + if (millivolt % SY6970_VINDPM_VOL_STEPS) + { + log_e("Mistake ! The steps is must %u mV", SY6970_VINDPM_VOL_STEPS); + return false; + } + if (millivolt < SY6970_VINDPM_VOL_MIN) + { + millivolt = SY6970_VINDPM_VOL_MIN; + } + if (millivolt > SY6970_VINDPM_VOL_MAX) + { + millivolt = SY6970_VINDPM_VOL_MAX; + } + int val = readRegister(POWERS_PPM_REG_0DH); + val &= 0x80; + val |= (((millivolt - SY6970_VINDPM_VOL_BASE) / SY6970_VINDPM_VOL_STEPS)); + return writeRegister(POWERS_PPM_REG_0DH, val) != -1; + } + + private: + bool initImpl() + { + __user_disable_charge = false; + setChipModel(PMICChipModel::BQ25896); + + uint8_t rev = getChipID(); + if (rev != SY6970_DEV_REV) + { + return false; + } + // Set the minimum operating voltage. Below this voltage, the PMU will protect + // setSysPowerDownVoltage(3300); + + // Default disable Watchdog + disableWatchdog(); + + return true; + } + + uint32_t __irq_mask; + }; +} // namespace HAL::PMIC \ No newline at end of file diff --git a/lib/HAL/PMIC/IMPL/TYPE2.hpp b/lib/HAL/PMIC/IMPL/TYPE2.hpp new file mode 100644 index 000000000..8dc5e9bf9 --- /dev/null +++ b/lib/HAL/PMIC/IMPL/TYPE2.hpp @@ -0,0 +1,91 @@ +#ifndef __TYPE2__ +#define __TYPE2__ +#define POWERS_PPM_REG_00H (0x00) +#define POWERS_PPM_REG_01H (0x01) +#define POWERS_PPM_REG_02H (0x02) +#define POWERS_PPM_REG_03H (0x03) +#define POWERS_PPM_REG_04H (0x04) +#define POWERS_PPM_REG_05H (0x05) +#define POWERS_PPM_REG_06H (0x06) +#define POWERS_PPM_REG_07H (0x07) +#define POWERS_PPM_REG_08H (0x08) +#define POWERS_PPM_REG_09H (0x09) +#define POWERS_PPM_REG_0AH (0x0A) +// Read only STATUS REG +#define POWERS_PPM_REG_0BH (0x0B) +// Read only CHARGE IRQ REG +#define POWERS_PPM_REG_0CH (0x0C) +// Absolute VINDPM Threshold +#define POWERS_PPM_REG_0DH (0x0D) +// Read only BATTERY VOLTAGE +#define POWERS_PPM_REG_0EH (0x0E) +// Read only SYSTEM VOLTAGE +#define POWERS_PPM_REG_0FH (0x0F) +// Read only NTC PERCENTAGE +#define POWERS_PPM_REG_10H (0x10) +// Read only VBUS VOLTAGE +#define POWERS_PPM_REG_11H (0x11) +// Read only CHARGE CURRENT +#define POWERS_PPM_REG_12H (0x12) +// Read only VINDPM/IINDPM STATUS/CURR LIMIT SETTING +#define POWERS_PPM_REG_13H (0x13) +// RESET REG +#define POWERS_PPM_REG_14H (0x14) +namespace HAL::PMIC +{ + enum BoostNTCStatus + { + BOOST_NTC_NORMAL = 0, + BOOST_NTC_COLD = 5, + BOOST_NTC_HOT = 6, + }; + + + enum MeasureMode + { + ONE_SHORT, + CONTINUOUS, + }; + + enum BoostFreq + { + BOOST_FREQ_1500KHZ, + BOOST_FREQ_500KHZ, + }; +/* + enum Timeout + { + TIMER_OUT_40SEC, // 40 Second + TIMER_OUT_80SEC, // 80 Second + TIMER_OUT_160SEC, // 160 Second + }; + + enum ChargeStatus + { + CHARGE_STATE_NO_CHARGE, + CHARGE_STATE_PRE_CHARGE, + CHARGE_STATE_FAST_CHARGE, + CHARGE_STATE_DONE, + CHARGE_STATE_UNKOWN, + }; + + enum NTCStatus + { + BUCK_NTC_NORMAL = 0, + BUCK_NTC_WARM = 2, + BUCK_NTC_COOL = 3, + BUCK_NTC_COLD = 5, + BUCK_NTC_HOT = 6, + }; + + enum FastChargeTimer + { + FAST_CHARGE_TIMER_5H, + FAST_CHARGE_TIMER_8H, + FAST_CHARGE_TIMER_12H, + FAST_CHARGE_TIMER_20H, + }; */ + +} + +#endif /* __TYPE2__ */ diff --git a/lib/HAL/PMIC/IMPL/TYPE2.tpp b/lib/HAL/PMIC/IMPL/TYPE2.tpp new file mode 100644 index 000000000..89cdd8f50 --- /dev/null +++ b/lib/HAL/PMIC/IMPL/TYPE2.tpp @@ -0,0 +1,388 @@ +#include "../PMIC.tpp" +#include "TYPE2.hpp" + +#include +#include +#include + +#ifdef PMIC_BQ25896 + #include "../REG/BQ25896.hpp" +#elif defined(PMIC_SY6970) + #include "../REG/SY6970.hpp" +#endif +namespace HAL::PMIC +{ + template + class Type2 : public Base + { + friend class Base; + + public: + virtual bool isPowerGood() = 0; + virtual uint16_t getSysPowerDownVoltage() = 0; + virtual const char *getBusStatusString() = 0; + virtual const char *getChargeStatusString() = 0; + virtual uint8_t getNTCStatus() = 0; + virtual const char *getNTCStatusString() = 0; + virtual bool isVbusIn() = 0; + + bool isEnableCharge() + { + return this->getRegisterBit(POWERS_PPM_REG_03H, 4); + } + + void disableCharge() + { + __user_disable_charge = true; + this->clrRegisterBit(POWERS_PPM_REG_03H, 4); + } + + void enableCharge() + { + __user_disable_charge = false; + this->setRegisterBit(POWERS_PPM_REG_03H, 4); + } + + bool isEnableOTG() + { + return this->getRegisterBit(POWERS_PPM_REG_03H, 5); + } + + void disableOTG() + { + this->clrRegisterBit(POWERS_PPM_REG_03H, 5); + /* + * After turning on the OTG function, the charging function will + * be automatically disabled. If the user does not disable the charging + * function, the charging function will be automatically enabled after + * turning off the OTG output. + * */ + if (!__user_disable_charge) + { + this->setRegisterBit(POWERS_PPM_REG_03H, 4); + } + } + + bool enableOTG() + { + if (isVbusIn()) + return false; + return this->setRegisterBit(POWERS_PPM_REG_03H, 5); + } + + void feedWatchdog() + { + this->setRegisterBit(POWERS_PPM_REG_03H, 6); + } + + // Charging Termination Enable + void enableChargingTermination() + { + this->setRegisterBit(POWERS_PPM_REG_07H, 7); + } + + // Charging Termination Enable + void disableChargingTermination() + { + this->clrRegisterBit(POWERS_PPM_REG_07H, 7); + } + + // Charging Termination Enable + bool isEnableChargingTermination() + { + return this->getRegisterBit(POWERS_PPM_REG_07H, 7); + } + + // STAT Pin function + void disableStatPin() + { + this->setRegisterBit(POWERS_PPM_REG_07H, 6); + } + + void enableStatPin() + { + this->clrRegisterBit(POWERS_PPM_REG_07H, 6); + } + + bool isEnableStatPin() + { + return this->getRegisterBit(POWERS_PPM_REG_07H, 6) == false; + } + + // I2C Watchdog Timer Setting + bool isEnableWatchdog() + { + int regVal = this->readRegister(POWERS_PPM_REG_07H); + if (regVal == -1) + { + log_e("Config watch dog failed!"); + return false; + } + regVal >>= 4; + return regVal & 0x03; + } + + void disableWatchdog() + { + int regVal = this->readRegister(POWERS_PPM_REG_07H); + regVal &= 0xCF; + this->writeRegister(POWERS_PPM_REG_07H, regVal); + } + + void enableWatchdog(Timeout val) + { + int regVal = this->readRegister(POWERS_PPM_REG_07H); + regVal &= 0xCF; + switch (val) + { + case TIMER_OUT_40SEC : + this->writeRegister(POWERS_PPM_REG_07H, regVal | 0x10); + break; + case TIMER_OUT_80SEC : + this->writeRegister(POWERS_PPM_REG_07H, regVal | 0x20); + break; + case TIMER_OUT_160SEC : + this->writeRegister(POWERS_PPM_REG_07H, regVal | 0x30); + break; + default : + break; + } + } + + void disableChargingSafetyTimer() + { + this->clrRegisterBit(POWERS_PPM_REG_07H, 3); + } + + void enableChargingSafetyTimer() + { + this->setRegisterBit(POWERS_PPM_REG_07H, 3); + } + + bool isEnableChargingSafetyTimer() + { + return this->getRegisterBit(POWERS_PPM_REG_07H, 3); + } + + void setFastChargeTimer(FastChargeTimer timer) + { + int val; + switch (timer) + { + case FAST_CHARGE_TIMER_5H : + case FAST_CHARGE_TIMER_8H : + case FAST_CHARGE_TIMER_12H : + case FAST_CHARGE_TIMER_20H : + val = this->readRegister(POWERS_PPM_REG_07H); + if (val == -1) + return; + val &= 0xF1; + val |= (timer << 1); + this->writeRegister(POWERS_PPM_REG_07H, val); + break; + default : + break; + } + } + + FastChargeTimer getFastChargeTimer() + { + int val = this->readRegister(POWERS_PPM_REG_07H); + return static_cast((val & 0x0E) >> 1); + } + + // Return Battery Load status + bool isEnableBatLoad() + { + return this->getRegisterBit(POWERS_PPM_REG_03H, 7); + } + + // Battery Load (10mA) Disable + void disableBatLoad() + { + this->clrRegisterBit(POWERS_PPM_REG_03H, 7); + } + + // Battery Load (10mA) Enable + void enableBatLoad() + { + this->setRegisterBit(POWERS_PPM_REG_03H, 7); + } + + bool enableMeasure(MeasureMode mode) + { + int val = this->readRegister(POWERS_PPM_REG_02H); + switch (mode) + { + case CONTINUOUS : + val |= _BV(6); + break; + case ONE_SHORT : + val &= (~_BV(6)); + default : + break; + } + val |= _BV(7); + return this->writeRegister(POWERS_PPM_REG_02H, val) != -1; + } + + bool disableADCMeasure() + { + int val = this->readRegister(POWERS_PPM_REG_02H); + if (val == -1) + { + return false; + } + val &= (~_BV(7)); + return this->writeRegister(POWERS_PPM_REG_02H, val) != 1; + } + + bool setBoostFreq(BoostFreq freq) + { + switch (freq) + { + case BOOST_FREQ_500KHZ : + return this->setRegisterBit(POWERS_PPM_REG_02H, 5); + case BOOST_FREQ_1500KHZ : + return this->clrRegisterBit(POWERS_PPM_REG_02H, 5); + default : + break; + } + return false; + } + + BoostFreq getBoostFreq() + { + return this->getRegisterBit(POWERS_PPM_REG_02H, 5) ? BOOST_FREQ_500KHZ : BOOST_FREQ_1500KHZ; + } + + // Enable Force Input Detection , Force PSEL detection + void enableInputDetection() + { + this->setRegisterBit(POWERS_PPM_REG_02H, 1); + } + + // Disable Force Input Detection , Not in PSEL detection (default) + void disableInputDetection() + { + this->clrRegisterBit(POWERS_PPM_REG_02H, 1); + } + + // Get Force DP/DM detection + bool isEnableInputDetection() + { + return this->getRegisterBit(POWERS_PPM_REG_02H, 1); + } + + // Enable PSEL detection when VBUS is plugged-in (default) + void enableAutomaticInputDetection() + { + this->setRegisterBit(POWERS_PPM_REG_02H, 0); + } + + // Disable PSEL detection when VBUS is plugged-in + void disableAutomaticInputDetection() + { + this->clrRegisterBit(POWERS_PPM_REG_02H, 0); + } + + // Get DPDM detection when BUS is plugged-in. + bool isEnableAutomaticInputDetection() + { + return this->getRegisterBit(POWERS_PPM_REG_02H, 0); + } + + void enterHizMode() + { + this->setRegisterBit(POWERS_PPM_REG_00H, 7); + } + + void exitHizMode() + { + this->clrRegisterBit(POWERS_PPM_REG_00H, 7); + } + + bool isHizMode() + { + return this->getRegisterBit(POWERS_PPM_REG_00H, 7); + } + + // Enable ILIM Pin + void enableCurrentLimitPin() + { + this->setRegisterBit(POWERS_PPM_REG_00H, 6); + } + + void disableCurrentLimitPin() + { + this->clrRegisterBit(POWERS_PPM_REG_00H, 6); + } + + bool isEnableCurrentLimitPin() + { + return this->getRegisterBit(POWERS_PPM_REG_00H, 6); + } + + bool isOTG() + { + return getBusStatus() == BUS_STATE_OTG; + } + + bool isCharging(void) + { + return chargeStatus() != CHARGE_STATE_NO_CHARGE; + } + + bool isChargeDone() + { + return chargeStatus() != CHARGE_STATE_DONE; + } + + BusStatus getBusStatus() + { + int val = this->readRegister(POWERS_PPM_REG_0BH); + return (BusStatus)((val >> 5) & 0x07); + } + + ChargeStatus chargeStatus() + { + int val = this->readRegister(POWERS_PPM_REG_0BH); + if (val == -1) + return CHARGE_STATE_UNKOWN; + return static_cast((val >> 3) & 0x03); + } + + void shutdown() + { + disableBatterPowerPath(); + } + + // Close battery power path + void disableBatterPowerPath() + { + this->setRegisterBit(POWERS_PPM_REG_09H, 5); // Force BATFET Off : BATFET_DIS + } + + // Enable battery power path + void enableBatterPowerPath() + { + this->clrRegisterBit(POWERS_PPM_REG_09H, 5); // Force BATFET Off : BATFET_DIS + } + + void resetDefault() + { + this->setRegisterBit(POWERS_PPM_REG_14H, 7); + } + + uint8_t getChipID() + { + int val = this->readRegister(POWERS_PPM_REG_14H); + if (val == -1) + return 0; + return (val & 0x03); + } + + protected: + bool __user_disable_charge; + }; +} // namespace HAL::PMIC \ No newline at end of file diff --git a/lib/HAL/PMIC/IMPL/XPOWERS.hpp b/lib/HAL/PMIC/IMPL/XPOWERS.hpp new file mode 100644 index 000000000..b691785a4 --- /dev/null +++ b/lib/HAL/PMIC/IMPL/XPOWERS.hpp @@ -0,0 +1,137 @@ +#ifndef __TYPE1__ +#define __TYPE1__ +#include + +#ifdef _BV +#undef _BV +#endif + +#define _BV(b) (1ULL << (uint64_t)(b)) +namespace HAL::PMIC +{ + /* + | CHIP | AXP173 | AXP192 | AXP202 | AXP2101 | + | ---------- | ----------------- | ----------------- | ----------------- | -------------------------------------- | + | DC1 | 0.7V-3.5V /1.2A | 0.7V-3.5V /1.2A | X | 1.5-3.4V /2A | + | DC2 | 0.7-2.275V/0.6A | 0.7-2.275V /1.6A | 0.7-2.275V /1.6A | 0.5-1.2V,1.22-1.54V /2A | + | DC3 | X | 0.7-3.5V /0.7A | 0.7-3.5V /1.2A | 0.5-1.2V,1.22-1.54V,1.6-3.4V /2A | + | DC4 | X | x | x | 0.5-1.2V,1.22-1.84V /1.5A | + | DC5 | X | x | x | 1.2V,1.4-3.7V /1A | + | LDO1(VRTC) | 3.3V /30mA | 3.3V /30mA | 3.3V /30mA | 1.8V /30mA | + | LDO2 | 1.8V-3.3V /200mA | 1.8V-3.3V /200mA | 1.8V-3.3V /200mA | x | + | LDO3 | 1.8V-3.3V /200mA | 1.8-3.3V /200mA | 0.7-3.5V /200mA | x | + | LDO4 | 0.7-3.5V /500mA | X | 1.8V-3.3V /200mA | x | + | LDO5/IO0 | X | 1.8-3.3V /50mA | 1.8-3.3V /50mA | x | + | ALDO1 | x | x | x | 0.5-3.5V /300mA | + | ALDO2 | x | x | x | 0.5-3.5V /300mA | + | ALDO3 | x | x | x | 0.5-3.5V /300mA | + | ALDO4 | x | x | x | 0.5-3.5V /300mA | + | BLDO1 | x | x | x | 0.5-3.5V /300mA | + | BLDO2 | x | x | x | 0.5-3.5V /300mA | + | DLDO1 | x | x | x | 0.5-3.3V/ 0.5-1.4V /300mA | + | DLDO1 | x | x | x | 0.5-3.3V/ 0.5-1.4V /300mA | + | CPUSLDO | x | x | x | 0.5-1.4V /30mA | + | | | | | | + */ + + /** + * @brief Each chip resource is different,please refer to the table above. + */ + enum PMICPowerChannel + { + DCDC1, + DCDC2, + DCDC3, + DCDC4, + DCDC5, + LDO1, + LDO2, + LDO3, + LDO4, + LDO5, + LDOIO, + ALDO1, + ALDO2, + ALDO3, + ALDO4, + BLDO1, + BLDO2, + DLDO1, + DLDO2, + VBACKUP, + CPULDO, + }; + + /** + * @brief PMU PEKEY Press off time parameters. + */ + enum pmic_press_off_time + { + POWEROFF_4S, + POWEROFF_6S, + POWEROFF_8S, + POWEROFF_10S, + }; + + /** + * @brief PMU PEKEY Press on time parameters. + */ + enum pmic_press_on_time + { + POWERON_128MS, + POWERON_512MS, + POWERON_1S, + POWERON_2S, + }; + + /** + * @brief Charging led mode parameters. + */ + enum pmic_chg_led_mode + { + CHG_LED_OFF, + CHG_LED_BLINK_1HZ, + CHG_LED_BLINK_4HZ, + CHG_LED_ON, + CHG_LED_CTRL_CHG, // The charging indicator is controlled by the charger + }; + + enum pmic_interrupt_enum + { + USB_INSERT_INT = _BV(0), + USB_REMOVE_INT = _BV(1), + BATTERY_INSERT_INT = _BV(2), + BATTERY_REMOVE_INT = _BV(3), + CHARGE_START_INT = _BV(4), + CHARGE_DONE_INT = _BV(5), + PWR_BTN_CLICK_INT = _BV(6), + PWR_BTN_LONGPRESSED_INT = _BV(7), + ALL_INT = _BV(8), + }; + + union battery_state + { + struct __st + { + uint16_t DSG : 1; + uint16_t SYSDWN : 1; + uint16_t TDA : 1; + uint16_t BATTPRES : 1; + uint16_t AUTH_GD : 1; + uint16_t OCVGD : 1; + uint16_t TCA : 1; + uint16_t RSVD : 1; + uint16_t CHGING : 1; + uint16_t FC : 1; + uint16_t OTD : 1; + uint16_t OTC : 1; + uint16_t SLEEP : 1; + uint16_t OCVFALL : 1; + uint16_t OCVCOMP : 1; + uint16_t FD : 1; + } st; + uint16_t full; + }; + +} +#endif /* __TYPE1__ */ \ No newline at end of file diff --git a/lib/HAL/PMIC/IMPL/XPOWERS.tpp b/lib/HAL/PMIC/IMPL/XPOWERS.tpp new file mode 100644 index 000000000..b55c50ab3 --- /dev/null +++ b/lib/HAL/PMIC/IMPL/XPOWERS.tpp @@ -0,0 +1,245 @@ +#include "../PMIC.tpp" +#include "XPOWERS.hpp" + +#include +#include + +#ifdef PMIC_AXP192 + #include "../REG/AXP192.hpp" +#elif defined(PMIC_AXP202) + #include "../REG/AXP202.hpp" +#elif defined(PMIC_AXP2101) + #include "../REG/AXP2101.hpp" +#endif +namespace HAL::PMIC +{ + template + class XPOWERS : public Base + { + friend class Base; + + public: + virtual bool enableSleep() = 0; + virtual uint16_t status() = 0; + virtual bool isDischarge() = 0; + virtual bool enablePowerOutput(PMICPowerChannel channel) = 0; + virtual bool disablePowerOutput(PMICPowerChannel channel) = 0; + virtual bool isPowerChannelEnable(PMICPowerChannel channel) = 0; + virtual uint16_t getPowerChannelVoltage(PMICPowerChannel channel) = 0; + virtual bool setPowerChannelVoltage(PMICPowerChannel channel, uint16_t millivolt) = 0; + virtual bool setVbusCurrentLimit(pmic_vbus_cur_limit opt) = 0; + virtual pmic_vbus_cur_limit getVbusCurrentLimit() = 0; + virtual void setVbusVoltageLimit(pmic_vbus_vol_limit opt) = 0; + virtual pmic_vbus_vol_limit getVbusVoltageLimit() = 0; + virtual bool setChargeTargetVoltage(pmic_chg_vol opt) = 0; + virtual bool setChargerConstantCurr(pmic_chg_curr opt) = 0; + virtual void setChargerTerminationCurr(pmic_chg_iterm opt) = 0; + virtual pmic_chg_iterm getChargerTerminationCurr(void) = 0; + virtual uint64_t getIrqStatus() = 0; + virtual void clearIrqStatus() = 0; + virtual bool enableIRQ(pmic_irq opt) = 0; + virtual bool disableIRQ(pmic_irq opt) = 0; + virtual bool isPekeyShortPressIrq() = 0; + virtual bool isPekeyLongPressIrq() = 0; + virtual bool isBatInsertIrq() = 0; + virtual bool isBatRemoveIrq() = 0; + virtual bool isVbusInsertIrq() = 0; + virtual bool isVbusRemoveIrq() = 0; + virtual bool isBatChargeDoneIrq() = 0; + virtual bool isBatChargeStartIrq() = 0; + virtual bool enableBattDetection() = 0; + virtual bool disableBattDetection() = 0; + virtual bool enableVbusVoltageMeasure(void) = 0; + virtual bool disableVbusVoltageMeasure(void) = 0; + virtual bool enableSystemVoltageMeasure(void) = 0; + virtual bool disableSystemVoltageMeasure(void) = 0; + virtual pmic_chg_curr getChargerConstantCurr() = 0; + virtual pmic_chg_vol getChargeTargetVoltage() = 0; + virtual bool enableTemperatureMeasure(void) = 0; + virtual bool disableTemperatureMeasure(void) = 0; + virtual bool enableBattVoltageMeasure(void) = 0; + virtual bool disableBattVoltageMeasure(void) = 0; + virtual bool enableTSPinMeasure(void) = 0; + virtual bool disableTSPinMeasure(void) = 0; + virtual void setChargingLedMode(pmic_chg_led_mode mode) = 0; + virtual pmic_chg_led_mode getChargingLedMode() = 0; + virtual bool setPowerKeyPressOnTime(pmic_press_on_time opt) = 0; + virtual pmic_press_on_time getPowerKeyPressOnTime() = 0; + virtual bool setPowerKeyPressOffTime(pmic_press_off_time opt) = 0; + virtual pmic_press_off_time getPowerKeyPressOffTime() = 0; + + typedef struct gpio_t + { + uint8_t mode; + }; + + uint16_t inline readRegisterH8L4(uint8_t highReg, uint8_t lowReg) + { + int h8 = this->readRegister(highReg); + int l4 = this->readRegister(lowReg); + if (h8 == -1 || l4 == -1) + return 0; + return (h8 << 4) | (l4 & 0x0F); + } + + uint16_t inline readRegisterH8L5(uint8_t highReg, uint8_t lowReg) + { + int h8 = this->readRegister(highReg); + int l5 = this->readRegister(lowReg); + if (h8 == -1 || l5 == -1) + return 0; + return (h8 << 5) | (l5 & 0x1F); + } + + uint16_t inline readRegisterH6L8(uint8_t highReg, uint8_t lowReg) + { + int h6 = this->readRegister(highReg); + int l8 = this->readRegister(lowReg); + if (h6 == -1 || l8 == -1) + return 0; + return ((h6 & 0x3F) << 8) | l8; + } + + uint16_t inline readRegisterH5L8(uint8_t highReg, uint8_t lowReg) + { + int h5 = this->readRegister(highReg); + int l8 = this->readRegister(lowReg); + if (h5 == -1 || l8 == -1) + return 0; + return ((h5 & 0x1F) << 8) | l8; + } + + bool isChannelAvailable(PMICPowerChannel channel) + { +#ifdef PMIC_AXP192 + switch (channel) + { + case DCDC1 : + case DCDC2 : + case DCDC3 : + case LDO2 : + case LDO3 : + case LDOIO : + return true; + default : + return false; + } +#elif defined(PMIC_AXP202) + + switch (channel) + { + case DCDC2 : + case DCDC3 : + case LDO2 : + case LDO3 : + case LDO4 : + case LDO5 : + return true; + default : + return false; + } +#elif defined(PMIC_AXP2101) + switch (channel) + { + case DCDC1 : + case DCDC2 : + case DCDC3 : + case DCDC4 : + case DCDC5 : + case ALDO1 : + case ALDO2 : + case ALDO3 : + case ALDO4 : + case BLDO1 : + case BLDO2 : + case VBACKUP : + case CPULDO : + return true; + default : + // DLDO is not available, will also return false + return false; + } +#endif + return false; + } + + void setProtectedChannel(PMICPowerChannel channel) + { + __protectedMask |= _BV(channel); + } + + void setUnprotectChannel(PMICPowerChannel channel) + { + __protectedMask &= (~_BV(channel)); + } + + bool getProtectedChannel(PMICPowerChannel channel) + { + return __protectedMask & _BV(channel); + } + + static uint64_t inline check_params(uint32_t opt, uint32_t params, uint64_t mask) + { + return ((opt & params) == params) ? mask : 0; + } + + bool enableInterrupt(uint32_t option) + { + return setInterruptMask(option, true); + } + + bool disableInterrupt(uint32_t option) + { + return setInterruptMask(option, false); + } + + bool setInterruptMask(uint32_t option, bool enable) + { + uint64_t params = 0; +#ifdef PMIC_AXP172 + return false; +#elif defined(PMIC_AXP192) + params |= check_params(option, USB_INSERT_INT, AXP192_VBUS_INSERT_IRQ); + params |= check_params(option, USB_REMOVE_INT, AXP192_VBUS_REMOVE_IRQ); + params |= check_params(option, BATTERY_INSERT_INT, AXP192_BAT_INSERT_IRQ); + params |= check_params(option, BATTERY_REMOVE_INT, AXP192_BAT_REMOVE_IRQ); + params |= check_params(option, CHARGE_START_INT, AXP192_BAT_CHG_START_IRQ); + params |= check_params(option, CHARGE_DONE_INT, AXP192_BAT_CHG_DONE_IRQ); + params |= check_params(option, PWR_BTN_CLICK_INT, AXP192_PKEY_SHORT_IRQ); + params |= check_params(option, PWR_BTN_LONGPRESSED_INT, AXP192_PKEY_LONG_IRQ); + params |= check_params(option, ALL_INT, AXP192_ALL_IRQ); + return enable ? enableIRQ(params) : disableIRQ(params); +#elif defined(PMIC_AXP202) + params |= check_params(option, USB_INSERT_INT, AXP202_VBUS_INSERT_IRQ); + params |= check_params(option, USB_REMOVE_INT, AXP202_VBUS_REMOVE_IRQ); + params |= check_params(option, BATTERY_INSERT_INT, AXP202_BAT_INSERT_IRQ); + params |= check_params(option, BATTERY_REMOVE_INT, AXP202_BAT_REMOVE_IRQ); + params |= check_params(option, CHARGE_START_INT, AXP202_BAT_CHG_START_IRQ); + params |= check_params(option, CHARGE_DONE_INT, AXP202_BAT_CHG_DONE_IRQ); + params |= check_params(option, PWR_BTN_CLICK_INT, AXP202_PKEY_SHORT_IRQ); + params |= check_params(option, PWR_BTN_LONGPRESSED_INT, AXP202_PKEY_LONG_IRQ); + params |= check_params(option, ALL_INT, AXP202_ALL_IRQ); + return enable ? enableIRQ(params) : disableIRQ(params); + break; +#elif defined(PMIC_216) + return false; +#elif defined(PMIC_AXP2101) + params |= check_params(option, USB_INSERT_INT, AXP2101_VBUS_INSERT_IRQ); + params |= check_params(option, USB_REMOVE_INT, AXP2101_VBUS_REMOVE_IRQ); + params |= check_params(option, BATTERY_INSERT_INT, AXP2101_BAT_INSERT_IRQ); + params |= check_params(option, BATTERY_REMOVE_INT, AXP2101_BAT_REMOVE_IRQ); + params |= check_params(option, CHARGE_START_INT, AXP2101_BAT_CHG_START_IRQ); + params |= check_params(option, CHARGE_DONE_INT, AXP2101_BAT_CHG_DONE_IRQ); + params |= check_params(option, PWR_BTN_CLICK_INT, AXP2101_PKEY_SHORT_IRQ); + params |= check_params(option, PWR_BTN_LONGPRESSED_INT, AXP2101_PKEY_LONG_IRQ); + params |= check_params(option, ALL_INT, AXP2101_ALL_IRQ); + return enable ? enableIRQ(params) : disableIRQ(params); +#else + return false; +#endif + } + + protected: + uint32_t __protectedMask = 0; + }; +} // namespace HAL::PMIC \ No newline at end of file diff --git a/lib/HAL/PMIC/PMIC.h b/lib/HAL/PMIC/PMIC.h new file mode 100644 index 000000000..18cce64bd --- /dev/null +++ b/lib/HAL/PMIC/PMIC.h @@ -0,0 +1,21 @@ +#ifndef __PMIC__ +#define __PMIC__ + +#ifdef PMIC_AXP192 + #include "DRIVER/AXP192.tpp" + typedef class HAL::PMIC::AXP192 PMIC; +#elif defined(PMIC_AXP202) + #include "DRIVER/AXP202.tpp" + typedef class HAL::PMIC::AXP202 PMIC; +#elif defined(PMIC_AXP2101) + #include "DRIVER/AXP2101.tpp" + typedef class HAL::PMIC::AXP2101 PMIC; +#elif defined(PMIC_BQ25896) + #include "DRIVER/BQ25896.tpp" + typedef class HAL::PMIC::BQ25896 PMIC; +#elif defined(PMIC_SY6970) + #include "DRIVER/SY6970.tpp" + typedef class HAL::PMIC::SY6970 PMIC; +#endif + +#endif /* __PMIC__ */ diff --git a/lib/HAL/PMIC/PMIC.hpp b/lib/HAL/PMIC/PMIC.hpp new file mode 100644 index 000000000..efa4e509b --- /dev/null +++ b/lib/HAL/PMIC/PMIC.hpp @@ -0,0 +1,17 @@ +#ifndef __PMIC_HPP__ +#define __PMIC_HPP__ +namespace HAL::PMIC +{ + enum PMICChipModel + { + AXP173, + AXP192, + AXP202, + AXP216, + AXP2101, + BQ25896, + SY6970, + UNDEFINED, + }; +} // namespace HAL::PMIC +#endif /* __PMIC_HPP__ */ diff --git a/lib/HAL/PMIC/PMIC.tpp b/lib/HAL/PMIC/PMIC.tpp new file mode 100644 index 000000000..95782fafd --- /dev/null +++ b/lib/HAL/PMIC/PMIC.tpp @@ -0,0 +1,88 @@ +#include "BUS/I2C/I2C_Device.tpp" +#include "PMIC.hpp" + +#include +#include +#define PMICLIB_I2C_MASTER_SPEED 400000 + +#define ATTR_NOT_IMPLEMENTED __attribute__((error("Not implemented"))) +#define IS_BIT_SET(val, mask) (((val) & (mask)) == (mask)) + +namespace HAL::PMIC +{ + using namespace HAL::BUS; + template + class Base : public I2C_Device + { + friend class I2C_Device; + + public: + Base() : myModel(UNDEFINED) {}; + virtual uint8_t getChipID() = 0; + virtual bool init() = 0; + virtual void deinit() = 0; + virtual void shutdown() = 0; + virtual uint8_t getBatteryPercent() { return -1; } + virtual uint16_t getBattVoltage() { return 0; } + virtual bool isBatteryConnect() { return false; } + virtual bool isVbusIn() { return false; } + virtual bool isCharging() { return false; } + virtual uint16_t getSystemVoltage() = 0; + virtual uint16_t getVbusVoltage() = 0; + virtual bool setSysPowerDownVoltage(uint16_t millivolt) = 0; + virtual uint16_t getSysPowerDownVoltage() = 0; + + bool begin(TwoWire &w, uint8_t addr, int sda, int scl) + { + if (started) + return thisChip().initImpl(); + started = true; + this->mySDA = sda; + this->mySCL = scl; + this->myWire = &w; + this->myWire->begin(this->mySDA, this->mySCL); + this->myADDR = addr; + return thisChip().initImpl(); + } + + PMICChipModel getChipModel() { return myModel; } + + /* + * CRTP Helper + */ + protected: + bool begin() + { + if (started) + return thisChip().initImpl(); + started = true; + if (this->myWire) + { + log_i("SDA:%d SCL:%d", this->mySDA, this->mySCL); + this->myWire->begin(this->mySDA, this->mySCL); + } + return thisChip().initImpl(); + } + + void end() + { + this->myWire->end(); + } + + inline const Driver &thisChip() const + { + return static_cast(*this); + } + + inline Driver &thisChip() + { + return static_cast(*this); + } + + void setChipModel(PMICChipModel m) { setChipModel(m); } + + protected: + bool started = false; + PMICChipModel myModel = UNDEFINED; + }; +} // namespace HAL::PMIC \ No newline at end of file diff --git a/lib/HAL/PMIC/REG/AXP173.hpp b/lib/HAL/PMIC/REG/AXP173.hpp new file mode 100644 index 000000000..4ab902b28 --- /dev/null +++ b/lib/HAL/PMIC/REG/AXP173.hpp @@ -0,0 +1,5 @@ +#ifndef __AXP173__ +#define __AXP173__ + + +#endif /* __AXP173__ */ diff --git a/lib/HAL/PMIC/REG/AXP192.hpp b/lib/HAL/PMIC/REG/AXP192.hpp new file mode 100644 index 000000000..7bcb5a5fd --- /dev/null +++ b/lib/HAL/PMIC/REG/AXP192.hpp @@ -0,0 +1,384 @@ +#ifndef __AXP192__ +#define __AXP192__ +#include + +#define AXP192_SLAVE_ADDRESS (0x34) + +#define AXP192_CHIP_ID (0x03) + +#define AXP192_STATUS (0x00) +#define AXP192_MODE_CHGSTATUS (0x01) +#define AXP192_OTG_STATUS (0x02) +#define AXP192_IC_TYPE (0x03) + +#define AXP192_DATA_BUFFER1 (0x06) +#define AXP192_DATA_BUFFER2 (0x07) +#define AXP192_DATA_BUFFER3 (0x08) +#define AXP192_DATA_BUFFER4 (0x09) +#define AXP192_DATA_BUFFER5 (0x0A) +#define AXP192_DATA_BUFFER6 (0x0B) +#define AXP192_DATA_BUFFER_SIZE (6) + +#define AXP192_LDO23_DC123_EXT_CTL (0x12) +#define AXP192_DC2OUT_VOL (0x23) +#define AXP192_DC2_DVM (0x25) +#define AXP192_DC3OUT_VOL (0x27) +#define AXP192_LDO24OUT_VOL (0x28) +#define AXP192_LDO3OUT_VOL (0x29) +#define AXP192_IPS_SET (0x30) +#define AXP192_VOFF_SET (0x31) +#define AXP192_OFF_CTL (0x32) +#define AXP192_CHARGE1 (0x33) +#define AXP192_CHARGE2 (0x34) +#define AXP192_BACKUP_CHG (0x35) +#define AXP192_POK_SET (0x36) +#define AXP192_DCDC_FREQSET (0x37) +#define AXP192_VLTF_CHGSET (0x38) +#define AXP192_VHTF_CHGSET (0x39) +#define AXP192_APS_WARNING1 (0x3A) +#define AXP192_APS_WARNING2 (0x3B) +#define AXP192_TLTF_DISCHGSET (0x3C) +#define AXP192_THTF_DISCHGSET (0x3D) +#define AXP192_DCDC_MODESET (0x80) +#define AXP192_ADC_EN1 (0x82) +#define AXP192_ADC_EN2 (0x83) +#define AXP192_ADC_SPEED (0x84) +#define AXP192_ADC_INPUTRANGE (0x85) +#define AXP192_ADC_IRQ_RETFSET (0x86) +#define AXP192_ADC_IRQ_FETFSET (0x87) +#define AXP192_TIMER_CTL (0x8A) +#define AXP192_VBUS_DET_SRP (0x8B) +#define AXP192_HOTOVER_CTL (0x8F) + +#define AXP192_PWM1_FREQ_SET (0x98) +#define AXP192_PWM1_DUTY_SET1 (0x99) +#define AXP192_PWM1_DUTY_SET2 (0x9A) + +#define AXP192_PWM2_FREQ_SET (0x9B) +#define AXP192_PWM2_DUTY_SET1 (0x9C) +#define AXP192_PWM2_DUTY_SET2 (0x9D) + +// INTERRUPT REGISTER +#define AXP192_INTEN1 (0x40) +#define AXP192_INTEN2 (0x41) +#define AXP192_INTEN3 (0x42) +#define AXP192_INTEN4 (0x43) +#define AXP192_INTEN5 (0x4A) + +// INTERRUPT STATUS REGISTER +#define AXP192_INTSTS1 (0x44) +#define AXP192_INTSTS2 (0x45) +#define AXP192_INTSTS3 (0x46) +#define AXP192_INTSTS4 (0x47) +#define AXP192_INTSTS5 (0x4D) +#define AXP192_INTSTS_CNT (5) + +#define AXP192_DC1_VLOTAGE (0x26) +#define AXP192_LDO23OUT_VOL (0x28) +#define AXP192_GPIO0_CTL (0x90) +#define AXP192_GPIO0_VOL (0x91) +#define AXP192_GPIO1_CTL (0X92) +#define AXP192_GPIO2_CTL (0x93) +#define AXP192_GPIO012_SIGNAL (0x94) +#define AXP192_GPIO34_CTL (0x95) +#define AXP192_GPIO34_SIGNAL (0x96) +#define AXP192_GPIO012_PULLDOWN (0x97) +#define AXP192_GPIO5_CTL (0x9E) +#define AXP192_GPIO_CNT (6) + +#define AXP192_GPIO0_VOL_ADC_H8 (0x64) +#define AXP192_GPIO0_VOL_ADC_L4 (0x65) +#define AXP192_GPIO1_VOL_ADC_H8 (0x66) +#define AXP192_GPIO1_VOL_ADC_L4 (0x67) +#define AXP192_GPIO2_VOL_ADC_H8 (0x68) +#define AXP192_GPIO2_VOL_ADC_L4 (0x69) +#define AXP192_GPIO3_VOL_ADC_H8 (0x6A) +#define AXP192_GPIO3_VOL_ADC_L4 (0x6B) + +#define AXP192_GPIO0_STEP (0.5F) +#define AXP192_GPIO1_STEP (0.5F) +#define AXP192_TS_IN_H8 (0x62) +#define AXP192_TS_IN_L4 (0x63) + +#define AXP192_ACIN_VOL_H8 (0x56) +#define AXP192_ACIN_VOL_L4 (0x57) +#define AXP192_ACIN_CUR_H8 (0x58) +#define AXP192_ACIN_CUR_L4 (0x59) +#define AXP192_VBUS_VOL_H8 (0x5A) +#define AXP192_VBUS_VOL_L4 (0x5B) +#define AXP192_VBUS_CUR_H8 (0x5C) +#define AXP192_VBUS_CUR_L4 (0x5D) + +#define AXP192_BAT_AVERCHGCUR_H8 (0x7A) +#define AXP192_BAT_AVERCHGCUR_L5 (0x7B) +#define AXP192_BAT_AVERDISCHGCUR_H8 (0x7C) +#define AXP192_BAT_AVERDISCHGCUR_L5 (0x7D) +#define AXP192_APS_AVERVOL_H8 (0x7E) +#define AXP192_APS_AVERVOL_L4 (0x7F) +#define AXP192_BAT_AVERVOL_H8 (0x78) +#define AXP192_BAT_AVERVOL_L4 (0x79) + +#define AXP192_BAT_CHGCOULOMB3 (0xB0) +#define AXP192_BAT_CHGCOULOMB2 (0xB1) +#define AXP192_BAT_CHGCOULOMB1 (0xB2) +#define AXP192_BAT_CHGCOULOMB0 (0xB3) +#define AXP192_BAT_DISCHGCOULOMB3 (0xB4) +#define AXP192_BAT_DISCHGCOULOMB2 (0xB5) +#define AXP192_BAT_DISCHGCOULOMB1 (0xB6) +#define AXP192_BAT_DISCHGCOULOMB0 (0xB7) +#define AXP192_COULOMB_CTL (0xB8) + +#define AXP192_BATT_VOLTAGE_STEP (1.1F) +#define AXP192_BATT_DISCHARGE_CUR_STEP (0.5F) +#define AXP192_BATT_CHARGE_CUR_STEP (0.5F) +#define AXP192_ACIN_VOLTAGE_STEP (1.7F) +#define AXP192_ACIN_CUR_STEP (0.625F) +#define AXP192_VBUS_VOLTAGE_STEP (1.7F) +#define AXP192_VBUS_CUR_STEP (0.375F) +#define AXP192_APS_VOLTAGE_STEP (1.4F) +#define AXP192_TS_PIN_OUT_STEP (0.8F) + +#define AXP192_LDO2_VOL_MIN (1800u) +#define AXP192_LDO2_VOL_MAX (3300u) +#define AXP192_LDO2_VOL_STEPS (100u) +#define AXP192_LDO2_VOL_BIT_MASK (4u) + +#define AXP192_LDO3_VOL_MIN (1800u) +#define AXP192_LDO3_VOL_MAX (3300u) +#define AXP192_LDO3_VOL_STEPS (100u) + +#define AXP192_DC1_VOL_STEPS (25u) +#define AXP192_DC1_VOL_MIN (700u) +#define AXP192_DC1_VOL_MAX (3500u) + +#define AXP192_DC2_VOL_STEPS (25u) +#define AXP192_DC2_VOL_MIN (700u) +#define AXP192_DC2_VOL_MAX (3500u) + +#define AXP192_DC3_VOL_STEPS (25u) +#define AXP192_DC3_VOL_MIN (700u) +#define AXP192_DC3_VOL_MAX (3500u) + +#define AXP192_LDOIO_VOL_STEPS (100) +#define AXP192_LDOIO_VOL_MIN (1800) +#define AXP192_LDOIO_VOL_MAX (3300) + +#define AXP192_SYS_VOL_STEPS (100) +#define AXP192_VOFF_VOL_MIN (2600) +#define AXP192_VOFF_VOL_MAX (3300) + +#define AXP192_CHG_EXT_CURR_MIN (300) +#define AXP192_CHG_EXT_CURR_MAX (1000) +#define AXP192_CHG_EXT_CURR_STEP (100) + +#define AXP192_INTERNAL_TEMP_H8 (0x5E) +#define AXP192_INTERNAL_TEMP_L4 (0x5F) +#define AXP192_INTERNAL_TEMP_STEP (0.1F) +#define AXP192_INERNAL_TEMP_OFFSET (144.7) + +enum pmic_boot_time : uint8_t +{ + AXP192_BOOT_TIME_128MS, + AXP192_BOOT_TIME_512MS, + AXP192_BOOT_TIME_1S, + AXP192_BOOT_TIME_2S, +}; + +enum pmic_chg_iterm : uint8_t +{ + AXP192_CHG_ITERM_LESS_10_PERCENT, + AXP192_CHG_ITERM_LESS_15_PERCENT, +}; + +enum pmic_prechg_to : uint8_t +{ + AXP192_PRECHG_TIMEOUT_30MIN, + AXP192_PRECHG_TIMEOUT_40MIN, + AXP192_PRECHG_TIMEOUT_50MIN, + AXP192_PRECHG_TIMEOUT_60MIN, +}; + +enum pmic_pekey_poweroff_arg : uint8_t +{ + AXP192_POWEROFF_4S, + AXP192_POWEROFF_65, + AXP192_POWEROFF_8S, + AXP192_POWEROFF_10S, +}; + +enum pmic_pekey_long_press : uint8_t +{ + AXP192_LONGPRESS_1000MS, + AXP192_LONGPRESS_1500MS, + AXP192_LONGPRESS_2000MS, + AXP192_LONGPRESS_2500MS, +}; + +enum pmic_chg_cons_to : uint8_t +{ + AXP192_CHG_CONS_TIMEOUT_7H, + AXP192_CHG_CONS_TIMEOUT_8H, + AXP192_CHG_CONS_TIMEOUT_9H, + AXP192_CHG_CONS_TIMEOUT_10H, +}; + +enum pmic_backup_batt_vol : uint8_t +{ + AXP192_BACKUP_BAT_VOL_3V1, + AXP192_BACKUP_BAT_VOL_3V, + AXP192_BACKUP_BAT_VOL_3V0, //! NEED FIX,DATASHEET ERROR! + AXP192_BACKUP_BAT_VOL_2V5, +}; + +enum pmic_backup_batt_curr : uint8_t +{ + AXP192_BACKUP_BAT_CUR_50UA, + AXP192_BACKUP_BAT_CUR_100UA, + AXP192_BACKUP_BAT_CUR_200UA, + AXP192_BACKUP_BAT_CUR_400UA, +}; + +struct pmic_gpio +{ + uint8_t mode; +}; + +/** + * @brief axp192 charge target voltage parameters. + */ +enum pmic_chg_vol +{ + AXP192_CHG_VOL_4V1, + AXP192_CHG_VOL_4V15, + AXP192_CHG_VOL_4V2, + AXP192_CHG_VOL_4V36, + AXP192_CHG_VOL_MAX, +}; + +/** + * @brief axp192 charge currnet voltage parameters. + */ +enum pmic_chg_curr +{ + AXP192_CHG_CUR_100MA, + AXP192_CHG_CUR_190MA, + AXP192_CHG_CUR_280MA, + AXP192_CHG_CUR_360MA, + AXP192_CHG_CUR_450MA, + AXP192_CHG_CUR_550MA, + AXP192_CHG_CUR_630MA, + AXP192_CHG_CUR_700MA, + AXP192_CHG_CUR_780MA, + AXP192_CHG_CUR_880MA, + AXP192_CHG_CUR_960MA, + AXP192_CHG_CUR_1000MA, + AXP192_CHG_CUR_1080MA, + AXP192_CHG_CUR_1160MA, + AXP192_CHG_CUR_1240MA, + AXP192_CHG_CUR_1320MA, +}; + +/** + * @brief axp192 vbus currnet limit parameters. + */ +enum pmic_vbus_cur_limit : uint8_t +{ + AXP192_VBUS_CUR_LIM_500MA, + AXP192_VBUS_CUR_LIM_100MA, + AXP192_VBUS_CUR_LIM_OFF, +}; +enum pmic_vbus_vol_limit +{ + AXP192_VBUS_VOL_LIM_4V, + AXP192_VBUS_VOL_LIM_4V1, + AXP192_VBUS_VOL_LIM_4V2, + AXP192_VBUS_VOL_LIM_4V3, + AXP192_VBUS_VOL_LIM_4V4, + AXP192_VBUS_VOL_LIM_4V5, + AXP192_VBUS_VOL_LIM_4V6, + AXP192_VBUS_VOL_LIM_4V7, +}; + +enum pmic_irq +{ + //! IRQ1 REG 40H + AXP192_VBUS_VHOLD_LOW_IRQ = _BV(1), // VBUS is available, but lower than V HOLD, IRQ enable + AXP192_VBUS_REMOVE_IRQ = _BV(2), // VBUS removed, IRQ enable + AXP192_VBUS_INSERT_IRQ = _BV(3), // VBUS connected, IRQ enable + AXP192_VBUS_OVER_VOL_IRQ = _BV(4), // VBUS over-voltage, IRQ enable + AXP192_ACIN_REMOVED_IRQ = _BV(5), // ACIN removed, IRQ enable + AXP192_ACIN_CONNECT_IRQ = _BV(6), // ACIN connected, IRQ enable + AXP192_ACIN_OVER_VOL_IRQ = _BV(7), // ACIN over-voltage, IRQ enable + + //! IRQ2 REG 41H + AXP192_BATT_LOW_TEMP_IRQ = _BV(8), // Battery low-temperature, IRQ enable + AXP192_BATT_OVER_TEMP_IRQ = _BV(9), // Battery over-temperature, IRQ enable + AXP192_BAT_CHG_DONE_IRQ = _BV(10), // Charge finished, IRQ enable + AXP192_BAT_CHG_START_IRQ = _BV(11), // Be charging, IRQ enable + AXP192_BATT_EXIT_ACTIVATE_IRQ = _BV(12), // Exit battery activate mode, IRQ enable + AXP192_BATT_ACTIVATE_IRQ = _BV(13), // Battery activate mode, IRQ enable + AXP192_BAT_REMOVE_IRQ = _BV(14), // Battery removed, IRQ enable + AXP192_BAT_INSERT_IRQ = _BV(15), // Battery connected, IRQ enable + + //! IRQ3 REG 42H + AXP192_PKEY_LONG_IRQ = _BV(16), // PEK long press, IRQ enable + AXP192_PKEY_SHORT_IRQ = _BV(17), // PEK short press, IRQ enable + //**Reserved and unchangeable BIT 2 + AXP192_DC3_LOW_VOL_IRQ = _BV(19), // DC-DC3output voltage is lower than the set value, IRQ enable + AXP192_DC2_LOW_VOL_IRQ = _BV(20), // DC-DC2 output voltage is lower than the set value, IRQ enable + AXP192_DC1_LOW_VOL_IRQ = _BV(21), // DC-DC1 output voltage is lower than the set value, IRQ enable + AXP192_CHARGE_LOW_CUR_IRQ = _BV(22), // Charge current is lower than the set current, IRQ enable + AXP192_CHIP_TEMP_HIGH_IRQ = _BV(23), // PMIC internal over-temperature, IRQ enable + + //! IRQ4 REG 43H + AXP192_APS_LOW_VOL_LEVEL_IRQ = _BV(24), // APS low-voltage, IRQ enable + //**Reserved and unchangeable BIT 1 + AXP192_VBUS_SESSION_END_IRQ = _BV(26), // VBUS Session End IRQ enable + AXP192_VBUS_SESSION_AB_IRQ = _BV(27), // VBUS Session A/B IRQ enable + AXP192_VBUS_INVALID_IRQ = _BV(28), // VBUS invalid, IRQ enable + AXP192_VBUS_VAILD_IRQ = _BV(29), // VBUS valid, IRQ enable + AXP192_NOE_OFF_IRQ = _BV(30), // N_OE shutdown, IRQ enable + AXP192_NOE_ON_IRQ = _BV(31), // N_OE startup, IRQ enable + + //! IRQ5 REG 4AH + AXP192_GPIO0_EDGE_TRIGGER_IRQ = _BV(32), // GPIO0 input edge trigger, IRQ enable + AXP192_GPIO1_EDGE_TRIGGER_IRQ = _BV(33), // GPIO1input edge trigger or ADC input, IRQ enable + AXP192_GPIO2_EDGE_TRIGGER_IRQ = _BV(34), // GPIO2input edge trigger, IRQ enable + //**Reserved and unchangeable BIT 3 + //**Reserved and unchangeable BIT 4 + //**Reserved and unchangeable BIT 5 + //**Reserved and unchangeable BIT 6 + AXP192_TIMER_TIMEOUT_IRQ = _BV(39), // Timer timeout, IRQ enable + + AXP192_ALL_IRQ = (0xFFFFFFFFFFULL) +}; + +enum pmic_num +{ + PMU_GPIO0, + PMU_GPIO1, + PMU_GPIO2, + PMU_GPIO3, + PMU_GPIO4, + PMU_GPIO5, + PMU_TS_PIN +}; + +enum pmic_adc_func +{ + MONITOR_TS_PIN = _BV(0), + MONITOR_APS_VOLTAGE = _BV(1), + MONITOR_USB_CURRENT = _BV(2), + MONITOR_USB_VOLTAGE = _BV(3), + MONITOR_AC_CURRENT = _BV(4), + MONITOR_AC_VOLTAGE = _BV(5), + MONITOR_BAT_CURRENT = _BV(6), + MONITOR_BAT_VOLTAGE = _BV(7), + MONITOR_ADC_IO3 = _BV(8), + MONITOR_ADC_IO2 = _BV(9), + MONITOR_ADC_IO1 = _BV(10), + MONITOR_ADC_IO0 = _BV(11), + MONITOR_TEMPERATURE = _BV(16), +}; + +#endif /* __AXP192__ */ diff --git a/lib/HAL/PMIC/REG/AXP202.hpp b/lib/HAL/PMIC/REG/AXP202.hpp new file mode 100644 index 000000000..5c6ffcb07 --- /dev/null +++ b/lib/HAL/PMIC/REG/AXP202.hpp @@ -0,0 +1,360 @@ +#ifndef __AXP202__ +#define __AXP202__ +#include + +#define AXP202_SLAVE_ADDRESS (0x35) + +#define AXP202_CHIP_ID (0x41) + +#define AXP202_STATUS (0x00) +#define AXP202_MODE_CHGSTATUS (0x01) +#define AXP202_OTG_STATUS (0x02) +#define AXP202_IC_TYPE (0x03) + +#define AXP202_DATA_BUFFER1 (0x04) +#define AXP202_DATA_BUFFER2 (0x05) +#define AXP202_DATA_BUFFER3 (0x06) +#define AXP202_DATA_BUFFER4 (0x07) +#define AXP202_DATA_BUFFER5 (0x08) +#define AXP202_DATA_BUFFER6 (0x09) +#define AXP202_DATA_BUFFER7 (0x0A) +#define AXP202_DATA_BUFFER8 (0x0B) +#define AXP202_DATA_BUFFER9 (0x0C) +#define AXP202_DATA_BUFFERA (0x0D) +#define AXP202_DATA_BUFFERB (0x0E) +#define AXP202_DATA_BUFFERC (0x0F) + +#define AXP202_LDO234_DC23_CTL (0x12) +#define AXP202_DC2OUT_VOL (0x23) +#define AXP202_LDO3_DC2_DVM (0x25) +#define AXP202_DC3OUT_VOL (0x27) +#define AXP202_LDO24OUT_VOL (0x28) +#define AXP202_LDO3OUT_VOL (0x29) +#define AXP202_IPS_SET (0x30) +#define AXP202_VOFF_SET (0x31) +#define AXP202_OFF_CTL (0x32) +#define AXP202_CHARGE1 (0x33) +#define AXP202_CHARGE2 (0x34) +#define AXP202_BACKUP_CHG (0x35) +#define AXP202_POK_SET (0x36) +#define AXP202_DCDC_FREQSET (0x37) +#define AXP202_VLTF_CHGSET (0x38) +#define AXP202_VHTF_CHGSET (0x39) +#define AXP202_APS_WARNING1 (0x3A) +#define AXP202_APS_WARNING2 (0x3B) +#define AXP202_TLTF_DISCHGSET (0x3C) +#define AXP202_THTF_DISCHGSET (0x3D) +#define AXP202_DCDC_MODESET (0x80) +#define AXP202_ADC_EN1 (0x82) +#define AXP202_ADC_EN2 (0x83) +#define AXP202_ADC_SPEED (0x84) +#define AXP202_ADC_INPUTRANGE (0x85) +#define AXP202_ADC_IRQ_RETFSET (0x86) +#define AXP202_ADC_IRQ_FETFSET (0x87) +#define AXP202_TIMER_CTL (0x8A) +#define AXP202_VBUS_DET_SRP (0x8B) +#define AXP202_HOTOVER_CTL (0x8F) + +#define AXP202_DATA_BUFFER_SIZE (12) +#define AXP202_GPIO0_CTL (0x90) +#define AXP202_GPIO0_VOL (0x91) +#define AXP202_GPIO1_CTL (0x92) +#define AXP202_GPIO2_CTL (0x93) +#define AXP202_GPIO012_SIGNAL (0x94) +#define AXP202_GPIO3_CTL (0x95) + +// INTERRUPT REGISTER +#define AXP202_INTEN1 (0x40) +#define AXP202_INTEN2 (0x41) +#define AXP202_INTEN3 (0x42) +#define AXP202_INTEN4 (0x43) +#define AXP202_INTEN5 (0x44) + +// INTERRUPT STATUS REGISTER +#define AXP202_INTSTS1 (0x48) +#define AXP202_INTSTS2 (0x49) +#define AXP202_INTSTS3 (0x4A) +#define AXP202_INTSTS4 (0x4B) +#define AXP202_INTSTS5 (0x4C) +#define AXP202_INTSTS_CNT (5) + +// AXP ADC DATA REGISTER +#define AXP202_GPIO0_VOL_ADC_H8 (0x64) +#define AXP202_GPIO0_VOL_ADC_L4 (0x65) +#define AXP202_GPIO1_VOL_ADC_H8 (0x66) +#define AXP202_GPIO1_VOL_ADC_L4 (0x67) + +#define AXP202_GPIO0_STEP (0.5F) +#define AXP202_GPIO1_STEP (0.5F) + +#define AXP202_BAT_AVERVOL_H8 (0x78) +#define AXP202_BAT_AVERVOL_L4 (0x79) + +#define AXP202_BAT_AVERCHGCUR_H8 (0x7A) +#define AXP202_BAT_AVERCHGCUR_L4 (0x7B) + +#define AXP202_BAT_AVERCHGCUR_L5 (0x7B) +#define AXP202_ACIN_VOL_H8 (0x56) +#define AXP202_ACIN_VOL_L4 (0x57) +#define AXP202_ACIN_CUR_H8 (0x58) +#define AXP202_ACIN_CUR_L4 (0x59) +#define AXP202_VBUS_VOL_H8 (0x5A) +#define AXP202_VBUS_VOL_L4 (0x5B) +#define AXP202_VBUS_CUR_H8 (0x5C) +#define AXP202_VBUS_CUR_L4 (0x5D) +#define AXP202_INTERNAL_TEMP_H8 (0x5E) +#define AXP202_INTERNAL_TEMP_L4 (0x5F) +#define AXP202_TS_IN_H8 (0x62) +#define AXP202_TS_IN_L4 (0x63) +#define AXP202_GPIO0_VOL_ADC_H8 (0x64) +#define AXP202_GPIO0_VOL_ADC_L4 (0x65) +#define AXP202_GPIO1_VOL_ADC_H8 (0x66) +#define AXP202_GPIO1_VOL_ADC_L4 (0x67) + +#define AXP202_BAT_AVERDISCHGCUR_H8 (0x7C) +#define AXP202_BAT_AVERDISCHGCUR_L5 (0x7D) +#define AXP202_APS_AVERVOL_H8 (0x7E) +#define AXP202_APS_AVERVOL_L4 (0x7F) +#define AXP202_INT_BAT_CHGCUR_H8 (0xA0) +#define AXP202_INT_BAT_CHGCUR_L4 (0xA1) +#define AXP202_EXT_BAT_CHGCUR_H8 (0xA2) +#define AXP202_EXT_BAT_CHGCUR_L4 (0xA3) +#define AXP202_INT_BAT_DISCHGCUR_H8 (0xA4) +#define AXP202_INT_BAT_DISCHGCUR_L4 (0xA5) +#define AXP202_EXT_BAT_DISCHGCUR_H8 (0xA6) +#define AXP202_EXT_BAT_DISCHGCUR_L4 (0xA7) +#define AXP202_BAT_CHGCOULOMB3 (0xB0) +#define AXP202_BAT_CHGCOULOMB2 (0xB1) +#define AXP202_BAT_CHGCOULOMB1 (0xB2) +#define AXP202_BAT_CHGCOULOMB0 (0xB3) +#define AXP202_BAT_DISCHGCOULOMB3 (0xB4) +#define AXP202_BAT_DISCHGCOULOMB2 (0xB5) +#define AXP202_BAT_DISCHGCOULOMB1 (0xB6) +#define AXP202_BAT_DISCHGCOULOMB0 (0xB7) +#define AXP202_COULOMB_CTL (0xB8) +#define AXP202_BATT_PERCENTAGE (0xB9) + +#define AXP202_BAT_POWERH8 (0x70) +#define AXP202_BAT_POWERM8 (0x71) +#define AXP202_BAT_POWERL8 (0x72) + +#define AXP202_BATT_VOLTAGE_STEP (1.1F) +#define AXP202_BATT_DISCHARGE_CUR_STEP (0.5F) +#define AXP202_BATT_CHARGE_CUR_STEP (0.5F) +#define AXP202_ACIN_VOLTAGE_STEP (1.7F) +#define AXP202_ACIN_CUR_STEP (0.625F) +#define AXP202_VBUS_VOLTAGE_STEP (1.7F) +#define AXP202_VBUS_CUR_STEP (0.375F) +#define AXP202_INTERNAL_TEMP_STEP (0.1F) +#define AXP202_APS_VOLTAGE_STEP (1.4F) +#define AXP202_TS_PIN_OUT_STEP (0.8F) + +#define AXP202_LDO2_VOL_MIN (1800u) +#define AXP202_LDO2_VOL_MAX (3300u) +#define AXP202_LDO2_VOL_STEPS (100u) +#define AXP202_LDO2_VOL_BIT_MASK (4u) + +#define AXP202_LDO3_VOL_MIN (1800u) +#define AXP202_LDO3_VOL_MAX (3300u) +#define AXP202_LDO3_VOL_STEPS (100u) + +#define AXP202_DC2_VOL_STEPS (25u) +#define AXP202_DC2_VOL_MIN (700u) +#define AXP202_DC2_VOL_MAX (3500u) + +#define AXP202_DC3_VOL_STEPS (25u) +#define AXP202_DC3_VOL_MIN (700u) +#define AXP202_DC3_VOL_MAX (3500u) + +#define AXP202_LDOIO_VOL_STEPS (100) +#define AXP202_LDOIO_VOL_MIN (1800) +#define AXP202_LDOIO_VOL_MAX (3300) + +#define AXP202_SYS_VOL_STEPS (100) +#define AXP202_VOFF_VOL_MIN (2600) +#define AXP202_VOFF_VOL_MAX (3300) + +#define AXP202_CHG_EXT_CURR_MIN (300) +#define AXP202_CHG_EXT_CURR_MAX (1000) +#define AXP202_CHG_EXT_CURR_STEP (100) + +#define AXP202_INERNAL_TEMP_OFFSET (144.7) + +const enum pmic_boot_time +{ + AXP202_BOOT_TIME_128MS, + AXP202_BOOT_TIME_512MS, + AXP202_BOOT_TIME_1S, + AXP202_BOOT_TIME_2S, +}; + +enum pmic_chg_iterm +{ + AXP202_CHG_ITERM_LESS_10_PERCENT, + AXP202_CHG_ITERM_LESS_15_PERCENT, +}; + +const enum pmic_prechg_to +{ + AXP202_PRECHG_TIMEOUT_30MIN, + AXP202_PRECHG_TIMEOUT_40MIN, + AXP202_PRECHG_TIMEOUT_50MIN, + AXP202_PRECHG_TIMEOUT_60MIN, +}; + +const enum pmic_pekey_poweroff_arg +{ + AXP202_POWEROFF_4S, + AXP202_POWEROFF_65, + AXP202_POWEROFF_8S, + AXP202_POWEROFF_10S, +}; + +const enum pmic_pekey_long_press +{ + AXP202_LONGPRESS_1000MS, + AXP202_LONGPRESS_1500MS, + AXP202_LONGPRESS_2000MS, + AXP202_LONGPRESS_2500MS, +}; + +const enum pmic_chg_cons_to +{ + AXP202_CHG_CONS_TIMEOUT_7H, + AXP202_CHG_CONS_TIMEOUT_8H, + AXP202_CHG_CONS_TIMEOUT_9H, + AXP202_CHG_CONS_TIMEOUT_10H, +}; + +const enum pmic_backup_batt_vol +{ + AXP202_BACKUP_BAT_VOL_3V1, + AXP202_BACKUP_BAT_VOL_3V, + AXP202_BACKUP_BAT_VOL_3V0, //! NEED FIX,DATASHEET ERROR! + AXP202_BACKUP_BAT_VOL_2V5, +}; + +const enum pmic_backup_batt_curr +{ + AXP202_BACKUP_BAT_CUR_50UA, + AXP202_BACKUP_BAT_CUR_100UA, + AXP202_BACKUP_BAT_CUR_200UA, + AXP202_BACKUP_BAT_CUR_400UA, +}; + +/** + * @brief axp202 charge target voltage parameters. + */ +const enum pmic_chg_vol +{ + AXP202_CHG_VOL_4V1, + AXP202_CHG_VOL_4V15, + AXP202_CHG_VOL_4V2, + AXP202_CHG_VOL_4V36, + AXP202_CHG_VOL_MAX, +}; + +/** + * @brief axp202 charge currnet voltage parameters. + */ +const enum pmic_chg_curr +{ + AXP202_CHG_CUR_100MA, + AXP202_CHG_CUR_190MA, + AXP202_CHG_CUR_280MA, + AXP202_CHG_CUR_360MA, + AXP202_CHG_CUR_450MA, + AXP202_CHG_CUR_550MA, + AXP202_CHG_CUR_630MA, + AXP202_CHG_CUR_700MA, + AXP202_CHG_CUR_780MA, + AXP202_CHG_CUR_880MA, + AXP202_CHG_CUR_960MA, + AXP202_CHG_CUR_1000MA, + AXP202_CHG_CUR_1080MA, + AXP202_CHG_CUR_1160MA, + AXP202_CHG_CUR_1240MA, + AXP202_CHG_CUR_1320MA, +}; + +const enum pmic_vbus_vol_limit +{ + AXP202_VBUS_VOL_LIM_4V, + AXP202_VBUS_VOL_LIM_4V1, + AXP202_VBUS_VOL_LIM_4V2, + AXP202_VBUS_VOL_LIM_4V3, + AXP202_VBUS_VOL_LIM_4V4, + AXP202_VBUS_VOL_LIM_4V5, + AXP202_VBUS_VOL_LIM_4V6, + AXP202_VBUS_VOL_LIM_4V7, +}; + +/** + * @brief axp202 vbus currnet limit parameters. + */ +enum pmic_vbus_cur_limit : uint8_t +{ + AXP202_VBUS_CUR_LIM_900MA, + AXP202_VBUS_CUR_LIM_500MA, + AXP202_VBUS_CUR_LIM_100MA, + AXP202_VBUS_CUR_LIM_OFF, +}; + +/** + * @brief axp202 interrupt control mask parameters. + */ +enum pmic_irq +{ + //! IRQ1 REG 40H + AXP202_VBUS_VHOLD_LOW_IRQ = _BV(1), // VBUS is available, but lower than V HOLD, IRQ enable + AXP202_VBUS_REMOVE_IRQ = _BV(2), // VBUS removed, IRQ enable + AXP202_VBUS_INSERT_IRQ = _BV(3), // VBUS connected, IRQ enable + AXP202_VBUS_OVER_VOL_IRQ = _BV(4), // VBUS over-voltage, IRQ enable + AXP202_ACIN_REMOVED_IRQ = _BV(5), // ACIN removed, IRQ enable + AXP202_ACIN_CONNECT_IRQ = _BV(6), // ACIN connected, IRQ enable + AXP202_ACIN_OVER_VOL_IRQ = _BV(7), // ACIN over-voltage, IRQ enable + + //! IRQ2 REG 41H + AXP202_BATT_LOW_TEMP_IRQ = _BV(8), // Battery low-temperature, IRQ enable + AXP202_BATT_OVER_TEMP_IRQ = _BV(9), // Battery over-temperature, IRQ enable + AXP202_BAT_CHG_DONE_IRQ = _BV(10), // Charge finished, IRQ enable + AXP202_BAT_CHG_START_IRQ = _BV(11), // Be charging, IRQ enable + AXP202_BATT_EXIT_ACTIVATE_IRQ = _BV(12), // Exit battery activate mode, IRQ enable + AXP202_BATT_ACTIVATE_IRQ = _BV(13), // Battery activate mode, IRQ enable + AXP202_BAT_REMOVE_IRQ = _BV(14), // Battery removed, IRQ enable + AXP202_BAT_INSERT_IRQ = _BV(15), // Battery connected, IRQ enable + + //! IRQ3 REG 42H + AXP202_PKEY_LONG_IRQ = _BV(16), // PEK long press, IRQ enable + AXP202_PKEY_SHORT_IRQ = _BV(17), // PEK short press, IRQ enable + AXP202_LDO3_LOW_VOL_IRQ = _BV(18), // LDO3output voltage is lower than the set value, IRQ enable + AXP202_DC3_LOW_VOL_IRQ = _BV(19), // DC-DC3output voltage is lower than the set value, IRQ enable + AXP202_DC2_LOW_VOL_IRQ = _BV(20), // DC-DC2 output voltage is lower than the set value, IRQ enable + //**Reserved and unchangeable BIT 5 + AXP202_CHARGE_LOW_CUR_IRQ = _BV(22), // Charge current is lower than the set current, IRQ enable + AXP202_CHIP_TEMP_HIGH_IRQ = _BV(23), // AXP202 internal over-temperature, IRQ enable + + //! IRQ4 REG 43H + AXP202_APS_LOW_VOL_LEVEL2_IRQ = _BV(24), // APS low-voltage, IRQ enable(LEVEL2) + APX202_APS_LOW_VOL_LEVEL1_IRQ = _BV(25), // APS low-voltage, IRQ enable(LEVEL1) + AXP202_VBUS_SESSION_END_IRQ = _BV(26), // VBUS Session End IRQ enable + AXP202_VBUS_SESSION_AB_IRQ = _BV(27), // VBUS Session A/B IRQ enable + AXP202_VBUS_INVALID_IRQ = _BV(28), // VBUS invalid, IRQ enable + AXP202_VBUS_VAILD_IRQ = _BV(29), // VBUS valid, IRQ enable + AXP202_NOE_OFF_IRQ = _BV(30), // N_OE shutdown, IRQ enable + AXP202_NOE_ON_IRQ = _BV(31), // N_OE startup, IRQ enable + + //! IRQ5 REG 44H + AXP202_GPIO0_EDGE_TRIGGER_IRQ = _BV(32), // G PIO0 input edge trigger, IRQ enable + AXP202_GPIO1_EDGE_TRIGGER_IRQ = _BV(33), // GPIO1input edge trigger or ADC input, IRQ enable + AXP202_GPIO2_EDGE_TRIGGER_IRQ = _BV(34), // GPIO2input edge trigger, IRQ enable + AXP202_GPIO3_EDGE_TRIGGER_IRQ = _BV(35), // GPIO3 input edge trigger, IRQ enable + //**Reserved and unchangeable BIT 4 + AXP202_PKEY_NEGATIVE_IRQ = _BV(37), // PEK press falling edge, IRQ enable + AXP202_PKEY_POSITIVE_IRQ = _BV(38), // PEK press rising edge, IRQ enable + AXP202_TIMER_TIMEOUT_IRQ = _BV(39), // Timer timeout, IRQ enable + + AXP202_ALL_IRQ = (0xFFFFFFFFFFULL) +}; + +#endif /* __AXP202__ */ diff --git a/lib/HAL/PMIC/REG/AXP209.hpp b/lib/HAL/PMIC/REG/AXP209.hpp new file mode 100644 index 000000000..48322e835 --- /dev/null +++ b/lib/HAL/PMIC/REG/AXP209.hpp @@ -0,0 +1,5 @@ +#ifndef __AXP209__ +#define __AXP209__ + + +#endif /* __AXP209__ */ diff --git a/lib/HAL/PMIC/REG/AXP2101.hpp b/lib/HAL/PMIC/REG/AXP2101.hpp new file mode 100644 index 000000000..e265ff338 --- /dev/null +++ b/lib/HAL/PMIC/REG/AXP2101.hpp @@ -0,0 +1,490 @@ +#ifndef __AXP2101__ +#define __AXP2101__ +#include + +#define AXP2101_SLAVE_ADDRESS (0x34) + +#define AXP2101_CHIP_ID (0x4A) + +#define AXP2101_STATUS1 (0x00) +#define AXP2101_STATUS2 (0x01) +#define AXP2101_IC_TYPE (0x03) + +#define AXP2101_DATA_BUFFER1 (0x04) +#define AXP2101_DATA_BUFFER2 (0x05) +#define AXP2101_DATA_BUFFER3 (0x06) +#define AXP2101_DATA_BUFFER4 (0x07) +#define AXP2101_DATA_BUFFER_SIZE (4u) + +#define AXP2101_COMMON_CONFIG (0x10) +#define AXP2101_BATFET_CTRL (0x12) +#define AXP2101_DIE_TEMP_CTRL (0x13) +#define AXP2101_MIN_SYS_VOL_CTRL (0x14) +#define AXP2101_INPUT_VOL_LIMIT_CTRL (0x15) +#define AXP2101_INPUT_CUR_LIMIT_CTRL (0x16) +#define AXP2101_RESET_FUEL_GAUGE (0x17) +#define AXP2101_CHARGE_GAUGE_WDT_CTRL (0x18) + +#define AXP2101_WDT_CTRL (0x19) +#define AXP2101_LOW_BAT_WARN_SET (0x1A) + +#define AXP2101_PWRON_STATUS (0x20) +#define AXP2101_PWROFF_STATUS (0x21) +#define AXP2101_PWROFF_EN (0x22) +#define AXP2101_DC_OVP_UVP_CTRL (0x23) +#define AXP2101_VOFF_SET (0x24) +#define AXP2101_PWROK_SEQU_CTRL (0x25) +#define AXP2101_SLEEP_WAKEUP_CTRL (0x26) +#define AXP2101_IRQ_OFF_ON_LEVEL_CTRL (0x27) + +#define AXP2101_FAST_PWRON_SET0 (0x28) +#define AXP2101_FAST_PWRON_SET1 (0x29) +#define AXP2101_FAST_PWRON_SET2 (0x2A) +#define AXP2101_FAST_PWRON_CTRL (0x2B) + +#define AXP2101_ADC_CHANNEL_CTRL (0x30) +#define AXP2101_ADC_DATA_RELUST0 (0x34) +#define AXP2101_ADC_DATA_RELUST1 (0x35) +#define AXP2101_ADC_DATA_RELUST2 (0x36) +#define AXP2101_ADC_DATA_RELUST3 (0x37) +#define AXP2101_ADC_DATA_RELUST4 (0x38) +#define AXP2101_ADC_DATA_RELUST5 (0x39) +#define AXP2101_ADC_DATA_RELUST6 (0x3A) +#define AXP2101_ADC_DATA_RELUST7 (0x3B) +#define AXP2101_ADC_DATA_RELUST8 (0x3C) +#define AXP2101_ADC_DATA_RELUST9 (0x3D) + +// XPOWERS INTERRUPT REGISTER +#define AXP2101_INTEN1 (0x40) +#define AXP2101_INTEN2 (0x41) +#define AXP2101_INTEN3 (0x42) + +// XPOWERS INTERRUPT STATUS REGISTER +#define AXP2101_INTSTS1 (0x48) +#define AXP2101_INTSTS2 (0x49) +#define AXP2101_INTSTS3 (0x4A) +#define AXP2101_INTSTS_CNT (3) + +#define AXP2101_TS_PIN_CTRL (0x50) +#define AXP2101_TS_HYSL2H_SET (0x52) +#define AXP2101_TS_LYSL2H_SET (0x53) + +#define AXP2101_VLTF_CHG_SET (0x54) +#define AXP2101_VHLTF_CHG_SET (0x55) +#define AXP2101_VLTF_WORK_SET (0x56) +#define AXP2101_VHLTF_WORK_SET (0x57) + +#define AXP2101_JIETA_EN_CTRL (0x58) +#define AXP2101_JIETA_SET0 (0x59) +#define AXP2101_JIETA_SET1 (0x5A) +#define AXP2101_JIETA_SET2 (0x5B) + +#define AXP2101_IPRECHG_SET (0x61) +#define AXP2101_ICC_CHG_SET (0x62) +#define AXP2101_ITERM_CHG_SET_CTRL (0x63) + +#define AXP2101_CV_CHG_VOL_SET (0x64) + +#define AXP2101_THE_REGU_THRES_SET (0x65) +#define AXP2101_CHG_TIMEOUT_SET_CTRL (0x67) + +#define AXP2101_BAT_DET_CTRL (0x68) +#define AXP2101_CHGLED_SET_CTRL (0x69) + +#define AXP2101_BTN_VOL_MIN (2600) +#define AXP2101_BTN_VOL_MAX (3300) +#define AXP2101_BTN_VOL_STEPS (100) + +#define AXP2101_BTN_BAT_CHG_VOL_SET (0x6A) + +#define AXP2101_DC_ONOFF_DVM_CTRL (0x80) +#define AXP2101_DC_FORCE_PWM_CTRL (0x81) +#define AXP2101_DC_VOL0_CTRL (0x82) +#define AXP2101_DC_VOL1_CTRL (0x83) +#define AXP2101_DC_VOL2_CTRL (0x84) +#define AXP2101_DC_VOL3_CTRL (0x85) +#define AXP2101_DC_VOL4_CTRL (0x86) + +#define AXP2101_LDO_ONOFF_CTRL0 (0x90) +#define AXP2101_LDO_ONOFF_CTRL1 (0x91) +#define AXP2101_LDO_VOL0_CTRL (0x92) +#define AXP2101_LDO_VOL1_CTRL (0x93) +#define AXP2101_LDO_VOL2_CTRL (0x94) +#define AXP2101_LDO_VOL3_CTRL (0x95) +#define AXP2101_LDO_VOL4_CTRL (0x96) +#define AXP2101_LDO_VOL5_CTRL (0x97) +#define AXP2101_LDO_VOL6_CTRL (0x98) +#define AXP2101_LDO_VOL7_CTRL (0x99) +#define AXP2101_LDO_VOL8_CTRL (0x9A) + +#define AXP2101_BAT_PARAME (0xA1) +#define AXP2101_FUEL_GAUGE_CTRL (0xA2) +#define AXP2101_BAT_PERCENT_DATA (0xA4) + +// DCDC 1~5 +#define AXP2101_DCDC1_VOL_MIN (1500) +#define AXP2101_DCDC1_VOL_MAX (3400) +#define AXP2101_DCDC1_VOL_STEPS (100u) + +#define AXP2101_DCDC2_VOL1_MIN (500u) +#define AXP2101_DCDC2_VOL1_MAX (1200u) +#define AXP2101_DCDC2_VOL2_MIN (1220u) +#define AXP2101_DCDC2_VOL2_MAX (1540u) + +#define AXP2101_DCDC2_VOL_STEPS1 (10u) +#define AXP2101_DCDC2_VOL_STEPS2 (20u) + +#define AXP2101_DCDC2_VOL_STEPS1_BASE (0u) +#define AXP2101_DCDC2_VOL_STEPS2_BASE (71) + +#define AXP2101_DCDC3_VOL1_MIN (500u) +#define AXP2101_DCDC3_VOL1_MAX (1200u) +#define AXP2101_DCDC3_VOL2_MIN (1220u) +#define AXP2101_DCDC3_VOL2_MAX (1540u) +#define AXP2101_DCDC3_VOL3_MIN (1600u) +#define AXP2101_DCDC3_VOL3_MAX (3400u) + +#define AXP2101_DCDC3_VOL_MIN (500) +#define AXP2101_DCDC3_VOL_MAX (3400) + +#define AXP2101_DCDC3_VOL_STEPS1 (10u) +#define AXP2101_DCDC3_VOL_STEPS2 (20u) +#define AXP2101_DCDC3_VOL_STEPS3 (100u) + +#define AXP2101_DCDC3_VOL_STEPS1_BASE (0u) +#define AXP2101_DCDC3_VOL_STEPS2_BASE (71) +#define AXP2101_DCDC3_VOL_STEPS3_BASE (88) + +#define AXP2101_DCDC4_VOL1_MIN (500u) +#define AXP2101_DCDC4_VOL1_MAX (1200u) +#define AXP2101_DCDC4_VOL2_MIN (1220u) +#define AXP2101_DCDC4_VOL2_MAX (1840u) + +#define AXP2101_DCDC4_VOL_STEPS1 (10u) +#define AXP2101_DCDC4_VOL_STEPS2 (20u) + +#define AXP2101_DCDC4_VOL_STEPS1_BASE (0u) +#define AXP2101_DCDC4_VOL_STEPS2_BASE (71) + +#define AXP2101_DCDC5_VOL_1200MV (1200) +#define AXP2101_DCDC5_VOL_VAL (0x19) +#define AXP2101_DCDC5_VOL_MIN (1400) +#define AXP2101_DCDC5_VOL_MAX (3700) +#define AXP2101_DCDC5_VOL_STEPS (100u) + +#define AXP2101_VSYS_VOL_THRESHOLD_MIN (2600) +#define AXP2101_VSYS_VOL_THRESHOLD_MAX (3300) +#define AXP2101_VSYS_VOL_THRESHOLD_STEPS (100) + +// ALDO 1~4 + +#define AXP2101_ALDO1_VOL_MIN (500) +#define AXP2101_ALDO1_VOL_MAX (3500) +#define AXP2101_ALDO1_VOL_STEPS (100u) + +#define AXP2101_ALDO2_VOL_MIN (500) +#define AXP2101_ALDO2_VOL_MAX (3500) +#define AXP2101_ALDO2_VOL_STEPS (100u) + +#define AXP2101_ALDO3_VOL_MIN (500) +#define AXP2101_ALDO3_VOL_MAX (3500) +#define AXP2101_ALDO3_VOL_STEPS (100u) + +#define AXP2101_ALDO4_VOL_MIN (500) +#define AXP2101_ALDO4_VOL_MAX (3500) +#define AXP2101_ALDO4_VOL_STEPS (100u) + +// BLDO 1~2 + +#define AXP2101_BLDO1_VOL_MIN (500) +#define AXP2101_BLDO1_VOL_MAX (3500) +#define AXP2101_BLDO1_VOL_STEPS (100u) + +#define AXP2101_BLDO2_VOL_MIN (500) +#define AXP2101_BLDO2_VOL_MAX (3500) +#define AXP2101_BLDO2_VOL_STEPS (100u) + +// CPUSLDO + +#define AXP2101_CPUSLDO_VOL_MIN (500) +#define AXP2101_CPUSLDO_VOL_MAX (1400) +#define AXP2101_CPUSLDO_VOL_STEPS (50) + +// DLDO 1~2 +#define AXP2101_DLDO1_VOL_MIN (500) +#define AXP2101_DLDO1_VOL_MAX (3400) +#define AXP2101_DLDO1_VOL_STEPS (100u) + +#define AXP2101_DLDO2_VOL_MIN (500) +#define AXP2101_DLDO2_VOL_MAX (3400) +#define AXP2101_DLDO2_VOL_STEPS (100u) + +#define AXP2101_CONVERSION(raw) (22.0 + (7274 - raw) / 20.0) + +enum pmic_chg_vol : uint8_t +{ + AXP2101_CHG_VOL_4V = 1, + AXP2101_CHG_VOL_4V1, + AXP2101_CHG_VOL_4V2, + AXP2101_CHG_VOL_4V35, + AXP2101_CHG_VOL_4V4, + AXP2101_CHG_VOL_MAX +}; + +enum pmic_irq_time : uint8_t +{ + AXP2101_IRQ_TIME_1S, + AXP2101_IRQ_TIME_1S5, + AXP2101_IRQ_TIME_2S, + AXP2101_PRESSOFF_2S5, +}; + +enum pmic_prechg +{ + AXP2101_PRECHARGE_0MA, + AXP2101_PRECHARGE_25MA, + AXP2101_PRECHARGE_50MA, + AXP2101_PRECHARGE_75MA, + AXP2101_PRECHARGE_100MA, + AXP2101_PRECHARGE_125MA, + AXP2101_PRECHARGE_150MA, + AXP2101_PRECHARGE_175MA, + AXP2101_PRECHARGE_200MA, +}; + +enum pmic_chg_iterm : uint8_t +{ + AXP2101_CHG_ITERM_0MA, + AXP2101_CHG_ITERM_25MA, + AXP2101_CHG_ITERM_50MA, + AXP2101_CHG_ITERM_75MA, + AXP2101_CHG_ITERM_100MA, + AXP2101_CHG_ITERM_125MA, + AXP2101_CHG_ITERM_150MA, + AXP2101_CHG_ITERM_175MA, + AXP2101_CHG_ITERM_200MA, +}; + +enum pmic_vbus_cur_limit : uint8_t +{ + AXP2101_VBUS_CUR_LIM_100MA, + AXP2101_VBUS_CUR_LIM_500MA, + AXP2101_VBUS_CUR_LIM_900MA, + AXP2101_VBUS_CUR_LIM_1000MA, + AXP2101_VBUS_CUR_LIM_1500MA, + AXP2101_VBUS_CUR_LIM_2000MA, +}; + +enum pmic_sys_vol_min +{ + AXP2101_SYS_VOL_MIN_4V1, + AXP2101_SYS_VOL_MIN_4V2, + AXP2101_SYS_VOL_MIN_4V3, + AXP2101_SYS_VOL_MIN_4V4, + AXP2101_SYS_VOL_MIN_4V5, + AXP2101_SYS_VOL_MIN_4V6, + AXP2101_SYS_VOL_MIN_4V7, // Default + AXP2101_SYS_VOL_MIN_4V8, +}; + +enum pmic_vbus_vol_limit +{ + AXP2101_VBUS_VOL_LIM_3V88, + AXP2101_VBUS_VOL_LIM_3V96, + AXP2101_VBUS_VOL_LIM_4V04, + AXP2101_VBUS_VOL_LIM_4V12, + AXP2101_VBUS_VOL_LIM_4V20, + AXP2101_VBUS_VOL_LIM_4V28, + AXP2101_VBUS_VOL_LIM_4V36, + AXP2101_VBUS_VOL_LIM_4V44, + AXP2101_VBUS_VOL_LIM_4V52, + AXP2101_VBUS_VOL_LIM_4V60, + AXP2101_VBUS_VOL_LIM_4V68, + AXP2101_VBUS_VOL_LIM_4V76, + AXP2101_VBUS_VOL_LIM_4V84, + AXP2101_VBUS_VOL_LIM_4V92, + AXP2101_VBUS_VOL_LIM_5V, + AXP2101_VBUS_VOL_LIM_5V08, +}; + +enum pmic_thermal : uint8_t +{ + AXP2101_THREMAL_60DEG, + AXP2101_THREMAL_80DEG, + AXP2101_THREMAL_100DEG, + AXP2101_THREMAL_120DEG, +}; + +enum pmic_chg_status +{ + AXP2101_CHG_TRI_STATE, // tri_charge + AXP2101_CHG_PRE_STATE, // pre_charge + AXP2101_CHG_CC_STATE, // constant charge + AXP2101_CHG_CV_STATE, // constant voltage + AXP2101_CHG_DONE_STATE, // charge done + AXP2101_CHG_STOP_STATE, // not charge +}; + +enum pmic_wakeup +{ + AXP2101_WAKEUP_IRQ_PIN_TO_LOW = _BV(4), + AXP2101_WAKEUP_PWROK_TO_LOW = _BV(3), + AXP2101_WAKEUP_DC_DLO_SELECT = _BV(2), +}; + +enum pmic_fast_on_opt +{ + AXP2101_FAST_DCDC1, + AXP2101_FAST_DCDC2, + AXP2101_FAST_DCDC3, + AXP2101_FAST_DCDC4, + AXP2101_FAST_DCDC5, + AXP2101_FAST_ALDO1, + AXP2101_FAST_ALDO2, + AXP2101_FAST_ALDO3, + AXP2101_FAST_ALDO4, + AXP2101_FAST_BLDO1, + AXP2101_FAST_BLDO2, + AXP2101_FAST_CPUSLDO, + AXP2101_FAST_DLDO1, + AXP2101_FAST_DLDO2, +}; + +enum pmic_start_sequence : uint8_t +{ + AXP2101_SEQUENCE_LEVEL_0, + AXP2101_SEQUENCE_LEVEL_1, + AXP2101_SEQUENCE_LEVEL_2, + AXP2101_SEQUENCE_DISABLE, +}; + +enum pmic_wdt_config : uint8_t +{ + AXP2101_WDT_IRQ_TO_PIN, // Just interrupt to pin + AXP2101_WDT_IRQ_AND_RSET, // IRQ to pin and reset pmu system + AXP2101_WDT_IRQ_AND_RSET_PD_PWROK, // IRQ to pin and reset pmu system,pull down pwrok + AXP2101_WDT_IRQ_AND_RSET_ALL_OFF, // IRQ to pin and reset pmu system,turn off dcdc & ldo ,pull down pwrok +}; + +enum pmic_wdt_timeout : uint8_t +{ + AXP2101_WDT_TIMEOUT_1S, + AXP2101_WDT_TIMEOUT_2S, + AXP2101_WDT_TIMEOUT_4S, + AXP2101_WDT_TIMEOUT_8S, + AXP2101_WDT_TIMEOUT_16S, + AXP2101_WDT_TIMEOUT_32S, + AXP2101_WDT_TIMEOUT_64S, + AXP2101_WDT_TIMEOUT_128S, +}; + +enum pmic_chg_dpm +{ + AXP2101_VSYS_VOL_4V1, + AXP2101_VSYS_VOL_4V2, + AXP2101_VSYS_VOL_4V3, + AXP2101_VSYS_VOL_4V4, + AXP2101_VSYS_VOL_4V5, + AXP2101_VSYS_VOL_4V6, + AXP2101_VSYS_VOL_4V7, + AXP2101_VSYS_VOL_4V8, +}; + +enum pmic_power_on_source +{ + AXP2101_POWERON_SRC_POWERON_LOW, // POWERON low for on level when POWERON Mode as POWERON Source + AXP2101_POWERON_SRC_IRQ_LOW, // IRQ PIN Pull-down as POWERON Source + AXP2101_POWERON_SRC_VBUS_INSERT, // Vbus Insert and Good as POWERON Source + AXP2101_POWERON_SRC_BAT_CHARGE, // Vbus Insert and Good as POWERON Source + AXP2101_POWERON_SRC_BAT_INSERT, // Battery Insert and Good as POWERON Source + AXP2101_POWERON_SRC_ENMODE, // POWERON always high when EN Mode as POWERON Source + AXP2101_POWERON_SRC_UNKONW, // Unkonw +}; + +enum pmic_power_off_source +{ + AXP2101_POWEROFF_SRC_PWEKEY_PULLDOWN, // POWERON Pull down for off level when POWERON Mode as POWEROFF Source + AXP2101_POWEROFF_SRC_SOFT_OFF, // Software configuration as POWEROFF Source + AXP2101_POWEROFF_SRC_PWEKEY_LOW, // POWERON always low when EN Mode as POWEROFF Source + AXP2101_POWEROFF_SRC_UNDER_VSYS, // Vsys Under Voltage as POWEROFF Source + AXP2101_POWEROFF_SRC_OVER_VBUS, // VBUS Over Voltage as POWEROFF Source + AXP2101_POWEROFF_SRC_UNDER_VOL, // DCDC Under Voltage as POWEROFF Source + AXP2101_POWEROFF_SRC_OVER_VOL, // DCDC Over Voltage as POWEROFF Source + AXP2101_POWEROFF_SRC_OVER_TEMP, // Die Over Temperature as POWEROFF Source + AXP2101_POWEROFF_SRC_UNKONW, // Unkonw +}; + +enum pmic_pwrok_delay : uint8_t +{ + AXP2101_PWROK_DELAY_8MS, + AXP2101_PWROK_DELAY_16MS, + AXP2101_PWROK_DELAY_32MS, + AXP2101_PWROK_DELAY_64MS, +}; + +/** + * @brief axp2101 charge currnet voltage parameters. + */ +enum pmic_chg_curr +{ + AXP2101_CHG_CUR_0MA, + AXP2101_CHG_CUR_100MA = 4, + AXP2101_CHG_CUR_125MA, + AXP2101_CHG_CUR_150MA, + AXP2101_CHG_CUR_175MA, + AXP2101_CHG_CUR_200MA, + AXP2101_CHG_CUR_300MA, + AXP2101_CHG_CUR_400MA, + AXP2101_CHG_CUR_500MA, + AXP2101_CHG_CUR_600MA, + AXP2101_CHG_CUR_700MA, + AXP2101_CHG_CUR_800MA, + AXP2101_CHG_CUR_900MA, + AXP2101_CHG_CUR_1000MA, +}; + +enum DVMRamp : uint8_t +{ + AXP2101_DVM_RAMP_15_625US, + AXP2101_DVM_RAMP_31_250US, +}; + +/** + * @brief axp2101 interrupt control mask parameters. + */ +enum pmic_irq : uint_fast64_t +{ + //! IRQ1 REG 40H + AXP2101_BAT_NOR_UNDER_TEMP_IRQ = _BV(0), // Battery Under Temperature in Work + AXP2101_BAT_NOR_OVER_TEMP_IRQ = _BV(1), // Battery Over Temperature in Work mode + AXP2101_BAT_CHG_UNDER_TEMP_IRQ = _BV(2), // Battery Under Temperature in Charge mode IRQ(bcut_irq) + AXP2101_BAT_CHG_OVER_TEMP_IRQ = _BV(3), // Battery Over Temperature in Charge mode IRQ(bcot_irq) enable + AXP2101_GAUGE_NEW_SOC_IRQ = _BV(4), // Gauge New SOC IRQ(lowsoc_irq) enable ??? + AXP2101_WDT_TIMEOUT_IRQ = _BV(5), // Gauge Watchdog Timeout IRQ(gwdt_irq) enable + AXP2101_WARNING_LEVEL1_IRQ = _BV(6), // SOC drop to Warning Level1 IRQ(socwl1_irq) enable + AXP2101_WARNING_LEVEL2_IRQ = _BV(7), // SOC drop to Warning Level2 IRQ(socwl2_irq) enable + + //! IRQ2 REG 41H + AXP2101_PKEY_POSITIVE_IRQ = _BV(8), // POWERON Positive Edge IRQ(ponpe_irq_en) enable + AXP2101_PKEY_NEGATIVE_IRQ = _BV(9), // POWERON Negative Edge IRQ(ponne_irq_en) enable + AXP2101_PKEY_LONG_IRQ = _BV(10), // POWERON Long PRESS IRQ(ponlp_irq) enable + AXP2101_PKEY_SHORT_IRQ = _BV(11), // POWERON Short PRESS IRQ(ponsp_irq_en) enable + AXP2101_BAT_REMOVE_IRQ = _BV(12), // Battery Remove IRQ(bremove_irq) enable + AXP2101_BAT_INSERT_IRQ = _BV(13), // Battery Insert IRQ(binsert_irq) enabl + AXP2101_VBUS_REMOVE_IRQ = _BV(14), // VBUS Remove IRQ(vremove_irq) enabl + AXP2101_VBUS_INSERT_IRQ = _BV(15), // VBUS Insert IRQ(vinsert_irq) enable + + //! IRQ3 REG 42H + AXP2101_BAT_OVER_VOL_IRQ = _BV(16), // Battery Over Voltage Protection IRQ(bovp_irq) enable + AXP2101_CHAGER_TIMER_IRQ = _BV(17), // Charger Safety Timer1/2 expire IRQ(chgte_irq) enable + AXP2101_DIE_OVER_TEMP_IRQ = _BV(18), // DIE Over Temperature level1 IRQ(dotl1_irq) enable + AXP2101_BAT_CHG_START_IRQ = _BV(19), // Charger start IRQ(chgst_irq) enable + AXP2101_BAT_CHG_DONE_IRQ = _BV(20), // Battery charge done IRQ(chgdn_irq) enable + AXP2101_BATFET_OVER_CURR_IRQ = _BV(21), // BATFET Over Current Protection IRQ(bocp_irq) enable + AXP2101_LDO_OVER_CURR_IRQ = _BV(22), // LDO Over Current IRQ(ldooc_irq) enable + AXP2101_WDT_EXPIRE_IRQ = _BV(23), // Watchdog Expire IRQ(wdexp_irq) enable + + AXP2101_ALL_IRQ = (0xFFFFFFFFUL) +}; + +#endif /* __AXP2101__ */ diff --git a/lib/HAL/PMIC/REG/AXP216.hpp b/lib/HAL/PMIC/REG/AXP216.hpp new file mode 100644 index 000000000..cea023010 --- /dev/null +++ b/lib/HAL/PMIC/REG/AXP216.hpp @@ -0,0 +1,100 @@ +#ifndef __AXP216__ +#define __AXP216__ +#include + +#define AXP216_SLAVE_ADDRESS (0x34) + +#define AXP216_CHIP_ID (0x41) + +//CONTROL REGISTER +#define AXP216_STATUS (0x00) +#define AXP216_MODE_CHGSTATUS (0x01) +#define AXP216_DATA_BUFFER1 (0x04) +#define AXP216_DATA_BUFFER2 (0x05) +#define AXP216_DATA_BUFFER3 (0x06) +#define AXP216_DATA_BUFFER4 (0x07) +#define AXP216_DATA_BUFFER5 (0x08) +#define AXP216_DATA_BUFFER6 (0x09) +#define AXP216_DATA_BUFFER7 (0x0A) +#define AXP216_DATA_BUFFER8 (0x0B) +#define AXP216_DATA_BUFFER9 (0x0C) +#define AXP216_DATA_BUFFERA (0x0D) +#define AXP216_DATA_BUFFERB (0x0E) +#define AXP216_DATA_BUFFERC (0x0F) + +#define AXP216_IC_TYPE (0x03) + +#define AXP216_DC12345_ALDO12_CTL (0x10) +#define AXP216_LDO123_CTL (0x12) +#define AXP216_OUTPUT_CTL (0x13) +#define AXP216_ELDO1_VCTL (0x19) +#define AXP216_ELDO2_VCTL (0x1A) +#define AXP216_DCDC1_VCTL (0x21) +#define AXP216_DCDC2_VCTL (0x22) +#define AXP216_DCDC3_VCTL (0x23) + +#define AXP216_DCDC4_VCTL (0x24) +#define AXP216_DCDC5_VCTL (0x25) +#define AXP216_DCDC23_VOLX (0x27) +#define AXP216_ALDO1_VCTL (0x28) +#define AXP216_ALDO2_VCTL (0x29) +#define AXP216_ALDO3_VCTL (0x2A) +#define AXP216_VBUS_IPSOUT (0x30) +#define AXP216_VOFF_SET (0x31) +#define AXP216_OFF_CTL (0x32) +#define AXP216_CHARGE1 (0x33) +#define AXP216_CHARGE2 (0x34) +#define AXP216_CHARGE3 (0x35) +#define AXP216_PEK_SET (0x36) +#define AXP216_OFFLEVEL (0x37) +#define AXP216_VLTF_CHGSET (0x38) +#define AXP216_VHTF_CHGSET (0x39) +#define AXP216_DCDC_FREQ (0x3B) +#define AXP216_TLTF_DISCHGSET (0x3C) +#define AXP216_THTF_DISCHGSET (0x3D) +#define AXP216_DCDC_MODESET (0x80) +#define AXP216_ADC_CTL (0x82) +#define AXP216_ADC_SPEED (0x84) +#define AXP216_TS_ADC (0x85) +#define AXP216_TIMER_CTL (0x8A) +#define AXP216_HOTOVER_CTL (0x8F) + +//GPIO REGISTER +#define AXP216_GPIO1_CTL (0x92) +#define AXP216_GPIO1_LDO_CTL (0x93) +#define AXP216_GPIO01_STATUS (0x94) +#define AXP216_GPIO1_PULLDOWN_CTL (0x97) + +//XPOWERS INTERRUPT REGISTER +#define AXP216_INTEN1 (0x40) +#define AXP216_INTEN2 (0x41) +#define AXP216_INTEN3 (0x42) +#define AXP216_INTEN4 (0x43) +#define AXP216_INTEN5 (0x44) + +//XPOWERS INTERRUPT STATUS REGISTER +#define AXP216_INTSTS1 (0x48) +#define AXP216_INTSTS2 (0x49) +#define AXP216_INTSTS3 (0x4A) +#define AXP216_INTSTS4 (0x4B) +#define AXP216_INTSTS5 (0x4C) + +//XPOWERS ADC DATA REGISTER +#define AXP216_INTERNAL_TEMP_H8 (0x56) +#define AXP216_INTERNAL_TEMP_L4 (0x57) +#define AXP216_TS_IN_H8 (0x58) +#define AXP216_TS_IN_L4 (0x59) +#define AXP216_BAT_VOLTAGE_H8 (0x78) +#define AXP216_BAT_VOLTAGE_L4 (0x79) +#define AXP216_BAT_CHGCURCUR_H8 (0x7A) +#define AXP216_BAT_CHGCURCUR_L4 (0x7B) +#define AXP216_BAT_DISCHGCUR_H8 (0x7C) +#define AXP216_BAT_DISCHGCUR_L4 (0x7D) +#define AXP216_FUEL_GAUGE_CTRL (0xB8) +#define AXP216_FUEL_GAUGE_REULST (0xB9) +#define AXP216_BAT_CAPACITY_0 (0xE0) +#define AXP216_BAT_CAPACITY_1 (0xE1) +#define AXP216_BAT_LOW_WARNING_CTRL (0xE6) + + +#endif /* __AXP216__ */ diff --git a/lib/HAL/PMIC/REG/AXP223.hpp b/lib/HAL/PMIC/REG/AXP223.hpp new file mode 100644 index 000000000..742b2e021 --- /dev/null +++ b/lib/HAL/PMIC/REG/AXP223.hpp @@ -0,0 +1,5 @@ +#ifndef __AXP223__ +#define __AXP223__ + + +#endif /* __AXP223__ */ diff --git a/lib/HAL/PMIC/REG/BQ25896.hpp b/lib/HAL/PMIC/REG/BQ25896.hpp new file mode 100644 index 000000000..7bbd66f8a --- /dev/null +++ b/lib/HAL/PMIC/REG/BQ25896.hpp @@ -0,0 +1,397 @@ +#ifndef __BQ25896__ +#define __BQ25896__ + +#define BQ25896_SLAVE_ADDRESS (0x6B) + +#define BQ25896_DEV_REV (0x02) + +#define BQ25896_VBUS_MASK_VAL(val) (val & 0x7F) +#define BQ25896_VBAT_MASK_VAL(val) (val & 0x7F) +#define BQ25896_VSYS_MASK_VAL(val) (val & 0x7F) +#define BQ25896_NTC_MASK_VAL(val) (val & 0x7F) + +#define BQ25896_VBUS_BASE_VAL (2600) +#define BQ25896_VBAT_BASE_VAL (2304) +#define BQ25896_VSYS_BASE_VAL (2304) +#define BQ25896_NTC_BASE_VAL (21) + +#define BQ25896_VBUS_VOL_STEP (100) +#define BQ25896_VBAT_VOL_STEP (20) +#define BQ25896_VSYS_VOL_STEP (20) +#define BQ25896_NTC_VOL_STEP (0.465) + +#define BQ25896_CHG_STEP_VAL (50) +#define BQ25896_FAST_CHG_CUR_STEP (64) +#define BQ25896_FAST_CHG_CURRENT_MIN (0) +#define BQ25896_FAST_CHG_CURRENT_MAX (3008) + +#define BQ25896_PRE_CHG_CUR_BASE (64) +#define BQ25896_PRE_CHG_CUR_STEP (64) +#define BQ25896_PRE_CHG_CURRENT_MIN (64) +#define BQ25896_PRE_CHG_CURRENT_MAX (1024) + +#define BQ25896_TERM_CHG_CUR_BASE (64) +#define BQ25896_TERM_CHG_CUR_STEP (64) +#define BQ25896_TERM_CHG_CURRENT_MIN (64) +#define BQ25896_TERM_CHG_CURRENT_MAX (1024) + +#define BQ25896_CHG_VOL_BASE (3840) +#define BQ25896_CHG_VOL_STEP (16) +#define BQ25896_FAST_CHG_VOL_MIN (3840) +#define BQ25896_FAST_CHG_VOL_MAX (4608) + +#define BQ25896_SYS_VOL_STEPS (100) +#define BQ25896_SYS_VOFF_VOL_MIN (3000) +#define BQ25896_SYS_VOFF_VOL_MAX (3700) + +#define BQ25896_IN_CURRENT_STEP (50) +#define BQ25896_IN_CURRENT_MIN (100) +#define BQ25896_IN_CURRENT_MAX (3250) + +#define BQ25896_IN_CURRENT_OPT_STEP (50) +#define BQ25896_IN_CURRENT_OPT_MIN (100) +#define BQ25896_IN_CURRENT_OPT_MAX (3250) + +#define BQ25896_IN_CURRENT_OFFSET_STEP (100) +#define BQ25896_IN_CURRENT_OFFSET_MAX (3100) + +#define BQ25896_BOOTS_VOL_BASE (4550) +#define BQ25896_BOOTS_VOL_STEP (64) +#define BQ25896_BOOST_VOL_MIN (4550) +#define BQ25896_BOOST_VOL_MAX (5510) + +#define BQ25896_VINDPM_VOL_BASE (4550) +#define BQ25896_VINDPM_VOL_STEPS (100) +#define BQ25896_VINDPM_VOL_MIN (3900) +#define BQ25896_VINDPM_VOL_MAX (15300) + +#define BQ25896_BAT_COMP_STEPS (20) +#define BQ25896_BAT_COMP_MAX (140) + +#define BQ25896_VCLAMP_STEPS (32) +#define BQ25896_VCLAMP_MAX (224) + +namespace HAL::PMIC +{ + #pragma region REG03 + //////////// + // REG 03 // + ////////////////// + // REG 03 ENUMS // + ////////////////// + enum REG03_00 : uint8_t + { + MINI_VOLT_2V9, + MINI_VOLT_2V5, + }; + typedef REG03_00 ExitBoostModeVolt; + // END REG 03 ENUMS + // REG 03 UNIONS + union REG03 + { + struct bits + { + REG03_00 MIN_VBAT_SEL : 1; + uint8_t SYS_MIN : 3; + bool CHG_CONFIG : 1; + bool OTG_CONFIG : 1; + bool WD_RST : 1; + bool BAT_LOADEN : 1; + }; + uint8_t reg; + }; + //////////////// + // END REG 03 // + //////////////// + #pragma endregion + + #pragma region REG06 + //////////// + // REG 06 // + ////////////////// + // REG 06 ENUMS // + ////////////////// + enum REG06_11 + { + FAST_CHG_THR_2V8, + FAST_CHG_THR_3V0 + }; + typedef REG06_11 FastChargeThreshold; + enum REG06_00 : uint8_t + { + RECHARGE_OFFSET_100MV, + RECHARGE_OFFSET_200MV + }; + typedef REG06_00 RechargeThresholdOffset; + // END REG 06 ENUMS + // REG 06 UNION + union REG06 + { + struct bits + { + REG06_00 VRECHG : 1; + REG06_11 BATLOWV : 1; + uint8_t VREG : 6; + }; + uint8_t reg; + }; + //////////////// + // END REG 06 // + //////////////// + #pragma endregion + + #pragma region REG07 + //////////// + // REG 07 // + ////////////////// + // REG 07 ENUMS // + ////////////////// + enum REG07_00 : uint8_t + { + JEITA_LOW_TEMP_50, // 50% of ICHG (REG04[6:0]) + JEITA_LOW_TEMP_20, // 20% of ICHG (REG04[6:0]) + }; + enum REG07_21 : uint8_t + { + FAST_CHARGE_TIMER_5H, + FAST_CHARGE_TIMER_8H, + FAST_CHARGE_TIMER_12H, + FAST_CHARGE_TIMER_20H, + }; + typedef REG07_21 FastChargeTimer; + enum REG07_54 : uint8_t + { + TIMER_OUT_OFF, + TIMER_OUT_40SEC, // 40 Second + TIMER_OUT_80SEC, // 80 Second + TIMER_OUT_160SEC, // 160 Second + }; + typedef REG07_54 Timeout; + // END REG 07 ENUMS + // REG 07 UNIONS + union REG07 + { + struct bits + { + REG07_00 JEITA_ISET : 1; + REG07_21 CHG_TIMER : 2; + bool EN_TIMER : 1; + REG07_54 WATCHDOG : 2; + bool STAT_DIS : 1; + bool EN_TERM : 1; + }; + uint8_t reg; + }; + //////////////// + // END REG 07 // + //////////////// + #pragma endregion + + #pragma region REG09 + //////////// + // REG 09 // + //////////// + union REG09 + { + struct bits + { + bool PUMPX_DN : 1; + bool PUMPX_UP : 1; + bool BATFET_RST_EN : 1; + bool BATFET_DLY : 1; + bool JEITA_VSET : 1; + bool BATFET_DIS : 1; + bool TMR2X_EN : 1; + bool FORCE_ICO : 1; + }; + uint8_t reg; + }; + //////////////// + // END REG 09 // + //////////////// + #pragma endregion + + #pragma region REG0A + //////////// + // REG 0A // + //////////// + enum REG0A_02 + { + BOOST_CUR_LIMIT_500MA, + BOOST_CUR_LIMIT_750MA, + BOOST_CUR_LIMIT_1200MA, + BOOST_CUR_LIMIT_1400MA, + BOOST_CUR_LIMIT_1650MA, + BOOST_CUR_LIMIT_1875MA, + BOOST_CUR_LIMIT_2150MA, + }; + typedef REG0A_02 BoostCurrentLimit; + // END REG 0A ENUMS + // REG 0A UNIONS + union REG0A + { + struct bits + { + REG0A_02 BOOST_LIM : 3; + bool PFM_OTG_DISABLE : 1; + uint8_t BOOSTV : 4; + }; + uint8_t reg; + }; + //////////////// + // END REG 0A // + //////////////// + #pragma endregion + + // + // REG 0B + // + enum REG0B_43 : uint8_t + { + CHARGE_STATE_NO_CHARGE, + CHARGE_STATE_PRE_CHARGE, + CHARGE_STATE_FAST_CHARGE, + CHARGE_STATE_DONE, + CHARGE_STATE_UNKOWN, + }; + typedef REG0B_43 ChargeStatus; + enum REG0B_75 : uint8_t + { + BUS_STATE_NOINPUT, + BUS_STATE_USB_SDP, + BUS_STATE_ADAPTER, + BUS_STATE_OTG = 7, + }; + typedef REG0B_75 BusStatus; + union REG0B + { + struct bits + { + bool VSYS_STAT : 1; + bool RESV : 1; + bool PG_STAT : 1; + REG0B_43 CHRG_STAT : 2; + REG0B_75 VBUS_STAT : 3; + } bits; + uint8_t reg; + }; + // END REG 0B + + // + // REG 0C + // + enum REG0C_20 : uint8_t + { + BUCK_NTC_NORMAL = 0, + BUCK_NTC_WARM = 2, + BUCK_NTC_COOL = 3, + BUCK_NTC_COLD = 5, + BUCK_NTC_HOT = 6, + }; + typedef REG0C_20 NTCStatus; + enum REG0C_54 : uint8_t + { + NORMAL, + INPUT_FAULT, + THERMAL_SHUTDOWN, + CG_SFTY_TMR_EXP, + }; + union REG0C + { + struct bits + { + REG0C_20 NTC : 3; + bool BAT : 1; + REG0C_54 CHRG : 2; + bool BOOST : 1; + bool WATCHDOG : 1; + } bits; + uint8_t reg; + }; + + // + // REG 0E + // + union REG0E + { + struct bits + { + uint8_t BATV : 7; + bool THERM_STAT : 1; + } bits; + uint8_t reg; + }; + // END REG 0E + + // + // REG 0F + // + union REG0F + { + struct bits + { + uint8_t SYSV : 7; + bool RESV : 1; + } bits; + uint8_t reg; + }; + // END REG 0F + + // + // REG 10 + // + union REG10 + { + struct bits + { + uint8_t TSPCT : 7; + bool RESV : 1; + } bits; + uint8_t reg; + }; + // END REG 10 + + // + // REG 11 + // + union REG11 + { + struct bits + { + uint8_t VBUSV : 7; + bool VBUS_GD : 1; + } bits; + uint8_t reg; + }; + // END REG 11 + + // + // REG 12 + // + union REG12 + { + struct bits + { + uint8_t ICHGR : 7; + bool RESV : 1; + } bits; + uint8_t reg; + }; + // END REG 12 + + // + // REG 13 + // + union REG13 + { + struct bits + { + uint8_t IDPM_LIM : 6; + bool IDPM_STAT : 1; + bool VDPM_STAT : 1; + } bits; + uint8_t reg; + }; + // END REG 13 +} // namespace HAL::PMIC +#endif /* __BQ25896__ */ diff --git a/lib/HAL/PMIC/REG/SY6970.hpp b/lib/HAL/PMIC/REG/SY6970.hpp new file mode 100644 index 000000000..27bc8e24f --- /dev/null +++ b/lib/HAL/PMIC/REG/SY6970.hpp @@ -0,0 +1,124 @@ +#ifndef __SY6970__ +#define __SY6970__ + +#define SY6970_SLAVE_ADDRESS (0x6A) +#define SY6970_DEV_REV (0x00) + +#define SY6970_VBUS_MASK_VAL(val) (val & 0x7F) +#define SY6970_VBAT_MASK_VAL(val) (val & 0x7F) +#define SY6970_VSYS_MASK_VAL(val) (val & 0x7F) +#define SY6970_NTC_MASK_VAL(val) (val & 0x7F) + +#define SY6970_VBUS_BASE_VAL (2600) +#define SY6970_VBAT_BASE_VAL (2304) +#define SY6970_VSYS_BASE_VAL (2304) +#define SY6970_NTC_BASE_VAL (21) + +#define SY6970_VBUS_VOL_STEP (100) +#define SY6970_VBAT_VOL_STEP (20) +#define SY6970_VSYS_VOL_STEP (20) +#define SY6970_NTC_VOL_STEP (0.465) +#define SY6970_CHG_STEP_VAL (50) + +#define SY6970_PRE_CHG_CUR_BASE (64) +#define SY6970_FAST_CHG_CUR_STEP (64) +#define SY6970_PRE_CHG_CUR_STEP (64) + +#define SY6970_FAST_CHG_CURRENT_MAX (5056) + +#define SY6970_PRE_CHG_CURRENT_MIN (64) +#define SY6970_PRE_CHG_CURRENT_MAX (1024) + +#define SY6970_CHG_VOL_BASE (3840) +#define SY6970_CHG_VOL_STEP (16) +#define SY6970_FAST_CHG_VOL_MIN (3840) +#define SY6970_FAST_CHG_VOL_MAX (4608) + +#define SY6970_SYS_VOL_STEPS (100) +#define SY6970_SYS_VOFF_VOL_MIN (3000) +#define SY6970_SYS_VOFF_VOL_MAX (3700) + +#define SY6970_IN_CURRENT_STEP (50) +#define SY6970_IN_CURRENT_MIN (100) +#define SY6970_IN_CURRENT_MAX (3250) + +#define SY6970_BOOTS_VOL_BASE (4550) +#define SY6970_BOOTS_VOL_STEP (64) +#define SY6970_BOOST_VOL_MIN (4550) +#define SY6970_BOOST_VOL_MAX (5510) + +#define SY6970_IRQ_WTD_FAULT(x) (bool)((x & 0xFF) >> 7) +#define SY6970_IRQ_BOOST_FAULT(x) (bool)((x & 0xFF) >> 6) +#define SY6970_IRQ_CHG_FAULT(x) (bool)((x & 0xFF) >> 5) +#define SY6970_IRQ_BAT_FAULT(x) (bool)((x & 0xFF) >> 4) +#define SY6970_IRQ_NTC_FAULT(x) (bool)((x & 0xFF) & 0x03) + +#define SY6970_VINDPM_VOL_BASE (4550) +#define SY6970_VINDPM_VOL_STEPS (100) +#define SY6970_VINDPM_VOL_MIN (3900) +#define SY6970_VINDPM_VOL_MAX (15300) + +enum BusStatus +{ + BUS_STATE_NOINPUT, + BUS_STATE_USB_SDP, + BUS_STATE_USB_CDP, + BUS_STATE_USB_DCP, + BUS_STATE_HVDCP, + BUS_STATE_ADAPTER, + BUS_STATE_NO_STANDARD_ADAPTER, + BUS_STATE_OTG +}; + +enum RequestRange +{ + REQUEST_9V, + REQUEST_12V, +}; + +enum BoostCurrentLimit +{ + BOOST_CUR_LIMIT_500MA, + BOOST_CUR_LIMIT_750MA, + BOOST_CUR_LIMIT_1200MA, + BOOST_CUR_LIMIT_1400MA, + BOOST_CUR_LIMIT_1650MA, + BOOST_CUR_LIMIT_1875MA, + BOOST_CUR_LIMIT_2150MA, + BOOST_CUR_LIMIT_2450MA, +}; + +enum Timeout +{ + TIMER_OUT_40SEC, // 40 Second + TIMER_OUT_80SEC, // 80 Second + TIMER_OUT_160SEC, // 160 Second +}; + +enum ChargeStatus +{ + CHARGE_STATE_NO_CHARGE, + CHARGE_STATE_PRE_CHARGE, + CHARGE_STATE_FAST_CHARGE, + CHARGE_STATE_DONE, + CHARGE_STATE_UNKOWN, +}; + +enum NTCStatus +{ + BUCK_NTC_NORMAL = 0, + BUCK_NTC_WARM = 2, + BUCK_NTC_COOL = 3, + BUCK_NTC_COLD = 5, + BUCK_NTC_HOT = 6, +}; + +enum FastChargeTimer +{ + FAST_CHARGE_TIMER_5H, + FAST_CHARGE_TIMER_8H, + FAST_CHARGE_TIMER_12H, + FAST_CHARGE_TIMER_20H, +}; + +#endif /* __SY6970__ */ diff --git a/lib/HAL/README b/lib/HAL/README new file mode 100644 index 000000000..e69de29bb diff --git a/lib/HAL/RF/REG/CC1101.hpp b/lib/HAL/RF/REG/CC1101.hpp new file mode 100644 index 000000000..637daab40 --- /dev/null +++ b/lib/HAL/RF/REG/CC1101.hpp @@ -0,0 +1,146 @@ +#ifndef __CC1101__ +#define __CC1101__ +#include + +// CC1101 CONFIG REGSITER +#define CC1101_IOCFG2 0x00 // GDO2 output pin configuration +#define CC1101_IOCFG1 0x01 // GDO1 output pin configuration +#define CC1101_IOCFG0 0x02 // GDO0 output pin configuration +#define CC1101_FIFOTHR 0x03 // RX FIFO and TX FIFO thresholds +#define CC1101_SYNC1 0x04 // Sync word, high INT8U +#define CC1101_SYNC0 0x05 // Sync word, low INT8U +#define CC1101_PKTLEN 0x06 // Packet length +#define CC1101_PKTCTRL1 0x07 // Packet automation control +#define CC1101_PKTCTRL0 0x08 // Packet automation control +#define CC1101_ADDR 0x09 // Device address +#define CC1101_CHANNR 0x0A // Channel number +#define CC1101_FSCTRL1 0x0B // Frequency synthesizer control +#define CC1101_FSCTRL0 0x0C // Frequency synthesizer control +#define CC1101_FREQ2 0x0D // Frequency control word, high INT8U +#define CC1101_FREQ1 0x0E // Frequency control word, middle INT8U +#define CC1101_FREQ0 0x0F // Frequency control word, low INT8U +#define CC1101_MDMCFG4 0x10 // Modem configuration +#define CC1101_MDMCFG3 0x11 // Modem configuration +#define CC1101_MDMCFG2 0x12 // Modem configuration +#define CC1101_MDMCFG1 0x13 // Modem configuration +#define CC1101_MDMCFG0 0x14 // Modem configuration +#define CC1101_DEVIATN 0x15 // Modem deviation setting +#define CC1101_MCSM2 0x16 // Main Radio Control State Machine configuration +#define CC1101_MCSM1 0x17 // Main Radio Control State Machine configuration +#define CC1101_MCSM0 0x18 // Main Radio Control State Machine configuration +#define CC1101_FOCCFG 0x19 // Frequency Offset Compensation configuration +#define CC1101_BSCFG 0x1A // Bit Synchronization configuration +#define CC1101_AGCCTRL2 0x1B // AGC control +#define CC1101_AGCCTRL1 0x1C // AGC control +#define CC1101_AGCCTRL0 0x1D // AGC control +#define CC1101_WOREVT1 0x1E // High INT8U Event 0 timeout +#define CC1101_WOREVT0 0x1F // Low INT8U Event 0 timeout +#define CC1101_WORCTRL 0x20 // Wake On Radio control +#define CC1101_FREND1 0x21 // Front end RX configuration +#define CC1101_FREND0 0x22 // Front end TX configuration +#define CC1101_FSCAL3 0x23 // Frequency synthesizer calibration +#define CC1101_FSCAL2 0x24 // Frequency synthesizer calibration +#define CC1101_FSCAL1 0x25 // Frequency synthesizer calibration +#define CC1101_FSCAL0 0x26 // Frequency synthesizer calibration +#define CC1101_RCCTRL1 0x27 // RC oscillator configuration +#define CC1101_RCCTRL0 0x28 // RC oscillator configuration +#define CC1101_FSTEST 0x29 // Frequency synthesizer calibration control +#define CC1101_PTEST 0x2A // Production test +#define CC1101_AGCTEST 0x2B // AGC test +#define CC1101_TEST2 0x2C // Various test settings +#define CC1101_TEST1 0x2D // Various test settings +#define CC1101_TEST0 0x2E // Various test settings + +enum class CC1101_REG : uint8_t { + IOCFG2 = 0x00, // GDO2 output pin configuration + IOCFG1 = 0x01, // GDO1 output pin configuration + IOCFG0 = 0x02, // GDO0 output pin configuration + FIFOTHR = 0x03, // RX FIFO and TX FIFO thresholds + SYNC1 = 0x04, // Sync word, high INT8U + SYNC0 = 0x05, // Sync word, low INT8U + PKTLEN = 0x06, // Packet length + PKTCTRL1 = 0x07, // Packet automation control + PKTCTRL0 = 0x08, // Packet automation control + ADDR = 0x09, // Device address + CHANNR = 0x0A, // Channel number + FSCTRL1 = 0x0B, // Frequency synthesizer control + FSCTRL0 = 0x0C, // Frequency synthesizer control + FREQ2 = 0x0D, // Frequency control word, high INT8U + FREQ1 = 0x0E, // Frequency control word, middle INT8U + FREQ0 = 0x0F, // Frequency control word, low INT8U + MDMCFG4 = 0x10, // Modem configuration + MDMCFG3 = 0x11, // Modem configuration + MDMCFG2 = 0x12, // Modem configuration + MDMCFG1 = 0x13, // Modem configuration + MDMCFG0 = 0x14, // Modem configuration + DEVIATN = 0x15, // Modem deviation setting + MCSM2 = 0x16, // Main Radio Control State Machine configuration + MCSM1 = 0x17, // Main Radio Control State Machine configuration + MCSM0 = 0x18, // Main Radio Control State Machine configuration + FOCCFG = 0x19, // Frequency Offset Compensation configuration + BSCFG = 0x1A, // Bit Synchronization configuration + AGCCTRL2 = 0x1B, // AGC control + AGCCTRL1 = 0x1C, // AGC control + AGCCTRL0 = 0x1D, // AGC control + WOREVT1 = 0x1E, // High INT8U Event 0 timeout + WOREVT0 = 0x1F, // Low INT8U Event 0 timeout + WORCTRL = 0x20, // Wake On Radio control + FREND1 = 0x21, // Front end RX configuration + FREND0 = 0x22, // Front end TX configuration + FSCAL3 = 0x23, // Frequency synthesizer calibration + FSCAL2 = 0x24, // Frequency synthesizer calibration + FSCAL1 = 0x25, // Frequency synthesizer calibration + FSCAL0 = 0x26, // Frequency synthesizer calibration + RCCTRL1 = 0x27, // RC oscillator configuration + RCCTRL0 = 0x28, // RC oscillator configuration + FSTEST = 0x29, // Frequency synthesizer calibration control + PTEST = 0x2A, // Production test + AGCTEST = 0x2B, // AGC test + TEST2 = 0x2C, // Various test settings + TEST1 = 0x2D, // Various test settings + TEST0 = 0x2E // Various test settings +}; + +//CC1101 Strobe commands +#define CC1101_SRES 0x30 // Reset chip. +#define CC1101_SFSTXON 0x31 // Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1). + // If in RX/TX: Go to a wait state where only the synthesizer is + // running (for quick RX / TX turnaround). +#define CC1101_SXOFF 0x32 // Turn off crystal oscillator. +#define CC1101_SCAL 0x33 // Calibrate frequency synthesizer and turn it off + // (enables quick start). +#define CC1101_SRX 0x34 // Enable RX. Perform calibration first if coming from IDLE and + // MCSM0.FS_AUTOCAL=1. +#define CC1101_STX 0x35 // In IDLE state: Enable TX. Perform calibration first if + // MCSM0.FS_AUTOCAL=1. If in RX state and CCA is enabled: + // Only go to TX if channel is clear. +#define CC1101_SIDLE 0x36 // Exit RX / TX, turn off frequency synthesizer and exit + // Wake-On-Radio mode if applicable. +#define CC1101_SAFC 0x37 // Perform AFC adjustment of the frequency synthesizer +#define CC1101_SWOR 0x38 // Start automatic RX polling sequence (Wake-on-Radio) +#define CC1101_SPWD 0x39 // Enter power down mode when CSn goes high. +#define CC1101_SFRX 0x3A // Flush the RX FIFO buffer. +#define CC1101_SFTX 0x3B // Flush the TX FIFO buffer. +#define CC1101_SWORRST 0x3C // Reset real time clock. +#define CC1101_SNOP 0x3D // No operation. May be used to pad strobe commands to two + // INT8Us for simpler software. +//CC1101 STATUS REGSITER +#define CC1101_PARTNUM 0x30 +#define CC1101_VERSION 0x31 +#define CC1101_FREQEST 0x32 +#define CC1101_LQI 0x33 +#define CC1101_RSSI 0x34 +#define CC1101_MARCSTATE 0x35 +#define CC1101_WORTIME1 0x36 +#define CC1101_WORTIME0 0x37 +#define CC1101_PKTSTATUS 0x38 +#define CC1101_VCO_VC_DAC 0x39 +#define CC1101_TXBYTES 0x3A +#define CC1101_RXBYTES 0x3B + +//CC1101 PATABLE,TXFIFO,RXFIFO +#define CC1101_PATABLE 0x3E +#define CC1101_TXFIFO 0x3F +#define CC1101_RXFIFO 0x3F + +#endif /* __CC1101__ */ diff --git a/lib/HAL/RFID/DATASHEETS/MFRC522.pdf b/lib/HAL/RFID/DATASHEETS/MFRC522.pdf new file mode 100644 index 000000000..f42af475d Binary files /dev/null and b/lib/HAL/RFID/DATASHEETS/MFRC522.pdf differ diff --git a/lib/HAL/RFID/DATASHEETS/PN532.pdf b/lib/HAL/RFID/DATASHEETS/PN532.pdf new file mode 100644 index 000000000..fd973fa8d Binary files /dev/null and b/lib/HAL/RFID/DATASHEETS/PN532.pdf differ diff --git a/lib/HAL/RTC/DATASHEETS/BM8563.pdf b/lib/HAL/RTC/DATASHEETS/BM8563.pdf new file mode 100644 index 000000000..0ebe78481 Binary files /dev/null and b/lib/HAL/RTC/DATASHEETS/BM8563.pdf differ diff --git a/lib/HAL/RTC/DATASHEETS/DS1302.pdf b/lib/HAL/RTC/DATASHEETS/DS1302.pdf new file mode 100644 index 000000000..ed8c42cb2 Binary files /dev/null and b/lib/HAL/RTC/DATASHEETS/DS1302.pdf differ diff --git a/lib/HAL/RTC/DATASHEETS/DS1307.pdf b/lib/HAL/RTC/DATASHEETS/DS1307.pdf new file mode 100644 index 000000000..5f55fa9e9 Binary files /dev/null and b/lib/HAL/RTC/DATASHEETS/DS1307.pdf differ diff --git a/lib/HAL/RTC/DATASHEETS/DS3231.pdf b/lib/HAL/RTC/DATASHEETS/DS3231.pdf new file mode 100644 index 000000000..4b51d64bc Binary files /dev/null and b/lib/HAL/RTC/DATASHEETS/DS3231.pdf differ diff --git a/lib/HAL/RTC/DATASHEETS/DS3232.pdf b/lib/HAL/RTC/DATASHEETS/DS3232.pdf new file mode 100644 index 000000000..185e9e2a2 Binary files /dev/null and b/lib/HAL/RTC/DATASHEETS/DS3232.pdf differ diff --git a/lib/HAL/RTC/DATASHEETS/DS3234.pdf b/lib/HAL/RTC/DATASHEETS/DS3234.pdf new file mode 100644 index 000000000..d7cb30fe5 Binary files /dev/null and b/lib/HAL/RTC/DATASHEETS/DS3234.pdf differ diff --git a/lib/HAL/RTC/DATASHEETS/PCF8563.pdf b/lib/HAL/RTC/DATASHEETS/PCF8563.pdf new file mode 100644 index 000000000..6e600f6bf Binary files /dev/null and b/lib/HAL/RTC/DATASHEETS/PCF8563.pdf differ diff --git a/lib/HAL/RTC/DATASHEETS/RV-1805-C3.pdf b/lib/HAL/RTC/DATASHEETS/RV-1805-C3.pdf new file mode 100644 index 000000000..95f8776fc Binary files /dev/null and b/lib/HAL/RTC/DATASHEETS/RV-1805-C3.pdf differ diff --git a/lib/HAL/RTC/DATASHEETS/RV-8803-C7.pdf b/lib/HAL/RTC/DATASHEETS/RV-8803-C7.pdf new file mode 100644 index 000000000..fa9627052 Binary files /dev/null and b/lib/HAL/RTC/DATASHEETS/RV-8803-C7.pdf differ diff --git a/lib/HAL/RTC/DRIVER/BM8563.tpp b/lib/HAL/RTC/DRIVER/BM8563.tpp new file mode 100644 index 000000000..18ede99b7 --- /dev/null +++ b/lib/HAL/RTC/DRIVER/BM8563.tpp @@ -0,0 +1,9 @@ +#include "../REG/BM8563.hpp" +#include "../RTC.tpp" +namespace HAL::RTC +{ + class BM8563 : public Base + { + friend class Base; + }; +} // namespace HAL::RTC \ No newline at end of file diff --git a/lib/HAL/RTC/DRIVER/DS3231.tpp b/lib/HAL/RTC/DRIVER/DS3231.tpp new file mode 100644 index 000000000..2d7d32d0c --- /dev/null +++ b/lib/HAL/RTC/DRIVER/DS3231.tpp @@ -0,0 +1,9 @@ +#include "../REG/DS3231.hpp" +#include "../RTC.tpp" +namespace HAL::RTC +{ + class DS3231 : public Base + { + friend class Base; + } +} // namespace HAL::RTC \ No newline at end of file diff --git a/lib/HAL/RTC/DRIVER/DS3234.tpp b/lib/HAL/RTC/DRIVER/DS3234.tpp new file mode 100644 index 000000000..573d22867 --- /dev/null +++ b/lib/HAL/RTC/DRIVER/DS3234.tpp @@ -0,0 +1,9 @@ +#include "../REG/DS3234.hpp" +#include "../RTC.tpp" +namespace HAL::RTC +{ + class DS3234 : public Base + { + friend class Base; + } +} // namespace HAL::RTC \ No newline at end of file diff --git a/lib/HAL/RTC/DRIVER/PCF8563.tpp b/lib/HAL/RTC/DRIVER/PCF8563.tpp new file mode 100644 index 000000000..4d4b53ed5 --- /dev/null +++ b/lib/HAL/RTC/DRIVER/PCF8563.tpp @@ -0,0 +1,9 @@ +#include "../REG/PCF8563.hpp" +#include "../RTC.tpp" +namespace HAL::RTC +{ + class PCF8563 : public Base + { + friend class Base; + }; +} // namespace HAL::RTC \ No newline at end of file diff --git a/lib/HAL/RTC/REG/BM8563.hpp b/lib/HAL/RTC/REG/BM8563.hpp new file mode 100644 index 000000000..f1600b880 --- /dev/null +++ b/lib/HAL/RTC/REG/BM8563.hpp @@ -0,0 +1,61 @@ +#ifndef __BM8563__ +#define __BM8563__ + +#define BM8563_I2C_ADDRESS (0x51) +#define BM8563_CONTROL_STATUS1 (0x00) +#define BM8563_CONTROL_STATUS2 (0x01) +#define BM8563_SECONDS (0x02) +#define BM8563_MINUTES (0x03) +#define BM8563_HOURS (0x04) +#define BM8563_DAY (0x05) +#define BM8563_WEEKDAY (0x06) +#define BM8563_MONTH (0x07) +#define BM8563_YEAR (0x08) +#define BM8563_MINUTE_ALARM (0x09) +#define BM8563_HOUR_ALARM (0x0a) +#define BM8563_DAY_ALARM (0x0b) +#define BM8563_WEEKDAY_ALARM (0x0c) +#define BM8563_CLKOUT_CONTROL (0x0d) +#define BM8563_TIMER_CONTROL (0x0e) +#define BM8563_TIMER (0x0f) + +#define BM8563_TESTC (0b00001000) +#define BM8563_STOP (0b00100000) +#define BM8563_TEST1 (0b10000000) + +#define BM8563_TIE (0b00000001) +#define BM8563_AIE (0b00000010) +#define BM8563_TF (0b00000100) +#define BM8563_AF (0b00001000) +#define BM8563_TI_TP (0b00010000) +#define BM8563_TIME_SIZE (0x07) +#define BM8563_CENTURY_BIT (0b10000000) + +#define BM8563_ALARM_DISABLE (0b10000000) +#define BM8563_ALARM_NONE (0xff) +#define BM8563_ALARM_SIZE (0x04) + +#define BM8563_TIMER_ENABLE (0b10000000) +#define BM8563_TIMER_4_096KHZ (0b00000000) +#define BM8563_TIMER_64HZ (0b00000001) +#define BM8563_TIMER_1HZ (0b00000010) +#define BM8563_TIMER_1_60HZ (0b00000011) + +/* IOCTL commands */ +#define BM8563_ALARM_SET (0x0900) +#define BM8563_ALARM_READ (0x0901) +#define BM8563_CONTROL_STATUS1_READ (0x0000) +#define BM8563_CONTROL_STATUS1_WRITE (0x0001) +#define BM8563_CONTROL_STATUS2_READ (0x0100) +#define BM8563_CONTROL_STATUS2_WRITE (0x0101) +#define BM8563_TIMER_CONTROL_READ (0x0e00) +#define BM8563_TIMER_CONTROL_WRITE (0x0e01) +#define BM8563_TIMER_READ (0x0f00) +#define BM8563_TIMER_WRITE (0x0f01) + +/* Status codes. */ +#define BM8563_ERROR_NOTTY (-1) +#define BM8563_OK (0x00) +#define BM8563_ERR_LOW_VOLTAGE (0x80) + +#endif /* __BM8563__ */ diff --git a/lib/HAL/RTC/REG/DS1307.hpp b/lib/HAL/RTC/REG/DS1307.hpp new file mode 100644 index 000000000..1b7c8fdac --- /dev/null +++ b/lib/HAL/RTC/REG/DS1307.hpp @@ -0,0 +1,29 @@ +#ifndef __DS1307__ +#define __DS1307__ + +#include + +// I2C Slave Address +const uint8_t DS1307_ADDRESS = 0x68; + +// DS1307 Register Addresses +const uint8_t DS1307_REG_TIMEDATE = 0x00; +const uint8_t DS1307_REG_STATUS = 0x00; +const uint8_t DS1307_REG_CONTROL = 0x07; +const uint8_t DS1307_REG_RAMSTART = 0x08; +const uint8_t DS1307_REG_RAMEND = 0x3f; +const uint8_t DS1307_REG_RAMSIZE = DS1307_REG_RAMEND - DS1307_REG_RAMSTART; + +// DS1307 Register Data Size if not just 1 +const size_t DS1307_REG_TIMEDATE_SIZE = 7; + +// DS1307 Control Register Bits +const uint8_t DS1307_RS0 = 0; +const uint8_t DS1307_RS1 = 1; +const uint8_t DS1307_SQWE = 4; +const uint8_t DS1307_OUT = 7; + +// DS1307 Status Register Bits +const uint8_t DS1307_CH = 7; + +#endif /* __DS1307__ */ diff --git a/lib/HAL/RTC/REG/DS3231.hpp b/lib/HAL/RTC/REG/DS3231.hpp new file mode 100644 index 000000000..681059c72 --- /dev/null +++ b/lib/HAL/RTC/REG/DS3231.hpp @@ -0,0 +1,47 @@ +#ifndef __DS3231__ +#define __DS3231__ + +#include + +// I2C Slave Address +const uint8_t DS3231_ADDRESS = 0x68; + +// DS3231 Register Addresses +const uint8_t DS3231_REG_TIMEDATE = 0x00; +const uint8_t DS3231_REG_ALARMONE = 0x07; +const uint8_t DS3231_REG_ALARMTWO = 0x0B; + +const uint8_t DS3231_REG_CONTROL = 0x0E; +const uint8_t DS3231_REG_STATUS = 0x0F; +const uint8_t DS3231_REG_AGING = 0x10; + +const uint8_t DS3231_REG_TEMP = 0x11; + +// DS3231 Register Data Size if not just 1 +const size_t DS3231_REG_TIMEDATE_SIZE = 7; +const size_t DS3231_REG_ALARMONE_SIZE = 4; +const size_t DS3231_REG_ALARMTWO_SIZE = 3; + +const size_t DS3231_REG_TEMP_SIZE = 2; + +// DS3231 Control Register Bits +const uint8_t DS3231_A1IE = 0; +const uint8_t DS3231_A2IE = 1; +const uint8_t DS3231_INTCN = 2; +const uint8_t DS3231_RS1 = 3; +const uint8_t DS3231_RS2 = 4; +const uint8_t DS3231_CONV = 5; +const uint8_t DS3231_BBSQW = 6; +const uint8_t DS3231_EOSC = 7; +const uint8_t DS3231_AIEMASK = (_BV(DS3231_A1IE) | _BV(DS3231_A2IE)); +const uint8_t DS3231_RSMASK = (_BV(DS3231_RS1) | _BV(DS3231_RS2)); + +// DS3231 Status Register Bits +const uint8_t DS3231_A1F = 0; +const uint8_t DS3231_A2F = 1; +const uint8_t DS3231_BSY = 2; +const uint8_t DS3231_EN32KHZ = 3; +const uint8_t DS3231_OSF = 7; +const uint8_t DS3231_AIFMASK = (_BV(DS3231_A1F) | _BV(DS3231_A2F)); + +#endif /* __DS3231__ */ diff --git a/lib/HAL/RTC/REG/DS3234.hpp b/lib/HAL/RTC/REG/DS3234.hpp new file mode 100644 index 000000000..e1c83c782 --- /dev/null +++ b/lib/HAL/RTC/REG/DS3234.hpp @@ -0,0 +1,49 @@ +#ifndef __DS3234__ +#define __DS3234__ +#include + +const uint8_t DS3234_REG_WRITE_FLAG = 0x80; + +const uint8_t DS3234_REG_TIMEDATE = 0x00; + +const uint8_t DS3234_REG_ALARMONE = 0x07; +const uint8_t DS3234_REG_ALARMTWO = 0x0B; + +const uint8_t DS3234_REG_CONTROL = 0x0E; +const uint8_t DS3234_REG_STATUS = 0x0F; +const uint8_t DS3234_REG_AGING = 0x10; + +const uint8_t DS3234_REG_TEMP = 0x11; + +const uint8_t DS3234_REG_RAM_ADDRESS = 0x18; +const uint8_t DS3234_REG_RAM_DATA = 0x19; + +const uint8_t DS3234_RAMSTART = 0x00; +const uint8_t DS3234_RAMEND = 0xFF; +const uint8_t DS3234_RAMSIZE = DS3234_RAMEND - DS3234_RAMSTART; + +// DS3234 Control Register Bits +const uint8_t DS3234_A1IE = 0; +const uint8_t DS3234_A2IE = 1; +const uint8_t DS3234_INTCN = 2; +const uint8_t DS3234_RS1 = 3; +const uint8_t DS3234_RS2 = 4; +const uint8_t DS3234_CONV = 5; +const uint8_t DS3234_BBSQW = 6; +const uint8_t DS3234_EOSC = 7; +const uint8_t DS3234_AIEMASK = (_BV(DS3234_A1IE) | _BV(DS3234_A2IE)); +const uint8_t DS3234_RSMASK = (_BV(DS3234_RS1) | _BV(DS3234_RS2)); + +// DS3234 Status Register Bits +const uint8_t DS3234_A1F = 0; +const uint8_t DS3234_A2F = 1; +const uint8_t DS3234_BSY = 2; +const uint8_t DS3234_EN32KHZ = 3; +const uint8_t DS3234_CRATE0 = 4; +const uint8_t DS3234_CRATE1 = 5; +const uint8_t DS3234_BB32KHZ = 6; +const uint8_t DS3234_OSF = 7; +const uint8_t DS3234_AIFMASK = (_BV(DS3234_A1F) | _BV(DS3234_A2F)); +const uint8_t DS3234_CRATEMASK = (_BV(DS3234_CRATE0) | _BV(DS3234_CRATE1)); + +#endif /* __DS3234__ */ diff --git a/lib/HAL/RTC/REG/PCF8563.hpp b/lib/HAL/RTC/REG/PCF8563.hpp new file mode 100644 index 000000000..58bc44fd0 --- /dev/null +++ b/lib/HAL/RTC/REG/PCF8563.hpp @@ -0,0 +1,36 @@ +#ifndef __PCF8563__ +#define __PCF8563__ + +#include + +// I2C Slave Address +const uint8_t PCF8563_ADDRESS = 0x51; + +// PCF8563 Register Addresses +const uint8_t PCF8563_REG_CONTROL = 0x00; +const uint8_t PCF8563_REG_STATUS = 0x01; +const uint8_t PCF8563_REG_TIMEDATE = 0x02; +const uint8_t PCF8563_REG_INTEGRITY = 0x02; +const uint8_t PCF8563_REG_ALARM = 0x09; +const uint8_t PCF8563_REG_CLKOUT_CONTROL = 0x0D; +const uint8_t PCF8563_REG_TIMER_CONTROL = 0x0E; +const uint8_t PCF8563_REG_TIMER = 0x0F; + +// PCF8563 Register Data Size if not just 1 +const size_t PCF8563_REG_TIMEDATE_SIZE = 7; +const size_t PCF8563_REG_ALARM_SIZE = 4; + +// PCF8563 Valid Register Bits (PCF8563_REG_INTEGRITY) +const uint8_t PCF8563_INTEGRITY_VALID = 7; + +// PCF8563 Control Register Bits (PCF8563_REG_CONTROL) +const uint8_t PCF8563_CONTROL_CLOCK = 5; + +// PCF8563 Status Register Bits (PCF8563_REG_STATUS) +const uint8_t PCF8563_STATUS_TIE = 0; // timer interrupt enable +const uint8_t PCF8563_STATUS_AIE = 1; // alarm interrupt enable +const uint8_t PCF8563_STATUS_TF = 2; // timer flag +const uint8_t PCF8563_STATUS_AF = 3; // alarm flag +const uint8_t PCF8563_STATUS_TITP = 4; // timer interrupt period config + +#endif /* __PCF8563__ */ diff --git a/lib/HAL/RTC/REG/RV-1805-C3.hpp b/lib/HAL/RTC/REG/RV-1805-C3.hpp new file mode 100644 index 000000000..879aa28d9 --- /dev/null +++ b/lib/HAL/RTC/REG/RV-1805-C3.hpp @@ -0,0 +1,125 @@ +#ifndef __RV_1805_C3__ +#define __RV_1805_C3__ + +#define RV1805C3_ADDRESS 0x69 + +/* Register Map */ + +#define REG_TIME_HUNDREDTHS 0x00 // Hundredths +#define REG_TIME_SECONDS 0x01 // Seconds +#define REG_TIME_MINUTES 0x02 // Minutes +#define REG_TIME_HOURS 0x03 // Hours +#define REG_DATE 0x04 // Date +#define REG_MONTHS 0x05 // Months +#define REG_YEARS 0x06 // Years +#define REG_WEEKDAYS 0x07 // Weekdays +#define REG_ALARM_HUNDREDTHS 0x08 // Hundredths Alarm +#define REG_ALARM_SECONDS 0x09 // Seconds Alarm +#define REG_ALARM_MINUTES 0x0A // Minutes Alarm +#define REG_ALARM_HOURS 0x0B // Hours Alarm +#define REG_ALARM_DATE 0x0C // Date Alarm +#define REG_ALARM_MONTHS 0x0D // Months Alarm +#define REG_ALARM_WEEKDAYS 0x0E // Weekdays Alarm +#define REG_STATUS 0x0F // Status +#define REG_CONTROL1 0x10 // Control1 +#define REG_CONTROL2 0x11 // Control2 +#define REG_INTERRUPT_MASK 0x12 // Interrupt Mask +#define REG_SQUARE_WAVE 0x13 // Square Wave SQW +#define REG_CAL_XT 0x14 // Calibration XT +#define REG_CAL_RC_UPPER 0x15 // Calibration RC Upper +#define REG_CAL_RC_LOWER 0x16 // Calibration RC Lower +#define REG_SLEEP_CONTROL 0x17 // Sleep Control +#define REG_COUNTDOWN_CONTROL 0x18 // Countdown Timer Control +#define REG_COUNTDOWN_TIMER 0x19 // Countdown Timer +#define REG_TIMER_INIT_VALUE 0x1A // Timer Initial Value +#define REG_WATCHDOG_TIMER 0x1B // Watchdog Timer +#define REG_OSC_CONTROL 0x1C // Oscillator Control +#define REG_OSC_STATUS 0x1D // Oscillator Status Register +#define REG_CONFIG_KEY 0x1F // Configuration Key +#define REG_TRICKLE_CHARGE 0x20 // Trickle Charge +#define REG_BREF_CONTROL 0x21 // BREF Control +#define REG_CAP_RC_CONTROL 0x26 // Cap_RC Control +#define REG_IO_BATMODE 0x27 // IO Batmode Register +#define REG_ID0 0x28 // ID0 (R) +#define REG_ID1 0x29 // ID1 (R) +#define REG_ANALOG_STAT 0x2F // Analog Stat. (R) +#define REG_OUTPUT_CONTROL 0x30 // Output Control Register + +#define PART_NUMBER_MSB 0x18 +#define PART_NUMBER_LSB 0x05 + +#define CONFKEY_OSC_CONTROL 0xA1 +#define CONFKEY_RESET 0x3C +#define CONFKEY_REGISTERS 0x9D + +#define DATETIME_COMPONENTS 8 + +enum DateTimeComponent { + DATETIME_HUNDREDTH = 0, + DATETIME_SECOND = 1, + DATETIME_MINUTE = 2, + DATETIME_HOUR = 3, + DATETIME_DAY_OF_MONTH = 4, + DATETIME_MONTH = 5, + DATETIME_YEAR = 6, + DATETIME_DAY_OF_WEEK = 7 +}; + +enum DayOfWeek { + SUN = 0, + MON = 1, + TUE = 2, + WED = 3, + THU = 4, + FRI = 5, + SAT = 6 +}; + +enum AlarmMode { + ALARM_DISABLED = 0, + ALARM_ONCE_PER_YEAR = 1, + ALARM_ONCE_PER_MONTH = 2, + ALARM_ONCE_PER_WEEK = 3, + ALARM_ONCE_PER_DAY = 4, + ALARM_ONCE_PER_HOUR = 5, + ALARM_ONCE_PER_MINUTE = 6, + ALARM_ONCE_PER_SECOND = 7, + ALARM_ONCE_PER_TENTH = 8, + ALARM_ONCE_PER_HUNDREDTH = 9 +}; + +enum CountdownUnit { + COUNTDOWN_SECONDS = 0b10, + COUNTDOWN_MINUTES = 0b11 +}; + +enum InterruptType { + INTERRUPT_WATCHDOG_TIMER = 5, + INTERRUPT_BATTERY_LOW = 4, + INTERRUPT_TIMER = 3, + INTERRUPT_ALARM = 2, + INTERRUPT_EXTERNAL = 1 +}; + +enum SleepWaitPeriod { + SLEEP_IMMEDIATELY = 0b000, + SLEEP_WAIT_8MS = 0b001, + SLEEP_WAIT_16MS = 0b010, + SLEEP_WAIT_24MS = 0b011, + SLEEP_WAIT_32MS = 0b100, + SLEEP_WAIT_40MS = 0b101, + SLEEP_WAIT_48MS = 0b110, + SLEEP_WAIT_56MS = 0b111 +}; + +enum PowerSwitchFunction { + PSWS_INVERSE_COMBINED_IRQ = 0b000, + PSWS_SQW = 0b001, + PSWS_INVERSE_AIRQ = 0b011, + PSWS_TIRQ = 0b100, + PSWS_INVERSE_TIRQ = 0b101, + PSWS_SLEEP = 0b110, + PSWS_STATIC = 0b111 +}; + +#endif /* __RV_1805_C3__ */ diff --git a/lib/HAL/RTC/REG/RV-8803-C7.hpp b/lib/HAL/RTC/REG/RV-8803-C7.hpp new file mode 100644 index 000000000..5b4ca7643 --- /dev/null +++ b/lib/HAL/RTC/REG/RV-8803-C7.hpp @@ -0,0 +1,113 @@ +#ifndef __RV_8803_C7__ +#define __RV_8803_C7__ + +//The 7-bit I2C address of the RV8803 +#define RV8803_ADDR 0x32 + +#define SUNDAY 0x01 +#define MONDAY 0x02 +#define TUESDAY 0x04 +#define WEDNESDAY 0x08 +#define THURSDAY 0x10 +#define FRIDAY 0x20 +#define SATURDAY 0x40 + +//Register names: +#define RV8803_RAM 0x07 +#define RV8803_HUNDREDTHS 0x10 +#define RV8803_SECONDS 0x11 +#define RV8803_MINUTES 0x12 +#define RV8803_HOURS 0x13 +#define RV8803_WEEKDAYS 0x14 +#define RV8803_DATE 0x15 +#define RV8803_MONTHS 0x16 +#define RV8803_YEARS 0x17 +#define RV8803_MINUTES_ALARM 0x18 +#define RV8803_HOURS_ALARM 0x19 +#define RV8803_WEEKDAYS_DATE_ALARM 0x1A +#define RV8803_TIMER_0 0x1B +#define RV8803_TIMER_1 0x1C +#define RV8803_EXTENSION 0x1D +#define RV8803_FLAG 0x1E +#define RV8803_CONTROL 0x1F +#define RV8803_HUNDREDTHS_CAPTURE 0x20 +#define RV8803_SECONDS_CAPTURE 0x21 +#define RV8803_OFFSET 0x2C +#define RV8803_EVENT_CONTROL 0x2F + +//Enable Bits for Alarm Registers +#define ALARM_ENABLE 7 + +//Extension Register Bits +#define EXTENSION_TEST 7 +#define EXTENSION_WADA 6 +#define EXTENSION_USEL 5 +#define EXTENSION_TE 4 +#define EXTENSION_FD 2 +#define EXTENSION_TD 0 + +//Flag Register Bits +#define FLAG_UPDATE 5 +#define FLAG_TIMER 4 +#define FLAG_ALARM 3 +#define FLAG_EVI 2 +#define FLAG_V2F 1 +#define FLAG_V1F 0 + +//Interrupt Control Register Bits +#define UPDATE_INTERRUPT 5 +#define TIMER_INTERRUPT 4 +#define ALARM_INTERRUPT 3 // +#define EVI_INTERRUPT 2 //External Event Interrupt +#define CONTROL_RESET 0 + +//Event Control Bits +#define EVENT_ECP 7 +#define EVENT_EHL 6 +#define EVENT_ET 4 +#define EVENT_ERST 0 + +//Possible Settings +#define TWELVE_HOUR_MODE true +#define TWENTYFOUR_HOUR_MODE false +#define COUNTDOWN_TIMER_FREQUENCY_4096_HZ 0b00 +#define COUNTDOWN_TIMER_FREQUENCY_64_HZ 0b01 +#define COUNTDOWN_TIMER_FREQUENCY_1_HZ 0b10 +#define COUNTDOWN_TIMER_FREQUENCY_1_60TH_HZ 0b11 +#define CLOCK_OUT_FREQUENCY_32768_HZ 0b00 +#define CLOCK_OUT_FREQUENCY_1024_HZ 0b01 +#define CLOCK_OUT_FREQUENCY_1_HZ 0b10 + +#define COUNTDOWN_TIMER_ON true +#define COUNTDOWN_TIMER_OFF false +#define TIME_UPDATE_1_SECOND false +#define TIME_UPDATE_1_MINUTE true + +#define ENABLE_EVI_CALIBRATION true +#define DISABLE_EVI_CALIBRATION false +#define EVI_DEBOUNCE_NONE 0b00 +#define EVI_DEBOUNCE_256HZ 0b01 +#define EVI_DEBOUNCE_64HZ 0b10 +#define EVI_DEBOUNCE_8HZ 0b11 +#define RISING_EDGE true +#define FALLING_EDGE false +#define EVI_CAPTURE_ENABLE true +#define EVI_CAPTURE_DISABLE false + +#define RV8803_ENABLE true +#define RV8803_DISABLE false + +#define TIME_ARRAY_LENGTH 8 // Total number of writable values in device + +enum time_order { + TIME_HUNDREDTHS, // 0 + TIME_SECONDS, // 1 + TIME_MINUTES, // 2 + TIME_HOURS, // 3 + TIME_WEEKDAY, // 4 + TIME_DATE, // 5 + TIME_MONTH, // 6 + TIME_YEAR, // 7 +}; + +#endif /* __RV_8803_C7__ */ diff --git a/lib/HAL/RTC/RTC.h b/lib/HAL/RTC/RTC.h new file mode 100644 index 000000000..f67a4166b --- /dev/null +++ b/lib/HAL/RTC/RTC.h @@ -0,0 +1,14 @@ +#ifndef __RTC__ +#define __RTC__ + +enum RTCChipModel +{ + BM8563, + UNDEFINED, +}; + +#ifdef RTC_BM8563 +#include "DRIVER/BM8563.tpp" +#endif + +#endif /* __RTC__ */ diff --git a/lib/HAL/RTC/RTC.tpp b/lib/HAL/RTC/RTC.tpp new file mode 100644 index 000000000..3f8f2bfe5 --- /dev/null +++ b/lib/HAL/RTC/RTC.tpp @@ -0,0 +1,68 @@ +namespace HAL::RTC +{ + template + class Base + { + void Bcd2asc(void) + { + uint8_t i, j; + for (j = 0, i = 0; i < 7; i++) + { + a sc[j++] = + (trdata[i] & 0xf0) >> 4 | 0x30; /*格式为: 秒 分 时 日 月 星期 年 */ + asc[j++] = (trdata[i] & 0x0f) | 0x30; + } + } + + uint8_t Bcd2ToByte(uint8_t Value) + { + uint8_t tmp = 0; + tmp = ((uint8_t)(Value & (uint8_t)0xF0) >> (uint8_t)0x4) * 10; + return (tmp + (Value & (uint8_t)0x0F)); + } + + uint8_t ByteToBcd2(uint8_t Value) + { + uint8_t bcdhigh = 0; + + while (Value >= 10) + { + bcdhigh++; + Value -= 10; + } + + return ((uint8_t)(bcdhigh << 4) | Value); + } + + uint8_t BcdToUint8(uint8_t val) + { + return val - 6 * (val >> 4); + } + + uint8_t Uint8ToBcd(uint8_t val) + { + return val + 6 * (val / 10); + } + + uint8_t BcdToBin24Hour(uint8_t bcdHour) + { + uint8_t hour; + if (bcdHour & 0x40) + { + // 12 hour mode, convert to 24 + bool isPm = ((bcdHour & 0x20) != 0); + + hour = BcdToUint8(bcdHour & 0x1f); + if (isPm) + { + hour += 12; + } + } + else + { + hour = BcdToUint8(bcdHour); + } + return hour; + } + }; +} // namespace HAL::RTC \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index a8ccf480d..ee5b54d68 100644 --- a/platformio.ini +++ b/platformio.ini @@ -33,7 +33,7 @@ extra_configs = boards/*/*.ini [env] -platform = espressif32 +platform = https://github.com/bmorcelli/platform-espressif32/releases/download/0.0.4/platform-espressif32.zip platform_packages = framework-arduinoespressif32 @ https://github.com/bmorcelli/arduino-esp32/releases/download/2.0.17e/esp32-2.0.17e.zip monitor_filters = esp32_exception_decoder, send_on_enter, colorize @@ -50,6 +50,8 @@ build_flags = -Wl,--gc-sections -DGIT_COMMIT_HASH='"Homebrew"' -DSAFE_STACK_BUFFER_SIZE=4096 + -DFASTLED_RMT_BUILTIN_DRIVER=1 ; https://github.com/FastLED/FastLED/blob/67436be11fc3b7be611cdf9011f31c4f76817741/src/platforms/esp/32/rmt_4/idf4_clockless_rmt_esp32.h#L25-L33 + ; This setting let RF Spectrum to work with LED interface with FastLED on ESP32-S3 ; rtl_433_ESP flags https://github.com/NorthernMan54/rtl_433_ESP/blob/main/example/OOK_Receiver/platformio.ini ;-DOOK_MODULATION=true ; False is FSK, True is OOK ;-DRF_CC1101="CC1101" diff --git a/src/core/config.cpp b/src/core/config.cpp index 211826be3..b66dfcd6f 100644 --- a/src/core/config.cpp +++ b/src/core/config.cpp @@ -328,7 +328,7 @@ void BruceConfig::setLedColor(uint32_t value) { void BruceConfig::validateLedColorValue() { - ledColor = max((uint32_t)0, min(0xFFFFFFFF, ledColor)); + ledColor = max((uint32_t)0, min((uint32_t)0xFFFFFFFF, ledColor)); } diff --git a/src/core/led_control.cpp b/src/core/led_control.cpp index 7f2503a08..a07af382f 100644 --- a/src/core/led_control.cpp +++ b/src/core/led_control.cpp @@ -4,6 +4,7 @@ #include "core/display.h" #include "core/utils.h" #include +#include "driver/rmt.h" CRGB leds[LED_COUNT]; @@ -36,6 +37,43 @@ void beginLed() { #else FastLED.addLeds(leds, LED_COUNT); // Initialize the LED Object. Only 1 LED. #endif + + +/* The default FastLED driver takes over control of the RMT interrupt + * handler, making it hard to use the RMT device for other + * (non-FastLED) purposes. You can change it's behavior to use the ESP + * core driver instead, allowing other RMT applications to + * co-exist. To switch to this mode, add the following directive + * before you include FastLED.h: + * + * #define FASTLED_RMT_BUILTIN_DRIVER 1 + * RMT is also used for RF Spectrum (and for RF readings in the future), + * So it is needed to restart the driver in case it had been turned off + * by the RF functions, in this case, we are restarting it all the time + */ +// -- RMT configuration for transmission +for (int i = 0; i < 8; i += 2) + { + rmt_config_t rmt_tx; + memset(&rmt_tx, 0, sizeof(rmt_config_t)); + rmt_tx.channel = rmt_channel_t(i); + rmt_tx.rmt_mode = RMT_MODE_TX; + rmt_tx.gpio_num = (gpio_num_t)RGB_LED; + rmt_tx.mem_block_num = 2; + rmt_tx.clk_div = 2; + rmt_tx.tx_config.loop_en = false; + rmt_tx.tx_config.carrier_level = RMT_CARRIER_LEVEL_LOW; + rmt_tx.tx_config.carrier_en = false; + rmt_tx.tx_config.idle_level = RMT_IDLE_LEVEL_LOW; + rmt_tx.tx_config.idle_output_en = true; + + // -- Apply the configuration + rmt_config(&rmt_tx); + rmt_driver_uninstall(rmt_channel_t(i)); + rmt_driver_install(rmt_channel_t(i), 0, 0); + } + + setLedColor(bruceConfig.ledColor); setLedBrightness(bruceConfig.ledBright); } diff --git a/src/core/menu_items/ConfigMenu.cpp b/src/core/menu_items/ConfigMenu.cpp index 475326a86..4b52b36f3 100644 --- a/src/core/menu_items/ConfigMenu.cpp +++ b/src/core/menu_items/ConfigMenu.cpp @@ -15,8 +15,8 @@ void ConfigMenu::optionsMenu() { {"Orientation", [=]() { gsetRotation(true); }}, {"UI Color", [=]() { setUIColor(); }}, #ifdef HAS_RGB_LED - {"LED Color", [=]() { setLedColorConfig(); }}, - {"LED Brightness",[=]() { setLedBrightnessConfig(); }}, + {"LED Color", [=]() { beginLed(); setLedColorConfig(); }}, + {"LED Brightness",[=]() { beginLed(); setLedBrightnessConfig(); }}, #endif {"Sound On/Off", [=]() { setSoundConfig(); }}, {"Startup WiFi", [=]() { setWifiStartupConfig(); }}, @@ -28,6 +28,15 @@ void ConfigMenu::optionsMenu() { #if defined(T_EMBED_1101) options.emplace_back("Turn-off", [=]() { digitalWrite(PIN_POWER_ON,LOW); esp_sleep_enable_ext0_wakeup(GPIO_NUM_6,LOW); esp_deep_sleep_start(); }); +#elif defined(T_DISPLAY_S3) + options.emplace_back("Turn-off", [=]() + { + tft.fillScreen(TFT_BLACK); + digitalWrite(PIN_POWER_ON, LOW); + digitalWrite(TFT_BL, LOW); + tft.writecommand(0x10); + esp_deep_sleep_start(); + }); #endif if (bruceConfig.devMode) options.emplace_back("Dev Mode", [=]() { devMenu(); }); diff --git a/src/core/mykeyboard.cpp b/src/core/mykeyboard.cpp index f2a295ec7..c605b1b0e 100644 --- a/src/core/mykeyboard.cpp +++ b/src/core/mykeyboard.cpp @@ -52,12 +52,18 @@ static box_t box_list[box_count]; // This will get the value from InputHandler and read add into loopTask, // reseting the value after used keyStroke _getKeyPress() { + #ifndef USE_TFT_eSPI_TOUCH vTaskSuspend( xHandle ); keyStroke key=KeyStroke; KeyStroke.Clear(); delay(10); vTaskResume( xHandle ); return key; + #else + keyStroke key=KeyStroke; + KeyStroke.Clear(); + return key; + #endif } // must return something that the keyboards won´t recognize by default diff --git a/src/core/sd_functions.cpp b/src/core/sd_functions.cpp index 145fb4e83..f7b66cac7 100644 --- a/src/core/sd_functions.cpp +++ b/src/core/sd_functions.cpp @@ -139,23 +139,23 @@ bool renameFile(FS fs, String path, String filename) { ***************************************************************************************/ bool copyToFs(FS from, FS to, String path, bool draw) { // Using Global Buffer - bool result; + bool result=false; if(!sdcardMounted) { Serial.println("Error 0"); return false; } - if (!SD.begin()) { sdcardMounted=false; result = false; Serial.println("Error 1"); } - if(!LittleFS.begin()) { result = false; Serial.println("Error 2"); } + if (!SD.begin()) { sdcardMounted=false; Serial.println("Error 1"); return false; } + if(!LittleFS.begin()) { Serial.println("Error 2"); return false; } File source = from.open(path, FILE_READ); if (!source) { Serial.println("Error 3"); - result = false; + return false; } path = path.substring(path.lastIndexOf('/')); if(!path.startsWith("/")) path = "/" + path; File dest = to.open(path, FILE_WRITE); if (!dest) { Serial.println("Error 4"); - result = false; + return false; } size_t bytesRead; int tot=source.size(); @@ -171,8 +171,8 @@ bool copyToFs(FS from, FS to, String path, bool draw) { //Serial.println("Falha ao escrever no arquivo de destino"); source.close(); dest.close(); - result = false; Serial.println("Error 5"); + return false; } else { prog+=bytesRead; float rad = 360*prog/tot; @@ -180,9 +180,8 @@ bool copyToFs(FS from, FS to, String path, bool draw) { } } if(prog==tot) result = true; - else { result = false; displayError("Error 6"); } + else { displayError("Fail Copying File",true); return false;} - if(!result) delay(5000); return result; } diff --git a/src/core/serialcmds.cpp b/src/core/serialcmds.cpp index eec3b3b4b..45a54f2f8 100644 --- a/src/core/serialcmds.cpp +++ b/src/core/serialcmds.cpp @@ -55,21 +55,36 @@ bool setupPsramFs() { } -String readSmallFileFromSerial() { - String buf = ""; - String curr_line = ""; +char *readFileFromSerial(size_t fileSizeChar = SAFE_STACK_BUFFER_SIZE) { + char *buf; + size_t bufSize = 0; + if(psramFound()) buf = (char *)ps_malloc((fileSizeChar) * sizeof(char)); + else buf = (char *)malloc((fileSizeChar) * sizeof(char)); + if (buf == NULL) { + Serial.printf("Could not allocate %d\n", fileSizeChar); + return NULL; + } + buf[0] = '\0'; + + String currLine = ""; + Serial.println("Serial connection ready to receive file data"); Serial.flush(); while (true) { - if (!Serial.available()) { - delay(500); - Serial.flush(); - continue; - } - curr_line = Serial.readStringUntil('\n'); - if(curr_line.startsWith("EOF")) break; - buf += curr_line + "\n"; - if(buf.length()>SAFE_STACK_BUFFER_SIZE) break; // trim? + if (!Serial.available()) { + delay(10); + continue; + } + currLine = Serial.readStringUntil('\n'); + if(currLine.startsWith("EOF")) break; + size_t lineLength = currLine.length(); + if((bufSize + lineLength + 1) > fileSizeChar) break; + + memcpy(buf + bufSize, currLine.c_str(), lineLength); + bufSize += lineLength; + buf[bufSize++] = '\n'; } + buf[bufSize] = '\0'; + Serial.println(buf); return buf; } /* @@ -270,14 +285,15 @@ bool processSerialCommand(String cmd_str) { if(cmd_str.startsWith("ir tx_from_buffer")){ if(!(setupPsramFs())) return false; - String txt = readSmallFileFromSerial(); - String tmpfilepath = "/tmpramfile"; // TODO: random name? + char *txt = readFileFromSerial(); + String tmpfilepath = "/tmpramfile"; // TODO: Change to use char *txt directly File f = PSRamFS.open(tmpfilepath, FILE_WRITE); if(!f) return false; - f.write((const uint8_t*) txt.c_str(), txt.length()); + f.write((const uint8_t*) txt, strlen(txt)); f.close(); + free(txt); bool r = txIrFile(&PSRamFS, tmpfilepath); - PSRamFS.remove(tmpfilepath); // TODO: keep cached? + PSRamFS.remove(tmpfilepath); return r; } @@ -378,15 +394,16 @@ bool processSerialCommand(String cmd_str) { } if(cmd_str == "subghz tx_from_buffer") { if(!(setupPsramFs())) return false; - String txt = readSmallFileFromSerial(); - String tmpfilepath = "/tmpramfile"; // TODO: random name? + char *txt = readFileFromSerial(); + String tmpfilepath = "/tmpramfile"; // TODO: Change to use char *txt directly File f = PSRamFS.open(tmpfilepath, FILE_WRITE); if(!f) return false; - f.write((const uint8_t*) txt.c_str(), txt.length()); + f.write((const uint8_t*) txt, strlen(txt)); f.close(); + free(txt); //if(PSRamFS.exists(filepath)) bool r = txSubFile(&PSRamFS, tmpfilepath); - PSRamFS.remove(tmpfilepath); // TODO: keep cached? + PSRamFS.remove(tmpfilepath); return r; } @@ -496,16 +513,17 @@ bool processSerialCommand(String cmd_str) { } if(cmd_str == "badusb run_from_buffer") { if(!(setupPsramFs())) return false; - String txt = readSmallFileFromSerial(); - String tmpfilepath = "/tmpramfile"; // TODO: random name? + char *txt = readFileFromSerial(); + String tmpfilepath = "/tmpramfile"; // TODO: Change to use char *txt directly File f = PSRamFS.open(tmpfilepath, FILE_WRITE); if(!f) return false; - f.write((const uint8_t*) txt.c_str(), txt.length()); + f.write((const uint8_t*) txt, strlen(txt)); f.close(); + free(txt); Kb.begin(); USB.begin(); key_input(PSRamFS, tmpfilepath); - PSRamFS.remove(tmpfilepath); // TODO: keep cached? + PSRamFS.remove(tmpfilepath); return true; } #endif @@ -1008,19 +1026,26 @@ bool processSerialCommand(String cmd_str) { // else return false; } - if(cmd_str.startsWith("storage write ")) { - String filepath = cmd_str.substring(strlen("storage write ")); + if(cmd_str.startsWith("storage write ")) { // usage: storage write + String filepathAndSize = cmd_str.substring(strlen("storage write ")); + filepathAndSize.trim(); + int delimiter = filepathAndSize.indexOf(' '); + + String filepath = filepathAndSize.substring(0, delimiter == -1 ? filepathAndSize.length() : delimiter); + int fileSize = delimiter == -1 ? SAFE_STACK_BUFFER_SIZE : filepathAndSize.substring(delimiter + 1).toInt(); filepath.trim(); + if(filepath.length()==0) return false; // missing arg if(!filepath.startsWith("/")) filepath = "/" + filepath; // add "/" if missing FS* fs = &LittleFS; // default fallback if(sdcardMounted) fs = &SD; - String txt = readSmallFileFromSerial(); - if(txt.length()==0) return false; + char *txt = readFileFromSerial(fileSize + 2); + if(strlen(txt) == 0) return false; File f = fs->open(filepath, FILE_APPEND, true); // create if it does not exist, append otherwise if(!f) return false; - f.write((const uint8_t*) txt.c_str(), txt.length()); + f.write((const uint8_t*) txt, strlen(txt)); f.close(); + free(txt); Serial.println("file written: " + filepath); return true; } @@ -1067,15 +1092,10 @@ bool processSerialCommand(String cmd_str) { #if !defined(LITE_VERSION) if(cmd_str.startsWith("js run_from_buffer")){ - if(!(setupPsramFs())) return false; - String txt = readSmallFileFromSerial(); - String tmpfilepath = "/tmpramfile"; - File f = PSRamFS.open(tmpfilepath, FILE_WRITE); - if(!f) return false; - f.write((const uint8_t*) txt.c_str(), txt.length()); - f.close(); - bool r = run_bjs_script_headless(PSRamFS, tmpfilepath); - PSRamFS.remove(tmpfilepath); + int fileSize = cmd_str.substring(strlen("js run_from_buffer ")).toInt(); + char *txt = readFileFromSerial(fileSize < 2 ? SAFE_STACK_BUFFER_SIZE : (fileSize + 2)); + bool r = run_bjs_script_headless(txt); + // *txt is freed by js interpreter return r; } @@ -1090,12 +1110,13 @@ bool processSerialCommand(String cmd_str) { if(!fs) { // dir not found // assume filepath is an inline script Serial.println(filepath); - run_bjs_script_headless(filepath); + char *txt = strdup(filepath.c_str()); + run_bjs_script_headless(txt); + // *txt is freed by js interpreter return true; } // else run_bjs_script_headless(*fs, filepath); - // else return true; } #endif @@ -1139,13 +1160,14 @@ bool processSerialCommand(String cmd_str) { return false; } else if(cmd_str.startsWith("crypto encrypt_to_file")) { - String txt = readSmallFileFromSerial(); - if(txt.length()==0) return false; + char *txt = readFileFromSerial(); + if(strlen(txt) == 0) return false; + String txtString = String(txt); FS* fs = &SD; if(!sdcardMounted) fs = &LittleFS; File f = fs->open(filepath, FILE_WRITE); if(!f) return false; - String cyphertxt = encryptString(txt, cachedPassword); + String cyphertxt = encryptString(txtString, cachedPassword); if(cyphertxt=="") return false; f.write((const uint8_t*) cyphertxt.c_str(), cyphertxt.length()); f.close(); diff --git a/src/main.cpp b/src/main.cpp index 517e52e39..e7f482c33 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,7 +8,7 @@ #include "esp32-hal-psram.h" #include "core/utils.h" #include "core/powerSave.h" - +#include "esp_task_wdt.h" BruceConfig bruceConfig; @@ -332,15 +332,18 @@ void setup() { _post_setup_gpio(); // end of post gpio begin +#ifndef USE_TFT_eSPI_TOUCH // This task keeps running all the time, will never stop xTaskCreate( taskInputHandler, // Task function "InputHandler", // Task Name - 2048, // Stack size + 4096, // Stack size NULL, // Task parameters 2, // Task priority (0 to 3), loopTask has priority 2. &xHandle // Task handle (not used) ); +#endif + boot_screen_anim(); startup_sound(); diff --git a/src/modules/bjs_interpreter/interpreter.cpp b/src/modules/bjs_interpreter/interpreter.cpp index 00c23301c..75caec2a4 100644 --- a/src/modules/bjs_interpreter/interpreter.cpp +++ b/src/modules/bjs_interpreter/interpreter.cpp @@ -11,13 +11,17 @@ //#include // used for badusbPressSpecial //USBHIDConsumerControl cc; -String headers[20]; -String script = "drawString('Something wrong.', 4, 4);"; +static bool isScriptDynamic = false; +static const char *script = "drawString('Something wrong.', 4, 4);"; HTTPClient http; static duk_ret_t native_load(duk_context *ctx) { - script = duk_to_string(ctx, 0); + if (isScriptDynamic) { + free((char *)script); + } + script = strdup(duk_to_string(ctx, 0)); + isScriptDynamic = true; return 0; } @@ -130,11 +134,17 @@ static duk_ret_t native_getFreeHeapSize(duk_context *ctx) { duk_idx_t obj_idx = duk_push_object(ctx); duk_push_uint(ctx, info.total_free_bytes); - duk_put_prop_string(ctx, obj_idx, "total_free_bytes"); + duk_put_prop_string(ctx, obj_idx, "ram_free"); duk_push_uint(ctx, info.minimum_free_bytes); - duk_put_prop_string(ctx, obj_idx, "minimum_free_bytes"); + duk_put_prop_string(ctx, obj_idx, "ram_min_free"); duk_push_uint(ctx, info.largest_free_block); - duk_put_prop_string(ctx, obj_idx, "largest_free_block"); + duk_put_prop_string(ctx, obj_idx, "ram_largest_free_block"); + duk_push_uint(ctx, ESP.getHeapSize()); + duk_put_prop_string(ctx, obj_idx, "ram_size"); + duk_push_uint(ctx, ESP.getFreePsram()); + duk_put_prop_string(ctx, obj_idx, "psram_free"); + duk_push_uint(ctx, ESP.getPsramSize()); + duk_put_prop_string(ctx, obj_idx, "psram_size"); return 1; } @@ -157,6 +167,7 @@ static duk_ret_t native_wifiConnect(duk_context *ctx) { Serial.println("Connecting to: " + ssid); + WiFi.mode(WIFI_MODE_STA); if(duk_is_string(ctx, 2)) { String pwd = duk_to_string(ctx, 2); WiFi.begin(ssid, pwd); @@ -177,38 +188,47 @@ static duk_ret_t native_wifiConnect(duk_context *ctx) { if(WiFi.status() == WL_CONNECTED) { r = true; wifiIP = WiFi.localIP().toString(); // update global var + wifiConnected = true; } duk_push_boolean(ctx, r); return 1; } +const char *wifi_enc_types[] = { + "OPEN", + "WEP", + "WPA_PSK", + "WPA2_PSK", + "WPA_WPA2_PSK", + "ENTERPRISE", + "WPA2_ENTERPRISE", + "WPA3_PSK", + "WPA2_WPA3_PSK", + "WAPI_PSK", + "WPA3_ENT_192", + "MAX" +}; + static duk_ret_t native_wifiScan(duk_context *ctx) { - // Example usage: `print(wifiScan()[0].SSID)` - wifiDisconnect(); WiFi.mode(WIFI_MODE_STA); - //Serial.println("Scanning..."); int nets = WiFi.scanNetworks(); - duk_push_array(ctx); + duk_idx_t arr_idx = duk_push_array(ctx); int arrayIndex = 0; duk_idx_t obj_idx; - for(int i=0; i= 0) { + Gif *gif = gifs.at(gifIndex); + if (gif != NULL) { + result = gif->playFrame(x, y); + } } - duk_push_int(ctx, gif->playFrame(x, y)); + duk_push_int(ctx, result); return 1; } @@ -466,7 +483,7 @@ static duk_ret_t native_gifDimensions(duk_context *ctx) { } } - return 0; + return 1; } static duk_ret_t native_gifReset(duk_context *ctx) { @@ -477,37 +494,43 @@ static duk_ret_t native_gifReset(duk_context *ctx) { gifIndex = duk_to_int(ctx, -1) - 1; } - if (gifIndex < 0) { - duk_push_int(ctx, 0); - } else { + uint8_t result = 0; + if (gifIndex >= 0) { Gif *gif = gifs.at(gifIndex); if (gif != NULL) { gifs.at(gifIndex)->reset(); + result = 1; } } + duk_push_int(ctx, result); - return 0; + return 1; } static duk_ret_t native_gifClose(duk_context *ctx) { int gifIndex = 0; - duk_push_this(ctx); + if (duk_is_object(ctx, 0)) { + duk_to_object(ctx, 0); + } else { + duk_push_this(ctx); + } if (duk_get_prop_string(ctx, -1, "gifPointer")) { gifIndex = duk_to_int(ctx, -1) - 1; } - if (gifIndex < 0) { - duk_push_int(ctx, 0); - } else { + uint8_t result = 0; + if (gifIndex >= 0) { Gif *gif = gifs.at(gifIndex); if (gif != NULL) { - gifs.at(gifIndex)->close(); - delete gifs.at(gifIndex); + delete gif; + gifs.at(gifIndex) = NULL; + result = 1; } } + duk_push_int(ctx, result); - return 0; + return 1; } static duk_ret_t native_gifOpen(duk_context *ctx) { @@ -537,6 +560,8 @@ static duk_ret_t native_gifOpen(duk_context *ctx) { duk_put_prop_string(ctx, obj_idx, "reset"); duk_push_c_function(ctx, native_gifClose, 0); duk_put_prop_string(ctx, obj_idx, "close"); + duk_push_c_function(ctx, native_gifClose, 1); + duk_set_finalizer(ctx, obj_idx); } return 1; @@ -1023,23 +1048,48 @@ static duk_ret_t native_storageWrite(duk_context *ctx) { // Read script file -String readScriptFile(FS fs, String filename) { - String fileError = "drawString('Something wrong.', 4, 4);"; +const char *readScriptFile(FS fs, String filename) { + isScriptDynamic = false; + File file = fs.open(filename); + const char *fileError = "drawString('Something wrong.', 4, 4);"; + + if (!file) { + Serial.println("Could not open file"); + return "drawString('Could not open file.', 4, 4);"; + } - File file = fs.open(filename); - if (!file) { - return fileError; - } + char *buf; + size_t len = file.size(); + if (psramFound()) { + buf = (char *)ps_malloc((len + 1) * sizeof(char)); + } else { + buf = (char *)malloc((len + 1) * sizeof(char)); + } + + if (!buf) { + Serial.println("Could not allocate memory for file"); + return "drawString('Could not allocate memory for file.', 4, 4);"; + } - String s; - Serial.println("Read from file"); - while (file.available()) { - s += (char)file.read(); + Serial.println("Reading from file"); + size_t bytesRead = 0; + + while (bytesRead < len && file.available()) { + size_t toRead = len - bytesRead; + if (toRead > 512) { + toRead = 512; } - file.close(); - Serial.println("loaded file:"); - Serial.println(s); - return s; + file.read((uint8_t *)(buf + bytesRead), toRead); + bytesRead += toRead; + } + buf[bytesRead] = '\0'; + + file.close(); + Serial.println("loaded file:"); + Serial.println(buf); + + isScriptDynamic = true; + return buf; } static void registerFunction(duk_context *ctx, const char *name, duk_c_function func, duk_idx_t nargs) { @@ -1047,11 +1097,35 @@ static void registerFunction(duk_context *ctx, const char *name, duk_c_function duk_put_global_string(ctx, name); } +static void registerLightFunction(duk_context *ctx, const char *name, duk_c_function func, duk_idx_t nargs, duk_idx_t magic = 0) { + duk_push_c_lightfunc(ctx, func, nargs, nargs, magic); + duk_put_global_string(ctx, name); +} + static void registerInt(duk_context *ctx, const char *name, duk_int_t val) { duk_push_int(ctx, val); duk_put_global_string(ctx, name); } +void *ps_alloc_function(void *udata, duk_size_t size) { + void *res; + DUK_UNREF(udata); + res = ps_malloc(size); + return res; +} + +void *ps_realloc_function(void *udata, void *ptr, duk_size_t newsize) { + void *res; + DUK_UNREF(udata); + res = ps_realloc(ptr, newsize); + return res; +} + +void ps_free_function(void *udata, void *ptr) { + DUK_UNREF(udata); + DUK_ANSI_FREE(ptr); +} + // Code interpreter, must be called in the loop() function to work bool interpreter() { tft.fillScreen(TFT_BLACK); @@ -1059,107 +1133,122 @@ bool interpreter() { tft.setTextSize(FM); tft.setTextColor(TFT_WHITE); // Create context. - duk_context *ctx = duk_create_heap_default(); + auto alloc_function = &ps_alloc_function; + auto realloc_function = &ps_realloc_function; + auto free_function = &ps_free_function; + if (!psramFound()) { + alloc_function = NULL; + realloc_function = NULL; + free_function = NULL; + } + + duk_context *ctx = duk_create_heap( + alloc_function, + realloc_function, + free_function, + NULL, + NULL + ); // Add native functions to context. - registerFunction(ctx, "load", native_load, 1); - registerFunction(ctx, "now", native_now, 0); - registerFunction(ctx, "delay", native_delay, 1); - registerFunction(ctx, "random", native_random, 2); - registerFunction(ctx, "digitalWrite", native_digitalWrite, 2); - registerFunction(ctx, "analogWrite", native_analogWrite, 2); - registerFunction(ctx, "digitalRead", native_digitalRead, 1); - registerFunction(ctx, "analogRead", native_analogRead, 1); - registerFunction(ctx, "pinMode", native_pinMode, 2); - // registerFunction(ctx, "exit", native_exit, 0); + registerLightFunction(ctx, "load", native_load, 1); + registerLightFunction(ctx, "now", native_now, 0); + registerLightFunction(ctx, "delay", native_delay, 1); + registerLightFunction(ctx, "random", native_random, 2); + registerLightFunction(ctx, "digitalWrite", native_digitalWrite, 2); + registerLightFunction(ctx, "analogWrite", native_analogWrite, 2); + registerLightFunction(ctx, "digitalRead", native_digitalRead, 1); + registerLightFunction(ctx, "analogRead", native_analogRead, 1); + registerLightFunction(ctx, "pinMode", native_pinMode, 2); + // registerLightFunction(ctx, "exit", native_exit, 0); // Get Informations from the board - registerFunction(ctx, "getBattery", native_getBattery, 0); - registerFunction(ctx, "getBoard", native_getBoard, 0); - registerFunction(ctx, "getFreeHeapSize", native_getFreeHeapSize, 0); + registerLightFunction(ctx, "getBattery", native_getBattery, 0); + registerLightFunction(ctx, "getBoard", native_getBoard, 0); + registerLightFunction(ctx, "getFreeHeapSize", native_getFreeHeapSize, 0); // Networking - registerFunction(ctx, "wifiConnect", native_wifiConnect, 2); - registerFunction(ctx, "wifiConnectDialog", native_wifiConnectDialog, 0); - registerFunction(ctx, "wifiDisconnect", native_wifiDisconnect, 0); - registerFunction(ctx, "wifiScan", native_wifiScan, 0); - registerFunction(ctx, "httpGet", native_get, 2); + registerLightFunction(ctx, "wifiConnect", native_wifiConnect, 3); + registerLightFunction(ctx, "wifiConnectDialog", native_wifiConnectDialog, 0); + registerLightFunction(ctx, "wifiDisconnect", native_wifiDisconnect, 0); + registerLightFunction(ctx, "wifiScan", native_wifiScan, 0); + registerLightFunction(ctx, "httpGet", native_get, 2); // Graphics - registerFunction(ctx, "color", native_color, 3); - registerFunction(ctx, "setTextColor", native_setTextColor, 1); - registerFunction(ctx, "setTextSize", native_setTextSize, 1); - registerFunction(ctx, "drawRect", native_drawRect, 5); - registerFunction(ctx, "drawFillRect", native_drawFillRect, 5); - registerFunction(ctx, "drawLine", native_drawLine, 5); - registerFunction(ctx, "drawString", native_drawString, 3); - registerFunction(ctx, "setCursor", native_setCursor, 2); - registerFunction(ctx, "print", native_print, 1); - registerFunction(ctx, "println", native_println, 1); - registerFunction(ctx, "drawPixel", native_drawPixel, 3); - registerFunction(ctx, "fillScreen", native_fillScreen, 1); - // registerFunction(ctx, "drawBitmap", native_drawBitmap, 4); - registerFunction(ctx, "drawJpg", native_drawJpg, 4); - registerFunction(ctx, "drawGif", native_drawGif, 6); + registerLightFunction(ctx, "color", native_color, 3); + registerLightFunction(ctx, "setTextColor", native_setTextColor, 1); + registerLightFunction(ctx, "setTextSize", native_setTextSize, 1); + registerLightFunction(ctx, "drawRect", native_drawRect, 5); + registerLightFunction(ctx, "drawFillRect", native_drawFillRect, 5); + registerLightFunction(ctx, "drawLine", native_drawLine, 5); + registerLightFunction(ctx, "drawString", native_drawString, 3); + registerLightFunction(ctx, "setCursor", native_setCursor, 2); + registerLightFunction(ctx, "print", native_print, 1); + registerLightFunction(ctx, "println", native_println, 1); + registerLightFunction(ctx, "drawPixel", native_drawPixel, 3); + registerLightFunction(ctx, "fillScreen", native_fillScreen, 1); + // registerLightFunction(ctx, "drawBitmap", native_drawBitmap, 4); + registerLightFunction(ctx, "drawJpg", native_drawJpg, 4); + registerLightFunction(ctx, "drawGif", native_drawGif, 6); clearGifsVector(); - registerFunction(ctx, "gifOpen", native_gifOpen, 2); + registerLightFunction(ctx, "gifOpen", native_gifOpen, 2); - registerFunction(ctx, "width", native_width, 0); - registerFunction(ctx, "height", native_height, 0); + registerLightFunction(ctx, "width", native_width, 0); + registerLightFunction(ctx, "height", native_height, 0); // Input - registerFunction(ctx, "getKeysPressed", native_getKeysPressed, 0); // keyboard btns for cardputer (entry) - registerFunction(ctx, "getPrevPress", native_getPrevPress, 0); - registerFunction(ctx, "getSelPress", native_getSelPress, 0); - registerFunction(ctx, "getNextPress", native_getNextPress, 0); - registerFunction(ctx, "getAnyPress", native_getAnyPress, 0); + registerLightFunction(ctx, "getKeysPressed", native_getKeysPressed, 0); // keyboard btns for cardputer (entry) + registerLightFunction(ctx, "getPrevPress", native_getPrevPress, 0); + registerLightFunction(ctx, "getSelPress", native_getSelPress, 0); + registerLightFunction(ctx, "getNextPress", native_getNextPress, 0); + registerLightFunction(ctx, "getAnyPress", native_getAnyPress, 0); // Serial + wrappers - registerFunction(ctx, "serialReadln", native_serialReadln, 0); - registerFunction(ctx, "serialPrintln", native_serialPrintln, 1); - registerFunction(ctx, "serialCmd", native_serialCmd, 1); - registerFunction(ctx, "playAudioFile", native_playAudioFile, 1); - registerFunction(ctx, "tone", native_tone, 2); - registerFunction(ctx, "irTransmitFile", native_irTransmitFile, 1); - registerFunction(ctx, "subghzTransmitFile", native_subghzTransmitFile, 1); - registerFunction(ctx, "badusbRunFile", native_badusbRunFile, 1); + registerLightFunction(ctx, "serialReadln", native_serialReadln, 0); + registerLightFunction(ctx, "serialPrintln", native_serialPrintln, 1); + registerLightFunction(ctx, "serialCmd", native_serialCmd, 1); + registerLightFunction(ctx, "playAudioFile", native_playAudioFile, 1); + registerLightFunction(ctx, "tone", native_tone, 2); + registerLightFunction(ctx, "irTransmitFile", native_irTransmitFile, 1); + registerLightFunction(ctx, "subghzTransmitFile", native_subghzTransmitFile, 1); + registerLightFunction(ctx, "badusbRunFile", native_badusbRunFile, 1); // badusb functions - registerFunction(ctx, "badusbSetup", native_badusbSetup, 0); - registerFunction(ctx, "badusbPrint", native_badusbPrint, 1); - registerFunction(ctx, "badusbPrintln", native_badusbPrintln, 1); - registerFunction(ctx, "badusbPress", native_badusbPress, 1); - registerFunction(ctx, "badusbHold", native_badusbHold, 1); - registerFunction(ctx, "badusbRelease", native_badusbRelease, 1); - registerFunction(ctx, "badusbReleaseAll", native_badusbReleaseAll, 0); - registerFunction(ctx, "badusbPressRaw", native_badusbPressRaw, 1); - //registerFunction(ctx, "badusbPressSpecial", native_badusbPressSpecial, 1); + registerLightFunction(ctx, "badusbSetup", native_badusbSetup, 0); + registerLightFunction(ctx, "badusbPrint", native_badusbPrint, 1); + registerLightFunction(ctx, "badusbPrintln", native_badusbPrintln, 1); + registerLightFunction(ctx, "badusbPress", native_badusbPress, 1); + registerLightFunction(ctx, "badusbHold", native_badusbHold, 1); + registerLightFunction(ctx, "badusbRelease", native_badusbRelease, 1); + registerLightFunction(ctx, "badusbReleaseAll", native_badusbReleaseAll, 0); + registerLightFunction(ctx, "badusbPressRaw", native_badusbPressRaw, 1); + //registerLightFunction(ctx, "badusbPressSpecial", native_badusbPressSpecial, 1); // IR functions - registerFunction(ctx, "irRead", native_irRead, 0); - registerFunction(ctx, "irReadRaw", native_irReadRaw, 0); + registerLightFunction(ctx, "irRead", native_irRead, 0); + registerLightFunction(ctx, "irReadRaw", native_irReadRaw, 0); // TODO: irTransmit(string) // subghz functions - registerFunction(ctx, "subghzRead", native_subghzRead, 0); - registerFunction(ctx, "subghzReadRaw", native_subghzReadRaw, 0); - registerFunction(ctx, "subghzSetFrequency", native_subghzSetFrequency, 1); - // registerFunction(ctx, "subghzSetIdle", native_subghzSetIdle, 1); + registerLightFunction(ctx, "subghzRead", native_subghzRead, 0); + registerLightFunction(ctx, "subghzReadRaw", native_subghzReadRaw, 0); + registerLightFunction(ctx, "subghzSetFrequency", native_subghzSetFrequency, 1); + // registerLightFunction(ctx, "subghzSetIdle", native_subghzSetIdle, 1); // TODO: subghzTransmit(string) // Dialog functions - registerFunction(ctx, "dialogMessage", native_dialogMessage, 1); - registerFunction(ctx, "dialogError", native_dialogError, 1); + registerLightFunction(ctx, "dialogMessage", native_dialogMessage, 1); + registerLightFunction(ctx, "dialogError", native_dialogError, 1); // TODO: dialogYesNo() - registerFunction(ctx, "dialogPickFile", native_dialogPickFile, 1); - registerFunction(ctx, "dialogChoice", native_dialogChoice, 1); - registerFunction(ctx, "dialogViewFile", native_dialogViewFile, 1); - registerFunction(ctx, "keyboard", native_keyboard, 3); + registerLightFunction(ctx, "dialogPickFile", native_dialogPickFile, 1); + registerLightFunction(ctx, "dialogChoice", native_dialogChoice, 1); + registerLightFunction(ctx, "dialogViewFile", native_dialogViewFile, 1); + registerLightFunction(ctx, "keyboard", native_keyboard, 3); // Storage functions - registerFunction(ctx, "storageRead", native_storageRead, 1); - registerFunction(ctx, "storageWrite", native_storageWrite, 2); + registerLightFunction(ctx, "storageRead", native_storageRead, 1); + registerLightFunction(ctx, "storageWrite", native_storageWrite, 2); // TODO: wrap more serial storage cmd: mkdir, remove, ... // Globals @@ -1178,7 +1267,7 @@ bool interpreter() { bool r; - duk_push_string(ctx, script.c_str()); + duk_push_string(ctx, script); if (duk_peval(ctx) != 0) { tft.fillScreen(bruceConfig.bgColor); tft.setTextSize(FM); @@ -1186,7 +1275,7 @@ bool interpreter() { tft.drawCentreString("Error", tftWidth / 2, 10, 1); tft.setTextColor(TFT_WHITE, bruceConfig.bgColor); tft.setTextSize(FP); - tft.setCursor(0,33); + tft.setCursor(0, 33); tft.println(duk_safe_to_string(ctx, -1)); printf("eval failed: %s\n", duk_safe_to_string(ctx, -1)); @@ -1198,6 +1287,11 @@ bool interpreter() { printf("result is: %s\n", duk_safe_to_string(ctx, -1)); r = true; } + if (isScriptDynamic) { + free((char *)script); + script = "drawString('Something wrong.', 4, 4);"; + isScriptDynamic = false; + } duk_pop(ctx); // Clean up. @@ -1230,12 +1324,11 @@ void run_bjs_script() { // To stop the script, press Prev and Next together for a few seconds } -bool run_bjs_script_headless(String code) { +bool run_bjs_script_headless(const char *code) { script = code; + isScriptDynamic = true; returnToMenu=true; interpreter_start=true; - interpreter(); - interpreter_start=false; return true; } diff --git a/src/modules/bjs_interpreter/interpreter.h b/src/modules/bjs_interpreter/interpreter.h index f9816047b..92c28bdf7 100644 --- a/src/modules/bjs_interpreter/interpreter.h +++ b/src/modules/bjs_interpreter/interpreter.h @@ -15,6 +15,6 @@ void run_bjs_script(); bool interpreter(); -bool run_bjs_script_headless(String code); +bool run_bjs_script_headless(const char *code); bool run_bjs_script_headless(FS fs, String filename); diff --git a/src/modules/ble/bad_ble.cpp b/src/modules/ble/bad_ble.cpp index bf8268a03..4e3d26985 100644 --- a/src/modules/ble/bad_ble.cpp +++ b/src/modules/ble/bad_ble.cpp @@ -271,6 +271,7 @@ void ble_setup() { {"da-DK", [=]() { chooseKb_ble(KeyboardLayout_da_DK); }}, {"hu-HU", [=]() { chooseKb_ble(KeyboardLayout_hu_HU); }}, {"tr-TR", [=]() { chooseKb_ble(KeyboardLayout_tr_TR); }}, + {"pl-PL", [=]() { chooseKb_ble(KeyboardLayout_en_US); }}, {"Main Menu", [=]() { returnToMenu=true; }}, }; index=loopOptions(options,false,true,"Keyboard Layout",index); // It will ask for the keyboard each time, but will save the last chosen to be faster @@ -360,6 +361,7 @@ void ble_keyboard() { {"da-DK", [=]() { chooseKb_ble(KeyboardLayout_da_DK); }}, {"hu-HU", [=]() { chooseKb_ble(KeyboardLayout_hu_HU); }}, {"tr-TR", [=]() { chooseKb_ble(KeyboardLayout_tr_TR); }}, + {"pl-PL", [=]() { chooseKb_ble(KeyboardLayout_en_US); }}, {"Main Menu", [=]() { returnToMenu = true; }}, }; loopOptions(options,false,true,"Keyboard Layout"); diff --git a/src/modules/ir/TV-B-Gone.cpp b/src/modules/ir/TV-B-Gone.cpp index 36e16cdfd..6a09cbb89 100644 --- a/src/modules/ir/TV-B-Gone.cpp +++ b/src/modules/ir/TV-B-Gone.cpp @@ -194,7 +194,7 @@ void StartTvBGone() { delay_ten_us(MAX_WAIT_TIME); // wait 655.350ms delay_ten_us(MAX_WAIT_TIME); // wait 655.350ms } else { - displayRedStripe("User Stoped"); + displayRedStripe("User Stopped"); delay(2000); } diff --git a/src/modules/others/bad_usb.cpp b/src/modules/others/bad_usb.cpp index 8a606eb7b..89fb13b3a 100644 --- a/src/modules/others/bad_usb.cpp +++ b/src/modules/others/bad_usb.cpp @@ -280,6 +280,7 @@ void usb_setup() { {"Danish (Denmark)", [=]() { chooseKb(KeyboardLayout_da_DK); }}, {"Hungarian (Hungary)", [=]() { chooseKb(KeyboardLayout_hu_HU); }}, {"Turkish (Turkey)", [=]() { chooseKb(KeyboardLayout_tr_TR); }}, + {"Polish (Poland)", [=]() { chooseKb(KeyboardLayout_en_US); }}, }; loopOptions(options,false,true,"Keyboard Layout"); @@ -381,6 +382,7 @@ void usb_keyboard() { {"da-DK", [=]() { chooseKb(KeyboardLayout_da_DK); }}, {"hu-HU", [=]() { chooseKb(KeyboardLayout_hu_HU); }}, {"tr-TR", [=]() { chooseKb(KeyboardLayout_tr_TR); }}, + {"pl-PL", [=]() { chooseKb(KeyboardLayout_en_US); }}, {"Main Menu", [=]() { returnToMenu=true; }}, }; diff --git a/src/modules/others/webInterface.cpp b/src/modules/others/webInterface.cpp index b9808f6d2..be659424e 100644 --- a/src/modules/others/webInterface.cpp +++ b/src/modules/others/webInterface.cpp @@ -111,7 +111,8 @@ String listFiles(FS fs, bool ishtml, String folder, bool isLittleFS) { if (String(foundfile.name()).substring(String(foundfile.name()).lastIndexOf('.') + 1).equalsIgnoreCase("enc")) returnText+= "  \n"; #endif returnText += "  \n"; - returnText += "\n\n"; + returnText += "  \n"; + returnText += "\n\n"; } else { returnText += "File: " + String(foundfile.name()) + " Size: " + humanReadableSize(foundfile.size()) + "\n"; } @@ -411,6 +412,15 @@ server->on("/script.js", HTTP_GET, []() { } else { server->send(200, "text/plain", "FAIL creating folder: " + String(fileName)); } + } + else if (strcmp(fileAction.c_str(), "createfile") == 0) { + File newFile = (*fs).open(fileName, FILE_WRITE, true); + if (newFile) { + newFile.close(); + server->send(200, "text/plain", "Created new file: " + String(fileName)); + } else { + server->send(200, "text/plain", "FAIL creating file: " + String(fileName)); + } } else server->send(400, "text/plain", "ERROR: file does not exist"); } else { @@ -438,7 +448,26 @@ server->on("/script.js", HTTP_GET, []() { } else { server->send(200, "text/plain", "FAIL creating folder: " + String(fileName)); } - } else { + } else if (strcmp(fileAction.c_str(), "createfile") == 0) { + File newFile = SD.open(fileName, FILE_WRITE, true); + if (newFile) { + newFile.close(); + server->send(200, "text/plain", "Created new file: " + String(fileName)); + } else { + server->send(200, "text/plain", "FAIL creating file: " + String(fileName)); + } + + } else if (strcmp(fileAction.c_str(), "edit") == 0) { + File editFile = (*fs).open(fileName, FILE_READ); + if (editFile) { + String fileContent = editFile.readString(); + server->send(200, "text/plain", fileContent); + editFile.close(); + } else { + server->send(500, "text/plain", "Failed to open file for reading"); + } + + } else { server->send(400, "text/plain", "ERROR: invalid action param supplied"); } } @@ -450,6 +479,43 @@ server->on("/script.js", HTTP_GET, []() { } }); + server->on("/edit", HTTP_POST, [](){ + if (checkUserWebAuth()) { + if (server->hasArg("name") && server->hasArg("content") && server->hasArg("fs")) { + String fileName = server->arg("name"); + String fileContent = server->arg("content"); + bool useSD = false; + + if (strcmp(server->arg("fs").c_str(), "SD") == 0) { + useSD = true; + } + + fs::FS *fs = useSD ? (fs::FS*)&SD : (fs::FS*)&LittleFS; + String fsType = useSD ? "SD" : "LittleFS"; + + if ((useSD && !SD.begin()) || (!useSD && !LittleFS.begin())) { + server->send(500, "text/plain", "Failed to initialize file system: " + fsType); + return; + } + + File editFile = fs->open(fileName, FILE_WRITE); + if (editFile) { + if (editFile.write((const uint8_t*)fileContent.c_str(), fileContent.length())) { + server->send(200, "text/plain", "File edited: " + fileName); + } else { + server->send(500, "text/plain", "Failed to write to file: " + fileName); + } + editFile.close(); + } else { + server->send(500, "text/plain", "Failed to open file for writing: " + fileName); + } + } else { + server->send(400, "text/plain", "ERROR: name, content, and fs parameters required"); + } + } else { + server->requestAuthentication(); + } }); + // Configuração de Wi-Fi via página web server->on("/wifi", HTTP_GET, []() { if (checkUserWebAuth()) { diff --git a/src/modules/others/webInterface.h b/src/modules/others/webInterface.h index f4ce0f8a2..86f81d9d3 100644 --- a/src/modules/others/webInterface.h +++ b/src/modules/others/webInterface.h @@ -18,7 +18,7 @@ void loopOptionsWebUi(); void configureWebServer(); void startWebUi(bool mode_ap = false); -const char index_css[] PROGMEM =R"rawliteral( +const char index_css[] PROGMEM = R"rawliteral( .gg-rename { box-sizing: border-box; position: relative; @@ -197,6 +197,55 @@ const char index_css[] PROGMEM =R"rawliteral( left: 8px; background: currentColor } + + .gg-pen { + box-sizing: border-box; + position: relative; + display: inline-block; + transform: rotate(-45deg) scale(var(--ggs, 1)); + width: 14px; + height: 4px; + border-right: 2px solid transparent; + box-shadow: + 0 0 0 2px, + inset -2px 0 0; + border-top-right-radius: 1px; + border-bottom-right-radius: 1px; + margin-top: 6px; + margin-bottom: 6px; + cursor: pointer; + } + + + .gg-pen::after, + .gg-pen::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + } + + .gg-pen::before { + background: currentColor; + border-left: 0; + right: -6px; + width: 3px; + height: 4px; + border-radius: 1px; + top: 0; + } + + .gg-pen::after { + width: 8px; + height: 7px; + border-top: 4px solid transparent; + border-bottom: 4px solid transparent; + border-right: 7px solid; + left: -11px; + top: -2px; + } + + body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; margin: 0; @@ -304,6 +353,47 @@ const char index_css[] PROGMEM =R"rawliteral( background-color: #303134; color: #ad007c65; } + +.editor-container { + display: none; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: #202124; + z-index: 999; + color: #ff3ec8; + flex-direction: column; +} + +.editor-container div { + padding: 10px; +} + +.editor-container div:first-child { + display: flex; + justify-content: space-between; + padding: 10px; + height: 50px; + border-bottom: 1px solid #7b007b; +} + +.editor-container textarea { + box-sizing: border-box; + background-color: #303134; + color: #ff3ec8; + border: 1px solid #7b007b; + padding: 10px; + font-size: 16px; + height: auto; + font-family: monospace; + width: 100%; + flex: 1; + white-space: pre; + overflow-wrap: normal; + overflow: auto; +} )rawliteral"; const char index_js[] PROGMEM = R"rawliteral( @@ -315,7 +405,7 @@ function WifiConfig() { if (wifiSsid == null || wifiSsid == "" || wifiPwd == null) { window.alert("Invalid User or Password"); } else { - xmlhttp=new XMLHttpRequest(); + xmlhttp = new XMLHttpRequest(); xmlhttp.open("GET", "/wifi?usr=" + wifiSsid + "&pwd=" + wifiPwd, false); xmlhttp.send(); document.getElementById("status").innerHTML = xmlhttp.responseText; @@ -341,33 +431,33 @@ function logoutButton() { var xhr = new XMLHttpRequest(); xhr.open("GET", "/logout", true); xhr.send(); - setTimeout(function(){ window.open("/logged-out","_self"); }, 500); + setTimeout(function () { window.open("/logged-out", "_self"); }, 500); } function rebootButton() { - if(confirm("Confirm Restart?!")) { - xmlhttp=new XMLHttpRequest(); + if (confirm("Confirm Restart?!")) { + xmlhttp = new XMLHttpRequest(); var xhr = new XMLHttpRequest(); xhr.open("GET", "/reboot", true); xhr.send(); - } + } } function listFilesButton(folders, fs = 'LittleFS', userRequest = false) { - xmlhttp=new XMLHttpRequest(); + xmlhttp = new XMLHttpRequest(); document.getElementById("actualFolder").value = ""; document.getElementById("actualFolder").value = folders; document.getElementById("actualFS").value = fs; - xmlhttp.onload = function() { - if (xmlhttp.status === 200) { - document.getElementById("details").innerHTML = xmlhttp.responseText; - } else { - console.error('Erro na requisição: ' + xmlhttp.status); - } + xmlhttp.onload = function () { + if (xmlhttp.status === 200) { + document.getElementById("details").innerHTML = xmlhttp.responseText; + } else { + console.error('Requests Error: ' + xmlhttp.status); + } }; - xmlhttp.onerror = function() { - console.error('Erro na rede ou falha na requisição.'); + xmlhttp.onerror = function () { + console.error('Erro na rede ou falha na requisição.'); }; xmlhttp.open("GET", "/listfiles?fs=" + fs + "&folder=" + folders, true); @@ -382,7 +472,7 @@ function listFilesButton(folders, fs = 'LittleFS', userRequest = false) { document.getElementById("detailsheader").innerHTML = "

LittleFS Files

"; } - document.getElementById("updetailsheader").innerHTML = "

Folder Actions:

" + document.getElementById("updetailsheader").innerHTML = "

Folder Actions:

" document.getElementById("updetails").innerHTML = ""; _("drop-area").style.display = "block"; buttonsInitialized = true; @@ -390,7 +480,7 @@ function listFilesButton(folders, fs = 'LittleFS', userRequest = false) { } } else { if (userRequest) { - if (fs == 'SD') { + if (fs == 'SD') { document.getElementById("detailsheader").innerHTML = "

SD Files

"; } else if (fs == 'LittleFS') { document.getElementById("detailsheader").innerHTML = "

LittleFS Files

"; @@ -423,7 +513,7 @@ function renameFile(filePath, oldName) { } function sendIrFile(filePath) { - if(!confirm("Confirm spamming all codes inside the file?")) return; + if (!confirm("Confirm spamming all codes inside the file?")) return; var actualFolder = document.getElementById("actualFolder").value; var fs = document.getElementById("actualFS").value; const ajax5 = new XMLHttpRequest(); @@ -437,7 +527,7 @@ function sendIrFile(filePath) { } function sendSubFile(filePath) { - if(!confirm("Confirm sending the codes inside the file?")) return; + if (!confirm("Confirm sending the codes inside the file?")) return; var actualFolder = document.getElementById("actualFolder").value; var fs = document.getElementById("actualFS").value; const ajax5 = new XMLHttpRequest(); @@ -451,7 +541,7 @@ function sendSubFile(filePath) { } function runJsFile(filePath) { - if(!confirm("Confirm executing the selected JS script?")) return; + if (!confirm("Confirm executing the selected JS script?")) return; var actualFolder = document.getElementById("actualFolder").value; var fs = document.getElementById("actualFS").value; const ajax5 = new XMLHttpRequest(); @@ -465,7 +555,7 @@ function runJsFile(filePath) { } function runBadusbFile(filePath) { - if(!confirm("Confirm executing the selected DuckyScript on the machine connected via USB?")) return; + if (!confirm("Confirm executing the selected DuckyScript on the machine connected via USB?")) return; var actualFolder = document.getElementById("actualFolder").value; var fs = document.getElementById("actualFS").value; const ajax5 = new XMLHttpRequest(); @@ -479,9 +569,9 @@ function runBadusbFile(filePath) { } function decryptAndType(filePath) { - if(!confirm("Type decrypted file contents on the machine connected via USB?")) return; - if(!cachedPassword) cachedPassword = prompt("Enter decryption password: ", cachedPassword); - if(!cachedPassword) return; // cancelled + if (!confirm("Type decrypted file contents on the machine connected via USB?")) return; + if (!cachedPassword) cachedPassword = prompt("Enter decryption password: ", cachedPassword); + if (!cachedPassword) return; // cancelled var actualFolder = document.getElementById("actualFolder").value; var fs = document.getElementById("actualFS").value; const ajax5 = new XMLHttpRequest(); @@ -494,6 +584,7 @@ function decryptAndType(filePath) { listFilesButton(actualFolder, fs, true); } function downloadDeleteButton(filename, action) { + /* fs actions: create (folder), createfile, delete, download */ var fs = document.getElementById("actualFS").value; var urltocall = "/file?name=" + filename + "&action=" + action + "&fs=" + fs; var actualFolder = document.getElementById("actualFolder").value; @@ -502,53 +593,98 @@ function downloadDeleteButton(filename, action) { option = confirm("Do you really want to DELETE the file: " + filename + " ?\n\nThis action can't be undone!"); } - xmlhttp=new XMLHttpRequest(); - if (option == true || action=="create") { + xmlhttp = new XMLHttpRequest(); + if (option == true || action == "create" || action == "createfile") { xmlhttp.open("GET", urltocall, false); xmlhttp.send(); document.getElementById("status").innerHTML = xmlhttp.responseText; var fs = document.getElementById("actualFS").value; - listFilesButton(actualFolder, fs,true); + listFilesButton(actualFolder, fs, true); + } + + if (action == "edit") { + xmlhttp.open("GET", urltocall, false); + xmlhttp.send(); + + if (xmlhttp.status === 200) { + document.getElementById("editor").value = xmlhttp.responseText; + document.getElementById("editor-file").innerHTML = filename; + document.querySelector('.editor-container').style.display = 'flex'; + } else { + console.error('Requests Error: ' + xmlhttp.status); + } } + if (action == "download") { document.getElementById("status").innerHTML = ""; - window.open(urltocall,"_blank"); + window.open(urltocall, "_blank"); } } + +function cancelEdit() { + document.querySelector('.editor-container').style.display = 'none'; + document.getElementById("editor").value = ""; + document.getElementById("status").innerHTML = ""; +} + function showCreateFolder(folders) { var fs = document.getElementById("actualFS").value; var uploadform = ""; //document.getElementById("updetailsheader").innerHTML = "

Create new Folder

" document.getElementById("status").innerHTML = ""; uploadform = - "

Creating folder at: " + folders + ""+ - "" + - "" + - "" + - "

"; + "

Creating folder at: " + folders + "" + + "" + + "" + + "" + + "

"; document.getElementById("updetails").innerHTML = uploadform; } + + function CreateFolder() { var folderName = ""; folderName = document.getElementById("folder").value + "/" + document.getElementById("foldername").value; downloadDeleteButton(folderName, 'create'); } +function showCreateFile(folders) { + var fs = document.getElementById("actualFS").value; + var uploadform = ""; + //document.getElementById("updetailsheader").innerHTML = "

Create new File

" + document.getElementById("status").innerHTML = ""; + uploadform = + "

Creating file at: " + folders + "" + + "" + + "" + + "" + + "

"; + document.getElementById("updetails").innerHTML = uploadform; +} + + +function CreateFile() { + var fileName = ""; + fileName = document.getElementById("folder").value + "/" + document.getElementById("filename").value; + downloadDeleteButton(fileName, 'createfile'); +} + + function showUploadButtonFancy(folders) { //document.getElementById("updetailsheader").innerHTML = "

Upload File

" document.getElementById("status").innerHTML = ""; var uploadform = - "

Send file to " + folders + "

"+ - "
" + - "" + - " Encrypted
" + - "
" + - "" + - "

" + - "

" + - "
"; + "

Send file to " + folders + "

" + + "
" + + "" + + " Encrypted
" + + "
" + + "" + + "

" + + "

" + + "
"; document.getElementById("updetails").innerHTML = uploadform; } @@ -556,17 +692,17 @@ function _(el) { return document.getElementById(el); } -var cachedPassword=""; +var cachedPassword = ""; function uploadFile(folder) { var fs = document.getElementById("actualFS").value; var folder = _("folder").value; var files = _("file1").files; // Extract files from input element - + var formdata = new FormData(); - + var encrypted = _("encryptCheckbox").checked; - if(encrypted) { + if (encrypted) { cachedPassword = prompt("Enter encryption password (do not lose it, cannot be recovered): ", cachedPassword); formdata.append("password", cachedPassword); } @@ -585,8 +721,29 @@ function uploadFile(folder) { ajax.send(formdata); } + +function saveFile() { + var fs = document.getElementById("actualFS").value; + var folder = document.getElementById("actualFolder").value; + var fileName = document.getElementById("editor-file").innerText; + var fileContent = document.getElementById("editor").value; + + const formdata = new FormData(); + formdata.append("fs", fs); + formdata.append("name", fileName); + formdata.append("content", fileContent); + + const ajax5 = new XMLHttpRequest(); + ajax5.open("POST", "/edit", false); + ajax5.send(formdata); + + document.getElementById("status").innerText = ajax5.responseText; + listFilesButton(folder, fs, true); +} + + // Drag and drop event listeners -window.addEventListener("load", function() { +window.addEventListener("load", function () { var dropArea = _("drop-area"); dropArea.addEventListener("dragenter", dragEnter, false); dropArea.addEventListener("dragover", dragOver, false); @@ -614,49 +771,49 @@ function dragLeave(event) { var fileQueue = []; var currentFileIndex = 0; - function drop(event, folder) { - event.stopPropagation(); - event.preventDefault(); - _("drop-area").classList.remove("highlight"); +function drop(event, folder) { + event.stopPropagation(); + event.preventDefault(); + _("drop-area").classList.remove("highlight"); - fileQueue = event.dataTransfer.files; - currentFileIndex = 0; - var fs = document.getElementById("actualFS").value; + fileQueue = event.dataTransfer.files; + currentFileIndex = 0; + var fs = document.getElementById("actualFS").value; - var uploadform = - "

Send file to " + folder + "

"+ + var uploadform = + "

Send file to " + folder + "

" + "
" + "" + "

" + "

" + "
"; - document.getElementById("updetails").innerHTML = uploadform; + document.getElementById("updetails").innerHTML = uploadform; - if (fileQueue.length > 0) { - uploadNextFile(folder, fs); - } + if (fileQueue.length > 0) { + uploadNextFile(folder, fs); } +} - function uploadNextFile(folder, fs) { - if (currentFileIndex >= fileQueue.length) { - console.log("Todos os arquivos foram enviados."); - listFilesButton(folder, fs, true); - return; - } +function uploadNextFile(folder, fs) { + if (currentFileIndex >= fileQueue.length) { + console.log("Upload complete"); + listFilesButton(folder, fs, true); + return; + } - var file = fileQueue[currentFileIndex]; - var formdata = new FormData(); - formdata.append("file", file); - formdata.append("folder", folder); + var file = fileQueue[currentFileIndex]; + var formdata = new FormData(); + formdata.append("file", file); + formdata.append("folder", folder); - var ajax = new XMLHttpRequest(); - ajax.upload.addEventListener("progress", progressHandler, false); - ajax.addEventListener("load", completeHandler, false); - ajax.addEventListener("error", errorHandler, false); - ajax.addEventListener("abort", abortHandler, false); - ajax.open("POST", "/upload" + fs); - ajax.send(formdata); - } + var ajax = new XMLHttpRequest(); + ajax.upload.addEventListener("progress", progressHandler, false); + ajax.addEventListener("load", completeHandler, false); + ajax.addEventListener("error", errorHandler, false); + ajax.addEventListener("abort", abortHandler, false); + ajax.open("POST", "/upload" + fs); + ajax.send(formdata); +} function progressHandler(event) { _("loaded_n_total").innerHTML = "Uploaded " + event.loaded + " bytes"; @@ -669,43 +826,91 @@ function progressHandler(event) { function completeHandler(event) { _("progressBar").value = 0; if (fileQueue.length > 0) { - currentFileIndex++; + currentFileIndex++; if (currentFileIndex <= fileQueue.length) { - document.getElementById("status").innerHTML = "Uploaded " + currentFileIndex + " of " + fileQueue.length + " files."; + document.getElementById("status").innerHTML = "Uploaded " + currentFileIndex + " of " + fileQueue.length + " files."; } - uploadNextFile(document.getElementById("actualFolder").value, document.getElementById("actualFS").value); - } - else { - _("status").innerHTML = "Upload Complete"; - var actualFolder = document.getElementById("actualFolder").value - document.getElementById("status").innerHTML = "File Uploaded"; - var fs = document.getElementById("actualFS").value; - listFilesButton(actualFolder, fs, true); - } + uploadNextFile(document.getElementById("actualFolder").value, document.getElementById("actualFS").value); + } + else { + _("status").innerHTML = "Upload Complete"; + var actualFolder = document.getElementById("actualFolder").value + document.getElementById("status").innerHTML = "File Uploaded"; + var fs = document.getElementById("actualFS").value; + listFilesButton(actualFolder, fs, true); + } } function errorHandler(event) { _("status").innerHTML = "Upload Failed"; - if (fileQueue.length > 0) { - currentFileIndex++; - document.getElementById("status").innerHTML = "Uploaded " + i + " of " + files.length + " files, please wait."; - uploadNextFile(document.getElementById("actualFolder").value, document.getElementById("actualFS").value); - } + if (fileQueue.length > 0) { + currentFileIndex++; + document.getElementById("status").innerHTML = "Uploaded " + i + " of " + files.length + " files, please wait."; + uploadNextFile(document.getElementById("actualFolder").value, document.getElementById("actualFS").value); + } } function abortHandler(event) { _("status").innerHTML = "inUpload Aborted"; - if (fileQueue.length > 0) { - currentFileIndex++; - document.getElementById("status").innerHTML = "Uploaded " + i + " of " + files.length + " files, please wait."; - uploadNextFile(document.getElementById("actualFolder").value, document.getElementById("actualFS").value); - } + if (fileQueue.length > 0) { + currentFileIndex++; + document.getElementById("status").innerHTML = "Uploaded " + i + " of " + files.length + " files, please wait."; + uploadNextFile(document.getElementById("actualFolder").value, document.getElementById("actualFS").value); + } } -window.addEventListener("load", function() { +window.addEventListener("load", function () { var actualFolder = document.getElementById("actualFolder").value var fs = document.getElementById("actualFS").value; document.getElementById("status").innerHTML = "Please select the storage you want to manage (SD or LittleFS)."; listFilesButton(actualFolder, fs, true); }); + + +document.getElementById("editor").addEventListener("keydown", function (e) { + if (e.key === 's' && e.ctrlKey) { + e.preventDefault(); + saveFile(); + } + + // tab + if (e.key === 'Tab') { + e.preventDefault(); + var cursorPos = document.getElementById("editor").selectionStart; + var textBefore = document.getElementById("editor").value.substring(0, cursorPos); + var textAfter = document.getElementById("editor").value.substring(cursorPos); + document.getElementById("editor").value = textBefore + " " + textAfter; + document.getElementById("editor").selectionStart = cursorPos + 2; + document.getElementById("editor").selectionEnd = cursorPos + 2; + } + +}); + +document.getElementById("editor").addEventListener("keyup", function (e) { + if (e.key === 'Escape') { + cancelEdit(); + } + + // map special characters to their closing pair + map_chars = { + "(": ")", + "{": "}", + "[": "]", + '"': '"', + "'": "'", + "`": "`", + "<": ">" + }; + + // if the key pressed is a special character, insert the closing pair + if (e.key in map_chars) { + var cursorPos = document.getElementById("editor").selectionStart; + var textBefore = document.getElementById("editor").value.substring(0, cursorPos); + var textAfter = document.getElementById("editor").value.substring(cursorPos); + document.getElementById("editor").value = textBefore + map_chars[e.key] + textAfter; + document.getElementById("editor").selectionStart = cursorPos; + document.getElementById("editor").selectionEnd = cursorPos; + } + +}); )rawliteral"; const char index_html[] PROGMEM = R"rawliteral( @@ -744,6 +949,23 @@ const char index_html[] PROGMEM = R"rawliteral(

Drag and drop files here

+ +
+
+ +

WebUi Editor

+ +
+
+ file: +
+ +
+ + +
+
+ diff --git a/src/modules/rf/rf.cpp b/src/modules/rf/rf.cpp index 4bfcc073f..f64fc2773 100644 --- a/src/modules/rf/rf.cpp +++ b/src/modules/rf/rf.cpp @@ -44,15 +44,21 @@ struct Protocol { }; -// Global to magane rmt installation.. if it is installed twice, it breakes -bool RxRF = false; bool sendRF = false; RfCodes recent_rfcodes[16]; // TODO: save/load in EEPROM int recent_rfcodes_last_used = 0; // TODO: save/load in EEPROM +void deinitRMT() { + // Deinit RMT channels + for (int i = 0; i < RMT_CHANNEL_MAX; i++) { + ESP_ERROR_CHECK_WITHOUT_ABORT(rmt_driver_uninstall((rmt_channel_t)i)); + } +} void initRMT() { + deinitRMT(); + rmt_config_t rxconfig; rxconfig.rmt_mode = RMT_MODE_RX; rxconfig.channel = RMT_RX_CHANNEL; @@ -67,27 +73,33 @@ void initRMT() { rxconfig.rx_config.idle_threshold = 3 * RMT_1MS_TICKS, rxconfig.rx_config.filter_ticks_thresh = 200 * RMT_1US_TICKS; rxconfig.rx_config.filter_en = true; - if(!RxRF) { //If spectrum had beed started before, it won't reinstall the driver to prevent mem alloc fail and restart. - ESP_ERROR_CHECK(rmt_config(&rxconfig)); - ESP_ERROR_CHECK(rmt_driver_install(rxconfig.channel, 2048, 0)); - RxRF=true; - } + + ESP_ERROR_CHECK(rmt_config(&rxconfig)); + ESP_ERROR_CHECK_WITHOUT_ABORT(rmt_driver_install(rxconfig.channel, 2048, 0)); } void rf_spectrum() { //@IncursioHack - https://github.com/IncursioHack ----thanks @aat440hz - RF433ANY-M5Cardputer - + RingbufHandle_t rb = nullptr; tft.fillScreen(bruceConfig.bgColor); tft.setTextSize(1); tft.println(""); tft.println(" RF - Spectrum"); + +#ifdef FASTLED_RMT_BUILTIN_DRIVER + bool run_twice=false; + RUN_AGAIN: +#endif if(!initRfModule("rx", bruceConfig.rfFreq)) return; initRMT(); - - RingbufHandle_t rb = nullptr; rmt_get_ringbuf_handle(RMT_RX_CHANNEL, &rb); rmt_rx_start(RMT_RX_CHANNEL, true); + +#ifdef FASTLED_RMT_BUILTIN_DRIVER + if(!run_twice) { run_twice=true; goto RUN_AGAIN; } +#endif + while (rb) { size_t rx_size = 0; rmt_item32_t* item = (rmt_item32_t*)xRingbufferReceive(rb, &rx_size, 500); @@ -114,6 +126,7 @@ void rf_spectrum() { //@IncursioHack - https://github.com/IncursioHack ----thank } returnToMenu=true; rmt_rx_stop(RMT_RX_CHANNEL); + deinitRMT(); delay(10); } @@ -1406,7 +1419,7 @@ void rf_scan_copy() { char hexString[64]; int signals = 0, idx = range_limits[bruceConfig.rfScanRange][0]; float found_freq = 0.f, frequency = 0.f; - int rssi=-80, rssiThreshold = -55; + int rssi=-80, rssiThreshold = -65; FreqFound _freqs[_MAX_TRIES]; // get the best RSSI out of 5 tries bool ReadRAW=true; @@ -1611,6 +1624,7 @@ void rf_scan_copy() { options.push_back({ "Reset Signal", [&]() { option = 3; } }); } if(bruceConfig.rfModule==CC1101_SPI_MODULE) options.push_back({ "Range", [&]() { option = 1; } }); + if(bruceConfig.rfModule==CC1101_SPI_MODULE && !bruceConfig.rfFxdFreq) options.push_back({ "Threshold", [&]() { option = 4; } }); if(ReadRAW) options.push_back({ "Stop RAW", [&]() { ReadRAW=false; } }); else options.push_back({ "Read RAW", [&]() { ReadRAW=true; } }); @@ -1687,7 +1701,19 @@ void rf_scan_copy() { deinitRfModule(); delay(1500); goto RestartScan; - } + } else if (option == 4) { // rssiThreshold to detect frequency + option=0; + options = { + { "(-55) More Accurate", [&]() { rssiThreshold=-55; } }, + { "(-60)", [&]() { rssiThreshold=-60; } }, + { "(-65) Default ", [&]() { rssiThreshold=-65; } }, + { "(-70)", [&]() { rssiThreshold=-70; } }, + { "(-75)", [&]() { rssiThreshold=-75; } }, + { "(-80) Less Accurate", [&]() { rssiThreshold=-80; } }, + }; + loopOptions(options); + goto RestartScan; + } } ++idx; } diff --git a/src/modules/wifi/sniffer.cpp b/src/modules/wifi/sniffer.cpp index 75052ad86..338117f8c 100644 --- a/src/modules/wifi/sniffer.cpp +++ b/src/modules/wifi/sniffer.cpp @@ -329,7 +329,7 @@ void sniffer_setup() { long deauth_tmp=0; drawMainBorderWithTitle("RAW SNIFFER"); - closeSdCard(); + //closeSdCard(); _only_HS=true; // default mode to start if it doesn't have SD Cadr if(setupSdCard()) {