From 20f6394ad8177e7e7589ad185e16193f7bab5f11 Mon Sep 17 00:00:00 2001 From: hedger Date: Mon, 17 Jul 2023 11:51:15 +0400 Subject: [PATCH 1/9] [FL-3431] Radio headers in SDK (#2881) --- applications/drivers/subghz/application.fam | 1 + firmware/targets/f18/api_symbols.csv | 3 ++- firmware/targets/f7/api_symbols.csv | 7 ++++++- lib/drivers/SConscript | 3 +++ lib/subghz/SConscript | 1 + scripts/fbt/appmanifest.py | 11 ++++++++++- 6 files changed, 23 insertions(+), 3 deletions(-) diff --git a/applications/drivers/subghz/application.fam b/applications/drivers/subghz/application.fam index aaf0e1bd9..2ee114833 100644 --- a/applications/drivers/subghz/application.fam +++ b/applications/drivers/subghz/application.fam @@ -4,5 +4,6 @@ App( targets=["f7"], entry_point="subghz_device_cc1101_ext_ep", requires=["subghz"], + sdk_headers=["cc1101_ext/cc1101_ext_interconnect.h"], fap_libs=["hwdrivers"], ) diff --git a/firmware/targets/f18/api_symbols.csv b/firmware/targets/f18/api_symbols.csv index bbeaa3b1a..20c829755 100644 --- a/firmware/targets/f18/api_symbols.csv +++ b/firmware/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,34.1,, +Version,+,34.2,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -82,6 +82,7 @@ Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h,, Header,+,firmware/targets/furi_hal_include/furi_hal_version.h,, Header,+,firmware/targets/furi_hal_include/furi_hal_vibro.h,, Header,+,lib/digital_signal/digital_signal.h,, +Header,+,lib/drivers/cc1101_regs.h,, Header,+,lib/flipper_application/api_hashtable/api_hashtable.h,, Header,+,lib/flipper_application/api_hashtable/compilesort.hpp,, Header,+,lib/flipper_application/flipper_application.h,, diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 0d33f70f6..cc1d016dd 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,6 @@ entry,status,name,type,params -Version,+,34.1,, +Version,+,34.2,, +Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -87,6 +88,7 @@ Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h,, Header,+,firmware/targets/furi_hal_include/furi_hal_version.h,, Header,+,firmware/targets/furi_hal_include/furi_hal_vibro.h,, Header,+,lib/digital_signal/digital_signal.h,, +Header,+,lib/drivers/cc1101_regs.h,, Header,+,lib/flipper_application/api_hashtable/api_hashtable.h,, Header,+,lib/flipper_application/api_hashtable/compilesort.hpp,, Header,+,lib/flipper_application/flipper_application.h,, @@ -192,6 +194,7 @@ Header,+,lib/subghz/blocks/encoder.h,, Header,+,lib/subghz/blocks/generic.h,, Header,+,lib/subghz/blocks/math.h,, Header,+,lib/subghz/devices/cc1101_configs.h,, +Header,+,lib/subghz/devices/cc1101_int/cc1101_int_interconnect.h,, Header,+,lib/subghz/environment.h,, Header,+,lib/subghz/protocols/raw.h,, Header,+,lib/subghz/receiver.h,, @@ -2697,6 +2700,7 @@ Function,+,subghz_block_generic_deserialize,SubGhzProtocolStatus,"SubGhzBlockGen Function,+,subghz_block_generic_deserialize_check_count_bit,SubGhzProtocolStatus,"SubGhzBlockGeneric*, FlipperFormat*, uint16_t" Function,+,subghz_block_generic_get_preset_name,void,"const char*, FuriString*" Function,+,subghz_block_generic_serialize,SubGhzProtocolStatus,"SubGhzBlockGeneric*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_device_cc1101_ext_ep,const FlipperAppPluginDescriptor*, Function,+,subghz_devices_begin,_Bool,const SubGhzDevice* Function,+,subghz_devices_deinit,void, Function,+,subghz_devices_end,void,const SubGhzDevice* @@ -3436,6 +3440,7 @@ Variable,+,sequence_set_vibro_on,const NotificationSequence, Variable,+,sequence_single_vibro,const NotificationSequence, Variable,+,sequence_solid_yellow,const NotificationSequence, Variable,+,sequence_success,const NotificationSequence, +Variable,-,subghz_device_cc1101_int,const SubGhzDevice, Variable,+,subghz_device_cc1101_preset_2fsk_dev2_38khz_async_regs,const uint8_t[], Variable,+,subghz_device_cc1101_preset_2fsk_dev47_6khz_async_regs,const uint8_t[], Variable,+,subghz_device_cc1101_preset_gfsk_9_99kb_async_regs,const uint8_t[], diff --git a/lib/drivers/SConscript b/lib/drivers/SConscript index 3b7ee2401..103472ccb 100644 --- a/lib/drivers/SConscript +++ b/lib/drivers/SConscript @@ -4,6 +4,9 @@ env.Append( CPPPATH=[ "#/lib/drivers", ], + SDK_HEADERS=[ + File("cc1101_regs.h"), + ], ) diff --git a/lib/subghz/SConscript b/lib/subghz/SConscript index 2c42a5157..82c925c1a 100644 --- a/lib/subghz/SConscript +++ b/lib/subghz/SConscript @@ -20,6 +20,7 @@ env.Append( File("subghz_setting.h"), File("subghz_protocol_registry.h"), File("devices/cc1101_configs.h"), + File("devices/cc1101_int/cc1101_int_interconnect.h"), ], ) diff --git a/scripts/fbt/appmanifest.py b/scripts/fbt/appmanifest.py index 5b830dda9..0064b3591 100644 --- a/scripts/fbt/appmanifest.py +++ b/scripts/fbt/appmanifest.py @@ -325,7 +325,16 @@ class AppBuildset: def get_sdk_headers(self): sdk_headers = [] for app in self.apps: - sdk_headers.extend([app._appdir.File(header) for header in app.sdk_headers]) + sdk_headers.extend( + [ + src._appdir.File(header) + for src in [ + app, + *(plugin for plugin in app._plugins), + ] + for header in src.sdk_headers + ] + ) return sdk_headers def get_apps_of_type(self, apptype: FlipperAppType, all_known: bool = False): From 9bb04832a84901b0fcf1b0921b472825fbca6bef Mon Sep 17 00:00:00 2001 From: Dzhos Oleksii <35292229+Programistich@users.noreply.github.com> Date: Mon, 17 Jul 2023 11:03:27 +0300 Subject: [PATCH 2/9] IButton: on delete scene key name not fully display if so long (#2882) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- .../main/ibutton/scenes/ibutton_scene_delete_confirm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/applications/main/ibutton/scenes/ibutton_scene_delete_confirm.c b/applications/main/ibutton/scenes/ibutton_scene_delete_confirm.c index 587cb748c..b293af952 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_delete_confirm.c +++ b/applications/main/ibutton/scenes/ibutton_scene_delete_confirm.c @@ -12,15 +12,15 @@ void ibutton_scene_delete_confirm_on_enter(void* context) { widget_add_button_element( widget, GuiButtonTypeRight, "Delete", ibutton_widget_callback, context); - furi_string_printf(tmp, "Delete %s?", ibutton->key_name); - widget_add_string_element( - widget, 128 / 2, 0, AlignCenter, AlignTop, FontPrimary, furi_string_get_cstr(tmp)); + furi_string_printf(tmp, "\e#Delete %s?\e#", ibutton->key_name); + widget_add_text_box_element( + widget, 0, 0, 128, 23, AlignCenter, AlignCenter, furi_string_get_cstr(tmp), false); furi_string_reset(tmp); ibutton_protocols_render_brief_data(ibutton->protocols, key, tmp); widget_add_string_multiline_element( - widget, 128 / 2, 16, AlignCenter, AlignTop, FontSecondary, furi_string_get_cstr(tmp)); + widget, 128 / 2, 24, AlignCenter, AlignTop, FontSecondary, furi_string_get_cstr(tmp)); view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget); furi_string_free(tmp); From 6870304a7393444c0bba7f67808e8da016cc6031 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 17 Jul 2023 20:37:30 +0300 Subject: [PATCH 3/9] Move subghz into internal memory we have no free ram :(((( --- applications/main/subghz/application.fam | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/applications/main/subghz/application.fam b/applications/main/subghz/application.fam index 759716065..946891a4a 100644 --- a/applications/main/subghz/application.fam +++ b/applications/main/subghz/application.fam @@ -1,8 +1,9 @@ App( appid="subghz", name="Sub-GHz", - apptype=FlipperAppType.MENUEXTERNAL, + apptype=FlipperAppType.APP, targets=["f7"], + cdefines=["APP_SUBGHZ"], entry_point="subghz_app", requires=[ "gui", @@ -26,6 +27,7 @@ App( targets=["f7"], apptype=FlipperAppType.STARTUP, entry_point="subghz_on_system_start", + requires=["subghz"], order=40, ) From e2028eb731e69c62d5160c0570fac54f8a2bc8f4 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 17 Jul 2023 22:12:34 +0300 Subject: [PATCH 4/9] Fix menu --- applications/main/subghz/application.fam | 2 +- applications/services/loader/loader_menu.c | 36 ++++++++++++---------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/applications/main/subghz/application.fam b/applications/main/subghz/application.fam index 946891a4a..7494e6fba 100644 --- a/applications/main/subghz/application.fam +++ b/applications/main/subghz/application.fam @@ -16,7 +16,7 @@ App( ], icon="A_Sub1ghz_14", stack_size=3 * 1024, - order=10, + order=1, fap_libs=["assets", "hwdrivers"], fap_icon="icon.png", fap_category="Sub-GHz", diff --git a/applications/services/loader/loader_menu.c b/applications/services/loader/loader_menu.c index 149fea72c..8277b6db0 100644 --- a/applications/services/loader/loader_menu.c +++ b/applications/services/loader/loader_menu.c @@ -94,7 +94,25 @@ static uint32_t loader_menu_exit(void* context) { } static void loader_menu_build_menu(LoaderMenuApp* app, LoaderMenu* menu) { - size_t i; + size_t i = 0; + + menu_add_item( + app->primary_menu, + LOADER_APPLICATIONS_NAME, + &A_Plugins_14, + i++, + loader_menu_applications_callback, + (void*)menu); + + for(i = 0; i < FLIPPER_APPS_COUNT; i++) { + menu_add_item( + app->primary_menu, + FLIPPER_APPS[i].name, + FLIPPER_APPS[i].icon, + i, + loader_menu_apps_callback, + (void*)menu); + } for(i = 0; i < FLIPPER_EXTERNAL_APPS_COUNT; i++) { menu_add_item( @@ -106,24 +124,8 @@ static void loader_menu_build_menu(LoaderMenuApp* app, LoaderMenu* menu) { (void*)menu); } - for(i = 0; i < FLIPPER_APPS_COUNT; i++) { - menu_add_item( - app->primary_menu, - FLIPPER_APPS[i].name, - FLIPPER_APPS[i].icon, - i, - loader_menu_apps_callback, - (void*)menu); - } menu_add_item( app->primary_menu, "Settings", &A_Settings_14, i++, loader_menu_switch_to_settings, app); - menu_add_item( - app->primary_menu, - LOADER_APPLICATIONS_NAME, - &A_Plugins_14, - i++, - loader_menu_applications_callback, - (void*)menu); }; static void loader_menu_build_submenu(LoaderMenuApp* app, LoaderMenu* loader_menu) { From bb6d3cb79637615b23ee6a20b52ba75e333a5473 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Tue, 18 Jul 2023 02:53:30 +0300 Subject: [PATCH 5/9] NRF24 plugins updates Updates by Sil333033 with some changes, furi_hal speaker direct calls was removed and replaced with notification service to avoid bypassing of user set silent mode --- .../external/mousejacker/lib/nrf24/nrf24.c | 10 +++ .../external/mousejacker/lib/nrf24/nrf24.h | 7 ++ .../external/mousejacker/mousejacker.c | 70 +++++++++---------- .../external/mousejacker/mousejacker_ducky.h | 1 + .../external/nrfsniff/lib/nrf24/nrf24.c | 10 +++ .../external/nrfsniff/lib/nrf24/nrf24.h | 7 ++ applications/external/nrfsniff/nrfsniff.c | 25 ++++--- 7 files changed, 85 insertions(+), 45 deletions(-) diff --git a/applications/external/mousejacker/lib/nrf24/nrf24.c b/applications/external/mousejacker/lib/nrf24/nrf24.c index 8b3776445..67c5dde1c 100644 --- a/applications/external/mousejacker/lib/nrf24/nrf24.c +++ b/applications/external/mousejacker/lib/nrf24/nrf24.c @@ -517,4 +517,14 @@ uint8_t nrf24_find_channel( } return ch; +} + +bool nrf24_check_connected(FuriHalSpiBusHandle* handle) { + uint8_t status = nrf24_status(handle); + + if(status != 0x00) { + return true; + } else { + return false; + } } \ No newline at end of file diff --git a/applications/external/mousejacker/lib/nrf24/nrf24.h b/applications/external/mousejacker/lib/nrf24/nrf24.h index 3cfcfe089..046784bc7 100644 --- a/applications/external/mousejacker/lib/nrf24/nrf24.h +++ b/applications/external/mousejacker/lib/nrf24/nrf24.h @@ -361,6 +361,13 @@ void int32_to_bytes(uint32_t val, uint8_t* out, bool bigendian); */ uint32_t bytes_to_int32(uint8_t* bytes, bool bigendian); +/** Check if the nrf24 is connected + * @param handle - pointer to FuriHalSpiHandle + * + * @return true if connected, otherwise false +*/ +bool nrf24_check_connected(FuriHalSpiBusHandle* handle); + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/applications/external/mousejacker/mousejacker.c b/applications/external/mousejacker/mousejacker.c index ce93aa996..6c5ec8c7f 100644 --- a/applications/external/mousejacker/mousejacker.c +++ b/applications/external/mousejacker/mousejacker.c @@ -9,15 +9,14 @@ #include #include #include +#include #include "mousejacker_ducky.h" #include #define TAG "mousejacker" #define LOGITECH_MAX_CHANNEL 85 -#define NRFSNIFF_APP_PATH_FOLDER "/ext/nrfsniff" -#define NRFSNIFF_APP_PATH_EXTENSION ".txt" -#define NRFSNIFF_APP_FILENAME "addresses.txt" -#define MOUSEJACKER_APP_PATH_FOLDER "/ext/mousejacker" +#define NRFSNIFF_APP_PATH_FOLDER_ADDRESSES EXT_PATH("apps_data/nrf24sniff/addresses.txt") +#define LOCAL_BADUSB_FOLDER EXT_PATH("badusb") #define MOUSEJACKER_APP_PATH_EXTENSION ".txt" #define MAX_ADDRS 100 @@ -32,12 +31,13 @@ typedef struct { } PluginEvent; uint8_t addrs_count = 0; -uint8_t addr_idx = 0; +int8_t addr_idx = 0; uint8_t loaded_addrs[MAX_ADDRS][6]; // first byte is rate, the rest are the address char target_fmt_text[] = "Target addr: %s"; char target_address_str[12] = "None"; char target_text[30]; +char index_text[30]; static void render_callback(Canvas* const canvas, void* ctx) { furi_assert(ctx); @@ -53,8 +53,15 @@ static void render_callback(Canvas* const canvas, void* ctx) { snprintf(target_text, sizeof(target_text), target_fmt_text, target_address_str); canvas_draw_str_aligned(canvas, 7, 10, AlignLeft, AlignBottom, target_text); canvas_draw_str_aligned(canvas, 22, 20, AlignLeft, AlignBottom, "<- select address ->"); - canvas_draw_str_aligned(canvas, 10, 30, AlignLeft, AlignBottom, "Press Ok button to "); - canvas_draw_str_aligned(canvas, 10, 40, AlignLeft, AlignBottom, "browse for ducky script"); + snprintf( + index_text, sizeof(index_text), "Address index: %d/%d", addr_idx + 1, addrs_count); + canvas_draw_str_aligned(canvas, 10, 30, AlignLeft, AlignBottom, index_text); + canvas_draw_str_aligned(canvas, 10, 40, AlignLeft, AlignBottom, "Press Ok button to "); + canvas_draw_str_aligned(canvas, 10, 50, AlignLeft, AlignBottom, "browse for ducky script"); + if(!plugin_state->is_nrf24_connected) { + canvas_draw_str_aligned( + canvas, 10, 60, AlignLeft, AlignBottom, "Connect NRF24 to GPIO!"); + } } else if(plugin_state->addr_err) { canvas_draw_str_aligned( canvas, 10, 10, AlignLeft, AlignBottom, "Error: No nrfsniff folder"); @@ -94,6 +101,7 @@ static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queu static void mousejacker_state_init(PluginState* const plugin_state) { plugin_state->is_thread_running = false; + plugin_state->is_nrf24_connected = true; } static void hexlify(uint8_t* in, uint8_t size, char* out) { @@ -107,7 +115,7 @@ static bool open_ducky_script(Stream* stream, PluginState* plugin_state) { bool result = false; FuriString* path; path = furi_string_alloc(); - furi_string_set(path, MOUSEJACKER_APP_PATH_FOLDER); + furi_string_set(path, LOCAL_BADUSB_FOLDER); DialogsFileBrowserOptions browser_options; dialog_file_browser_set_basic_options( @@ -132,27 +140,17 @@ static bool open_ducky_script(Stream* stream, PluginState* plugin_state) { } static bool open_addrs_file(Stream* stream) { - DialogsApp* dialogs = furi_record_open("dialogs"); bool result = false; FuriString* path; path = furi_string_alloc(); - furi_string_set(path, NRFSNIFF_APP_PATH_FOLDER); + furi_string_set(path, NRFSNIFF_APP_PATH_FOLDER_ADDRESSES); - DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options( - &browser_options, NRFSNIFF_APP_PATH_EXTENSION, &I_sub1_10px); - browser_options.hide_ext = false; - - bool ret = dialog_file_browser_show(dialogs, path, path, &browser_options); - - furi_record_close("dialogs"); - if(ret) { - if(!file_stream_open(stream, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { - FURI_LOG_D(TAG, "Cannot open file \"%s\"", furi_string_get_cstr(path)); - } else { - result = true; - } + if(!file_stream_open(stream, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { + FURI_LOG_D(TAG, "Cannot open file \"%s\"", furi_string_get_cstr(path)); + } else { + result = true; } + furi_string_free(path); return result; } @@ -277,12 +275,6 @@ static int32_t mj_worker_thread(void* ctx) { return 0; } -void start_mjthread(PluginState* plugin_state) { - if(!plugin_state->is_thread_running) { - furi_thread_start(plugin_state->mjthread); - } -} - int32_t mousejacker_app(void* p) { UNUSED(p); FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent)); @@ -297,6 +289,8 @@ int32_t mousejacker_app(void* p) { return 255; } + NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); + // Set system callbacks ViewPort* view_port = view_port_alloc(); view_port_draw_callback_set(view_port, render_callback, plugin_state); @@ -307,7 +301,6 @@ int32_t mousejacker_app(void* p) { gui_add_view_port(gui, view_port, GuiLayerFullscreen); plugin_state->storage = furi_record_open(RECORD_STORAGE); - storage_common_mkdir(plugin_state->storage, MOUSEJACKER_APP_PATH_FOLDER); plugin_state->file_stream = file_stream_alloc(plugin_state->storage); plugin_state->mjthread = furi_thread_alloc(); @@ -344,21 +337,25 @@ int32_t mousejacker_app(void* p) { case InputKeyRight: if(!plugin_state->addr_err) { addr_idx++; - if(addr_idx > addrs_count) addr_idx = 0; + if(addr_idx >= addrs_count) addr_idx = 0; hexlify(loaded_addrs[addr_idx] + 1, 5, target_address_str); } break; case InputKeyLeft: if(!plugin_state->addr_err) { addr_idx--; - if(addr_idx == 0) addr_idx = addrs_count - 1; + if(addr_idx < 0) addr_idx = addrs_count - 1; hexlify(loaded_addrs[addr_idx] + 1, 5, target_address_str); } break; case InputKeyOk: if(!plugin_state->addr_err) { - if(!plugin_state->is_thread_running) { - start_mjthread(plugin_state); + if(!nrf24_check_connected(nrf24_HANDLE)) { + plugin_state->is_nrf24_connected = false; + view_port_update(view_port); + notification_message(notification, &sequence_error); + } else if(!plugin_state->is_thread_running) { + furi_thread_start(plugin_state->mjthread); view_port_update(view_port); } } @@ -388,6 +385,7 @@ int32_t mousejacker_app(void* p) { view_port_enabled_set(view_port, false); gui_remove_view_port(gui, view_port); furi_record_close(RECORD_GUI); + furi_record_close(RECORD_NOTIFICATION); furi_record_close(RECORD_STORAGE); view_port_free(view_port); furi_message_queue_free(event_queue); @@ -395,4 +393,4 @@ int32_t mousejacker_app(void* p) { free(plugin_state); return 0; -} \ No newline at end of file +} diff --git a/applications/external/mousejacker/mousejacker_ducky.h b/applications/external/mousejacker/mousejacker_ducky.h index e1a422ea7..01dc32c30 100644 --- a/applications/external/mousejacker/mousejacker_ducky.h +++ b/applications/external/mousejacker/mousejacker_ducky.h @@ -26,6 +26,7 @@ typedef struct { bool addr_err; bool is_thread_running; bool is_ducky_running; + bool is_nrf24_connected; bool close_thread_please; Storage* storage; FuriThread* mjthread; diff --git a/applications/external/nrfsniff/lib/nrf24/nrf24.c b/applications/external/nrfsniff/lib/nrf24/nrf24.c index 8b3776445..67c5dde1c 100644 --- a/applications/external/nrfsniff/lib/nrf24/nrf24.c +++ b/applications/external/nrfsniff/lib/nrf24/nrf24.c @@ -517,4 +517,14 @@ uint8_t nrf24_find_channel( } return ch; +} + +bool nrf24_check_connected(FuriHalSpiBusHandle* handle) { + uint8_t status = nrf24_status(handle); + + if(status != 0x00) { + return true; + } else { + return false; + } } \ No newline at end of file diff --git a/applications/external/nrfsniff/lib/nrf24/nrf24.h b/applications/external/nrfsniff/lib/nrf24/nrf24.h index 3cfcfe089..046784bc7 100644 --- a/applications/external/nrfsniff/lib/nrf24/nrf24.h +++ b/applications/external/nrfsniff/lib/nrf24/nrf24.h @@ -361,6 +361,13 @@ void int32_to_bytes(uint32_t val, uint8_t* out, bool bigendian); */ uint32_t bytes_to_int32(uint8_t* bytes, bool bigendian); +/** Check if the nrf24 is connected + * @param handle - pointer to FuriHalSpiHandle + * + * @return true if connected, otherwise false +*/ +bool nrf24_check_connected(FuriHalSpiBusHandle* handle); + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/applications/external/nrfsniff/nrfsniff.c b/applications/external/nrfsniff/nrfsniff.c index 56bc33d05..39a9b68d4 100644 --- a/applications/external/nrfsniff/nrfsniff.c +++ b/applications/external/nrfsniff/nrfsniff.c @@ -10,11 +10,11 @@ #define LOGITECH_MAX_CHANNEL 85 #define COUNT_THRESHOLD 2 -#define DEFAULT_SAMPLE_TIME 8000 +#define DEFAULT_SAMPLE_TIME 4000 #define MAX_ADDRS 100 #define MAX_CONFIRMED 32 -#define NRFSNIFF_APP_PATH_FOLDER "/ext/nrfsniff" +#define NRFSNIFF_APP_PATH_FOLDER STORAGE_APP_DATA_PATH_PREFIX #define NRFSNIFF_APP_FILENAME "addresses.txt" #define TAG "nrfsniff" @@ -341,6 +341,7 @@ int32_t nrfsniff_app(void* p) { NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); Storage* storage = furi_record_open(RECORD_STORAGE); + storage_common_migrate(storage, EXT_PATH("nrfsniff"), NRFSNIFF_APP_PATH_FOLDER); storage_common_mkdir(storage, NRFSNIFF_APP_PATH_FOLDER); PluginEvent event; @@ -387,13 +388,19 @@ int32_t nrfsniff_app(void* p) { break; case InputKeyOk: // toggle sniffing - sniffing_state = !sniffing_state; - if(sniffing_state) { - clear_cache(); - start_sniffing(); - start = furi_get_tick(); - } else - wrap_up(storage, notification); + if(nrf24_check_connected(nrf24_HANDLE)) { + sniffing_state = !sniffing_state; + if(sniffing_state) { + clear_cache(); + start_sniffing(); + start = furi_get_tick(); + } else { + wrap_up(storage, notification); + } + } else { + notification_message(notification, &sequence_error); + } + break; case InputKeyBack: if(event.input.type == InputTypeLong) processing = false; From 12f7edb56a9385ad3227d09dec53786f54b3cfcf Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Tue, 18 Jul 2023 02:59:45 +0300 Subject: [PATCH 6/9] Update changelog --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 93f9e6455..28e88d5ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,17 +2,21 @@ * !!! **Warning! After installing, Desktop settings (Favoutite apps, PIN Code, AutoLock time..) will be resetted to default due to settings changes, Please set your PIN code, Favourite apps again in Settings->Desktop** !!! * This next text applies to you only **If you have copied any apps manually** into `apps` folder and don't know that you need to update those apps manually in same way you added them - remove `apps` folder or that specific apps you copied on your microSD before installing this release to avoid issues due to OFW API version update! **If you using regular builds or extra pack builds (e) without your manually added apps, all included apps will be installed automatically, no extra actions needed!** ----- +* SubGHz Remote: Merged SubGHz Remote and Remote maker in one app, **use back button to access remote maker** (by @gid9798 | PR #545) * SubGHz: Port latest OFW external radio driver, fix issues (now you can make drivers for other radio chips) (by @gid9798 | PR #539 #536 #535 #534) * GUI module: SubMenu fix vertical orientation (by @gid9798 | PR #543) * Apps: After merge fixes (by @gid9798 | PR #537) * Docs: Update docs for debug build and update vscode example, please remove `debug_pack` target if you had it in your workflow -* Infrared: Updated universal remote assets (by @amec0e | PR #544) +* Infrared: Updated universal remote assets (by @amec0e | PR #544 #546) +* Plugins: NRF24 plugins -> Updates by @Sil333033 with some changes by @xMasterX -> furi_hal_speaker direct calls was removed and replaced with notification service to avoid bypassing of user set silent mode -> What was changed - NRF24 connection check added, app folders was moved (uses migrate, all done automatically), and mousejacker now uses badusb folder for badusb scripts * Plugins: Added Camera Suite GPIO application for the ESP32-CAM module. [(by CodyTolene)](https://github.com/CodyTolene/Flipper-Zero-Camera-Suite) (PR #541) * Plugins: Updated ESP32: WiFi Marauder companion plugin [(by 0xchocolate)](https://github.com/0xchocolate/flipperzero-wifi-marauder) * Plugins: Updated **NFC Maker** plugin (make tags with URLs, Wifi and other things) [(by Willy-JL)](https://github.com/ClaraCrazy/Flipper-Xtreme/tree/dev/applications/external/nfc_maker) * Plugins: Updated **Mifare Nested** [(by AloneLiberty)](https://github.com/AloneLiberty/FlipperNested) * Plugins: Updated Lightmeter [(by oleksiikutuzov)](https://github.com/oleksiikutuzov/flipperzero-lightmeter) * Plugins: Updated **Multi (RFID/iButton) Fuzzer** [(by @gid9798)](https://github.com/DarkFlippers/Multi_Fuzzer) +* OFW: IButton: on delete scene key name not fully display if so long +* OFW: Radio headers in SDK * OFW: Loader: good looking error messages * OFW: Desktop,Cli: add uptime info * OFW: Archive and file browser fixes From 309f65e40167799fb11a259b12ffa4e62338508b Mon Sep 17 00:00:00 2001 From: hedger Date: Tue, 18 Jul 2023 13:39:30 +0400 Subject: [PATCH 7/9] [FL-3437] fbt: `build` target for faps (#2888) * fbt: added build target for faps. Usage: ./fbt build APPSRC= * Updated docs & vscode config * Code cleanup --- .vscode/example/tasks.json | 20 +++++-- .../examples/example_thermo/README.md | 2 +- documentation/AppsOnSDCard.md | 3 +- scripts/fbt/appmanifest.py | 5 +- scripts/fbt_tools/fbt_extapps.py | 55 ++++++++++++------- scripts/fbt_tools/fbt_help.py | 5 +- scripts/ufbt/SConstruct | 2 + site_scons/extapps.scons | 14 ++++- 8 files changed, 73 insertions(+), 33 deletions(-) diff --git a/.vscode/example/tasks.json b/.vscode/example/tasks.json index 28e67d456..3c01506a8 100644 --- a/.vscode/example/tasks.json +++ b/.vscode/example/tasks.json @@ -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", diff --git a/applications/examples/example_thermo/README.md b/applications/examples/example_thermo/README.md index 08240a1f8..d298de643 100644 --- a/applications/examples/example_thermo/README.md +++ b/applications/examples/example_thermo/README.md @@ -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: diff --git a/documentation/AppsOnSDCard.md b/documentation/AppsOnSDCard.md index 212df5b1b..051fbb84f 100644 --- a/documentation/AppsOnSDCard.md +++ b/documentation/AppsOnSDCard.md @@ -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 diff --git a/scripts/fbt/appmanifest.py b/scripts/fbt/appmanifest.py index 0064b3591..067b4a26f 100644 --- a/scripts/fbt/appmanifest.py +++ b/scripts/fbt/appmanifest.py @@ -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 ] ) diff --git a/scripts/fbt_tools/fbt_extapps.py b/scripts/fbt_tools/fbt_extapps.py index a6cd831d4..1766d4c44 100644 --- a/scripts/fbt_tools/fbt_extapps.py +++ b/scripts/fbt_tools/fbt_extapps.py @@ -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={ diff --git a/scripts/fbt_tools/fbt_help.py b/scripts/fbt_tools/fbt_help.py index c7452af98..68fc2aaf9 100644 --- a/scripts/fbt_tools/fbt_help.py +++ b/scripts/fbt_tools/fbt_help.py @@ -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: diff --git a/scripts/ufbt/SConstruct b/scripts/ufbt/SConstruct index 703a9187a..9a9e0938c 100644 --- a/scripts/ufbt/SConstruct +++ b/scripts/ufbt/SConstruct @@ -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 diff --git a/site_scons/extapps.scons b/site_scons/extapps.scons index 0893c4556..5c6f18d68 100644 --- a/site_scons/extapps.scons +++ b/site_scons/extapps.scons @@ -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 From 76e97b8d35807ea86308b2a45445311226ff64ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Tue, 18 Jul 2023 14:46:38 +0400 Subject: [PATCH 8/9] [FL-3051] Gauge initialization routine refactoring, new DataMemory layout, configuration update (#2887) * FuriHal: refactor power gauge config * Format sources and move gauge DM load to separate method * FuriHal: bq27220 refactoring part 1 * Power: use SYSDWN battery status flag for system shutdown * Libs: bq27220 read DM before write, fix incorrect shift * FuriHal: cleanup gauge config, add flags, add ptr DM type, update symbols * FuriHal: 2 stage gauge DM verification and update, better detection routine * FuriHal: update gauge configuration, lower sleep current and deadband * FuriHal: gauge and charger health reporting * Lib: cleanup bq27220 sources * FuriHal: correct documentation for furi_hal_power_is_shutdown_requested * FuriHal: proper gauge config for f7 --- .../services/power/power_service/power.c | 3 +- .../services/power/power_service/power.h | 1 + .../power_settings_app/views/battery_info.c | 3 +- firmware/targets/f18/api_symbols.csv | 4 +- .../f18/furi_hal/furi_hal_power_calibration.h | 37 --- .../f18/furi_hal/furi_hal_power_config.c | 149 +++++++++++ firmware/targets/f7/api_symbols.csv | 4 +- firmware/targets/f7/furi_hal/furi_hal_power.c | 46 +++- .../f7/furi_hal/furi_hal_power_calibration.h | 37 --- .../f7/furi_hal/furi_hal_power_config.c | 149 +++++++++++ .../targets/furi_hal_include/furi_hal_power.h | 6 + lib/drivers/bq25896.c | 18 +- lib/drivers/bq25896.h | 2 +- lib/drivers/bq27220.c | 246 +++++++++++++----- lib/drivers/bq27220.h | 62 +---- lib/drivers/bq27220_data_memory.h | 84 ++++++ lib/drivers/bq27220_reg.h | 25 -- 17 files changed, 626 insertions(+), 250 deletions(-) delete mode 100644 firmware/targets/f18/furi_hal/furi_hal_power_calibration.h create mode 100644 firmware/targets/f18/furi_hal/furi_hal_power_config.c delete mode 100644 firmware/targets/f7/furi_hal/furi_hal_power_calibration.h create mode 100644 firmware/targets/f7/furi_hal/furi_hal_power_config.c create mode 100644 lib/drivers/bq27220_data_memory.h diff --git a/applications/services/power/power_service/power.c b/applications/services/power/power_service/power.c index 72dc8f3f1..aadb5f46e 100644 --- a/applications/services/power/power_service/power.c +++ b/applications/services/power/power_service/power.c @@ -117,6 +117,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(); @@ -145,7 +146,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); diff --git a/applications/services/power/power_service/power.h b/applications/services/power/power_service/power.h index c7f5d7e35..fdc5b527a 100644 --- a/applications/services/power/power_service/power.h +++ b/applications/services/power/power_service/power.h @@ -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; diff --git a/applications/settings/power_settings_app/views/battery_info.c b/applications/settings/power_settings_app/views/battery_info.c index d56dfc628..8add60db5 100644 --- a/applications/settings/power_settings_app/views/battery_info.c +++ b/applications/settings/power_settings_app/views/battery_info.c @@ -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), diff --git a/firmware/targets/f18/api_symbols.csv b/firmware/targets/f18/api_symbols.csv index 20c829755..8b04f441a 100644 --- a/firmware/targets/f18/api_symbols.csv +++ b/firmware/targets/f18/api_symbols.csv @@ -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,, @@ -1149,6 +1148,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 diff --git a/firmware/targets/f18/furi_hal/furi_hal_power_calibration.h b/firmware/targets/f18/furi_hal/furi_hal_power_calibration.h deleted file mode 100644 index e97e1657d..000000000 --- a/firmware/targets/f18/furi_hal/furi_hal_power_calibration.h +++ /dev/null @@ -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, -}; diff --git a/firmware/targets/f18/furi_hal/furi_hal_power_config.c b/firmware/targets/f18/furi_hal/furi_hal_power_config.c new file mode 100644 index 000000000..50efceb7d --- /dev/null +++ b/firmware/targets/f18/furi_hal/furi_hal_power_config.c @@ -0,0 +1,149 @@ +#include + +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, + }, +}; diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index cc1d016dd..dc0720ee2 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -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,, @@ -1270,6 +1269,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 diff --git a/firmware/targets/f7/furi_hal/furi_hal_power.c b/firmware/targets/f7/furi_hal/furi_hal_power.c index 5edde86e9..035919d78 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_power.c +++ b/firmware/targets/f7/furi_hal/furi_hal_power.c @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -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 +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); diff --git a/firmware/targets/f7/furi_hal/furi_hal_power_calibration.h b/firmware/targets/f7/furi_hal/furi_hal_power_calibration.h deleted file mode 100644 index 5eb0f938b..000000000 --- a/firmware/targets/f7/furi_hal/furi_hal_power_calibration.h +++ /dev/null @@ -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, -}; diff --git a/firmware/targets/f7/furi_hal/furi_hal_power_config.c b/firmware/targets/f7/furi_hal/furi_hal_power_config.c new file mode 100644 index 000000000..488edce91 --- /dev/null +++ b/firmware/targets/f7/furi_hal/furi_hal_power_config.c @@ -0,0 +1,149 @@ +#include + +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, + }, +}; diff --git a/firmware/targets/furi_hal_include/furi_hal_power.h b/firmware/targets/furi_hal_include/furi_hal_power.h index 6b4b6cd89..5edda6ba1 100644 --- a/firmware/targets/furi_hal_include/furi_hal_power.h +++ b/firmware/targets/furi_hal_include/furi_hal_power.h @@ -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. diff --git a/lib/drivers/bq25896.c b/lib/drivers/bq25896.c index f675233bd..76aae5e82 100644 --- a/lib/drivers/bq25896.c +++ b/lib/drivers/bq25896.c @@ -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) { diff --git a/lib/drivers/bq25896.h b/lib/drivers/bq25896.h index ce7293960..d35625ab3 100644 --- a/lib/drivers/bq25896.h +++ b/lib/drivers/bq25896.h @@ -7,7 +7,7 @@ #include /** 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); diff --git a/lib/drivers/bq27220.c b/lib/drivers/bq27220.c index f64120fa8..92dbfcd6a 100644 --- a/lib/drivers/bq27220.c +++ b/lib/drivers/bq27220.c @@ -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 #include #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; } } diff --git a/lib/drivers/bq27220.h b/lib/drivers/bq27220.h index c822301a4..ca9e0312e 100644 --- a/lib/drivers/bq27220.h +++ b/lib/drivers/bq27220.h @@ -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); diff --git a/lib/drivers/bq27220_data_memory.h b/lib/drivers/bq27220_data_memory.h new file mode 100644 index 000000000..ae00be883 --- /dev/null +++ b/lib/drivers/bq27220_data_memory.h @@ -0,0 +1,84 @@ +#pragma once + +#include +#include + +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; diff --git a/lib/drivers/bq27220_reg.h b/lib/drivers/bq27220_reg.h index fa81b66eb..2e6e54aab 100644 --- a/lib/drivers/bq27220_reg.h +++ b/lib/drivers/bq27220_reg.h @@ -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 From 3c32075919fb19613334f9d2dc86b818e3e2b66a Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Tue, 18 Jul 2023 22:55:46 +0300 Subject: [PATCH 9/9] add fbt format and clear to quick tasks --- .vscode/example/tasks.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.vscode/example/tasks.json b/.vscode/example/tasks.json index 3c01506a8..1d2b55a2c 100644 --- a/.vscode/example/tasks.json +++ b/.vscode/example/tasks.json @@ -15,6 +15,18 @@ "type": "shell", "command": "./fbt" }, + { + "label": "[FBT] Format", + "group": "build", + "type": "shell", + "command": "./fbt format" + }, + { + "label": "[FBT] Clear", + "group": "build", + "type": "shell", + "command": "./fbt -c" + }, { "label": "[Release] Flash (ST-Link)", "group": "build",