1
mirror of https://github.com/DarkFlippers/unleashed-firmware.git synced 2025-12-12 20:49:49 +04:00

Compare commits

..

14 Commits

Author SHA1 Message Date
MX
827341ec08 Merge branch 'dev' into release 2023-01-19 01:53:01 +03:00
MX
5c36043d03 Merge branch 'dev' into release 2022-12-31 03:21:55 +03:00
MX
cf5811f8d9 Merge branch 'dev' into release 2022-12-31 02:59:26 +03:00
MX
ec6a169bf8 Merge branch 'dev' into release 2022-12-19 21:57:35 +03:00
MX
f1dec87c1b Merge branch 'dev' into release 2022-12-19 20:52:17 +03:00
MX
ab29951a99 Merge branch 'dev' into release 2022-12-19 19:26:06 +03:00
MX
bbe9f88bbe Merge branch 'dev' into release 2022-12-11 01:34:50 +03:00
MX
9188bf0013 Merge branch 'dev' into release 2022-12-10 04:38:04 +03:00
MX
f33ed59567 Merge branch 'dev' into release 2022-12-03 01:04:48 +03:00
MX
3fd8c80861 Merge branch 'dev' into release 2022-12-03 00:59:18 +03:00
MX
7b8ac3a5a0 Merge branch 'dev' into release 2022-11-30 21:05:08 +03:00
MX
6fef957001 Merge branch 'dev' into release 2022-11-24 04:02:59 +03:00
MX
0de1c9df89 Merge branch 'dev' into release 2022-11-24 03:45:52 +03:00
MX
a0e8cfbe97 Merge branch 'dev' into release 2022-11-24 03:41:01 +03:00
551 changed files with 5192 additions and 24355 deletions

View File

@@ -192,7 +192,7 @@ steps:
Version: {{build.tag}}
[-Github - Changelog-](https://github.com/DarkFlippers/unleashed-firmware/releases/tag/${DRONE_TAG})
[-Github-](https://github.com/DarkFlippers/unleashed-firmware/releases/tag/${DRONE_TAG})
[-How to install firmware-](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)
@@ -201,38 +201,45 @@ steps:
[-Download latest extra apps pack-](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps)
[-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})
[-Version without custom animations - Install 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)
[-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)
[-Version with extra apps - Install 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)
[-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)"
[-Install 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})"
document:
- ${DRONE_TAG}/flipper-z-f7-update-${DRONE_TAG}.tgz
- name: "Send discord notification"
image: hfdj/fztools
pull: never
environment:
DISCORD_WEBHOOK:
from_secret: dis_release_webhook
commands:
- wget "https://raw.githubusercontent.com/fieu/discord.sh/e1dc1a7595efad2cad8f072f0b3531c470f5b7c8/discord.sh"
- 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
image: appleboy/drone-discord
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
webhook_id:
from_secret: ds_wh_id
webhook_token:
from_secret: ds_wh_token
message: "New Unleashed firmware released!
Version: {{build.tag}}
[[Github]](https://github.com/DarkFlippers/unleashed-firmware/releases/tag/${DRONE_TAG})
[-How to install firmware-](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)
[-Download latest extra apps pack-](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps)
[-Version without custom animations - Install 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)
[-Version with extra apps - Install 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)
[-Install 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})"
trigger:
event:
@@ -392,29 +399,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
environment:
DISCORD_WEBHOOK:
from_secret: dis_dev_webhook
commands:
- wget "https://raw.githubusercontent.com/fieu/discord.sh/e1dc1a7595efad2cad8f072f0b3531c470f5b7c8/discord.sh"
- chmod +x ./discord.sh
- ./discord.sh --text 'Unleashed firmware dev build successful!\n\nBuild - '${DRONE_BUILD_NUMBER}'\n\nSHA - '${DRONE_COMMIT_SHA}'\n\n[-Version with extra apps - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'e.tgz&channel=dev-cfw&version='${DRONE_BUILD_NUMBER}'e)\n\n[-Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/dev/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'.tgz&channel=dev-cfw&version='${DRONE_BUILD_NUMBER}')'
trigger:
branch:
- dev

1
.gitignore vendored
View File

@@ -1,5 +1,4 @@
*.swp
*.swo
*.gdb_history

View File

@@ -11,8 +11,5 @@
"augustocdias.tasks-shell-input"
],
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
"unwantedRecommendations": [
"twxs.cmake",
"ms-vscode.cmake-tools"
]
}
"unwantedRecommendations": []
}

View File

