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",
"tasks": [
{
"label": "[Release] Build",
"label": "[Release] Build Firmware",
"group": "build",
"type": "shell",
"command": "./fbt COMPACT=1 DEBUG=0"
},
{
"label": "[Debug] Build",
"label": "[Debug] Build Firmware",
"group": "build",
"type": "shell",
"command": "./fbt"
@ -123,17 +123,29 @@
"type": "shell",
"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",
"group": "build",
"type": "shell",
"command": "./fbt launch_app APPSRC=${relativeFileDirname}"
"command": "./fbt launch APPSRC=${relativeFileDirname}"
},
{
"label": "[Release] Launch App on Flipper",
"group": "build",
"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",

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:
1. Make sure your Flipper has an SD card installed.
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
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.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.health = furi_hal_power_get_bat_health_pct();
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
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) {
if(!power->battery_low) {
view_dispatcher_send_to_front(power->view_dispatcher);

View file

@ -37,6 +37,7 @@ typedef struct {
typedef struct {
bool gauge_is_ok;
bool is_charging;
bool is_shutdown_requested;
float current_charger;
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,
current);
} else if(current < -5) {
// Often gauge reports anything in the range 1~5ma as 5ma
// That brings confusion, so we'll treat it as Napping
// 0-5ma deadband
snprintf(
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, 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`.
## FAP assets

View file

@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,34.2,,
Version,+,34.3,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.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/rpc/rpc_app.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_spi_config.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_done,_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_reset,void,
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
Version,+,34.2,,
Version,+,34.3,,
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
Header,+,applications/services/bt/bt_service/bt.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_nfc.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_resources.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_done,_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_reset,void,
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 <bq27220.h>
#include <bq27220_data_memory.h>
#include <bq25896.h>
#include <furi.h>
@ -37,16 +38,18 @@ typedef struct {
volatile uint8_t insomnia;
volatile uint8_t suppress_charge;
uint8_t gauge_initialized;
uint8_t charger_initialized;
bool gauge_ok;
bool charger_ok;
} FuriHalPower;
static volatile FuriHalPower furi_hal_power = {
.insomnia = 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() {
#ifdef FURI_HAL_POWER_DEBUG
@ -63,8 +66,13 @@ void furi_hal_power_init() {
LL_C2_PWR_SetPowerMode(FURI_HAL_POWER_STOP_MODE);
furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
bq27220_init(&furi_hal_i2c_handle_power, &cedv);
bq25896_init(&furi_hal_i2c_handle_power);
// Find and init gauge
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_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);
if(bq27220_get_battery_status(&furi_hal_i2c_handle_power, &battery_status) == BQ27220_ERROR ||
bq27220_get_operation_status(&furi_hal_i2c_handle_power, &operation_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)) {
ret = false;
} else {
ret &= battery_status.BATTPRES;
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);
@ -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);
if(bq27220_get_battery_status(&furi_hal_i2c_handle_power, &battery_status) != BQ27220_ERROR &&
bq27220_get_operation_status(&furi_hal_i2c_handle_power, &operation_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)) {
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", "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();
/** Check if gauge requests system shutdown
*
* @return true if system shutdown requested
*/
bool furi_hal_power_is_shutdown_requested();
/** Get current insomnia level
*
* @return insomnia level: 0 - no insomnia, >0 - insomnia, bearer count.

View file

@ -35,13 +35,15 @@ typedef struct {
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;
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);
// Readout all registers
furi_hal_i2c_read_mem(
result &= furi_hal_i2c_read_mem(
handle,
BQ25896_ADDRESS,
0x00,
@ -52,26 +54,28 @@ void bq25896_init(FuriHalI2cBusHandle* handle) {
// Poll ADC forever
bq25896_regs.r02.CONV_START = 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);
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);
// OTG power configuration
bq25896_regs.r0A.BOOSTV = 0x8; // BOOST Voltage: 5.062V
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);
furi_hal_i2c_read_mem(
result &= furi_hal_i2c_read_mem(
handle,
BQ25896_ADDRESS,
0x00,
(uint8_t*)&bq25896_regs,
sizeof(bq25896_regs),
BQ25896_I2C_TIMEOUT);
return result;
}
void bq25896_set_boost_lim(FuriHalI2cBusHandle* handle, BoostLim boost_lim) {

View file

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

View file

@ -1,12 +1,16 @@
#include "bq27220.h"
#include "bq27220_reg.h"
#include "bq27220_data_memory.h"
_Static_assert(sizeof(BQ27220DMGaugingConfig) == 2, "Incorrect structure size");
#include <furi.h>
#include <stdbool.h>
#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;
furi_hal_i2c_read_mem(
@ -15,14 +19,14 @@ uint16_t bq27220_read_word(FuriHalI2cBusHandle* handle, uint8_t address) {
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(
handle, BQ27220_ADDRESS, CommandControl, (uint8_t*)&control, 2, BQ27220_I2C_TIMEOUT);
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;
for(uint16_t i = 0; i < len; i++) {
ret += data[i];
@ -30,80 +34,181 @@ uint8_t bq27220_get_checksum(uint8_t* data, uint16_t len) {
return 0xFF - ret;
}
bool bq27220_set_parameter_u16(FuriHalI2cBusHandle* handle, uint16_t address, uint16_t value) {
bool ret;
uint8_t buffer[4];
static bool bq27220_parameter_check(
FuriHalI2cBusHandle* handle,
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;
buffer[1] = (address >> 8) & 0xFF;
buffer[2] = (value >> 8) & 0xFF;
buffer[3] = value & 0xFF;
ret = furi_hal_i2c_write_mem(
handle, BQ27220_ADDRESS, CommandSelectSubclass, buffer, 4, BQ27220_I2C_TIMEOUT);
do {
buffer[0] = address & 0xFF;
buffer[1] = (address >> 8) & 0xFF;
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);
buffer[0] = checksum;
buffer[1] = 6;
ret &= furi_hal_i2c_write_mem(
handle, BQ27220_ADDRESS, CommandMACDataSum, buffer, 2, BQ27220_I2C_TIMEOUT);
if(update) {
if(!furi_hal_i2c_write_mem(
handle,
BQ27220_ADDRESS,
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;
}
bool bq27220_init(FuriHalI2cBusHandle* handle, const ParamCEDV* cedv) {
uint32_t timeout = 100;
uint16_t design_cap = bq27220_get_design_capacity(handle);
if(cedv->design_cap == design_cap) {
FURI_LOG_I(TAG, "Skip battery profile update");
return true;
static bool bq27220_data_memory_check(
FuriHalI2cBusHandle* handle,
const BQ27220DMData* data_memory,
bool update) {
if(update) {
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};
if(!bq27220_control(handle, Control_ENTER_CFG_UPDATE)) {
FURI_LOG_E(TAG, "Can't configure update");
// Process data memory records
bool result = true;
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;
};
while((status.CFGUPDATE != true) && (timeout-- > 0)) {
bq27220_get_operation_status(handle, &status);
}
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);
data = bq27220_read_word(handle, CommandMACData);
FURI_LOG_I(TAG, "Device Number %04x", data);
bq27220_control(handle, Control_EXIT_CFG_UPDATE_REINIT);
furi_delay_us(10000);
design_cap = bq27220_get_design_capacity(handle);
if(cedv->design_cap == design_cap) {
FURI_LOG_I(TAG, "Battery profile update success");
return true;
} else {
FURI_LOG_E(TAG, "Battery profile update failed");
return false;
return data == 0x0220;
}
bool bq27220_apply_data_memory(FuriHalI2cBusHandle* handle, const BQ27220DMData* data_memory) {
FURI_LOG_I(TAG, "Verifying data memory");
if(!bq27220_data_memory_check(handle, data_memory, false)) {
FURI_LOG_I(TAG, "Updating data memory");
bq27220_data_memory_check(handle, data_memory, true);
}
FURI_LOG_I(TAG, "Data memory verification complete");
return true;
}
uint16_t bq27220_get_voltage(FuriHalI2cBusHandle* handle) {
@ -114,24 +219,23 @@ int16_t bq27220_get_current(FuriHalI2cBusHandle* handle) {
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);
if(data == BQ27220_ERROR) {
return BQ27220_ERROR;
return false;
} else {
*(uint16_t*)battery_status = data;
return BQ27220_SUCCESS;
return true;
}
}
uint8_t
bq27220_get_operation_status(FuriHalI2cBusHandle* handle, OperationStatus* operation_status) {
bool bq27220_get_operation_status(FuriHalI2cBusHandle* handle, OperationStatus* operation_status) {
uint16_t data = bq27220_read_word(handle, CommandOperationStatus);
if(data == BQ27220_ERROR) {
return BQ27220_ERROR;
return false;
} else {
*(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");
typedef struct {
// 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;
typedef struct BQ27220DMData BQ27220DMData;
/** Initialize Driver
* @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 */
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);
/** 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 */
uint8_t
bq27220_get_operation_status(FuriHalI2cBusHandle* handle, OperationStatus* operation_status);
bool bq27220_get_operation_status(FuriHalI2cBusHandle* handle, OperationStatus* operation_status);
/** Get temperature in units of 0.1°K */
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 0x0092
#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(
[
src._appdir.File(header)
for src in [
app,
*(plugin for plugin in app._plugins),
]
for src in [app, *app._plugins]
for header in src.sdk_headers
]
)

View file

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

View file

@ -4,15 +4,16 @@ targets_help = """Configuration variables:
tail_help = """
TASKS:
Building:
Firmware & apps:
firmware_all, fw_dist:
Build firmware; create distribution package
faps, fap_dist:
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
fap_deploy:
Build and upload all FAP apps over USB
Flashing & debugging:
flash, flash_blackmagic, jflash:

View file

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

View file

@ -114,8 +114,20 @@ extapps.resources_dist = appenv.FapDist(appenv["RESOURCES_ROOT"], [])
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