Merge branch 'ofw-dev' into dev

This commit is contained in:
MX 2023-07-18 22:53:16 +03:00
commit 2f532a547e
No known key found for this signature in database
GPG Key ID: 7CCC66B7DBDD1C83
25 changed files with 699 additions and 283 deletions

View File

@ -4,13 +4,13 @@
"version": "2.0.0", "version": "2.0.0",
"tasks": [ "tasks": [
{ {
"label": "[Release] Build", "label": "[Release] Build Firmware",
"group": "build", "group": "build",
"type": "shell", "type": "shell",
"command": "./fbt COMPACT=1 DEBUG=0" "command": "./fbt COMPACT=1 DEBUG=0"
}, },
{ {
"label": "[Debug] Build", "label": "[Debug] Build Firmware",
"group": "build", "group": "build",
"type": "shell", "type": "shell",
"command": "./fbt" "command": "./fbt"
@ -123,17 +123,29 @@
"type": "shell", "type": "shell",
"command": "./fbt COMPACT=1 DEBUG=0 fap_dist" "command": "./fbt COMPACT=1 DEBUG=0 fap_dist"
}, },
{
"label": "[Debug] Build App",
"group": "build",
"type": "shell",
"command": "./fbt build APPSRC=${relativeFileDirname}"
},
{
"label": "[Release] Build App",
"group": "build",
"type": "shell",
"command": "./fbt COMPACT=1 DEBUG=0 build APPSRC=${relativeFileDirname}"
},
{ {
"label": "[Debug] Launch App on Flipper", "label": "[Debug] Launch App on Flipper",
"group": "build", "group": "build",
"type": "shell", "type": "shell",
"command": "./fbt launch_app APPSRC=${relativeFileDirname}" "command": "./fbt launch APPSRC=${relativeFileDirname}"
}, },
{ {
"label": "[Release] Launch App on Flipper", "label": "[Release] Launch App on Flipper",
"group": "build", "group": "build",
"type": "shell", "type": "shell",
"command": "./fbt COMPACT=1 DEBUG=0 launch_app APPSRC=${relativeFileDirname}" "command": "./fbt COMPACT=1 DEBUG=0 launch APPSRC=${relativeFileDirname}"
}, },
{ {
"label": "[Debug] Launch App on Flipper with Serial Console", "label": "[Debug] Launch App on Flipper with Serial Console",

View File

@ -18,7 +18,7 @@ Before launching the application, connect the sensor to Flipper's external GPIO
In order to launch this demo, follow the steps below: In order to launch this demo, follow the steps below:
1. Make sure your Flipper has an SD card installed. 1. Make sure your Flipper has an SD card installed.
2. Connect your Flipper to the computer via a USB cable. 2. Connect your Flipper to the computer via a USB cable.
3. Run `./fbt launch_app APPSRC=example_thermo` in your terminal emulator of choice. 3. Run `./fbt launch APPSRC=example_thermo` in your terminal emulator of choice.
## Changing the data pin ## Changing the data pin
It is possible to use other GPIO pin as a 1-Wire data pin. In order to change it, set the `THERMO_GPIO_PIN` macro to any of the options listed below: It is possible to use other GPIO pin as a 1-Wire data pin. In order to change it, set the `THERMO_GPIO_PIN` macro to any of the options listed below:

View File

@ -300,6 +300,7 @@ static bool power_update_info(Power* power) {
info.is_charging = furi_hal_power_is_charging(); info.is_charging = furi_hal_power_is_charging();
info.gauge_is_ok = furi_hal_power_gauge_is_ok(); info.gauge_is_ok = furi_hal_power_gauge_is_ok();
info.is_shutdown_requested = furi_hal_power_is_shutdown_requested();
info.charge = furi_hal_power_get_pct(); info.charge = furi_hal_power_get_pct();
info.health = furi_hal_power_get_bat_health_pct(); info.health = furi_hal_power_get_bat_health_pct();
info.capacity_remaining = furi_hal_power_get_battery_remaining_capacity(); info.capacity_remaining = furi_hal_power_get_battery_remaining_capacity();
@ -328,7 +329,7 @@ static void power_check_low_battery(Power* power) {
} }
// Check battery charge and vbus voltage // Check battery charge and vbus voltage
if((power->info.charge == 0) && (power->info.voltage_vbus < 4.0f) && if((power->info.is_shutdown_requested) && (power->info.voltage_vbus < 4.0f) &&
power->show_low_bat_level_message) { power->show_low_bat_level_message) {
if(!power->battery_low) { if(!power->battery_low) {
view_dispatcher_send_to_front(power->view_dispatcher); view_dispatcher_send_to_front(power->view_dispatcher);

View File

@ -37,6 +37,7 @@ typedef struct {
typedef struct { typedef struct {
bool gauge_is_ok; bool gauge_is_ok;
bool is_charging; bool is_charging;
bool is_shutdown_requested;
float current_charger; float current_charger;
float current_gauge; float current_gauge;

View File

@ -54,8 +54,7 @@ static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) {
(uint32_t)(data->vbus_voltage * 10) % 10, (uint32_t)(data->vbus_voltage * 10) % 10,
current); current);
} else if(current < -5) { } else if(current < -5) {
// Often gauge reports anything in the range 1~5ma as 5ma // 0-5ma deadband
// That brings confusion, so we'll treat it as Napping
snprintf( snprintf(
emote, emote,
sizeof(emote), sizeof(emote),

View File

@ -13,7 +13,8 @@ FAPs are created and developed the same way as internal applications that are pa
To build your application as a FAP, create a folder with your app's source code in `applications_user`, then write its code the way you'd do when creating a regular built-in application. Then configure its `application.fam` manifest, and set its _apptype_ to FlipperAppType.EXTERNAL. See [Application Manifests](./AppManifests.md#application-definition) for more details. To build your application as a FAP, create a folder with your app's source code in `applications_user`, then write its code the way you'd do when creating a regular built-in application. Then configure its `application.fam` manifest, and set its _apptype_ to FlipperAppType.EXTERNAL. See [Application Manifests](./AppManifests.md#application-definition) for more details.
- To build your application, run `./fbt fap_{APPID}`, where APPID is your application's ID in its manifest. - To build your application, run `./fbt fap_{APPID}`, where APPID is your application's ID in its manifest.
- To build your app and upload it over USB to run on Flipper, use `./fbt launch_app APPSRC=applications_user/path/to/app`. This command is configured in the default [VS Code profile](../.vscode/ReadMe.md) as a "Launch App on Flipper" build action (Ctrl+Shift+B menu). - To build your app and upload it over USB to run on Flipper, use `./fbt launch APPSRC=applications_user/path/to/app`. This command is configured in the default [VS Code profile](../.vscode/ReadMe.md) as a "Launch App on Flipper" build action (Ctrl+Shift+B menu).
- To build an app without uploading it to Flipper, use `./fbt build APPSRC=applications_user/path/to/app`. This command is also availabe in VSCode configuration as "Build App".
- To build all FAPs, run `./fbt faps` or `./fbt fap_dist`. - To build all FAPs, run `./fbt faps` or `./fbt fap_dist`.
## FAP assets ## FAP assets

View File

@ -1,5 +1,5 @@
entry,status,name,type,params entry,status,name,type,params
Version,+,34.2,, Version,+,34.3,,
Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,, Header,+,applications/services/cli/cli_vcp.h,,
@ -36,7 +36,6 @@ Header,+,applications/services/notification/notification_messages.h,,
Header,+,applications/services/power/power_service/power.h,, Header,+,applications/services/power/power_service/power.h,,
Header,+,applications/services/rpc/rpc_app.h,, Header,+,applications/services/rpc/rpc_app.h,,
Header,+,applications/services/storage/storage.h,, Header,+,applications/services/storage/storage.h,,
Header,-,firmware/targets/f18/furi_hal/furi_hal_power_calibration.h,,
Header,+,firmware/targets/f18/furi_hal/furi_hal_resources.h,, Header,+,firmware/targets/f18/furi_hal/furi_hal_resources.h,,
Header,+,firmware/targets/f18/furi_hal/furi_hal_spi_config.h,, Header,+,firmware/targets/f18/furi_hal/furi_hal_spi_config.h,,
Header,+,firmware/targets/f18/furi_hal/furi_hal_target_hw.h,, Header,+,firmware/targets/f18/furi_hal/furi_hal_target_hw.h,,
@ -1148,6 +1147,7 @@ Function,-,furi_hal_power_insomnia_level,uint16_t,
Function,+,furi_hal_power_is_charging,_Bool, Function,+,furi_hal_power_is_charging,_Bool,
Function,+,furi_hal_power_is_charging_done,_Bool, Function,+,furi_hal_power_is_charging_done,_Bool,
Function,+,furi_hal_power_is_otg_enabled,_Bool, Function,+,furi_hal_power_is_otg_enabled,_Bool,
Function,+,furi_hal_power_is_shutdown_requested,_Bool,
Function,+,furi_hal_power_off,void, Function,+,furi_hal_power_off,void,
Function,+,furi_hal_power_reset,void, Function,+,furi_hal_power_reset,void,
Function,+,furi_hal_power_set_battery_charge_voltage_limit,void,float Function,+,furi_hal_power_set_battery_charge_voltage_limit,void,float

1 entry status name type params
2 Version + 34.2 34.3
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
36 Header + applications/services/power/power_service/power.h
37 Header + applications/services/rpc/rpc_app.h
38 Header + applications/services/storage/storage.h
Header - firmware/targets/f18/furi_hal/furi_hal_power_calibration.h
39 Header + firmware/targets/f18/furi_hal/furi_hal_resources.h
40 Header + firmware/targets/f18/furi_hal/furi_hal_spi_config.h
41 Header + firmware/targets/f18/furi_hal/furi_hal_target_hw.h
1147 Function + furi_hal_power_is_charging _Bool
1148 Function + furi_hal_power_is_charging_done _Bool
1149 Function + furi_hal_power_is_otg_enabled _Bool
1150 Function + furi_hal_power_is_shutdown_requested _Bool
1151 Function + furi_hal_power_off void
1152 Function + furi_hal_power_reset void
1153 Function + furi_hal_power_set_battery_charge_voltage_limit void float

View File

@ -1,37 +0,0 @@
const ParamCEDV cedv = {
.cedv_conf.gauge_conf =
{
.CCT = 1,
.CSYNC = 0,
.EDV_CMP = 0,
.SC = 1,
.FIXED_EDV0 = 1,
.FCC_LIM = 1,
.FC_FOR_VDQ = 1,
.IGNORE_SD = 1,
.SME0 = 0,
},
.full_charge_cap = 1300,
.design_cap = 1300,
.EDV0 = 3300,
.EDV1 = 3321,
.EDV2 = 3355,
.EMF = 3679,
.C0 = 430,
.C1 = 0,
.R1 = 408,
.R0 = 334,
.T0 = 4626,
.TC = 11,
.DOD0 = 4044,
.DOD10 = 3905,
.DOD20 = 3807,
.DOD30 = 3718,
.DOD40 = 3642,
.DOD50 = 3585,
.DOD60 = 3546,
.DOD70 = 3514,
.DOD80 = 3477,
.DOD90 = 3411,
.DOD100 = 3299,
};

View File

@ -0,0 +1,149 @@
#include <bq27220_data_memory.h>
const BQ27220DMGaugingConfig furi_hal_power_gauge_data_memory_gauging_config = {
.CCT = 1,
.CSYNC = 0,
.EDV_CMP = 0,
.SC = 1,
.FIXED_EDV0 = 1,
.FCC_LIM = 1,
.FC_FOR_VDQ = 1,
.IGNORE_SD = 1,
.SME0 = 0,
};
const BQ27220DMData furi_hal_power_gauge_data_memory[] = {
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1GaugingConfig,
.type = BQ27220DMTypePtr16,
.value.u32 = (uint32_t)&furi_hal_power_gauge_data_memory_gauging_config,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1FullChargeCapacity,
.type = BQ27220DMTypeU16,
.value.u16 = 1300,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1DesignCapacity,
.type = BQ27220DMTypeU16,
.value.u16 = 1300,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1EMF,
.type = BQ27220DMTypeU16,
.value.u16 = 3679,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1C0,
.type = BQ27220DMTypeU16,
.value.u16 = 430,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1R0,
.type = BQ27220DMTypeU16,
.value.u16 = 334,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1T0,
.type = BQ27220DMTypeU16,
.value.u16 = 4626,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1R1,
.type = BQ27220DMTypeU16,
.value.u16 = 408,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1TC,
.type = BQ27220DMTypeU8,
.value.u8 = 11,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1C1,
.type = BQ27220DMTypeU8,
.value.u8 = 0,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD0,
.type = BQ27220DMTypeU16,
.value.u16 = 4044,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD10,
.type = BQ27220DMTypeU16,
.value.u16 = 3905,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD20,
.type = BQ27220DMTypeU16,
.value.u16 = 3807,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD30,
.type = BQ27220DMTypeU16,
.value.u16 = 3718,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD40,
.type = BQ27220DMTypeU16,
.value.u16 = 3642,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD50,
.type = BQ27220DMTypeU16,
.value.u16 = 3585,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD60,
.type = BQ27220DMTypeU16,
.value.u16 = 3546,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD70,
.type = BQ27220DMTypeU16,
.value.u16 = 3514,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD80,
.type = BQ27220DMTypeU16,
.value.u16 = 3477,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD90,
.type = BQ27220DMTypeU16,
.value.u16 = 3411,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD100,
.type = BQ27220DMTypeU16,
.value.u16 = 3299,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1EDV0,
.type = BQ27220DMTypeU16,
.value.u16 = 3300,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1EDV1,
.type = BQ27220DMTypeU16,
.value.u16 = 3321,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1EDV2,
.type = BQ27220DMTypeU16,
.value.u16 = 3355,
},
{
.address = BQ27220DMAddressCalibrationCurrentDeadband,
.type = BQ27220DMTypeU8,
.value.u8 = 1,
},
{
.address = BQ27220DMAddressConfigurationPowerSleepCurrent,
.type = BQ27220DMTypeI16,
.value.i16 = 1,
},
{
.type = BQ27220DMTypeEnd,
},
};

View File

@ -1,5 +1,5 @@
entry,status,name,type,params entry,status,name,type,params
Version,+,34.2,, Version,+,34.3,,
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,, Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli.h,,
@ -50,7 +50,6 @@ Header,+,firmware/targets/f7/furi_hal/furi_hal_idle_timer.h,,
Header,+,firmware/targets/f7/furi_hal/furi_hal_interrupt.h,, Header,+,firmware/targets/f7/furi_hal/furi_hal_interrupt.h,,
Header,+,firmware/targets/f7/furi_hal/furi_hal_nfc.h,, Header,+,firmware/targets/f7/furi_hal/furi_hal_nfc.h,,
Header,+,firmware/targets/f7/furi_hal/furi_hal_os.h,, Header,+,firmware/targets/f7/furi_hal/furi_hal_os.h,,
Header,-,firmware/targets/f7/furi_hal/furi_hal_power_calibration.h,,
Header,+,firmware/targets/f7/furi_hal/furi_hal_pwm.h,, Header,+,firmware/targets/f7/furi_hal/furi_hal_pwm.h,,
Header,+,firmware/targets/f7/furi_hal/furi_hal_resources.h,, Header,+,firmware/targets/f7/furi_hal/furi_hal_resources.h,,
Header,+,firmware/targets/f7/furi_hal/furi_hal_rfid.h,, Header,+,firmware/targets/f7/furi_hal/furi_hal_rfid.h,,
@ -1297,6 +1296,7 @@ Function,-,furi_hal_power_insomnia_level,uint16_t,
Function,+,furi_hal_power_is_charging,_Bool, Function,+,furi_hal_power_is_charging,_Bool,
Function,+,furi_hal_power_is_charging_done,_Bool, Function,+,furi_hal_power_is_charging_done,_Bool,
Function,+,furi_hal_power_is_otg_enabled,_Bool, Function,+,furi_hal_power_is_otg_enabled,_Bool,
Function,+,furi_hal_power_is_shutdown_requested,_Bool,
Function,+,furi_hal_power_off,void, Function,+,furi_hal_power_off,void,
Function,+,furi_hal_power_reset,void, Function,+,furi_hal_power_reset,void,
Function,+,furi_hal_power_set_battery_charge_voltage_limit,void,float Function,+,furi_hal_power_set_battery_charge_voltage_limit,void,float

1 entry status name type params
2 Version + 34.2 34.3
3 Header + applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h
4 Header + applications/services/bt/bt_service/bt.h
5 Header + applications/services/cli/cli.h
50 Header + firmware/targets/f7/furi_hal/furi_hal_interrupt.h
51 Header + firmware/targets/f7/furi_hal/furi_hal_nfc.h
52 Header + firmware/targets/f7/furi_hal/furi_hal_os.h
Header - firmware/targets/f7/furi_hal/furi_hal_power_calibration.h
53 Header + firmware/targets/f7/furi_hal/furi_hal_pwm.h
54 Header + firmware/targets/f7/furi_hal/furi_hal_resources.h
55 Header + firmware/targets/f7/furi_hal/furi_hal_rfid.h
1296 Function + furi_hal_power_is_charging _Bool
1297 Function + furi_hal_power_is_charging_done _Bool
1298 Function + furi_hal_power_is_otg_enabled _Bool
1299 Function + furi_hal_power_is_shutdown_requested _Bool
1300 Function + furi_hal_power_off void
1301 Function + furi_hal_power_reset void
1302 Function + furi_hal_power_set_battery_charge_voltage_limit void float

View File

@ -15,6 +15,7 @@
#include <hw_conf.h> #include <hw_conf.h>
#include <bq27220.h> #include <bq27220.h>
#include <bq27220_data_memory.h>
#include <bq25896.h> #include <bq25896.h>
#include <furi.h> #include <furi.h>
@ -37,16 +38,18 @@ typedef struct {
volatile uint8_t insomnia; volatile uint8_t insomnia;
volatile uint8_t suppress_charge; volatile uint8_t suppress_charge;
uint8_t gauge_initialized; bool gauge_ok;
uint8_t charger_initialized; bool charger_ok;
} FuriHalPower; } FuriHalPower;
static volatile FuriHalPower furi_hal_power = { static volatile FuriHalPower furi_hal_power = {
.insomnia = 0, .insomnia = 0,
.suppress_charge = 0, .suppress_charge = 0,
.gauge_ok = false,
.charger_ok = false,
}; };
#include <furi_hal_power_calibration.h> extern const BQ27220DMData furi_hal_power_gauge_data_memory[];
void furi_hal_power_init() { void furi_hal_power_init() {
#ifdef FURI_HAL_POWER_DEBUG #ifdef FURI_HAL_POWER_DEBUG
@ -63,8 +66,13 @@ void furi_hal_power_init() {
LL_C2_PWR_SetPowerMode(FURI_HAL_POWER_STOP_MODE); LL_C2_PWR_SetPowerMode(FURI_HAL_POWER_STOP_MODE);
furi_hal_i2c_acquire(&furi_hal_i2c_handle_power); furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
bq27220_init(&furi_hal_i2c_handle_power, &cedv); // Find and init gauge
bq25896_init(&furi_hal_i2c_handle_power); if(bq27220_init(&furi_hal_i2c_handle_power)) {
furi_hal_power.gauge_ok = bq27220_apply_data_memory(
&furi_hal_i2c_handle_power, furi_hal_power_gauge_data_memory);
}
// Find and init charger
furi_hal_power.charger_ok = bq25896_init(&furi_hal_i2c_handle_power);
furi_hal_i2c_release(&furi_hal_i2c_handle_power); furi_hal_i2c_release(&furi_hal_i2c_handle_power);
FURI_LOG_I(TAG, "Init OK"); FURI_LOG_I(TAG, "Init OK");
@ -78,14 +86,29 @@ bool furi_hal_power_gauge_is_ok() {
furi_hal_i2c_acquire(&furi_hal_i2c_handle_power); furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
if(bq27220_get_battery_status(&furi_hal_i2c_handle_power, &battery_status) == BQ27220_ERROR || if(!bq27220_get_battery_status(&furi_hal_i2c_handle_power, &battery_status) ||
bq27220_get_operation_status(&furi_hal_i2c_handle_power, &operation_status) == !bq27220_get_operation_status(&furi_hal_i2c_handle_power, &operation_status)) {
BQ27220_ERROR) {
ret = false; ret = false;
} else { } else {
ret &= battery_status.BATTPRES; ret &= battery_status.BATTPRES;
ret &= operation_status.INITCOMP; ret &= operation_status.INITCOMP;
ret &= (cedv.design_cap == bq27220_get_design_capacity(&furi_hal_i2c_handle_power)); ret &= furi_hal_power.gauge_ok;
}
furi_hal_i2c_release(&furi_hal_i2c_handle_power);
return ret;
}
bool furi_hal_power_is_shutdown_requested() {
bool ret = false;
BatteryStatus battery_status;
furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
if(bq27220_get_battery_status(&furi_hal_i2c_handle_power, &battery_status) != BQ27220_ERROR) {
ret = battery_status.SYSDWN;
} }
furi_hal_i2c_release(&furi_hal_i2c_handle_power); furi_hal_i2c_release(&furi_hal_i2c_handle_power);
@ -576,9 +599,8 @@ void furi_hal_power_debug_get(PropertyValueCallback out, void* context) {
const uint32_t ntc_mpct = bq25896_get_ntc_mpct(&furi_hal_i2c_handle_power); const uint32_t ntc_mpct = bq25896_get_ntc_mpct(&furi_hal_i2c_handle_power);
if(bq27220_get_battery_status(&furi_hal_i2c_handle_power, &battery_status) != BQ27220_ERROR && if(bq27220_get_battery_status(&furi_hal_i2c_handle_power, &battery_status) &&
bq27220_get_operation_status(&furi_hal_i2c_handle_power, &operation_status) != bq27220_get_operation_status(&furi_hal_i2c_handle_power, &operation_status)) {
BQ27220_ERROR) {
property_value_out(&property_context, "%lu", 2, "charger", "ntc", ntc_mpct); property_value_out(&property_context, "%lu", 2, "charger", "ntc", ntc_mpct);
property_value_out(&property_context, "%d", 2, "gauge", "calmd", operation_status.CALMD); property_value_out(&property_context, "%d", 2, "gauge", "calmd", operation_status.CALMD);
property_value_out(&property_context, "%d", 2, "gauge", "sec", operation_status.SEC); property_value_out(&property_context, "%d", 2, "gauge", "sec", operation_status.SEC);

View File

@ -1,37 +0,0 @@
const ParamCEDV cedv = {
.cedv_conf.gauge_conf =
{
.CCT = 1,
.CSYNC = 0,
.EDV_CMP = 0,
.SC = 1,
.FIXED_EDV0 = 1,
.FCC_LIM = 1,
.FC_FOR_VDQ = 1,
.IGNORE_SD = 1,
.SME0 = 0,
},
.full_charge_cap = 2101,
.design_cap = 2101,
.EDV0 = 3300,
.EDV1 = 3321,
.EDV2 = 3355,
.EMF = 3679,
.C0 = 430,
.C1 = 0,
.R1 = 408,
.R0 = 334,
.T0 = 4626,
.TC = 11,
.DOD0 = 4044,
.DOD10 = 3905,
.DOD20 = 3807,
.DOD30 = 3718,
.DOD40 = 3642,
.DOD50 = 3585,
.DOD60 = 3546,
.DOD70 = 3514,
.DOD80 = 3477,
.DOD90 = 3411,
.DOD100 = 3299,
};

View File

@ -0,0 +1,149 @@
#include <bq27220_data_memory.h>
const BQ27220DMGaugingConfig furi_hal_power_gauge_data_memory_gauging_config = {
.CCT = 1,
.CSYNC = 0,
.EDV_CMP = 0,
.SC = 1,
.FIXED_EDV0 = 1,
.FCC_LIM = 1,
.FC_FOR_VDQ = 1,
.IGNORE_SD = 1,
.SME0 = 0,
};
const BQ27220DMData furi_hal_power_gauge_data_memory[] = {
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1GaugingConfig,
.type = BQ27220DMTypePtr16,
.value.u32 = (uint32_t)&furi_hal_power_gauge_data_memory_gauging_config,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1FullChargeCapacity,
.type = BQ27220DMTypeU16,
.value.u16 = 2100,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1DesignCapacity,
.type = BQ27220DMTypeU16,
.value.u16 = 2100,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1EMF,
.type = BQ27220DMTypeU16,
.value.u16 = 3679,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1C0,
.type = BQ27220DMTypeU16,
.value.u16 = 430,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1R0,
.type = BQ27220DMTypeU16,
.value.u16 = 334,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1T0,
.type = BQ27220DMTypeU16,
.value.u16 = 4626,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1R1,
.type = BQ27220DMTypeU16,
.value.u16 = 408,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1TC,
.type = BQ27220DMTypeU8,
.value.u8 = 11,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1C1,
.type = BQ27220DMTypeU8,
.value.u8 = 0,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD0,
.type = BQ27220DMTypeU16,
.value.u16 = 4044,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD10,
.type = BQ27220DMTypeU16,
.value.u16 = 3905,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD20,
.type = BQ27220DMTypeU16,
.value.u16 = 3807,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD30,
.type = BQ27220DMTypeU16,
.value.u16 = 3718,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD40,
.type = BQ27220DMTypeU16,
.value.u16 = 3642,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD50,
.type = BQ27220DMTypeU16,
.value.u16 = 3585,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD60,
.type = BQ27220DMTypeU16,
.value.u16 = 3546,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD70,
.type = BQ27220DMTypeU16,
.value.u16 = 3514,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD80,
.type = BQ27220DMTypeU16,
.value.u16 = 3477,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD90,
.type = BQ27220DMTypeU16,
.value.u16 = 3411,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD100,
.type = BQ27220DMTypeU16,
.value.u16 = 3299,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1EDV0,
.type = BQ27220DMTypeU16,
.value.u16 = 3300,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1EDV1,
.type = BQ27220DMTypeU16,
.value.u16 = 3321,
},
{
.address = BQ27220DMAddressGasGaugingCEDVProfile1EDV2,
.type = BQ27220DMTypeU16,
.value.u16 = 3355,
},
{
.address = BQ27220DMAddressCalibrationCurrentDeadband,
.type = BQ27220DMTypeU8,
.value.u8 = 1,
},
{
.address = BQ27220DMAddressConfigurationPowerSleepCurrent,
.type = BQ27220DMTypeI16,
.value.i16 = 1,
},
{
.type = BQ27220DMTypeEnd,
},
};

View File

@ -34,6 +34,12 @@ void furi_hal_power_init();
*/ */
bool furi_hal_power_gauge_is_ok(); bool furi_hal_power_gauge_is_ok();
/** Check if gauge requests system shutdown
*
* @return true if system shutdown requested
*/
bool furi_hal_power_is_shutdown_requested();
/** Get current insomnia level /** Get current insomnia level
* *
* @return insomnia level: 0 - no insomnia, >0 - insomnia, bearer count. * @return insomnia level: 0 - no insomnia, >0 - insomnia, bearer count.

View File

@ -35,13 +35,15 @@ typedef struct {
static bq25896_regs_t bq25896_regs; static bq25896_regs_t bq25896_regs;
void bq25896_init(FuriHalI2cBusHandle* handle) { bool bq25896_init(FuriHalI2cBusHandle* handle) {
bool result = true;
bq25896_regs.r14.REG_RST = 1; bq25896_regs.r14.REG_RST = 1;
furi_hal_i2c_write_reg_8( result &= furi_hal_i2c_write_reg_8(
handle, BQ25896_ADDRESS, 0x14, *(uint8_t*)&bq25896_regs.r14, BQ25896_I2C_TIMEOUT); handle, BQ25896_ADDRESS, 0x14, *(uint8_t*)&bq25896_regs.r14, BQ25896_I2C_TIMEOUT);
// Readout all registers // Readout all registers
furi_hal_i2c_read_mem( result &= furi_hal_i2c_read_mem(
handle, handle,
BQ25896_ADDRESS, BQ25896_ADDRESS,
0x00, 0x00,
@ -52,26 +54,28 @@ void bq25896_init(FuriHalI2cBusHandle* handle) {
// Poll ADC forever // Poll ADC forever
bq25896_regs.r02.CONV_START = 1; bq25896_regs.r02.CONV_START = 1;
bq25896_regs.r02.CONV_RATE = 1; bq25896_regs.r02.CONV_RATE = 1;
furi_hal_i2c_write_reg_8( result &= furi_hal_i2c_write_reg_8(
handle, BQ25896_ADDRESS, 0x02, *(uint8_t*)&bq25896_regs.r02, BQ25896_I2C_TIMEOUT); handle, BQ25896_ADDRESS, 0x02, *(uint8_t*)&bq25896_regs.r02, BQ25896_I2C_TIMEOUT);
bq25896_regs.r07.WATCHDOG = WatchdogDisable; bq25896_regs.r07.WATCHDOG = WatchdogDisable;
furi_hal_i2c_write_reg_8( result &= furi_hal_i2c_write_reg_8(
handle, BQ25896_ADDRESS, 0x07, *(uint8_t*)&bq25896_regs.r07, BQ25896_I2C_TIMEOUT); handle, BQ25896_ADDRESS, 0x07, *(uint8_t*)&bq25896_regs.r07, BQ25896_I2C_TIMEOUT);
// OTG power configuration // OTG power configuration
bq25896_regs.r0A.BOOSTV = 0x8; // BOOST Voltage: 5.062V bq25896_regs.r0A.BOOSTV = 0x8; // BOOST Voltage: 5.062V
bq25896_regs.r0A.BOOST_LIM = BoostLim_1400; // BOOST Current limit: 1.4A bq25896_regs.r0A.BOOST_LIM = BoostLim_1400; // BOOST Current limit: 1.4A
furi_hal_i2c_write_reg_8( result &= furi_hal_i2c_write_reg_8(
handle, BQ25896_ADDRESS, 0x0A, *(uint8_t*)&bq25896_regs.r0A, BQ25896_I2C_TIMEOUT); handle, BQ25896_ADDRESS, 0x0A, *(uint8_t*)&bq25896_regs.r0A, BQ25896_I2C_TIMEOUT);
furi_hal_i2c_read_mem( result &= furi_hal_i2c_read_mem(
handle, handle,
BQ25896_ADDRESS, BQ25896_ADDRESS,
0x00, 0x00,
(uint8_t*)&bq25896_regs, (uint8_t*)&bq25896_regs,
sizeof(bq25896_regs), sizeof(bq25896_regs),
BQ25896_I2C_TIMEOUT); BQ25896_I2C_TIMEOUT);
return result;
} }
void bq25896_set_boost_lim(FuriHalI2cBusHandle* handle, BoostLim boost_lim) { void bq25896_set_boost_lim(FuriHalI2cBusHandle* handle, BoostLim boost_lim) {

View File

@ -7,7 +7,7 @@
#include <furi_hal_i2c.h> #include <furi_hal_i2c.h>
/** Initialize Driver */ /** Initialize Driver */
void bq25896_init(FuriHalI2cBusHandle* handle); bool bq25896_init(FuriHalI2cBusHandle* handle);
/** Set boost lim*/ /** Set boost lim*/
void bq25896_set_boost_lim(FuriHalI2cBusHandle* handle, BoostLim boost_lim); void bq25896_set_boost_lim(FuriHalI2cBusHandle* handle, BoostLim boost_lim);

View File

@ -1,12 +1,16 @@
#include "bq27220.h" #include "bq27220.h"
#include "bq27220_reg.h" #include "bq27220_reg.h"
#include "bq27220_data_memory.h"
_Static_assert(sizeof(BQ27220DMGaugingConfig) == 2, "Incorrect structure size");
#include <furi.h> #include <furi.h>
#include <stdbool.h> #include <stdbool.h>
#define TAG "Gauge" #define TAG "Gauge"
uint16_t bq27220_read_word(FuriHalI2cBusHandle* handle, uint8_t address) { static uint16_t bq27220_read_word(FuriHalI2cBusHandle* handle, uint8_t address) {
uint16_t buf = 0; uint16_t buf = 0;
furi_hal_i2c_read_mem( furi_hal_i2c_read_mem(
@ -15,14 +19,14 @@ uint16_t bq27220_read_word(FuriHalI2cBusHandle* handle, uint8_t address) {
return buf; return buf;
} }
bool bq27220_control(FuriHalI2cBusHandle* handle, uint16_t control) { static bool bq27220_control(FuriHalI2cBusHandle* handle, uint16_t control) {
bool ret = furi_hal_i2c_write_mem( bool ret = furi_hal_i2c_write_mem(
handle, BQ27220_ADDRESS, CommandControl, (uint8_t*)&control, 2, BQ27220_I2C_TIMEOUT); handle, BQ27220_ADDRESS, CommandControl, (uint8_t*)&control, 2, BQ27220_I2C_TIMEOUT);
return ret; return ret;
} }
uint8_t bq27220_get_checksum(uint8_t* data, uint16_t len) { static uint8_t bq27220_get_checksum(uint8_t* data, uint16_t len) {
uint8_t ret = 0; uint8_t ret = 0;
for(uint16_t i = 0; i < len; i++) { for(uint16_t i = 0; i < len; i++) {
ret += data[i]; ret += data[i];
@ -30,80 +34,181 @@ uint8_t bq27220_get_checksum(uint8_t* data, uint16_t len) {
return 0xFF - ret; return 0xFF - ret;
} }
bool bq27220_set_parameter_u16(FuriHalI2cBusHandle* handle, uint16_t address, uint16_t value) { static bool bq27220_parameter_check(
bool ret; FuriHalI2cBusHandle* handle,
uint8_t buffer[4]; uint16_t address,
uint32_t value,
size_t size,
bool update) {
furi_assert(size == 1 || size == 2 || size == 4);
bool ret = false;
uint8_t buffer[6] = {0};
uint8_t old_data[4] = {0};
buffer[0] = address & 0xFF; do {
buffer[1] = (address >> 8) & 0xFF; buffer[0] = address & 0xFF;
buffer[2] = (value >> 8) & 0xFF; buffer[1] = (address >> 8) & 0xFF;
buffer[3] = value & 0xFF;
ret = furi_hal_i2c_write_mem(
handle, BQ27220_ADDRESS, CommandSelectSubclass, buffer, 4, BQ27220_I2C_TIMEOUT);
furi_delay_us(10000); for(size_t i = 0; i < size; i++) {
buffer[1 + size - i] = (value >> (i * 8)) & 0xFF;
}
uint8_t checksum = bq27220_get_checksum(buffer, 4); if(update) {
buffer[0] = checksum; if(!furi_hal_i2c_write_mem(
buffer[1] = 6; handle,
ret &= furi_hal_i2c_write_mem( BQ27220_ADDRESS,
handle, BQ27220_ADDRESS, CommandMACDataSum, buffer, 2, BQ27220_I2C_TIMEOUT); CommandSelectSubclass,
buffer,
size + 2,
BQ27220_I2C_TIMEOUT)) {
FURI_LOG_I(TAG, "DM write failed");
break;
}
furi_delay_us(10000);
uint8_t checksum = bq27220_get_checksum(buffer, size + 2);
buffer[0] = checksum;
buffer[1] = 4 + size; // TODO: why 4?
if(!furi_hal_i2c_write_mem(
handle, BQ27220_ADDRESS, CommandMACDataSum, buffer, 2, BQ27220_I2C_TIMEOUT)) {
FURI_LOG_I(TAG, "CRC write failed");
break;
}
furi_delay_us(10000);
ret = true;
} else {
if(!furi_hal_i2c_write_mem(
handle, BQ27220_ADDRESS, CommandSelectSubclass, buffer, 2, BQ27220_I2C_TIMEOUT)) {
FURI_LOG_I(TAG, "DM SelectSubclass for read failed");
break;
}
if(!furi_hal_i2c_rx(handle, BQ27220_ADDRESS, old_data, size, BQ27220_I2C_TIMEOUT)) {
FURI_LOG_I(TAG, "DM read failed");
break;
}
if(*(uint32_t*)&(old_data[0]) != *(uint32_t*)&(buffer[2])) {
FURI_LOG_W( //-V641
TAG,
"Data at 0x%04x(%zu): 0x%08lx!=0x%08lx",
address,
size,
*(uint32_t*)&(old_data[0]),
*(uint32_t*)&(buffer[2]));
} else {
ret = true;
}
}
} while(0);
furi_delay_us(10000);
return ret; return ret;
} }
bool bq27220_init(FuriHalI2cBusHandle* handle, const ParamCEDV* cedv) { static bool bq27220_data_memory_check(
uint32_t timeout = 100; FuriHalI2cBusHandle* handle,
uint16_t design_cap = bq27220_get_design_capacity(handle); const BQ27220DMData* data_memory,
if(cedv->design_cap == design_cap) { bool update) {
FURI_LOG_I(TAG, "Skip battery profile update"); if(update) {
return true; if(!bq27220_control(handle, Control_ENTER_CFG_UPDATE)) {
FURI_LOG_E(TAG, "ENTER_CFG_UPDATE command failed");
return false;
};
// Wait for enter CFG update mode
uint32_t timeout = 100;
OperationStatus status = {0};
while((status.CFGUPDATE != true) && (timeout-- > 0)) {
bq27220_get_operation_status(handle, &status);
}
if(timeout == 0) {
FURI_LOG_E(TAG, "CFGUPDATE mode failed");
return false;
}
} }
FURI_LOG_I(TAG, "Start updating battery profile");
OperationStatus status = {0}; // Process data memory records
if(!bq27220_control(handle, Control_ENTER_CFG_UPDATE)) { bool result = true;
FURI_LOG_E(TAG, "Can't configure update"); while(data_memory->type != BQ27220DMTypeEnd) {
if(data_memory->type == BQ27220DMTypeWait) {
furi_delay_us(data_memory->value.u32);
} else if(data_memory->type == BQ27220DMTypeU8) {
result &= bq27220_parameter_check(
handle, data_memory->address, data_memory->value.u8, 1, update);
} else if(data_memory->type == BQ27220DMTypeU16) {
result &= bq27220_parameter_check(
handle, data_memory->address, data_memory->value.u16, 2, update);
} else if(data_memory->type == BQ27220DMTypeU32) {
result &= bq27220_parameter_check(
handle, data_memory->address, data_memory->value.u32, 4, update);
} else if(data_memory->type == BQ27220DMTypeI8) {
result &= bq27220_parameter_check(
handle, data_memory->address, data_memory->value.i8, 1, update);
} else if(data_memory->type == BQ27220DMTypeI16) {
result &= bq27220_parameter_check(
handle, data_memory->address, data_memory->value.i16, 2, update);
} else if(data_memory->type == BQ27220DMTypeI32) {
result &= bq27220_parameter_check(
handle, data_memory->address, data_memory->value.i32, 4, update);
} else if(data_memory->type == BQ27220DMTypeF32) {
result &= bq27220_parameter_check(
handle, data_memory->address, data_memory->value.u32, 4, update);
} else if(data_memory->type == BQ27220DMTypePtr8) {
result &= bq27220_parameter_check(
handle, data_memory->address, *(uint8_t*)data_memory->value.u32, 1, update);
} else if(data_memory->type == BQ27220DMTypePtr16) {
result &= bq27220_parameter_check(
handle, data_memory->address, *(uint16_t*)data_memory->value.u32, 2, update);
} else if(data_memory->type == BQ27220DMTypePtr32) {
result &= bq27220_parameter_check(
handle, data_memory->address, *(uint32_t*)data_memory->value.u32, 4, update);
} else {
furi_crash("Invalid DM Type");
}
data_memory++;
}
// Finalize configuration update
if(update) {
bq27220_control(handle, Control_EXIT_CFG_UPDATE_REINIT);
furi_delay_us(10000);
}
return result;
}
bool bq27220_init(FuriHalI2cBusHandle* handle) {
// Request device number(chip PN)
if(!bq27220_control(handle, Control_DEVICE_NUMBER)) {
FURI_LOG_E(TAG, "Device is not present");
return false;
};
// Check control response
uint16_t data = 0;
data = bq27220_read_word(handle, CommandControl);
if(data != 0xFF00) {
FURI_LOG_E(TAG, "Invalid control response: %x", data);
return false; return false;
}; };
while((status.CFGUPDATE != true) && (timeout-- > 0)) { data = bq27220_read_word(handle, CommandMACData);
bq27220_get_operation_status(handle, &status); FURI_LOG_I(TAG, "Device Number %04x", data);
}
bq27220_set_parameter_u16(handle, AddressGaugingConfig, cedv->cedv_conf.gauge_conf_raw);
bq27220_set_parameter_u16(handle, AddressFullChargeCapacity, cedv->full_charge_cap);
bq27220_set_parameter_u16(handle, AddressDesignCapacity, cedv->design_cap);
bq27220_set_parameter_u16(handle, AddressEMF, cedv->EMF);
bq27220_set_parameter_u16(handle, AddressC0, cedv->C0);
bq27220_set_parameter_u16(handle, AddressR0, cedv->R0);
bq27220_set_parameter_u16(handle, AddressT0, cedv->T0);
bq27220_set_parameter_u16(handle, AddressR1, cedv->R1);
bq27220_set_parameter_u16(handle, AddressTC, (cedv->TC) << 8 | cedv->C1);
bq27220_set_parameter_u16(handle, AddressStartDOD0, cedv->DOD0);
bq27220_set_parameter_u16(handle, AddressStartDOD10, cedv->DOD10);
bq27220_set_parameter_u16(handle, AddressStartDOD20, cedv->DOD20);
bq27220_set_parameter_u16(handle, AddressStartDOD30, cedv->DOD30);
bq27220_set_parameter_u16(handle, AddressStartDOD40, cedv->DOD40);
bq27220_set_parameter_u16(handle, AddressStartDOD50, cedv->DOD40);
bq27220_set_parameter_u16(handle, AddressStartDOD60, cedv->DOD60);
bq27220_set_parameter_u16(handle, AddressStartDOD70, cedv->DOD70);
bq27220_set_parameter_u16(handle, AddressStartDOD80, cedv->DOD80);
bq27220_set_parameter_u16(handle, AddressStartDOD90, cedv->DOD90);
bq27220_set_parameter_u16(handle, AddressStartDOD100, cedv->DOD100);
bq27220_set_parameter_u16(handle, AddressEDV0, cedv->EDV0);
bq27220_set_parameter_u16(handle, AddressEDV1, cedv->EDV1);
bq27220_set_parameter_u16(handle, AddressEDV2, cedv->EDV2);
bq27220_control(handle, Control_EXIT_CFG_UPDATE_REINIT); return data == 0x0220;
furi_delay_us(10000); }
design_cap = bq27220_get_design_capacity(handle);
if(cedv->design_cap == design_cap) { bool bq27220_apply_data_memory(FuriHalI2cBusHandle* handle, const BQ27220DMData* data_memory) {
FURI_LOG_I(TAG, "Battery profile update success"); FURI_LOG_I(TAG, "Verifying data memory");
return true; if(!bq27220_data_memory_check(handle, data_memory, false)) {
} else { FURI_LOG_I(TAG, "Updating data memory");
FURI_LOG_E(TAG, "Battery profile update failed"); bq27220_data_memory_check(handle, data_memory, true);
return false;
} }
FURI_LOG_I(TAG, "Data memory verification complete");
return true;
} }
uint16_t bq27220_get_voltage(FuriHalI2cBusHandle* handle) { uint16_t bq27220_get_voltage(FuriHalI2cBusHandle* handle) {
@ -114,24 +219,23 @@ int16_t bq27220_get_current(FuriHalI2cBusHandle* handle) {
return bq27220_read_word(handle, CommandCurrent); return bq27220_read_word(handle, CommandCurrent);
} }
uint8_t bq27220_get_battery_status(FuriHalI2cBusHandle* handle, BatteryStatus* battery_status) { bool bq27220_get_battery_status(FuriHalI2cBusHandle* handle, BatteryStatus* battery_status) {
uint16_t data = bq27220_read_word(handle, CommandBatteryStatus); uint16_t data = bq27220_read_word(handle, CommandBatteryStatus);
if(data == BQ27220_ERROR) { if(data == BQ27220_ERROR) {
return BQ27220_ERROR; return false;
} else { } else {
*(uint16_t*)battery_status = data; *(uint16_t*)battery_status = data;
return BQ27220_SUCCESS; return true;
} }
} }
uint8_t bool bq27220_get_operation_status(FuriHalI2cBusHandle* handle, OperationStatus* operation_status) {
bq27220_get_operation_status(FuriHalI2cBusHandle* handle, OperationStatus* operation_status) {
uint16_t data = bq27220_read_word(handle, CommandOperationStatus); uint16_t data = bq27220_read_word(handle, CommandOperationStatus);
if(data == BQ27220_ERROR) { if(data == BQ27220_ERROR) {
return BQ27220_ERROR; return false;
} else { } else {
*(uint16_t*)operation_status = data; *(uint16_t*)operation_status = data;
return BQ27220_SUCCESS; return true;
} }
} }

View File

@ -47,60 +47,17 @@ typedef struct {
_Static_assert(sizeof(OperationStatus) == 2, "Incorrect structure size"); _Static_assert(sizeof(OperationStatus) == 2, "Incorrect structure size");
typedef struct { typedef struct BQ27220DMData BQ27220DMData;
// Low byte, Low bit first
bool CCT : 1;
bool CSYNC : 1;
bool RSVD0 : 1;
bool EDV_CMP : 1;
bool SC : 1;
bool FIXED_EDV0 : 1;
uint8_t RSVD1 : 2;
// High byte, Low bit first
bool FCC_LIM : 1;
bool RSVD2 : 1;
bool FC_FOR_VDQ : 1;
bool IGNORE_SD : 1;
bool SME0 : 1;
uint8_t RSVD3 : 3;
} GaugingConfig;
_Static_assert(sizeof(GaugingConfig) == 2, "Incorrect structure size");
typedef struct {
union {
GaugingConfig gauge_conf;
uint16_t gauge_conf_raw;
} cedv_conf;
uint16_t full_charge_cap;
uint16_t design_cap;
uint16_t EDV0;
uint16_t EDV1;
uint16_t EDV2;
uint16_t EMF;
uint16_t C0;
uint16_t R0;
uint16_t T0;
uint16_t R1;
uint8_t TC;
uint8_t C1;
uint16_t DOD0;
uint16_t DOD10;
uint16_t DOD20;
uint16_t DOD30;
uint16_t DOD40;
uint16_t DOD50;
uint16_t DOD60;
uint16_t DOD70;
uint16_t DOD80;
uint16_t DOD90;
uint16_t DOD100;
} ParamCEDV;
/** Initialize Driver /** Initialize Driver
* @return true on success, false otherwise * @return true on success, false otherwise
*/ */
bool bq27220_init(FuriHalI2cBusHandle* handle, const ParamCEDV* cedv); bool bq27220_init(FuriHalI2cBusHandle* handle);
/** Initialize Driver
* @return true on success, false otherwise
*/
bool bq27220_apply_data_memory(FuriHalI2cBusHandle* handle, const BQ27220DMData* data_memory);
/** Get battery voltage in mV or error */ /** Get battery voltage in mV or error */
uint16_t bq27220_get_voltage(FuriHalI2cBusHandle* handle); uint16_t bq27220_get_voltage(FuriHalI2cBusHandle* handle);
@ -109,11 +66,10 @@ uint16_t bq27220_get_voltage(FuriHalI2cBusHandle* handle);
int16_t bq27220_get_current(FuriHalI2cBusHandle* handle); int16_t bq27220_get_current(FuriHalI2cBusHandle* handle);
/** Get battery status */ /** Get battery status */
uint8_t bq27220_get_battery_status(FuriHalI2cBusHandle* handle, BatteryStatus* battery_status); bool bq27220_get_battery_status(FuriHalI2cBusHandle* handle, BatteryStatus* battery_status);
/** Get operation status */ /** Get operation status */
uint8_t bool bq27220_get_operation_status(FuriHalI2cBusHandle* handle, OperationStatus* operation_status);
bq27220_get_operation_status(FuriHalI2cBusHandle* handle, OperationStatus* operation_status);
/** Get temperature in units of 0.1°K */ /** Get temperature in units of 0.1°K */
uint16_t bq27220_get_temperature(FuriHalI2cBusHandle* handle); uint16_t bq27220_get_temperature(FuriHalI2cBusHandle* handle);

View File

@ -0,0 +1,84 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
typedef enum {
BQ27220DMTypeEnd,
BQ27220DMTypeWait,
BQ27220DMTypeU8,
BQ27220DMTypeU16,
BQ27220DMTypeU32,
BQ27220DMTypeI8,
BQ27220DMTypeI16,
BQ27220DMTypeI32,
BQ27220DMTypeF32,
BQ27220DMTypePtr8,
BQ27220DMTypePtr16,
BQ27220DMTypePtr32,
} BQ27220DMType;
typedef enum {
BQ27220DMAddressGasGaugingCEDVProfile1GaugingConfig = 0x929B,
BQ27220DMAddressGasGaugingCEDVProfile1FullChargeCapacity = 0x929D,
BQ27220DMAddressGasGaugingCEDVProfile1DesignCapacity = 0x929F,
BQ27220DMAddressGasGaugingCEDVProfile1EMF = 0x92A3,
BQ27220DMAddressGasGaugingCEDVProfile1C0 = 0x92A9,
BQ27220DMAddressGasGaugingCEDVProfile1R0 = 0x92AB,
BQ27220DMAddressGasGaugingCEDVProfile1T0 = 0x92AD,
BQ27220DMAddressGasGaugingCEDVProfile1R1 = 0x92AF,
BQ27220DMAddressGasGaugingCEDVProfile1TC = 0x92B1,
BQ27220DMAddressGasGaugingCEDVProfile1C1 = 0x92B2,
BQ27220DMAddressGasGaugingCEDVProfile1EDV0 = 0x92B4,
BQ27220DMAddressGasGaugingCEDVProfile1EDV1 = 0x92B7,
BQ27220DMAddressGasGaugingCEDVProfile1EDV2 = 0x92BA,
BQ27220DMAddressGasGaugingCEDVProfile1StartDOD0 = 0x92BD,
BQ27220DMAddressGasGaugingCEDVProfile1StartDOD10 = 0x92BF,
BQ27220DMAddressGasGaugingCEDVProfile1StartDOD20 = 0x92C1,
BQ27220DMAddressGasGaugingCEDVProfile1StartDOD30 = 0x92C3,
BQ27220DMAddressGasGaugingCEDVProfile1StartDOD40 = 0x92C5,
BQ27220DMAddressGasGaugingCEDVProfile1StartDOD50 = 0x92C7,
BQ27220DMAddressGasGaugingCEDVProfile1StartDOD60 = 0x92C9,
BQ27220DMAddressGasGaugingCEDVProfile1StartDOD70 = 0x92CB,
BQ27220DMAddressGasGaugingCEDVProfile1StartDOD80 = 0x92CD,
BQ27220DMAddressGasGaugingCEDVProfile1StartDOD90 = 0x92CF,
BQ27220DMAddressGasGaugingCEDVProfile1StartDOD100 = 0x92D1,
BQ27220DMAddressCalibrationCurrentDeadband = 0x91DE,
BQ27220DMAddressConfigurationPowerSleepCurrent = 0x9217,
BQ27220DMAddressConfigurationCurrentThresholdsDischargeDetectionThreshold = 0x9228,
BQ27220DMAddressConfigurationDataInitialStandby = 0x923C,
} BQ27220DMAddress;
typedef struct BQ27220DMData BQ27220DMData;
struct BQ27220DMData {
uint16_t type;
uint16_t address;
union {
uint8_t u8;
uint16_t u16;
uint32_t u32;
int8_t i8;
int16_t i16;
int32_t i32;
float f32;
} value;
};
typedef struct {
// Low byte, Low bit first
const bool CCT : 1;
const bool CSYNC : 1;
const bool RSVD0 : 1;
const bool EDV_CMP : 1;
const bool SC : 1;
const bool FIXED_EDV0 : 1;
const uint8_t RSVD1 : 2;
// High byte, Low bit first
const bool FCC_LIM : 1;
const bool RSVD2 : 1;
const bool FC_FOR_VDQ : 1;
const bool IGNORE_SD : 1;
const bool SME0 : 1;
const uint8_t RSVD3 : 3;
} BQ27220DMGaugingConfig;

View File

@ -66,28 +66,3 @@
#define Control_EXIT_CFG_UPDATE_REINIT 0x0091 #define Control_EXIT_CFG_UPDATE_REINIT 0x0091
#define Control_EXIT_CFG_UPDATE 0x0092 #define Control_EXIT_CFG_UPDATE 0x0092
#define Control_RETURN_TO_ROM 0x0F00 #define Control_RETURN_TO_ROM 0x0F00
#define AddressGaugingConfig 0x929B
#define AddressFullChargeCapacity 0x929D
#define AddressDesignCapacity 0x929F
#define AddressEMF 0x92A3
#define AddressC0 0x92A9
#define AddressR0 0x92AB
#define AddressT0 0x92AD
#define AddressR1 0x92AF
#define AddressTC 0x92B1
#define AddressC1 0x92B2
#define AddressEDV0 0x92B4
#define AddressEDV1 0x92B7
#define AddressEDV2 0x92BA
#define AddressStartDOD0 0x92BD
#define AddressStartDOD10 0x92BF
#define AddressStartDOD20 0x92C1
#define AddressStartDOD30 0x92C3
#define AddressStartDOD40 0x92C5
#define AddressStartDOD50 0x92C7
#define AddressStartDOD60 0x92C9
#define AddressStartDOD70 0x92CB
#define AddressStartDOD80 0x92CD
#define AddressStartDOD90 0x92CF
#define AddressStartDOD100 0x92D1

View File

@ -328,10 +328,7 @@ class AppBuildset:
sdk_headers.extend( sdk_headers.extend(
[ [
src._appdir.File(header) src._appdir.File(header)
for src in [ for src in [app, *app._plugins]
app,
*(plugin for plugin in app._plugins),
]
for header in src.sdk_headers for header in src.sdk_headers
] ]
) )

View File

@ -3,7 +3,7 @@ import os
import pathlib import pathlib
import shutil import shutil
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Optional from typing import Optional, Dict, List
import SCons.Warnings import SCons.Warnings
from ansi.color import fg from ansi.color import fg
@ -400,22 +400,26 @@ def generate_embed_app_metadata_actions(source, target, env, for_signature):
return Action(actions) return Action(actions)
def AddAppLaunchTarget(env, appname, launch_target_name): @dataclass
deploy_sources, flipp_dist_paths, validators = [], [], [] class AppDeploymentComponents:
run_script_extra_ars = "" deploy_sources: Dict[str, object] = field(default_factory=dict)
validators: List[object] = field(default_factory=list)
extra_launch_args: str = ""
def _add_dist_targets(app_artifacts): def add_app(self, app_artifacts):
validators.append(app_artifacts.validator)
for _, ext_path in app_artifacts.dist_entries: for _, ext_path in app_artifacts.dist_entries:
deploy_sources.append(app_artifacts.compact) self.deploy_sources[f"/ext/{ext_path}"] = app_artifacts.compact
flipp_dist_paths.append(f"/ext/{ext_path}") self.validators.append(app_artifacts.validator)
return app_artifacts
def _gather_app_components(env, appname) -> AppDeploymentComponents:
components = AppDeploymentComponents()
def _add_host_app_to_targets(host_app): def _add_host_app_to_targets(host_app):
artifacts_app_to_run = env["EXT_APPS"].get(host_app.appid, None) artifacts_app_to_run = env["EXT_APPS"].get(host_app.appid, None)
_add_dist_targets(artifacts_app_to_run) components.add_app(artifacts_app_to_run)
for plugin in host_app._plugins: for plugin in host_app._plugins:
_add_dist_targets(env["EXT_APPS"].get(plugin.appid, None)) components.add_app(env["EXT_APPS"].get(plugin.appid, None))
artifacts_app_to_run = env.GetExtAppByIdOrPath(appname) artifacts_app_to_run = env.GetExtAppByIdOrPath(appname)
if artifacts_app_to_run.app.apptype == FlipperAppType.PLUGIN: if artifacts_app_to_run.app.apptype == FlipperAppType.PLUGIN:
@ -427,25 +431,35 @@ def AddAppLaunchTarget(env, appname, launch_target_name):
FlipperAppType.EXTERNAL, FlipperAppType.EXTERNAL,
FlipperAppType.MENUEXTERNAL, FlipperAppType.MENUEXTERNAL,
]: ]:
_add_host_app_to_targets(host_app) components.add_app(host_app)
else: else:
# host app is a built-in app # host app is a built-in app
run_script_extra_ars = f"-a {host_app.name}" components.add_app(artifacts_app_to_run)
_add_dist_targets(artifacts_app_to_run) components.extra_launch_args = f"-a {host_app.name}"
else: else:
raise UserError("Host app is unknown") raise UserError("Host app is unknown")
else: else:
_add_host_app_to_targets(artifacts_app_to_run.app) _add_host_app_to_targets(artifacts_app_to_run.app)
return components
# print(deploy_sources, flipp_dist_paths)
env.PhonyTarget( def AddAppLaunchTarget(env, appname, launch_target_name):
components = _gather_app_components(env, appname)
target = env.PhonyTarget(
launch_target_name, launch_target_name,
'${PYTHON3} "${APP_RUN_SCRIPT}" -p ${FLIP_PORT} ${EXTRA_ARGS} -s ${SOURCES} -t ${FLIPPER_FILE_TARGETS}', '${PYTHON3} "${APP_RUN_SCRIPT}" -p ${FLIP_PORT} ${EXTRA_ARGS} -s ${SOURCES} -t ${FLIPPER_FILE_TARGETS}',
source=deploy_sources, source=components.deploy_sources.values(),
FLIPPER_FILE_TARGETS=flipp_dist_paths, FLIPPER_FILE_TARGETS=components.deploy_sources.keys(),
EXTRA_ARGS=run_script_extra_ars, EXTRA_ARGS=components.extra_launch_args,
) )
env.Alias(launch_target_name, validators) env.Alias(launch_target_name, components.validators)
return target
def AddAppBuildTarget(env, appname, build_target_name):
components = _gather_app_components(env, appname)
env.Alias(build_target_name, components.validators)
env.Alias(build_target_name, components.deploy_sources.values())
def generate(env, **kw): def generate(env, **kw):
@ -474,6 +488,7 @@ def generate(env, **kw):
env.AddMethod(BuildAppElf) env.AddMethod(BuildAppElf)
env.AddMethod(GetExtAppByIdOrPath) env.AddMethod(GetExtAppByIdOrPath)
env.AddMethod(AddAppLaunchTarget) env.AddMethod(AddAppLaunchTarget)
env.AddMethod(AddAppBuildTarget)
env.Append( env.Append(
BUILDERS={ BUILDERS={

View File

@ -4,16 +4,17 @@ targets_help = """Configuration variables:
tail_help = """ tail_help = """
TASKS: TASKS:
Building: Firmware & apps:
firmware_all, fw_dist: firmware_all, fw_dist:
Build firmware; create distribution package Build firmware; create distribution package
faps, fap_dist: faps, fap_dist:
Build all FAP apps Build all FAP apps
fap_{APPID}, launch_app APPSRC={APPID}: fap_{APPID}, build APPSRC={APPID}; launch APPSRC={APPID}:
Build FAP app with appid={APPID}; upload & start it over USB Build FAP app with appid={APPID}; upload & start it over USB
fap_deploy: fap_deploy:
Build and upload all FAP apps over USB Build and upload all FAP apps over USB
Flashing & debugging: Flashing & debugging:
flash, flash_blackmagic, jflash: flash, flash_blackmagic, jflash:
Flash firmware to target using debug probe Flash firmware to target using debug probe

View File

@ -336,8 +336,10 @@ def ambiguous_app_call(**kw):
if app_to_launch: if app_to_launch:
appenv.AddAppLaunchTarget(app_to_launch, "launch") appenv.AddAppLaunchTarget(app_to_launch, "launch")
appenv.AddAppBuildTarget(app_to_launch, "build")
else: else:
dist_env.PhonyTarget("launch", Action(ambiguous_app_call, None)) dist_env.PhonyTarget("launch", Action(ambiguous_app_call, None))
dist_env.PhonyTarget("build", Action(ambiguous_app_call, None))
# cli handler # cli handler

View File

@ -114,8 +114,20 @@ extapps.resources_dist = appenv.FapDist(appenv["RESOURCES_ROOT"], [])
if appsrc := appenv.subst("$APPSRC"): if appsrc := appenv.subst("$APPSRC"):
appenv.AddAppLaunchTarget(appsrc, "launch_app") launch_target = appenv.AddAppLaunchTarget(appsrc, "launch")
Alias("launch_app", launch_target)
appenv.PhonyTarget(
"launch_app",
Action(
lambda **kw: warn(
WarningOnByDefault,
"The 'launch_app' target is deprecated. Use 'launch' instead.",
),
None,
),
)
appenv.AddAppBuildTarget(appsrc, "build")
# SDK management # SDK management