@@ -1,12 +1,28 @@
### 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
* SubGHz: **Somfy Telis Encoder** (PR #289 | by @assasinfil & @TQMatvey)
* SubGHz: Add 350Mhz to default range
* Plugins -> Solitaire: Fix for solitaire card placement bug (PR #253 | by @teeebor)
* Plugins -> UniTemp (New sensors added), TOTP - Updated to latest commits
* Plugins -> Added Text Viewer [(by kowalski7cc & kyhwana)](https://github.com/kowalski7cc/flipper-zero-text-viewer/tree/refactor-text-app)
* Plugins -> Added **UART Terminal** [(by cool4uma)](https://github.com/cool4uma/UART_Terminal/tree/main)
* Plugins -> Added **ProtoView** [(by antirez)](https://github.com/antirez/protoview)
* Plugins -> WAV Player - Replaced with fixed and improved version by [@LTVA1](https://github.com/LTVA1/wav_player)
* Clock: Fix 12AM was displaying as 00 AM (PR #288 | by @Smileycathy1128)
* Infrared: Allow disabling automatic signal decoding (aka Learn RAW) - works only when debug enabled (PR #273 | by @darmiel)
* Infrared: Update universal remote assets (by @amec0e)
* Desktop: New battery display (Bar %) - (PR #278 | by @Fasjeit)
* BadUSB: Adding CZ keyboard layout (PR #255 | by @peoblouk)
* OFW: Various improvements: Toolbox, Updater and Unit Tests.
* OFW: Fix typos in source code
* OFW: Add the sleigh ride animation
* OFW: Documentation: edit texts, markdown linting
* OFW: Change broken BadUSB link to Hak5 duckyscript quick reference webpage
* OFW: **Per protocol signal repeat count** - **Fixes issues with Sony remotes with SIRC protocol (bruteforce also fixed now!)**
* OFW: Add the ability to turn pages in infrared
* OFW: **BadUSB backspace/delete fix**
* OFW: relocate R_ARM_CALL
* OFW: fbt: PVS support
* OFW: fbt: removed DEBUG_TOOLS & FAP_EXAMPLES flags
#### [🎲 Download latest extra apps pack](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps)

View File

@@ -52,7 +52,7 @@ Almost everything in flipper firmware is built around this concept.
## Naming
### Type names are PascalCase
### Type names are CamelCase
Examples:

View File

@@ -40,7 +40,7 @@ Our Discord Community:
* FAAC SLH (Spa) & BFT Mitto (secure with seed) manual creation
* Sub-GHz static code brute-force plugin
* LFRFID Fuzzer plugin
* Custom community plugins and games added + all known working apps can be downloaded in extra pack in every release
* Custom community plugins and games added
* Extra Sub-GHz frequencies + extra Mifare Classic keys
* Picopass/iClass plugin included in releases
* Recompiled IR TV Universal Remote for ALL buttons
@@ -49,17 +49,12 @@ Our Discord Community:
* Customizable Flipper name
* Sub-GHz -> Press OK in frequency analyzer to use detected frequency in Read modes
* Sub-GHz -> Long press OK button in Sub-GHz Frequency analyzer to switch to Read menu
* Sub-GHz -> External CC1101 module support
* Other small fixes and changes throughout
* See other changes in changelog and in readme below
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 +71,12 @@ 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 (by @assasinfil & @TQMatvey)
## 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
@@ -124,7 +112,7 @@ You can support us by using links or addresses below:
- GPIO: Sentry Safe plugin [(by H4ckd4ddy)](https://github.com/H4ckd4ddy/flipperzero-sentry-safe-plugin)
- ESP32: WiFi Marauder companion plugin [(by 0xchocolate)](https://github.com/0xchocolate/flipperzero-firmware-with-wifi-marauder-companion)
- NRF24: Sniffer & MouseJacker (with changes) [(by mothball187)](https://github.com/mothball187/flipperzero-nrf24/tree/main/mousejacker)
- Simple Clock (timer by GMMan) [(original by CompaqDisc)](https://gist.github.com/CompaqDisc/4e329c501bd03c1e801849b81f48ea61)
- Simple Clock (timer by GMMan / settings by kowalski7cc) [(original by CompaqDisc)](https://gist.github.com/CompaqDisc/4e329c501bd03c1e801849b81f48ea61)
- **Sub-GHz Remote** (UniversalRF Remix) [(by @darmiel & @xMasterX)](https://github.com/darmiel/flipper-playlist/tree/feat/unirf-protocols) (original by @ESurge)
- Spectrum Analyzer (with changes) [(by jolcese)](https://github.com/jolcese/flipperzero-firmware/tree/spectrum/applications/spectrum_analyzer) - [Ultra Narrow mode & scan channels non-consecutively](https://github.com/theY4Kman/flipperzero-firmware/commits?author=theY4Kman)
- Metronome [(by panki27)](https://github.com/panki27/Metronome)
@@ -160,8 +148,8 @@ Games:
### Other changes
- BadUSB -> Keyboard layouts [(by rien > dummy-decoy)](https://github.com/dummy-decoy/flipperzero-firmware/tree/dummy_decoy/bad_usb_keyboard_layout)
- Sub-GHz -> External CC1101 module support - [(by quen0n)](https://github.com/DarkFlippers/unleashed-firmware/pull/307)
- Sub-GHz -> New frequency analyzer - [(by ClusterM)](https://github.com/DarkFlippers/unleashed-firmware/pull/43)
- Sub-GHz -> Detect RAW feature - [(by perspecdev)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/152)
- Sub-GHz -> Save last used frequency [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77)
- Sub-GHz -> Press OK in frequency analyzer to use detected frequency in Read modes [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77)
- Sub-GHz -> Long press OK button in Sub-GHz Frequency analyzer to switch to Read menu [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/79)
@@ -172,8 +160,6 @@ Games:
## [- How to build firmware](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToBuild.md)
## [- How to connect external CC1101 module](https://github.com/quen0n/flipperzero-ext-cc1101)
## [- BadUSB: how to add new keyboard layouts](https://github.com/dummy-decoy/flipperzero_badusb_kl)
## [- How to change Flipper name](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/CustomFlipperName.md)

View File

@@ -34,7 +34,7 @@ void AccessorApp::run(void) {
AccessorApp::AccessorApp()
: text_store{0} {
notification = static_cast<NotificationApp*>(furi_record_open(RECORD_NOTIFICATION));
onewire_host = onewire_host_alloc(&ibutton_gpio);
onewire_host = onewire_host_alloc();
furi_hal_power_enable_otg();
}

View File

@@ -2,7 +2,6 @@ App(
appid="accessor",
name="Accessor",
apptype=FlipperAppType.DEBUG,
targets=["f7"],
entry_point="accessor_app",
cdefines=["APP_ACCESSOR"],
requires=["gui"],

View File

@@ -11,5 +11,4 @@ App(
stack_size=1 * 1024,
order=130,
fap_category="Debug",
fap_libs=["assets"],
)

View File

@@ -1,148 +0,0 @@
#include "battery_info.h"
#include <furi.h>
#include <gui/elements.h>
#include <assets_icons.h>
#define LOW_CHARGE_THRESHOLD 10
#define HIGH_DRAIN_CURRENT_THRESHOLD 100
struct BatteryInfo {
View* view;
};
static void draw_stat(Canvas* canvas, int x, int y, const Icon* icon, char* val) {
canvas_draw_frame(canvas, x - 7, y + 7, 30, 13);
canvas_draw_icon(canvas, x, y, icon);
canvas_set_color(canvas, ColorWhite);
canvas_draw_box(canvas, x - 4, y + 16, 24, 6);
canvas_set_color(canvas, ColorBlack);
canvas_draw_str_aligned(canvas, x + 8, y + 22, AlignCenter, AlignBottom, val);
};
static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) {
char emote[20] = {};
char header[20] = {};
char value[20] = {};
int32_t drain_current = data->gauge_current * (-1000);
uint32_t charge_current = data->gauge_current * 1000;
// Draw battery
canvas_draw_icon(canvas, x, y, &I_BatteryBody_52x28);
if(charge_current > 0) {
canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceCharging_29x14);
} else if(drain_current > HIGH_DRAIN_CURRENT_THRESHOLD) {
canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceConfused_29x14);
} else if(data->charge < LOW_CHARGE_THRESHOLD) {
canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceNopower_29x14);
} else {
canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceNormal_29x14);
}
// Draw bubble
elements_bubble(canvas, 53, 0, 71, 39);
// Set text
if(charge_current > 0) {
snprintf(emote, sizeof(emote), "%s", "Yummy!");
snprintf(header, sizeof(header), "%s", "Charging at");
snprintf(
value,
sizeof(value),
"%lu.%luV %lumA",
(uint32_t)(data->vbus_voltage),
(uint32_t)(data->vbus_voltage * 10) % 10,
charge_current);
} else if(drain_current > 0) {
snprintf(
emote,
sizeof(emote),
"%s",
drain_current > HIGH_DRAIN_CURRENT_THRESHOLD ? "Oh no!" : "Om-nom-nom!");
snprintf(header, sizeof(header), "%s", "Consumption is");
snprintf(
value,
sizeof(value),
"%ld %s",
drain_current,
drain_current > HIGH_DRAIN_CURRENT_THRESHOLD ? "mA!" : "mA");
} else if(drain_current != 0) {
snprintf(header, 20, "...");
} else if(data->charging_voltage < 4.2) {
// Non-default battery charging limit, mention it
snprintf(emote, sizeof(emote), "Charged!");
snprintf(header, sizeof(header), "Limited to");
snprintf(
value,
sizeof(value),
"%lu.%luV",
(uint32_t)(data->charging_voltage),
(uint32_t)(data->charging_voltage * 10) % 10);
} else {
snprintf(header, sizeof(header), "Charged!");
}
canvas_draw_str_aligned(canvas, 92, y + 3, AlignCenter, AlignCenter, emote);
canvas_draw_str_aligned(canvas, 92, y + 15, AlignCenter, AlignCenter, header);
canvas_draw_str_aligned(canvas, 92, y + 27, AlignCenter, AlignCenter, value);
};
static void battery_info_draw_callback(Canvas* canvas, void* context) {
furi_assert(context);
BatteryInfoModel* model = context;
canvas_clear(canvas);
canvas_set_color(canvas, ColorBlack);
draw_battery(canvas, model, 0, 5);
char batt_level[10];
char temperature[10];
char voltage[10];
char health[10];
snprintf(batt_level, sizeof(batt_level), "%lu%%", (uint32_t)model->charge);
snprintf(temperature, sizeof(temperature), "%lu C", (uint32_t)model->gauge_temperature);
snprintf(
voltage,
sizeof(voltage),
"%lu.%01lu V",
(uint32_t)model->gauge_voltage,
(uint32_t)(model->gauge_voltage * 10) % 10UL);
snprintf(health, sizeof(health), "%d%%", model->health);
draw_stat(canvas, 8, 42, &I_Battery_16x16, batt_level);
draw_stat(canvas, 40, 42, &I_Temperature_16x16, temperature);
draw_stat(canvas, 72, 42, &I_Voltage_16x16, voltage);
draw_stat(canvas, 104, 42, &I_Health_16x16, health);
}
BatteryInfo* battery_info_alloc() {
BatteryInfo* battery_info = malloc(sizeof(BatteryInfo));
battery_info->view = view_alloc();
view_set_context(battery_info->view, battery_info);
view_allocate_model(battery_info->view, ViewModelTypeLocking, sizeof(BatteryInfoModel));
view_set_draw_callback(battery_info->view, battery_info_draw_callback);
return battery_info;
}
void battery_info_free(BatteryInfo* battery_info) {
furi_assert(battery_info);
view_free(battery_info->view);
free(battery_info);
}
View* battery_info_get_view(BatteryInfo* battery_info) {
furi_assert(battery_info);
return battery_info->view;
}
void battery_info_set_data(BatteryInfo* battery_info, BatteryInfoModel* data) {
furi_assert(battery_info);
furi_assert(data);
with_view_model(
battery_info->view,
BatteryInfoModel * model,
{ memcpy(model, data, sizeof(BatteryInfoModel)); },
true);
}

View File

@@ -1,23 +0,0 @@
#pragma once
#include <gui/view.h>
typedef struct BatteryInfo BatteryInfo;
typedef struct {
float vbus_voltage;
float gauge_voltage;
float gauge_current;
float gauge_temperature;
float charging_voltage;
uint8_t charge;
uint8_t health;
} BatteryInfoModel;
BatteryInfo* battery_info_alloc();
void battery_info_free(BatteryInfo* battery_info);
View* battery_info_get_view(BatteryInfo* battery_info);
void battery_info_set_data(BatteryInfo* battery_info, BatteryInfoModel* data);

View File

@@ -31,6 +31,9 @@ uint32_t bt_debug_start_view(void* context) {
BtDebugApp* bt_debug_app_alloc() {
BtDebugApp* app = malloc(sizeof(BtDebugApp));
// Load settings
bt_settings_load(&app->settings);
// Gui
app->gui = furi_record_open(RECORD_GUI);
@@ -102,15 +105,13 @@ int32_t bt_debug_app(void* p) {
}
BtDebugApp* app = bt_debug_app_alloc();
// Was bt active?
const bool was_active = furi_hal_bt_is_active();
// Stop advertising
furi_hal_bt_stop_advertising();
view_dispatcher_run(app->view_dispatcher);
// Restart advertising
if(was_active) {
if(app->settings.enabled) {
furi_hal_bt_start_advertising();
}
bt_debug_app_free(app);

View File

@@ -4,14 +4,15 @@
#include <gui/gui.h>
#include <gui/view.h>
#include <gui/view_dispatcher.h>
#include <gui/modules/submenu.h>
#include <dialogs/dialogs.h>
#include <gui/modules/submenu.h>
#include "views/bt_carrier_test.h"
#include "views/bt_packet_test.h"
#include <bt/bt_settings.h>
typedef struct {
BtSettings settings;
Gui* gui;
ViewDispatcher* view_dispatcher;
Submenu* submenu;

View File

@@ -1,7 +1,7 @@
#include "bt_carrier_test.h"
#include "bt_test.h"
#include "bt_test_types.h"
#include <furi_hal_bt.h>
#include "furi_hal_bt.h"
struct BtCarrierTest {
BtTest* bt_test;

View File

@@ -1,7 +1,7 @@
#include "bt_packet_test.h"
#include "bt_test.h"
#include "bt_test_types.h"
#include <furi_hal_bt.h>
#include "furi_hal_bt.h"
struct BtPacketTest {
BtTest* bt_test;

View File

@@ -5,7 +5,6 @@ App(
entry_point="display_test_app",
cdefines=["APP_DISPLAY_TEST"],
requires=["gui"],
fap_libs=["misc"],
stack_size=1 * 1024,
order=120,
fap_category="Debug",

View File

@@ -91,6 +91,7 @@ static void display_test_reload_config(DisplayTest* instance) {
instance->config_contrast,
instance->config_regulation_ratio,
instance->config_bias);
gui_update(instance->gui);
}
static void display_config_set_bias(VariableItem* item) {

View File

@@ -1,9 +0,0 @@
App(
appid="example_custom_font",
name="Example: custom font",
apptype=FlipperAppType.DEBUG,
entry_point="example_custom_font_main",
requires=["gui"],
stack_size=1 * 1024,
fap_category="Debug",
)

View File

@@ -1,98 +0,0 @@
#include <furi.h>
#include <furi_hal.h>
#include <gui/gui.h>
#include <input/input.h>
//This arrays contains the font itself. You can use any u8g2 font you want
/*
Fontname: -Raccoon-Fixed4x6-Medium-R-Normal--6-60-75-75-P-40-ISO10646-1
Copyright:
Glyphs: 95/203
BBX Build Mode: 0
*/
const uint8_t u8g2_font_tom_thumb_4x6_tr[725] =
"_\0\2\2\2\3\3\4\4\3\6\0\377\5\377\5\0\0\352\1\330\2\270 \5\340\315\0!\6\265\310"
"\254\0\42\6\213\313$\25#\10\227\310\244\241\206\12$\10\227\310\215\70b\2%\10\227\310d\324F\1"
"&\10\227\310(\65R\22'\5\251\313\10(\6\266\310\251\62)\10\226\310\304\224\24\0*\6\217\312\244"
"\16+\7\217\311\245\225\0,\6\212\310)\0-\5\207\312\14.\5\245\310\4/\7\227\310Ve\4\60"
"\7\227\310-k\1\61\6\226\310\255\6\62\10\227\310h\220\312\1\63\11\227\310h\220\62X\0\64\10\227"
"\310$\65b\1\65\10\227\310\214\250\301\2\66\10\227\310\315\221F\0\67\10\227\310\314TF\0\70\10\227"
"\310\214\64\324\10\71\10\227\310\214\64\342\2:\6\255\311\244\0;\7\222\310e\240\0<\10\227\310\246\32"
"d\20=\6\217\311l\60>\11\227\310d\220A*\1\77\10\227\310\314\224a\2@\10\227\310UC\3"
"\1A\10\227\310UC\251\0B\10\227\310\250\264\322\2C\7\227\310\315\32\10D\10\227\310\250d-\0"
"E\10\227\310\214\70\342\0F\10\227\310\214\70b\4G\10\227\310\315\221\222\0H\10\227\310$\65\224\12"
"I\7\227\310\254X\15J\7\227\310\226\252\2K\10\227\310$\265\222\12L\7\227\310\304\346\0M\10\227"
"\310\244\61\224\12N\10\227\310\244q\250\0O\7\227\310UV\5P\10\227\310\250\264b\4Q\10\227\310"
"Uj$\1R\10\227\310\250\64V\1S\10\227\310m\220\301\2T\7\227\310\254\330\2U\7\227\310$"
"W\22V\10\227\310$\253L\0W\10\227\310$\65\206\12X\10\227\310$\325R\1Y\10\227\310$U"
"V\0Z\7\227\310\314T\16[\7\227\310\214X\16\134\10\217\311d\220A\0]\7\227\310\314r\4^"
"\5\213\313\65_\5\207\310\14`\6\212\313\304\0a\7\223\310\310\65\2b\10\227\310D\225\324\2c\7"
"\223\310\315\14\4d\10\227\310\246\245\222\0e\6\223\310\235\2f\10\227\310\246\264b\2g\10\227\307\35"
"\61%\0h\10\227\310D\225\254\0i\6\265\310\244\1j\10\233\307f\30U\5k\10\227\310\304\264T"
"\1l\7\227\310\310\326\0m\7\223\310<R\0n\7\223\310\250d\5o\7\223\310U\252\2p\10\227"
"\307\250\244V\4q\10\227\307-\225d\0r\6\223\310\315\22s\10\223\310\215\70\22\0t\10\227\310\245"
"\25\243\0u\7\223\310$+\11v\10\223\310$\65R\2w\7\223\310\244q\4x\7\223\310\244\62\25"
"y\11\227\307$\225dJ\0z\7\223\310\254\221\6{\10\227\310\251\32D\1|\6\265\310(\1}\11"
"\227\310\310\14RR\0~\6\213\313\215\4\0\0\0\4\377\377\0";
// Screen is 128x64 px
static void app_draw_callback(Canvas* canvas, void* ctx) {
UNUSED(ctx);
canvas_clear(canvas);
canvas_set_custom_u8g2_font(canvas, u8g2_font_tom_thumb_4x6_tr);
canvas_draw_str(canvas, 0, 6, "This is a tiny custom font");
canvas_draw_str(canvas, 0, 12, "012345.?! ,:;\"\'@#$%");
}
static void app_input_callback(InputEvent* input_event, void* ctx) {
furi_assert(ctx);
FuriMessageQueue* event_queue = ctx;
furi_message_queue_put(event_queue, input_event, FuriWaitForever);
}
int32_t example_custom_font_main(void* p) {
UNUSED(p);
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
// Configure view port
ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, app_draw_callback, view_port);
view_port_input_callback_set(view_port, app_input_callback, event_queue);
// Register view port in GUI
Gui* gui = furi_record_open(RECORD_GUI);
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
InputEvent event;
bool running = true;
while(running) {
if(furi_message_queue_get(event_queue, &event, 100) == FuriStatusOk) {
if((event.type == InputTypePress) || (event.type == InputTypeRepeat)) {
switch(event.key) {
case InputKeyBack:
running = false;
break;
default:
break;
}
}
}
}
view_port_enabled_set(view_port, false);
gui_remove_view_port(gui, view_port);
view_port_free(view_port);
furi_message_queue_free(event_queue);
furi_record_close(RECORD_GUI);
return 0;
}

View File

@@ -1,11 +1,10 @@
#include "file_browser_app_i.h"
#include <file_browser_test_icons.h>
#include <gui/modules/file_browser.h>
#include <storage/storage.h>
#include <lib/toolbox/path.h>
#include "file_browser_app_i.h"
#include "gui/modules/file_browser.h"
#include <furi.h>
#include <furi_hal.h>
#include <storage/storage.h>
#include <lib/toolbox/path.h>
static bool file_browser_app_custom_event_callback(void* context, uint32_t event) {
furi_assert(context);

View File

@@ -2,7 +2,6 @@ App(
appid="lfrfid_debug",
name="LF-RFID Debug",
apptype=FlipperAppType.DEBUG,
targets=["f7"],
entry_point="lfrfid_debug_app",
requires=[
"gui",

View File

@@ -44,11 +44,7 @@ bool rpc_debug_app_scene_input_error_code_on_event(void* context, SceneManagerEv
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == RpcDebugAppCustomEventInputErrorCode) {
char* end;
int error_code = strtol(app->text_store, &end, 10);
if(!*end) {
rpc_system_app_set_error_code(app->rpc, error_code);
}
rpc_system_app_set_error_code(app->rpc, (uint32_t)atol(app->text_store));
scene_manager_previous_scene(app->scene_manager);
consumed = true;
}

View File

@@ -348,37 +348,13 @@ static void mf_classic_generator_test(uint8_t uid_len, MfClassicType type) {
memcpy(atqa, nfc_dev->dev_data.nfc_data.atqa, 2);
MfClassicData* mf_data = &nfc_dev->dev_data.mf_classic_data;
// Check the manufacturer block (should be uid[uid_len] + BCC (for 4byte only) + SAK + ATQA0 + ATQA1 + 0xFF[rest])
// Check the manufacturer block (should be uid[uid_len] + 0xFF[rest])
uint8_t manufacturer_block[16] = {0};
memcpy(manufacturer_block, nfc_dev->dev_data.mf_classic_data.block[0].value, 16);
mu_assert(
memcmp(manufacturer_block, uid, uid_len) == 0,
"manufacturer_block uid doesn't match the file\r\n");
uint8_t position = 0;
if(uid_len == 4) {
position = uid_len;
uint8_t bcc = 0;
for(int i = 0; i < uid_len; i++) {
bcc ^= uid[i];
}
mu_assert(manufacturer_block[position] == bcc, "manufacturer_block bcc assert failed\r\n");
} else {
position = uid_len - 1;
}
mu_assert(manufacturer_block[position + 1] == sak, "manufacturer_block sak assert failed\r\n");
mu_assert(
manufacturer_block[position + 2] == atqa[0], "manufacturer_block atqa0 assert failed\r\n");
mu_assert(
manufacturer_block[position + 3] == atqa[1], "manufacturer_block atqa1 assert failed\r\n");
for(uint8_t i = position + 4; i < 16; i++) {
for(uint8_t i = uid_len; i < 16; i++) {
mu_assert(
manufacturer_block[i] == 0xFF, "manufacturer_block[i] == 0xFF assert failed\r\n");
}
@@ -490,10 +466,6 @@ static void mf_classic_generator_test(uint8_t uid_len, MfClassicType type) {
nfc_device_free(nfc_keys);
}
MU_TEST(mf_mini_file_test) {
mf_classic_generator_test(4, MfClassicTypeMini);
}
MU_TEST(mf_classic_1k_4b_file_test) {
mf_classic_generator_test(4, MfClassicType1k);
}
@@ -514,7 +486,6 @@ MU_TEST_SUITE(nfc) {
nfc_test_alloc();
MU_RUN_TEST(nfca_file_test);
MU_RUN_TEST(mf_mini_file_test);
MU_RUN_TEST(mf_classic_1k_4b_file_test);
MU_RUN_TEST(mf_classic_4k_4b_file_test);
MU_RUN_TEST(mf_classic_1k_7b_file_test);

View File

@@ -89,7 +89,7 @@ static void test_rpc_setup(void) {
}
furi_check(rpc_session[0].session);
rpc_session[0].output_stream = furi_stream_buffer_alloc(4096, 1);
rpc_session[0].output_stream = furi_stream_buffer_alloc(1000, 1);
rpc_session_set_send_bytes_callback(rpc_session[0].session, output_bytes_callback);
rpc_session[0].close_session_semaphore = xSemaphoreCreateBinary();
rpc_session[0].terminate_semaphore = xSemaphoreCreateBinary();

View File

@@ -12,9 +12,8 @@
#define KEYSTORE_DIR_NAME EXT_PATH("subghz/assets/keeloq_mfcodes")
#define CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo")
#define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s")
#define ALUTECH_AT_4N_DIR_NAME EXT_PATH("subghz/assets/alutech_at_4n")
#define TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub")
#define TEST_RANDOM_COUNT_PARSE 329
#define TEST_RANDOM_COUNT_PARSE 273
#define TEST_TIMEOUT 10000
static SubGhzEnvironment* environment_handler;
@@ -44,8 +43,6 @@ static void subghz_test_init(void) {
environment_handler, CAME_ATOMO_DIR_NAME);
subghz_environment_set_nice_flor_s_rainbow_table_file_name(
environment_handler, NICE_FLOR_S_DIR_NAME);
subghz_environment_set_alutech_at_4n_rainbow_table_file_name(
environment_handler, ALUTECH_AT_4N_DIR_NAME);
subghz_environment_set_protocol_registry(
environment_handler, (void*)&subghz_protocol_registry);
@@ -492,14 +489,6 @@ MU_TEST(subghz_decoder_linear_test) {
"Test decoder " SUBGHZ_PROTOCOL_LINEAR_NAME " error\r\n");
}
MU_TEST(subghz_decoder_linear_delta3_test) {
mu_assert(
subghz_decoder_test(
EXT_PATH("unit_tests/subghz/linear_delta3_raw.sub"),
SUBGHZ_PROTOCOL_LINEAR_DELTA3_NAME),
"Test decoder " SUBGHZ_PROTOCOL_LINEAR_DELTA3_NAME " error\r\n");
}
MU_TEST(subghz_decoder_megacode_test) {
mu_assert(
subghz_decoder_test(
@@ -615,36 +604,6 @@ MU_TEST(subghz_decoder_holtek_ht12x_test) {
"Test decoder " SUBGHZ_PROTOCOL_HOLTEK_HT12X_NAME " error\r\n");
}
MU_TEST(subghz_decoder_dooya_test) {
mu_assert(
subghz_decoder_test(
EXT_PATH("unit_tests/subghz/dooya_raw.sub"), SUBGHZ_PROTOCOL_DOOYA_NAME),
"Test decoder " SUBGHZ_PROTOCOL_DOOYA_NAME " error\r\n");
}
MU_TEST(subghz_decoder_alutech_at_4n_test) {
mu_assert(
subghz_decoder_test(
EXT_PATH("unit_tests/subghz/alutech_at_4n_raw.sub"),
SUBGHZ_PROTOCOL_ALUTECH_AT_4N_NAME),
"Test decoder " SUBGHZ_PROTOCOL_ALUTECH_AT_4N_NAME " error\r\n");
}
MU_TEST(subghz_decoder_nice_one_test) {
mu_assert(
subghz_decoder_test(
EXT_PATH("unit_tests/subghz/nice_one_raw.sub"), SUBGHZ_PROTOCOL_NICE_FLOR_S_NAME),
"Test decoder " SUBGHZ_PROTOCOL_NICE_FLOR_S_NAME " error\r\n");
}
MU_TEST(subghz_decoder_kinggates_stylo4k_test) {
mu_assert(
subghz_decoder_test(
EXT_PATH("unit_tests/subghz/kinggates_stylo4k_raw.sub"),
SUBGHZ_PROTOCOL_KINGGATES_STYLO_4K_NAME),
"Test decoder " SUBGHZ_PROTOCOL_KINGGATES_STYLO_4K_NAME " error\r\n");
}
//test encoders
MU_TEST(subghz_encoder_princeton_test) {
mu_assert(
@@ -688,12 +647,6 @@ MU_TEST(subghz_encoder_linear_test) {
"Test encoder " SUBGHZ_PROTOCOL_LINEAR_NAME " error\r\n");
}
MU_TEST(subghz_encoder_linear_delta3_test) {
mu_assert(
subghz_encoder_test(EXT_PATH("unit_tests/subghz/linear_delta3.sub")),
"Test encoder " SUBGHZ_PROTOCOL_LINEAR_DELTA3_NAME " error\r\n");
}
MU_TEST(subghz_encoder_megacode_test) {
mu_assert(
subghz_encoder_test(EXT_PATH("unit_tests/subghz/megacode.sub")),
@@ -790,12 +743,6 @@ MU_TEST(subghz_encoder_holtek_ht12x_test) {
"Test encoder " SUBGHZ_PROTOCOL_HOLTEK_HT12X_NAME " error\r\n");
}
MU_TEST(subghz_encoder_dooya_test) {
mu_assert(
subghz_encoder_test(EXT_PATH("unit_tests/subghz/dooya.sub")),
"Test encoder " SUBGHZ_PROTOCOL_DOOYA_NAME " error\r\n");
}
MU_TEST(subghz_random_test) {
mu_assert(subghz_decode_random_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n");
}
@@ -825,7 +772,6 @@ MU_TEST_SUITE(subghz) {
MU_RUN_TEST(subghz_decoder_somfy_telis_test);
MU_RUN_TEST(subghz_decoder_star_line_test);
MU_RUN_TEST(subghz_decoder_linear_test);
MU_RUN_TEST(subghz_decoder_linear_delta3_test);
MU_RUN_TEST(subghz_decoder_megacode_test);
MU_RUN_TEST(subghz_decoder_secplus_v1_test);
MU_RUN_TEST(subghz_decoder_secplus_v2_test);
@@ -842,10 +788,6 @@ MU_TEST_SUITE(subghz) {
MU_RUN_TEST(subghz_decoder_ansonic_test);
MU_RUN_TEST(subghz_decoder_smc5326_test);
MU_RUN_TEST(subghz_decoder_holtek_ht12x_test);
MU_RUN_TEST(subghz_decoder_dooya_test);
MU_RUN_TEST(subghz_decoder_alutech_at_4n_test);
MU_RUN_TEST(subghz_decoder_nice_one_test);
MU_RUN_TEST(subghz_decoder_kinggates_stylo4k_test);
MU_RUN_TEST(subghz_encoder_princeton_test);
MU_RUN_TEST(subghz_encoder_came_test);
@@ -854,7 +796,6 @@ MU_TEST_SUITE(subghz) {
MU_RUN_TEST(subghz_encoder_nice_flo_test);
MU_RUN_TEST(subghz_encoder_keelog_test);
MU_RUN_TEST(subghz_encoder_linear_test);
MU_RUN_TEST(subghz_encoder_linear_delta3_test);
MU_RUN_TEST(subghz_encoder_megacode_test);
MU_RUN_TEST(subghz_encoder_holtek_test);
MU_RUN_TEST(subghz_encoder_secplus_v1_test);
@@ -871,7 +812,6 @@ MU_TEST_SUITE(subghz) {
MU_RUN_TEST(subghz_encoder_ansonic_test);
MU_RUN_TEST(subghz_encoder_smc5326_test);
MU_RUN_TEST(subghz_encoder_holtek_ht12x_test);
MU_RUN_TEST(subghz_encoder_dooya_test);
MU_RUN_TEST(subghz_random_test);
subghz_test_deinit();

View File

@@ -70,7 +70,7 @@ void minunit_print_progress() {
}
void minunit_print_fail(const char* str) {
printf(_FURI_LOG_CLR_E "%s\r\n" _FURI_LOG_CLR_RESET, str);
printf(FURI_LOG_CLR_E "%s\r\n" FURI_LOG_CLR_RESET, str);
}
void unit_tests_cli(Cli* cli, FuriString* args, void* context) {

View File

@@ -1,44 +0,0 @@
# 1-Wire Thermometer
This example application demonstrates the use of the 1-Wire library with a DS18B20 thermometer.
It also covers basic GUI, input handling, threads and localisation.
## Electrical connections
Before launching the application, connect the sensor to Flipper's external GPIO according to the table below:
| DS18B20 | Flipper |
| :-----: | :-----: |
| VDD | 9 |
| GND | 18 |
| DQ | 17 |
*NOTE 1*: GND is also available on pins 8 and 11.
*NOTE 2*: For any other pin than 17, connect an external 4.7k pull-up resistor to pin 9.
## Launching the application
In order to launch this demo, follow the steps below:
1. Make sure your Flipper has an SD card installed.
2. Connect your Flipper to the computer via a USB cable.
3. Run `./fbt launch_app APPSRC=example_thermo` in your terminal emulator of choice.
## Changing the data pin
It is possible to use other GPIO pin as a 1-Wire data pin. In order to change it, set the `THERMO_GPIO_PIN` macro to any of the options listed below:
```c
/* Possible GPIO pin choices:
- gpio_ext_pc0
- gpio_ext_pc1
- gpio_ext_pc3
- gpio_ext_pb2
- gpio_ext_pb3
- gpio_ext_pa4
- gpio_ext_pa6
- gpio_ext_pa7
- ibutton_gpio
*/
#define THERMO_GPIO_PIN (ibutton_gpio)
```
Do not forget about the external pull-up resistor as these pins do not have one built-in.
With the changes been made, recompile and launch the application again.
The on-screen text should reflect it by asking to connect the thermometer to another pin.

View File

@@ -1,10 +0,0 @@
App(
appid="example_thermo",
name="Example: Thermometer",
apptype=FlipperAppType.EXTERNAL,
entry_point="example_thermo_main",
requires=["gui"],
stack_size=1 * 1024,
fap_icon="example_thermo_10px.png",
fap_category="Examples",
)

View File

@@ -1,356 +0,0 @@
/*
* This file contains an example application that reads and displays
* the temperature from a DS18B20 1-wire thermometer.
*
* It also covers basic GUI, input handling, threads and localisation.
*
* References:
* [1] DS18B20 Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/DS18B20.pdf
*/
#include <gui/gui.h>
#include <gui/view_port.h>
#include <core/thread.h>
#include <core/kernel.h>
#include <locale/locale.h>
#include <one_wire/maxim_crc.h>
#include <one_wire/one_wire_host.h>
#define UPDATE_PERIOD_MS 1000UL
#define TEXT_STORE_SIZE 64U
#define DS18B20_CMD_CONVERT 0x44U
#define DS18B20_CMD_READ_SCRATCHPAD 0xbeU
#define DS18B20_CFG_RESOLUTION_POS 5U
#define DS18B20_CFG_RESOLUTION_MASK 0x03U
#define DS18B20_DECIMAL_PART_MASK 0x0fU
#define DS18B20_SIGN_MASK 0xf0U
/* Possible GPIO pin choices:
- gpio_ext_pc0
- gpio_ext_pc1
- gpio_ext_pc3
- gpio_ext_pb2
- gpio_ext_pb3
- gpio_ext_pa4
- gpio_ext_pa6
- gpio_ext_pa7
- ibutton_gpio
*/
#define THERMO_GPIO_PIN (ibutton_gpio)
/* Flags which the reader thread responds to */
typedef enum {
ReaderThreadFlagExit = 1,
} ReaderThreadFlag;
typedef union {
struct {
uint8_t temp_lsb; /* Least significant byte of the temperature */
uint8_t temp_msb; /* Most significant byte of the temperature */
uint8_t user_alarm_high; /* User register 1 (Temp high alarm) */
uint8_t user_alarm_low; /* User register 2 (Temp low alarm) */
uint8_t config; /* Configuration register */
uint8_t reserved[3]; /* Not used */
uint8_t crc; /* CRC checksum for error detection */
} fields;
uint8_t bytes[9];
} DS18B20Scratchpad;
/* Application context structure */
typedef struct {
Gui* gui;
ViewPort* view_port;
FuriThread* reader_thread;
FuriMessageQueue* event_queue;
OneWireHost* onewire;
float temp_celsius;
bool has_device;
} ExampleThermoContext;
/*************** 1-Wire Communication and Processing *****************/
/* Commands the thermometer to begin measuring the temperature. */
static void example_thermo_request_temperature(ExampleThermoContext* context) {
OneWireHost* onewire = context->onewire;
/* All 1-wire transactions must happen in a critical section, i.e
not interrupted by other threads. */
FURI_CRITICAL_ENTER();
bool success = false;
do {
/* Each communication with a 1-wire device starts by a reset.
The functon will return true if a device responded with a presence pulse. */
if(!onewire_host_reset(onewire)) break;
/* After the reset, a ROM operation must follow.
If there is only one device connected, the "Skip ROM" command is most appropriate
(it can also be used to address all of the connected devices in some cases).*/
onewire_host_skip(onewire);
/* After the ROM operation, a device-specific command is issued.
In this case, it's a request to start measuring the temperature. */
onewire_host_write(onewire, DS18B20_CMD_CONVERT);
success = true;
} while(false);
context->has_device = success;
FURI_CRITICAL_EXIT();
}
/* Reads the measured temperature from the thermometer. */
static void example_thermo_read_temperature(ExampleThermoContext* context) {
/* If there was no device detected, don't try to read the temperature */
if(!context->has_device) {
return;
}
OneWireHost* onewire = context->onewire;
/* All 1-wire transactions must happen in a critical section, i.e
not interrupted by other threads. */
FURI_CRITICAL_ENTER();
bool success = false;
do {
DS18B20Scratchpad buf;
/* Attempt reading the temperature 10 times before giving up */
size_t attempts_left = 10;
do {
/* Each communication with a 1-wire device starts by a reset.
The functon will return true if a device responded with a presence pulse. */
if(!onewire_host_reset(onewire)) continue;
/* After the reset, a ROM operation must follow.
If there is only one device connected, the "Skip ROM" command is most appropriate
(it can also be used to address all of the connected devices in some cases).*/
onewire_host_skip(onewire);
/* After the ROM operation, a device-specific command is issued.
This time, it will be the "Read Scratchpad" command which will
prepare the device's internal buffer memory for reading. */
onewire_host_write(onewire, DS18B20_CMD_READ_SCRATCHPAD);
/* The actual reading happens here. A total of 9 bytes is read. */
onewire_host_read_bytes(onewire, buf.bytes, sizeof(buf.bytes));
/* Calculate the checksum and compare it with one provided by the device. */
const uint8_t crc = maxim_crc8(buf.bytes, sizeof(buf.bytes) - 1, MAXIM_CRC8_INIT);
/* Checksums match, exit the loop */
if(crc == buf.fields.crc) break;
} while(--attempts_left);
if(attempts_left == 0) break;
/* Get the measurement resolution from the configuration register. (See [1] page 9) */
const uint8_t resolution_mode = (buf.fields.config >> DS18B20_CFG_RESOLUTION_POS) &
DS18B20_CFG_RESOLUTION_MASK;
/* Generate a mask for undefined bits in the decimal part. (See [1] page 6) */
const uint8_t decimal_mask =
(DS18B20_DECIMAL_PART_MASK << (DS18B20_CFG_RESOLUTION_MASK - resolution_mode)) &
DS18B20_DECIMAL_PART_MASK;
/* Get the integer and decimal part of the temperature (See [1] page 6) */
const uint8_t integer_part = (buf.fields.temp_msb << 4U) | (buf.fields.temp_lsb >> 4U);
const uint8_t decimal_part = buf.fields.temp_lsb & decimal_mask;
/* Calculate the sign of the temperature (See [1] page 6) */
const bool is_negative = (buf.fields.temp_msb & DS18B20_SIGN_MASK) != 0;
/* Combine the integer and decimal part together */
const float temp_celsius_abs = integer_part + decimal_part / 16.f;
/* Set the appropriate sign */
context->temp_celsius = is_negative ? -temp_celsius_abs : temp_celsius_abs;
success = true;
} while(false);
context->has_device = success;
FURI_CRITICAL_EXIT();
}
/* Periodically requests measurements and reads temperature. This function runs in a separare thread. */
static int32_t example_thermo_reader_thread_callback(void* ctx) {
ExampleThermoContext* context = ctx;
for(;;) {
/* Tell the termometer to start measuring the temperature. The process may take up to 750ms. */
example_thermo_request_temperature(context);
/* Wait for the measurement to finish. At the same time wait for an exit signal. */
const uint32_t flags =
furi_thread_flags_wait(ReaderThreadFlagExit, FuriFlagWaitAny, UPDATE_PERIOD_MS);
/* If an exit signal was received, return from this thread. */
if(flags != (unsigned)FuriFlagErrorTimeout) break;
/* The measurement is now ready, read it from the termometer. */
example_thermo_read_temperature(context);
}
return 0;
}
/*************** GUI, Input and Main Loop *****************/
/* Draw the GUI of the application. The screen is completely redrawn during each call. */
static void example_thermo_draw_callback(Canvas* canvas, void* ctx) {
ExampleThermoContext* context = ctx;
char text_store[TEXT_STORE_SIZE];
const size_t middle_x = canvas_width(canvas) / 2U;
canvas_set_font(canvas, FontPrimary);
canvas_draw_str_aligned(canvas, middle_x, 12, AlignCenter, AlignBottom, "Thermometer Demo");
canvas_draw_line(canvas, 0, 16, 128, 16);
canvas_set_font(canvas, FontSecondary);
canvas_draw_str_aligned(
canvas, middle_x, 30, AlignCenter, AlignBottom, "Connnect thermometer");
snprintf(
text_store,
TEXT_STORE_SIZE,
"to GPIO pin %ld",
furi_hal_resources_get_ext_pin_number(&THERMO_GPIO_PIN));
canvas_draw_str_aligned(canvas, middle_x, 42, AlignCenter, AlignBottom, text_store);
canvas_set_font(canvas, FontKeyboard);
if(context->has_device) {
float temp;
char temp_units;
/* The applicaton is locale-aware.
Change Settings->System->Units to check it out. */
switch(locale_get_measurement_unit()) {
case LocaleMeasurementUnitsMetric:
temp = context->temp_celsius;
temp_units = 'C';
break;
case LocaleMeasurementUnitsImperial:
temp = locale_celsius_to_fahrenheit(context->temp_celsius);
temp_units = 'F';
break;
default:
furi_crash("Illegal measurement units");
}
/* If a reading is available, display it */
snprintf(text_store, TEXT_STORE_SIZE, "Temperature: %+.1f%c", (double)temp, temp_units);
} else {
/* Or show a message that no data is available */
strncpy(text_store, "-- No data --", TEXT_STORE_SIZE);
}
canvas_draw_str_aligned(canvas, middle_x, 58, AlignCenter, AlignBottom, text_store);
}
/* This function is called from the GUI thread. All it does is put the event
into the application's queue so it can be processed later. */
static void example_thermo_input_callback(InputEvent* event, void* ctx) {
ExampleThermoContext* context = ctx;
furi_message_queue_put(context->event_queue, event, FuriWaitForever);
}
/* Starts the reader thread and handles the input */
static void example_thermo_run(ExampleThermoContext* context) {
/* Configure the hardware in host mode */
onewire_host_start(context->onewire);
/* Start the reader thread. It will talk to the thermometer in the background. */
furi_thread_start(context->reader_thread);
/* An endless loop which handles the input*/
for(bool is_running = true; is_running;) {
InputEvent event;
/* Wait for an input event. Input events come from the GUI thread via a callback. */
const FuriStatus status =
furi_message_queue_get(context->event_queue, &event, FuriWaitForever);
/* This application is only interested in short button presses. */
if((status != FuriStatusOk) || (event.type != InputTypeShort)) {
continue;
}
/* When the user presses the "Back" button, break the loop and exit the application. */
if(event.key == InputKeyBack) {
is_running = false;
}
}
/* Signal the reader thread to cease operation and exit */
furi_thread_flags_set(furi_thread_get_id(context->reader_thread), ReaderThreadFlagExit);
/* Wait for the reader thread to finish */
furi_thread_join(context->reader_thread);
/* Reset the hardware */
onewire_host_stop(context->onewire);
}
/******************** Initialisation & startup *****************************/
/* Allocate the memory and initialise the variables */
static ExampleThermoContext* example_thermo_context_alloc() {
ExampleThermoContext* context = malloc(sizeof(ExampleThermoContext));
context->view_port = view_port_alloc();
view_port_draw_callback_set(context->view_port, example_thermo_draw_callback, context);
view_port_input_callback_set(context->view_port, example_thermo_input_callback, context);
context->event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
context->reader_thread = furi_thread_alloc();
furi_thread_set_stack_size(context->reader_thread, 1024U);
furi_thread_set_context(context->reader_thread, context);
furi_thread_set_callback(context->reader_thread, example_thermo_reader_thread_callback);
context->gui = furi_record_open(RECORD_GUI);
gui_add_view_port(context->gui, context->view_port, GuiLayerFullscreen);
context->onewire = onewire_host_alloc(&THERMO_GPIO_PIN);
return context;
}
/* Release the unused resources and deallocate memory */
static void example_thermo_context_free(ExampleThermoContext* context) {
view_port_enabled_set(context->view_port, false);
gui_remove_view_port(context->gui, context->view_port);
onewire_host_free(context->onewire);
furi_thread_free(context->reader_thread);
furi_message_queue_free(context->event_queue);
view_port_free(context->view_port);
furi_record_close(RECORD_GUI);
}
/* The application's entry point. Execution starts from here. */
int32_t example_thermo_main(void* p) {
UNUSED(p);
/* Allocate all of the necessary structures */
ExampleThermoContext* context = example_thermo_context_alloc();
/* Start the applicaton's main loop. It won't return until the application was requested to exit. */
example_thermo_run(context);
/* Release all unneeded resources */
example_thermo_context_free(context);
return 0;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

View File

@@ -1,14 +1,12 @@
#include <archive/views/archive_browser_view.h>
#include "archive_files.h"
#include "archive_apps.h"
#include "archive_browser.h"
#include "../views/archive_browser_view.h"
#include <core/common_defines.h>
#include <core/log.h>
#include <gui/modules/file_browser_worker.h>
#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 +55,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 +139,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 +206,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 +455,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);

View File

@@ -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,
};

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -1,13 +1,10 @@
#pragma once
#include "../helpers/archive_files.h"
#include "../helpers/archive_favorites.h"
#include <gui/gui_i.h>
#include <gui/view.h>
#include <gui/canvas.h>
#include <gui/elements.h>
#include <gui/modules/file_browser_worker.h>
#include <furi.h>
#include <storage/storage.h>
#include "../helpers/archive_files.h"
#include "../helpers/archive_menu.h"
@@ -31,7 +28,6 @@ typedef enum {
ArchiveTabBadUsb,
ArchiveTabU2f,
ArchiveTabApplications,
ArchiveTabInternal,
ArchiveTabBrowser,
ArchiveTabTotal,
} ArchiveTabEnum;

View File

@@ -33,26 +33,9 @@ static void bad_usb_load_settings(BadUsbApp* app) {
!storage_file_eof(settings_file) && !isspace(chr)) {
furi_string_push_back(app->keyboard_layout, chr);
}
} else {
furi_string_reset(app->keyboard_layout);
}
storage_file_close(settings_file);
storage_file_free(settings_file);
if(!furi_string_empty(app->keyboard_layout)) {
Storage* fs_api = furi_record_open(RECORD_STORAGE);
FileInfo layout_file_info;
FS_Error file_check_err = storage_common_stat(
fs_api, furi_string_get_cstr(app->keyboard_layout), &layout_file_info);
furi_record_close(RECORD_STORAGE);
if(file_check_err != FSE_OK) {
furi_string_reset(app->keyboard_layout);
return;
}
if(layout_file_info.size != 256) {
furi_string_reset(app->keyboard_layout);
}
}
}
static void bad_usb_save_settings(BadUsbApp* app) {
@@ -115,12 +98,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 +121,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);

View File

@@ -14,10 +14,9 @@
#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"
#define BAD_USB_APP_PATH_LAYOUT_FOLDER BAD_USB_APP_BASE_FOLDER "/layouts"
#define BAD_USB_APP_SCRIPT_EXTENSION ".txt"
#define BAD_USB_APP_LAYOUT_EXTENSION ".kl"
@@ -40,8 +39,6 @@ struct BadUsbApp {
FuriString* keyboard_layout;
BadUsb* bad_usb_view;
BadUsbScript* bad_usb_script;
FuriHalUsbInterface* usb_if_prev;
};
typedef enum {

View File

@@ -54,7 +54,6 @@ static const DuckyKey ducky_keys[] = {
{"ALT-SHIFT", KEY_MOD_LEFT_ALT | KEY_MOD_LEFT_SHIFT},
{"ALT-GUI", KEY_MOD_LEFT_ALT | KEY_MOD_LEFT_GUI},
{"GUI-SHIFT", KEY_MOD_LEFT_GUI | KEY_MOD_LEFT_SHIFT},
{"GUI-CTRL", KEY_MOD_LEFT_GUI | KEY_MOD_LEFT_CTRL},
{"CTRL", KEY_MOD_LEFT_CTRL},
{"CONTROL", KEY_MOD_LEFT_CTRL},
@@ -120,6 +119,8 @@ static const char ducky_cmd_altchar[] = {"ALTCHAR "};
static const char ducky_cmd_altstr_1[] = {"ALTSTRING "};
static const char ducky_cmd_altstr_2[] = {"ALTCODE "};
static const char ducky_cmd_lang[] = {"DUCKY_LANG"};
static const uint8_t numpad_keys[10] = {
HID_KEYPAD_0,
HID_KEYPAD_1,
@@ -255,6 +256,9 @@ static int32_t
} else if(strncmp(line_tmp, ducky_cmd_id, strlen(ducky_cmd_id)) == 0) {
// ID - executed in ducky_script_preload
return (0);
} else if(strncmp(line_tmp, ducky_cmd_lang, strlen(ducky_cmd_lang)) == 0) {
// DUCKY_LANG - ignore command to retain compatibility with existing scripts
return (0);
} else if(strncmp(line_tmp, ducky_cmd_delay, strlen(ducky_cmd_delay)) == 0) {
// DELAY
line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1];
@@ -490,6 +494,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 +646,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);
@@ -690,7 +698,7 @@ void bad_usb_script_set_keyboard_layout(BadUsbScript* bad_usb, FuriString* layou
}
File* layout_file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
if(!furi_string_empty(layout_path)) { //-V1051
if(!furi_string_empty(layout_path)) {
if(storage_file_open(
layout_file, furi_string_get_cstr(layout_path), FSAM_READ, FSOM_OPEN_EXISTING)) {
uint16_t layout[128];

View File

@@ -17,8 +17,6 @@ static bool bad_usb_layout_select(BadUsbApp* bad_usb) {
DialogsFileBrowserOptions browser_options;
dialog_file_browser_set_basic_options(
&browser_options, BAD_USB_APP_LAYOUT_EXTENSION, &I_keyboard_10px);
browser_options.base_path = BAD_USB_APP_PATH_LAYOUT_FOLDER;
browser_options.skip_assets = false;
// Input events and views are managed by file_browser
bool res = dialog_file_browser_show(

View File

@@ -1,6 +1,6 @@
#include "../bad_usb_app_i.h"
#include <furi_hal_power.h>
#include <furi_hal_usb.h>
#include "furi_hal_power.h"
#include "furi_hal_usb.h"
#include <storage/storage.h>
static bool bad_usb_file_select(BadUsbApp* bad_usb) {

View File

@@ -1,7 +1,7 @@
#include "../bad_usb_script.h"
#include "../bad_usb_app_i.h"
#include "../views/bad_usb_view.h"
#include <furi_hal.h>
#include "furi_hal.h"
#include "toolbox/path.h"
void bad_usb_scene_work_button_callback(InputKey key, void* context) {

View File

@@ -25,7 +25,6 @@ GpioApp* gpio_app_alloc() {
GpioApp* app = malloc(sizeof(GpioApp));
app->gui = furi_record_open(RECORD_GUI);
app->gpio_items = gpio_items_alloc();
app->view_dispatcher = view_dispatcher_alloc();
app->scene_manager = scene_manager_alloc(&gpio_scene_handlers, app);
@@ -48,7 +47,7 @@ GpioApp* gpio_app_alloc() {
app->view_dispatcher,
GpioAppViewVarItemList,
variable_item_list_get_view(app->var_item_list));
app->gpio_test = gpio_test_alloc(app->gpio_items);
app->gpio_test = gpio_test_alloc();
view_dispatcher_add_view(
app->view_dispatcher, GpioAppViewGpioTest, gpio_test_get_view(app->gpio_test));
@@ -92,7 +91,6 @@ void gpio_app_free(GpioApp* app) {
furi_record_close(RECORD_GUI);
furi_record_close(RECORD_NOTIFICATION);
gpio_items_free(app->gpio_items);
free(app);
}

View File

@@ -1,7 +1,7 @@
#pragma once
#include "gpio_app.h"
#include "gpio_items.h"
#include "gpio_item.h"
#include "scenes/gpio_scene.h"
#include "gpio_custom_event.h"
#include "usb_uart_bridge.h"
@@ -28,7 +28,6 @@ struct GpioApp {
VariableItem* var_item_flow;
GpioTest* gpio_test;
GpioUsbUart* gpio_usb_uart;
GPIOItems* gpio_items;
UsbUartBridge* usb_uart_bridge;
UsbUartConfig* usb_uart_cfg;
};

View File

@@ -0,0 +1,51 @@
#include "gpio_item.h"
#include <furi_hal_resources.h>
typedef struct {
const char* name;
const GpioPin* pin;
} GpioItem;
static const GpioItem gpio_item[GPIO_ITEM_COUNT] = {
{"1.2: PA7", &gpio_ext_pa7},
{"1.3: PA6", &gpio_ext_pa6},
{"1.4: PA4", &gpio_ext_pa4},
{"1.5: PB3", &gpio_ext_pb3},
{"1.6: PB2", &gpio_ext_pb2},
{"1.7: PC3", &gpio_ext_pc3},
{"2.7: PC1", &gpio_ext_pc1},
{"2.8: PC0", &gpio_ext_pc0},
};
void gpio_item_configure_pin(uint8_t index, GpioMode mode) {
furi_assert(index < GPIO_ITEM_COUNT);
furi_hal_gpio_write(gpio_item[index].pin, false);
furi_hal_gpio_init(gpio_item[index].pin, mode, GpioPullNo, GpioSpeedVeryHigh);
}
void gpio_item_configure_all_pins(GpioMode mode) {
for(uint8_t i = 0; i < GPIO_ITEM_COUNT; i++) {
gpio_item_configure_pin(i, mode);
}
}
void gpio_item_set_pin(uint8_t index, bool level) {
furi_assert(index < GPIO_ITEM_COUNT);
furi_hal_gpio_write(gpio_item[index].pin, level);
}
void gpio_item_set_all_pins(bool level) {
for(uint8_t i = 0; i < GPIO_ITEM_COUNT; i++) {
gpio_item_set_pin(i, level);
}
}
const char* gpio_item_get_pin_name(uint8_t index) {
furi_assert(index < GPIO_ITEM_COUNT + 1);
if(index == GPIO_ITEM_COUNT) {
return "ALL";
} else {
return gpio_item[index].name;
}
}

View File

@@ -0,0 +1,15 @@
#pragma once
#include <furi_hal_gpio.h>
#define GPIO_ITEM_COUNT 8
void gpio_item_configure_pin(uint8_t index, GpioMode mode);
void gpio_item_configure_all_pins(GpioMode mode);
void gpio_item_set_pin(uint8_t index, bool level);
void gpio_item_set_all_pins(bool level);
const char* gpio_item_get_pin_name(uint8_t index);

View File

@@ -1,69 +0,0 @@
#include "gpio_items.h"
#include <furi_hal_resources.h>
struct GPIOItems {
GpioPinRecord* pins;
size_t count;
};
GPIOItems* gpio_items_alloc() {
GPIOItems* items = malloc(sizeof(GPIOItems));
items->count = 0;
for(size_t i = 0; i < gpio_pins_count; i++) {
if(!gpio_pins[i].debug) {
items->count++;
}
}
items->pins = malloc(sizeof(GpioPinRecord) * items->count);
for(size_t i = 0; i < items->count; i++) {
if(!gpio_pins[i].debug) {
items->pins[i].pin = gpio_pins[i].pin;
items->pins[i].name = gpio_pins[i].name;
}
}
return items;
}
void gpio_items_free(GPIOItems* items) {
free(items->pins);
free(items);
}
uint8_t gpio_items_get_count(GPIOItems* items) {
return items->count;
}
void gpio_items_configure_pin(GPIOItems* items, uint8_t index, GpioMode mode) {
furi_assert(index < items->count);
furi_hal_gpio_write(items->pins[index].pin, false);
furi_hal_gpio_init(items->pins[index].pin, mode, GpioPullNo, GpioSpeedVeryHigh);
}
void gpio_items_configure_all_pins(GPIOItems* items, GpioMode mode) {
for(uint8_t i = 0; i < items->count; i++) {
gpio_items_configure_pin(items, i, mode);
}
}
void gpio_items_set_pin(GPIOItems* items, uint8_t index, bool level) {
furi_assert(index < items->count);
furi_hal_gpio_write(items->pins[index].pin, level);
}
void gpio_items_set_all_pins(GPIOItems* items, bool level) {
for(uint8_t i = 0; i < items->count; i++) {
gpio_items_set_pin(items, i, level);
}
}
const char* gpio_items_get_pin_name(GPIOItems* items, uint8_t index) {
furi_assert(index < items->count + 1);
if(index == items->count) {
return "ALL";
} else {
return items->pins[index].name;
}
}

View File

@@ -1,29 +0,0 @@
#pragma once
#include <furi_hal_gpio.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct GPIOItems GPIOItems;
GPIOItems* gpio_items_alloc();
void gpio_items_free(GPIOItems* items);
uint8_t gpio_items_get_count(GPIOItems* items);
void gpio_items_configure_pin(GPIOItems* items, uint8_t index, GpioMode mode);
void gpio_items_configure_all_pins(GPIOItems* items, GpioMode mode);
void gpio_items_set_pin(GPIOItems* items, uint8_t index, bool level);
void gpio_items_set_all_pins(GPIOItems* items, bool level);
const char* gpio_items_get_pin_name(GPIOItems* items, uint8_t index);
#ifdef __cplusplus
}
#endif

View File

@@ -1,6 +1,6 @@
#include "../gpio_app_i.h"
#include <furi_hal_power.h>
#include <furi_hal_usb.h>
#include "furi_hal_power.h"
#include "furi_hal_usb.h"
#include <dolphin/dolphin.h>
enum GpioItem {

View File

@@ -12,9 +12,8 @@ void gpio_scene_test_ok_callback(InputType type, void* context) {
}
void gpio_scene_test_on_enter(void* context) {
furi_assert(context);
GpioApp* app = context;
gpio_items_configure_all_pins(app->gpio_items, GpioModeOutputPushPull);
gpio_item_configure_all_pins(GpioModeOutputPushPull);
gpio_test_set_ok_callback(app->gpio_test, gpio_scene_test_ok_callback, app);
view_dispatcher_switch_to_view(app->view_dispatcher, GpioAppViewGpioTest);
}
@@ -26,7 +25,6 @@ bool gpio_scene_test_on_event(void* context, SceneManagerEvent event) {
}
void gpio_scene_test_on_exit(void* context) {
furi_assert(context);
GpioApp* app = context;
gpio_items_configure_all_pins(app->gpio_items, GpioModeAnalog);
UNUSED(context);
gpio_item_configure_all_pins(GpioModeAnalog);
}

View File

@@ -1,6 +1,6 @@
#include "../usb_uart_bridge.h"
#include "../gpio_app_i.h"
#include <furi_hal.h>
#include "furi_hal.h"
typedef enum {
UsbUartLineIndexVcp,

View File

@@ -1,10 +1,10 @@
#include "usb_uart_bridge.h"
#include "usb_cdc.h"
#include <cli/cli_vcp.h>
#include <cli/cli.h>
#include <toolbox/api_lock.h>
#include <furi_hal.h>
#include "furi_hal.h"
#include <furi_hal_usb_cdc.h>
#include "usb_cdc.h"
#include "cli/cli_vcp.h"
#include <toolbox/api_lock.h>
#include "cli/cli.h"
#define USB_CDC_PKT_LEN CDC_DATA_SZ
#define USB_UART_RX_BUF_SIZE (USB_CDC_PKT_LEN * 5)

View File

@@ -1,5 +1,5 @@
#include "gpio_test.h"
#include "../gpio_items.h"
#include "../gpio_item.h"
#include <gui/elements.h>
@@ -11,7 +11,6 @@ struct GpioTest {
typedef struct {
uint8_t pin_idx;
GPIOItems* gpio_items;
} GpioTestModel;
static bool gpio_test_process_left(GpioTest* gpio_test);
@@ -26,12 +25,7 @@ static void gpio_test_draw_callback(Canvas* canvas, void* _model) {
elements_multiline_text_aligned(
canvas, 64, 16, AlignCenter, AlignTop, "Press < or > to change pin");
elements_multiline_text_aligned(
canvas,
64,
32,
AlignCenter,
AlignTop,
gpio_items_get_pin_name(model->gpio_items, model->pin_idx));
canvas, 64, 32, AlignCenter, AlignTop, gpio_item_get_pin_name(model->pin_idx));
}
static bool gpio_test_input_callback(InputEvent* event, void* context) {
@@ -70,7 +64,7 @@ static bool gpio_test_process_right(GpioTest* gpio_test) {
gpio_test->view,
GpioTestModel * model,
{
if(model->pin_idx < gpio_items_get_count(model->gpio_items)) {
if(model->pin_idx < GPIO_ITEM_COUNT) {
model->pin_idx++;
}
},
@@ -86,17 +80,17 @@ static bool gpio_test_process_ok(GpioTest* gpio_test, InputEvent* event) {
GpioTestModel * model,
{
if(event->type == InputTypePress) {
if(model->pin_idx < gpio_items_get_count(model->gpio_items)) {
gpio_items_set_pin(model->gpio_items, model->pin_idx, true);
if(model->pin_idx < GPIO_ITEM_COUNT) {
gpio_item_set_pin(model->pin_idx, true);
} else {
gpio_items_set_all_pins(model->gpio_items, true);
gpio_item_set_all_pins(true);
}
consumed = true;
} else if(event->type == InputTypeRelease) {
if(model->pin_idx < gpio_items_get_count(model->gpio_items)) {
gpio_items_set_pin(model->gpio_items, model->pin_idx, false);
if(model->pin_idx < GPIO_ITEM_COUNT) {
gpio_item_set_pin(model->pin_idx, false);
} else {
gpio_items_set_all_pins(model->gpio_items, false);
gpio_item_set_all_pins(false);
}
consumed = true;
}
@@ -107,15 +101,11 @@ static bool gpio_test_process_ok(GpioTest* gpio_test, InputEvent* event) {
return consumed;
}
GpioTest* gpio_test_alloc(GPIOItems* gpio_items) {
GpioTest* gpio_test_alloc() {
GpioTest* gpio_test = malloc(sizeof(GpioTest));
gpio_test->view = view_alloc();
view_allocate_model(gpio_test->view, ViewModelTypeLocking, sizeof(GpioTestModel));
with_view_model(
gpio_test->view, GpioTestModel * model, { model->gpio_items = gpio_items; }, false);
view_set_context(gpio_test->view, gpio_test);
view_set_draw_callback(gpio_test->view, gpio_test_draw_callback);
view_set_input_callback(gpio_test->view, gpio_test_input_callback);

View File

@@ -1,13 +1,11 @@
#pragma once
#include "../gpio_items.h"
#include <gui/view.h>
typedef struct GpioTest GpioTest;
typedef void (*GpioTestOkCallback)(InputType type, void* context);
GpioTest* gpio_test_alloc(GPIOItems* gpio_items);
GpioTest* gpio_test_alloc();
void gpio_test_free(GpioTest* gpio_test);

View File

@@ -1,6 +1,6 @@
#include "../usb_uart_bridge.h"
#include "../gpio_app_i.h"
#include <furi_hal.h>
#include "furi_hal.h"
#include <gui/elements.h>
struct GpioUsbUart {

View File

@@ -2,7 +2,6 @@ App(
appid="ibutton",
name="iButton",
apptype=FlipperAppType.APP,
targets=["f7"],
entry_point="ibutton_app",
cdefines=["APP_IBUTTON"],
requires=[

View File

@@ -271,7 +271,7 @@ void onewire_cli_print_usage() {
static void onewire_cli_search(Cli* cli) {
UNUSED(cli);
OneWireHost* onewire = onewire_host_alloc(&ibutton_gpio);
OneWireHost* onewire = onewire_host_alloc();
uint8_t address[8];
bool done = false;

View File

@@ -3,7 +3,6 @@ App(
name="Infrared",
apptype=FlipperAppType.APP,
entry_point="infrared_app",
targets=["f7"],
cdefines=["APP_INFRARED"],
requires=[
"gui",

View File

@@ -86,7 +86,7 @@ static void infrared_cli_print_usage(void) {
printf("\tir universal <remote_name> <signal_name>\r\n");
printf("\tir universal list <remote_name>\r\n");
// TODO: Do not hardcode universal remote names
printf("\tAvailable universal remotes: tv audio ac projector\r\n");
printf("\tAvailable universal remotes: tv audio ac\r\n");
}
static void infrared_cli_start_ir_rx(Cli* cli, FuriString* args) {

View File

@@ -1,5 +1,5 @@
#include "../infrared_i.h"
#include <gui/canvas.h>
#include "gui/canvas.h"
typedef enum {
InfraredRpcStateIdle,

View File

@@ -52,8 +52,7 @@ void infrared_scene_universal_on_enter(void* context) {
infrared_scene_universal_submenu_callback,
context);
submenu_set_selected_item(
submenu, scene_manager_get_scene_state(infrared->scene_manager, InfraredSceneUniversal));
submenu_set_selected_item(submenu, 0);
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewSubmenu);
}
@@ -80,7 +79,6 @@ bool infrared_scene_universal_on_event(void* context, SceneManagerEvent event) {
scene_manager_next_scene(scene_manager, InfraredSceneUniversalAC);
consumed = true;
}
scene_manager_set_scene_state(scene_manager, InfraredSceneUniversal, event.event);
}
return consumed;

View File

@@ -1,11 +1,11 @@
#include "infrared_debug_view.h"
#include <gui/canvas.h>
#include <gui/elements.h>
#include <stdlib.h>
#include <string.h>
#include <gui/canvas.h>
#include <gui/elements.h>
#define INFRARED_DEBUG_TEXT_LENGTH 64
struct InfraredDebugView {

View File

@@ -1,15 +1,13 @@
#include "infrared_progress_view.h"
#include <assets_icons.h>
#include <gui/canvas.h>
#include <gui/view.h>
#include <gui/elements.h>
#include <gui/modules/button_panel.h>
#include <input/input.h>
#include <furi.h>
#include <furi_hal_resources.h>
#include <core/check.h>
#include "furi_hal_resources.h"
#include "assets_icons.h"
#include "gui/canvas.h"
#include "gui/view.h"
#include "input/input.h"
#include <gui/elements.h>
#include <furi.h>
#include "infrared_progress_view.h"
#include "gui/modules/button_panel.h"
#include <stdint.h>
struct InfraredProgressView {

View File

@@ -2,7 +2,6 @@ App(
appid="lfrfid",
name="125 kHz RFID",
apptype=FlipperAppType.APP,
targets=["f7"],
entry_point="lfrfid_app",
cdefines=["APP_LF_RFID"],
requires=[

View File

@@ -47,28 +47,21 @@ bool lfrfid_scene_start_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubmenuIndexRead) {
scene_manager_set_scene_state(app->scene_manager, LfRfidSceneStart, SubmenuIndexRead);
scene_manager_next_scene(app->scene_manager, LfRfidSceneRead);
DOLPHIN_DEED(DolphinDeedRfidRead);
consumed = true;
} else if(event.event == SubmenuIndexSaved) {
// Like in the other apps, explicitly save the scene state
// in each branch in case the user cancels loading a file.
scene_manager_set_scene_state(app->scene_manager, LfRfidSceneStart, SubmenuIndexSaved);
furi_string_set(app->file_path, LFRFID_APP_FOLDER);
scene_manager_next_scene(app->scene_manager, LfRfidSceneSelectKey);
consumed = true;
} else if(event.event == SubmenuIndexAddManually) {
scene_manager_set_scene_state(
app->scene_manager, LfRfidSceneStart, SubmenuIndexAddManually);
scene_manager_next_scene(app->scene_manager, LfRfidSceneSaveType);
consumed = true;
} else if(event.event == SubmenuIndexExtraActions) {
scene_manager_set_scene_state(
app->scene_manager, LfRfidSceneStart, SubmenuIndexExtraActions);
scene_manager_next_scene(app->scene_manager, LfRfidSceneExtraActions);
consumed = true;
}
scene_manager_set_scene_state(app->scene_manager, LfRfidSceneStart, event.event);
}
return consumed;

View File

@@ -2,7 +2,6 @@ App(
appid="nfc",
name="NFC",
apptype=FlipperAppType.APP,
targets=["f7"],
entry_point="nfc_app",
cdefines=["APP_NFC"],
requires=[

View File

@@ -1,5 +1,5 @@
#include "nfc_i.h"
#include <furi_hal_nfc.h>
#include "furi_hal_nfc.h"
#include <dolphin/dolphin.h>
bool nfc_custom_event_callback(void* context, uint32_t event) {

View File

@@ -4,7 +4,7 @@ ADD_SCENE(nfc, saved_menu, SavedMenu)
ADD_SCENE(nfc, extra_actions, ExtraActions)
ADD_SCENE(nfc, set_type, SetType)
ADD_SCENE(nfc, set_sak, SetSak)
ADD_SCENE(nfc, set_atqa, SetAtqa)
ADD_SCENE(nfc, set_atqa, SetAtqua)
ADD_SCENE(nfc, set_uid, SetUid)
ADD_SCENE(nfc, generate_info, GenerateInfo)
ADD_SCENE(nfc, read_card_success, ReadCardSuccess)

View File

@@ -30,7 +30,7 @@ bool nfc_scene_delete_success_on_event(void* context, SceneManagerEvent event) {
nfc->scene_manager, NfcSceneMfClassicKeys);
} else {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneFileSelect);
nfc->scene_manager, NfcSceneStart);
}
}
}

View File

@@ -34,8 +34,6 @@ void nfc_scene_extra_actions_on_enter(void* context) {
SubmenuIndexMfUltralightUnlock,
nfc_scene_extra_actions_submenu_callback,
nfc);
submenu_set_selected_item(
submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneExtraActions));
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
}

View File

@@ -11,7 +11,7 @@ void nfc_scene_set_atqa_on_enter(void* context) {
// Setup view
ByteInput* byte_input = nfc->byte_input;
byte_input_set_header_text(byte_input, "Enter ATQA in hex");
byte_input_set_header_text(byte_input, "Enter atqa in hex");
byte_input_set_result_callback(
byte_input,
nfc_scene_set_atqa_byte_input_callback,

View File

@@ -28,7 +28,7 @@ bool nfc_scene_set_sak_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventByteInputDone) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneSetAtqa);
scene_manager_next_scene(nfc->scene_manager, NfcSceneSetAtqua);
consumed = true;
}
}

View File

@@ -11,7 +11,7 @@ void nfc_scene_set_uid_on_enter(void* context) {
// Setup view
ByteInput* byte_input = nfc->byte_input;
byte_input_set_header_text(byte_input, "Enter UID in hex");
byte_input_set_header_text(byte_input, "Enter uid in hex");
nfc->dev_edit_data = nfc->dev->dev_data.nfc_data;
byte_input_set_result_callback(
byte_input,

View File

@@ -48,14 +48,11 @@ bool nfc_scene_start_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubmenuIndexRead) {
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, SubmenuIndexRead);
nfc->dev->dev_data.read_mode = NfcReadModeAuto;
scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
DOLPHIN_DEED(DolphinDeedNfcRead);
consumed = true;
} else if(event.event == SubmenuIndexDetectReader) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneStart, SubmenuIndexDetectReader);
bool sd_exist = storage_sd_status(nfc->dev->storage) == FSE_OK;
if(sd_exist) {
nfc_device_data_clear(&nfc->dev->dev_data);
@@ -66,27 +63,19 @@ bool nfc_scene_start_on_event(void* context, SceneManagerEvent event) {
}
consumed = true;
} else if(event.event == SubmenuIndexSaved) {
// Save the scene state explicitly in each branch, so that
// if the user cancels loading a file, the Saved menu item
// is properly reselected.
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, SubmenuIndexSaved);
scene_manager_next_scene(nfc->scene_manager, NfcSceneFileSelect);
consumed = true;
} else if(event.event == SubmenuIndexExtraAction) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneStart, SubmenuIndexExtraAction);
scene_manager_next_scene(nfc->scene_manager, NfcSceneExtraActions);
consumed = true;
} else if(event.event == SubmenuIndexAddManually) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneStart, SubmenuIndexAddManually);
scene_manager_next_scene(nfc->scene_manager, NfcSceneSetType);
consumed = true;
} else if(event.event == SubmenuIndexDebug) {
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, SubmenuIndexDebug);
scene_manager_next_scene(nfc->scene_manager, NfcSceneDebug);
consumed = true;
}
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, event.event);
}
return consumed;
}

View File

@@ -2,7 +2,6 @@ App(
appid="subghz",
name="Sub-GHz",
apptype=FlipperAppType.APP,
targets=["f7"],
entry_point="subghz_app",
cdefines=["APP_SUBGHZ"],
requires=[
@@ -12,7 +11,7 @@ App(
],
provides=["subghz_start"],
icon="A_Sub1ghz_14",
stack_size=3 * 1024,
stack_size=2 * 1024,
order=10,
)

View File

@@ -36,13 +36,13 @@ struct SubGhzFrequencyAnalyzerWorker {
};
static void subghz_frequency_analyzer_worker_load_registers(const uint8_t data[][2]) {
furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle);
furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
size_t i = 0;
while(data[i][0]) {
cc1101_write_reg(furi_hal_subghz.spi_bus_handle, data[i][0], data[i][1]);
cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, data[i][0], data[i][1]);
i++;
}
furi_hal_spi_release(furi_hal_subghz.spi_bus_handle);
furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
}
// running average with adaptive coefficient
@@ -80,26 +80,26 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) {
//Start CC1101
furi_hal_subghz_reset();
furi_hal_spi_acquire(furi_hal_subghz.spi_bus_handle);
cc1101_flush_rx(furi_hal_subghz.spi_bus_handle);
cc1101_flush_tx(furi_hal_subghz.spi_bus_handle);
cc1101_write_reg(furi_hal_subghz.spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHW);
cc1101_write_reg(furi_hal_subghz.spi_bus_handle, CC1101_MDMCFG3,
furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
cc1101_flush_rx(&furi_hal_spi_bus_handle_subghz);
cc1101_flush_tx(&furi_hal_spi_bus_handle_subghz);
cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHW);
cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_MDMCFG3,
0b01111111); // symbol rate
cc1101_write_reg(
furi_hal_subghz.spi_bus_handle,
&furi_hal_spi_bus_handle_subghz,
CC1101_AGCCTRL2,
0b00000111); // 00 - DVGA all; 000 - MAX LNA+LNA2; 111 - MAGN_TARGET 42 dB
cc1101_write_reg(
furi_hal_subghz.spi_bus_handle,
&furi_hal_spi_bus_handle_subghz,
CC1101_AGCCTRL1,
0b00001000); // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 1000 - Absolute carrier sense threshold disabled
cc1101_write_reg(
furi_hal_subghz.spi_bus_handle,
&furi_hal_spi_bus_handle_subghz,
CC1101_AGCCTRL0,
0b00110000); // 00 - No hysteresis, medium asymmetric dead zone, medium gain ; 11 - 64 samples agc; 00 - Normal AGC, 00 - 4dB boundary
furi_hal_spi_release(furi_hal_subghz.spi_bus_handle);
furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate);
@@ -117,23 +117,21 @@ 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) &&
!((furi_hal_subghz.radio_type == SubGhzRadioExternal) &&
(current_frequnecy >= 311900000 && current_frequnecy <= 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);
if(furi_hal_subghz_is_frequency_valid(
subghz_setting_get_frequency(instance->setting, i))) {
furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz);
frequency = cc1101_set_frequency(
&furi_hal_spi_bus_handle_subghz,
subghz_setting_get_frequency(instance->setting, i));
cc1101_calibrate(furi_hal_subghz.spi_bus_handle);
cc1101_calibrate(&furi_hal_spi_bus_handle_subghz);
do {
status = cc1101_get_status(furi_hal_subghz.spi_bus_handle);
status = cc1101_get_status(&furi_hal_spi_bus_handle_subghz);
} while(status.STATE != CC1101StateIDLE);
cc1101_switch_to_rx(furi_hal_subghz.spi_bus_handle);
furi_hal_spi_release(furi_hal_subghz.spi_bus_handle);
cc1101_switch_to_rx(&furi_hal_spi_bus_handle_subghz);
furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
furi_delay_ms(2);
@@ -168,17 +166,17 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) {
i < frequency_rssi.frequency_coarse + 300000;
i += 20000) {
if(furi_hal_subghz_is_frequency_valid(i)) {
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, i);
furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz);
frequency = cc1101_set_frequency(&furi_hal_spi_bus_handle_subghz, i);
cc1101_calibrate(furi_hal_subghz.spi_bus_handle);
cc1101_calibrate(&furi_hal_spi_bus_handle_subghz);
do {
status = cc1101_get_status(furi_hal_subghz.spi_bus_handle);
status = cc1101_get_status(&furi_hal_spi_bus_handle_subghz);
} while(status.STATE != CC1101StateIDLE);
cc1101_switch_to_rx(furi_hal_subghz.spi_bus_handle);
furi_hal_spi_release(furi_hal_subghz.spi_bus_handle);
cc1101_switch_to_rx(&furi_hal_spi_bus_handle_subghz);
furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
furi_delay_ms(2);

View File

@@ -26,7 +26,6 @@ ADD_SCENE(subghz, set_fix_bft, SetFixBft)
ADD_SCENE(subghz, set_cnt_bft, SetCntBft)
ADD_SCENE(subghz, set_seed_bft, SetSeedBft)
ADD_SCENE(subghz, frequency_analyzer, FrequencyAnalyzer)
ADD_SCENE(subghz, ext_module_settings, ExtModuleSettings)
ADD_SCENE(subghz, read_raw, ReadRAW)
ADD_SCENE(subghz, more_raw, MoreRAW)
ADD_SCENE(subghz, decode_raw, DecodeRAW)

View File

@@ -170,6 +170,11 @@ void subghz_scene_decode_raw_on_enter(void* context) {
subghz_receiver_set_rx_callback(
subghz->txrx->receiver, subghz_scene_add_to_history_callback, subghz);
// make sure we're not in auto-detect mode, which is only meant for the Read app
subghz_protocol_decoder_raw_set_auto_mode(
subghz_receiver_search_decoder_base_by_name(
subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME),
false);
subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable);
if(subghz->decode_raw_state == SubGhzDecodeRawStateStart) {

View File

@@ -31,6 +31,7 @@ bool subghz_scene_delete_success_on_event(void* context, SceneManagerEvent event
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReadRAW);
} else if(scene_manager_search_and_switch_to_previous_scene(
subghz->scene_manager, SubGhzSceneSaved)) {
//scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaved);
} else {
scene_manager_search_and_switch_to_previous_scene(
subghz->scene_manager, SubGhzSceneStart);

View File

@@ -1,92 +0,0 @@
#include "../subghz_i.h"
#include "../helpers/subghz_custom_event.h"
uint8_t value_index;
uint8_t value_index2;
#define EXT_MODULES_COUNT (sizeof(radio_modules_variables_text) / sizeof(char* const))
const char* const radio_modules_variables_text[] = {
"Internal",
"External",
};
#define DEBUG_P_COUNT 2
const char* const debug_pin_text[DEBUG_P_COUNT] = {
"OFF",
"17(1W)",
};
static void subghz_scene_ext_module_changed(VariableItem* item) {
SubGhz* subghz = variable_item_get_context(item);
value_index = variable_item_get_current_value_index(item);
UNUSED(subghz);
variable_item_set_current_value_text(item, radio_modules_variables_text[value_index]);
}
static void subghz_ext_module_start_var_list_enter_callback(void* context, uint32_t index) {
SubGhz* subghz = context;
view_dispatcher_send_custom_event(subghz->view_dispatcher, index);
}
static void subghz_scene_receiver_config_set_debug_pin(VariableItem* item) {
SubGhz* subghz = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(item, debug_pin_text[index]);
subghz->txrx->debug_pin_state = index == 1;
}
void subghz_scene_ext_module_settings_on_enter(void* context) {
SubGhz* subghz = context;
VariableItemList* variable_item_list = subghz->variable_item_list;
value_index = furi_hal_subghz.radio_type;
VariableItem* item = variable_item_list_add(
variable_item_list, "Module", EXT_MODULES_COUNT, subghz_scene_ext_module_changed, subghz);
variable_item_list_set_enter_callback(
variable_item_list, subghz_ext_module_start_var_list_enter_callback, subghz);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, radio_modules_variables_text[value_index]);
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
item = variable_item_list_add(
subghz->variable_item_list,
"Debug Pin:",
DEBUG_P_COUNT,
subghz_scene_receiver_config_set_debug_pin,
subghz);
value_index2 = subghz->txrx->debug_pin_state;
variable_item_set_current_value_index(item, value_index2);
variable_item_set_current_value_text(item, debug_pin_text[value_index2]);
}
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdVariableItemList);
}
bool subghz_scene_ext_module_settings_on_event(void* context, SceneManagerEvent event) {
SubGhz* subghz = context;
UNUSED(subghz);
UNUSED(event);
// Set selected radio module
furi_hal_subghz_set_radio_type(value_index);
// Check if module is present, if no -> show error
if(!furi_hal_subghz_check_radio()) {
value_index = 0;
furi_hal_subghz_set_radio_type(value_index);
furi_string_set(subghz->error_str, "Please connect\nexternal radio");
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowErrorSub);
}
return false;
}
void subghz_scene_ext_module_settings_on_exit(void* context) {
SubGhz* subghz = context;
variable_item_list_reset(subghz->variable_item_list);
}

View File

@@ -119,6 +119,9 @@ void subghz_scene_read_raw_on_enter(void* context) {
subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME);
furi_assert(subghz->txrx->decoder_result);
// make sure we're not in auto-detect mode, which is only meant for the Read app
subghz_protocol_decoder_raw_set_auto_mode(subghz->txrx->decoder_result, false);
//set filter RAW feed
subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_RAW);
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdReadRAW);
@@ -419,6 +422,10 @@ void subghz_scene_read_raw_on_exit(void* context) {
subghz->state_notifications = SubGhzNotificationStateIDLE;
notification_message(subghz->notifications, &sequence_reset_rgb);
//filter restoration
subghz_receiver_set_filter(subghz->txrx->receiver, subghz->txrx->filter);
//filter restoration
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
subghz_last_settings_set_detect_raw_values(subghz);
#else
subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable);
#endif
}

View File

@@ -1,7 +1,6 @@
#include "../subghz_i.h"
#include "../views/receiver.h"
#include <dolphin/dolphin.h>
#include <lib/subghz/protocols/bin_raw.h>
#define TAG "SubGhzSceneReceiver"
@@ -54,10 +53,7 @@ static void subghz_scene_receiver_update_statusbar(void* context) {
} else {
subghz_get_frequency_modulation(subghz, frequency_str, NULL);
furi_string_printf(
modulation_str,
"%s Mod: %s",
furi_hal_subghz_get_radio_type() ? "Ext" : "Int",
furi_string_get_cstr(subghz->txrx->preset->name));
modulation_str, "Mod: %s", furi_string_get_cstr(subghz->txrx->preset->name));
}
#else
subghz_get_frequency_modulation(subghz, frequency_str, modulation_str);
@@ -161,11 +157,6 @@ void subghz_scene_receiver_on_enter(void* context) {
}
subghz_view_receiver_set_idx_menu(subghz->subghz_receiver, subghz->txrx->idx_menu_chosen);
//to use a universal decoder, we are looking for a link to it
subghz->txrx->decoder_result = subghz_receiver_search_decoder_base_by_name(
subghz->txrx->receiver, SUBGHZ_PROTOCOL_BIN_RAW_NAME);
furi_assert(subghz->txrx->decoder_result);
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdReceiver);
}
@@ -182,6 +173,7 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) {
subghz_sleep(subghz);
}
subghz->txrx->hopper_state = SubGhzHopperStateOFF;
subghz_history_set_hopper_state(subghz->txrx->history, false);
subghz->txrx->idx_menu_chosen = 0;
subghz_receiver_set_rx_callback(subghz->txrx->receiver, NULL, subghz);
@@ -229,13 +221,6 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) {
subghz_hopper_update(subghz);
subghz_scene_receiver_update_statusbar(subghz);
}
//get RSSI
float rssi = furi_hal_subghz_get_rssi();
subghz_receiver_rssi(subghz->subghz_receiver, rssi);
subghz_protocol_decoder_bin_raw_data_input_rssi(
(SubGhzProtocolDecoderBinRAW*)subghz->txrx->decoder_result, rssi);
switch(subghz->state_notifications) {
case SubGhzNotificationStateRx:
notification_message(subghz->notifications, &sequence_blink_cyan_10);

View File

@@ -1,11 +1,16 @@
#include "../subghz_i.h"
#include <lib/toolbox/value_index.h>
#include <lib/subghz/protocols/raw.h>
#define TAG "SubGhzSceneReceiverConfig"
enum SubGhzSettingIndex {
SubGhzSettingIndexFrequency,
SubGhzSettingIndexHopping,
SubGhzSettingIndexModulation,
SubGhzSettingIndexBinRAW,
SubGhzSettingIndexDetectRaw,
SubGhzSettingIndexRSSIThreshold,
SubGhzSettingIndexSound,
SubGhzSettingIndexLock,
SubGhzSettingIndexRAWThesholdRSSI,
@@ -50,6 +55,40 @@ const uint32_t hopping_value[HOPPING_COUNT] = {
SubGhzHopperStateRunnig,
};
#define DETECT_RAW_COUNT 2
const char* const detect_raw_text[DETECT_RAW_COUNT] = {
"OFF",
"ON",
};
#ifndef SUBGHZ_SAVE_DETECT_RAW_SETTING
const SubGhzProtocolFlag detect_raw_value[DETECT_RAW_COUNT] = {
SubGhzProtocolFlag_Decodable,
SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_RAW,
};
#endif
#define RSSI_THRESHOLD_COUNT 7
const char* const rssi_threshold_text[RSSI_THRESHOLD_COUNT] = {
"-72db",
"-67db",
"-62db",
"-57db",
"-52db",
"-47db",
"-42db",
};
const int rssi_threshold_value[RSSI_THRESHOLD_COUNT] = {
-72,
-67,
-62,
-57,
-52,
-47,
-42,
};
#define SPEAKER_COUNT 2
const char* const speaker_text[SPEAKER_COUNT] = {
"OFF",
@@ -59,15 +98,6 @@ const uint32_t speaker_value[SPEAKER_COUNT] = {
SubGhzSpeakerStateShutdown,
SubGhzSpeakerStateEnable,
};
#define BIN_RAW_COUNT 2
const char* const bin_raw_text[BIN_RAW_COUNT] = {
"OFF",
"ON",
};
const uint32_t bin_raw_value[BIN_RAW_COUNT] = {
SubGhzProtocolFlag_Decodable,
SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_BinRAW,
};
uint8_t subghz_scene_receiver_config_next_frequency(const uint32_t value, void* context) {
furi_assert(context);
@@ -119,6 +149,36 @@ uint8_t subghz_scene_receiver_config_hopper_value_index(
}
}
#ifndef SUBGHZ_SAVE_DETECT_RAW_SETTING
uint8_t subghz_scene_receiver_config_detect_raw_value_index(
const SubGhzProtocolFlag value,
const SubGhzProtocolFlag values[],
uint8_t values_count) {
uint8_t index = 0;
for(uint8_t i = 0; i < values_count; i++) {
if(value == values[i]) {
index = i;
break;
}
}
return index;
}
#endif
uint8_t subghz_scene_receiver_config_rssi_threshold_value_index(
const int value,
const int values[],
uint8_t values_count) {
uint8_t index = 0;
for(uint8_t i = 0; i < values_count; i++) {
if(value == values[i]) {
index = i;
break;
}
}
return index;
}
static void subghz_scene_receiver_config_set_frequency(VariableItem* item) {
SubGhz* subghz = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
@@ -156,10 +216,45 @@ static void subghz_scene_receiver_config_set_preset(VariableItem* item) {
subghz_setting_get_preset_data_size(subghz->setting, index));
}
static void subghz_scene_receiver_config_set_rssi_threshold(VariableItem* item) {
SubGhz* subghz = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(item, rssi_threshold_text[index]);
subghz_protocol_decoder_raw_set_rssi_threshold(
subghz_receiver_search_decoder_base_by_name(
subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME),
rssi_threshold_value[index]);
}
static void subghz_scene_receiver_config_set_detect_raw(VariableItem* item) {
SubGhz* subghz = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
//if(subghz->txrx->hopper_state == 0) {
variable_item_set_current_value_text(item, detect_raw_text[index]);
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
subghz->last_settings->detect_raw = index;
subghz_last_settings_set_detect_raw_values(subghz);
#else
subghz_receiver_set_filter(subghz->txrx->receiver, detect_raw_value[index]);
subghz_protocol_decoder_raw_set_auto_mode(
subghz_receiver_search_decoder_base_by_name(
subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME),
(index == 1));
#endif
/*} else {
variable_item_set_current_value_index(item, 0);
}*/
}
static void subghz_scene_receiver_config_set_hopping_running(VariableItem* item) {
SubGhz* subghz = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
//if(subghz_receiver_get_filter(subghz->txrx->receiver) == SubGhzProtocolFlag_Decodable) {
variable_item_set_current_value_text(item, hopping_text[index]);
if(hopping_value[index] == SubGhzHopperStateOFF) {
char text_buf[10] = {0};
@@ -190,6 +285,10 @@ static void subghz_scene_receiver_config_set_hopping_running(VariableItem* item)
}
subghz->txrx->hopper_state = hopping_value[index];
subghz_history_set_hopper_state(subghz->txrx->history, (index == 1));
/*} else {
variable_item_set_current_value_index(item, 0);
}*/
}
static void subghz_scene_receiver_config_set_speaker(VariableItem* item) {
@@ -200,15 +299,6 @@ static void subghz_scene_receiver_config_set_speaker(VariableItem* item) {
subghz->txrx->speaker_state = speaker_value[index];
}
static void subghz_scene_receiver_config_set_bin_raw(VariableItem* item) {
SubGhz* subghz = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(item, bin_raw_text[index]);
subghz->txrx->filter = bin_raw_value[index];
subghz_receiver_set_filter(subghz->txrx->receiver, subghz->txrx->filter);
}
static void subghz_scene_receiver_config_set_raw_threshold_rssi(VariableItem* item) {
SubGhz* subghz = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
@@ -231,6 +321,13 @@ void subghz_scene_receiver_config_on_enter(void* context) {
VariableItem* item;
uint8_t value_index;
#ifdef FURI_DEBUG
FURI_LOG_D(
TAG,
"Last frequency: %ld, Preset: %ld",
subghz->last_settings->frequency,
subghz->last_settings->preset);
#endif
item = variable_item_list_add(
subghz->variable_item_list,
"Frequency:",
@@ -276,35 +373,52 @@ void subghz_scene_receiver_config_on_enter(void* context) {
subghz->txrx->hopper_state, hopping_value, HOPPING_COUNT, subghz);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, hopping_text[value_index]);
}
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) !=
SubGhzCustomEventManagerSet) {
// Detect Raw
item = variable_item_list_add(
subghz->variable_item_list,
"Bin RAW:",
BIN_RAW_COUNT,
subghz_scene_receiver_config_set_bin_raw,
"Detect Raw:",
DETECT_RAW_COUNT,
subghz_scene_receiver_config_set_detect_raw,
subghz);
value_index = value_index_uint32(subghz->txrx->filter, bin_raw_value, BIN_RAW_COUNT);
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
value_index = subghz->last_settings->detect_raw;
#else
value_index = subghz_scene_receiver_config_detect_raw_value_index(
subghz_receiver_get_filter(subghz->txrx->receiver),
detect_raw_value,
DETECT_RAW_COUNT);
#endif
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, bin_raw_text[value_index]);
}
variable_item_set_current_value_text(item, detect_raw_text[value_index]);
// Enable speaker, will send all incoming noises and signals to speaker so you can listen how your remote sounds like :)
item = variable_item_list_add(
subghz->variable_item_list,
"Sound:",
SPEAKER_COUNT,
subghz_scene_receiver_config_set_speaker,
subghz);
value_index = value_index_uint32(subghz->txrx->speaker_state, speaker_value, SPEAKER_COUNT);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, speaker_text[value_index]);
// RSSI
item = variable_item_list_add(
subghz->variable_item_list,
"RSSI for Raw:",
RSSI_THRESHOLD_COUNT,
subghz_scene_receiver_config_set_rssi_threshold,
subghz);
value_index = subghz_scene_receiver_config_rssi_threshold_value_index(
subghz_protocol_encoder_get_rssi_threshold(subghz_receiver_search_decoder_base_by_name(
subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME)),
rssi_threshold_value,
RSSI_THRESHOLD_COUNT);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, rssi_threshold_text[value_index]);
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) !=
SubGhzCustomEventManagerSet) {
// Lock keyboard
item = variable_item_list_add(
subghz->variable_item_list,
"Sound:",
SPEAKER_COUNT,
subghz_scene_receiver_config_set_speaker,
subghz);
value_index =
value_index_uint32(subghz->txrx->speaker_state, speaker_value, SPEAKER_COUNT);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, speaker_text[value_index]);
variable_item_list_add(subghz->variable_item_list, "Lock Keyboard", 1, NULL, NULL);
variable_item_list_set_enter_callback(
subghz->variable_item_list,

View File

@@ -92,6 +92,8 @@ void subghz_scene_receiver_info_draw_widget(SubGhz* subghz) {
// Removed static check
if(((subghz->txrx->decoder_result->protocol->flag & SubGhzProtocolFlag_Send) ==
SubGhzProtocolFlag_Send) &&
// disable "Send" for auto-captured RAW signals for now. They can still be saved and sent by loading them.
subghz->txrx->decoder_result->protocol->type != SubGhzProtocolTypeRAW &&
subghz->txrx->decoder_result->protocol->encoder->deserialize) {
widget_add_button_element(
subghz->widget,
@@ -136,21 +138,6 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event)
subghz_history_get_raw_data(
subghz->txrx->history, subghz->txrx->idx_menu_chosen))) {
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowOnlyRx);
if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
subghz_tx_stop(subghz);
}
if(subghz->txrx->txrx_state == SubGhzTxRxStateIDLE) {
subghz_begin(
subghz,
subghz_setting_get_preset_data_by_name(
subghz->setting,
furi_string_get_cstr(subghz->txrx->preset->name)));
subghz_rx(subghz, subghz->txrx->preset->frequency);
}
if(subghz->txrx->hopper_state == SubGhzHopperStatePause) {
subghz->txrx->hopper_state = SubGhzHopperStateRunnig;
}
subghz->state_notifications = SubGhzNotificationStateRx;
} else {
subghz->state_notifications = SubGhzNotificationStateTx;
}

View File

@@ -10,7 +10,6 @@ enum SubmenuIndex {
SubmenuIndexAddManually,
SubmenuIndexFrequencyAnalyzer,
SubmenuIndexReadRAW,
SubmenuIndexExtSettings,
};
void subghz_scene_start_submenu_callback(void* context, uint32_t index) {
@@ -23,6 +22,15 @@ void subghz_scene_start_on_enter(void* context) {
if(subghz->state_notifications == SubGhzNotificationStateStarting) {
subghz->state_notifications = SubGhzNotificationStateIDLE;
}
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
subghz_last_settings_set_detect_raw_values(subghz);
#else
subghz_protocol_decoder_raw_set_auto_mode(
subghz_receiver_search_decoder_base_by_name(
subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME),
false);
subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable);
#endif
submenu_add_item(
subghz->submenu, "Read", SubmenuIndexRead, subghz_scene_start_submenu_callback, subghz);
@@ -46,12 +54,6 @@ void subghz_scene_start_on_enter(void* context) {
SubmenuIndexFrequencyAnalyzer,
subghz_scene_start_submenu_callback,
subghz);
submenu_add_item(
subghz->submenu,
"Radio Settings",
SubmenuIndexExtSettings,
subghz_scene_start_submenu_callback,
subghz);
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
submenu_add_item(
subghz->submenu, "Test", SubmenuIndexTest, subghz_scene_start_submenu_callback, subghz);
@@ -70,17 +72,7 @@ bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) {
view_dispatcher_stop(subghz->view_dispatcher);
return true;
} else if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubmenuIndexExtSettings) {
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexExtSettings);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneExtModuleSettings);
return true;
} else if(!furi_hal_subghz_check_radio()) {
furi_string_set(subghz->error_str, "Please connect\nexternal radio");
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowErrorSub);
return true;
} else if(event.event == SubmenuIndexReadRAW) {
if(event.event == SubmenuIndexReadRAW) {
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexReadRAW);
subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
@@ -107,6 +99,7 @@ bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) {
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneFrequencyAnalyzer);
DOLPHIN_DEED(DolphinDeedSubGhzFrequencyAnalyzer);
return true;
} else if(event.event == SubmenuIndexTest) {
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexTest);

View File

@@ -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
@@ -247,11 +236,20 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) {
subghz->last_settings = subghz_last_settings_alloc();
subghz_last_settings_load(subghz->last_settings, 0);
#if FURI_DEBUG
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
FURI_LOG_D(
TAG,
"last frequency: %ld, preset: %ld, detect_raw: %d",
subghz->last_settings->frequency,
subghz->last_settings->preset,
subghz->last_settings->detect_raw);
#else
FURI_LOG_D(
TAG,
"last frequency: %ld, preset: %ld",
subghz->last_settings->frequency,
subghz->last_settings->preset);
#endif
#endif
subghz_setting_set_default_frequency(subghz->setting, subghz->last_settings->frequency);
}
@@ -270,7 +268,6 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) {
subghz->txrx->hopper_state = SubGhzHopperStateOFF;
subghz->txrx->speaker_state = SubGhzSpeakerStateDisable;
subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
subghz->txrx->debug_pin_state = false;
if(!alloc_for_tx_only) {
subghz->txrx->history = subghz_history_alloc();
}
@@ -284,15 +281,16 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) {
subghz->txrx->environment = subghz_environment_alloc();
subghz_environment_set_came_atomo_rainbow_table_file_name(
subghz->txrx->environment, EXT_PATH("subghz/assets/came_atomo"));
subghz_environment_set_alutech_at_4n_rainbow_table_file_name(
subghz->txrx->environment, EXT_PATH("subghz/assets/alutech_at_4n"));
subghz_environment_set_nice_flor_s_rainbow_table_file_name(
subghz->txrx->environment, EXT_PATH("subghz/assets/nice_flor_s"));
subghz_environment_set_protocol_registry(
subghz->txrx->environment, (void*)&subghz_protocol_registry);
subghz->txrx->receiver = subghz_receiver_alloc_init(subghz->txrx->environment);
subghz->txrx->filter = SubGhzProtocolFlag_Decodable;
subghz_receiver_set_filter(subghz->txrx->receiver, subghz->txrx->filter);
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
subghz_last_settings_set_detect_raw_values(subghz);
#else
subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable);
#endif
subghz_worker_set_overrun_callback(
subghz->txrx->worker, (SubGhzWorkerOverrunCallback)subghz_receiver_reset);
@@ -316,8 +314,6 @@ void subghz_free(SubGhz* subghz, bool alloc_for_tx_only) {
subghz->rpc_ctx = NULL;
}
subghz_speaker_off(subghz);
#if FURI_DEBUG
// Packet Test
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdTestPacket);

View File

@@ -42,9 +42,8 @@ void subghz_cli_command_tx_carrier(Cli* cli, FuriString* args, void* context) {
furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async);
frequency = furi_hal_subghz_set_frequency_and_path(frequency);
furi_hal_gpio_init(
furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, true);
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
furi_hal_gpio_write(&gpio_cc1101_g0, true);
furi_hal_power_suppress_charge_enter();
@@ -253,8 +252,6 @@ void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) {
subghz_environment_load_keystore(environment, EXT_PATH("subghz/assets/keeloq_mfcodes_user"));
subghz_environment_set_came_atomo_rainbow_table_file_name(
environment, EXT_PATH("subghz/assets/came_atomo"));
subghz_environment_set_alutech_at_4n_rainbow_table_file_name(
environment, EXT_PATH("subghz/assets/alutech_at_4n"));
subghz_environment_set_nice_flor_s_rainbow_table_file_name(
environment, EXT_PATH("subghz/assets/nice_flor_s"));
subghz_environment_set_protocol_registry(environment, (void*)&subghz_protocol_registry);
@@ -267,7 +264,7 @@ void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) {
furi_hal_subghz_reset();
furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async);
frequency = furi_hal_subghz_set_frequency_and_path(frequency);
furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow);
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
furi_hal_power_suppress_charge_enter();
@@ -307,81 +304,6 @@ void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) {
free(instance);
}
void subghz_cli_command_rx_raw(Cli* cli, FuriString* args, void* context) {
UNUSED(context);
uint32_t frequency = 433920000;
if(furi_string_size(args)) {
int ret = sscanf(furi_string_get_cstr(args), "%lu", &frequency);
if(ret != 1) {
printf("sscanf returned %d, frequency: %lu\r\n", ret, frequency);
cli_print_usage("subghz rx", "<Frequency: in Hz>", furi_string_get_cstr(args));
return;
}
if(!furi_hal_subghz_is_frequency_valid(frequency)) {
printf(
"Frequency must be in " SUBGHZ_FREQUENCY_RANGE_STR " range, not %lu\r\n",
frequency);
return;
}
}
// Allocate context and buffers
SubGhzCliCommandRx* instance = malloc(sizeof(SubGhzCliCommandRx));
instance->stream =
furi_stream_buffer_alloc(sizeof(LevelDuration) * 1024, sizeof(LevelDuration));
furi_check(instance->stream);
// Configure radio
furi_hal_subghz_reset();
furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok270Async);
frequency = furi_hal_subghz_set_frequency_and_path(frequency);
furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow);
furi_hal_power_suppress_charge_enter();
// Prepare and start RX
furi_hal_subghz_start_async_rx(subghz_cli_command_rx_capture_callback, instance);
// Wait for packets to arrive
printf("Listening at %lu. Press CTRL+C to stop\r\n", frequency);
LevelDuration level_duration;
size_t counter = 0;
while(!cli_cmd_interrupt_received(cli)) {
int ret = furi_stream_buffer_receive(
instance->stream, &level_duration, sizeof(LevelDuration), 10);
if(ret == 0) {
continue;
}
if(ret != sizeof(LevelDuration)) {
puts("stream corrupt");
break;
}
if(level_duration_is_reset(level_duration)) {
puts(". ");
} else {
bool level = level_duration_get_level(level_duration);
uint32_t duration = level_duration_get_duration(level_duration);
printf("%c%lu ", level ? '+' : '-', duration);
}
furi_thread_stdout_flush();
counter++;
if(counter > 255) {
puts("\r\n");
counter = 0;
}
}
// Shutdown radio
furi_hal_subghz_stop_async_rx();
furi_hal_subghz_sleep();
furi_hal_power_suppress_charge_exit();
// Cleanup
furi_stream_buffer_free(instance->stream);
free(instance);
}
void subghz_cli_command_decode_raw(Cli* cli, FuriString* args, void* context) {
UNUSED(context);
FuriString* file_name;
@@ -450,8 +372,6 @@ void subghz_cli_command_decode_raw(Cli* cli, FuriString* args, void* context) {
}
subghz_environment_set_came_atomo_rainbow_table_file_name(
environment, EXT_PATH("subghz/assets/came_atomo"));
subghz_environment_set_alutech_at_4n_rainbow_table_file_name(
environment, EXT_PATH("subghz/assets/alutech_at_4n"));
subghz_environment_set_nice_flor_s_rainbow_table_file_name(
environment, EXT_PATH("subghz/assets/nice_flor_s"));
subghz_environment_set_protocol_registry(environment, (void*)&subghz_protocol_registry);
@@ -506,8 +426,7 @@ static void subghz_cli_command_print_usage() {
printf("\tchat <frequency:in Hz>\t - Chat with other Flippers\r\n");
printf(
"\ttx <3 byte Key: in hex> <frequency: in Hz> <te: us> <repeat: count>\t - Transmitting key\r\n");
printf("\trx <frequency:in Hz>\t - Receive\r\n");
printf("\trx_raw <frequency:in Hz>\t - Receive RAW\r\n");
printf("\trx <frequency:in Hz>\t - Reception key\r\n");
printf("\tdecode_raw <file_name: path_RAW_file>\t - Testing\r\n");
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
@@ -809,11 +728,6 @@ static void subghz_cli_command(Cli* cli, FuriString* args, void* context) {
break;
}
if(furi_string_cmp_str(cmd, "rx_raw") == 0) {
subghz_cli_command_rx_raw(cli, args, context);
break;
}
if(furi_string_cmp_str(cmd, "decode_raw") == 0) {
subghz_cli_command_decode_raw(cli, args, context);
break;

View File

@@ -1,15 +1,33 @@
#include "subghz_history.h"
#include "subghz_history_private.h"
#include <lib/subghz/receiver.h>
#include <toolbox/path.h>
#include <flipper_format/flipper_format_i.h>
#include "flipper_format_stream_i.h"
#include <inttypes.h>
#include <furi.h>
#define SUBGHZ_HISTORY_MAX 60
/**
* @brief Settings for temporary files
*
*/
#define SUBGHZ_HISTORY_TMP_DIR EXT_PATH("subghz/tmp_history")
#define SUBGHZ_HISTORY_TMP_EXTENSION ".tmp"
#define SUBGHZ_HISTORY_TMP_SIGNAL_MAX 700
#define SUBGHZ_HISTORY_TMP_SIGNAL_MIN 100
#define SUBGHZ_HISTORY_TMP_REMOVE_FILES true
#define SUBGHZ_HISTORY_TMP_RAW_KEY "RAW_Data"
#define MAX_LINE 500
const size_t buffer_size = 32;
#define SUBGHZ_HISTORY_MAX 55
#define SUBGHZ_HISTORY_FREE_HEAP 20480
#define TAG "SubGhzHistory"
typedef struct {
FuriString* item_str;
FlipperFormat* flipper_string;
FuriString* protocol_name;
bool is_file;
uint8_t type;
SubGhzRadioPreset* preset;
} SubGhzHistoryItem;
@@ -27,30 +45,146 @@ struct SubGhzHistory {
uint16_t last_index_write;
uint8_t code_last_hash_data;
FuriString* tmp_string;
bool write_tmp_files;
bool is_hopper_running;
Storage* storage;
SubGhzHistoryStruct* history;
};
#ifdef FURI_DEBUG
#define LOG_DELAY 0
#endif
FuriString* subghz_history_generate_temp_filename(uint32_t index) {
FuriHalRtcDateTime datetime = {0};
furi_hal_rtc_get_datetime(&datetime);
return furi_string_alloc_printf("%03ld%s", index, SUBGHZ_HISTORY_TMP_EXTENSION);
}
bool subghz_history_is_tmp_dir_exists(SubGhzHistory* instance) {
FileInfo file_info;
FS_Error error = storage_common_stat(instance->storage, SUBGHZ_HISTORY_TMP_DIR, &file_info);
if(error == FSE_OK) {
if(file_info.flags & FSF_DIRECTORY) {
return true;
}
}
return false;
}
bool subghz_history_check_sdcard(SubGhzHistory* instance) {
#ifdef FURI_DEBUG
FURI_LOG_I(TAG, "check_sdcard");
uint32_t start_time = furi_get_tick();
#endif
bool result = false;
// Stage 0 - check SD Card
FS_Error status = storage_sd_status(instance->storage);
if(status == FSE_OK) {
result = subghz_history_is_tmp_dir_exists(instance);
if(!subghz_history_is_tmp_dir_exists(instance)) {
result = storage_simply_mkdir(instance->storage, SUBGHZ_HISTORY_TMP_DIR);
}
} else {
FURI_LOG_W(TAG, "SD storage not installed! Status: %d", status);
}
#ifdef FURI_DEBUG
FURI_LOG_I(TAG, "Running time (check_sdcard): %ld ms", furi_get_tick() - start_time);
#endif
return result;
}
void subghz_history_clear_tmp_dir(SubGhzHistory* instance) {
furi_assert(instance);
#ifdef FURI_DEBUG
FURI_LOG_I(TAG, "clear_tmp_dir");
#endif
if(!instance->write_tmp_files) {
// Nothing to do here!
return;
}
//uint32_t start_time = furi_get_tick();
#ifdef SUBGHZ_HISTORY_TMP_REMOVE_FILES
// Stage 0 - Dir exists?
bool res = subghz_history_is_tmp_dir_exists(instance);
if(res) {
// Stage 1 - delete all content if exists
FileInfo fileinfo;
storage_common_stat(instance->storage, SUBGHZ_HISTORY_TMP_DIR, &fileinfo);
res = fileinfo.flags & FSF_DIRECTORY ?
storage_simply_remove_recursive(instance->storage, SUBGHZ_HISTORY_TMP_DIR) :
(storage_common_remove(instance->storage, SUBGHZ_HISTORY_TMP_DIR) == FSE_OK);
}
// Stage 2 - create dir if necessary
res = storage_simply_mkdir(instance->storage, SUBGHZ_HISTORY_TMP_DIR);
if(!res) {
FURI_LOG_E(TAG, "Cannot process temp dir!");
}
#endif
/* uint32_t stop_time = furi_get_tick() - start_time;
FURI_LOG_I(TAG, "Running time (clear_tmp_dir): %d ms", stop_time);*/
}
SubGhzHistory* subghz_history_alloc(void) {
SubGhzHistory* instance = malloc(sizeof(SubGhzHistory));
instance->tmp_string = furi_string_alloc();
instance->history = malloc(sizeof(SubGhzHistoryStruct));
SubGhzHistoryItemArray_init(instance->history->data);
instance->storage = furi_record_open(RECORD_STORAGE);
instance->write_tmp_files = subghz_history_check_sdcard(instance);
instance->is_hopper_running = false;
if(!instance->write_tmp_files) {
FURI_LOG_E(TAG, "Unstable work! Cannot use SD Card!");
}
return instance;
}
void subghz_history_item_free(void* current_item) {
furi_assert(current_item);
SubGhzHistoryItem* item = (SubGhzHistoryItem*)current_item;
furi_string_free(item->item_str);
furi_string_free(item->preset->name);
furi_string_free(item->protocol_name);
free(item->preset);
item->type = 0;
item->is_file = false;
if(item->flipper_string != NULL) {
flipper_format_free(item->flipper_string);
}
}
void subghz_history_clean_item_array(SubGhzHistory* instance) {
for
M_EACH(item, instance->history->data, SubGhzHistoryItemArray_t) {
subghz_history_item_free(item);
}
}
void subghz_history_free(SubGhzHistory* instance) {
furi_assert(instance);
furi_string_free(instance->tmp_string);
for
M_EACH(item, instance->history->data, SubGhzHistoryItemArray_t) {
furi_string_free(item->item_str);
furi_string_free(item->preset->name);
free(item->preset);
flipper_format_free(item->flipper_string);
item->type = 0;
}
subghz_history_clean_item_array(instance);
SubGhzHistoryItemArray_clear(instance->history->data);
free(instance->history);
// Delete all temporary file, on exit it's ok
subghz_history_clear_tmp_dir(instance);
furi_record_close(RECORD_STORAGE);
free(instance);
}
@@ -75,19 +209,20 @@ const char* subghz_history_get_preset(SubGhzHistory* instance, uint16_t idx) {
void subghz_history_reset(SubGhzHistory* instance) {
furi_assert(instance);
furi_string_reset(instance->tmp_string);
for
M_EACH(item, instance->history->data, SubGhzHistoryItemArray_t) {
furi_string_free(item->item_str);
furi_string_free(item->preset->name);
free(item->preset);
flipper_format_free(item->flipper_string);
item->type = 0;
}
subghz_history_clean_item_array(instance);
SubGhzHistoryItemArray_reset(instance->history->data);
instance->last_index_write = 0;
instance->code_last_hash_data = 0;
}
void subghz_history_set_hopper_state(SubGhzHistory* instance, bool hopper_state) {
furi_assert(instance);
instance->is_hopper_running = hopper_state;
}
uint16_t subghz_history_get_item(SubGhzHistory* instance) {
furi_assert(instance);
return instance->last_index_write;
@@ -102,12 +237,8 @@ uint8_t subghz_history_get_type_protocol(SubGhzHistory* instance, uint16_t idx)
const char* subghz_history_get_protocol_name(SubGhzHistory* instance, uint16_t idx) {
furi_assert(instance);
SubGhzHistoryItem* item = SubGhzHistoryItemArray_get(instance->history->data, idx);
flipper_format_rewind(item->flipper_string);
if(!flipper_format_read_string(item->flipper_string, "Protocol", instance->tmp_string)) {
FURI_LOG_E(TAG, "Missing Protocol");
furi_string_reset(instance->tmp_string);
}
return furi_string_get_cstr(instance->tmp_string);
return furi_string_get_cstr(item->protocol_name);
}
FlipperFormat* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx) {
@@ -116,27 +247,72 @@ FlipperFormat* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx
if(item->flipper_string) {
return item->flipper_string;
} else {
return NULL;
bool result_ok = false;
if(instance->write_tmp_files && item->is_file) {
// We have files!
FuriString* filename = subghz_history_generate_temp_filename(idx);
FuriString* dir_path;
dir_path = furi_string_alloc_printf(
"%s/%s", SUBGHZ_HISTORY_TMP_DIR, furi_string_get_cstr(filename));
if(storage_file_exists(instance->storage, furi_string_get_cstr(dir_path))) {
#ifdef FURI_DEBUG
FURI_LOG_D(TAG, "Exist: %s", furi_string_get_cstr(dir_path));
furi_delay_ms(LOG_DELAY);
#endif
// Set to current anyway it has NULL value
item->flipper_string = flipper_format_string_alloc();
Stream* dst_stream = flipper_format_get_raw_stream(item->flipper_string);
stream_clean(dst_stream);
size_t size = stream_load_from_file(
dst_stream, instance->storage, furi_string_get_cstr(dir_path));
if(size > 0) {
#ifdef FURI_DEBUG
FURI_LOG_I(TAG, "Save ok!");
furi_delay_ms(LOG_DELAY);
#endif
// We changed contents of file, so we no needed to load
// content from disk for the next time
item->is_file = false;
result_ok = true;
} else {
FURI_LOG_E(TAG, "Stream copy failed!");
flipper_format_free(item->flipper_string);
}
} else {
FURI_LOG_E(TAG, "Can't convert filename to file");
}
furi_string_free(filename);
furi_string_free(dir_path);
} else {
#ifdef FURI_DEBUG
FURI_LOG_W(TAG, "Write TMP files failed!");
furi_delay_ms(LOG_DELAY);
#endif
}
return result_ok ? item->flipper_string : NULL;
}
}
bool subghz_history_get_text_space_left(SubGhzHistory* instance, FuriString* output) {
furi_assert(instance);
if(memmgr_get_free_heap() < SUBGHZ_HISTORY_FREE_HEAP) {
if(output != NULL) furi_string_printf(output, " Free heap LOW");
return true;
}
if(instance->last_index_write == SUBGHZ_HISTORY_MAX) {
if(output != NULL) furi_string_printf(output, " Memory is FULL");
if(output != NULL) furi_string_printf(output, "Memory is FULL");
return true;
}
if(output != NULL)
if(output != NULL) {
furi_string_printf(output, "%02u/%02u", instance->last_index_write, SUBGHZ_HISTORY_MAX);
}
return false;
}
uint16_t subghz_history_get_last_index(SubGhzHistory* instance) {
return instance->last_index_write;
}
void subghz_history_get_text_item_menu(SubGhzHistory* instance, FuriString* output, uint16_t idx) {
SubGhzHistoryItem* item = SubGhzHistoryItemArray_get(instance->history->data, idx);
furi_string_set(output, item->item_str);
@@ -149,8 +325,9 @@ bool subghz_history_add_to_history(
furi_assert(instance);
furi_assert(context);
if(memmgr_get_free_heap() < SUBGHZ_HISTORY_FREE_HEAP) return false;
if(instance->last_index_write >= SUBGHZ_HISTORY_MAX) return false;
if(instance->last_index_write >= SUBGHZ_HISTORY_MAX) {
return false;
}
SubGhzProtocolDecoderBase* decoder_base = context;
if((instance->code_last_hash_data ==
@@ -162,7 +339,6 @@ bool subghz_history_add_to_history(
instance->code_last_hash_data = subghz_protocol_decoder_base_get_hash_data(decoder_base);
instance->last_update_timestamp = furi_get_tick();
FuriString* text;
text = furi_string_alloc();
SubGhzHistoryItem* item = SubGhzHistoryItemArray_push_raw(instance->history->data);
@@ -175,6 +351,11 @@ bool subghz_history_add_to_history(
item->preset->data_size = preset->data_size;
item->item_str = furi_string_alloc();
item->protocol_name = furi_string_alloc();
bool tmp_file_for_raw = false;
// At this point file mapped to memory otherwise file cannot decode
item->flipper_string = flipper_format_string_alloc();
subghz_protocol_decoder_base_serialize(decoder_base, item->flipper_string, preset);
@@ -186,8 +367,30 @@ bool subghz_history_add_to_history(
if(!flipper_format_read_string(item->flipper_string, "Protocol", instance->tmp_string)) {
FURI_LOG_E(TAG, "Missing Protocol");
break;
} else {
furi_string_printf(
item->protocol_name, "%s", furi_string_get_cstr(instance->tmp_string));
}
if(!strcmp(furi_string_get_cstr(instance->tmp_string), "KeeLoq")) {
if(!strcmp(furi_string_get_cstr(instance->tmp_string), "RAW")) {
// Check if hopper enabled we need to add little delay
if(instance->is_hopper_running) {
furi_delay_ms(40);
}
// Enable writing temp files to micro sd
tmp_file_for_raw = true;
// Write display name
furi_string_printf(
item->item_str,
"RAW %03ld.%02ld",
preset->frequency / 1000000 % 1000,
preset->frequency / 10000 % 100);
// Rewind
if(!flipper_format_rewind(item->flipper_string)) {
FURI_LOG_E(TAG, "Rewind error");
}
break;
} else if(!strcmp(furi_string_get_cstr(instance->tmp_string), "KeeLoq")) {
furi_string_set(instance->tmp_string, "KL ");
if(!flipper_format_read_string(item->flipper_string, "Manufacture", text)) {
FURI_LOG_E(TAG, "Missing Protocol");
@@ -208,34 +411,485 @@ bool subghz_history_add_to_history(
}
uint8_t key_data[sizeof(uint64_t)] = {0};
if(!flipper_format_read_hex(item->flipper_string, "Key", key_data, sizeof(uint64_t))) {
FURI_LOG_D(TAG, "No Key");
FURI_LOG_E(TAG, "Missing Key");
break;
}
uint64_t data = 0;
for(uint8_t i = 0; i < sizeof(uint64_t); i++) {
data = (data << 8) | key_data[i];
}
if(data != 0) {
if(!(uint32_t)(data >> 32)) {
furi_string_printf(
item->item_str,
"%s %lX",
furi_string_get_cstr(instance->tmp_string),
(uint32_t)(data & 0xFFFFFFFF));
} else {
furi_string_printf(
item->item_str,
"%s %lX%08lX",
furi_string_get_cstr(instance->tmp_string),
(uint32_t)(data >> 32),
(uint32_t)(data & 0xFFFFFFFF));
}
} else {
furi_string_printf(item->item_str, "%s", furi_string_get_cstr(instance->tmp_string));
}
if(!(uint32_t)(data >> 32)) {
furi_string_printf(
item->item_str,
"%s %lX",
furi_string_get_cstr(instance->tmp_string),
(uint32_t)(data & 0xFFFFFFFF));
} else {
furi_string_printf(
item->item_str,
"%s %lX%08lX",
furi_string_get_cstr(instance->tmp_string),
(uint32_t)(data >> 32),
(uint32_t)(data & 0xFFFFFFFF));
}
} while(false);
// If we can write to files
if(instance->write_tmp_files && tmp_file_for_raw) {
FuriString* filename = subghz_history_generate_temp_filename(instance->last_index_write);
FuriString* dir_path;
dir_path = furi_string_alloc();
furi_string_cat_printf(
dir_path, "%s/%s", SUBGHZ_HISTORY_TMP_DIR, furi_string_get_cstr(filename));
#ifdef FURI_DEBUG
FURI_LOG_I(TAG, "Save temp file: %s", furi_string_get_cstr(dir_path));
#endif
if(!subghz_history_tmp_write_file_split(instance, item, furi_string_get_cstr(dir_path))) {
// Plan B!
subghz_history_tmp_write_file_full(instance, item, dir_path);
}
if(item->is_file) {
flipper_format_free(item->flipper_string);
item->flipper_string = NULL;
}
furi_string_free(filename);
furi_string_free(dir_path);
} else {
#ifdef FURI_DEBUG
FURI_LOG_I(TAG, "Old fashion way");
#endif
}
furi_string_free(text);
instance->last_index_write++;
return true;
}
static inline bool is_space_playground(char c) {
return c == ' ' || c == '\t' || c == flipper_format_eolr;
}
bool subghz_history_stream_read_valid_key(Stream* stream, FuriString* key) {
furi_string_reset(key);
uint8_t buffer[buffer_size];
bool found = false;
bool error = false;
bool accumulate = true;
bool new_line = true;
while(true) {
size_t was_read = stream_read(stream, buffer, buffer_size);
if(was_read == 0) break;
for(size_t i = 0; i < was_read; i++) {
uint8_t data = buffer[i];
if(data == flipper_format_eoln) {
// EOL found, clean data, start accumulating data and set the new_line flag
furi_string_reset(key);
accumulate = true;
new_line = true;
} else if(data == flipper_format_eolr) {
// ignore
} else if(data == flipper_format_comment && new_line) {
// if there is a comment character and we are at the beginning of a new line
// do not accumulate comment data and reset the new_line flag
accumulate = false;
new_line = false;
} else if(data == flipper_format_delimiter) {
if(new_line) {
// we are on a "new line" and found the delimiter
// this can only be if we have previously found some kind of key, so
// clear the data, set the flag that we no longer want to accumulate data
// and reset the new_line flag
furi_string_reset(key);
accumulate = false;
new_line = false;
} else {
// parse the delimiter only if we are accumulating data
if(accumulate) {
// we found the delimiter, move the rw pointer to the delimiter location
// and signal that we have found something
if(!stream_seek(stream, i - was_read, StreamOffsetFromCurrent)) {
error = true;
break;
}
found = true;
break;
}
}
} else {
// just new symbol, reset the new_line flag
new_line = false;
if(accumulate) {
// and accumulate data if we want
furi_string_push_back(key, data);
}
}
}
if(found || error) break;
}
return found;
}
bool subghz_history_stream_seek_to_key(Stream* stream, const char* key, bool strict_mode) {
bool found = false;
FuriString* read_key;
read_key = furi_string_alloc();
while(!stream_eof(stream)) {
if(subghz_history_stream_read_valid_key(stream, read_key)) {
if(furi_string_cmp_str(read_key, key) == 0) {
if(!stream_seek(stream, 2, StreamOffsetFromCurrent)) {
break;
}
found = true;
break;
} else if(strict_mode) {
found = false;
break;
}
}
}
furi_string_free(read_key);
return found;
}
bool subghz_history_stream_read_value(Stream* stream, FuriString* value, bool* last) {
enum { LeadingSpace, ReadValue, TrailingSpace } state = LeadingSpace;
const size_t buffer_size = 32;
uint8_t buffer[buffer_size];
bool result = false;
bool error = false;
furi_string_reset(value);
while(true) {
size_t was_read = stream_read(stream, buffer, buffer_size);
if(was_read == 0) {
if(state != LeadingSpace && stream_eof(stream)) {
result = true;
*last = true;
} else {
error = true;
}
}
for(uint16_t i = 0; i < was_read; i++) {
const uint8_t data = buffer[i];
if(state == LeadingSpace) {
if(is_space_playground(data)) {
continue;
} else if(data == flipper_format_eoln) {
stream_seek(stream, i - was_read, StreamOffsetFromCurrent);
error = true;
break;
} else {
state = ReadValue;
furi_string_push_back(value, data);
}
} else if(state == ReadValue) {
if(is_space_playground(data)) {
state = TrailingSpace;
} else if(data == flipper_format_eoln) {
if(!stream_seek(stream, i - was_read, StreamOffsetFromCurrent)) {
error = true;
} else {
result = true;
*last = true;
}
break;
} else {
furi_string_push_back(value, data);
}
} else if(state == TrailingSpace) {
if(is_space_playground(data)) {
continue;
} else if(!stream_seek(stream, i - was_read, StreamOffsetFromCurrent)) {
error = true;
} else {
*last = (data == flipper_format_eoln);
result = true;
}
break;
}
}
if(error || result) break;
}
return result;
}
bool subghz_history_read_int32(Stream* stream, int32_t* _data, const uint16_t data_size) {
bool result = false;
result = true;
FuriString* value;
value = furi_string_alloc();
for(size_t i = 0; i < data_size; i++) {
bool last = false;
result = subghz_history_stream_read_value(stream, value, &last);
if(result) {
int scan_values = 0;
int32_t* data = _data;
scan_values = sscanf(furi_string_get_cstr(value), "%" PRIi32, &data[i]);
if(scan_values != 1) {
result = false;
break;
}
} else {
break;
}
if(last && ((i + 1) != data_size)) {
result = false;
break;
}
}
furi_string_free(value);
return result;
}
uint32_t subghz_history_rand_range(uint32_t min, uint32_t max) {
// size of range, inclusive
const uint32_t length_of_range = max - min + 1;
// add n so that we don't return a number below our range
return (uint32_t)(rand() % length_of_range + min);
}
bool subghz_history_write_file_noise(
Stream* file,
bool is_negative_start,
size_t current_position,
bool empty_line) {
size_t was_write = 0;
if(empty_line) {
was_write = stream_write_format(file, "%s: ", SUBGHZ_HISTORY_TMP_RAW_KEY);
if(was_write <= 0) {
FURI_LOG_E(TAG, "Can't write key!");
return false;
}
}
int8_t first;
int8_t second;
if(is_negative_start) {
first = -1;
second = 1;
} else {
first = 1;
second = -1;
}
while(current_position < MAX_LINE) {
was_write = stream_write_format(
file,
"%ld %ld ",
subghz_history_rand_range(
SUBGHZ_HISTORY_TMP_SIGNAL_MIN, SUBGHZ_HISTORY_TMP_SIGNAL_MAX) *
first,
subghz_history_rand_range(
SUBGHZ_HISTORY_TMP_SIGNAL_MIN, SUBGHZ_HISTORY_TMP_SIGNAL_MAX) *
second);
if(was_write <= 0) {
FURI_LOG_E(TAG, "Can't write random values!");
return false;
}
current_position += was_write;
}
// Step back to write \n instead of space
size_t offset = stream_tell(file);
if(stream_seek(file, offset - 1, StreamOffsetFromCurrent)) {
FURI_LOG_E(TAG, "Step back failed!");
return false;
}
return stream_write_char(file, flipper_format_eoln) > 0;
}
bool subghz_history_write_file_data(
Stream* src,
Stream* file,
bool* is_negative_start,
size_t* current_position) {
size_t offset_file = 0;
bool result = false;
int32_t value = 0;
do {
if(!subghz_history_read_int32(src, &value, 1)) {
result = true;
break;
}
offset_file = stream_tell(file);
stream_write_format(file, "%ld ", value);
*current_position += stream_tell(file) - offset_file;
if(*current_position > MAX_LINE) {
if((is_negative_start && value > 0) || (!is_negative_start && value < 0)) {
// Align values
continue;
}
if(stream_write_format(file, "\n%s: ", SUBGHZ_HISTORY_TMP_RAW_KEY) == 0) {
FURI_LOG_E(TAG, "Can't write new line!");
result = false;
break;
}
*current_position = 0;
}
} while(true);
*is_negative_start = value < 0;
return result;
}
bool subghz_history_tmp_write_file_split(
SubGhzHistory* instance,
void* current_item,
const char* dir_path) {
furi_assert(instance);
furi_assert(current_item);
furi_assert(dir_path);
#ifdef FURI_DEBUG
FURI_LOG_I(TAG, "Save temp file splitted: %s", dir_path);
#endif
SubGhzHistoryItem* item = (SubGhzHistoryItem*)current_item;
uint8_t buffer[buffer_size];
Stream* src = flipper_format_get_raw_stream(item->flipper_string);
stream_rewind(src);
FlipperFormat* flipper_format_file = flipper_format_file_alloc(instance->storage);
bool result = false;
FuriString* temp_str = furi_string_alloc();
do {
if(storage_file_exists(instance->storage, dir_path) &&
storage_common_remove(instance->storage, dir_path) != FSE_OK) {
FURI_LOG_E(TAG, "Can't delete old file!");
break;
}
path_extract_dirname(dir_path, temp_str);
FS_Error fs_result =
storage_common_mkdir(instance->storage, furi_string_get_cstr(temp_str));
if(fs_result != FSE_OK && fs_result != FSE_EXIST) {
FURI_LOG_E(TAG, "Can't create dir!");
break;
}
result = flipper_format_file_open_always(flipper_format_file, dir_path);
if(!result) {
FURI_LOG_E(TAG, "Can't open file for write!");
break;
}
Stream* file = flipper_format_get_raw_stream(flipper_format_file);
if(!subghz_history_stream_seek_to_key(src, SUBGHZ_HISTORY_TMP_RAW_KEY, false)) {
FURI_LOG_E(TAG, "Can't find key!");
break;
}
bool is_negative_start = false;
bool found = false;
size_t offset_start;
offset_start = stream_tell(src);
// Check for negative value at the start and end to align file by correct values
size_t was_read = stream_read(src, buffer, 1);
if(was_read <= 0) {
FURI_LOG_E(TAG, "Can't obtain first mark!");
break;
}
is_negative_start = buffer[0] == '-';
// Ready to write stream to file
size_t current_position;
stream_rewind(src);
current_position = stream_copy(src, file, offset_start);
if(current_position != offset_start) {
FURI_LOG_E(TAG, "Invalid copy header data from one stream to another!");
break;
}
found = true;
current_position = 0;
if(!subghz_history_write_file_noise(file, is_negative_start, current_position, false)) {
FURI_LOG_E(TAG, "Add start noise failed!");
break;
}
if(stream_write_format(file, "%s: ", SUBGHZ_HISTORY_TMP_RAW_KEY) == 0) {
FURI_LOG_E(TAG, "Can't write new line!");
result = false;
break;
}
if(!subghz_history_write_file_data(src, file, &is_negative_start, &current_position)) {
FURI_LOG_E(TAG, "Split by lines failed!");
break;
}
if(!subghz_history_write_file_noise(file, is_negative_start, current_position, false)) {
FURI_LOG_E(TAG, "Add end noise failed!");
break;
}
if(!subghz_history_write_file_noise(file, is_negative_start, 0, true)) {
FURI_LOG_E(TAG, "Add end noise failed!");
break;
}
result = found;
} while(false);
flipper_format_file_close(flipper_format_file);
flipper_format_free(flipper_format_file);
furi_string_free(temp_str);
item->is_file = result;
return result;
}
void subghz_history_tmp_write_file_full(
SubGhzHistory* instance,
void* current_item,
FuriString* dir_path) {
SubGhzHistoryItem* item = (SubGhzHistoryItem*)current_item;
#ifdef FURI_DEBUG
FURI_LOG_W(TAG, "Save temp file full: %s", furi_string_get_cstr(dir_path));
#endif
Stream* dst = flipper_format_get_raw_stream(item->flipper_string);
stream_rewind(dst);
if(stream_save_to_file(
dst, instance->storage, furi_string_get_cstr(dir_path), FSOM_CREATE_ALWAYS) > 0) {
#ifdef FURI_DEBUG
FURI_LOG_I(TAG, "Save done!");
#endif
// This item contains fake data to load from SD
item->is_file = true;
} else {
FURI_LOG_E(TAG, "Stream copy failed!");
}
}

View File

@@ -110,3 +110,10 @@ bool subghz_history_add_to_history(
* @return SubGhzProtocolCommonLoad*
*/
FlipperFormat* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx);
/** Set hopper state for internal usage in history
*
* @param instance - SubGhzHistory instance
* @param hopper_state - bool is hopper running?
*/
void subghz_history_set_hopper_state(SubGhzHistory* instance, bool hopper_state);

View File

@@ -69,7 +69,7 @@ void subghz_begin(SubGhz* subghz, uint8_t* preset_data) {
furi_hal_subghz_reset();
furi_hal_subghz_idle();
furi_hal_subghz_load_custom_preset(preset_data);
furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow);
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
subghz->txrx->txrx_state = SubGhzTxRxStateIDLE;
}
@@ -84,7 +84,7 @@ uint32_t subghz_rx(SubGhz* subghz, uint32_t frequency) {
furi_hal_subghz_idle();
uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency);
furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow);
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
furi_hal_subghz_flush_rx();
subghz_speaker_on(subghz);
furi_hal_subghz_rx();
@@ -103,9 +103,8 @@ static bool subghz_tx(SubGhz* subghz, uint32_t frequency) {
furi_assert(subghz->txrx->txrx_state != SubGhzTxRxStateSleep);
furi_hal_subghz_idle();
furi_hal_subghz_set_frequency_and_path(frequency);
furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, false);
furi_hal_gpio_init(
furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
furi_hal_gpio_write(&gpio_cc1101_g0, false);
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
subghz_speaker_on(subghz);
bool ret = furi_hal_subghz_tx();
subghz->txrx->txrx_state = SubGhzTxRxStateTx;
@@ -597,15 +596,9 @@ 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);
}
if(subghz->txrx->speaker_state == SubGhzSpeakerStateEnable) {
if(furi_hal_speaker_acquire(30)) {
if(!subghz->txrx->debug_pin_state) {
furi_hal_subghz_set_async_mirror_pin(&gpio_speaker);
}
furi_hal_subghz_set_async_mirror_pin(&gpio_speaker);
} else {
subghz->txrx->speaker_state = SubGhzSpeakerStateDisable;
}
@@ -613,14 +606,9 @@ void subghz_speaker_on(SubGhz* subghz) {
}
void subghz_speaker_off(SubGhz* subghz) {
if(subghz->txrx->debug_pin_state) {
furi_hal_subghz_set_async_mirror_pin(NULL);
}
if(subghz->txrx->speaker_state != SubGhzSpeakerStateDisable) {
if(furi_hal_speaker_is_mine()) {
if(!subghz->txrx->debug_pin_state) {
furi_hal_subghz_set_async_mirror_pin(NULL);
}
furi_hal_subghz_set_async_mirror_pin(NULL);
furi_hal_speaker_release();
if(subghz->txrx->speaker_state == SubGhzSpeakerStateShutdown)
subghz->txrx->speaker_state = SubGhzSpeakerStateDisable;
@@ -629,27 +617,17 @@ void subghz_speaker_off(SubGhz* subghz) {
}
void subghz_speaker_mute(SubGhz* subghz) {
if(subghz->txrx->debug_pin_state) {
furi_hal_subghz_set_async_mirror_pin(NULL);
}
if(subghz->txrx->speaker_state == SubGhzSpeakerStateEnable) {
if(furi_hal_speaker_is_mine()) {
if(!subghz->txrx->debug_pin_state) {
furi_hal_subghz_set_async_mirror_pin(NULL);
}
furi_hal_subghz_set_async_mirror_pin(NULL);
}
}
}
void subghz_speaker_unmute(SubGhz* subghz) {
if(subghz->txrx->debug_pin_state) {
furi_hal_subghz_set_async_mirror_pin(&ibutton_gpio);
}
if(subghz->txrx->speaker_state == SubGhzSpeakerStateEnable) {
if(furi_hal_speaker_is_mine()) {
if(!subghz->txrx->debug_pin_state) {
furi_hal_subghz_set_async_mirror_pin(&gpio_speaker);
}
furi_hal_subghz_set_async_mirror_pin(&gpio_speaker);
}
}
}

View File

@@ -62,7 +62,6 @@ struct SubGhzTxRx {
SubGhzEnvironment* environment;
SubGhzReceiver* receiver;
SubGhzTransmitter* transmitter;
SubGhzProtocolFlag filter;
SubGhzProtocolDecoderBase* decoder_result;
FlipperFormat* fff_data;
SecureData* secure_data;
@@ -77,8 +76,6 @@ struct SubGhzTxRx {
uint8_t hopper_idx_frequency;
SubGhzRxKeyState rx_key_state;
bool debug_pin_state;
float raw_threshold_rssi;
uint8_t raw_threshold_rssi_low_count;
};

View File

@@ -1,5 +1,8 @@
#include "subghz_last_settings.h"
#include "subghz_i.h"
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
#include <lib/subghz/protocols/raw.h>
#endif
#define TAG "SubGhzLastSettings"
@@ -13,6 +16,11 @@
#define SUBGHZ_LAST_SETTING_FREQUENCY_ANALYZER_FEEDBACK_LEVEL 2
#define SUBGHZ_LAST_SETTING_FREQUENCY_ANALYZER_TRIGGER -93.0f
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
#define SUBGHZ_LAST_SETTING_DEFAULT_READ_RAW 0
#define SUBGHZ_LAST_SETTING_FIELD_DETECT_RAW "DetectRaw"
#endif
#define SUBGHZ_LAST_SETTING_FIELD_FREQUENCY "Frequency"
//#define SUBGHZ_LAST_SETTING_FIELD_PRESET "Preset"
#define SUBGHZ_LAST_SETTING_FIELD_FREQUENCY_ANALYZER_FEEDBACK_LEVEL "FeedbackLevel"
@@ -44,6 +52,9 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count
//int32_t temp_preset = 0;
bool frequency_analyzer_feedback_level_was_read = false;
bool frequency_analyzer_trigger_was_read = false;
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
uint32_t temp_read_raw = 0;
#endif
if(FSE_OK == storage_sd_status(storage) && SUBGHZ_LAST_SETTINGS_PATH &&
flipper_format_file_open_existing(fff_data_file, SUBGHZ_LAST_SETTINGS_PATH)) {
@@ -62,7 +73,10 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count
SUBGHZ_LAST_SETTING_FIELD_FREQUENCY_ANALYZER_TRIGGER,
(float*)&temp_frequency_analyzer_trigger,
1);
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
flipper_format_read_uint32(
fff_data_file, SUBGHZ_LAST_SETTING_FIELD_DETECT_RAW, (uint32_t*)&temp_read_raw, 1);
#endif
} else {
FURI_LOG_E(TAG, "Error open file %s", SUBGHZ_LAST_SETTINGS_PATH);
}
@@ -74,7 +88,9 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count
instance->frequency_analyzer_feedback_level =
SUBGHZ_LAST_SETTING_FREQUENCY_ANALYZER_FEEDBACK_LEVEL;
instance->frequency_analyzer_trigger = SUBGHZ_LAST_SETTING_FREQUENCY_ANALYZER_TRIGGER;
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
instance->detect_raw = SUBGHZ_LAST_SETTING_DEFAULT_READ_RAW;
#endif
} else {
instance->frequency = temp_frequency;
instance->frequency_analyzer_feedback_level =
@@ -85,6 +101,9 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count
instance->frequency_analyzer_trigger = frequency_analyzer_trigger_was_read ?
temp_frequency_analyzer_trigger :
SUBGHZ_LAST_SETTING_FREQUENCY_ANALYZER_TRIGGER;
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
instance->detect_raw = temp_read_raw;
#endif
/*if(temp_preset > (int32_t)preset_count - 1 || temp_preset < 0) {
FURI_LOG_W(TAG, "Last used preset no found");*/
@@ -145,6 +164,12 @@ bool subghz_last_settings_save(SubGhzLastSettings* instance) {
1)) {
break;
}
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
if(!flipper_format_insert_or_update_uint32(
file, SUBGHZ_LAST_SETTING_FIELD_DETECT_RAW, &instance->detect_raw, 1)) {
break;
}
#endif
saved = true;
} while(0);
@@ -158,3 +183,17 @@ bool subghz_last_settings_save(SubGhzLastSettings* instance) {
return saved;
}
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
void subghz_last_settings_set_detect_raw_values(void* context) {
furi_assert(context);
SubGhz* instance = (SubGhz*)context;
bool is_detect_raw = instance->last_settings->detect_raw > 0;
subghz_receiver_set_filter(
instance->txrx->receiver, is_detect_raw ? DETECT_RAW_TRUE : DETECT_RAW_FALSE);
subghz_protocol_decoder_raw_set_auto_mode(
subghz_receiver_search_decoder_base_by_name(
instance->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME),
is_detect_raw);
}
#endif

View File

@@ -1,12 +1,23 @@
#pragma once
// Enable saving detect raw setting state
// #define SUBGHZ_SAVE_DETECT_RAW_SETTING 1
#include <furi_hal.h>
#include <stdint.h>
#include <stdbool.h>
#include <storage/storage.h>
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
#include <lib/subghz/protocols/base.h>
#define DETECT_RAW_FALSE SubGhzProtocolFlag_Decodable
#define DETECT_RAW_TRUE SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_RAW
#endif
typedef struct {
uint32_t frequency;
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
uint32_t detect_raw;
#endif
int32_t preset;
uint32_t frequency_analyzer_feedback_level;
float frequency_analyzer_trigger;
@@ -19,3 +30,6 @@ void subghz_last_settings_free(SubGhzLastSettings* instance);
void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count);
bool subghz_last_settings_save(SubGhzLastSettings* instance);
#ifdef SUBGHZ_SAVE_DETECT_RAW_SETTING
void subghz_last_settings_set_detect_raw_values(void* context);
#endif

View File

@@ -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;
@@ -34,7 +32,7 @@ static const Icon* ReceiverItemIcons[] = {
[SubGhzProtocolTypeUnknown] = &I_Quest_7x8,
[SubGhzProtocolTypeStatic] = &I_Static_9x7,
[SubGhzProtocolTypeDynamic] = &I_Dynamic_9x7,
[SubGhzProtocolTypeBinRAW] = &I_Raw_9x7,
[SubGhzProtocolTypeRAW] = &I_Raw_9x7,
};
typedef enum {
@@ -64,7 +62,6 @@ typedef struct {
uint16_t history_item;
SubGhzViewReceiverBarShow bar_show;
SubGhzViewReceiverMode mode;
uint8_t u_rssi;
} SubGhzViewReceiverModel;
void subghz_view_receiver_set_mode(
@@ -74,21 +71,6 @@ void subghz_view_receiver_set_mode(
subghz_receiver->view, SubGhzViewReceiverModel * model, { model->mode = mode; }, true);
}
void subghz_receiver_rssi(SubGhzViewReceiver* instance, float rssi) {
furi_assert(instance);
with_view_model(
instance->view,
SubGhzViewReceiverModel * model,
{
if(rssi < SUBGHZ_RAW_TRESHOLD_MIN) {
model->u_rssi = 0;
} else {
model->u_rssi = (uint8_t)(rssi - SUBGHZ_RAW_TRESHOLD_MIN);
}
},
true);
}
void subghz_view_receiver_set_lock(SubGhzViewReceiver* subghz_receiver, SubGhzLock lock) {
furi_assert(subghz_receiver);
subghz_receiver->lock_count = 0;
@@ -207,16 +189,6 @@ static void subghz_view_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool s
canvas_draw_dot(canvas, scrollbar ? 121 : 126, (0 + idx * FRAME_HEIGHT) + 11);
}
static void subghz_view_rssi_draw(Canvas* canvas, SubGhzViewReceiverModel* 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 subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) {
canvas_clear(canvas);
canvas_set_color(canvas, ColorBlack);
@@ -224,9 +196,8 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) {
if(model->mode == SubGhzViewReceiverModeLive) {
elements_button_left(canvas, "Config");
//canvas_draw_line(canvas, 46, 51, 125, 51);
canvas_draw_line(canvas, 46, 51, 125, 51);
} else {
canvas_draw_line(canvas, 2, 52, 125, 52);
canvas_draw_str(canvas, 3, 62, furi_string_get_cstr(model->progress_str));
}
@@ -259,30 +230,19 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) {
if(model->history_item == 0) {
if(model->mode == SubGhzViewReceiverModeLive) {
canvas_draw_icon(
canvas,
0,
0,
furi_hal_subghz_get_radio_type() ? &I_Fishing_123x52 : &I_Scanning_123x52);
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);
} else {
canvas_draw_icon(
canvas,
0,
0,
furi_hal_subghz_get_radio_type() ? &I_Fishing_123x52 : &I_Scanning_123x52);
canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52);
canvas_set_font(canvas, FontPrimary);
canvas_draw_str(canvas, 63, 46, "Decoding...");
canvas_set_font(canvas, FontSecondary);
}
}
if(model->mode == SubGhzViewReceiverModeLive) {
subghz_view_rssi_draw(canvas, model);
}
switch(model->bar_show) {
case SubGhzViewReceiverBarShowLock:
canvas_draw_icon(canvas, 64, 55, &I_Lock_7x8);
@@ -290,28 +250,7 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) {
break;
case SubGhzViewReceiverBarShowToUnlockPress:
canvas_draw_str(canvas, 44, 62, furi_string_get_cstr(model->frequency_str));
#ifdef SUBGHZ_EXT_PRESET_NAME
if(model->history_item == 0 && model->mode == SubGhzViewReceiverModeLive) {
canvas_draw_str(
canvas,
44 + canvas_string_width(canvas, furi_string_get_cstr(model->frequency_str)) + 1,
62,
"MHz");
const char* str = furi_string_get_cstr(model->preset_str);
const uint8_t vertical_offset = 7;
const uint8_t horizontal_offset = 3;
const uint8_t string_width = canvas_string_width(canvas, str);
canvas_draw_str(
canvas,
canvas_width(canvas) - (string_width + horizontal_offset),
vertical_offset,
str);
} else {
canvas_draw_str(canvas, 79, 62, furi_string_get_cstr(model->preset_str));
}
#else
canvas_draw_str(canvas, 79, 62, furi_string_get_cstr(model->preset_str));
#endif
canvas_draw_str(canvas, 96, 62, furi_string_get_cstr(model->history_stat_str));
canvas_set_font(canvas, FontSecondary);
elements_bold_rounded_frame(canvas, 14, 8, 99, 48);

View File

@@ -12,8 +12,6 @@ void subghz_view_receiver_set_mode(
SubGhzViewReceiver* subghz_receiver,
SubGhzViewReceiverMode mode);
void subghz_receiver_rssi(SubGhzViewReceiver* instance, float rssi);
void subghz_view_receiver_set_lock(SubGhzViewReceiver* subghz_receiver, SubGhzLock keyboard);
void subghz_view_receiver_set_callback(

View File

@@ -165,7 +165,6 @@ void subghz_frequency_analyzer_draw(Canvas* canvas, SubGhzFrequencyAnalyzerModel
// Title
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 0, 7, furi_hal_subghz_get_radio_type() ? "Ext" : "Int");
canvas_draw_str(canvas, 20, 7, "Frequency Analyzer");
// RSSI
@@ -645,4 +644,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);
}
}

View File

@@ -30,7 +30,6 @@ typedef struct {
SubGhzReadRAWStatus status;
bool raw_send_only;
float raw_threshold_rssi;
bool not_showing_samples;
} SubGhzReadRAWModel;
void subghz_read_raw_set_callback(
@@ -93,10 +92,7 @@ void subghz_read_raw_update_sample_write(SubGhzReadRAW* instance, size_t sample)
with_view_model(
instance->view,
SubGhzReadRAWModel * model,
{
model->not_showing_samples = false;
furi_string_printf(model->sample_write, "%zu spl.", sample);
},
{ furi_string_printf(model->sample_write, "%zu spl.", sample); },
false);
}
@@ -284,15 +280,8 @@ void subghz_read_raw_draw(Canvas* canvas, SubGhzReadRAWModel* model) {
uint8_t graphics_mode = 1;
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 0, 7, furi_string_get_cstr(model->frequency_str));
canvas_draw_str(canvas, 35, 7, furi_string_get_cstr(model->preset_str));
if(model->not_showing_samples) {
canvas_draw_str(canvas, 77, 7, furi_hal_subghz_get_radio_type() ? "R: Ext" : "R: Int");
} else {
canvas_draw_str(canvas, 70, 7, furi_hal_subghz_get_radio_type() ? "E" : "I");
}
canvas_draw_str(canvas, 5, 7, furi_string_get_cstr(model->frequency_str));
canvas_draw_str(canvas, 40, 7, furi_string_get_cstr(model->preset_str));
canvas_draw_str_aligned(
canvas, 126, 0, AlignRight, AlignTop, furi_string_get_cstr(model->sample_write));
@@ -459,7 +448,6 @@ bool subghz_read_raw_input(InputEvent* event, void* context) {
model->status = SubGhzReadRAWStatusStart;
model->rssi_history_end = false;
model->ind_write = 0;
model->not_showing_samples = true;
furi_string_set(model->sample_write, "0 spl.");
furi_string_reset(model->file_name);
instance->callback(SubGhzCustomEventViewReadRAWErase, instance->context);
@@ -521,7 +509,6 @@ void subghz_read_raw_set_status(
model->status = SubGhzReadRAWStatusStart;
model->rssi_history_end = false;
model->ind_write = 0;
model->not_showing_samples = true;
furi_string_reset(model->file_name);
furi_string_set(model->sample_write, "0 spl.");
model->raw_threshold_rssi = raw_threshold_rssi;
@@ -543,7 +530,6 @@ void subghz_read_raw_set_status(
model->status = SubGhzReadRAWStatusLoadKeyIDLE;
model->rssi_history_end = false;
model->ind_write = 0;
model->not_showing_samples = true;
furi_string_set(model->file_name, file_name);
furi_string_set(model->sample_write, "RAW");
},
@@ -556,7 +542,6 @@ void subghz_read_raw_set_status(
{
model->status = SubGhzReadRAWStatusLoadKeyIDLE;
if(!model->ind_write) {
model->not_showing_samples = true;
furi_string_set(model->file_name, file_name);
furi_string_set(model->sample_write, "RAW");
} else {

View File

@@ -115,19 +115,14 @@ bool subghz_test_carrier_input(InputEvent* event, void* context) {
furi_hal_subghz_set_path(model->path);
if(model->status == SubGhzTestCarrierModelStatusRx) {
furi_hal_gpio_init(
furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow);
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
furi_hal_subghz_rx();
} else {
furi_hal_gpio_init(
furi_hal_subghz.cc1101_g0_pin,
GpioModeOutputPushPull,
GpioPullNo,
GpioSpeedLow);
furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, true);
&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
furi_hal_gpio_write(&gpio_cc1101_g0, true);
if(!furi_hal_subghz_tx()) {
furi_hal_gpio_init(
furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow);
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
subghz_test_carrier->callback(
SubGhzTestCarrierEventOnlyRx, subghz_test_carrier->context);
}
@@ -145,7 +140,7 @@ void subghz_test_carrier_enter(void* context) {
furi_hal_subghz_reset();
furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async);
furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow);
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
with_view_model(
subghz_test_carrier->view,

View File

@@ -143,9 +143,8 @@ void subghz_test_static_enter(void* context) {
furi_hal_subghz_reset();
furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async);
furi_hal_gpio_init(
furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, false);
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
furi_hal_gpio_write(&gpio_cc1101_g0, false);
instance->status_tx = SubGhzTestStaticStatusIDLE;
with_view_model(

View File

@@ -84,15 +84,10 @@ void subghz_view_transmitter_draw(Canvas* canvas, SubGhzViewTransmitterModel* mo
canvas_clear(canvas);
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontSecondary);
elements_multiline_text_aligned(
canvas, 0, 0, AlignLeft, AlignTop, furi_string_get_cstr(model->key_str));
elements_multiline_text(canvas, 0, 7, furi_string_get_cstr(model->key_str));
canvas_draw_str(canvas, 78, 7, furi_string_get_cstr(model->frequency_str));
canvas_draw_str(canvas, 113, 7, furi_string_get_cstr(model->preset_str));
if(model->show_button) {
canvas_draw_str(canvas, 58, 62, furi_hal_subghz_get_radio_type() ? "R: Ext" : "R: Int");
subghz_view_transmitter_button_right(canvas, "Send");
}
if(model->show_button) subghz_view_transmitter_button_right(canvas, "Send");
}
bool subghz_view_transmitter_input(InputEvent* event, void* context) {

View File

@@ -1,7 +1,7 @@
#include "../u2f_app_i.h"
#include "../views/u2f_view.h"
#include <dolphin/dolphin.h>
#include <furi_hal.h>
#include "furi_hal.h"
#include "../u2f.h"
#define U2F_REQUEST_TIMEOUT 500

Some files were not shown because too many files have changed in this diff Show More