mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2025-12-13 13:09:49 +04:00
Compare commits
19 Commits
subghz_pro
...
unlshd-027
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5cf46d2aa9 | ||
|
|
beedf54e75 | ||
|
|
70ccb89c3d | ||
|
|
5ea43a2a4b | ||
|
|
41f60dbbf4 | ||
|
|
827341ec08 | ||
|
|
5c36043d03 | ||
|
|
cf5811f8d9 | ||
|
|
ec6a169bf8 | ||
|
|
f1dec87c1b | ||
|
|
ab29951a99 | ||
|
|
bbe9f88bbe | ||
|
|
9188bf0013 | ||
|
|
f33ed59567 | ||
|
|
3fd8c80861 | ||
|
|
7b8ac3a5a0 | ||
|
|
6fef957001 | ||
|
|
0de1c9df89 | ||
|
|
a0e8cfbe97 |
24
.drone.yml
24
.drone.yml
@@ -222,18 +222,6 @@ steps:
|
||||
- chmod +x ./discord.sh
|
||||
- ./discord.sh --text 'New Unleashed firmware released!\n\nVersion - '${DRONE_TAG}'\n\n[[Github - Changelog]](https://github.com/DarkFlippers/unleashed-firmware/releases/tag/'${DRONE_TAG}')\n\n[-How to install firmware-](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)\n\n[-Download latest extra apps pack-](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps)\n\n[-Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/'${DRONE_TAG}'/flipper-z-f7-update-'${DRONE_TAG}'.tgz&channel=release-cfw&version='${DRONE_TAG}')\n\n[-Version without custom animations - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_no_anim/flipper-z-f7-update-'${DRONE_TAG}'n.tgz&channel=release-cfw&version='${DRONE_TAG}'n)\n\n[-Version with extra apps - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'e.tgz&channel=release-cfw&version='${DRONE_TAG}'e)'
|
||||
|
||||
- name: "Send extra pack build to telegram"
|
||||
image: appleboy/drone-telegram
|
||||
settings:
|
||||
token:
|
||||
from_secret: tgtoken
|
||||
to:
|
||||
from_secret: tgid
|
||||
format: markdown
|
||||
message: "Build with extra apps pack:"
|
||||
document:
|
||||
- flipper-z-f7-update-${DRONE_TAG}e.tgz
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- tag
|
||||
@@ -392,18 +380,6 @@ steps:
|
||||
document:
|
||||
- dev/flipper-z-f7-update-${DRONE_BUILD_NUMBER}.tgz
|
||||
|
||||
- name: "Send extra pack build to telegram"
|
||||
image: appleboy/drone-telegram
|
||||
settings:
|
||||
token:
|
||||
from_secret: tgtoken
|
||||
to:
|
||||
from_secret: tgid_dev
|
||||
format: markdown
|
||||
message: "Build with extra apps pack:"
|
||||
document:
|
||||
- flipper-z-f7-update-${DRONE_BUILD_NUMBER}e.tgz
|
||||
|
||||
- name: "Send discord notification"
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
|
||||
45
CHANGELOG.md
45
CHANGELOG.md
@@ -1,12 +1,41 @@
|
||||
### New changes
|
||||
* SubGHz: **Nice ON2E (Nice One)** support (by @assasinfil | PR #335)
|
||||
* SubGHz: Remove 467.75 From freq analyzer since it has too much noise (Frequency is still can be used, just excluded from FA to avoid false detections)
|
||||
* Archive and FileBrowser: **Fixed more navigation issues** (by @Willy-JL | PR #334)
|
||||
* Plugins -> SubGHz Bruteforcer: Fix Linear Delta 3 repeats (now its more stable and we will be sure signal is received correctly)
|
||||
* Plugins: Updated TOTP (Authenticator) [(by akopachov)](https://github.com/akopachov/flipper-zero_authenticator)
|
||||
* OFW: **Fix Cyfral & Metakom emulation (My temp fix removed and proper fix from OFW applied)**
|
||||
* OFW: BadUSB: disable CDC mode, USB mode switch fix
|
||||
* OFW: Updater visual fixes
|
||||
* API: Due to OFW changes API was updated to 14.x, extra pack was updated you can install it separatly or use build with extra pack included
|
||||
* SubGHz: **Fixed bug in SubGHz HAL, now CC1101 shutdowns properly, (also this fixed unstable TX)**
|
||||
* SubGHz: **Alutech AT-4N** encoder (support for sending signals) (by @assasinfil | PR #322)
|
||||
* SubGHz: **KingGates Stylo 4k** encoder (support for sending signals) (by @assasinfil | PR #321)
|
||||
* SubGHz: Added Debug Pin setting for protocol development and fixed debug (and sound) with internal module
|
||||
* SubGHz: GUI Fixes
|
||||
* SubGHz: Removed bugged Detect RAW feature, now its replaced with BinRAW
|
||||
* Plugins: SubGHz Bruteforcer - Added support for Linear Delta-3 310MHz
|
||||
* Plugins: Fix CTRL-SHIFT in mousejacker (by @notmarek | PR #316)
|
||||
* Infrared: Update universal remote assets (by @amec0e) (PR #318)
|
||||
* NFC: Add Mifare Classic keys (by @Bon-Jorik (scaff.walker) | PR #324)
|
||||
* Misc: Playing games now affect Flipper's level
|
||||
* OFW: Fixed typo in nfc_magic_scene_wrong_card.c
|
||||
* OFW: SubGhz: fix cc1101_read_fifo func
|
||||
* OFW: feat: add missing `const` qualifiers
|
||||
* OFW: **SubGhz: add protocol BinRAW (binarization of data quantized by the minimum correlated duration)**
|
||||
* OFW: Picopass: show elite key used from dictionary
|
||||
* OFW: Firmware fixes and improvements for flashing via blackmagic
|
||||
* OFW: fbt: building fap_dist for compact gh build; accessor: fixed for latest ibutton changes
|
||||
* OFW: Move CSN space to revent overflow
|
||||
* OFW: **SubGhz: add protocol KingGates Stylo4k**
|
||||
* OFW: **SubGhz: add protocol Nice One**
|
||||
* OFW: **SubGhz: add protocol Alutech at-4n**
|
||||
* OFW: **SubGhz: add DOOYA protocol**
|
||||
* OFW: **SubGhz: add protocol "Linear Delta-3"**
|
||||
* OFW: **SubGhz: Fix Raw write, add short duration filter setting**
|
||||
* OFW: Update Missing SD Card icon from PR 2373
|
||||
* OFW: SCons: do not include backup files in build
|
||||
* OFW: Fix minor UI inconsistencies and bugs
|
||||
* OFW: Allow use of any suitable pin for 1-Wire devices
|
||||
* OFW: **SD over SPI improvements**
|
||||
* OFW: Multitarget support for fbt (includes support for non released yet flipper hardware)
|
||||
* OFW: Pin Reset
|
||||
* OFW: nfc: Add mifare classic value block commands
|
||||
* OFW: battery info temperature shown in C or F based on settings
|
||||
* OFW: Script that can find programmer and flash firmware via it.
|
||||
* OFW: **SPI Mem Manager C port** (You can use flipper as programmer to flash supported chips)
|
||||
|
||||
#### [🎲 Download latest extra apps pack](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps)
|
||||
|
||||
|
||||
16
ReadMe.md
16
ReadMe.md
@@ -56,10 +56,6 @@ Our Discord Community:
|
||||
Also check the changelog in releases for latest updates!
|
||||
|
||||
### Current modified and new Sub-GHz protocols list:
|
||||
Thanks to Official team (to thier SubGHz Developer, Skorp) for implementing decoders for these protocols.
|
||||
|
||||
Encoders/sending made by Eng1n33r & @xMasterX:
|
||||
|
||||
- Keeloq [Not ALL systems supported for decode or emulation yet!] - [Supported manufacturers list](https://0bin.net/paste/VwR2lNJY#WH9vnPgvcp7w6zVKucFCuNREKAcOij8KsJ6vqLfMn3b)
|
||||
- Keeloq: HCS101
|
||||
- Keeloq: AN-Motors
|
||||
@@ -76,19 +72,15 @@ Encoders/sending made by Eng1n33r & @xMasterX:
|
||||
- BFT Mitto [External seed calculation required (For info contact me in Discord: Nano#8998)]
|
||||
- Security+ v1 & v2
|
||||
- Star Line
|
||||
|
||||
Encoders made by @assasinfil & @xMasterX:
|
||||
- Somfy Telis
|
||||
- Somfy Keytis
|
||||
- KingGates Stylo 4k
|
||||
- Alutech AT-4N
|
||||
- Nice ON2E (Nice One)
|
||||
- Somfy Telis (encoder by @assasinfil & @TQMatvey)
|
||||
- Somfy Keytis (encoder by @assasinfil)
|
||||
- KingGates Stylo 4k (encoder by @assasinfil)
|
||||
- Alutech AT-4N (encoder by @assasinfil)
|
||||
|
||||
## Please support development of the project
|
||||
The majority of this project is developed and maintained by me, @xMasterX.
|
||||
I'm unemployed because of the war, and the only income I receive is from your donations.
|
||||
Our team is small and the guys are working on this project as much as they can solely based on the enthusiasm they have for this project and the community.
|
||||
- @assasinfil - SubGHz
|
||||
- @Svaarich - UI design and animations
|
||||
- @Amec0e - Infrared assets
|
||||
- Community moderators in Telegram, Discord, and Reddit
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include <gui/modules/file_browser_worker.h>
|
||||
#include <fap_loader/fap_loader_app.h>
|
||||
#include <math.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
static void
|
||||
archive_folder_open_cb(void* context, uint32_t item_cnt, int32_t file_idx, bool is_root) {
|
||||
@@ -57,29 +56,16 @@ static void archive_list_load_cb(void* context, uint32_t list_load_offset) {
|
||||
false);
|
||||
}
|
||||
|
||||
static void archive_list_item_cb(
|
||||
void* context,
|
||||
FuriString* item_path,
|
||||
uint32_t idx,
|
||||
bool is_folder,
|
||||
bool is_last) {
|
||||
static void
|
||||
archive_list_item_cb(void* context, FuriString* item_path, bool is_folder, bool is_last) {
|
||||
furi_assert(context);
|
||||
UNUSED(idx);
|
||||
ArchiveBrowserView* browser = (ArchiveBrowserView*)context;
|
||||
|
||||
if(!is_last) {
|
||||
archive_add_file_item(browser, is_folder, furi_string_get_cstr(item_path));
|
||||
} else {
|
||||
with_view_model(
|
||||
browser->view,
|
||||
ArchiveBrowserViewModel * model,
|
||||
{
|
||||
if(model->item_cnt <= BROWSER_SORT_THRESHOLD) {
|
||||
files_array_sort(model->files);
|
||||
}
|
||||
model->list_loading = false;
|
||||
},
|
||||
true);
|
||||
browser->view, ArchiveBrowserViewModel * model, { model->list_loading = false; }, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +140,7 @@ void archive_update_focus(ArchiveBrowserView* browser, const char* target) {
|
||||
archive_get_items(browser, furi_string_get_cstr(browser->path));
|
||||
|
||||
if(!archive_file_get_array_size(browser) && archive_is_home(browser)) {
|
||||
archive_switch_tab(browser, TAB_LEFT);
|
||||
archive_switch_tab(browser, TAB_RIGHT);
|
||||
} else {
|
||||
with_view_model(
|
||||
browser->view,
|
||||
@@ -221,7 +207,7 @@ void archive_file_array_rm_selected(ArchiveBrowserView* browser) {
|
||||
false);
|
||||
|
||||
if((items_cnt == 0) && (archive_is_home(browser))) {
|
||||
archive_switch_tab(browser, TAB_LEFT);
|
||||
archive_switch_tab(browser, TAB_RIGHT);
|
||||
}
|
||||
|
||||
archive_update_offset(browser);
|
||||
@@ -470,13 +456,6 @@ void archive_switch_tab(ArchiveBrowserView* browser, InputKey key) {
|
||||
} else {
|
||||
tab = (tab + 1) % ArchiveTabTotal;
|
||||
}
|
||||
if(tab == ArchiveTabInternal && !furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
|
||||
if(key == InputKeyLeft) {
|
||||
tab = ((tab - 1) + ArchiveTabTotal) % ArchiveTabTotal;
|
||||
} else {
|
||||
tab = (tab + 1) % ArchiveTabTotal;
|
||||
}
|
||||
}
|
||||
|
||||
browser->is_root = true;
|
||||
archive_set_tab(browser, tab);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "../archive_i.h"
|
||||
#include <storage/storage.h>
|
||||
|
||||
#define TAB_LEFT InputKeyLeft // Default tab switch direction
|
||||
#define TAB_RIGHT InputKeyRight // Default tab switch direction
|
||||
#define TAB_DEFAULT ArchiveTabFavorites // Start tab
|
||||
#define FILE_LIST_BUF_LEN 50
|
||||
|
||||
@@ -17,7 +17,6 @@ static const char* tab_default_paths[] = {
|
||||
[ArchiveTabBadUsb] = ANY_PATH("badusb"),
|
||||
[ArchiveTabU2f] = "/app:u2f",
|
||||
[ArchiveTabApplications] = ANY_PATH("apps"),
|
||||
[ArchiveTabInternal] = STORAGE_INT_PATH_PREFIX,
|
||||
[ArchiveTabBrowser] = STORAGE_ANY_PATH_PREFIX,
|
||||
};
|
||||
|
||||
@@ -45,7 +44,6 @@ static const ArchiveFileTypeEnum known_type[] = {
|
||||
[ArchiveTabBadUsb] = ArchiveFileTypeBadUsb,
|
||||
[ArchiveTabU2f] = ArchiveFileTypeU2f,
|
||||
[ArchiveTabApplications] = ArchiveFileTypeApplication,
|
||||
[ArchiveTabInternal] = ArchiveFileTypeUnknown,
|
||||
[ArchiveTabBrowser] = ArchiveFileTypeUnknown,
|
||||
};
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include <m-array.h>
|
||||
#include <furi.h>
|
||||
#include <m-algo.h>
|
||||
#include <storage/storage.h>
|
||||
#include "toolbox/path.h"
|
||||
|
||||
@@ -82,29 +81,13 @@ static void ArchiveFile_t_clear(ArchiveFile_t* obj) {
|
||||
furi_string_free(obj->custom_name);
|
||||
}
|
||||
|
||||
static int ArchiveFile_t_cmp(const ArchiveFile_t* a, const ArchiveFile_t* b) {
|
||||
if(a->type == ArchiveFileTypeFolder && b->type != ArchiveFileTypeFolder) {
|
||||
return -1;
|
||||
}
|
||||
if(a->type != ArchiveFileTypeFolder && b->type == ArchiveFileTypeFolder) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return furi_string_cmpi(a->path, b->path);
|
||||
}
|
||||
|
||||
#define M_OPL_ArchiveFile_t() \
|
||||
(INIT(API_2(ArchiveFile_t_init)), \
|
||||
SET(API_6(ArchiveFile_t_set)), \
|
||||
INIT_SET(API_6(ArchiveFile_t_init_set)), \
|
||||
CLEAR(API_2(ArchiveFile_t_clear)), \
|
||||
CMP(API_6(ArchiveFile_t_cmp)), \
|
||||
SWAP(M_SWAP_DEFAULT), \
|
||||
EQUAL(API_6(M_EQUAL_DEFAULT)))
|
||||
|
||||
ARRAY_DEF(files_array, ArchiveFile_t)
|
||||
|
||||
ALGO_DEF(files_array, ARRAY_OPLIST(files_array, M_OPL_ArchiveFile_t()))
|
||||
ARRAY_DEF(
|
||||
files_array,
|
||||
ArchiveFile_t,
|
||||
(INIT(API_2(ArchiveFile_t_init)),
|
||||
SET(API_6(ArchiveFile_t_set)),
|
||||
INIT_SET(API_6(ArchiveFile_t_init_set)),
|
||||
CLEAR(API_2(ArchiveFile_t_clear))))
|
||||
|
||||
void archive_set_file_type(ArchiveFile_t* file, const char* path, bool is_folder, bool is_app);
|
||||
bool archive_get_items(void* context, const char* path);
|
||||
|
||||
@@ -19,7 +19,6 @@ static const char* ArchiveTabNames[] = {
|
||||
[ArchiveTabBadUsb] = "Bad USB",
|
||||
[ArchiveTabU2f] = "U2F",
|
||||
[ArchiveTabApplications] = "Apps",
|
||||
[ArchiveTabInternal] = "Internal",
|
||||
[ArchiveTabBrowser] = "Browser",
|
||||
};
|
||||
|
||||
@@ -398,20 +397,15 @@ static bool archive_view_input(InputEvent* event, void* context) {
|
||||
|
||||
bool in_menu;
|
||||
bool move_fav_mode;
|
||||
bool is_loading;
|
||||
with_view_model(
|
||||
browser->view,
|
||||
ArchiveBrowserViewModel * model,
|
||||
{
|
||||
in_menu = model->menu;
|
||||
move_fav_mode = model->move_fav;
|
||||
is_loading = model->folder_loading || model->list_loading;
|
||||
},
|
||||
false);
|
||||
|
||||
if(is_loading) {
|
||||
return false;
|
||||
}
|
||||
if(in_menu) {
|
||||
if(event->type != InputTypeShort) {
|
||||
return true; // RETURN
|
||||
@@ -487,7 +481,7 @@ static bool archive_view_input(InputEvent* event, void* context) {
|
||||
model->scroll_counter = 0;
|
||||
}
|
||||
},
|
||||
false);
|
||||
true);
|
||||
archive_update_offset(browser);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "../helpers/archive_files.h"
|
||||
#include "../helpers/archive_favorites.h"
|
||||
#include "../helpers/archive_menu.h"
|
||||
|
||||
#include <gui/gui_i.h>
|
||||
#include <gui/view.h>
|
||||
@@ -9,10 +10,7 @@
|
||||
#include <gui/elements.h>
|
||||
#include <gui/modules/file_browser_worker.h>
|
||||
#include <storage/storage.h>
|
||||
#include "../helpers/archive_files.h"
|
||||
#include "../helpers/archive_menu.h"
|
||||
#include "../helpers/archive_favorites.h"
|
||||
#include "gui/modules/file_browser_worker.h"
|
||||
#include <furi.h>
|
||||
|
||||
#define MAX_LEN_PX 110
|
||||
#define MAX_NAME_LEN 255
|
||||
@@ -31,7 +29,6 @@ typedef enum {
|
||||
ArchiveTabBadUsb,
|
||||
ArchiveTabU2f,
|
||||
ArchiveTabApplications,
|
||||
ArchiveTabInternal,
|
||||
ArchiveTabBrowser,
|
||||
ArchiveTabTotal,
|
||||
} ArchiveTabEnum;
|
||||
|
||||
@@ -115,12 +115,8 @@ BadUsbApp* bad_usb_app_alloc(char* arg) {
|
||||
|
||||
if(furi_hal_usb_is_locked()) {
|
||||
app->error = BadUsbAppErrorCloseRpc;
|
||||
app->usb_if_prev = NULL;
|
||||
scene_manager_next_scene(app->scene_manager, BadUsbSceneError);
|
||||
} else {
|
||||
app->usb_if_prev = furi_hal_usb_get_config();
|
||||
furi_check(furi_hal_usb_set_config(NULL, NULL));
|
||||
|
||||
if(!furi_string_empty(app->file_path)) {
|
||||
app->bad_usb_script = bad_usb_script_open(app->file_path);
|
||||
bad_usb_script_set_keyboard_layout(app->bad_usb_script, app->keyboard_layout);
|
||||
@@ -142,10 +138,6 @@ void bad_usb_app_free(BadUsbApp* app) {
|
||||
app->bad_usb_script = NULL;
|
||||
}
|
||||
|
||||
if(app->usb_if_prev) {
|
||||
furi_check(furi_hal_usb_set_config(app->usb_if_prev, NULL));
|
||||
}
|
||||
|
||||
// Views
|
||||
view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewWork);
|
||||
bad_usb_free(app->bad_usb_view);
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include <gui/modules/variable_item_list.h>
|
||||
#include <gui/modules/widget.h>
|
||||
#include "views/bad_usb_view.h"
|
||||
#include <furi_hal_usb.h>
|
||||
|
||||
#define BAD_USB_APP_BASE_FOLDER ANY_PATH("badusb")
|
||||
#define BAD_USB_APP_PATH_LAYOUT_FOLDER BAD_USB_APP_BASE_FOLDER "/assets/layouts"
|
||||
@@ -40,8 +39,6 @@ struct BadUsbApp {
|
||||
FuriString* keyboard_layout;
|
||||
BadUsb* bad_usb_view;
|
||||
BadUsbScript* bad_usb_script;
|
||||
|
||||
FuriHalUsbInterface* usb_if_prev;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -490,6 +490,8 @@ static int32_t bad_usb_worker(void* context) {
|
||||
BadUsbWorkerState worker_state = BadUsbStateInit;
|
||||
int32_t delay_val = 0;
|
||||
|
||||
FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config();
|
||||
|
||||
FURI_LOG_I(WORKER_TAG, "Init");
|
||||
File* script_file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
|
||||
bad_usb->line = furi_string_alloc();
|
||||
@@ -640,6 +642,8 @@ static int32_t bad_usb_worker(void* context) {
|
||||
|
||||
furi_hal_hid_set_state_callback(NULL, NULL);
|
||||
|
||||
furi_hal_usb_set_config(usb_mode_prev, NULL);
|
||||
|
||||
storage_file_close(script_file);
|
||||
storage_file_free(script_file);
|
||||
furi_string_free(bad_usb->line);
|
||||
|
||||
@@ -117,15 +117,16 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) {
|
||||
|
||||
// First stage: coarse scan
|
||||
for(size_t i = 0; i < subghz_setting_get_frequency_count(instance->setting); i++) {
|
||||
uint32_t current_frequnecy = subghz_setting_get_frequency(instance->setting, i);
|
||||
if(furi_hal_subghz_is_frequency_valid(current_frequnecy) &&
|
||||
(current_frequnecy != 467750000) &&
|
||||
if(furi_hal_subghz_is_frequency_valid(
|
||||
subghz_setting_get_frequency(instance->setting, i)) &&
|
||||
!((furi_hal_subghz.radio_type == SubGhzRadioExternal) &&
|
||||
(current_frequnecy >= 311900000 && current_frequnecy <= 312200000))) {
|
||||
(subghz_setting_get_frequency(instance->setting, i) >= 311900000 &&
|
||||
subghz_setting_get_frequency(instance->setting, i) <= 312200000))) {
|
||||
furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle);
|
||||
cc1101_switch_to_idle(furi_hal_subghz.spi_bus_handle);
|
||||
frequency =
|
||||
cc1101_set_frequency(furi_hal_subghz.spi_bus_handle, current_frequnecy);
|
||||
frequency = cc1101_set_frequency(
|
||||
furi_hal_subghz.spi_bus_handle,
|
||||
subghz_setting_get_frequency(instance->setting, i));
|
||||
|
||||
cc1101_calibrate(furi_hal_subghz.spi_bus_handle);
|
||||
do {
|
||||
|
||||
@@ -13,7 +13,7 @@ const char* const radio_modules_variables_text[] = {
|
||||
#define DEBUG_P_COUNT 2
|
||||
const char* const debug_pin_text[DEBUG_P_COUNT] = {
|
||||
"OFF",
|
||||
"17(1W)",
|
||||
"A7",
|
||||
};
|
||||
|
||||
static void subghz_scene_ext_module_changed(VariableItem* item) {
|
||||
|
||||
@@ -208,38 +208,27 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) {
|
||||
|
||||
flipper_format_free(temp_fm_preset2);
|
||||
|
||||
// Pagers
|
||||
// # HND - FM presets
|
||||
FlipperFormat* temp_fm_preset3 = flipper_format_string_alloc();
|
||||
flipper_format_write_string_cstr(
|
||||
temp_fm_preset3,
|
||||
(const char*)"Custom_preset_data",
|
||||
(const char*)"02 0D 07 04 08 32 0B 06 10 64 11 93 12 0C 13 02 14 00 15 15 18 18 19 16 1B 07 1C 00 1D 91 20 FB 21 56 22 10 00 00 C0 00 00 00 00 00 00 00");
|
||||
(const char*)"02 0D 0B 06 08 32 07 04 14 00 13 02 12 04 11 36 10 69 15 32 18 18 19 16 1D 91 1C 00 1B 07 20 FB 22 10 21 56 00 00 C0 00 00 00 00 00 00 00");
|
||||
flipper_format_rewind(temp_fm_preset3);
|
||||
subghz_setting_load_custom_preset(subghz->setting, (const char*)"Pagers", temp_fm_preset3);
|
||||
subghz_setting_load_custom_preset(subghz->setting, (const char*)"HND_1", temp_fm_preset3);
|
||||
|
||||
flipper_format_free(temp_fm_preset3);
|
||||
|
||||
// # HND - FM presets
|
||||
FlipperFormat* temp_fm_preset4 = flipper_format_string_alloc();
|
||||
flipper_format_write_string_cstr(
|
||||
temp_fm_preset4,
|
||||
(const char*)"Custom_preset_data",
|
||||
(const char*)"02 0D 0B 06 08 32 07 04 14 00 13 02 12 04 11 36 10 69 15 32 18 18 19 16 1D 91 1C 00 1B 07 20 FB 22 10 21 56 00 00 C0 00 00 00 00 00 00 00");
|
||||
(const char*)"02 0D 0B 06 08 32 07 04 14 00 13 02 12 07 11 36 10 E9 15 32 18 18 19 16 1D 92 1C 40 1B 03 20 FB 22 10 21 56 00 00 C0 00 00 00 00 00 00 00");
|
||||
flipper_format_rewind(temp_fm_preset4);
|
||||
subghz_setting_load_custom_preset(subghz->setting, (const char*)"HND_1", temp_fm_preset4);
|
||||
subghz_setting_load_custom_preset(subghz->setting, (const char*)"HND_2", temp_fm_preset4);
|
||||
|
||||
flipper_format_free(temp_fm_preset4);
|
||||
|
||||
FlipperFormat* temp_fm_preset5 = flipper_format_string_alloc();
|
||||
flipper_format_write_string_cstr(
|
||||
temp_fm_preset5,
|
||||
(const char*)"Custom_preset_data",
|
||||
(const char*)"02 0D 0B 06 08 32 07 04 14 00 13 02 12 07 11 36 10 E9 15 32 18 18 19 16 1D 92 1C 40 1B 03 20 FB 22 10 21 56 00 00 C0 00 00 00 00 00 00 00");
|
||||
flipper_format_rewind(temp_fm_preset5);
|
||||
subghz_setting_load_custom_preset(subghz->setting, (const char*)"HND_2", temp_fm_preset5);
|
||||
|
||||
flipper_format_free(temp_fm_preset5);
|
||||
|
||||
// custom presets loading - end
|
||||
|
||||
// Load last used values for Read, Read RAW, etc. or default
|
||||
|
||||
@@ -598,7 +598,7 @@ void subghz_hopper_update(SubGhz* subghz) {
|
||||
|
||||
void subghz_speaker_on(SubGhz* subghz) {
|
||||
if(subghz->txrx->debug_pin_state) {
|
||||
furi_hal_subghz_set_async_mirror_pin(&ibutton_gpio);
|
||||
furi_hal_subghz_set_async_mirror_pin(&gpio_ext_pa7);
|
||||
}
|
||||
|
||||
if(subghz->txrx->speaker_state == SubGhzSpeakerStateEnable) {
|
||||
@@ -643,7 +643,7 @@ void subghz_speaker_mute(SubGhz* subghz) {
|
||||
|
||||
void subghz_speaker_unmute(SubGhz* subghz) {
|
||||
if(subghz->txrx->debug_pin_state) {
|
||||
furi_hal_subghz_set_async_mirror_pin(&ibutton_gpio);
|
||||
furi_hal_subghz_set_async_mirror_pin(&gpio_ext_pa7);
|
||||
}
|
||||
if(subghz->txrx->speaker_state == SubGhzSpeakerStateEnable) {
|
||||
if(furi_hal_speaker_is_mine()) {
|
||||
|
||||
@@ -645,4 +645,4 @@ SubGHzFrequencyAnalyzerFeedbackLevel subghz_frequency_analyzer_feedback_level(
|
||||
float subghz_frequency_analyzer_get_trigger_level(SubGhzFrequencyAnalyzer* instance) {
|
||||
furi_assert(instance);
|
||||
return subghz_frequency_analyzer_worker_get_trigger_level(instance->worker);
|
||||
}
|
||||
}
|
||||
@@ -120,10 +120,7 @@ bool subghz_test_carrier_input(InputEvent* event, void* context) {
|
||||
furi_hal_subghz_rx();
|
||||
} else {
|
||||
furi_hal_gpio_init(
|
||||
furi_hal_subghz.cc1101_g0_pin,
|
||||
GpioModeOutputPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedLow);
|
||||
furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, true);
|
||||
if(!furi_hal_subghz_tx()) {
|
||||
furi_hal_gpio_init(
|
||||
|
||||
@@ -195,10 +195,6 @@ bool pocsag_pager_scene_receiver_on_event(void* context, SceneManagerEvent event
|
||||
pcsg_hopper_update(app);
|
||||
pocsag_pager_scene_receiver_update_statusbar(app);
|
||||
}
|
||||
// Get current RSSI
|
||||
float rssi = furi_hal_subghz_get_rssi();
|
||||
pcsg_receiver_rssi(app->pcsg_receiver, rssi);
|
||||
|
||||
if(app->txrx->txrx_state == PCSGTxRxStateRx) {
|
||||
notification_message(app->notifications, &sequence_blink_cyan_10);
|
||||
}
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
#define MENU_ITEMS 4u
|
||||
#define UNLOCK_CNT 3
|
||||
|
||||
#define SUBGHZ_RAW_TRESHOLD_MIN -90.0f
|
||||
|
||||
typedef struct {
|
||||
FuriString* item_str;
|
||||
uint8_t type;
|
||||
@@ -60,24 +58,8 @@ typedef struct {
|
||||
uint16_t list_offset;
|
||||
uint16_t history_item;
|
||||
PCSGReceiverBarShow bar_show;
|
||||
uint8_t u_rssi;
|
||||
} PCSGReceiverModel;
|
||||
|
||||
void pcsg_receiver_rssi(PCSGReceiver* instance, float rssi) {
|
||||
furi_assert(instance);
|
||||
with_view_model(
|
||||
instance->view,
|
||||
PCSGReceiverModel * model,
|
||||
{
|
||||
if(rssi < SUBGHZ_RAW_TRESHOLD_MIN) {
|
||||
model->u_rssi = 0;
|
||||
} else {
|
||||
model->u_rssi = (uint8_t)(rssi - SUBGHZ_RAW_TRESHOLD_MIN);
|
||||
}
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
void pcsg_view_receiver_set_lock(PCSGReceiver* pcsg_receiver, PCSGLock lock) {
|
||||
furi_assert(pcsg_receiver);
|
||||
pcsg_receiver->lock_count = 0;
|
||||
@@ -185,23 +167,13 @@ static void pcsg_view_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool scr
|
||||
canvas_draw_dot(canvas, scrollbar ? 121 : 126, (0 + idx * FRAME_HEIGHT) + 11);
|
||||
}
|
||||
|
||||
static void pcsg_view_rssi_draw(Canvas* canvas, PCSGReceiverModel* model) {
|
||||
for(uint8_t i = 1; i < model->u_rssi; i++) {
|
||||
if(i % 5) {
|
||||
canvas_draw_dot(canvas, 46 + i, 50);
|
||||
canvas_draw_dot(canvas, 47 + i, 51);
|
||||
canvas_draw_dot(canvas, 46 + i, 52);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pcsg_view_receiver_draw(Canvas* canvas, PCSGReceiverModel* model) {
|
||||
canvas_clear(canvas);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
|
||||
elements_button_left(canvas, "Config");
|
||||
//canvas_draw_line(canvas, 46, 51, 125, 51);
|
||||
canvas_draw_line(canvas, 46, 51, 125, 51);
|
||||
|
||||
bool scrollbar = model->history_item > 4;
|
||||
FuriString* str_buff;
|
||||
@@ -235,13 +207,10 @@ void pcsg_view_receiver_draw(Canvas* canvas, PCSGReceiverModel* model) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str(canvas, 63, 46, "Scanning...");
|
||||
//canvas_draw_line(canvas, 46, 51, 125, 51);
|
||||
canvas_draw_line(canvas, 46, 51, 125, 51);
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
}
|
||||
|
||||
// Draw RSSI
|
||||
pcsg_view_rssi_draw(canvas, model);
|
||||
|
||||
switch(model->bar_show) {
|
||||
case PCSGReceiverBarShowLock:
|
||||
canvas_draw_icon(canvas, 64, 55, &I_Lock_7x8);
|
||||
|
||||
@@ -8,8 +8,6 @@ typedef struct PCSGReceiver PCSGReceiver;
|
||||
|
||||
typedef void (*PCSGReceiverCallback)(PCSGCustomEvent event, void* context);
|
||||
|
||||
void pcsg_receiver_rssi(PCSGReceiver* instance, float rssi);
|
||||
|
||||
void pcsg_view_receiver_set_lock(PCSGReceiver* pcsg_receiver, PCSGLock keyboard);
|
||||
|
||||
void pcsg_view_receiver_set_callback(
|
||||
|
||||
Submodule applications/plugins/subbrute updated: 819b532937...94d417e6a4
@@ -34,10 +34,10 @@ void totp_cli_command_move_docopt_usage() {
|
||||
void totp_cli_command_move_docopt_options() {
|
||||
TOTP_CLI_PRINTF(" " DOCOPT_OPTION(
|
||||
TOTP_CLI_COMMAND_MOVE_ARG_NEW_NAME_PREFIX,
|
||||
DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_MOVE_ARG_NEW_NAME)) " New token name\r\n");
|
||||
DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_MOVE_ARG_NEW_NAME)) " New token name.\r\n");
|
||||
TOTP_CLI_PRINTF(" " DOCOPT_OPTION(
|
||||
TOTP_CLI_COMMAND_MOVE_ARG_NEW_INDEX_PREFIX,
|
||||
DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_MOVE_ARG_NEW_INDEX)) " New token index\r\n");
|
||||
DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_MOVE_ARG_NEW_INDEX)) " New token index.\r\n");
|
||||
}
|
||||
|
||||
void totp_cli_command_move_handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
|
||||
|
||||
@@ -20,7 +20,7 @@ void totp_cli_command_timezone_docopt_usage() {
|
||||
|
||||
void totp_cli_command_timezone_docopt_arguments() {
|
||||
TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_TIMEZONE_ARG_TIMEZONE
|
||||
" Timezone offset in hours to be set\r\n");
|
||||
" Timezone offset in hours to be set.\r\n");
|
||||
}
|
||||
|
||||
void totp_cli_command_timezone_handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
|
||||
|
||||
@@ -196,7 +196,7 @@ static TotpConfigFileOpenResult totp_open_config_file(Storage* storage, FlipperF
|
||||
return TotpConfigFileOpenSuccess;
|
||||
}
|
||||
|
||||
static TotpConfigFileUpdateResult
|
||||
TotpConfigFileUpdateResult
|
||||
totp_config_file_save_new_token_i(FlipperFormat* file, const TokenInfo* token_info) {
|
||||
TotpConfigFileUpdateResult update_result;
|
||||
do {
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include <flipper_format/flipper_format.h>
|
||||
#include <notification/notification.h>
|
||||
#include <notification/notification_messages.h>
|
||||
#include <dolphin/dolphin.h>
|
||||
#include "services/config/config.h"
|
||||
#include "types/plugin_state.h"
|
||||
#include "types/token_info.h"
|
||||
@@ -152,9 +151,6 @@ int32_t totp_app() {
|
||||
return 253;
|
||||
}
|
||||
|
||||
// Affecting dolphin level
|
||||
DOLPHIN_DEED(DolphinDeedPluginStart);
|
||||
|
||||
// Set system callbacks
|
||||
ViewPort* view_port = view_port_alloc();
|
||||
view_port_draw_callback_set(view_port, render_callback, &state_mutex);
|
||||
|
||||
@@ -195,10 +195,6 @@ bool weather_station_scene_receiver_on_event(void* context, SceneManagerEvent ev
|
||||
ws_hopper_update(app);
|
||||
weather_station_scene_receiver_update_statusbar(app);
|
||||
}
|
||||
// Get current RSSI
|
||||
float rssi = furi_hal_subghz_get_rssi();
|
||||
ws_receiver_rssi(app->ws_receiver, rssi);
|
||||
|
||||
if(app->txrx->txrx_state == WSTxRxStateRx) {
|
||||
notification_message(app->notifications, &sequence_blink_cyan_10);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#define MENU_ITEMS 4u
|
||||
#define UNLOCK_CNT 3
|
||||
|
||||
#define SUBGHZ_RAW_TRESHOLD_MIN -90.0f
|
||||
typedef struct {
|
||||
FuriString* item_str;
|
||||
uint8_t type;
|
||||
@@ -60,24 +59,8 @@ typedef struct {
|
||||
uint16_t list_offset;
|
||||
uint16_t history_item;
|
||||
WSReceiverBarShow bar_show;
|
||||
uint8_t u_rssi;
|
||||
} WSReceiverModel;
|
||||
|
||||
void ws_receiver_rssi(WSReceiver* instance, float rssi) {
|
||||
furi_assert(instance);
|
||||
with_view_model(
|
||||
instance->view,
|
||||
WSReceiverModel * model,
|
||||
{
|
||||
if(rssi < SUBGHZ_RAW_TRESHOLD_MIN) {
|
||||
model->u_rssi = 0;
|
||||
} else {
|
||||
model->u_rssi = (uint8_t)(rssi - SUBGHZ_RAW_TRESHOLD_MIN);
|
||||
}
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
void ws_view_receiver_set_lock(WSReceiver* ws_receiver, WSLock lock) {
|
||||
furi_assert(ws_receiver);
|
||||
ws_receiver->lock_count = 0;
|
||||
@@ -181,23 +164,13 @@ static void ws_view_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool scrol
|
||||
canvas_draw_dot(canvas, scrollbar ? 121 : 126, (0 + idx * FRAME_HEIGHT) + 11);
|
||||
}
|
||||
|
||||
static void ws_view_rssi_draw(Canvas* canvas, WSReceiverModel* model) {
|
||||
for(uint8_t i = 1; i < model->u_rssi; i++) {
|
||||
if(i % 5) {
|
||||
canvas_draw_dot(canvas, 46 + i, 50);
|
||||
canvas_draw_dot(canvas, 47 + i, 51);
|
||||
canvas_draw_dot(canvas, 46 + i, 52);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ws_view_receiver_draw(Canvas* canvas, WSReceiverModel* model) {
|
||||
canvas_clear(canvas);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
|
||||
elements_button_left(canvas, "Config");
|
||||
//canvas_draw_line(canvas, 46, 51, 125, 51);
|
||||
canvas_draw_line(canvas, 46, 51, 125, 51);
|
||||
|
||||
bool scrollbar = model->history_item > 4;
|
||||
FuriString* str_buff;
|
||||
@@ -230,13 +203,10 @@ void ws_view_receiver_draw(Canvas* canvas, WSReceiverModel* model) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str(canvas, 63, 46, "Scanning...");
|
||||
//canvas_draw_line(canvas, 46, 51, 125, 51);
|
||||
canvas_draw_line(canvas, 46, 51, 125, 51);
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
}
|
||||
|
||||
// Draw RSSI
|
||||
ws_view_rssi_draw(canvas, model);
|
||||
|
||||
switch(model->bar_show) {
|
||||
case WSReceiverBarShowLock:
|
||||
canvas_draw_icon(canvas, 64, 55, &I_Lock_7x8);
|
||||
|
||||
@@ -8,8 +8,6 @@ typedef struct WSReceiver WSReceiver;
|
||||
|
||||
typedef void (*WSReceiverCallback)(WSCustomEvent event, void* context);
|
||||
|
||||
void ws_receiver_rssi(WSReceiver* instance, float rssi);
|
||||
|
||||
void ws_view_receiver_set_lock(WSReceiver* ws_receiver, WSLock keyboard);
|
||||
|
||||
void ws_view_receiver_set_callback(
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <core/check.h>
|
||||
#include <core/common_defines.h>
|
||||
#include <core/log.h>
|
||||
#include "m-algo.h"
|
||||
#include <m-array.h>
|
||||
|
||||
#define LIST_ITEMS 5u
|
||||
@@ -34,7 +33,6 @@ typedef enum {
|
||||
} BrowserItemType;
|
||||
|
||||
typedef struct {
|
||||
uint32_t unsorted_idx;
|
||||
FuriString* path;
|
||||
BrowserItemType type;
|
||||
uint8_t* custom_icon_data;
|
||||
@@ -42,7 +40,6 @@ typedef struct {
|
||||
} BrowserItem_t;
|
||||
|
||||
static void BrowserItem_t_init(BrowserItem_t* obj) {
|
||||
obj->unsorted_idx = 0;
|
||||
obj->type = BrowserItemTypeLoading;
|
||||
obj->path = furi_string_alloc();
|
||||
obj->display_name = furi_string_alloc();
|
||||
@@ -50,7 +47,6 @@ static void BrowserItem_t_init(BrowserItem_t* obj) {
|
||||
}
|
||||
|
||||
static void BrowserItem_t_init_set(BrowserItem_t* obj, const BrowserItem_t* src) {
|
||||
obj->unsorted_idx = src->unsorted_idx;
|
||||
obj->type = src->type;
|
||||
obj->path = furi_string_alloc_set(src->path);
|
||||
obj->display_name = furi_string_alloc_set(src->display_name);
|
||||
@@ -63,7 +59,6 @@ static void BrowserItem_t_init_set(BrowserItem_t* obj, const BrowserItem_t* src)
|
||||
}
|
||||
|
||||
static void BrowserItem_t_set(BrowserItem_t* obj, const BrowserItem_t* src) {
|
||||
obj->unsorted_idx = src->unsorted_idx;
|
||||
obj->type = src->type;
|
||||
furi_string_set(obj->path, src->path);
|
||||
furi_string_set(obj->display_name, src->display_name);
|
||||
@@ -82,36 +77,13 @@ static void BrowserItem_t_clear(BrowserItem_t* obj) {
|
||||
}
|
||||
}
|
||||
|
||||
static int BrowserItem_t_cmp(const BrowserItem_t* a, const BrowserItem_t* b) {
|
||||
// Back indicator comes before everything, then folders, then all other files.
|
||||
if(a->type == BrowserItemTypeBack) {
|
||||
return -1;
|
||||
}
|
||||
if(b->type == BrowserItemTypeBack) {
|
||||
return 1;
|
||||
}
|
||||
if(a->type == BrowserItemTypeFolder && b->type != BrowserItemTypeFolder) {
|
||||
return -1;
|
||||
}
|
||||
if(a->type != BrowserItemTypeFolder && b->type == BrowserItemTypeFolder) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return furi_string_cmpi(a->path, b->path);
|
||||
}
|
||||
|
||||
#define M_OPL_BrowserItem_t() \
|
||||
(INIT(API_2(BrowserItem_t_init)), \
|
||||
SET(API_6(BrowserItem_t_set)), \
|
||||
INIT_SET(API_6(BrowserItem_t_init_set)), \
|
||||
CLEAR(API_2(BrowserItem_t_clear)), \
|
||||
CMP(API_6(BrowserItem_t_cmp)), \
|
||||
SWAP(M_SWAP_DEFAULT), \
|
||||
EQUAL(API_6(M_EQUAL_DEFAULT)))
|
||||
|
||||
ARRAY_DEF(items_array, BrowserItem_t)
|
||||
|
||||
ALGO_DEF(items_array, ARRAY_OPLIST(items_array, M_OPL_BrowserItem_t()))
|
||||
ARRAY_DEF(
|
||||
items_array,
|
||||
BrowserItem_t,
|
||||
(INIT(API_2(BrowserItem_t_init)),
|
||||
SET(API_6(BrowserItem_t_set)),
|
||||
INIT_SET(API_6(BrowserItem_t_init_set)),
|
||||
CLEAR(API_2(BrowserItem_t_clear))))
|
||||
|
||||
struct FileBrowser {
|
||||
View* view;
|
||||
@@ -161,12 +133,8 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context);
|
||||
static void
|
||||
browser_folder_open_cb(void* context, uint32_t item_cnt, int32_t file_idx, bool is_root);
|
||||
static void browser_list_load_cb(void* context, uint32_t list_load_offset);
|
||||
static void browser_list_item_cb(
|
||||
void* context,
|
||||
FuriString* item_path,
|
||||
uint32_t idx,
|
||||
bool is_folder,
|
||||
bool is_last);
|
||||
static void
|
||||
browser_list_item_cb(void* context, FuriString* item_path, bool is_folder, bool is_last);
|
||||
static void browser_long_load_cb(void* context);
|
||||
|
||||
static void file_browser_scroll_timer_callback(void* context) {
|
||||
@@ -355,7 +323,7 @@ static void browser_update_offset(FileBrowser* browser) {
|
||||
CLAMP(model->item_idx - 1, (int32_t)model->item_cnt - bounds, 0);
|
||||
}
|
||||
},
|
||||
true);
|
||||
false);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -387,7 +355,7 @@ static void
|
||||
model->list_loading = true;
|
||||
model->folder_loading = false;
|
||||
},
|
||||
false);
|
||||
true);
|
||||
browser_update_offset(browser);
|
||||
|
||||
file_browser_worker_load(browser->worker, load_offset, ITEM_LIST_LEN_MAX);
|
||||
@@ -420,18 +388,13 @@ static void browser_list_load_cb(void* context, uint32_t list_load_offset) {
|
||||
BrowserItem_t_clear(&back_item);
|
||||
}
|
||||
|
||||
static void browser_list_item_cb(
|
||||
void* context,
|
||||
FuriString* item_path,
|
||||
uint32_t idx,
|
||||
bool is_folder,
|
||||
bool is_last) {
|
||||
static void
|
||||
browser_list_item_cb(void* context, FuriString* item_path, bool is_folder, bool is_last) {
|
||||
furi_assert(context);
|
||||
FileBrowser* browser = (FileBrowser*)context;
|
||||
|
||||
BrowserItem_t item;
|
||||
item.custom_icon_data = NULL;
|
||||
item.unsorted_idx = idx;
|
||||
|
||||
if(!is_last) {
|
||||
item.path = furi_string_alloc_set(item_path);
|
||||
@@ -467,7 +430,7 @@ static void browser_list_item_cb(
|
||||
items_array_push_back(model->items, item);
|
||||
// TODO: calculate if element is visible
|
||||
},
|
||||
false);
|
||||
true);
|
||||
furi_string_free(item.display_name);
|
||||
furi_string_free(item.path);
|
||||
if(item.custom_icon_data) {
|
||||
@@ -475,31 +438,7 @@ static void browser_list_item_cb(
|
||||
}
|
||||
} else {
|
||||
with_view_model(
|
||||
browser->view,
|
||||
FileBrowserModel * model,
|
||||
{
|
||||
if(model->item_cnt <= BROWSER_SORT_THRESHOLD) {
|
||||
FuriString* selected = NULL;
|
||||
if(model->item_idx > 0) {
|
||||
selected = furi_string_alloc_set(
|
||||
items_array_get(model->items, model->item_idx)->path);
|
||||
}
|
||||
|
||||
items_array_sort(model->items);
|
||||
|
||||
if(selected != NULL) {
|
||||
for(uint32_t i = 0; i < model->item_cnt; i++) {
|
||||
if(!furi_string_cmp(items_array_get(model->items, i)->path, selected)) {
|
||||
model->item_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
model->list_loading = false;
|
||||
},
|
||||
false);
|
||||
browser_update_offset(browser);
|
||||
browser->view, FileBrowserModel * model, { model->list_loading = false; }, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -546,25 +485,19 @@ static void browser_draw_list(Canvas* canvas, FileBrowserModel* model) {
|
||||
for(uint32_t i = 0; i < MIN(model->item_cnt, LIST_ITEMS); i++) {
|
||||
int32_t idx = CLAMP((uint32_t)(i + model->list_offset), model->item_cnt, 0u);
|
||||
|
||||
BrowserItemType item_type;
|
||||
BrowserItemType item_type = BrowserItemTypeLoading;
|
||||
uint8_t* custom_icon_data = NULL;
|
||||
|
||||
if(browser_is_item_in_array(model, idx)) {
|
||||
BrowserItem_t* item = items_array_get(
|
||||
model->items, CLAMP(idx - model->array_offset, (int32_t)(array_size - 1), 0));
|
||||
item_type = item->type;
|
||||
if(model->list_loading && item_type != BrowserItemTypeBack) {
|
||||
furi_string_set(filename, "---");
|
||||
item_type = BrowserItemTypeLoading;
|
||||
} else {
|
||||
furi_string_set(filename, item->display_name);
|
||||
if(item_type == BrowserItemTypeFile) {
|
||||
custom_icon_data = item->custom_icon_data;
|
||||
}
|
||||
furi_string_set(filename, item->display_name);
|
||||
if(item_type == BrowserItemTypeFile) {
|
||||
custom_icon_data = item->custom_icon_data;
|
||||
}
|
||||
} else {
|
||||
furi_string_set(filename, "---");
|
||||
item_type = BrowserItemTypeLoading;
|
||||
}
|
||||
|
||||
if(item_type == BrowserItemTypeBack) {
|
||||
@@ -646,10 +579,7 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) {
|
||||
bool is_loading = false;
|
||||
|
||||
with_view_model(
|
||||
browser->view,
|
||||
FileBrowserModel * model,
|
||||
{ is_loading = model->folder_loading || model->list_loading; },
|
||||
false);
|
||||
browser->view, FileBrowserModel * model, { is_loading = model->folder_loading; }, false);
|
||||
|
||||
if(is_loading) {
|
||||
return false;
|
||||
@@ -686,7 +616,7 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) {
|
||||
model->scroll_counter = 0;
|
||||
}
|
||||
},
|
||||
false);
|
||||
true);
|
||||
browser_update_offset(browser);
|
||||
consumed = true;
|
||||
}
|
||||
@@ -701,7 +631,10 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) {
|
||||
if(browser_is_item_in_array(model, model->item_idx)) {
|
||||
selected_item =
|
||||
items_array_get(model->items, model->item_idx - model->array_offset);
|
||||
select_index = selected_item->unsorted_idx;
|
||||
select_index = model->item_idx;
|
||||
if((!model->is_root) && (select_index > 0)) {
|
||||
select_index -= 1;
|
||||
}
|
||||
}
|
||||
},
|
||||
false);
|
||||
|
||||
@@ -189,12 +189,8 @@ static bool browser_folder_init(
|
||||
return state;
|
||||
}
|
||||
|
||||
// Load files list by chunks, like it was originally, not compatible with sorting, sorting needs to be disabled to use this
|
||||
static bool browser_folder_load_chunked(
|
||||
BrowserWorker* browser,
|
||||
FuriString* path,
|
||||
uint32_t offset,
|
||||
uint32_t count) {
|
||||
static bool
|
||||
browser_folder_load(BrowserWorker* browser, FuriString* path, uint32_t offset, uint32_t count) {
|
||||
FileInfo file_info;
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
@@ -244,11 +240,7 @@ static bool browser_folder_load_chunked(
|
||||
furi_string_printf(name_str, "%s/%s", furi_string_get_cstr(path), name_temp);
|
||||
if(browser->list_item_cb) {
|
||||
browser->list_item_cb(
|
||||
browser->cb_ctx,
|
||||
name_str,
|
||||
items_cnt,
|
||||
(file_info.flags & FSF_DIRECTORY),
|
||||
false);
|
||||
browser->cb_ctx, name_str, (file_info.flags & FSF_DIRECTORY), false);
|
||||
}
|
||||
items_cnt++;
|
||||
}
|
||||
@@ -257,7 +249,7 @@ static bool browser_folder_load_chunked(
|
||||
}
|
||||
}
|
||||
if(browser->list_item_cb) {
|
||||
browser->list_item_cb(browser->cb_ctx, NULL, 0, false, true);
|
||||
browser->list_item_cb(browser->cb_ctx, NULL, false, true);
|
||||
}
|
||||
} while(0);
|
||||
|
||||
@@ -271,59 +263,6 @@ static bool browser_folder_load_chunked(
|
||||
return (items_cnt == count);
|
||||
}
|
||||
|
||||
// Load all files at once, may cause memory overflow so need to limit that to about 400 files
|
||||
static bool browser_folder_load_full(BrowserWorker* browser, FuriString* path) {
|
||||
FileInfo file_info;
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
File* directory = storage_file_alloc(storage);
|
||||
|
||||
char name_temp[FILE_NAME_LEN_MAX];
|
||||
FuriString* name_str;
|
||||
name_str = furi_string_alloc();
|
||||
|
||||
uint32_t items_cnt = 0;
|
||||
|
||||
bool ret = false;
|
||||
do {
|
||||
if(!storage_dir_open(directory, furi_string_get_cstr(path))) {
|
||||
break;
|
||||
}
|
||||
if(browser->list_load_cb) {
|
||||
browser->list_load_cb(browser->cb_ctx, 0);
|
||||
}
|
||||
while(storage_dir_read(directory, &file_info, name_temp, FILE_NAME_LEN_MAX) &&
|
||||
storage_file_get_error(directory) == FSE_OK) {
|
||||
furi_string_set(name_str, name_temp);
|
||||
if(browser_filter_by_name(browser, name_str, (file_info.flags & FSF_DIRECTORY))) {
|
||||
furi_string_printf(name_str, "%s/%s", furi_string_get_cstr(path), name_temp);
|
||||
if(browser->list_item_cb) {
|
||||
browser->list_item_cb(
|
||||
browser->cb_ctx,
|
||||
name_str,
|
||||
items_cnt,
|
||||
(file_info.flags & FSF_DIRECTORY),
|
||||
false);
|
||||
}
|
||||
items_cnt++;
|
||||
}
|
||||
}
|
||||
if(browser->list_item_cb) {
|
||||
browser->list_item_cb(browser->cb_ctx, NULL, 0, false, true);
|
||||
}
|
||||
ret = true;
|
||||
} while(0);
|
||||
|
||||
furi_string_free(name_str);
|
||||
|
||||
storage_dir_close(directory);
|
||||
storage_file_free(directory);
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t browser_worker(void* context) {
|
||||
BrowserWorker* browser = (BrowserWorker*)context;
|
||||
furi_assert(browser);
|
||||
@@ -418,12 +357,7 @@ static int32_t browser_worker(void* context) {
|
||||
if(flags & WorkerEvtLoad) {
|
||||
FURI_LOG_D(
|
||||
TAG, "Load offset: %lu cnt: %lu", browser->load_offset, browser->load_count);
|
||||
if(items_cnt > BROWSER_SORT_THRESHOLD) {
|
||||
browser_folder_load_chunked(
|
||||
browser, path, browser->load_offset, browser->load_count);
|
||||
} else {
|
||||
browser_folder_load_full(browser, path);
|
||||
}
|
||||
browser_folder_load(browser, path, browser->load_offset, browser->load_count);
|
||||
}
|
||||
|
||||
if(flags & WorkerEvtStop) {
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BROWSER_SORT_THRESHOLD 400
|
||||
|
||||
typedef struct BrowserWorker BrowserWorker;
|
||||
typedef void (*BrowserWorkerFolderOpenCallback)(
|
||||
void* context,
|
||||
@@ -19,7 +17,6 @@ typedef void (*BrowserWorkerListLoadCallback)(void* context, uint32_t list_load_
|
||||
typedef void (*BrowserWorkerListItemCallback)(
|
||||
void* context,
|
||||
FuriString* item_path,
|
||||
uint32_t idx,
|
||||
bool is_folder,
|
||||
bool is_last);
|
||||
typedef void (*BrowserWorkerLongLoadCallback)(void* context);
|
||||
|
||||
@@ -58,12 +58,8 @@ bool updater_scene_error_on_event(void* context, SceneManagerEvent event) {
|
||||
}
|
||||
|
||||
void updater_scene_error_on_exit(void* context) {
|
||||
furi_assert(context);
|
||||
Updater* updater = (Updater*)context;
|
||||
|
||||
widget_reset(updater->widget);
|
||||
|
||||
if(updater->loaded_manifest) {
|
||||
update_manifest_free(updater->loaded_manifest);
|
||||
}
|
||||
free(updater->pending_update);
|
||||
}
|
||||
|
||||
@@ -21,9 +21,11 @@ void updater_scene_loadcfg_apply_callback(GuiButtonType result, InputType type,
|
||||
|
||||
void updater_scene_loadcfg_on_enter(void* context) {
|
||||
Updater* updater = (Updater*)context;
|
||||
UpdateManifest* loaded_manifest = updater->loaded_manifest = update_manifest_alloc();
|
||||
UpdaterManifestProcessingState* pending_upd = updater->pending_update =
|
||||
malloc(sizeof(UpdaterManifestProcessingState));
|
||||
pending_upd->manifest = update_manifest_alloc();
|
||||
|
||||
if(update_manifest_init(loaded_manifest, furi_string_get_cstr(updater->startup_arg))) {
|
||||
if(update_manifest_init(pending_upd->manifest, furi_string_get_cstr(updater->startup_arg))) {
|
||||
widget_add_string_element(
|
||||
updater->widget, 64, 12, AlignCenter, AlignCenter, FontPrimary, "Update");
|
||||
|
||||
@@ -35,7 +37,7 @@ void updater_scene_loadcfg_on_enter(void* context) {
|
||||
32,
|
||||
AlignCenter,
|
||||
AlignCenter,
|
||||
furi_string_get_cstr(loaded_manifest->version),
|
||||
furi_string_get_cstr(pending_upd->manifest->version),
|
||||
true);
|
||||
|
||||
widget_add_button_element(
|
||||
@@ -93,12 +95,13 @@ bool updater_scene_loadcfg_on_event(void* context, SceneManagerEvent event) {
|
||||
}
|
||||
|
||||
void updater_scene_loadcfg_on_exit(void* context) {
|
||||
furi_assert(context);
|
||||
Updater* updater = (Updater*)context;
|
||||
|
||||
widget_reset(updater->widget);
|
||||
|
||||
if(updater->loaded_manifest) {
|
||||
update_manifest_free(updater->loaded_manifest);
|
||||
if(updater->pending_update) {
|
||||
update_manifest_free(updater->pending_update->manifest);
|
||||
furi_string_free(updater->pending_update->message);
|
||||
}
|
||||
|
||||
widget_reset(updater->widget);
|
||||
free(updater->pending_update);
|
||||
}
|
||||
|
||||
@@ -33,6 +33,12 @@ typedef enum {
|
||||
UpdaterCustomEventSdUnmounted,
|
||||
} UpdaterCustomEvent;
|
||||
|
||||
typedef struct UpdaterManifestProcessingState {
|
||||
UpdateManifest* manifest;
|
||||
FuriString* message;
|
||||
bool ready_to_be_applied;
|
||||
} UpdaterManifestProcessingState;
|
||||
|
||||
typedef struct {
|
||||
// GUI
|
||||
Gui* gui;
|
||||
@@ -43,7 +49,7 @@ typedef struct {
|
||||
|
||||
UpdaterMainView* main_view;
|
||||
|
||||
UpdateManifest* loaded_manifest;
|
||||
UpdaterManifestProcessingState* pending_update;
|
||||
UpdatePrepareResult preparation_result;
|
||||
|
||||
UpdateTask* update_task;
|
||||
|
||||
@@ -41,22 +41,22 @@ typedef struct {
|
||||
static const UpdateTaskStageGroupMap update_task_stage_progress[] = {
|
||||
[UpdateTaskStageProgress] = STAGE_DEF(UpdateTaskStageGroupMisc, 0),
|
||||
|
||||
[UpdateTaskStageReadManifest] = STAGE_DEF(UpdateTaskStageGroupPreUpdate, 45),
|
||||
[UpdateTaskStageLfsBackup] = STAGE_DEF(UpdateTaskStageGroupPreUpdate, 5),
|
||||
[UpdateTaskStageReadManifest] = STAGE_DEF(UpdateTaskStageGroupPreUpdate, 5),
|
||||
[UpdateTaskStageLfsBackup] = STAGE_DEF(UpdateTaskStageGroupPreUpdate, 15),
|
||||
|
||||
[UpdateTaskStageRadioImageValidate] = STAGE_DEF(UpdateTaskStageGroupRadio, 15),
|
||||
[UpdateTaskStageRadioErase] = STAGE_DEF(UpdateTaskStageGroupRadio, 35),
|
||||
[UpdateTaskStageRadioWrite] = STAGE_DEF(UpdateTaskStageGroupRadio, 60),
|
||||
[UpdateTaskStageRadioInstall] = STAGE_DEF(UpdateTaskStageGroupRadio, 30),
|
||||
[UpdateTaskStageRadioBusy] = STAGE_DEF(UpdateTaskStageGroupRadio, 5),
|
||||
[UpdateTaskStageRadioErase] = STAGE_DEF(UpdateTaskStageGroupRadio, 60),
|
||||
[UpdateTaskStageRadioWrite] = STAGE_DEF(UpdateTaskStageGroupRadio, 80),
|
||||
[UpdateTaskStageRadioInstall] = STAGE_DEF(UpdateTaskStageGroupRadio, 60),
|
||||
[UpdateTaskStageRadioBusy] = STAGE_DEF(UpdateTaskStageGroupRadio, 80),
|
||||
|
||||
[UpdateTaskStageOBValidation] = STAGE_DEF(UpdateTaskStageGroupOptionBytes, 2),
|
||||
[UpdateTaskStageOBValidation] = STAGE_DEF(UpdateTaskStageGroupOptionBytes, 10),
|
||||
|
||||
[UpdateTaskStageValidateDFUImage] = STAGE_DEF(UpdateTaskStageGroupFirmware, 30),
|
||||
[UpdateTaskStageFlashWrite] = STAGE_DEF(UpdateTaskStageGroupFirmware, 150),
|
||||
[UpdateTaskStageFlashValidate] = STAGE_DEF(UpdateTaskStageGroupFirmware, 15),
|
||||
[UpdateTaskStageValidateDFUImage] = STAGE_DEF(UpdateTaskStageGroupFirmware, 50),
|
||||
[UpdateTaskStageFlashWrite] = STAGE_DEF(UpdateTaskStageGroupFirmware, 200),
|
||||
[UpdateTaskStageFlashValidate] = STAGE_DEF(UpdateTaskStageGroupFirmware, 30),
|
||||
|
||||
[UpdateTaskStageLfsRestore] = STAGE_DEF(UpdateTaskStageGroupPostUpdate, 5),
|
||||
[UpdateTaskStageLfsRestore] = STAGE_DEF(UpdateTaskStageGroupPostUpdate, 30),
|
||||
|
||||
[UpdateTaskStageResourcesUpdate] = STAGE_DEF(UpdateTaskStageGroupResources, 255),
|
||||
[UpdateTaskStageSplashscreenInstall] = STAGE_DEF(UpdateTaskStageGroupSplashscreen, 5),
|
||||
|
||||
@@ -41,14 +41,6 @@ static bool update_task_pre_update(UpdateTask* update_task) {
|
||||
return success;
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
UpdateTaskResourcesWeightsFileCleanup = 20,
|
||||
UpdateTaskResourcesWeightsDirCleanup = 20,
|
||||
UpdateTaskResourcesWeightsFileUnpack = 60,
|
||||
} UpdateTaskResourcesWeights;
|
||||
|
||||
#define UPDATE_TASK_RESOURCES_FILE_TO_TOTAL_PERCENT 90
|
||||
|
||||
typedef struct {
|
||||
UpdateTask* update_task;
|
||||
int32_t total_files, processed_files;
|
||||
@@ -62,36 +54,33 @@ static bool update_task_resource_unpack_cb(const char* name, bool is_directory,
|
||||
update_task_set_progress(
|
||||
unpack_progress->update_task,
|
||||
UpdateTaskStageProgress,
|
||||
/* For this stage, last progress segment = extraction */
|
||||
(UpdateTaskResourcesWeightsFileCleanup + UpdateTaskResourcesWeightsDirCleanup) +
|
||||
(unpack_progress->processed_files * UpdateTaskResourcesWeightsFileUnpack) /
|
||||
(unpack_progress->total_files + 1));
|
||||
/* For this stage, last 70% of progress = extraction */
|
||||
30 + (unpack_progress->processed_files * 70) / (unpack_progress->total_files + 1));
|
||||
return true;
|
||||
}
|
||||
|
||||
static void update_task_cleanup_resources(UpdateTask* update_task, const uint32_t n_tar_entries) {
|
||||
static void
|
||||
update_task_cleanup_resources(UpdateTask* update_task, uint32_t n_approx_file_entries) {
|
||||
ResourceManifestReader* manifest_reader = resource_manifest_reader_alloc(update_task->storage);
|
||||
do {
|
||||
FURI_LOG_D(TAG, "Cleaning up old manifest");
|
||||
FURI_LOG_I(TAG, "Cleaning up old manifest");
|
||||
if(!resource_manifest_reader_open(manifest_reader, EXT_PATH("Manifest"))) {
|
||||
FURI_LOG_W(TAG, "No existing manifest");
|
||||
break;
|
||||
}
|
||||
|
||||
const uint32_t n_approx_file_entries =
|
||||
n_tar_entries * UPDATE_TASK_RESOURCES_FILE_TO_TOTAL_PERCENT / 100 + 1;
|
||||
uint32_t n_dir_entries = 1;
|
||||
/* We got # of entries in TAR file. Approx 1/4th is dir entries, we skip them */
|
||||
n_approx_file_entries = n_approx_file_entries * 3 / 4 + 1;
|
||||
uint32_t n_processed_files = 0;
|
||||
|
||||
ResourceManifestEntry* entry_ptr = NULL;
|
||||
uint32_t n_processed_entries = 0;
|
||||
while((entry_ptr = resource_manifest_reader_next(manifest_reader))) {
|
||||
if(entry_ptr->type == ResourceManifestEntryTypeFile) {
|
||||
update_task_set_progress(
|
||||
update_task,
|
||||
UpdateTaskStageProgress,
|
||||
/* For this stage, first pass = old manifest's file cleanup */
|
||||
(n_processed_entries++ * UpdateTaskResourcesWeightsFileCleanup) /
|
||||
n_approx_file_entries);
|
||||
/* For this stage, first 20% of progress = cleanup files */
|
||||
(n_processed_files++ * 20) / (n_approx_file_entries + 1));
|
||||
|
||||
FuriString* file_path = furi_string_alloc();
|
||||
path_concat(
|
||||
@@ -99,21 +88,16 @@ static void update_task_cleanup_resources(UpdateTask* update_task, const uint32_
|
||||
FURI_LOG_D(TAG, "Removing %s", furi_string_get_cstr(file_path));
|
||||
storage_simply_remove(update_task->storage, furi_string_get_cstr(file_path));
|
||||
furi_string_free(file_path);
|
||||
} else if(entry_ptr->type == ResourceManifestEntryTypeDirectory) {
|
||||
n_dir_entries++;
|
||||
}
|
||||
}
|
||||
|
||||
n_processed_entries = 0;
|
||||
while((entry_ptr = resource_manifest_reader_previous(manifest_reader))) {
|
||||
if(entry_ptr->type == ResourceManifestEntryTypeDirectory) {
|
||||
update_task_set_progress(
|
||||
update_task,
|
||||
UpdateTaskStageProgress,
|
||||
/* For this stage, second 10% of progress = cleanup directories */
|
||||
UpdateTaskResourcesWeightsFileCleanup +
|
||||
(n_processed_entries++ * UpdateTaskResourcesWeightsDirCleanup) /
|
||||
n_dir_entries);
|
||||
(n_processed_files++ * 10) / (n_approx_file_entries + 1));
|
||||
|
||||
FuriString* folder_path = furi_string_alloc();
|
||||
File* folder_file = storage_file_alloc(update_task->storage);
|
||||
|
||||
@@ -44,15 +44,13 @@ volatile FuriHalSubGhz furi_hal_subghz = {
|
||||
bool furi_hal_subghz_set_radio_type(SubGhzRadioType state) {
|
||||
furi_hal_subghz.radio_type = state;
|
||||
furi_hal_spi_bus_handle_deinit(furi_hal_subghz.spi_bus_handle);
|
||||
|
||||
if(furi_hal_subghz.radio_type == SubGhzRadioInternal) {
|
||||
furi_hal_subghz.spi_bus_handle = &furi_hal_spi_bus_handle_subghz;
|
||||
furi_hal_subghz.cc1101_g0_pin = &gpio_cc1101_g0;
|
||||
} else {
|
||||
if(state) {
|
||||
furi_hal_subghz.spi_bus_handle = &furi_hal_spi_bus_handle_subghz_ext;
|
||||
furi_hal_subghz.cc1101_g0_pin = &gpio_cc1101_g0_ext;
|
||||
} else {
|
||||
furi_hal_subghz.spi_bus_handle = &furi_hal_spi_bus_handle_subghz;
|
||||
furi_hal_subghz.cc1101_g0_pin = &gpio_cc1101_g0;
|
||||
}
|
||||
|
||||
furi_hal_spi_bus_handle_init(furi_hal_subghz.spi_bus_handle);
|
||||
furi_hal_subghz_init_check();
|
||||
return true;
|
||||
@@ -123,26 +121,37 @@ bool furi_hal_subghz_init_check(void) {
|
||||
|
||||
// Prepare GD0 for power on self test
|
||||
furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
// GD0 low
|
||||
cc1101_write_reg(furi_hal_subghz.spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHW);
|
||||
uint32_t test_start_time = furi_get_tick();
|
||||
while(furi_hal_gpio_read(furi_hal_subghz.cc1101_g0_pin) != false && result) {
|
||||
if(furi_get_tick() - test_start_time > INIT_TIMEOUT) {
|
||||
result = false;
|
||||
if(furi_hal_subghz.radio_type == SubGhzRadioExternal) {
|
||||
// GD0 low
|
||||
cc1101_write_reg(furi_hal_subghz.spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHW);
|
||||
uint32_t test_start_time = furi_get_tick();
|
||||
while(furi_hal_gpio_read(furi_hal_subghz.cc1101_g0_pin) != false && result) {
|
||||
if(furi_get_tick() - test_start_time > INIT_TIMEOUT) {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GD0 high
|
||||
cc1101_write_reg(
|
||||
furi_hal_subghz.spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV);
|
||||
test_start_time = furi_get_tick();
|
||||
while(furi_hal_gpio_read(furi_hal_subghz.cc1101_g0_pin) != true && result) {
|
||||
if(furi_get_tick() - test_start_time > INIT_TIMEOUT) {
|
||||
result = false;
|
||||
// GD0 high
|
||||
cc1101_write_reg(
|
||||
furi_hal_subghz.spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV);
|
||||
test_start_time = furi_get_tick();
|
||||
while(furi_hal_gpio_read(furi_hal_subghz.cc1101_g0_pin) != true && result) {
|
||||
if(furi_get_tick() - test_start_time > INIT_TIMEOUT) {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// GD0 low
|
||||
cc1101_write_reg(furi_hal_subghz.spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHW);
|
||||
while(furi_hal_gpio_read(&gpio_cc1101_g0) != false)
|
||||
;
|
||||
|
||||
// GD0 high
|
||||
cc1101_write_reg(
|
||||
furi_hal_subghz.spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV);
|
||||
while(furi_hal_gpio_read(&gpio_cc1101_g0) != true)
|
||||
;
|
||||
}
|
||||
// Reset GD0 to floating state
|
||||
cc1101_write_reg(furi_hal_subghz.spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHighImpedance);
|
||||
furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
@@ -424,8 +433,8 @@ bool furi_hal_subghz_is_tx_allowed(uint32_t value) {
|
||||
flipper_format_free(fff_data_file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
if(!(value >= 299999755 && value <= 350000335) && // was increased from 348 to 350
|
||||
!(value >= 386999938 && value <= 467750000) && // was increased from 464 to 467.75
|
||||
if(!(value >= 299999755 && value <= 350000335) &&
|
||||
!(value >= 386999938 && value <= 464000000) &&
|
||||
!(value >= 778999847 && value <= 928000000) && !(is_extended)) {
|
||||
FURI_LOG_I(TAG, "Frequency blocked - outside default range");
|
||||
return false;
|
||||
@@ -505,55 +514,56 @@ volatile uint32_t furi_hal_subghz_capture_delta_duration = 0;
|
||||
volatile FuriHalSubGhzCaptureCallback furi_hal_subghz_capture_callback = NULL;
|
||||
volatile void* furi_hal_subghz_capture_callback_context = NULL;
|
||||
|
||||
static void furi_hal_subghz_capture_int_ISR() {
|
||||
// Channel 1
|
||||
if(LL_TIM_IsActiveFlag_CC1(TIM2)) {
|
||||
LL_TIM_ClearFlag_CC1(TIM2);
|
||||
furi_hal_subghz_capture_delta_duration = LL_TIM_IC_GetCaptureCH1(TIM2);
|
||||
if(furi_hal_subghz_capture_callback) {
|
||||
if(furi_hal_subghz.async_mirror_pin != NULL)
|
||||
furi_hal_gpio_write(furi_hal_subghz.async_mirror_pin, false);
|
||||
static void furi_hal_subghz_capture_ISR() {
|
||||
if(furi_hal_subghz.radio_type == SubGhzRadioExternal) {
|
||||
if(!furi_hal_gpio_read(furi_hal_subghz.cc1101_g0_pin)) {
|
||||
if(furi_hal_subghz_capture_callback) {
|
||||
if(furi_hal_subghz.async_mirror_pin != NULL)
|
||||
furi_hal_gpio_write(furi_hal_subghz.async_mirror_pin, false);
|
||||
|
||||
furi_hal_subghz_capture_callback(
|
||||
true,
|
||||
furi_hal_subghz_capture_delta_duration,
|
||||
(void*)furi_hal_subghz_capture_callback_context);
|
||||
}
|
||||
}
|
||||
// Channel 2
|
||||
if(LL_TIM_IsActiveFlag_CC2(TIM2)) {
|
||||
LL_TIM_ClearFlag_CC2(TIM2);
|
||||
if(furi_hal_subghz_capture_callback) {
|
||||
if(furi_hal_subghz.async_mirror_pin != NULL)
|
||||
furi_hal_gpio_write(furi_hal_subghz.async_mirror_pin, true);
|
||||
|
||||
furi_hal_subghz_capture_callback(
|
||||
false,
|
||||
LL_TIM_IC_GetCaptureCH2(TIM2) - furi_hal_subghz_capture_delta_duration,
|
||||
(void*)furi_hal_subghz_capture_callback_context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void furi_hal_subghz_capture_ext_ISR() {
|
||||
if(!furi_hal_gpio_read(furi_hal_subghz.cc1101_g0_pin)) {
|
||||
if(furi_hal_subghz_capture_callback) {
|
||||
if(furi_hal_subghz.async_mirror_pin != NULL)
|
||||
furi_hal_gpio_write(furi_hal_subghz.async_mirror_pin, false);
|
||||
|
||||
furi_hal_subghz_capture_callback(
|
||||
true, TIM2->CNT, (void*)furi_hal_subghz_capture_callback_context);
|
||||
furi_hal_subghz_capture_callback(
|
||||
true, TIM2->CNT, (void*)furi_hal_subghz_capture_callback_context);
|
||||
}
|
||||
} else {
|
||||
if(furi_hal_subghz_capture_callback) {
|
||||
if(furi_hal_subghz.async_mirror_pin != NULL)
|
||||
furi_hal_gpio_write(furi_hal_subghz.async_mirror_pin, true);
|
||||
|
||||
furi_hal_subghz_capture_callback(
|
||||
false, TIM2->CNT, (void*)furi_hal_subghz_capture_callback_context);
|
||||
}
|
||||
}
|
||||
//Forced correction for improved accuracy
|
||||
TIM2->CNT = 7;
|
||||
} else {
|
||||
if(furi_hal_subghz_capture_callback) {
|
||||
if(furi_hal_subghz.async_mirror_pin != NULL)
|
||||
furi_hal_gpio_write(furi_hal_subghz.async_mirror_pin, true);
|
||||
// Channel 1
|
||||
if(LL_TIM_IsActiveFlag_CC1(TIM2)) {
|
||||
LL_TIM_ClearFlag_CC1(TIM2);
|
||||
furi_hal_subghz_capture_delta_duration = LL_TIM_IC_GetCaptureCH1(TIM2);
|
||||
if(furi_hal_subghz_capture_callback) {
|
||||
if(furi_hal_subghz.async_mirror_pin != NULL)
|
||||
furi_hal_gpio_write(furi_hal_subghz.async_mirror_pin, false);
|
||||
|
||||
furi_hal_subghz_capture_callback(
|
||||
false, TIM2->CNT, (void*)furi_hal_subghz_capture_callback_context);
|
||||
furi_hal_subghz_capture_callback(
|
||||
true,
|
||||
furi_hal_subghz_capture_delta_duration,
|
||||
(void*)furi_hal_subghz_capture_callback_context);
|
||||
}
|
||||
}
|
||||
// Channel 2
|
||||
if(LL_TIM_IsActiveFlag_CC2(TIM2)) {
|
||||
LL_TIM_ClearFlag_CC2(TIM2);
|
||||
if(furi_hal_subghz_capture_callback) {
|
||||
if(furi_hal_subghz.async_mirror_pin != NULL)
|
||||
furi_hal_gpio_write(furi_hal_subghz.async_mirror_pin, true);
|
||||
|
||||
furi_hal_subghz_capture_callback(
|
||||
false,
|
||||
LL_TIM_IC_GetCaptureCH2(TIM2) - furi_hal_subghz_capture_delta_duration,
|
||||
(void*)furi_hal_subghz_capture_callback_context);
|
||||
}
|
||||
}
|
||||
}
|
||||
TIM2->CNT = 6;
|
||||
}
|
||||
|
||||
void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void* context) {
|
||||
@@ -563,27 +573,43 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void*
|
||||
furi_hal_subghz_capture_callback = callback;
|
||||
furi_hal_subghz_capture_callback_context = context;
|
||||
|
||||
if(furi_hal_subghz.radio_type == SubGhzRadioExternal) {
|
||||
furi_hal_gpio_init(
|
||||
furi_hal_subghz.cc1101_g0_pin,
|
||||
GpioModeInterruptRiseFall,
|
||||
GpioPullUp,
|
||||
GpioSpeedVeryHigh);
|
||||
furi_hal_gpio_add_int_callback(
|
||||
furi_hal_subghz.cc1101_g0_pin,
|
||||
furi_hal_subghz_capture_ISR,
|
||||
furi_hal_subghz_capture_callback);
|
||||
furi_hal_gpio_enable_int_callback(furi_hal_subghz.cc1101_g0_pin);
|
||||
} else {
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_cc1101_g0, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn1TIM2);
|
||||
}
|
||||
|
||||
// Timer: base
|
||||
LL_TIM_InitTypeDef TIM_InitStruct = {0};
|
||||
TIM_InitStruct.Prescaler = 64 - 1;
|
||||
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
|
||||
TIM_InitStruct.Autoreload = 0x7FFFFFFE;
|
||||
// Clock division for capture filter (for internal radio)
|
||||
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV4;
|
||||
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV4; // Clock division for capture filter
|
||||
LL_TIM_Init(TIM2, &TIM_InitStruct);
|
||||
|
||||
// Timer: advanced
|
||||
LL_TIM_SetClockSource(TIM2, LL_TIM_CLOCKSOURCE_INTERNAL);
|
||||
LL_TIM_DisableARRPreload(TIM2);
|
||||
LL_TIM_DisableDMAReq_TRIG(TIM2);
|
||||
LL_TIM_DisableIT_TRIG(TIM2);
|
||||
|
||||
if(furi_hal_subghz.radio_type == SubGhzRadioInternal) {
|
||||
LL_TIM_SetTriggerInput(TIM2, LL_TIM_TS_TI2FP2);
|
||||
LL_TIM_SetSlaveMode(TIM2, LL_TIM_SLAVEMODE_RESET);
|
||||
LL_TIM_SetTriggerOutput(TIM2, LL_TIM_TRGO_RESET);
|
||||
LL_TIM_EnableMasterSlaveMode(TIM2);
|
||||
}
|
||||
LL_TIM_DisableDMAReq_TRIG(TIM2);
|
||||
LL_TIM_DisableIT_TRIG(TIM2);
|
||||
|
||||
if(furi_hal_subghz.radio_type == SubGhzRadioInternal) {
|
||||
// Timer: channel 1 indirect
|
||||
LL_TIM_IC_SetActiveInput(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_ACTIVEINPUT_INDIRECTTI);
|
||||
LL_TIM_IC_SetPrescaler(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_ICPSC_DIV1);
|
||||
@@ -597,31 +623,13 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void*
|
||||
LL_TIM_IC_SetFilter(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_IC_FILTER_FDIV32_N8);
|
||||
|
||||
// ISR setup
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, furi_hal_subghz_capture_int_ISR, NULL);
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, furi_hal_subghz_capture_ISR, NULL);
|
||||
|
||||
// Interrupts and channels
|
||||
LL_TIM_EnableIT_CC1(TIM2);
|
||||
LL_TIM_EnableIT_CC2(TIM2);
|
||||
LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH1);
|
||||
LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH2);
|
||||
|
||||
furi_hal_gpio_init_ex(
|
||||
furi_hal_subghz.cc1101_g0_pin,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedLow,
|
||||
GpioAltFn1TIM2);
|
||||
} else {
|
||||
furi_hal_gpio_init(
|
||||
furi_hal_subghz.cc1101_g0_pin,
|
||||
GpioModeInterruptRiseFall,
|
||||
GpioPullUp,
|
||||
GpioSpeedVeryHigh);
|
||||
furi_hal_gpio_add_int_callback(
|
||||
furi_hal_subghz.cc1101_g0_pin,
|
||||
furi_hal_subghz_capture_ext_ISR,
|
||||
furi_hal_subghz_capture_callback);
|
||||
furi_hal_gpio_enable_int_callback(furi_hal_subghz.cc1101_g0_pin);
|
||||
}
|
||||
|
||||
// Start timer
|
||||
@@ -654,9 +662,6 @@ void furi_hal_subghz_stop_async_rx() {
|
||||
FURI_CRITICAL_EXIT();
|
||||
if(furi_hal_subghz.radio_type == SubGhzRadioInternal) {
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, NULL, NULL);
|
||||
} else {
|
||||
furi_hal_gpio_disable_int_callback(furi_hal_subghz.cc1101_g0_pin);
|
||||
furi_hal_gpio_remove_int_callback(furi_hal_subghz.cc1101_g0_pin);
|
||||
}
|
||||
|
||||
furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
@@ -791,19 +796,18 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
|
||||
furi_hal_subghz_async_tx.buffer =
|
||||
malloc(API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL * sizeof(uint32_t));
|
||||
|
||||
if(furi_hal_subghz.radio_type == SubGhzRadioInternal) {
|
||||
if(furi_hal_subghz.radio_type == SubGhzRadioExternal) {
|
||||
furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, true);
|
||||
furi_hal_gpio_init(
|
||||
furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||
} else {
|
||||
// Connect CC1101_GD0 to TIM2 as output
|
||||
furi_hal_gpio_init_ex(
|
||||
furi_hal_subghz.cc1101_g0_pin,
|
||||
&gpio_cc1101_g0,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullDown,
|
||||
GpioSpeedLow,
|
||||
GpioAltFn1TIM2);
|
||||
} else {
|
||||
//Signal generation with mem-to-mem DMA
|
||||
furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, true);
|
||||
furi_hal_gpio_init(
|
||||
furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||
}
|
||||
|
||||
// Configure DMA
|
||||
@@ -864,28 +868,22 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
|
||||
LL_TIM_SetCounter(TIM2, 0);
|
||||
LL_TIM_EnableCounter(TIM2);
|
||||
|
||||
// Start debug
|
||||
if(furi_hal_subghz_start_debug() || furi_hal_subghz.radio_type == SubGhzRadioExternal) {
|
||||
const GpioPin* gpio = furi_hal_subghz.cc1101_g0_pin;
|
||||
//Preparing bit mask
|
||||
//Debug pin is may be only PORTB! (PB0, PB1, .., PB15)
|
||||
furi_hal_subghz_debug_gpio_buff[0] = 0;
|
||||
furi_hal_subghz_debug_gpio_buff[1] = 0;
|
||||
//Signal generation for external module
|
||||
|
||||
//Mirror pin (for example, speaker)
|
||||
if(furi_hal_subghz.async_mirror_pin != NULL) {
|
||||
furi_hal_subghz_debug_gpio_buff[0] |= (uint32_t)furi_hal_subghz.async_mirror_pin->pin
|
||||
<< GPIO_NUMBER;
|
||||
furi_hal_subghz_debug_gpio_buff[1] |= furi_hal_subghz.async_mirror_pin->pin;
|
||||
gpio = furi_hal_subghz.async_mirror_pin;
|
||||
}
|
||||
// Start debug (and speaker)
|
||||
furi_hal_subghz_start_debug();
|
||||
|
||||
//G0 singnal generation for external radio
|
||||
if(furi_hal_subghz.radio_type == SubGhzRadioExternal) {
|
||||
furi_hal_subghz_debug_gpio_buff[0] |= (uint32_t)furi_hal_subghz.cc1101_g0_pin->pin
|
||||
<< GPIO_NUMBER;
|
||||
furi_hal_subghz_debug_gpio_buff[1] |= furi_hal_subghz.cc1101_g0_pin->pin;
|
||||
}
|
||||
const GpioPin* gpio = furi_hal_subghz.cc1101_g0_pin;
|
||||
|
||||
if((furi_hal_subghz.async_mirror_pin != NULL) &&
|
||||
(furi_hal_subghz.radio_type == SubGhzRadioInternal)) {
|
||||
gpio = furi_hal_subghz.async_mirror_pin;
|
||||
}
|
||||
if(((furi_hal_subghz.async_mirror_pin != NULL) &&
|
||||
(furi_hal_subghz.radio_type == SubGhzRadioInternal)) ||
|
||||
(furi_hal_subghz.radio_type == SubGhzRadioExternal)) {
|
||||
furi_hal_subghz_debug_gpio_buff[0] = (uint32_t)gpio->pin << GPIO_NUMBER;
|
||||
furi_hal_subghz_debug_gpio_buff[1] = gpio->pin;
|
||||
|
||||
dma_config.MemoryOrM2MDstAddress = (uint32_t)furi_hal_subghz_debug_gpio_buff;
|
||||
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (gpio->port->BSRR);
|
||||
|
||||
@@ -340,7 +340,7 @@ static void usb_process_mode_start(FuriHalUsbInterface* interface, void* context
|
||||
}
|
||||
|
||||
static void usb_process_mode_change(FuriHalUsbInterface* interface, void* context) {
|
||||
if((interface != usb.interface) || (context != usb.interface_context)) {
|
||||
if(interface != usb.interface) {
|
||||
if(usb.enabled) {
|
||||
// Disable current interface
|
||||
susp_evt(&udev, 0, 0);
|
||||
|
||||
@@ -237,8 +237,10 @@ void ibutton_worker_emulate_timer_cb(void* context) {
|
||||
const LevelDuration level_duration =
|
||||
protocol_dict_encoder_yield(worker->protocols, worker->protocol_to_encode);
|
||||
|
||||
furi_hal_ibutton_emulate_set_next(level_duration_get_duration(level_duration));
|
||||
furi_hal_ibutton_pin_write(level_duration_get_level(level_duration));
|
||||
const bool level = level_duration_get_level(level_duration);
|
||||
|
||||
furi_hal_ibutton_emulate_set_next(level);
|
||||
furi_hal_ibutton_pin_write(level);
|
||||
}
|
||||
|
||||
void ibutton_worker_emulate_timer_start(iButtonWorker* worker) {
|
||||
|
||||
@@ -100,7 +100,7 @@ void* subghz_protocol_encoder_nice_flor_s_alloc(SubGhzEnvironment* environment)
|
||||
TAG, "Loading rainbow table from %s", instance->nice_flor_s_rainbow_table_file_name);
|
||||
}
|
||||
instance->encoder.repeat = 10;
|
||||
instance->encoder.size_upload = 2400; //wrong!! upload 186*16 = 2976 - actual size about 1728
|
||||
instance->encoder.size_upload = 1728; //wrong!! upload 186*16 = 2976 - actual size about 1728
|
||||
instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration));
|
||||
instance->encoder.is_running = false;
|
||||
return instance;
|
||||
@@ -113,8 +113,6 @@ void subghz_protocol_encoder_nice_flor_s_free(void* context) {
|
||||
free(instance);
|
||||
}
|
||||
|
||||
static void subghz_protocol_nice_one_get_data(uint8_t* p, uint8_t num_parcel, uint8_t hold_bit);
|
||||
|
||||
/**
|
||||
* Generating an upload from data.
|
||||
* @param instance Pointer to a SubGhzProtocolEncoderNiceFlorS instance
|
||||
@@ -162,8 +160,8 @@ static void subghz_protocol_encoder_nice_flor_s_get_upload(
|
||||
level_duration_make(false, (uint32_t)subghz_protocol_nice_flor_s_const.te_short * 3);
|
||||
|
||||
//Send key data
|
||||
for(uint8_t j = 52; j > 0; j--) {
|
||||
if(bit_read(instance->generic.data, j - 1)) {
|
||||
for(uint8_t i = instance->generic.data_count_bit; i > 0; i--) {
|
||||
if(bit_read(instance->generic.data, i - 1)) {
|
||||
//send bit 1
|
||||
instance->encoder.upload[index++] =
|
||||
level_duration_make(true, (uint32_t)subghz_protocol_nice_flor_s_const.te_long);
|
||||
@@ -177,35 +175,6 @@ static void subghz_protocol_encoder_nice_flor_s_get_upload(
|
||||
false, (uint32_t)subghz_protocol_nice_flor_s_const.te_long);
|
||||
}
|
||||
}
|
||||
if(instance->generic.data_count_bit == NICE_ONE_COUNT_BIT) {
|
||||
uint8_t add_data[10] = {0};
|
||||
for(size_t i = 0; i < 7; i++) {
|
||||
add_data[i] = (instance->generic.data >> (48 - i * 8)) & 0xFF;
|
||||
}
|
||||
subghz_protocol_nice_one_get_data(add_data, loops[i], loops[i]);
|
||||
instance->generic.data_2 = 0;
|
||||
for(size_t j = 7; j < 10; j++) {
|
||||
instance->generic.data_2 <<= 8;
|
||||
instance->generic.data_2 += add_data[j];
|
||||
}
|
||||
|
||||
//Send key data
|
||||
for(uint8_t j = 24; j > 4; j--) {
|
||||
if(bit_read(instance->generic.data_2, j - 1)) {
|
||||
//send bit 1
|
||||
instance->encoder.upload[index++] = level_duration_make(
|
||||
true, (uint32_t)subghz_protocol_nice_flor_s_const.te_long);
|
||||
instance->encoder.upload[index++] = level_duration_make(
|
||||
false, (uint32_t)subghz_protocol_nice_flor_s_const.te_short);
|
||||
} else {
|
||||
//send bit 0
|
||||
instance->encoder.upload[index++] = level_duration_make(
|
||||
true, (uint32_t)subghz_protocol_nice_flor_s_const.te_short);
|
||||
instance->encoder.upload[index++] = level_duration_make(
|
||||
false, (uint32_t)subghz_protocol_nice_flor_s_const.te_long);
|
||||
}
|
||||
}
|
||||
}
|
||||
//Send stop bit
|
||||
instance->encoder.upload[index++] =
|
||||
level_duration_make(true, (uint32_t)subghz_protocol_nice_flor_s_const.te_short * 3);
|
||||
@@ -228,8 +197,6 @@ bool subghz_protocol_encoder_nice_flor_s_deserialize(void* context, FlipperForma
|
||||
//optional parameter parameter
|
||||
flipper_format_read_uint32(
|
||||
flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1);
|
||||
// flipper_format_read_uint32(
|
||||
// flipper_format, "Data", (uint32_t*)&instance->generic.data_2, 1);
|
||||
|
||||
subghz_protocol_nice_flor_s_remote_controller(
|
||||
&instance->generic, instance->nice_flor_s_rainbow_table_file_name);
|
||||
@@ -249,17 +216,6 @@ bool subghz_protocol_encoder_nice_flor_s_deserialize(void* context, FlipperForma
|
||||
break;
|
||||
}
|
||||
|
||||
if(instance->generic.data_count_bit == NICE_ONE_COUNT_BIT) {
|
||||
if(!flipper_format_rewind(flipper_format)) {
|
||||
FURI_LOG_E(TAG, "Rewind error");
|
||||
break;
|
||||
}
|
||||
uint32_t temp = (instance->generic.data_2 >> 4) & 0xFFFFF;
|
||||
if(!flipper_format_update_uint32(flipper_format, "Data", &temp, 1)) {
|
||||
FURI_LOG_E(TAG, "Unable to add Data");
|
||||
}
|
||||
}
|
||||
|
||||
instance->encoder.is_running = true;
|
||||
|
||||
res = true;
|
||||
@@ -291,63 +247,63 @@ LevelDuration subghz_protocol_encoder_nice_flor_s_yield(void* context) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read bytes from rainbow table
|
||||
* @param p array[10] P0-P1|P2-P3-P4-P5-P6-P7-P8-P9-P10
|
||||
* @return crc
|
||||
*/
|
||||
static uint32_t subghz_protocol_nice_one_crc(uint8_t* p) {
|
||||
uint8_t crc = 0;
|
||||
uint8_t crc_data = 0xff;
|
||||
for(uint8_t i = 4; i < 68; i++) {
|
||||
if(subghz_protocol_blocks_get_bit_array(p, i)) {
|
||||
crc = crc_data ^ 1;
|
||||
} else {
|
||||
crc = crc_data;
|
||||
}
|
||||
crc_data >>= 1;
|
||||
if((crc & 0x01)) {
|
||||
crc_data ^= 0x97;
|
||||
}
|
||||
}
|
||||
crc = 0;
|
||||
for(uint8_t i = 0; i < 8; i++) {
|
||||
crc <<= 1;
|
||||
if((crc_data >> i) & 0x01) crc = crc | 1;
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
// /**
|
||||
// * Read bytes from rainbow table
|
||||
// * @param p array[10] P0-P1|P2-P3-P4-P5-P6-P7-P8-P9-P10
|
||||
// * @return crc
|
||||
// */
|
||||
// static uint32_t subghz_protocol_nice_one_crc(uint8_t* p) {
|
||||
// uint8_t crc = 0;
|
||||
// uint8_t crc_data = 0xff;
|
||||
// for(uint8_t i = 4; i < 68; i++) {
|
||||
// if(subghz_protocol_blocks_get_bit_array(p, i)) {
|
||||
// crc = crc_data ^ 1;
|
||||
// } else {
|
||||
// crc = crc_data;
|
||||
// }
|
||||
// crc_data >>= 1;
|
||||
// if((crc & 0x01)) {
|
||||
// crc_data ^= 0x97;
|
||||
// }
|
||||
// }
|
||||
// crc = 0;
|
||||
// for(uint8_t i = 0; i < 8; i++) {
|
||||
// crc <<= 1;
|
||||
// if((crc_data >> i) & 0x01) crc = crc | 1;
|
||||
// }
|
||||
// return crc;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Read bytes from rainbow table
|
||||
* @param p array[10] P0-P1|P2-P3-P4-P5-P6-P7-XX-XX-XX
|
||||
* @param num_parcel parcel number 0..15
|
||||
* @param hold_bit 0 - the button was only pressed, 1 - the button was held down
|
||||
*/
|
||||
static void subghz_protocol_nice_one_get_data(uint8_t* p, uint8_t num_parcel, uint8_t hold_bit) {
|
||||
uint8_t k = 0;
|
||||
uint8_t crc = 0;
|
||||
p[1] = (p[1] & 0x0f) | ((0x0f ^ (p[0] & 0x0F) ^ num_parcel) << 4);
|
||||
if(num_parcel < 4) {
|
||||
k = 0x8f;
|
||||
} else {
|
||||
k = 0x80;
|
||||
}
|
||||
// /**
|
||||
// * Read bytes from rainbow table
|
||||
// * @param p array[10] P0-P1|P2-P3-P4-P5-P6-P7-XX-XX-XX
|
||||
// * @param num_parcel parcel number 0..15
|
||||
// * @param hold_bit 0 - the button was only pressed, 1 - the button was held down
|
||||
// */
|
||||
// static void subghz_protocol_nice_one_get_data(uint8_t* p, uint8_t num_parcel, uint8_t hold_bit) {
|
||||
// uint8_t k = 0;
|
||||
// uint8_t crc = 0;
|
||||
// p[1] = (p[1] & 0x0f) | ((0x0f ^ (p[0] & 0x0F) ^ num_parcel) << 4);
|
||||
// if(num_parcel < 4) {
|
||||
// k = 0x8f;
|
||||
// } else {
|
||||
// k = 0x80;
|
||||
// }
|
||||
|
||||
if(!hold_bit) {
|
||||
hold_bit = 0;
|
||||
} else {
|
||||
hold_bit = 0x10;
|
||||
}
|
||||
k = num_parcel ^ k;
|
||||
p[7] = k;
|
||||
p[8] = hold_bit ^ (k << 4);
|
||||
// if(!hold_bit) {
|
||||
// hold_bit = 0;
|
||||
// } else {
|
||||
// hold_bit = 0x10;
|
||||
// }
|
||||
// k = num_parcel ^ k;
|
||||
// p[7] = k;
|
||||
// p[8] = hold_bit ^ (k << 4);
|
||||
|
||||
crc = subghz_protocol_nice_one_crc(p);
|
||||
// crc = subghz_protocol_nice_one_crc(p);
|
||||
|
||||
p[8] |= crc >> 4;
|
||||
p[9] = crc << 4;
|
||||
}
|
||||
// p[8] |= crc >> 4;
|
||||
// p[9] = crc << 4;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Read bytes from rainbow table
|
||||
|
||||
@@ -1,309 +0,0 @@
|
||||
#include "revers.h"
|
||||
|
||||
#include "../blocks/const.h"
|
||||
#include "../blocks/decoder.h"
|
||||
#include "../blocks/encoder.h"
|
||||
#include "../blocks/generic.h"
|
||||
#include "../blocks/math.h"
|
||||
|
||||
#define TAG "SubGhzProtocolRevers"
|
||||
|
||||
static const SubGhzBlockConst subghz_protocol_revers_const = {
|
||||
.te_short = 200,
|
||||
.te_long = 430,
|
||||
.te_delta = 80,
|
||||
.min_count_bit_for_found = 8,
|
||||
};
|
||||
|
||||
struct SubGhzProtocolDecoderRevers {
|
||||
SubGhzProtocolDecoderBase base;
|
||||
|
||||
SubGhzBlockDecoder decoder;
|
||||
SubGhzBlockGeneric generic;
|
||||
|
||||
uint32_t last_data;
|
||||
uint16_t header_count;
|
||||
};
|
||||
|
||||
struct SubGhzProtocolEncoderRevers {
|
||||
SubGhzProtocolEncoderBase base;
|
||||
|
||||
SubGhzProtocolBlockEncoder encoder;
|
||||
SubGhzBlockGeneric generic;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
ReversDecoderStepReset = 0,
|
||||
ReversDecoderStepCheckPreambula,
|
||||
ReversDecoderStepSaveDuration,
|
||||
ReversDecoderStepCheckDuration,
|
||||
} ReversDecoderStep;
|
||||
|
||||
const SubGhzProtocolDecoder subghz_protocol_revers_decoder = {
|
||||
.alloc = subghz_protocol_decoder_revers_alloc,
|
||||
.free = subghz_protocol_decoder_revers_free,
|
||||
|
||||
.feed = subghz_protocol_decoder_revers_feed,
|
||||
.reset = subghz_protocol_decoder_revers_reset,
|
||||
|
||||
.get_hash_data = subghz_protocol_decoder_revers_get_hash_data,
|
||||
.serialize = subghz_protocol_decoder_revers_serialize,
|
||||
.deserialize = subghz_protocol_decoder_revers_deserialize,
|
||||
.get_string = subghz_protocol_decoder_revers_get_string,
|
||||
};
|
||||
|
||||
const SubGhzProtocolEncoder subghz_protocol_revers_encoder = {
|
||||
.alloc = subghz_protocol_encoder_revers_alloc,
|
||||
.free = subghz_protocol_encoder_revers_free,
|
||||
|
||||
.deserialize = subghz_protocol_encoder_revers_deserialize,
|
||||
.stop = subghz_protocol_encoder_revers_stop,
|
||||
.yield = subghz_protocol_encoder_revers_yield,
|
||||
};
|
||||
|
||||
const SubGhzProtocol subghz_protocol_revers = {
|
||||
.name = SUBGHZ_PROTOCOL_REVERS_NAME,
|
||||
.type = SubGhzProtocolTypeStatic,
|
||||
.flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable |
|
||||
SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send,
|
||||
|
||||
.decoder = &subghz_protocol_revers_decoder,
|
||||
.encoder = &subghz_protocol_revers_encoder,
|
||||
};
|
||||
|
||||
void* subghz_protocol_encoder_revers_alloc(SubGhzEnvironment* environment) {
|
||||
UNUSED(environment);
|
||||
SubGhzProtocolEncoderRevers* instance = malloc(sizeof(SubGhzProtocolEncoderRevers));
|
||||
|
||||
instance->base.protocol = &subghz_protocol_revers;
|
||||
instance->generic.protocol_name = instance->base.protocol->name;
|
||||
|
||||
instance->encoder.repeat = 10;
|
||||
instance->encoder.size_upload = 512;
|
||||
instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration));
|
||||
instance->encoder.is_running = false;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_encoder_revers_free(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzProtocolEncoderRevers* instance = context;
|
||||
free(instance->encoder.upload);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generating an upload from data.
|
||||
* @param instance Pointer to a SubGhzProtocolEncoderRevers instance
|
||||
* @return true On success
|
||||
*/
|
||||
static bool subghz_protocol_encoder_revers_get_upload(SubGhzProtocolEncoderRevers* instance) {
|
||||
furi_assert(instance);
|
||||
size_t index = 0;
|
||||
/*size_t size_upload = instance->generic.data_count_bit;
|
||||
if(size_upload > instance->encoder.size_upload) {
|
||||
FURI_LOG_E(TAG, "Size upload exceeds allocated encoder buffer.");
|
||||
return false;
|
||||
} else {
|
||||
instance->encoder.size_upload = size_upload;
|
||||
}*/
|
||||
|
||||
//Send key data
|
||||
/*for(uint8_t i = instance->generic.data_count_bit; i > 1; i--) {
|
||||
if(bit_read(instance->generic.data, i - 1)) {
|
||||
//send bit 1
|
||||
instance->encoder.upload[index++] =
|
||||
level_duration_make(true, (uint32_t)subghz_protocol_revers_const.te_short);
|
||||
instance->encoder.upload[index++] =
|
||||
level_duration_make(false, (uint32_t)subghz_protocol_revers_const.te_short);
|
||||
} else {
|
||||
//send bit 0
|
||||
instance->encoder.upload[index++] =
|
||||
level_duration_make(true, (uint32_t)subghz_protocol_revers_const.te_long);
|
||||
instance->encoder.upload[index++] =
|
||||
level_duration_make(false, (uint32_t)subghz_protocol_revers_const.te_long);
|
||||
}
|
||||
}*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool subghz_protocol_encoder_revers_deserialize(void* context, FlipperFormat* flipper_format) {
|
||||
furi_assert(context);
|
||||
SubGhzProtocolEncoderRevers* instance = context;
|
||||
bool res = false;
|
||||
do {
|
||||
if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) {
|
||||
FURI_LOG_E(TAG, "Deserialize error");
|
||||
break;
|
||||
}
|
||||
if(instance->generic.data_count_bit !=
|
||||
subghz_protocol_revers_const.min_count_bit_for_found) {
|
||||
FURI_LOG_E(TAG, "Wrong number of bits in key");
|
||||
break;
|
||||
}
|
||||
//optional parameter parameter
|
||||
flipper_format_read_uint32(
|
||||
flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1);
|
||||
|
||||
if(!subghz_protocol_encoder_revers_get_upload(instance)) break;
|
||||
instance->encoder.is_running = true;
|
||||
|
||||
res = true;
|
||||
} while(false);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void subghz_protocol_encoder_revers_stop(void* context) {
|
||||
SubGhzProtocolEncoderRevers* instance = context;
|
||||
instance->encoder.is_running = false;
|
||||
}
|
||||
|
||||
LevelDuration subghz_protocol_encoder_revers_yield(void* context) {
|
||||
SubGhzProtocolEncoderRevers* instance = context;
|
||||
|
||||
if(instance->encoder.repeat == 0 || !instance->encoder.is_running) {
|
||||
instance->encoder.is_running = false;
|
||||
return level_duration_reset();
|
||||
}
|
||||
|
||||
LevelDuration ret = instance->encoder.upload[instance->encoder.front];
|
||||
|
||||
if(++instance->encoder.front == instance->encoder.size_upload) {
|
||||
instance->encoder.repeat--;
|
||||
instance->encoder.front = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void* subghz_protocol_decoder_revers_alloc(SubGhzEnvironment* environment) {
|
||||
UNUSED(environment);
|
||||
SubGhzProtocolDecoderRevers* instance = malloc(sizeof(SubGhzProtocolDecoderRevers));
|
||||
instance->base.protocol = &subghz_protocol_revers;
|
||||
instance->generic.protocol_name = instance->base.protocol->name;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_decoder_revers_free(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzProtocolDecoderRevers* instance = context;
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void subghz_protocol_decoder_revers_reset(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzProtocolDecoderRevers* instance = context;
|
||||
instance->decoder.parser_step = ReversDecoderStepReset;
|
||||
instance->last_data = 0;
|
||||
}
|
||||
|
||||
void subghz_protocol_decoder_revers_feed(void* context, bool level, uint32_t duration) {
|
||||
furi_assert(context);
|
||||
SubGhzProtocolDecoderRevers* instance = context;
|
||||
switch(instance->decoder.parser_step) {
|
||||
case ReversDecoderStepReset:
|
||||
if((level) && DURATION_DIFF(duration, subghz_protocol_revers_const.te_short) <
|
||||
subghz_protocol_revers_const.te_delta) {
|
||||
instance->decoder.parser_step = ReversDecoderStepCheckPreambula;
|
||||
instance->header_count++;
|
||||
}
|
||||
break;
|
||||
case ReversDecoderStepCheckPreambula:
|
||||
if((!level) && (DURATION_DIFF(duration, subghz_protocol_revers_const.te_short) <
|
||||
subghz_protocol_revers_const.te_delta)) {
|
||||
instance->decoder.parser_step = ReversDecoderStepReset;
|
||||
break;
|
||||
}
|
||||
if((instance->header_count > 2) &&
|
||||
(DURATION_DIFF(duration, subghz_protocol_revers_const.te_long) <
|
||||
subghz_protocol_revers_const.te_delta)) {
|
||||
// Preambula found
|
||||
instance->decoder.parser_step = ReversDecoderStepSaveDuration;
|
||||
} else {
|
||||
instance->decoder.parser_step = ReversDecoderStepReset;
|
||||
instance->header_count = 0;
|
||||
}
|
||||
case ReversDecoderStepSaveDuration:
|
||||
if(level) {
|
||||
instance->decoder.te_last = duration;
|
||||
instance->decoder.parser_step = ReversDecoderStepCheckDuration;
|
||||
} else {
|
||||
instance->decoder.parser_step = ReversDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case ReversDecoderStepCheckDuration:
|
||||
if(!level) {
|
||||
/*if((DURATION_DIFF(instance->decoder.te_last, subghz_protocol_revers_const.te_short) <
|
||||
subghz_protocol_revers_const.te_delta) &&
|
||||
(DURATION_DIFF(duration, subghz_protocol_revers_const.te_short * 7) <
|
||||
subghz_protocol_revers_const.te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(&instance->decoder, 1);
|
||||
instance->decoder.parser_step = ReversDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->decoder.te_last, subghz_protocol_revers_const.te_long) <
|
||||
subghz_protocol_revers_const.te_delta) &&
|
||||
(DURATION_DIFF(duration, subghz_protocol_revers_const.te_long) <
|
||||
subghz_protocol_revers_const.te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(&instance->decoder, 0);
|
||||
instance->decoder.parser_step = ReversDecoderStepSaveDuration;
|
||||
} else {
|
||||
instance->decoder.parser_step = ReversDecoderStepReset;
|
||||
}*/
|
||||
|
||||
} else {
|
||||
instance->decoder.parser_step = ReversDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t subghz_protocol_decoder_revers_get_hash_data(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzProtocolDecoderRevers* instance = context;
|
||||
return subghz_protocol_blocks_get_hash_data(
|
||||
&instance->decoder, (instance->decoder.decode_count_bit / 8));
|
||||
}
|
||||
|
||||
bool subghz_protocol_decoder_revers_serialize(
|
||||
void* context,
|
||||
FlipperFormat* flipper_format,
|
||||
SubGhzRadioPreset* preset) {
|
||||
furi_assert(context);
|
||||
SubGhzProtocolDecoderRevers* instance = context;
|
||||
return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
|
||||
}
|
||||
|
||||
bool subghz_protocol_decoder_revers_deserialize(void* context, FlipperFormat* flipper_format) {
|
||||
furi_assert(context);
|
||||
SubGhzProtocolDecoderRevers* instance = context;
|
||||
bool ret = false;
|
||||
do {
|
||||
if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) {
|
||||
break;
|
||||
}
|
||||
if(instance->generic.data_count_bit !=
|
||||
subghz_protocol_revers_const.min_count_bit_for_found) {
|
||||
FURI_LOG_E(TAG, "Wrong number of bits in key");
|
||||
break;
|
||||
}
|
||||
ret = true;
|
||||
} while(false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void subghz_protocol_decoder_revers_get_string(void* context, FuriString* output) {
|
||||
furi_assert(context);
|
||||
SubGhzProtocolDecoderRevers* instance = context;
|
||||
|
||||
uint32_t data = instance->generic.data & 0xFF;
|
||||
|
||||
furi_string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:0x%lX\r\n",
|
||||
instance->generic.protocol_name,
|
||||
instance->generic.data_count_bit,
|
||||
data);
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "base.h"
|
||||
|
||||
#define SUBGHZ_PROTOCOL_REVERS_NAME "Revers"
|
||||
|
||||
typedef struct SubGhzProtocolDecoderRevers SubGhzProtocolDecoderRevers;
|
||||
typedef struct SubGhzProtocolEncoderRevers SubGhzProtocolEncoderRevers;
|
||||
|
||||
extern const SubGhzProtocolDecoder subghz_protocol_revers_decoder;
|
||||
extern const SubGhzProtocolEncoder subghz_protocol_revers_encoder;
|
||||
extern const SubGhzProtocol subghz_protocol_revers;
|
||||
|
||||
/**
|
||||
* Allocate SubGhzProtocolEncoderRevers.
|
||||
* @param environment Pointer to a SubGhzEnvironment instance
|
||||
* @return SubGhzProtocolEncoderRevers* pointer to a SubGhzProtocolEncoderRevers instance
|
||||
*/
|
||||
void* subghz_protocol_encoder_revers_alloc(SubGhzEnvironment* environment);
|
||||
|
||||
/**
|
||||
* Free SubGhzProtocolEncoderRevers.
|
||||
* @param context Pointer to a SubGhzProtocolEncoderRevers instance
|
||||
*/
|
||||
void subghz_protocol_encoder_revers_free(void* context);
|
||||
|
||||
/**
|
||||
* Deserialize and generating an upload to send.
|
||||
* @param context Pointer to a SubGhzProtocolEncoderRevers instance
|
||||
* @param flipper_format Pointer to a FlipperFormat instance
|
||||
* @return true On success
|
||||
*/
|
||||
bool subghz_protocol_encoder_revers_deserialize(void* context, FlipperFormat* flipper_format);
|
||||
|
||||
/**
|
||||
* Forced transmission stop.
|
||||
* @param context Pointer to a SubGhzProtocolEncoderRevers instance
|
||||
*/
|
||||
void subghz_protocol_encoder_revers_stop(void* context);
|
||||
|
||||
/**
|
||||
* Getting the level and duration of the upload to be loaded into DMA.
|
||||
* @param context Pointer to a SubGhzProtocolEncoderRevers instance
|
||||
* @return LevelDuration
|
||||
*/
|
||||
LevelDuration subghz_protocol_encoder_revers_yield(void* context);
|
||||
|
||||
/**
|
||||
* Allocate SubGhzProtocolDecoderRevers.
|
||||
* @param environment Pointer to a SubGhzEnvironment instance
|
||||
* @return SubGhzProtocolDecoderRevers* pointer to a SubGhzProtocolDecoderRevers instance
|
||||
*/
|
||||
void* subghz_protocol_decoder_revers_alloc(SubGhzEnvironment* environment);
|
||||
|
||||
/**
|
||||
* Free SubGhzProtocolDecoderRevers.
|
||||
* @param context Pointer to a SubGhzProtocolDecoderRevers instance
|
||||
*/
|
||||
void subghz_protocol_decoder_revers_free(void* context);
|
||||
|
||||
/**
|
||||
* Reset decoder SubGhzProtocolDecoderRevers.
|
||||
* @param context Pointer to a SubGhzProtocolDecoderRevers instance
|
||||
*/
|
||||
void subghz_protocol_decoder_revers_reset(void* context);
|
||||
|
||||
/**
|
||||
* Parse a raw sequence of levels and durations received from the air.
|
||||
* @param context Pointer to a SubGhzProtocolDecoderRevers instance
|
||||
* @param level Signal level true-high false-low
|
||||
* @param duration Duration of this level in, us
|
||||
*/
|
||||
void subghz_protocol_decoder_revers_feed(void* context, bool level, uint32_t duration);
|
||||
|
||||
/**
|
||||
* Getting the hash sum of the last randomly received parcel.
|
||||
* @param context Pointer to a SubGhzProtocolDecoderRevers instance
|
||||
* @return hash Hash sum
|
||||
*/
|
||||
uint8_t subghz_protocol_decoder_revers_get_hash_data(void* context);
|
||||
|
||||
/**
|
||||
* Serialize data SubGhzProtocolDecoderRevers.
|
||||
* @param context Pointer to a SubGhzProtocolDecoderRevers instance
|
||||
* @param flipper_format Pointer to a FlipperFormat instance
|
||||
* @param preset The modulation on which the signal was received, SubGhzRadioPreset
|
||||
* @return true On success
|
||||
*/
|
||||
bool subghz_protocol_decoder_revers_serialize(
|
||||
void* context,
|
||||
FlipperFormat* flipper_format,
|
||||
SubGhzRadioPreset* preset);
|
||||
|
||||
/**
|
||||
* Deserialize data SubGhzProtocolDecoderRevers.
|
||||
* @param context Pointer to a SubGhzProtocolDecoderRevers instance
|
||||
* @param flipper_format Pointer to a FlipperFormat instance
|
||||
* @return true On success
|
||||
*/
|
||||
bool subghz_protocol_decoder_revers_deserialize(void* context, FlipperFormat* flipper_format);
|
||||
|
||||
/**
|
||||
* Getting a textual representation of the received data.
|
||||
* @param context Pointer to a SubGhzProtocolDecoderRevers instance
|
||||
* @param output Resulting text
|
||||
*/
|
||||
void subghz_protocol_decoder_revers_get_string(void* context, FuriString* output);
|
||||
@@ -61,7 +61,6 @@ static const uint32_t subghz_frequency_list[] = {
|
||||
438900000,
|
||||
440175000,
|
||||
464000000,
|
||||
467750000,
|
||||
|
||||
/* 779 - 928 */
|
||||
779000000,
|
||||
|
||||
@@ -106,7 +106,6 @@ void tar_archive_set_file_callback(TarArchive* archive, tar_unpack_file_cb callb
|
||||
static int tar_archive_entry_counter(mtar_t* tar, const mtar_header_t* header, void* param) {
|
||||
UNUSED(tar);
|
||||
UNUSED(header);
|
||||
furi_assert(param);
|
||||
int32_t* counter = param;
|
||||
(*counter)++;
|
||||
return 0;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from SCons.Builder import Builder
|
||||
from SCons.Action import Action
|
||||
from SCons.Script import Delete, Mkdir, GetBuildFailures, Flatten
|
||||
from SCons.Script import Delete, Mkdir, GetBuildFailures
|
||||
import multiprocessing
|
||||
import webbrowser
|
||||
import atexit
|
||||
@@ -30,14 +30,13 @@ def atexist_handler():
|
||||
return
|
||||
|
||||
for bf in GetBuildFailures():
|
||||
for node in Flatten(bf.node):
|
||||
if node.exists and node.name.endswith(".html"):
|
||||
# macOS
|
||||
if sys.platform == "darwin":
|
||||
subprocess.run(["open", node.abspath])
|
||||
else:
|
||||
webbrowser.open(node.abspath)
|
||||
break
|
||||
if bf.node.exists and bf.node.name.endswith(".html"):
|
||||
# macOS
|
||||
if sys.platform == "darwin":
|
||||
subprocess.run(["open", bf.node.abspath])
|
||||
else:
|
||||
webbrowser.open(bf.node.abspath)
|
||||
break
|
||||
|
||||
|
||||
def generate(env):
|
||||
|
||||
Reference in New Issue
Block a user