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

Merge branch 'dev' into release

This commit is contained in:
MX
2022-12-19 19:26:06 +03:00
95 changed files with 3234 additions and 589 deletions

View File

@@ -36,10 +36,10 @@ Min level: 1
Max level: 1
Weight: 3
Name: L2_Wake_up_128x64
Name: L1_Happy_holidays_128x64
Min butthurt: 0
Max butthurt: 12
Min level: 2
Max butthurt: 14
Min level: 1
Max level: 3
Weight: 4
@@ -92,6 +92,13 @@ Min level: 1
Max level: 3
Weight: 3
Name: L2_Wake_up_128x64
Min butthurt: 0
Max butthurt: 12
Min level: 2
Max level: 3
Weight: 4
Name: L2_Furippa2_128x64
Min butthurt: 0
Max butthurt: 6

2
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,2 @@
ko_fi: masterx
custom: ['https://boosty.to/mmxdev', 'https://destream.net/live/MMX/donate', 'https://pay.cloudtips.ru/p/7b3e9d65', 'https://yoomoney.ru/fundraise/XA49mgQLPA0.221209']

View File

@@ -128,6 +128,38 @@
"group": "build",
"type": "shell",
"command": "./fbt COMPACT=1 DEBUG=0 launch_app APPSRC=${relativeFileDirname}"
},
{
"label": "[Debug] Launch App on Flipper with Serial Console",
"dependsOrder": "sequence",
"group": "build",
"dependsOn": [
"[Debug] Launch App on Flipper",
"Serial Console"
]
},
{
// Press Ctrl+] to quit
"label": "Serial Console",
"type": "shell",
"command": "./fbt cli",
"group": "none",
"isBackground": true,
"options": {
"env": {
"FBT_NO_SYNC": "0"
}
},
"presentation": {
"reveal": "always",
"revealProblems": "never",
"showReuseMessage": false,
"panel": "dedicated",
"focus": true,
"echo": true,
"close": true,
"group": "Logger"
}
}
]
}
}

View File

@@ -1,11 +1,20 @@
### New changes
* SubGHz: app launch times improved significantly, also setting_user file no longer overwritten by firmware updates, this update will remove this file (only this version, next ones will not touch it (if you skip this version file will be removed in any case on next update)), be sure to backup if you have custom changes in it!
Now this file is actually should be created by user and will be not removed every update!
* Plugins: Add POCSAG Pager [(by xMasterX & Shmuma)](https://github.com/xMasterX/flipper-pager)
* Misc fixes
* OFW: IR button overflow fix
* OFW: Weather Station: proper event flow for view redraw.
* OFW: Untangle NFC from Unit Tests
* API: Version was changed due to breaking changes - from 10.x to 11.x - Extra pack was updated, download it by using link below ([- Download latest extra apps pack](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps))
* Plugins -> SubGHz Bruteforcer: Add support for PT2260, SMC5326, UNILARM, Honeywell(file only) protocols
* Plugins: Add mouse jiggler to USB Keyboard&Mouse App
* Clock: Use system locale settings
* Infrared: Update universal remote assets (by @Amec0e) + (PR #215 | by @airs0urce)
* SubGHz: Removing duplicate code in subghz FAAC scenes. (PR #208 | by @gid9798)
* Plugins -> Weather Station: Fix display of temps lower than -9
* OFW: Notification: fix recursive speaker acquire
* OFW: Locale settings
* OFW: Audio support for SubGhz **(Breaking API change)**
* OFW: Dolphin: add new animation (Happy holidays)
* OFW: SubGhz: add SMC5326, UNILARM protocol
* OFW: Added support for IDTECK cards
* OFW: WS: fix protocol and add new (Oregon_v1, TX8300)
* OFW: VSCode: add task 'Serial console' and group task with sequence calling
* OFW: Dictionary stuff: iClass keys
#### [🎲 Download latest extra apps pack](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps)
@@ -15,6 +24,7 @@ Now this file is actually should be created by user and will be not removed ever
## Please support development of the project
* Boosty: https://boosty.to/mmxdev
* Ko-Fi: https://ko-fi.com/masterx
* destream (100 EUR min): https://destream.net/live/MMX/donate
* cloudtips (only RU payments accepted): https://pay.cloudtips.ru/p/7b3e9d65
* YooMoney (only RU payments accepted): https://yoomoney.ru/fundraise/XA49mgQLPA0.221209
@@ -27,6 +37,10 @@ Now this file is actually should be created by user and will be not removed ever
* XMR (Monero): `41xUz92suUu1u5Mu4qkrcs52gtfpu9rnZRdBpCJ244KRHf6xXSvVFevdf2cnjS7RAeYr5hn9MsEfxKoFDRSctFjG5fv1Mhn`
* TON: `EQCOqcnYkvzOZUV_9bPE_8oTbOrOF03MnF-VcJyjisTZmpGf`
### Thanks to our sponsors:
callmezimbra, Quen0n, MERRON, grvpvl (lvpvrg), art_col, ThurstonWaffles, Moneron, UterGrooll, LUCFER, Northpirate, zloepuzo, T.Rat, Alexey B., ionelife, ...
and all other great people who supported our project and me (xMasterX), thanks to you all!
**Note: To avoid issues with .dfu, prefer installing using .tgz with qFlipper, web updater or by self update package, all needed assets will be installed**
**Recommended option - Web Updater**

View File

@@ -27,6 +27,12 @@ Our Discord Community:
<br>
<br>
## Dev builds
- https://dev.unleashedflip.com/
- https://t.me/kotnehleb
## Releases in Telegram
- https://t.me/unleashed_fw
# What's changed
* SubGHz regional TX restrictions removed
* SubGHz frequency range can be extended in settings file (Warning: It can damage flipper's hardware)
@@ -68,6 +74,7 @@ Also check changelog in releases for latest updates!
## Please support development of the project
* Boosty: https://boosty.to/mmxdev
* Ko-Fi: https://ko-fi.com/masterx
* destream (100 EUR min): https://destream.net/live/MMX/donate
* cloudtips (only RU payments accepted): https://pay.cloudtips.ru/p/7b3e9d65
* YooMoney (only RU payments accepted): https://yoomoney.ru/fundraise/XA49mgQLPA0.221209

View File

@@ -0,0 +1,11 @@
App(
appid="locale_test",
name="Locale Test",
apptype=FlipperAppType.DEBUG,
entry_point="locale_test_app",
cdefines=["APP_LOCALE"],
requires=["gui", "locale"],
stack_size=2 * 1024,
order=70,
fap_category="Debug",
)

View File

@@ -0,0 +1,102 @@
#include <furi.h>
#include <gui/gui.h>
#include <gui/elements.h>
#include <gui/view_dispatcher.h>
#include <gui/modules/dialog_ex.h>
#include <locale/locale.h>
typedef struct {
Gui* gui;
ViewDispatcher* view_dispatcher;
View* view;
} LocaleTestApp;
static void locale_test_view_draw_callback(Canvas* canvas, void* _model) {
UNUSED(_model);
// Prepare canvas
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontSecondary);
FuriString* tmp_string = furi_string_alloc();
float temp = 25.3f;
LocaleMeasurementUnits units = locale_get_measurement_unit();
if(units == LocaleMeasurementUnitsMetric) {
furi_string_printf(tmp_string, "Temp: %5.1fC", (double)temp);
} else {
temp = locale_celsius_to_fahrenheit(temp);
furi_string_printf(tmp_string, "Temp: %5.1fF", (double)temp);
}
canvas_draw_str(canvas, 0, 10, furi_string_get_cstr(tmp_string));
FuriHalRtcDateTime datetime;
furi_hal_rtc_get_datetime(&datetime);
locale_format_time(tmp_string, &datetime, locale_get_time_format(), false);
canvas_draw_str(canvas, 0, 25, furi_string_get_cstr(tmp_string));
locale_format_date(tmp_string, &datetime, locale_get_date_format(), "/");
canvas_draw_str(canvas, 0, 40, furi_string_get_cstr(tmp_string));
furi_string_free(tmp_string);
}
static bool locale_test_view_input_callback(InputEvent* event, void* context) {
UNUSED(event);
UNUSED(context);
return false;
}
static uint32_t locale_test_exit(void* context) {
UNUSED(context);
return VIEW_NONE;
}
static LocaleTestApp* locale_test_alloc() {
LocaleTestApp* app = malloc(sizeof(LocaleTestApp));
// Gui
app->gui = furi_record_open(RECORD_GUI);
// View dispatcher
app->view_dispatcher = view_dispatcher_alloc();
view_dispatcher_enable_queue(app->view_dispatcher);
view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
// Views
app->view = view_alloc();
view_set_draw_callback(app->view, locale_test_view_draw_callback);
view_set_input_callback(app->view, locale_test_view_input_callback);
view_set_previous_callback(app->view, locale_test_exit);
view_dispatcher_add_view(app->view_dispatcher, 0, app->view);
view_dispatcher_switch_to_view(app->view_dispatcher, 0);
return app;
}
static void locale_test_free(LocaleTestApp* app) {
furi_assert(app);
// Free views
view_dispatcher_remove_view(app->view_dispatcher, 0);
view_free(app->view);
view_dispatcher_free(app->view_dispatcher);
// Close gui record
furi_record_close(RECORD_GUI);
app->gui = NULL;
// Free rest
free(app);
}
int32_t locale_test_app(void* p) {
UNUSED(p);
LocaleTestApp* app = locale_test_alloc();
view_dispatcher_run(app->view_dispatcher);
locale_test_free(app);
return 0;
}

View File

@@ -13,7 +13,7 @@
#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 TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub")
#define TEST_RANDOM_COUNT_PARSE 244
#define TEST_RANDOM_COUNT_PARSE 253
#define TEST_TIMEOUT 10000
static SubGhzEnvironment* environment_handler;
@@ -587,6 +587,13 @@ MU_TEST(subghz_decoder_ansonic_test) {
"Test decoder " SUBGHZ_PROTOCOL_ANSONIC_NAME " error\r\n");
}
MU_TEST(subghz_decoder_smc5326_test) {
mu_assert(
subghz_decoder_test(
EXT_PATH("unit_tests/subghz/smc5326_raw.sub"), SUBGHZ_PROTOCOL_SMC5326_NAME),
"Test decoder " SUBGHZ_PROTOCOL_SMC5326_NAME " error\r\n");
}
//test encoders
MU_TEST(subghz_encoder_princeton_test) {
mu_assert(
@@ -714,6 +721,12 @@ MU_TEST(subghz_encoder_ansonic_test) {
"Test encoder " SUBGHZ_PROTOCOL_ANSONIC_NAME " error\r\n");
}
MU_TEST(subghz_encoder_smc5326_test) {
mu_assert(
subghz_encoder_test(EXT_PATH("unit_tests/subghz/smc5326.sub")),
"Test encoder " SUBGHZ_PROTOCOL_SMC5326_NAME " error\r\n");
}
MU_TEST(subghz_random_test) {
mu_assert(subghz_decode_random_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n");
}
@@ -757,6 +770,7 @@ MU_TEST_SUITE(subghz) {
MU_RUN_TEST(subghz_decoder_intertechno_v3_test);
MU_RUN_TEST(subghz_decoder_clemsa_test);
MU_RUN_TEST(subghz_decoder_ansonic_test);
MU_RUN_TEST(subghz_decoder_smc5326_test);
MU_RUN_TEST(subghz_encoder_princeton_test);
MU_RUN_TEST(subghz_encoder_came_test);
@@ -779,6 +793,7 @@ MU_TEST_SUITE(subghz) {
MU_RUN_TEST(subghz_encoder_intertechno_v3_test);
MU_RUN_TEST(subghz_encoder_clemsa_test);
MU_RUN_TEST(subghz_encoder_ansonic_test);
MU_RUN_TEST(subghz_encoder_smc5326_test);
MU_RUN_TEST(subghz_random_test);
subghz_test_deinit();

View File

@@ -5,21 +5,8 @@ App(
entry_point="clock_app",
cdefines=["APP_CLOCK"],
requires=["gui"],
provides=["clock_settings"],
icon="A_Clock_14",
stack_size=2 * 1024,
order=81,
)
App(
appid="clock_settings",
name="Clock",
apptype=FlipperAppType.SETTINGS,
entry_point="clock_settings_app",
requires=["gui","clock"],
stack_size=1 * 1024,
order=20,
)

View File

@@ -33,7 +33,7 @@ static void clock_render_callback(Canvas* const canvas, void* ctx) {
char meridian_string[MERIDIAN_LEN];
char timer_string[20];
if(state->settings.time_format == H24) {
if(state->time_format == LocaleTimeFormat24h) {
snprintf(
time_string, TIME_LEN, CLOCK_TIME_FORMAT, curr_dt.hour, curr_dt.minute, curr_dt.second);
} else {
@@ -54,9 +54,12 @@ static void clock_render_callback(Canvas* const canvas, void* ctx) {
pm12 ? MERIDIAN_STRING_PM : MERIDIAN_STRING_AM);
}
if(state->settings.date_format == Iso) {
if(state->date_format == LocaleDateFormatYMD) {
snprintf(
date_string, DATE_LEN, CLOCK_ISO_DATE_FORMAT, curr_dt.year, curr_dt.month, curr_dt.day);
} else if(state->date_format == LocaleDateFormatMDY) {
snprintf(
date_string, DATE_LEN, CLOCK_RFC_DATE_FORMAT, curr_dt.month, curr_dt.day, curr_dt.year);
} else {
snprintf(
date_string, DATE_LEN, CLOCK_RFC_DATE_FORMAT, curr_dt.day, curr_dt.month, curr_dt.year);
@@ -84,7 +87,7 @@ static void clock_render_callback(Canvas* const canvas, void* ctx) {
canvas_set_font(canvas, FontSecondary);
canvas_draw_str_aligned(canvas, 64, 42, AlignCenter, AlignTop, date_string);
if(state->settings.time_format == H12)
if(state->time_format == LocaleTimeFormat12h)
canvas_draw_str_aligned(canvas, 65, 12, AlignCenter, AlignCenter, meridian_string);
}
if(timer_running) {
@@ -95,16 +98,12 @@ static void clock_render_callback(Canvas* const canvas, void* ctx) {
}
static void clock_state_init(ClockState* const state) {
LOAD_CLOCK_SETTINGS(&state->settings);
if(state->settings.time_format != H12 && state->settings.time_format != H24) {
state->settings.time_format = H12;
}
if(state->settings.date_format != Iso && state->settings.date_format != Rfc) {
state->settings.date_format = Iso;
}
FURI_LOG_D(TAG, "Time format: %s", state->settings.time_format == H12 ? "12h" : "24h");
FURI_LOG_D(
TAG, "Date format: %s", state->settings.date_format == Iso ? "ISO 8601" : "RFC 5322");
state->time_format = locale_get_time_format();
state->date_format = locale_get_date_format();
//FURI_LOG_D(TAG, "Time format: %s", state->settings.time_format == H12 ? "12h" : "24h");
//FURI_LOG_D(TAG, "Date format: %s", state->settings.date_format == Iso ? "ISO 8601" : "RFC 5322");
//furi_hal_rtc_get_datetime(&state->datetime);
}

View File

@@ -1,7 +1,7 @@
#pragma once
#include <input/input.h>
#include "clock_settings.h"
#include <locale/locale.h>
#define TAG "Clock"
@@ -28,7 +28,8 @@ typedef struct {
} PluginEvent;
typedef struct {
ClockSettings settings;
LocaleDateFormat date_format;
LocaleTimeFormat time_format;
FuriHalRtcDateTime datetime;
FuriMutex* mutex;
FuriMessageQueue* event_queue;

View File

@@ -1,36 +0,0 @@
#pragma once
#include "clock_settings_filename.h"
#include <furi_hal.h>
#include <stdint.h>
#include <stdbool.h>
#include <toolbox/saved_struct.h>
#include <storage/storage.h>
#define CLOCK_SETTINGS_VER (1)
#define CLOCK_SETTINGS_PATH EXT_PATH(CLOCK_SETTINGS_FILE_NAME)
#define CLOCK_SETTINGS_MAGIC (0xC1)
#define SAVE_CLOCK_SETTINGS(x) \
saved_struct_save( \
CLOCK_SETTINGS_PATH, (x), sizeof(ClockSettings), CLOCK_SETTINGS_MAGIC, CLOCK_SETTINGS_VER)
#define LOAD_CLOCK_SETTINGS(x) \
saved_struct_load( \
CLOCK_SETTINGS_PATH, (x), sizeof(ClockSettings), CLOCK_SETTINGS_MAGIC, CLOCK_SETTINGS_VER)
typedef enum {
H12 = 1,
H24 = 2,
} TimeFormat;
typedef enum {
Iso = 1, // ISO 8601: yyyy-mm-dd
Rfc = 2, // RFC 5322: dd-mm-yyyy
} DateFormat;
typedef struct {
TimeFormat time_format;
DateFormat date_format;
} ClockSettings;

View File

@@ -1,102 +0,0 @@
#include <furi.h>
#include <gui/modules/variable_item_list.h>
#include <gui/view_dispatcher.h>
#include <lib/toolbox/value_index.h>
#include "clock_settings.h"
#define TAG "Clock"
typedef struct {
ClockSettings clock_settings;
Gui* gui;
ViewDispatcher* view_dispatcher;
VariableItemList* variable_item_list;
} ClockAppSettings;
static uint32_t clock_app_settings_exit(void* context) {
UNUSED(context);
return VIEW_NONE;
}
#define TIME_FORMAT_COUNT 2
const char* const time_format_text[TIME_FORMAT_COUNT] = {
"12h",
"24h",
};
const uint32_t time_format_value[TIME_FORMAT_COUNT] = {H12, H24};
#define DATE_FORMAT_COUNT 2
const char* const date_format_text[DATE_FORMAT_COUNT] = {
"mm-dd", // ISO 8601
"dd-mm", // RFC 5322
};
const uint32_t date_format_value[DATE_FORMAT_COUNT] = {Iso, Rfc};
static void time_format_changed(VariableItem* item) {
ClockAppSettings* app = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(item, time_format_text[index]);
app->clock_settings.time_format = time_format_value[index];
}
static void date_format_changed(VariableItem* item) {
ClockAppSettings* app = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(item, date_format_text[index]);
app->clock_settings.date_format = date_format_value[index];
}
static ClockAppSettings* alloc_settings() {
ClockAppSettings* app = malloc(sizeof(ClockAppSettings));
LOAD_CLOCK_SETTINGS(&app->clock_settings);
app->gui = furi_record_open(RECORD_GUI);
app->variable_item_list = variable_item_list_alloc();
View* view = variable_item_list_get_view(app->variable_item_list);
view_set_previous_callback(view, clock_app_settings_exit);
VariableItem* item;
uint8_t value_index;
item = variable_item_list_add(
app->variable_item_list, "Clock format", TIME_FORMAT_COUNT, time_format_changed, app);
value_index = value_index_uint32(
(uint32_t)(app->clock_settings.time_format), time_format_value, TIME_FORMAT_COUNT);
//FURI_LOG_T(TAG, "Time format index: %u", value_index);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, time_format_text[value_index]);
item = variable_item_list_add(
app->variable_item_list, "Date format", DATE_FORMAT_COUNT, date_format_changed, app);
value_index = value_index_uint32(
(uint32_t)(app->clock_settings.date_format), date_format_value, DATE_FORMAT_COUNT);
//FURI_LOG_T(TAG, "Date format index: %u", value_index);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, date_format_text[value_index]);
app->view_dispatcher = view_dispatcher_alloc();
view_dispatcher_enable_queue(app->view_dispatcher);
view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
view_dispatcher_add_view(app->view_dispatcher, 0, view);
view_dispatcher_switch_to_view(app->view_dispatcher, 0);
return app;
}
static void free_settings(ClockAppSettings* app) {
view_dispatcher_remove_view(app->view_dispatcher, 0);
variable_item_list_free(app->variable_item_list);
view_dispatcher_free(app->view_dispatcher);
furi_record_close(RECORD_GUI);
SAVE_CLOCK_SETTINGS(&app->clock_settings);
free(app);
}
extern int32_t clock_settings_app(void* p) {
UNUSED(p);
ClockAppSettings* app = alloc_settings();
view_dispatcher_run(app->view_dispatcher);
free_settings(app);
return 0;
}

View File

@@ -1,3 +0,0 @@
#pragma once
#define CLOCK_SETTINGS_FILE_NAME ".clock.settings"

View File

@@ -28,6 +28,13 @@ typedef enum {
SubGhzHopperStateRSSITimeOut,
} SubGhzHopperState;
/** SubGhzSpeakerState state */
typedef enum {
SubGhzSpeakerStateDisable,
SubGhzSpeakerStateShutdown,
SubGhzSpeakerStateEnable,
} SubGhzSpeakerState;
/** SubGhzRxKeyState state */
typedef enum {
SubGhzRxKeyStateIDLE,

View File

@@ -19,12 +19,9 @@ ADD_SCENE(subghz, test_static, TestStatic)
ADD_SCENE(subghz, test_packet, TestPacket)
#endif
ADD_SCENE(subghz, set_type, SetType)
ADD_SCENE(subghz, set_fix_faac_868, SetFixFaac868)
ADD_SCENE(subghz, set_cnt_faac_868, SetCntFaac868)
ADD_SCENE(subghz, set_seed_faac_868, SetSeedFaac868)
ADD_SCENE(subghz, set_fix_faac_433, SetFixFaac433)
ADD_SCENE(subghz, set_cnt_faac_433, SetCntFaac433)
ADD_SCENE(subghz, set_seed_faac_433, SetSeedFaac433)
ADD_SCENE(subghz, set_fix_faac, SetFixFaac)
ADD_SCENE(subghz, set_cnt_faac, SetCntFaac)
ADD_SCENE(subghz, set_seed_faac, SetSeedFaac)
ADD_SCENE(subghz, set_fix_bft, SetFixBft)
ADD_SCENE(subghz, set_cnt_bft, SetCntBft)
ADD_SCENE(subghz, set_seed_bft, SetSeedBft)

View File

@@ -271,6 +271,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
case SubGhzCustomEventViewReadRAWSendStop:
subghz->state_notifications = SubGhzNotificationStateIDLE;
if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
subghz_speaker_unmute(subghz);
subghz_tx_stop(subghz);
subghz_sleep(subghz);
}
@@ -388,10 +389,12 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
subghz_read_raw_add_data_rssi(subghz->subghz_read_raw, rssi, false);
subghz_protocol_raw_save_to_file_pause(
(SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result, true);
subghz_speaker_mute(subghz);
} else {
subghz_read_raw_add_data_rssi(subghz->subghz_read_raw, rssi, true);
subghz_protocol_raw_save_to_file_pause(
(SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result, false);
subghz_speaker_unmute(subghz);
}
}

View File

@@ -11,6 +11,7 @@ enum SubGhzSettingIndex {
SubGhzSettingIndexModulation,
SubGhzSettingIndexDetectRaw,
SubGhzSettingIndexRSSIThreshold,
SubGhzSettingIndexSound,
SubGhzSettingIndexLock,
SubGhzSettingIndexRAWThesholdRSSI,
};
@@ -88,6 +89,16 @@ const int rssi_threshold_value[RSSI_THRESHOLD_COUNT] = {
-42,
};
#define SPEAKER_COUNT 2
const char* const speaker_text[SPEAKER_COUNT] = {
"OFF",
"ON",
};
const uint32_t speaker_value[SPEAKER_COUNT] = {
SubGhzSpeakerStateShutdown,
SubGhzSpeakerStateEnable,
};
uint8_t subghz_scene_receiver_config_next_frequency(const uint32_t value, void* context) {
furi_assert(context);
SubGhz* subghz = context;
@@ -280,6 +291,14 @@ static void subghz_scene_receiver_config_set_hopping_running(VariableItem* item)
}*/
}
static void subghz_scene_receiver_config_set_speaker(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, speaker_text[index]);
subghz->txrx->speaker_state = speaker_value[index];
}
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);
@@ -389,6 +408,16 @@ void subghz_scene_receiver_config_on_enter(void* context) {
variable_item_set_current_value_text(item, rssi_threshold_text[value_index]);
// 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

@@ -1,14 +1,14 @@
#include "../subghz_i.h"
#define TAG "SubGhzSetCntFaac868"
#define TAG "SubGhzSetCntFaac"
void subghz_scene_set_cnt_faac_868_byte_input_callback(void* context) {
void subghz_scene_set_cnt_faac_byte_input_callback(void* context) {
SubGhz* subghz = context;
view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventByteInputDone);
}
void subghz_scene_set_cnt_faac_868_on_enter(void* context) {
void subghz_scene_set_cnt_faac_on_enter(void* context) {
SubGhz* subghz = context;
// Setup view
@@ -16,7 +16,7 @@ void subghz_scene_set_cnt_faac_868_on_enter(void* context) {
byte_input_set_header_text(byte_input, "Enter COUNTER in hex, 20bits");
byte_input_set_result_callback(
byte_input,
subghz_scene_set_cnt_faac_868_byte_input_callback,
subghz_scene_set_cnt_faac_byte_input_callback,
NULL,
subghz,
subghz->txrx->secure_data->cnt,
@@ -24,20 +24,20 @@ void subghz_scene_set_cnt_faac_868_on_enter(void* context) {
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdByteInput);
}
bool subghz_scene_set_cnt_faac_868_on_event(void* context, SceneManagerEvent event) {
bool subghz_scene_set_cnt_faac_on_event(void* context, SceneManagerEvent event) {
SubGhz* subghz = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubGhzCustomEventByteInputDone) {
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetSeedFaac868);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetSeedFaac);
consumed = true;
}
}
return consumed;
}
void subghz_scene_set_cnt_faac_868_on_exit(void* context) {
void subghz_scene_set_cnt_faac_on_exit(void* context) {
SubGhz* subghz = context;
// Clear view

View File

@@ -1,46 +0,0 @@
#include "../subghz_i.h"
#define TAG "SubGhzSetCntFaac433"
void subghz_scene_set_cnt_faac_433_byte_input_callback(void* context) {
SubGhz* subghz = context;
view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventByteInputDone);
}
void subghz_scene_set_cnt_faac_433_on_enter(void* context) {
SubGhz* subghz = context;
// Setup view
ByteInput* byte_input = subghz->byte_input;
byte_input_set_header_text(byte_input, "Enter COUNTER in hex, 20bits");
byte_input_set_result_callback(
byte_input,
subghz_scene_set_cnt_faac_433_byte_input_callback,
NULL,
subghz,
subghz->txrx->secure_data->cnt,
3);
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdByteInput);
}
bool subghz_scene_set_cnt_faac_433_on_event(void* context, SceneManagerEvent event) {
SubGhz* subghz = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubGhzCustomEventByteInputDone) {
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetSeedFaac433);
consumed = true;
}
}
return consumed;
}
void subghz_scene_set_cnt_faac_433_on_exit(void* context) {
SubGhz* subghz = context;
// Clear view
byte_input_set_result_callback(subghz->byte_input, NULL, NULL, NULL, NULL, 0);
byte_input_set_header_text(subghz->byte_input, "");
}

View File

@@ -1,14 +1,14 @@
#include "../subghz_i.h"
#define TAG "SubGhzSetFixFaac868"
#define TAG "SubGhzSetFixFaac"
void subghz_scene_set_fix_faac_868_byte_input_callback(void* context) {
void subghz_scene_set_fix_faac_byte_input_callback(void* context) {
SubGhz* subghz = context;
view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventByteInputDone);
}
void subghz_scene_set_fix_faac_868_on_enter(void* context) {
void subghz_scene_set_fix_faac_on_enter(void* context) {
SubGhz* subghz = context;
// Setup view
@@ -16,7 +16,7 @@ void subghz_scene_set_fix_faac_868_on_enter(void* context) {
byte_input_set_header_text(byte_input, "Enter FIX in hex");
byte_input_set_result_callback(
byte_input,
subghz_scene_set_fix_faac_868_byte_input_callback,
subghz_scene_set_fix_faac_byte_input_callback,
NULL,
subghz,
subghz->txrx->secure_data->fix,
@@ -24,20 +24,20 @@ void subghz_scene_set_fix_faac_868_on_enter(void* context) {
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdByteInput);
}
bool subghz_scene_set_fix_faac_868_on_event(void* context, SceneManagerEvent event) {
bool subghz_scene_set_fix_faac_on_event(void* context, SceneManagerEvent event) {
SubGhz* subghz = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubGhzCustomEventByteInputDone) {
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetCntFaac868);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetCntFaac);
consumed = true;
}
}
return consumed;
}
void subghz_scene_set_fix_faac_868_on_exit(void* context) {
void subghz_scene_set_fix_faac_on_exit(void* context) {
SubGhz* subghz = context;
// Clear view

View File

@@ -1,46 +0,0 @@
#include "../subghz_i.h"
#define TAG "SubGhzSetFixFaac433"
void subghz_scene_set_fix_faac_433_byte_input_callback(void* context) {
SubGhz* subghz = context;
view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventByteInputDone);
}
void subghz_scene_set_fix_faac_433_on_enter(void* context) {
SubGhz* subghz = context;
// Setup view
ByteInput* byte_input = subghz->byte_input;
byte_input_set_header_text(byte_input, "Enter FIX in hex");
byte_input_set_result_callback(
byte_input,
subghz_scene_set_fix_faac_433_byte_input_callback,
NULL,
subghz,
subghz->txrx->secure_data->fix,
4);
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdByteInput);
}
bool subghz_scene_set_fix_faac_433_on_event(void* context, SceneManagerEvent event) {
SubGhz* subghz = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubGhzCustomEventByteInputDone) {
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetCntFaac433);
consumed = true;
}
}
return consumed;
}
void subghz_scene_set_fix_faac_433_on_exit(void* context) {
SubGhz* subghz = context;
// Clear view
byte_input_set_result_callback(subghz->byte_input, NULL, NULL, NULL, NULL, 0);
byte_input_set_header_text(subghz->byte_input, "");
}

View File

@@ -2,15 +2,15 @@
#include <dolphin/dolphin.h>
#include <lib/subghz/protocols/faac_slh.h>
#define TAG "SubGhzSetSeedFaac433"
#define TAG "SubGhzSetSeedFaac"
void subghz_scene_set_seed_faac_433_byte_input_callback(void* context) {
void subghz_scene_set_seed_faac_byte_input_callback(void* context) {
SubGhz* subghz = context;
view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventByteInputDone);
}
void subghz_scene_set_seed_faac_433_on_enter(void* context) {
void subghz_scene_set_seed_faac_on_enter(void* context) {
SubGhz* subghz = context;
// Setup view
@@ -18,7 +18,7 @@ void subghz_scene_set_seed_faac_433_on_enter(void* context) {
byte_input_set_header_text(byte_input, "Enter SEED in hex");
byte_input_set_result_callback(
byte_input,
subghz_scene_set_seed_faac_433_byte_input_callback,
subghz_scene_set_seed_faac_byte_input_callback,
NULL,
subghz,
subghz->txrx->secure_data->seed,
@@ -26,7 +26,7 @@ void subghz_scene_set_seed_faac_433_on_enter(void* context) {
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdByteInput);
}
bool subghz_scene_set_seed_faac_433_on_event(void* context, SceneManagerEvent event) {
bool subghz_scene_set_seed_faac_on_event(void* context, SceneManagerEvent event) {
SubGhz* subghz = context;
bool consumed = false;
bool generated_protocol = false;
@@ -48,7 +48,14 @@ bool subghz_scene_set_seed_faac_433_on_event(void* context, SceneManagerEvent ev
subghz->txrx->transmitter =
subghz_transmitter_alloc_init(subghz->txrx->environment, "Faac SLH");
if(subghz->txrx->transmitter) {
subghz_preset_init(subghz, "AM650", 433920000, NULL, 0);
SubGhzCustomEvent state =
scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneSetType);
if(state == SubmenuIndexFaacSLH_433) {
subghz_preset_init(subghz, "AM650", 433920000, NULL, 0);
} else if(state == SubmenuIndexFaacSLH_868) {
subghz_preset_init(subghz, "AM650", 868350000, NULL, 0);
}
subghz_protocol_faac_slh_create_data(
subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter),
subghz->txrx->fff_data,
@@ -94,7 +101,7 @@ bool subghz_scene_set_seed_faac_433_on_event(void* context, SceneManagerEvent ev
return consumed;
}
void subghz_scene_set_seed_faac_433_on_exit(void* context) {
void subghz_scene_set_seed_faac_on_exit(void* context) {
SubGhz* subghz = context;
// Clear view

View File

@@ -1,103 +0,0 @@
#include "../subghz_i.h"
#include <dolphin/dolphin.h>
#include <lib/subghz/protocols/faac_slh.h>
#define TAG "SubGhzSetSeedFaac868"
void subghz_scene_set_seed_faac_868_byte_input_callback(void* context) {
SubGhz* subghz = context;
view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventByteInputDone);
}
void subghz_scene_set_seed_faac_868_on_enter(void* context) {
SubGhz* subghz = context;
// Setup view
ByteInput* byte_input = subghz->byte_input;
byte_input_set_header_text(byte_input, "Enter SEED in hex");
byte_input_set_result_callback(
byte_input,
subghz_scene_set_seed_faac_868_byte_input_callback,
NULL,
subghz,
subghz->txrx->secure_data->seed,
4);
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdByteInput);
}
bool subghz_scene_set_seed_faac_868_on_event(void* context, SceneManagerEvent event) {
SubGhz* subghz = context;
bool consumed = false;
bool generated_protocol = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubGhzCustomEventByteInputDone) {
uint32_t fix_part =
subghz->txrx->secure_data->fix[0] << 24 | subghz->txrx->secure_data->fix[1] << 16 |
subghz->txrx->secure_data->fix[2] << 8 | subghz->txrx->secure_data->fix[3];
uint32_t cnt = subghz->txrx->secure_data->cnt[0] << 16 |
subghz->txrx->secure_data->cnt[1] << 8 |
subghz->txrx->secure_data->cnt[2];
uint32_t seed = subghz->txrx->secure_data->seed[0] << 24 |
subghz->txrx->secure_data->seed[1] << 16 |
subghz->txrx->secure_data->seed[2] << 8 |
subghz->txrx->secure_data->seed[3];
subghz->txrx->transmitter =
subghz_transmitter_alloc_init(subghz->txrx->environment, "Faac SLH");
if(subghz->txrx->transmitter) {
subghz_preset_init(subghz, "AM650", 868350000, NULL, 0);
subghz_protocol_faac_slh_create_data(
subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter),
subghz->txrx->fff_data,
fix_part >> 4,
fix_part & 0xf,
(cnt & 0xFFFFF),
seed,
"FAAC_SLH",
subghz->txrx->preset);
// roguemastter dont steal!!
uint8_t seed_data[sizeof(uint32_t)] = {0};
for(size_t i = 0; i < sizeof(uint32_t); i++) {
seed_data[sizeof(uint32_t) - i - 1] = (seed >> i * 8) & 0xFF;
}
flipper_format_write_hex(
subghz->txrx->fff_data, "Seed", seed_data, sizeof(uint32_t));
generated_protocol = true;
} else {
generated_protocol = false;
}
subghz_transmitter_free(subghz->txrx->transmitter);
if(!generated_protocol) {
furi_string_set(
subghz->error_str, "Function requires\nan SD card with\nfresh databases.");
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError);
}
consumed = true;
}
if(generated_protocol) {
subghz_file_name_clear(subghz);
DOLPHIN_DEED(DolphinDeedSubGhzAddManually);
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneSetType, SubGhzCustomEventManagerSet);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName);
return true;
}
}
return consumed;
}
void subghz_scene_set_seed_faac_868_on_exit(void* context) {
SubGhz* subghz = context;
// Clear view
byte_input_set_result_callback(subghz->byte_input, NULL, NULL, NULL, NULL, 0);
byte_input_set_header_text(subghz->byte_input, "");
}

View File

@@ -212,10 +212,10 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
uint32_t key = subghz_random_serial();
switch(event.event) {
case SubmenuIndexFaacSLH_868:
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetFixFaac868);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetFixFaac);
break;
case SubmenuIndexFaacSLH_433:
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetFixFaac433);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetFixFaac);
break;
case SubmenuIndexBFT:
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetFixBft);

View File

@@ -266,6 +266,7 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) {
}
subghz->txrx->txrx_state = SubGhzTxRxStateSleep;
subghz->txrx->hopper_state = SubGhzHopperStateOFF;
subghz->txrx->speaker_state = SubGhzSpeakerStateDisable;
subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
if(!alloc_for_tx_only) {
subghz->txrx->history = subghz_history_alloc();

View File

@@ -86,6 +86,7 @@ uint32_t subghz_rx(SubGhz* subghz, uint32_t frequency) {
uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency);
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
furi_hal_subghz_flush_rx();
subghz_speaker_on(subghz);
furi_hal_subghz_rx();
furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, subghz->txrx->worker);
@@ -104,6 +105,7 @@ static bool subghz_tx(SubGhz* subghz, uint32_t frequency) {
furi_hal_subghz_set_frequency_and_path(frequency);
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;
return ret;
@@ -119,11 +121,13 @@ void subghz_idle(SubGhz* subghz) {
void subghz_rx_end(SubGhz* subghz) {
furi_assert(subghz);
furi_assert(subghz->txrx->txrx_state == SubGhzTxRxStateRx);
if(subghz_worker_is_running(subghz->txrx->worker)) {
subghz_worker_stop(subghz->txrx->worker);
furi_hal_subghz_stop_async_rx();
}
furi_hal_subghz_idle();
subghz_speaker_off(subghz);
subghz->txrx->txrx_state = SubGhzTxRxStateIDLE;
}
@@ -212,6 +216,7 @@ void subghz_tx_stop(SubGhz* subghz) {
subghz, subghz->txrx->fff_data, furi_string_get_cstr(subghz->file_path));
}
subghz_idle(subghz);
subghz_speaker_off(subghz);
notification_message(subghz->notifications, &sequence_reset_red);
}
@@ -592,3 +597,40 @@ void subghz_hopper_update(SubGhz* subghz) {
subghz_rx(subghz, subghz->txrx->preset->frequency);
}
}
void subghz_speaker_on(SubGhz* subghz) {
if(subghz->txrx->speaker_state == SubGhzSpeakerStateEnable) {
if(furi_hal_speaker_acquire(30)) {
furi_hal_subghz_set_async_mirror_pin(&gpio_speaker);
} else {
subghz->txrx->speaker_state = SubGhzSpeakerStateDisable;
}
}
}
void subghz_speaker_off(SubGhz* subghz) {
if(subghz->txrx->speaker_state != SubGhzSpeakerStateDisable) {
if(furi_hal_speaker_is_mine()) {
furi_hal_subghz_set_async_mirror_pin(NULL);
furi_hal_speaker_release();
if(subghz->txrx->speaker_state == SubGhzSpeakerStateShutdown)
subghz->txrx->speaker_state = SubGhzSpeakerStateDisable;
}
}
}
void subghz_speaker_mute(SubGhz* subghz) {
if(subghz->txrx->speaker_state == SubGhzSpeakerStateEnable) {
if(furi_hal_speaker_is_mine()) {
furi_hal_subghz_set_async_mirror_pin(NULL);
}
}
}
void subghz_speaker_unmute(SubGhz* subghz) {
if(subghz->txrx->speaker_state == SubGhzSpeakerStateEnable) {
if(furi_hal_speaker_is_mine()) {
furi_hal_subghz_set_async_mirror_pin(&gpio_speaker);
}
}
}

View File

@@ -71,6 +71,7 @@ struct SubGhzTxRx {
uint16_t idx_menu_chosen;
SubGhzTxRxState txrx_state;
SubGhzHopperState hopper_state;
SubGhzSpeakerState speaker_state;
uint8_t hopper_timeout;
uint8_t hopper_idx_frequency;
SubGhzRxKeyState rx_key_state;
@@ -160,6 +161,10 @@ void subghz_file_name_clear(SubGhz* subghz);
bool subghz_path_is_file(FuriString* path);
uint32_t subghz_random_serial(void);
void subghz_hopper_update(SubGhz* subghz);
void subghz_speaker_on(SubGhz* subghz);
void subghz_speaker_off(SubGhz* subghz);
void subghz_speaker_mute(SubGhz* subghz);
void subghz_speaker_unmute(SubGhz* subghz);
extern const NotificationSequence subghz_sequence_rx;
extern const NotificationSequence subghz_sequence_rx_locked;

View File

@@ -47,47 +47,51 @@ static int32_t music_player_worker_thread_callback(void* context) {
NoteBlockArray_it_t it;
NoteBlockArray_it(it, instance->notes);
if(furi_hal_speaker_acquire(1000)) {
while(instance->should_work) {
if(NoteBlockArray_end_p(it)) {
NoteBlockArray_it(it, instance->notes);
furi_delay_ms(10);
} else {
NoteBlock* note_block = NoteBlockArray_ref(it);
while(instance->should_work) {
if(NoteBlockArray_end_p(it)) {
NoteBlockArray_it(it, instance->notes);
furi_delay_ms(10);
} else {
NoteBlock* note_block = NoteBlockArray_ref(it);
float note_from_a4 = (float)note_block->semitone - NOTE_C4_SEMITONE;
float frequency = NOTE_C4 * powf(TWO_POW_TWELTH_ROOT, note_from_a4);
float duration = 60.0 * furi_kernel_get_tick_frequency() * 4 / instance->bpm /
note_block->duration;
uint32_t dots = note_block->dots;
while(dots > 0) {
duration += duration / 2;
dots--;
}
uint32_t next_tick = furi_get_tick() + duration;
float volume = instance->volume;
float note_from_a4 = (float)note_block->semitone - NOTE_C4_SEMITONE;
float frequency = NOTE_C4 * powf(TWO_POW_TWELTH_ROOT, note_from_a4);
float duration =
60.0 * furi_kernel_get_tick_frequency() * 4 / instance->bpm / note_block->duration;
uint32_t dots = note_block->dots;
while(dots > 0) {
duration += duration / 2;
dots--;
if(instance->callback) {
instance->callback(
note_block->semitone,
note_block->dots,
note_block->duration,
0.0,
instance->callback_context);
}
furi_hal_speaker_stop();
furi_hal_speaker_start(frequency, volume);
while(instance->should_work && furi_get_tick() < next_tick) {
volume *= 0.9945679;
furi_hal_speaker_set_volume(volume);
furi_delay_ms(2);
}
NoteBlockArray_next(it);
}
uint32_t next_tick = furi_get_tick() + duration;
float volume = instance->volume;
if(instance->callback) {
instance->callback(
note_block->semitone,
note_block->dots,
note_block->duration,
0.0,
instance->callback_context);
}
furi_hal_speaker_stop();
furi_hal_speaker_start(frequency, volume);
while(instance->should_work && furi_get_tick() < next_tick) {
volume *= 0.9945679;
furi_hal_speaker_set_volume(volume);
furi_delay_ms(2);
}
NoteBlockArray_next(it);
}
}
furi_hal_speaker_stop();
furi_hal_speaker_stop();
furi_hal_speaker_release();
} else {
FURI_LOG_E(TAG, "Speaker system is busy with another process.");
}
return 0;
}

View File

@@ -9,10 +9,10 @@ enum HidDebugSubmenuIndex {
HidSubmenuIndexKeynote,
HidSubmenuIndexKeyboard,
HidSubmenuIndexMedia,
BtHidSubmenuIndexTikTok,
HidSubmenuIndexTikTok,
HidSubmenuIndexMouse,
HidSubmenuIndexMouseJiggler,
};
typedef enum { ConnTypeSubmenuIndexBluetooth, ConnTypeSubmenuIndexUsb } ConnTypeDebugSubmenuIndex;
static void hid_submenu_callback(void* context, uint32_t index) {
furi_assert(context);
@@ -29,9 +29,12 @@ static void hid_submenu_callback(void* context, uint32_t index) {
} else if(index == HidSubmenuIndexMouse) {
app->view_id = HidViewMouse;
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewMouse);
} else if(index == BtHidSubmenuIndexTikTok) {
} else if(index == HidSubmenuIndexTikTok) {
app->view_id = BtHidViewTikTok;
view_dispatcher_switch_to_view(app->view_dispatcher, BtHidViewTikTok);
} else if(index == HidSubmenuIndexMouseJiggler) {
app->view_id = HidViewMouseJiggler;
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewMouseJiggler);
}
}
@@ -48,6 +51,7 @@ static void bt_hid_connection_status_changed_callback(BtStatus status, void* con
hid_keyboard_set_connected_status(hid->hid_keyboard, connected);
hid_media_set_connected_status(hid->hid_media, connected);
hid_mouse_set_connected_status(hid->hid_mouse, connected);
hid_mouse_jiggler_set_connected_status(hid->hid_mouse_jiggler, connected);
hid_tiktok_set_connected_status(hid->hid_tiktok, connected);
}
@@ -104,10 +108,16 @@ Hid* hid_alloc(HidTransport transport) {
submenu_add_item(
app->device_type_submenu,
"TikTok Controller",
BtHidSubmenuIndexTikTok,
HidSubmenuIndexTikTok,
hid_submenu_callback,
app);
}
submenu_add_item(
app->device_type_submenu,
"Mouse Jiggler",
HidSubmenuIndexMouseJiggler,
hid_submenu_callback,
app);
view_set_previous_callback(submenu_get_view(app->device_type_submenu), hid_exit);
view_dispatcher_add_view(
app->view_dispatcher, HidViewSubmenu, submenu_get_view(app->device_type_submenu));
@@ -160,6 +170,15 @@ Hid* hid_app_alloc_view(void* context) {
view_dispatcher_add_view(
app->view_dispatcher, HidViewMouse, hid_mouse_get_view(app->hid_mouse));
// Mouse jiggler view
app->hid_mouse_jiggler = hid_mouse_jiggler_alloc(app);
view_set_previous_callback(
hid_mouse_jiggler_get_view(app->hid_mouse_jiggler), hid_exit_confirm_view);
view_dispatcher_add_view(
app->view_dispatcher,
HidViewMouseJiggler,
hid_mouse_jiggler_get_view(app->hid_mouse_jiggler));
return app;
}
@@ -182,6 +201,8 @@ void hid_free(Hid* app) {
hid_media_free(app->hid_media);
view_dispatcher_remove_view(app->view_dispatcher, HidViewMouse);
hid_mouse_free(app->hid_mouse);
view_dispatcher_remove_view(app->view_dispatcher, HidViewMouseJiggler);
hid_mouse_jiggler_free(app->hid_mouse_jiggler);
view_dispatcher_remove_view(app->view_dispatcher, BtHidViewTikTok);
hid_tiktok_free(app->hid_tiktok);
view_dispatcher_free(app->view_dispatcher);

View File

@@ -19,6 +19,7 @@
#include "views/hid_keyboard.h"
#include "views/hid_media.h"
#include "views/hid_mouse.h"
#include "views/hid_mouse_jiggler.h"
#include "views/hid_tiktok.h"
typedef enum {
@@ -39,6 +40,7 @@ struct Hid {
HidKeyboard* hid_keyboard;
HidMedia* hid_media;
HidMouse* hid_mouse;
HidMouseJiggler* hid_mouse_jiggler;
HidTikTok* hid_tiktok;
HidTransport transport;

View File

@@ -4,6 +4,7 @@ typedef enum {
HidViewKeyboard,
HidViewMedia,
HidViewMouse,
HidViewMouseJiggler,
BtHidViewTikTok,
HidViewExitConfirm,
} HidView;

View File

@@ -0,0 +1,149 @@
#include "hid_mouse_jiggler.h"
#include <gui/elements.h>
#include "../hid.h"
#include "hid_icons.h"
#define TAG "HidMouseJiggler"
struct HidMouseJiggler {
View* view;
Hid* hid;
FuriTimer* timer;
};
typedef struct {
bool connected;
bool running;
uint8_t counter;
} HidMouseJigglerModel;
static void hid_mouse_jiggler_draw_callback(Canvas* canvas, void* context) {
furi_assert(context);
HidMouseJigglerModel* model = context;
// Header
if(model->connected) {
canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
} else {
canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
}
canvas_set_font(canvas, FontPrimary);
elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Mouse Jiggler");
canvas_set_font(canvas, FontPrimary);
elements_multiline_text(canvas, AlignLeft, 35, "Press Start\nto jiggle");
canvas_set_font(canvas, FontSecondary);
// Ok
canvas_draw_icon(canvas, 63, 25, &I_Space_65x18);
if(model->running) {
elements_slightly_rounded_box(canvas, 66, 27, 60, 13);
canvas_set_color(canvas, ColorWhite);
}
canvas_draw_icon(canvas, 74, 29, &I_Ok_btn_9x9);
if(model->running) {
elements_multiline_text_aligned(canvas, 91, 36, AlignLeft, AlignBottom, "Stop");
} else {
elements_multiline_text_aligned(canvas, 91, 36, AlignLeft, AlignBottom, "Start");
}
canvas_set_color(canvas, ColorBlack);
// Back
canvas_draw_icon(canvas, 74, 49, &I_Pin_back_arrow_10x8);
elements_multiline_text_aligned(canvas, 91, 57, AlignLeft, AlignBottom, "Quit");
}
static void hid_mouse_jiggler_timer_callback(void* context) {
furi_assert(context);
HidMouseJiggler* hid_mouse_jiggler = context;
with_view_model(
hid_mouse_jiggler->view,
HidMouseJigglerModel * model,
{
if(model->running) {
model->counter++;
hid_hal_mouse_move(
hid_mouse_jiggler->hid,
(model->counter % 2 == 0) ? MOUSE_MOVE_SHORT : -MOUSE_MOVE_SHORT,
0);
}
},
false);
}
static void hid_mouse_jiggler_enter_callback(void* context) {
furi_assert(context);
HidMouseJiggler* hid_mouse_jiggler = context;
furi_timer_start(hid_mouse_jiggler->timer, 500);
}
static void hid_mouse_jiggler_exit_callback(void* context) {
furi_assert(context);
HidMouseJiggler* hid_mouse_jiggler = context;
furi_timer_stop(hid_mouse_jiggler->timer);
}
static bool hid_mouse_jiggler_input_callback(InputEvent* event, void* context) {
furi_assert(context);
HidMouseJiggler* hid_mouse_jiggler = context;
bool consumed = false;
if(event->key == InputKeyOk) {
with_view_model(
hid_mouse_jiggler->view,
HidMouseJigglerModel * model,
{ model->running = !model->running; },
true);
consumed = true;
}
return consumed;
}
HidMouseJiggler* hid_mouse_jiggler_alloc(Hid* hid) {
HidMouseJiggler* hid_mouse_jiggler = malloc(sizeof(HidMouseJiggler));
hid_mouse_jiggler->view = view_alloc();
view_set_context(hid_mouse_jiggler->view, hid_mouse_jiggler);
view_allocate_model(
hid_mouse_jiggler->view, ViewModelTypeLocking, sizeof(HidMouseJigglerModel));
view_set_draw_callback(hid_mouse_jiggler->view, hid_mouse_jiggler_draw_callback);
view_set_input_callback(hid_mouse_jiggler->view, hid_mouse_jiggler_input_callback);
view_set_enter_callback(hid_mouse_jiggler->view, hid_mouse_jiggler_enter_callback);
view_set_exit_callback(hid_mouse_jiggler->view, hid_mouse_jiggler_exit_callback);
hid_mouse_jiggler->hid = hid;
hid_mouse_jiggler->timer = furi_timer_alloc(
hid_mouse_jiggler_timer_callback, FuriTimerTypePeriodic, hid_mouse_jiggler);
return hid_mouse_jiggler;
}
void hid_mouse_jiggler_free(HidMouseJiggler* hid_mouse_jiggler) {
furi_assert(hid_mouse_jiggler);
furi_timer_stop(hid_mouse_jiggler->timer);
furi_timer_free(hid_mouse_jiggler->timer);
view_free(hid_mouse_jiggler->view);
free(hid_mouse_jiggler);
}
View* hid_mouse_jiggler_get_view(HidMouseJiggler* hid_mouse_jiggler) {
furi_assert(hid_mouse_jiggler);
return hid_mouse_jiggler->view;
}
void hid_mouse_jiggler_set_connected_status(HidMouseJiggler* hid_mouse_jiggler, bool connected) {
furi_assert(hid_mouse_jiggler);
with_view_model(
hid_mouse_jiggler->view,
HidMouseJigglerModel * model,
{ model->connected = connected; },
true);
}

View File

@@ -0,0 +1,17 @@
#pragma once
#include <gui/view.h>
#define MOUSE_MOVE_SHORT 5
#define MOUSE_MOVE_LONG 20
typedef struct Hid Hid;
typedef struct HidMouseJiggler HidMouseJiggler;
HidMouseJiggler* hid_mouse_jiggler_alloc(Hid* bt_hid);
void hid_mouse_jiggler_free(HidMouseJiggler* hid_mouse_jiggler);
View* hid_mouse_jiggler_get_view(HidMouseJiggler* hid_mouse_jiggler);
void hid_mouse_jiggler_set_connected_status(HidMouseJiggler* hid_mouse_jiggler, bool connected);

View File

@@ -47,47 +47,51 @@ static int32_t music_player_worker_thread_callback(void* context) {
NoteBlockArray_it_t it;
NoteBlockArray_it(it, instance->notes);
if(furi_hal_speaker_acquire(1000)) {
while(instance->should_work) {
if(NoteBlockArray_end_p(it)) {
NoteBlockArray_it(it, instance->notes);
furi_delay_ms(10);
} else {
NoteBlock* note_block = NoteBlockArray_ref(it);
while(instance->should_work) {
if(NoteBlockArray_end_p(it)) {
NoteBlockArray_it(it, instance->notes);
furi_delay_ms(10);
} else {
NoteBlock* note_block = NoteBlockArray_ref(it);
float note_from_a4 = (float)note_block->semitone - NOTE_C4_SEMITONE;
float frequency = NOTE_C4 * powf(TWO_POW_TWELTH_ROOT, note_from_a4);
float duration = 60.0 * furi_kernel_get_tick_frequency() * 4 / instance->bpm /
note_block->duration;
uint32_t dots = note_block->dots;
while(dots > 0) {
duration += duration / 2;
dots--;
}
uint32_t next_tick = furi_get_tick() + duration;
float volume = instance->volume;
float note_from_a4 = (float)note_block->semitone - NOTE_C4_SEMITONE;
float frequency = NOTE_C4 * powf(TWO_POW_TWELTH_ROOT, note_from_a4);
float duration =
60.0 * furi_kernel_get_tick_frequency() * 4 / instance->bpm / note_block->duration;
uint32_t dots = note_block->dots;
while(dots > 0) {
duration += duration / 2;
dots--;
if(instance->callback) {
instance->callback(
note_block->semitone,
note_block->dots,
note_block->duration,
0.0,
instance->callback_context);
}
furi_hal_speaker_stop();
furi_hal_speaker_start(frequency, volume);
while(instance->should_work && furi_get_tick() < next_tick) {
volume *= 0.9945679;
furi_hal_speaker_set_volume(volume);
furi_delay_ms(2);
}
NoteBlockArray_next(it);
}
uint32_t next_tick = furi_get_tick() + duration;
float volume = instance->volume;
if(instance->callback) {
instance->callback(
note_block->semitone,
note_block->dots,
note_block->duration,
0.0,
instance->callback_context);
}
furi_hal_speaker_stop();
furi_hal_speaker_start(frequency, volume);
while(instance->should_work && furi_get_tick() < next_tick) {
volume *= 0.9945679;
furi_hal_speaker_set_volume(volume);
furi_delay_ms(2);
}
NoteBlockArray_next(it);
}
}
furi_hal_speaker_stop();
furi_hal_speaker_stop();
furi_hal_speaker_release();
} else {
FURI_LOG_E(TAG, "Speaker system is busy with another process.");
}
return 0;
}

View File

@@ -10,6 +10,7 @@ enum UsbDebugSubmenuIndex {
UsbHidSubmenuIndexKeyboard,
UsbHidSubmenuIndexMedia,
UsbHidSubmenuIndexMouse,
UsbHidSubmenuIndexMouseJiggler,
};
void usb_hid_submenu_callback(void* context, uint32_t index) {
@@ -27,6 +28,9 @@ void usb_hid_submenu_callback(void* context, uint32_t index) {
} else if(index == UsbHidSubmenuIndexMouse) {
app->view_id = UsbHidViewMouse;
view_dispatcher_switch_to_view(app->view_dispatcher, UsbHidViewMouse);
} else if(index == UsbHidSubmenuIndexMouseJiggler) {
app->view_id = UsbHidViewMouseJiggler;
view_dispatcher_switch_to_view(app->view_dispatcher, UsbHidViewMouseJiggler);
}
}
@@ -76,6 +80,12 @@ UsbHid* usb_hid_app_alloc() {
app->submenu, "Media", UsbHidSubmenuIndexMedia, usb_hid_submenu_callback, app);
submenu_add_item(
app->submenu, "Mouse", UsbHidSubmenuIndexMouse, usb_hid_submenu_callback, app);
submenu_add_item(
app->submenu,
"Mouse Jiggler",
UsbHidSubmenuIndexMouseJiggler,
usb_hid_submenu_callback,
app);
view_set_previous_callback(submenu_get_view(app->submenu), usb_hid_exit);
view_dispatcher_add_view(
app->view_dispatcher, UsbHidViewSubmenu, submenu_get_view(app->submenu));
@@ -121,6 +131,15 @@ UsbHid* usb_hid_app_alloc() {
view_dispatcher_add_view(
app->view_dispatcher, UsbHidViewMouse, usb_hid_mouse_get_view(app->usb_hid_mouse));
// Mouse jiggler view
app->hid_mouse_jiggler = hid_mouse_jiggler_alloc(app);
view_set_previous_callback(
hid_mouse_jiggler_get_view(app->hid_mouse_jiggler), usb_hid_exit_confirm_view);
view_dispatcher_add_view(
app->view_dispatcher,
UsbHidViewMouseJiggler,
hid_mouse_jiggler_get_view(app->hid_mouse_jiggler));
// TODO switch to menu after Media is done
app->view_id = UsbHidViewSubmenu;
view_dispatcher_switch_to_view(app->view_dispatcher, app->view_id);
@@ -147,6 +166,8 @@ void usb_hid_app_free(UsbHid* app) {
usb_hid_media_free(app->usb_hid_media);
view_dispatcher_remove_view(app->view_dispatcher, UsbHidViewMouse);
usb_hid_mouse_free(app->usb_hid_mouse);
view_dispatcher_remove_view(app->view_dispatcher, UsbHidViewMouseJiggler);
hid_mouse_jiggler_free(app->hid_mouse_jiggler);
view_dispatcher_free(app->view_dispatcher);
// Close records
furi_record_close(RECORD_GUI);

View File

@@ -12,6 +12,7 @@
#include "views/usb_hid_keyboard.h"
#include "views/usb_hid_media.h"
#include "views/usb_hid_mouse.h"
#include "views/usb_hid_mouse_jiggler.h"
typedef struct {
Gui* gui;
@@ -23,6 +24,7 @@ typedef struct {
UsbHidKeyboard* usb_hid_keyboard;
UsbHidMedia* usb_hid_media;
UsbHidMouse* usb_hid_mouse;
HidMouseJiggler* hid_mouse_jiggler;
uint32_t view_id;
} UsbHid;
@@ -32,5 +34,6 @@ typedef enum {
UsbHidViewKeyboard,
UsbHidViewMedia,
UsbHidViewMouse,
UsbHidViewMouseJiggler,
UsbHidViewExitConfirm,
} UsbHidView;

View File

@@ -0,0 +1,130 @@
#include "usb_hid_mouse_jiggler.h"
#include <furi.h>
#include <furi_hal_usb_hid.h>
#include <gui/elements.h>
#include <USB_Keyboard_icons.h>
#define TAG "HidMouseJiggler"
struct HidMouseJiggler {
View* view;
FuriTimer* timer;
};
typedef struct {
bool running;
uint8_t counter;
} HidMouseJigglerModel;
static void hid_mouse_jiggler_draw_callback(Canvas* canvas, void* context) {
furi_assert(context);
HidMouseJigglerModel* model = context;
// Header
canvas_set_font(canvas, FontPrimary);
elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Mouse Jiggler");
canvas_set_font(canvas, FontPrimary);
elements_multiline_text(canvas, AlignLeft, 35, "Press Start\nto jiggle");
canvas_set_font(canvas, FontSecondary);
// Ok
canvas_draw_icon(canvas, 63, 25, &I_Space_65x18);
if(model->running) {
elements_slightly_rounded_box(canvas, 66, 27, 60, 13);
canvas_set_color(canvas, ColorWhite);
}
canvas_draw_icon(canvas, 74, 29, &I_Ok_btn_9x9);
if(model->running) {
elements_multiline_text_aligned(canvas, 91, 36, AlignLeft, AlignBottom, "Stop");
} else {
elements_multiline_text_aligned(canvas, 91, 36, AlignLeft, AlignBottom, "Start");
}
canvas_set_color(canvas, ColorBlack);
// Back
canvas_draw_icon(canvas, 74, 49, &I_Pin_back_arrow_10x8);
elements_multiline_text_aligned(canvas, 91, 57, AlignLeft, AlignBottom, "Quit");
}
static void hid_mouse_jiggler_timer_callback(void* context) {
furi_assert(context);
HidMouseJiggler* hid_mouse_jiggler = context;
with_view_model(
hid_mouse_jiggler->view,
HidMouseJigglerModel * model,
{
if(model->running) {
model->counter++;
furi_hal_hid_mouse_move(
(model->counter % 2 == 0) ? MOUSE_MOVE_SHORT : -MOUSE_MOVE_SHORT, 0);
}
},
false);
}
static void hid_mouse_jiggler_enter_callback(void* context) {
furi_assert(context);
HidMouseJiggler* hid_mouse_jiggler = context;
furi_timer_start(hid_mouse_jiggler->timer, 500);
}
static void hid_mouse_jiggler_exit_callback(void* context) {
furi_assert(context);
HidMouseJiggler* hid_mouse_jiggler = context;
furi_timer_stop(hid_mouse_jiggler->timer);
}
static bool hid_mouse_jiggler_input_callback(InputEvent* event, void* context) {
furi_assert(context);
HidMouseJiggler* hid_mouse_jiggler = context;
bool consumed = false;
if(event->key == InputKeyOk) {
with_view_model(
hid_mouse_jiggler->view,
HidMouseJigglerModel * model,
{ model->running = !model->running; },
true);
consumed = true;
}
return consumed;
}
HidMouseJiggler* hid_mouse_jiggler_alloc() {
HidMouseJiggler* hid_mouse_jiggler = malloc(sizeof(HidMouseJiggler));
hid_mouse_jiggler->view = view_alloc();
view_set_context(hid_mouse_jiggler->view, hid_mouse_jiggler);
view_allocate_model(
hid_mouse_jiggler->view, ViewModelTypeLocking, sizeof(HidMouseJigglerModel));
view_set_draw_callback(hid_mouse_jiggler->view, hid_mouse_jiggler_draw_callback);
view_set_input_callback(hid_mouse_jiggler->view, hid_mouse_jiggler_input_callback);
view_set_enter_callback(hid_mouse_jiggler->view, hid_mouse_jiggler_enter_callback);
view_set_exit_callback(hid_mouse_jiggler->view, hid_mouse_jiggler_exit_callback);
hid_mouse_jiggler->timer = furi_timer_alloc(
hid_mouse_jiggler_timer_callback, FuriTimerTypePeriodic, hid_mouse_jiggler);
return hid_mouse_jiggler;
}
void hid_mouse_jiggler_free(HidMouseJiggler* hid_mouse_jiggler) {
furi_assert(hid_mouse_jiggler);
furi_timer_stop(hid_mouse_jiggler->timer);
furi_timer_free(hid_mouse_jiggler->timer);
view_free(hid_mouse_jiggler->view);
free(hid_mouse_jiggler);
}
View* hid_mouse_jiggler_get_view(HidMouseJiggler* hid_mouse_jiggler) {
furi_assert(hid_mouse_jiggler);
return hid_mouse_jiggler->view;
}

View File

@@ -0,0 +1,14 @@
#pragma once
#include <gui/view.h>
#define MOUSE_MOVE_SHORT 5
#define MOUSE_MOVE_LONG 20
typedef struct HidMouseJiggler HidMouseJiggler;
HidMouseJiggler* hid_mouse_jiggler_alloc();
void hid_mouse_jiggler_free(HidMouseJiggler* hid_mouse_jiggler);
View* hid_mouse_jiggler_get_view(HidMouseJiggler* hid_mouse_jiggler);

View File

@@ -3,7 +3,7 @@
#include <furi.h>
#include <furi_hal.h>
#define WS_VERSION_APP "0.5"
#define WS_VERSION_APP "0.6"
#define WS_DEVELOPED "SkorP"
#define WS_GITHUB "https://github.com/flipperdevices/flipperzero-firmware"

View File

@@ -135,6 +135,10 @@ static void ws_protocol_nexus_th_remote_controller(WSBlockGeneric* instance) {
}
instance->humidity = instance->data & 0xFF;
if(instance->humidity > 95)
instance->humidity = 95;
else if(instance->humidity < 20)
instance->humidity = 20;
}
void ws_protocol_decoder_nexus_th_feed(void* context, bool level, uint32_t duration) {

View File

@@ -0,0 +1,331 @@
#include "oregon_v1.h"
#include <lib/toolbox/manchester_decoder.h>
#define TAG "WSProtocolOregon_V1"
/*
* Help
* https://github.dev/merbanan/rtl_433/blob/bb1be7f186ac0fdb7dc5d77693847d96fb95281e/src/devices/oregon_scientific_v1.c
*
* OSv1 protocol.
*
* MC with nominal bit width of 2930 us.
* Pulses are somewhat longer than nominal half-bit width, 1748 us / 3216 us,
* Gaps are somewhat shorter than nominal half-bit width, 1176 us / 2640 us.
* After 12 preamble bits there is 4200 us gap, 5780 us pulse, 5200 us gap.
* And next 32 bit data
*
* Care must be taken with the gap after the sync pulse since it
* is outside of the normal clocking. Because of this a data stream
* beginning with a 0 will have data in this gap.
*
*
* Data is in reverse order of bits
* RevBit(data32bit)=> tib23atad
*
* tib23atad => xxxxxxxx | busuTTTT | ttttzzzz | ccuuiiii
*
* - i: ID
* - x: CRC;
* - u: unknown;
* - b: battery low; flag to indicate low battery voltage
* - s: temperature sign
* - T: BCD, Temperature; in <20>C * 10
* - t: BCD, Temperature; in <20>C * 1
* - z: BCD, Temperature; in <20>C * 0.1
* - c: Channel 00=CH1, 01=CH2, 10=CH3
*
*/
#define OREGON_V1_HEADER_OK 0xFF
static const SubGhzBlockConst ws_protocol_oregon_v1_const = {
.te_short = 1465,
.te_long = 2930,
.te_delta = 350,
.min_count_bit_for_found = 32,
};
struct WSProtocolDecoderOregon_V1 {
SubGhzProtocolDecoderBase base;
SubGhzBlockDecoder decoder;
WSBlockGeneric generic;
ManchesterState manchester_state;
uint16_t header_count;
uint8_t first_bit;
};
struct WSProtocolEncoderOregon_V1 {
SubGhzProtocolEncoderBase base;
SubGhzProtocolBlockEncoder encoder;
WSBlockGeneric generic;
};
typedef enum {
Oregon_V1DecoderStepReset = 0,
Oregon_V1DecoderStepFoundPreamble,
Oregon_V1DecoderStepParse,
} Oregon_V1DecoderStep;
const SubGhzProtocolDecoder ws_protocol_oregon_v1_decoder = {
.alloc = ws_protocol_decoder_oregon_v1_alloc,
.free = ws_protocol_decoder_oregon_v1_free,
.feed = ws_protocol_decoder_oregon_v1_feed,
.reset = ws_protocol_decoder_oregon_v1_reset,
.get_hash_data = ws_protocol_decoder_oregon_v1_get_hash_data,
.serialize = ws_protocol_decoder_oregon_v1_serialize,
.deserialize = ws_protocol_decoder_oregon_v1_deserialize,
.get_string = ws_protocol_decoder_oregon_v1_get_string,
};
const SubGhzProtocolEncoder ws_protocol_oregon_v1_encoder = {
.alloc = NULL,
.free = NULL,
.deserialize = NULL,
.stop = NULL,
.yield = NULL,
};
const SubGhzProtocol ws_protocol_oregon_v1 = {
.name = WS_PROTOCOL_OREGON_V1_NAME,
.type = SubGhzProtocolWeatherStation,
.flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 |
SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable,
.decoder = &ws_protocol_oregon_v1_decoder,
.encoder = &ws_protocol_oregon_v1_encoder,
};
void* ws_protocol_decoder_oregon_v1_alloc(SubGhzEnvironment* environment) {
UNUSED(environment);
WSProtocolDecoderOregon_V1* instance = malloc(sizeof(WSProtocolDecoderOregon_V1));
instance->base.protocol = &ws_protocol_oregon_v1;
instance->generic.protocol_name = instance->base.protocol->name;
return instance;
}
void ws_protocol_decoder_oregon_v1_free(void* context) {
furi_assert(context);
WSProtocolDecoderOregon_V1* instance = context;
free(instance);
}
void ws_protocol_decoder_oregon_v1_reset(void* context) {
furi_assert(context);
WSProtocolDecoderOregon_V1* instance = context;
instance->decoder.parser_step = Oregon_V1DecoderStepReset;
}
static bool ws_protocol_oregon_v1_check(WSProtocolDecoderOregon_V1* instance) {
if(!instance->decoder.decode_data) return false;
uint64_t data = subghz_protocol_blocks_reverse_key(instance->decoder.decode_data, 32);
uint16_t crc = (data & 0xff) + ((data >> 8) & 0xff) + ((data >> 16) & 0xff);
crc = (crc & 0xff) + ((crc >> 8) & 0xff);
return (crc == ((data >> 24) & 0xFF));
}
/**
* Analysis of received data
* @param instance Pointer to a WSBlockGeneric* instance
*/
static void ws_protocol_oregon_v1_remote_controller(WSBlockGeneric* instance) {
uint64_t data = subghz_protocol_blocks_reverse_key(instance->data, 32);
instance->id = data & 0xFF;
instance->channel = ((data >> 6) & 0x03) + 1;
float temp_raw =
((data >> 8) & 0x0F) * 0.1f + ((data >> 12) & 0x0F) + ((data >> 16) & 0x0F) * 10.0f;
if(!((data >> 21) & 1)) {
instance->temp = temp_raw;
} else {
instance->temp = -temp_raw;
}
instance->battery_low = !(instance->data >> 23) & 1;
instance->btn = WS_NO_BTN;
instance->humidity = WS_NO_HUMIDITY;
}
void ws_protocol_decoder_oregon_v1_feed(void* context, bool level, uint32_t duration) {
furi_assert(context);
WSProtocolDecoderOregon_V1* instance = context;
ManchesterEvent event = ManchesterEventReset;
switch(instance->decoder.parser_step) {
case Oregon_V1DecoderStepReset:
if((level) && (DURATION_DIFF(duration, ws_protocol_oregon_v1_const.te_short) <
ws_protocol_oregon_v1_const.te_delta)) {
instance->decoder.parser_step = Oregon_V1DecoderStepFoundPreamble;
instance->decoder.te_last = duration;
instance->header_count = 0;
}
break;
case Oregon_V1DecoderStepFoundPreamble:
if(level) {
//keep high levels, if they suit our durations
if((DURATION_DIFF(duration, ws_protocol_oregon_v1_const.te_short) <
ws_protocol_oregon_v1_const.te_delta) ||
(DURATION_DIFF(duration, ws_protocol_oregon_v1_const.te_short * 4) <
ws_protocol_oregon_v1_const.te_delta)) {
instance->decoder.te_last = duration;
} else {
instance->decoder.parser_step = Oregon_V1DecoderStepReset;
}
} else if(
//checking low levels
(DURATION_DIFF(duration, ws_protocol_oregon_v1_const.te_short) <
ws_protocol_oregon_v1_const.te_delta) &&
(DURATION_DIFF(instance->decoder.te_last, ws_protocol_oregon_v1_const.te_short) <
ws_protocol_oregon_v1_const.te_delta)) {
// Found header
instance->header_count++;
} else if(
(DURATION_DIFF(duration, ws_protocol_oregon_v1_const.te_short * 3) <
ws_protocol_oregon_v1_const.te_delta) &&
(DURATION_DIFF(instance->decoder.te_last, ws_protocol_oregon_v1_const.te_short) <
ws_protocol_oregon_v1_const.te_delta)) {
// check header
if(instance->header_count > 7) {
instance->header_count = OREGON_V1_HEADER_OK;
}
} else if(
(instance->header_count == OREGON_V1_HEADER_OK) &&
(DURATION_DIFF(instance->decoder.te_last, ws_protocol_oregon_v1_const.te_short * 4) <
ws_protocol_oregon_v1_const.te_delta)) {
//found all the necessary patterns
instance->decoder.decode_data = 0;
instance->decoder.decode_count_bit = 1;
manchester_advance(
instance->manchester_state,
ManchesterEventReset,
&instance->manchester_state,
NULL);
instance->decoder.parser_step = Oregon_V1DecoderStepParse;
if(duration < ws_protocol_oregon_v1_const.te_short * 4) {
instance->first_bit = 1;
} else {
instance->first_bit = 0;
}
} else {
instance->decoder.parser_step = Oregon_V1DecoderStepReset;
}
break;
case Oregon_V1DecoderStepParse:
if(level) {
if(DURATION_DIFF(duration, ws_protocol_oregon_v1_const.te_short) <
ws_protocol_oregon_v1_const.te_delta) {
event = ManchesterEventShortHigh;
} else if(
DURATION_DIFF(duration, ws_protocol_oregon_v1_const.te_long) <
ws_protocol_oregon_v1_const.te_delta) {
event = ManchesterEventLongHigh;
} else {
instance->decoder.parser_step = Oregon_V1DecoderStepReset;
}
} else {
if(DURATION_DIFF(duration, ws_protocol_oregon_v1_const.te_short) <
ws_protocol_oregon_v1_const.te_delta) {
event = ManchesterEventShortLow;
} else if(
DURATION_DIFF(duration, ws_protocol_oregon_v1_const.te_long) <
ws_protocol_oregon_v1_const.te_delta) {
event = ManchesterEventLongLow;
} else if(duration >= ((uint32_t)ws_protocol_oregon_v1_const.te_long * 2)) {
if(instance->decoder.decode_count_bit ==
ws_protocol_oregon_v1_const.min_count_bit_for_found) {
if(instance->first_bit) {
instance->decoder.decode_data = ~instance->decoder.decode_data | (1 << 31);
}
if(ws_protocol_oregon_v1_check(instance)) {
instance->generic.data = instance->decoder.decode_data;
instance->generic.data_count_bit = instance->decoder.decode_count_bit;
ws_protocol_oregon_v1_remote_controller(&instance->generic);
if(instance->base.callback)
instance->base.callback(&instance->base, instance->base.context);
}
}
instance->decoder.decode_data = 0;
instance->decoder.decode_count_bit = 0;
manchester_advance(
instance->manchester_state,
ManchesterEventReset,
&instance->manchester_state,
NULL);
} else {
instance->decoder.parser_step = Oregon_V1DecoderStepReset;
}
}
if(event != ManchesterEventReset) {
bool data;
bool data_ok = manchester_advance(
instance->manchester_state, event, &instance->manchester_state, &data);
if(data_ok) {
instance->decoder.decode_data = (instance->decoder.decode_data << 1) | !data;
instance->decoder.decode_count_bit++;
}
}
break;
}
}
uint8_t ws_protocol_decoder_oregon_v1_get_hash_data(void* context) {
furi_assert(context);
WSProtocolDecoderOregon_V1* instance = context;
return subghz_protocol_blocks_get_hash_data(
&instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
}
bool ws_protocol_decoder_oregon_v1_serialize(
void* context,
FlipperFormat* flipper_format,
SubGhzRadioPreset* preset) {
furi_assert(context);
WSProtocolDecoderOregon_V1* instance = context;
return ws_block_generic_serialize(&instance->generic, flipper_format, preset);
}
bool ws_protocol_decoder_oregon_v1_deserialize(void* context, FlipperFormat* flipper_format) {
furi_assert(context);
WSProtocolDecoderOregon_V1* instance = context;
bool ret = false;
do {
if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) {
break;
}
if(instance->generic.data_count_bit !=
ws_protocol_oregon_v1_const.min_count_bit_for_found) {
FURI_LOG_E(TAG, "Wrong number of bits in key");
break;
}
ret = true;
} while(false);
return ret;
}
void ws_protocol_decoder_oregon_v1_get_string(void* context, FuriString* output) {
furi_assert(context);
WSProtocolDecoderOregon_V1* instance = context;
furi_string_printf(
output,
"%s %dbit\r\n"
"Key:0x%lX%08lX\r\n"
"Sn:0x%lX Ch:%d Bat:%d\r\n"
"Temp:%3.1f C Hum:%d%%",
instance->generic.protocol_name,
instance->generic.data_count_bit,
(uint32_t)(instance->generic.data >> 32),
(uint32_t)(instance->generic.data),
instance->generic.id,
instance->generic.channel,
instance->generic.battery_low,
(double)instance->generic.temp,
instance->generic.humidity);
}

View File

@@ -0,0 +1,79 @@
#pragma once
#include <lib/subghz/protocols/base.h>
#include <lib/subghz/blocks/const.h>
#include <lib/subghz/blocks/decoder.h>
#include <lib/subghz/blocks/encoder.h>
#include "ws_generic.h"
#include <lib/subghz/blocks/math.h>
#define WS_PROTOCOL_OREGON_V1_NAME "Oregon-v1"
typedef struct WSProtocolDecoderOregon_V1 WSProtocolDecoderOregon_V1;
typedef struct WSProtocolEncoderOregon_V1 WSProtocolEncoderOregon_V1;
extern const SubGhzProtocolDecoder ws_protocol_oregon_v1_decoder;
extern const SubGhzProtocolEncoder ws_protocol_oregon_v1_encoder;
extern const SubGhzProtocol ws_protocol_oregon_v1;
/**
* Allocate WSProtocolDecoderOregon_V1.
* @param environment Pointer to a SubGhzEnvironment instance
* @return WSProtocolDecoderOregon_V1* pointer to a WSProtocolDecoderOregon_V1 instance
*/
void* ws_protocol_decoder_oregon_v1_alloc(SubGhzEnvironment* environment);
/**
* Free WSProtocolDecoderOregon_V1.
* @param context Pointer to a WSProtocolDecoderOregon_V1 instance
*/
void ws_protocol_decoder_oregon_v1_free(void* context);
/**
* Reset decoder WSProtocolDecoderOregon_V1.
* @param context Pointer to a WSProtocolDecoderOregon_V1 instance
*/
void ws_protocol_decoder_oregon_v1_reset(void* context);
/**
* Parse a raw sequence of levels and durations received from the air.
* @param context Pointer to a WSProtocolDecoderOregon_V1 instance
* @param level Signal level true-high false-low
* @param duration Duration of this level in, us
*/
void ws_protocol_decoder_oregon_v1_feed(void* context, bool level, uint32_t duration);
/**
* Getting the hash sum of the last randomly received parcel.
* @param context Pointer to a WSProtocolDecoderOregon_V1 instance
* @return hash Hash sum
*/
uint8_t ws_protocol_decoder_oregon_v1_get_hash_data(void* context);
/**
* Serialize data WSProtocolDecoderOregon_V1.
* @param context Pointer to a WSProtocolDecoderOregon_V1 instance
* @param flipper_format Pointer to a FlipperFormat instance
* @param preset The modulation on which the signal was received, SubGhzRadioPreset
* @return true On success
*/
bool ws_protocol_decoder_oregon_v1_serialize(
void* context,
FlipperFormat* flipper_format,
SubGhzRadioPreset* preset);
/**
* Deserialize data WSProtocolDecoderOregon_V1.
* @param context Pointer to a WSProtocolDecoderOregon_V1 instance
* @param flipper_format Pointer to a FlipperFormat instance
* @return true On success
*/
bool ws_protocol_decoder_oregon_v1_deserialize(void* context, FlipperFormat* flipper_format);
/**
* Getting a textual representation of the received data.
* @param context Pointer to a WSProtocolDecoderOregon_V1 instance
* @param output Resulting text
*/
void ws_protocol_decoder_oregon_v1_get_string(void* context, FuriString* output);

View File

@@ -13,6 +13,8 @@ const SubGhzProtocol* weather_station_protocol_registry_items[] = {
&ws_protocol_acurite_592txr,
&ws_protocol_ambient_weather,
&ws_protocol_auriol_th,
&ws_protocol_oregon_v1,
&ws_protocol_tx_8300,
};
const SubGhzProtocolRegistry weather_station_protocol_registry = {

View File

@@ -13,5 +13,7 @@
#include "acurite_592txr.h"
#include "ambient_weather.h"
#include "auriol_hg0601a.h"
#include "oregon_v1.h"
#include "tx_8300.h"
extern const SubGhzProtocolRegistry weather_station_protocol_registry;

View File

@@ -0,0 +1,293 @@
#include "tx_8300.h"
#define TAG "WSProtocolTX_8300"
/*
* Help
* https://github.com/merbanan/rtl_433/blob/master/src/devices/ambientweather_tx8300.c
*
* Ambient Weather TX-8300 (also sold as TFA 30.3211.02).
* 1970us pulse with variable gap (third pulse 3920 us).
* Above 79% humidity, gap after third pulse is 5848 us.
* - Bit 1 : 1970us pulse with 3888 us gap
* - Bit 0 : 1970us pulse with 1936 us gap
* 74 bit (2 bit preamble and 72 bit data => 9 bytes => 18 nibbles)
* The preamble seems to be a repeat counter (00, and 01 seen),
* the first 4 bytes are data,
* the second 4 bytes the same data inverted,
* the last byte is a checksum.
* Preamble format (2 bits):
* [1 bit (0)] [1 bit rolling count]
* Payload format (32 bits):
* HHHHhhhh ??CCNIII IIIITTTT ttttuuuu
* - H = First BCD digit humidity (the MSB might be distorted by the demod)
* - h = Second BCD digit humidity, invalid humidity seems to be 0x0e
* - ? = Likely battery flag, 2 bits
* - C = Channel, 2 bits
* - N = Negative temperature sign bit
* - I = ID, 7-bit
* - T = First BCD digit temperature
* - t = Second BCD digit temperature
* - u = Third BCD digit temperature
* The Checksum seems to covers the 4 data bytes and is something like Fletcher-8.
**/
#define TX_8300_PACKAGE_SIZE 32
static const SubGhzBlockConst ws_protocol_tx_8300_const = {
.te_short = 1940,
.te_long = 3880,
.te_delta = 250,
.min_count_bit_for_found = 72,
};
struct WSProtocolDecoderTX_8300 {
SubGhzProtocolDecoderBase base;
SubGhzBlockDecoder decoder;
WSBlockGeneric generic;
uint32_t package_1;
uint32_t package_2;
};
struct WSProtocolEncoderTX_8300 {
SubGhzProtocolEncoderBase base;
SubGhzProtocolBlockEncoder encoder;
WSBlockGeneric generic;
};
typedef enum {
TX_8300DecoderStepReset = 0,
TX_8300DecoderStepCheckPreambule,
TX_8300DecoderStepSaveDuration,
TX_8300DecoderStepCheckDuration,
} TX_8300DecoderStep;
const SubGhzProtocolDecoder ws_protocol_tx_8300_decoder = {
.alloc = ws_protocol_decoder_tx_8300_alloc,
.free = ws_protocol_decoder_tx_8300_free,
.feed = ws_protocol_decoder_tx_8300_feed,
.reset = ws_protocol_decoder_tx_8300_reset,
.get_hash_data = ws_protocol_decoder_tx_8300_get_hash_data,
.serialize = ws_protocol_decoder_tx_8300_serialize,
.deserialize = ws_protocol_decoder_tx_8300_deserialize,
.get_string = ws_protocol_decoder_tx_8300_get_string,
};
const SubGhzProtocolEncoder ws_protocol_tx_8300_encoder = {
.alloc = NULL,
.free = NULL,
.deserialize = NULL,
.stop = NULL,
.yield = NULL,
};
const SubGhzProtocol ws_protocol_tx_8300 = {
.name = WS_PROTOCOL_TX_8300_NAME,
.type = SubGhzProtocolWeatherStation,
.flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 |
SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable,
.decoder = &ws_protocol_tx_8300_decoder,
.encoder = &ws_protocol_tx_8300_encoder,
};
void* ws_protocol_decoder_tx_8300_alloc(SubGhzEnvironment* environment) {
UNUSED(environment);
WSProtocolDecoderTX_8300* instance = malloc(sizeof(WSProtocolDecoderTX_8300));
instance->base.protocol = &ws_protocol_tx_8300;
instance->generic.protocol_name = instance->base.protocol->name;
return instance;
}
void ws_protocol_decoder_tx_8300_free(void* context) {
furi_assert(context);
WSProtocolDecoderTX_8300* instance = context;
free(instance);
}
void ws_protocol_decoder_tx_8300_reset(void* context) {
furi_assert(context);
WSProtocolDecoderTX_8300* instance = context;
instance->decoder.parser_step = TX_8300DecoderStepReset;
}
static bool ws_protocol_tx_8300_check_crc(WSProtocolDecoderTX_8300* instance) {
if(!instance->package_2) return false;
if(instance->package_1 != ~instance->package_2) return false;
uint16_t x = 0;
uint16_t y = 0;
for(int i = 0; i < 32; i += 4) {
x += (instance->package_1 >> i) & 0x0F;
y += (instance->package_1 >> i) & 0x05;
}
uint8_t crc = (~x & 0xF) << 4 | (~y & 0xF);
return (crc == ((instance->decoder.decode_data) & 0xFF));
}
/**
* Analysis of received data
* @param instance Pointer to a WSBlockGeneric* instance
*/
static void ws_protocol_tx_8300_remote_controller(WSBlockGeneric* instance) {
instance->humidity = (((instance->data >> 28) & 0x0F) * 10) + ((instance->data >> 24) & 0x0F);
instance->btn = WS_NO_BTN;
if(!((instance->data >> 22) & 0x03))
instance->battery_low = 0;
else
instance->battery_low = 1;
instance->channel = (instance->data >> 20) & 0x03;
instance->id = (instance->data >> 12) & 0x7F;
float temp_raw = ((instance->data >> 8) & 0x0F) * 10.0f + ((instance->data >> 4) & 0x0F) +
(instance->data & 0x0F) * 0.1f;
if(!((instance->data >> 19) & 1)) {
instance->temp = temp_raw;
} else {
instance->temp = -temp_raw;
}
}
void ws_protocol_decoder_tx_8300_feed(void* context, bool level, uint32_t duration) {
furi_assert(context);
WSProtocolDecoderTX_8300* instance = context;
switch(instance->decoder.parser_step) {
case TX_8300DecoderStepReset:
if((level) && (DURATION_DIFF(duration, ws_protocol_tx_8300_const.te_short * 2) <
ws_protocol_tx_8300_const.te_delta)) {
instance->decoder.parser_step = TX_8300DecoderStepCheckPreambule;
}
break;
case TX_8300DecoderStepCheckPreambule:
if((!level) && ((DURATION_DIFF(duration, ws_protocol_tx_8300_const.te_short * 2) <
ws_protocol_tx_8300_const.te_delta) ||
(DURATION_DIFF(duration, ws_protocol_tx_8300_const.te_short * 3) <
ws_protocol_tx_8300_const.te_delta))) {
instance->decoder.parser_step = TX_8300DecoderStepSaveDuration;
instance->decoder.decode_data = 0;
instance->decoder.decode_count_bit = 1;
instance->package_1 = 0;
instance->package_2 = 0;
} else {
instance->decoder.parser_step = TX_8300DecoderStepReset;
}
break;
case TX_8300DecoderStepSaveDuration:
if(level) {
instance->decoder.te_last = duration;
instance->decoder.parser_step = TX_8300DecoderStepCheckDuration;
} else {
instance->decoder.parser_step = TX_8300DecoderStepReset;
}
break;
case TX_8300DecoderStepCheckDuration:
if(!level) {
if(duration >= ((uint32_t)ws_protocol_tx_8300_const.te_short * 5)) {
//Found syncPostfix
if((instance->decoder.decode_count_bit ==
ws_protocol_tx_8300_const.min_count_bit_for_found) &&
ws_protocol_tx_8300_check_crc(instance)) {
instance->generic.data = instance->package_1;
instance->generic.data_count_bit = instance->decoder.decode_count_bit;
ws_protocol_tx_8300_remote_controller(&instance->generic);
if(instance->base.callback)
instance->base.callback(&instance->base, instance->base.context);
}
instance->decoder.decode_data = 0;
instance->decoder.decode_count_bit = 1;
instance->decoder.parser_step = TX_8300DecoderStepReset;
break;
} else if(
(DURATION_DIFF(instance->decoder.te_last, ws_protocol_tx_8300_const.te_short) <
ws_protocol_tx_8300_const.te_delta) &&
(DURATION_DIFF(duration, ws_protocol_tx_8300_const.te_long) <
ws_protocol_tx_8300_const.te_delta * 2)) {
subghz_protocol_blocks_add_bit(&instance->decoder, 1);
instance->decoder.parser_step = TX_8300DecoderStepSaveDuration;
} else if(
(DURATION_DIFF(instance->decoder.te_last, ws_protocol_tx_8300_const.te_short) <
ws_protocol_tx_8300_const.te_delta) &&
(DURATION_DIFF(duration, ws_protocol_tx_8300_const.te_short) <
ws_protocol_tx_8300_const.te_delta)) {
subghz_protocol_blocks_add_bit(&instance->decoder, 0);
instance->decoder.parser_step = TX_8300DecoderStepSaveDuration;
} else {
instance->decoder.parser_step = TX_8300DecoderStepReset;
}
if(instance->decoder.decode_count_bit == TX_8300_PACKAGE_SIZE) {
instance->package_1 = instance->decoder.decode_data;
instance->decoder.decode_data = 0;
} else if(instance->decoder.decode_count_bit == TX_8300_PACKAGE_SIZE * 2) {
instance->package_2 = instance->decoder.decode_data;
instance->decoder.decode_data = 0;
}
} else {
instance->decoder.parser_step = TX_8300DecoderStepReset;
}
break;
}
}
uint8_t ws_protocol_decoder_tx_8300_get_hash_data(void* context) {
furi_assert(context);
WSProtocolDecoderTX_8300* instance = context;
return subghz_protocol_blocks_get_hash_data(
&instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
}
bool ws_protocol_decoder_tx_8300_serialize(
void* context,
FlipperFormat* flipper_format,
SubGhzRadioPreset* preset) {
furi_assert(context);
WSProtocolDecoderTX_8300* instance = context;
return ws_block_generic_serialize(&instance->generic, flipper_format, preset);
}
bool ws_protocol_decoder_tx_8300_deserialize(void* context, FlipperFormat* flipper_format) {
furi_assert(context);
WSProtocolDecoderTX_8300* instance = context;
bool ret = false;
do {
if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) {
break;
}
if(instance->generic.data_count_bit != ws_protocol_tx_8300_const.min_count_bit_for_found) {
FURI_LOG_E(TAG, "Wrong number of bits in key");
break;
}
ret = true;
} while(false);
return ret;
}
void ws_protocol_decoder_tx_8300_get_string(void* context, FuriString* output) {
furi_assert(context);
WSProtocolDecoderTX_8300* instance = context;
furi_string_printf(
output,
"%s %dbit\r\n"
"Key:0x%lX%08lX\r\n"
"Sn:0x%lX Ch:%d Bat:%d\r\n"
"Temp:%3.1f C Hum:%d%%",
instance->generic.protocol_name,
instance->generic.data_count_bit,
(uint32_t)(instance->generic.data >> 32),
(uint32_t)(instance->generic.data),
instance->generic.id,
instance->generic.channel,
instance->generic.battery_low,
(double)instance->generic.temp,
instance->generic.humidity);
}

View File

@@ -0,0 +1,79 @@
#pragma once
#include <lib/subghz/protocols/base.h>
#include <lib/subghz/blocks/const.h>
#include <lib/subghz/blocks/decoder.h>
#include <lib/subghz/blocks/encoder.h>
#include "ws_generic.h"
#include <lib/subghz/blocks/math.h>
#define WS_PROTOCOL_TX_8300_NAME "TX8300"
typedef struct WSProtocolDecoderTX_8300 WSProtocolDecoderTX_8300;
typedef struct WSProtocolEncoderTX_8300 WSProtocolEncoderTX_8300;
extern const SubGhzProtocolDecoder ws_protocol_tx_8300_decoder;
extern const SubGhzProtocolEncoder ws_protocol_tx_8300_encoder;
extern const SubGhzProtocol ws_protocol_tx_8300;
/**
* Allocate WSProtocolDecoderTX_8300.
* @param environment Pointer to a SubGhzEnvironment instance
* @return WSProtocolDecoderTX_8300* pointer to a WSProtocolDecoderTX_8300 instance
*/
void* ws_protocol_decoder_tx_8300_alloc(SubGhzEnvironment* environment);
/**
* Free WSProtocolDecoderTX_8300.
* @param context Pointer to a WSProtocolDecoderTX_8300 instance
*/
void ws_protocol_decoder_tx_8300_free(void* context);
/**
* Reset decoder WSProtocolDecoderTX_8300.
* @param context Pointer to a WSProtocolDecoderTX_8300 instance
*/
void ws_protocol_decoder_tx_8300_reset(void* context);
/**
* Parse a raw sequence of levels and durations received from the air.
* @param context Pointer to a WSProtocolDecoderTX_8300 instance
* @param level Signal level true-high false-low
* @param duration Duration of this level in, us
*/
void ws_protocol_decoder_tx_8300_feed(void* context, bool level, uint32_t duration);
/**
* Getting the hash sum of the last randomly received parcel.
* @param context Pointer to a WSProtocolDecoderTX_8300 instance
* @return hash Hash sum
*/
uint8_t ws_protocol_decoder_tx_8300_get_hash_data(void* context);
/**
* Serialize data WSProtocolDecoderTX_8300.
* @param context Pointer to a WSProtocolDecoderTX_8300 instance
* @param flipper_format Pointer to a FlipperFormat instance
* @param preset The modulation on which the signal was received, SubGhzRadioPreset
* @return true On success
*/
bool ws_protocol_decoder_tx_8300_serialize(
void* context,
FlipperFormat* flipper_format,
SubGhzRadioPreset* preset);
/**
* Deserialize data WSProtocolDecoderTX_8300.
* @param context Pointer to a WSProtocolDecoderTX_8300 instance
* @param flipper_format Pointer to a FlipperFormat instance
* @return true On success
*/
bool ws_protocol_decoder_tx_8300_deserialize(void* context, FlipperFormat* flipper_format);
/**
* Getting a textual representation of the received data.
* @param context Pointer to a WSProtocolDecoderTX_8300 instance
* @param output Resulting text
*/
void ws_protocol_decoder_tx_8300_get_string(void* context, FuriString* output);

View File

@@ -82,8 +82,14 @@ void ws_view_receiver_info_draw(Canvas* canvas, WSReceiverInfoModel* model) {
if(model->generic->temp != WS_NO_TEMPERATURE) {
canvas_draw_icon(canvas, 6, 43, &I_Therm_7x16);
snprintf(buffer, sizeof(buffer), "%3.1f C", (double)model->generic->temp);
canvas_draw_str_aligned(canvas, 47, 47, AlignRight, AlignTop, buffer);
canvas_draw_circle(canvas, 38, 46, 1);
uint8_t temp_x1 = 47;
uint8_t temp_x2 = 38;
if(model->generic->temp < -9.0) {
temp_x1 = 49;
temp_x2 = 40;
}
canvas_draw_str_aligned(canvas, temp_x1, 47, AlignRight, AlignTop, buffer);
canvas_draw_circle(canvas, temp_x2, 46, 1);
}
if(model->generic->humidity != WS_NO_HUMIDITY) {

View File

@@ -52,6 +52,7 @@ struct AnimationManager {
FuriString* freezed_animation_name;
int32_t freezed_animation_time_left;
ViewStack* view_stack;
bool dummy_mode;
};
static StorageAnimation*
@@ -93,6 +94,12 @@ void animation_manager_set_interact_callback(
animation_manager->interact_callback = callback;
}
void animation_manager_set_dummy_mode_state(AnimationManager* animation_manager, bool enabled) {
furi_assert(animation_manager);
animation_manager->dummy_mode = enabled;
animation_manager_start_new_idle(animation_manager);
}
static void animation_manager_check_blocking_callback(const void* message, void* context) {
const StorageEvent* storage_event = message;
@@ -363,7 +370,9 @@ static bool animation_manager_is_valid_idle_animation(
static StorageAnimation*
animation_manager_select_idle_animation(AnimationManager* animation_manager) {
UNUSED(animation_manager);
if(animation_manager->dummy_mode) {
return animation_storage_find_animation(HARDCODED_ANIMATION_NAME);
}
StorageAnimationList_t animation_list;
StorageAnimationList_init(animation_list);
animation_storage_fill_animation_list(&animation_list);

View File

@@ -157,3 +157,11 @@ void animation_manager_unload_and_stall_animation(AnimationManager* animation_ma
* @animation_manager instance
*/
void animation_manager_load_and_continue_animation(AnimationManager* animation_manager);
/**
* Enable or disable dummy mode backgrounds of animation manager.
*
* @animation_manager instance
* @enabled bool
*/
void animation_manager_set_dummy_mode_state(AnimationManager* animation_manager, bool enabled);

View File

@@ -144,6 +144,7 @@ void desktop_unlock(Desktop* desktop) {
void desktop_set_dummy_mode_state(Desktop* desktop, bool enabled) {
view_port_enabled_set(desktop->dummy_mode_icon_viewport, enabled);
desktop_main_set_dummy_mode_state(desktop->main_view, enabled);
animation_manager_set_dummy_mode_state(desktop->animation_manager, enabled);
desktop->settings.dummy_mode = enabled;
DESKTOP_SETTINGS_SAVE(&desktop->settings);
}
@@ -330,6 +331,8 @@ int32_t desktop_srv(void* p) {
view_port_enabled_set(desktop->dummy_mode_icon_viewport, desktop->settings.dummy_mode);
desktop_main_set_dummy_mode_state(desktop->main_view, desktop->settings.dummy_mode);
animation_manager_set_dummy_mode_state(
desktop->animation_manager, desktop->settings.dummy_mode);
scene_manager_next_scene(desktop->scene_manager, DesktopSceneMain);

View File

@@ -0,0 +1,9 @@
App(
appid="locale",
name="LocaleSrv",
apptype=FlipperAppType.STARTUP,
entry_point="locale_on_system_start",
cdefines=["SRV_LOCALE"],
order=90,
sdk_headers=["locale.h"],
)

View File

@@ -0,0 +1,109 @@
#include "locale.h"
#define TAG "LocaleSrv"
LocaleMeasurementUnits locale_get_measurement_unit(void) {
return (LocaleMeasurementUnits)furi_hal_rtc_get_locale_units();
}
void locale_set_measurement_unit(LocaleMeasurementUnits format) {
furi_hal_rtc_set_locale_units((FuriHalRtcLocaleUnits)format);
}
LocaleTimeFormat locale_get_time_format(void) {
return (LocaleTimeFormat)furi_hal_rtc_get_locale_timeformat();
}
void locale_set_time_format(LocaleTimeFormat format) {
furi_hal_rtc_set_locale_timeformat((FuriHalRtcLocaleTimeFormat)format);
}
LocaleDateFormat locale_get_date_format(void) {
return (LocaleDateFormat)furi_hal_rtc_get_locale_dateformat();
}
void locale_set_date_format(LocaleDateFormat format) {
furi_hal_rtc_set_locale_dateformat((FuriHalRtcLocaleDateFormat)format);
}
float locale_fahrenheit_to_celsius(float temp_f) {
return (temp_f - 32.f) / 1.8f;
}
float locale_celsius_to_fahrenheit(float temp_c) {
return (temp_c * 1.8f + 32.f);
}
void locale_format_time(
FuriString* out_str,
const FuriHalRtcDateTime* datetime,
const LocaleTimeFormat format,
const bool show_seconds) {
furi_assert(out_str);
furi_assert(datetime);
uint8_t hours = datetime->hour;
uint8_t am_pm = 0;
if(format == LocaleTimeFormat12h) {
if(hours > 12) {
hours -= 12;
am_pm = 2;
} else {
am_pm = 1;
}
}
if(show_seconds) {
furi_string_printf(out_str, "%02u:%02u:%02u", hours, datetime->minute, datetime->second);
} else {
furi_string_printf(out_str, "%02u:%02u", hours, datetime->minute);
}
if(am_pm > 0) {
furi_string_cat_printf(out_str, " %s", (am_pm == 1) ? ("AM") : ("PM"));
}
}
void locale_format_date(
FuriString* out_str,
const FuriHalRtcDateTime* datetime,
const LocaleDateFormat format,
const char* separator) {
furi_assert(out_str);
furi_assert(datetime);
furi_assert(separator);
if(format == LocaleDateFormatDMY) {
furi_string_printf(
out_str,
"%02u%s%02u%s%04u",
datetime->day,
separator,
datetime->month,
separator,
datetime->year);
} else if(format == LocaleDateFormatMDY) {
furi_string_printf(
out_str,
"%02u%s%02u%s%04u",
datetime->month,
separator,
datetime->day,
separator,
datetime->year);
} else {
furi_string_printf(
out_str,
"%04u%s%02u%s%02u",
datetime->year,
separator,
datetime->month,
separator,
datetime->day);
}
}
int32_t locale_on_system_start(void* p) {
UNUSED(p);
return 0;
}

View File

@@ -0,0 +1,107 @@
#pragma once
#include <stdbool.h>
#include <furi.h>
#include <furi_hal.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
LocaleMeasurementUnitsMetric = 0, /**< Metric measurement units */
LocaleMeasurementUnitsImperial = 1, /**< Imperial measurement units */
} LocaleMeasurementUnits;
typedef enum {
LocaleTimeFormat24h = 0, /**< 24-hour format */
LocaleTimeFormat12h = 1, /**< 12-hour format */
} LocaleTimeFormat;
typedef enum {
LocaleDateFormatDMY = 0, /**< Day/Month/Year */
LocaleDateFormatMDY = 1, /**< Month/Day/Year */
LocaleDateFormatYMD = 2, /**< Year/Month/Day */
} LocaleDateFormat;
/** Get Locale measurement units
*
* @return The locale measurement units.
*/
LocaleMeasurementUnits locale_get_measurement_unit();
/** Set locale measurement units
*
* @param[in] format The locale measurements units
*/
void locale_set_measurement_unit(LocaleMeasurementUnits format);
/** Convert Fahrenheit to Celsius
*
* @param[in] temp_f The Temperature in Fahrenheit
*
* @return The Temperature in Celsius
*/
float locale_fahrenheit_to_celsius(float temp_f);
/** Convert Celsius to Fahrenheit
*
* @param[in] temp_c The Temperature in Celsius
*
* @return The Temperature in Fahrenheit
*/
float locale_celsius_to_fahrenheit(float temp_c);
/** Get Locale time format
*
* @return The locale time format.
*/
LocaleTimeFormat locale_get_time_format();
/** Set Locale Time Format
*
* @param[in] format The Locale Time Format
*/
void locale_set_time_format(LocaleTimeFormat format);
/** Format time to furi string
*
* @param[out] out_str The FuriString to store formatted time
* @param[in] datetime Pointer to the datetime
* @param[in] format The Locale Time Format
* @param[in] show_seconds The show seconds flag
*/
void locale_format_time(
FuriString* out_str,
const FuriHalRtcDateTime* datetime,
const LocaleTimeFormat format,
const bool show_seconds);
/** Get Locale DateFormat
*
* @return The Locale DateFormat.
*/
LocaleDateFormat locale_get_date_format();
/** Set Locale DateFormat
*
* @param[in] format The Locale DateFormat
*/
void locale_set_date_format(LocaleDateFormat format);
/** Format date to furi string
*
* @param[out] out_str The FuriString to store formatted date
* @param[in] datetime Pointer to the datetime
* @param[in] format The format
* @param[in] separator The separator
*/
void locale_format_date(
FuriString* out_str,
const FuriHalRtcDateTime* datetime,
const LocaleDateFormat format,
const char* separator);
#ifdef __cplusplus
}
#endif

View File

@@ -150,11 +150,16 @@ void notification_vibro_off() {
}
void notification_sound_on(float freq, float volume) {
furi_hal_speaker_start(freq, volume);
if(furi_hal_speaker_is_mine() || furi_hal_speaker_acquire(30)) {
furi_hal_speaker_start(freq, volume);
}
}
void notification_sound_off() {
furi_hal_speaker_stop();
if(furi_hal_speaker_is_mine()) {
furi_hal_speaker_stop();
furi_hal_speaker_release();
}
}
// display timer

View File

@@ -3,7 +3,7 @@ App(
name="System",
apptype=FlipperAppType.SETTINGS,
entry_point="system_settings_app",
requires=["gui"],
requires=["gui", "locale"],
stack_size=1 * 1024,
order=70,
)

View File

@@ -1,6 +1,7 @@
#include "system_settings.h"
#include <loader/loader.h>
#include <lib/toolbox/value_index.h>
#include <locale/locale.h>
const char* const log_level_text[] = {
"Default",
@@ -70,6 +71,59 @@ static void heap_trace_mode_changed(VariableItem* item) {
furi_hal_rtc_set_heap_track_mode(heap_trace_mode_value[index]);
}
const char* const mesurement_units_text[] = {
"Metric",
"Imperial",
};
const uint32_t mesurement_units_value[] = {
LocaleMeasurementUnitsMetric,
LocaleMeasurementUnitsImperial,
};
static void mesurement_units_changed(VariableItem* item) {
// SystemSettings* app = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(item, mesurement_units_text[index]);
locale_set_measurement_unit(mesurement_units_value[index]);
}
const char* const time_format_text[] = {
"24h",
"12h",
};
const uint32_t time_format_value[] = {
LocaleTimeFormat24h,
LocaleTimeFormat12h,
};
static void time_format_changed(VariableItem* item) {
// SystemSettings* app = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(item, time_format_text[index]);
locale_set_time_format(time_format_value[index]);
}
const char* const date_format_text[] = {
"D/M/Y",
"M/D/Y",
"Y/M/D",
};
const uint32_t date_format_value[] = {
LocaleDateFormatDMY,
LocaleDateFormatMDY,
LocaleDateFormatYMD,
};
static void date_format_changed(VariableItem* item) {
// SystemSettings* app = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
variable_item_set_current_value_text(item, date_format_text[index]);
locale_set_date_format(date_format_value[index]);
}
static uint32_t system_settings_exit(void* context) {
UNUSED(context);
return VIEW_NONE;
@@ -91,6 +145,31 @@ SystemSettings* system_settings_alloc() {
uint8_t value_index;
app->var_item_list = variable_item_list_alloc();
item = variable_item_list_add(
app->var_item_list,
"Units",
COUNT_OF(mesurement_units_text),
mesurement_units_changed,
app);
value_index = value_index_uint32(
locale_get_measurement_unit(), mesurement_units_value, COUNT_OF(mesurement_units_value));
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, mesurement_units_text[value_index]);
item = variable_item_list_add(
app->var_item_list, "Time Format", COUNT_OF(time_format_text), time_format_changed, app);
value_index = value_index_uint32(
locale_get_time_format(), time_format_value, COUNT_OF(time_format_value));
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, time_format_text[value_index]);
item = variable_item_list_add(
app->var_item_list, "Date Format", COUNT_OF(date_format_text), date_format_changed, app);
value_index = value_index_uint32(
locale_get_date_format(), date_format_value, COUNT_OF(date_format_value));
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, date_format_text[value_index]);
item = variable_item_list_add(
app->var_item_list, "Log Level", COUNT_OF(log_level_text), log_level_changed, app);
value_index = value_index_uint32(

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -0,0 +1,23 @@
Filetype: Flipper Animation
Version: 1
Width: 128
Height: 64
Passive frames: 10
Active frames: 18
Frames order: 0 1 2 1 0 1 2 1 0 1 2 3 4 5 6 5 4 7 2 8 9 10 11 10 9 10 11 12
Active cycles: 1
Frame rate: 2
Duration: 3600
Active cooldown: 7
Bubble slots: 1
Slot: 0
X: 11
Y: 19
Text: HAPPY\nHOLIDAYS!
AlignH: Right
AlignV: Center
StartFrame: 22
EndFrame: 27

View File

@@ -36,10 +36,10 @@ Min level: 1
Max level: 1
Weight: 3
Name: L2_Wake_up_128x64
Name: L1_Happy_holidays_128x64
Min butthurt: 0
Max butthurt: 12
Min level: 2
Max butthurt: 14
Min level: 1
Max level: 3
Weight: 4
@@ -92,6 +92,13 @@ Min level: 1
Max level: 3
Weight: 3
Name: L2_Wake_up_128x64
Min butthurt: 0
Max butthurt: 12
Min level: 2
Max level: 3
Weight: 4
Name: L2_Furippa2_128x64
Min butthurt: 0
Max butthurt: 6
@@ -139,7 +146,7 @@ Min butthurt: 0
Max butthurt: 10
Min level: 1
Max level: 3
Weight: 7
Weight: 2
Name: L3_Fireplace_128x64
Min butthurt: 0

View File

@@ -1,6 +1,31 @@
Filetype: IR library file
Version: 1
# Last Updated 6th Dec, 2022
# Last Updated 19th Dec, 2022
#
# ON/Speed
name: POWER
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 1280 423 1285 445 414 1287 1259 418 1279 450 409 1266 442 1260 437 1265 443 1259 438 1264 1282 421 438 8680 1284 419 1289 442 406 1268 1288 415 1282 447 412 1263 434 1267 440 1262 435 1266 441 1261 1285 444 415 8677 1287 415 1282 447 412 1263 1283 447 1261 442 406 1268 439 1262 435 1267 440 1262 435 1267 1289 413 435 8683 1281 421 1286 443 416 1259 1287 416 1281 448 411 1263 444 1258 439 1262 435 1267 440 1263 1283 419 440 8679 1285 417 1280 449 410 1292 1254 448 1260 443 416 1259 438 1264 444 1258 439 1263 444 1258 1288 415 444 8675 1289 413 1284 445 414 1262 1284 419 1288 440 408 1293 415 1261 436 1265 442 1260 437 1265 1281 422 437 8680 1284 418 1289 440 408 1267 1289 414 1283 445 414 1262 435 1266 442 1260 437 1265 442 1261 1285 418 441 8678 1286 417 1290 439 409 1267 1289 414 1283 445 414 1262 435 1267 440 1262 435 1267 440 1263 1283 420 439
#
name: MODE
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 1284 419 1288 442 417 1258 1288 415 1282 448 411 1264 443 1258 439 1263 444 1258 1288 415 444 1258 439 8679 1284 419 1288 441 407 1267 1289 441 1256 447 412 1262 435 1267 440 1262 435 1293 1263 413 435 1267 440 8679 1284 418 1289 441 407 1267 1289 414 1283 447 412 1262 435 1267 440 1261 436 1267 1289 413 435 1267 440 8678 1285 418 1289 440 408 1267 1289 440 1257 447 412 1262 435 1267 440 1262 435 1268 1288 414 434 1268 439 8679 1284 418 1289 440 408 1267 1289 413 1284 445 414 1261 436 1266 441 1260 437 1266 1290 412 436 1266 441 8676 1287 415 1282 448 411 1264 1282 421 1286 443 416 1258 439 1263 434 1267 440 1262 1284 419 440 1262 435 8683 1280 422 1285 444 415 1287 1259 444 1253 449 410 1292 415 1285 412 1264 443 1259 1287 416 443 1259 438 8680 1284 420 1287 414 434 1268 1288 415 1282 447 412 1289 408 1267 440 1262 435 1267 1289 414 434 1268 439
#
name: SWING
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 1281 422 1285 444 415 1260 1286 444 1263 439 409 1266 441 1261 1285 445 414 1261 436 1266 441 1261 436 8682 1281 421 1286 444 415 1260 1286 445 1262 439 409 1266 441 1261 1285 445 414 1261 436 1266 441 1260 437 8683 1280 422 1286 444 415 1261 1285 445 1262 440 408 1267 440 1262 1284 446 413 1262 435 1268 439 1262 435 8684 1279 423 1284 445 414 1261 1285 445 1263 439 409 1265 442 1260 1286 444 415 1260 437 1265 442 1259 438 8682 1281 421 1286 443 416 1259 1287 443 1254 448 411 1264 443 1259 1287 443 416 1259 438 1265 442 1260 437 8682 1281 421 1286 444 415 1260 1286 444 1253 450 409 1266 441 1261 1285 445 414 1261 436 1266 441 1261 436 8683 1290 413 1284 445 414 1262 1283 446 1261 441 407 1294 413 1262 1284 420 439 1263 434 1267 440 1262 435
#
name: TIMER
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 1283 420 1287 443 416 1259 1287 443 1254 449 410 1292 415 1260 437 1266 1290 439 409 1266 442 1261 436 8684 1290 413 1284 446 413 1263 1283 447 1261 442 417 1258 439 1263 444 1259 1287 442 417 1259 438 1264 443 8677 1287 416 1281 449 410 1265 1281 449 1259 444 415 1260 437 1265 442 1260 1286 443 416 1260 437 1265 442 8676 1288 415 1282 447 412 1263 1283 447 1261 442 417 1257 440 1263 434 1268 1288 441 418 1257 440 1263 434 8685 1289 414 1283 447 412 1263 1283 447 1261 442 417 1258 439 1263 445 1258 1288 442 417 1258 439 1264 444 8676 1288 415 1282 448 411 1264 1282 448 1260 444 415 1259 438 1264 443 1260 1286 417 442 1260 437 1265 442 8677 1286 416 1281 449 410 1265 1281 422 1285 444 415 1260 437 1265 442 1260 1286 417 442 1260 437 1265 442
#
name: POWER
type: parsed

View File

@@ -0,0 +1,47 @@
## From https://github.com/RfidResearchGroup/proxmark3/blob/master/client/dictionaries/iclass_default_keys.dic
# AA1
AEA684A6DAB23278
# key1/Kc from PicoPass 2k documentation
7665544332211000
# SAGEM
0123456789ABCDEF
# from loclass demo file.
5b7c62c491c11b39
# Kd from PicoPass 2k documentation
F0E1D2C3B4A59687
# PicoPass Default Exchange Key
5CBCF1DA45D5FB4F
# From HID multiclassSE reader
31ad7ebd2f282168
# From pastebin: https://pastebin.com/uHqpjiuU
6EFD46EFCBB3C875
E033CA419AEE43F9
# iCopy-x DRM keys
# iCL tags
2020666666668888
# iCS tags reversed from the SOs
6666202066668888
# default picopass KD / Page 0 / Book 1
FDCB5A52EA8F3090
237FF9079863DF44
5ADC25FB27181D32
83B881F2936B2E49
43644E61EE866BA5
897034143D016080
82D17B44C0122963
4895CA7DE65E2025
DADAD4C57BE271B7
E41E9EDEF5719ABF
293D275EC3AF9C7F
C3C169251B8A70FB
F41DAF58B20C8B91
28877A609EC0DD2B
66584C91EE80D5E5
C1B74D7478053AE2
# default iCLASS RFIDeas
6B65797374726B72

View File

@@ -0,0 +1,8 @@
Filetype: Flipper SubGhz Key File
Version: 1
Frequency: 433920000
Preset: FuriHalSubGhzPresetOok650Async
Protocol: SMC5326
Bit: 25
Key: 00 00 00 00 01 7D 55 80
TE: 210

View File

@@ -0,0 +1,7 @@
Filetype: Flipper SubGhz RAW File
Version: 1
Frequency: 433920000
Preset: FuriHalSubGhzPresetOok650Async
Protocol: RAW
RAW_Data: 2442 -312 275 -972 949 -310 941 -322 923 -342 921 -352 923 -334 281 -954 945 -350 279 -958 907 -354 289 -980 909 -352 281 -962 907 -330 311 -964 913 -350 317 -930 933 -344 921 -352 893 -330 311 -954 943 -318 315 -958 909 -324 947 -7854 953 -322 289 -948 939 -354 927 -332 911 -324 943 -344 917 -318 317 -964 905 -344 303 -942 947 -312 319 -960 913 -348 281 -958 941 -322 295 -978 905 -350 279 -962 931 -328 947 -324 939 -346 267 -964 935 -348 283 -938 953 -318 931 -7868 935 -346 269 -968 953 -310 941 -322 921 -330 935 -342 931 -318 311 -962 939 -290 337 -950 909 -352 317 -924 943 -324 313 -938 941 -318 317 -932 939 -344 301 -938 933 -350 921 -322 959 -310 301 -942 933 -352 317 -926 957 -314 919 -7868 943 -314 317 -958 909 -322 951 -344 919 -352 921 -324 937 -326 281 -964 941 -318 317 -930 939 -344 301 -938 933 -352 281 -962 953 -314 317 -922 933 -330 315 -954 943 -318 921 -342 943 -320 291 -980 909 -354 281 -962 943 -296 967 -7836 943 -332 309 -950 935 -318 929 -340 943 -320 921 -344 921 -354 283 -960 943 -296 309 -964 945 -318 279 -964 941 -322 333 -944 939 -314 279 -992 903 -342 319 -932 933 -330 931 -340 929 -348 281 -964 935 -334 281 -970 927 -346 921 -7862 951 -314 319 -922 953 -320 923 -346 921 -320 965 -298 943 -324 313 -942 941 -320 317 -930 941 -344 303 -940 945 -312 321 -940 953 -314 303 -960 933 -348 287 -962 911 -352 917 -350 905 -324 333 -918 971 -322 317 -924 945 -324 937 -7872 919 -324 317 -942 941 -318 933 -330 943 -324 943 -310 951 -318 317 -930 939 -344 301 -938 933 -352 317 -926 953 -314 319 -924 939 -324 331 -950 907 -354 315 -926 945 -324 939 -312 953 -318 317 -930 937 -344 301 -940 947 -348 909 -7864 949 -310 319 -956 915 -350 919 -348 905 -322 963 -296 935 -348 317 -922 951 -322 295 -976 939 -314 281 -996 915 -326 307 -940 959 -310 301 -966 935 -346 285 -958 915 -348 921 -348 903 -354 303 -948 911 -350 315 -926 945 -324 941 -7874 943 -290 319 -942 973 -318 929 -314 937 -328 941 -324 939 -310 303 -962 933 -352 285 -962 949 -314 319 -924 951 -320 293 -948 941 -354 283 -962 943 -294 309 -966 943 -320 931 -328 943 -326 311 -940 939 -320 309 -958 933 -338 943 -7840 933 -352 277 -964 941 -322 923 -344 923 -350 931 -310 955 -320 291 -974 907 -350 281 -958 963 -298 313 -956 945 -314 311 -960 937 -312 311 -966 909 -324 319 -944 941 -354 929 -298 945 -324 315 -940
RAW_Data: 943 -354 281 -964 905 -330 933 -7868 951 -324 315 -938 943 -354 893 -330 943 -324 943 -344 919 -318 317 -962 903 -344 301 -974 903 -350 317 -932 931 -342 269 -972 949 -346 285 -938 955 -310 301 -964 935 -348 921 -320 921 -344 301 -940 935 -350 317 -930 929 -318 937 -7872 939 -344 301 -940 947 -346 917 -322 921 -344 923 -352 927 -334 281 -970 925 -334 277 -982 943 -318 317 -932 931 -344 301 -936 935 -350 281 -960 957 -312 303 -960 935 -346 907 -322 929 -344 301 -942 935 -350 317 -924 955 -312 951 -7858 919 -342 309 -940 949 -348 909 -322 923 -344 923 -352 923 -336 317 -924 945 -312 311 -966 921 -340 317 -924 947 -350 281 -958 941 -322 291 -976 905 -350 279 -960 935 -342 943 -320 919 -330 311 -958 943 -320 315 -932 935 -344 919 -7866 957 -312 303 -964 917 -342 945 -320 923 -344 923 -354 929 -298 315 -956 941 -318 315 -960 911 -324 317 -942 939 -354 281 -964 941 -294 311 -968 943 -318 317 -932 937 -330 931 -350 919 -348 283 -960 917 -350 317 -922 939 -322 965 -7864 921 -324 329 -950 909 -354 923 -336 913 -322 947 -344 919 -354 281 -962 941 -294 311 -960 935 -354 281 -962 939 -294 311 -964 937 -354 281 -964 941 -296 309 -964 939 -318 931 -330 945 -324 315 -940 939 -354 281 -964 909 -344 921 -7862 963 -304 307 -976 933 -320 929 -328 941 -324 939 -348 915 -320 317 -930 939 -344 301 -940 965 -320 319 -926 953 -312 303 -960 933 -312 321 -960 913 -348 319 -924 943 -320 959 -310 921 -354 319 -924 943 -324 311 -938 941 -318 957 -7862 943 -318 317 -932 933 -344 925 -352 897 -332 943 -324 943 -346 267 -966 951 -310 321 -960 911 -350 281 -958 949 -320 291 -978 937 -316 279 -964 949 -326 309 -944 943 -314 959 -318 933 -336 317 -934 933 -344 267 -964 937 -350 905 -7896 943 -318 319 -926 955 -314 919 -350 935 -324 941 -294 967 -312 303 -962 933 -348 285 -960 917 -348 317 -922 941 -322 329 -950 907 -354 315 -926 943 -326 313 -940 941 -352 893 -332 949 -324 315 -938 941 -352 283 -962 943 -310 925 -7890 931 -344 269 -968 949 -310 943 -320 923 -350 937 -310 955 -318 317 -930 935 -344 301 -942 947 -346 285 -958 915 -346 317 -924 951 -322 295 -982 905 -352 317 -924 945 -324 941 -346 917 -318 317 -962 905 -330 311 -956 937 -352 897 -7878 939 -354 283 -960 941 -294 965 -312 953 -318 385 -201512 165 -198 265 -526 229 -298 755 -164 61687 -17310 131 -1056 99 -296 195 -296 65 -66 1617

View File

@@ -165,4 +165,6 @@ RAW_Data: 1125 -536 1145 -19444 567 -542 1151 -1086 581 -534 1133 -1084 583 -530
RAW_Data: 317 -144 57 -486 53 -282 115 -585 97 -72 229 -174 257 -440 225 -86 173 -518 243 -167 95 -259 137 -96 694 -58 227 -80 279 -287 71 -72 301 -72 121 -106 51 -84 57 -58 199 -260 143 -288 219 -174 113 -681 115 -172 403 -58 113 -116 113 -432 171 -202 55 -108 95 -212 113 -72 527 -166 95 -212 195 -108 603 -142 239 -296 173 -346 373 -287 53 -80 79 -72 95 -238 95 -312 167 -618 143 -288 95 -72 95 -72 141 -210 55 -258 143 -328 305 -58 87 -86 315 -116 195 -218 85 -290 285 -220 215 -189 201 -58 57 -645 119 -96 71 -144 119 -406 143 -72 191 -72 631 -268 344 -56 115 -260 315 -140 455 -518 57 -58 171 -144 488 -86 219 -232 257 -144 85 -174 171 -260 115 -56 87 -166 197 -58 83 -56 85 -288 113 -410 115 -172 163 -202 113 -58 201 -144 201 -86 143 -264 167 -212 113 -116 139 -72 181 -287 343 -430 201 -260 201 -462 143 -192 301 -230 191 -454 187 -144 315 -164 143 -477 165 -58 201 -114 143 -490 115 -86 201 -58 113 -88 85 -58 203 -198 375 -86 171 -346 95 -88 257 -170 81 -56 143 -172 335 -230 173 -202 133 -471 187 -264 215 -86 115 -198 159 -72 179 -112 195 -116 449 -216 93 -96 167 -216 71 -216 71 -166 235 -86 447 -102 101 -226 195 -213 71 -144 215 -144 215 -261 241 -136 269 -142 263 -311 215 -172 201 -144 265 -168 71 -404 259 -86 85 -230 115 -650 143 -202 749 -512 248 -316 201 -154 71 -96 95 -360 105 -56 57 -432 95 -288 95 -286 95 -96 166 -144 93 -144 167 -150 904 -162 95 -526 287 -244 95 -240 383 -120 167 -394 430 -854 95 -72 143 -194 227 -120 167 -264 405 -144 143 -72 143 -72 141 -120 187 -86 143 -164 170 -96 143 -58 143 -86 402 -166 153 -120 95 -96 69 -96 71 -359 404 -338 71 -225 93 -74 97 -54 161 -114 319 -288 113 -116 459 -202 115 -114 115 -116 143 -86 57 -56 87 -114 85 -375 113 -58 311 -240 203 -288 95 -72 119 -383 213 -384 115 -86 171 -58 53 -104 401 -58 115 -86 373 -116 143 -144 161 -216 406 -72 263 -96 215 -72 95 -94 167 -96 191 -240 95 -94 214 -120 403 -116 200 -114 57 -172 220 -120 137 -364 334 -392 115 -260 199 -116 373 -188 95 -110 143 -172 87 -114 172 -230 57 -316 201 -56 249 -485 171 -202 87 -86 85 -144 345 -86 171 -58 259 -58 295 -120 95 -120 71 -192 635 -118 167 -96 375 -72 119 -120 261 -144 167 -96 95 -96 923 -215 71 -433 71 -477
RAW_Data: 191 -240 85 -72 637 -408 213 -510 261 -168 143 -126 79 -106 167 -72 117 -218 251 -168 119 -96 215 -182 191 -238 517 -116 201 -144 255 -154 97 -94 215 -72 95 -120 71 -288 261 -106 434 -96 606 -232 229 -432 85 -174 343 -58 329 -156 55 -116 259 -144 488 -56 307 -339 115 -202 334 -88 113 -86 57 -174 143 -144 401 -376 85 -240 267 -82 95 -216 137 -158 85 -144 143 -58 221 -308 295 -114 87 -114 301 -120 358 -517 71 -262 191 -144 57 -140 165 -407 53 -262 217 -120 238 -358 119 -357 71 -72 119 -96 428 -72 95 -72 167 -72 93 -240 335 -96 357 -240 173 -230 143 -114 87 -200 143 -232 287 -150 97 -288 71 -72 93 -288 115 -58 143 -230 109 -264 71 -72 119 -72 238 -242 97 -78 163 -86 115 -518 79 -560 205 -449 969 -144 507 -86 231 -114 345 -58 979 -110 85 -288 287 -404 229 -202 57 -274 233 -86 115 -202 632 -230 85 -312 369 -392 460 -450 75 -280 85 -202 201 -86 229 -174 143 -144 233 -528 115 -212 127 -202 287 -172 403 -172 139 -128 165 -138 261 -392 143 -480 142 -189 291 -80 53 -283 167 -140 113 -1008 191 -144 119 -120 71 -193 241 -462 201 -58 143 -344 539 -316 113 -174 85 -116 113 -250 239 -168 405 -168 239 -158 85 -144 115 -86 57 -86 341 -144 171 -202 85 -202 115 -114 719 -88 55 -318 257 -56 254 -86 171 -116 459 -174 171 -329 95 -134 85 -314 431 -306 77 -316 401 -86 173 -404 281 -1073 488 -94 217 -78 101 -98 214 -120 215 -340 403 -535 143 -564 115 -116 199 -58 85 -174 315 -58 335 -136 55 -260 143 -144 229 -460 143 -58 143 -144 171 -202 115 -374 291 -130 339 -82 143 -58 171 -58 201 -86 85 -174 1022 -56 85 -82 255 -240 103 -202 431 -278 95 -216 119 -72 71 -96 71 -559 57 -144 171 -88 113 -86 231 -414 131 -192 237 -360 95 -168 145 -168 213 -120 167 -96 143 -110 57 -86 259 -56 87 -777 295 -96 57 -86 173 -86 171 -404 143 -172 231 -200 57 -441 55 -58 173 -56 87 -86 171 -72 287 -72 119 -262 119 -144 71 -72 121 -310 71 -302 113 -54 193 -80 307 -58 257 -232 143 -56 143 -116 219 -72 695 -70 71 -460 85 -232 719 -363 57 -402 604 -230 287 -138 83 -172 259 -58 171 -174 55 -88 489 -114 143 -116 171 -116 143 -58 199 -144 145 -343 374 -186 235 -140 77 -86 143 -202 143 -144 113 -144 143 -58 732 -96 263 -264 71 -206 95 -168 215 -144 271 -80 139 -88 85 -414 75 -100
RAW_Data: 285 -96 627 -362 53 -84 201 -374 113 -202 115 -202 421 -316 85 -58 139 -224 87 -86 229 -58 243 -178 267 -288 95 -336 171 -96 213 -288 71 -405 95 -96 95 -384 95 -72 213 -72 95 -96 95 -272 87 -1083 85 -58 113 -88 257 -116 143 -292 175 -318 95 -120 95 -144 95 -72 71 -216 368 -116 373 -172 115 -58 85 -116 143 -86 85 -144 201 -86 201 -202 257 -144 201 -174 113 -144 115 -144 257 -202 585 -364 173 -138 287 -422 431 -86 85 -96 869 -186 95 -52 115 -86 115 -58 55 -276 365 -86 85 -489 171 -140 577 -106 718 -144 391 -232 195 -82 143 -172 109 -120 167 -96 280 -216 145 -240 215 -186 163 -96 141 -172 159 -603 257 -108 629 -192 119 -80 87 -172 57 -144 286 -86 57 -230 344 -58 113 -537 75 -96 537 -86 403 -196 167 -264 119 -238 119 -120 167 -96 95 -478 95 -120 167 -216 1085 -96 358 -72 263 -72 69 -120 143 -96 71 -96 191 -362 55 -144 57 -260 113 -58 85 -174 55 -88 257 -86 231 -194 55 -58 115 -56 55 -339 55 -58 374 -172 139 -82 419 -98 119 -261 71 -72 71 -240 713 -86 143 -218 295 -72 53 -56 431 -58 317 -144 161 -144 373 -144 173 -144 57 -114 85 -116 195 -72 708 -172 115 -86 191 -96 506 -120 71 -174 85 -58 363 -114 317 -230 316 -200 87 -114 57 -230 115 -315 173 -280 694 -212 453 -256 143 -202 113 -540 352 -116 257 -116 457 -56 109 -58 143 -230 259 -144 259 -525 119 -408 247 -112 389 -72 431 -96 137 -236 97 -474 201 -298 71 -82 55 -116 55 -112 199 -174 191 -86 143 -144 115 -114 317 -86 85 -230 87 -114 259 -84 107 -130 143 -94 153 -86 135 -94 215 -72 239 -94 435 -96 263 -142 166 -334 87 -194 179 -96 115 -284 135 -56 57 -144 463 -204 143 -316 201 -58 403 -86 141 -288 85 -202 139 -397 171 -174 305 -202 85 -144 373 -253 161 -492 181 -191 95 -216 315 -191 71 -166 97 -126 337 -96 71 -96 189 -168 295 -84 197 -86 259 -345 137 -144 167 -796 115 -344 455 -72 119 -96 119 -550 209 -88 85 -86 143 -340 167 -260 143 -537 85 -226 51 -537 57 -260 315 -461 51 -84 199 -358 383 -96 143 -257 115 -86 173 -86 201 -144 143 -316 85 -86 479 -88 85 -72 71 -104 115 -116 267 -72 137 -144 143 -116 85 -86 373 -288 115 -200 87 -114 259 -114 259 -462 143 -144 171 -86 57 -58 137 -144 57 -634 343 -72 205 -86 143 -258 57 -232 113 -230 461 -58 185 -74 537 -86
RAW_Data: 535 -142 57 -58 55 -116 115 -432 85 -172 259 -192 167 -120 117 -72 119 -240 334 -72 71 -267 285 -144 119 -374 85 -88 85 -114 143 -202 229 -58 143 -202 115 -202 171 -86 71 -144 87 -56 173 -373 143 -116 113 -462 169 -80 215 -148 115 -336 85 -230 163 -432 85 -374 639 -174 85 -58 57 -82 295 -352 269 -532 414 -322 95 -287 263 -268 115 -56 259 -76 85 -282 401 -305 516 -114 115 -202 171 -86 451 -110 85 -346 201 -274 149 -202 85 -364 366 -258 57 -114 259 -172 142 -144 85 -116 85 -480 171 -144 57 -352 115 -116 535 -404 315 -202 163 -158 517 -316 215 -98 85 -346 85 -144 87 -86 257 -82 167 -58 85 -116 113 -894 233 -186 77 -266 147 -72 71 -82 57 -86 171 -58 57 -86 201 -364 143 -202 115 -114 85 -88 113 -86 87 -230 57 -76 613 -72 85 -96 209 -346 458 -58 547 -490 201 -315 315 -116 75 -168 359 -335 95 -384 93 -120 71 -312 251 -366 233 -96 189 -240 263 -192 271 -58 115 -58 229 -346 459 -174 113 -144 173 -144 218 -224 57 -116 215 -72 103 -202 513 -210 433 -116 113 -174 650 -273 147 -450 375 -86 115 -172 536 -84 85 -230 85 -58 195 -468 287 -110 551 -214 167 -311 213 -250 85 -58 85 -355 113 -230 115 -144 117 -288 195 -202 57 -376 123 -144 236 -168 553 -284 119 -72 143 -188 161 -120 93 -312 335 -58 55 -260 105 -244 143 -120 381 -268 173 -268 635 -168 453 -318 71 -167 71 -406 191 -172 215 -408 119 -144 93 -120 97 -130 143 -192 308 -122 147 -550 313 -96 139 -162 167 -96 431 -80 83 -112 201 -86 287 -86 229 -116 57 -288 113 -174 143 -116 113 -144 115 -518 57 -230 57 -172 231 -86 113 -314 183 -144 119 -72 165 -446 81 -86 135 -190 143 -96 71 -72 411 -96 143 -120 69 -216 349 -72 95 -96 517 -646 163 -86 113 -116 171 -116 143 -116 113 -287 259 -114 517 -168 141 -116 105 -72 95 -96 311 -118 159 -310 191 -54 143 -258 115 -450 219 -54 339 -372 239 -72 167 -174 113 -58 57 -144 259 -172 143 -336 113 -174 85 -230 83 -668 85 -202 113 -144 57 -116 373 -316 719 -288 115 -58 75 -120 139 -144 229 -144 57 -144 171 -192 391 -202 403 -58 315 -188 259 -56 115 -144 85 -404 57 -58 105 -102 429 -406 81 -172 57 -144 287 -230 287 -220 317 -458 283 -58 113 -86 269 -72 281 -58 85 -202 113 -52 421 -58 229 -480 259 -58 143 -660 155 -638 123 -86 57 -86 143 -346 143 -144 57 -144
RAW_Data: 535 -142 57 -58 55 -116 115 -432 85 -172 259 -192 167 -120 117 -72 119 -240 334 -72 71 -267 285 -144 119 -374 85 -88 85 -114 143 -202 229 -58 143 -202 115 -202 171 -86 71 -144 87 -56 173 -373 143 -116 113 -462 169 -80 215 -148 115 -336 85 -230 163 -432 85 -374 639 -174 85 -58 57 -82 295 -352 269 -532 414 -322 95 -287 263 -268 115 -56 259 -76 85 -282 401 -305 516 -114 115 -202 171 -86 451 -110 85 -346 201 -274 149 -202 85 -364 366 -258 57 -114 259 -172 142 -144 85 -116 85 -480 171 -144 57 -352 115 -116 535 -404 315 -202 163 -158 517 -316 215 -98 85 -346 85 -144 87 -86 257 -82 167 -58 85 -116 113 -894 233 -186 77 -266 147 -72 71 -82 57 -86 171 -58 57 -86 201 -364 143 -202 115 -114 85 -88 113 -86 87 -230 57 -76 613 -72 85 -96 209 -346 458 -58 547 -490 201 -315 315 -116 75 -168 359 -335 95 -384 93 -120 71 -312 251 -366 233 -96 189 -240 263 -192 271 -58 115 -58 229 -346 459 -174 113 -144 173 -144 218 -224 57 -116 215 -72 103 -202 513 -210 433 -116 113 -174 650 -273 147 -450 375 -86 115 -172 536 -84 85 -230 85 -58 195 -468 287 -110 551 -214 167 -311 213 -250 85 -58 85 -355 113 -230 115 -144 117 -288 195 -202 57 -376 123 -144 236 -168 553 -284 119 -72 143 -188 161 -120 93 -312 335 -58 55 -260 105 -244 143 -120 381 -268 173 -268 635 -168 453 -318 71 -167 71 -406 191 -172 215 -408 119 -144 93 -120 97 -130 143 -192 308 -122 147 -550 313 -96 139 -162 167 -96 431 -80 83 -112 201 -86 287 -86 229 -116 57 -288 113 -174 143 -116 113 -144 115 -518 57 -230 57 -172 231 -86 113 -314 183 -144 119 -72 165 -446 81 -86 135 -190 143 -96 71 -72 411 -96 143 -120 69 -216 349 -72 95 -96 517 -646 163 -86 113 -116 171 -116 143 -116 113 -287 259 -114 517 -168 141 -116 105 -72 95 -96 311 -118 159 -310 191 -54 143 -258 115 -450 219 -54 339 -372 239 -72 167 -174 113 -58 57 -144 259 -172 143 -336 113 -174 85 -230 83 -668 85 -202 113 -144 57 -116 373 -316 719 -288 115 -58 75 -120 139 -144 229 -144 57 -144 171 -192 391 -202 403 -58 315 -188 259 -56 115 -144 85 -404 57 -58 105 -102 429 -406 81 -172 57 -144 287 -230 287 -220 317 -458 283 -58 113 -86 269 -72 281 -58 85 -202 113 -52 421 -58 229 -480 259 -58 143 -660 155 -638 123 -86 57 -86 143 -346 143 -144 57 -144
RAW_Data: 2442 -312 275 -972 949 -310 941 -322 923 -342 921 -352 923 -334 281 -954 945 -350 279 -958 907 -354 289 -980 909 -352 281 -962 907 -330 311 -964 913 -350 317 -930 933 -344 921 -352 893 -330 311 -954 943 -318 315 -958 909 -324 947 -7854 953 -322 289 -948 939 -354 927 -332 911 -324 943 -344 917 -318 317 -964 905 -344 303 -942 947 -312 319 -960 913 -348 281 -958 941 -322 295 -978 905 -350 279 -962 931 -328 947 -324 939 -346 267 -964 935 -348 283 -938 953 -318 931 -7868 935 -346 269 -968 953 -310 941 -322 921 -330 935 -342 931 -318 311 -962 939 -290 337 -950 909 -352 317 -924 943 -324 313 -938 941 -318 317 -932 939 -344 301 -938 933 -350 921 -322 959 -310 301 -942 933 -352 317 -926 957 -314 919 -7868 943 -314 317 -958 909 -322 951 -344 919 -352 921 -324 937 -326 281 -964 941 -318 317 -930 939 -344 301 -938 933 -352 281 -962 953 -314 317 -922 933 -330 315 -954 943 -318 921 -342 943 -320 291 -980 909 -354 281 -962 943 -296 967 -7836 943 -332 309 -950 935 -318 929 -340 943 -320 921 -344 921 -354 283 -960 943 -296 309 -964 945 -318 279 -964 941 -322 333 -944 939 -314 279 -992 903 -342 319 -932 933 -330 931 -340 929 -348 281 -964 935 -334 281 -970 927 -346 921 -7862 951 -314 319 -922 953 -320 923 -346 921 -320 965 -298 943 -324 313 -942 941 -320 317 -930 941 -344 303 -940 945 -312 321 -940 953 -314 303 -960 933 -348 287 -962 911 -352 917 -350 905 -324 333 -918 971 -322 317 -924 945 -324 937 -7872 919 -324 317 -942 941 -318 933 -330 943 -324 943 -310 951 -318 317 -930 939 -344 301 -938 933 -352 317 -926 953 -314 319 -924 939 -324 331 -950 907 -354 315 -926 945 -324 939 -312 953 -318 317 -930 937 -344 301 -940 947 -348 909 -7864 949 -310 319 -956 915 -350 919 -348 905 -322 963 -296 935 -348 317 -922 951 -322 295 -976 939 -314 281 -996 915 -326 307 -940 959 -310 301 -966 935 -346 285 -958 915 -348 921 -348 903 -354 303 -948 911 -350 315 -926 945 -324 941 -7874 943 -290 319 -942 973 -318 929 -314 937 -328 941 -324 939 -310 303 -962 933 -352 285 -962 949 -314 319 -924 951 -320 293 -948 941 -354 283 -962 943 -294 309 -966 943 -320 931 -328 943 -326 311 -940 939 -320 309 -958 933 -338 943 -7840 933 -352 277 -964 941 -322 923 -344 923 -350 931 -310 955 -320 291 -974 907 -350 281 -958 963 -298 313 -956 945 -314 311 -960 937 -312 311 -966 909 -324 319 -944 941 -354 929 -298 945 -324 315 -940
RAW_Data: 943 -354 281 -964 905 -330 933 -7868 951 -324 315 -938 943 -354 893 -330 943 -324 943 -344 919 -318 317 -962 903 -344 301 -974 903 -350 317 -932 931 -342 269 -972 949 -346 285 -938 955 -310 301 -964 935 -348 921 -320 921 -344 301 -940 935 -350 317 -930 929 -318 937 -7872 939 -344 301 -940 947 -346 917 -322 921 -344 923 -352 927 -334 281 -970 925 -334 277 -982 943 -318 317 -932 931 -344 301 -936 935 -350 281 -960 957 -312 303 -960 935 -346 907 -322 929 -344 301 -942 935 -350 317 -924 955 -312 951 -7858 919 -342 309 -940 949 -348 909 -322 923 -344 923 -352 923 -336 317 -924 945 -312 311 -966 921 -340 317 -924 947 -350 281 -958 941 -322 291 -976 905 -350 279 -960 935 -342 943 -320 919 -330 311 -958 943 -320 315 -932 935 -344 919 -7866 957 -312 303 -964 917 -342 945 -320 923 -344 923 -354 929 -298 315 -956 941 -318 315 -960 911 -324 317 -942 939 -354 281 -964 941 -294 311 -968 943 -318 317 -932 937 -330 931 -350 919 -348 283 -960 917 -350 317 -922 939 -322 965 -7864 921 -324 329 -950 909 -354 923 -336 913 -322 947 -344 919 -354 281 -962 941 -294 311 -960 935 -354 281 -962 939 -294 311 -964 937 -354 281 -964 941 -296 309 -964 939 -318 931 -330 945 -324 315 -940 939 -354 281 -964 909 -344 921 -7862 963 -304 307 -976 933 -320 929 -328 941 -324 939 -348 915 -320 317 -930 939 -344 301 -940 965 -320 319 -926 953 -312 303 -960 933 -312 321 -960 913 -348 319 -924 943 -320 959 -310 921 -354 319 -924 943 -324 311 -938 941 -318 957 -7862 943 -318 317 -932 933 -344 925 -352 897 -332 943 -324 943 -346 267 -966 951 -310 321 -960 911 -350 281 -958 949 -320 291 -978 937 -316 279 -964 949 -326 309 -944 943 -314 959 -318 933 -336 317 -934 933 -344 267 -964 937 -350 905 -7896 943 -318 319 -926 955 -314 919 -350 935 -324 941 -294 967 -312 303 -962 933 -348 285 -960 917 -348 317 -922 941 -322 329 -950 907 -354 315 -926 943 -326 313 -940 941 -352 893 -332 949 -324 315 -938 941 -352 283 -962 943 -310 925 -7890 931 -344 269 -968 949 -310 943 -320 923 -350 937 -310 955 -318 317 -930 935 -344 301 -942 947 -346 285 -958 915 -346 317 -924 951 -322 295 -982 905 -352 317 -924 945 -324 941 -346 917 -318 317 -962 905 -330 311 -956 937 -352 897 -7878 939 -354 283 -960 941 -294 965 -312 953 -318 385 -201512 165 -198 265 -526 229 -298 755 -164 61687 -17310 131 -1056 99 -296 195 -296 65 -66 1617

View File

@@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,10.1,,
Version,+,11.1,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,,
@@ -30,6 +30,7 @@ Header,+,applications/services/gui/view_dispatcher.h,,
Header,+,applications/services/gui/view_stack.h,,
Header,+,applications/services/input/input.h,,
Header,+,applications/services/loader/loader.h,,
Header,+,applications/services/locale/locale.h,,
Header,+,applications/services/notification/notification.h,,
Header,+,applications/services/notification/notification_messages.h,,
Header,+,applications/services/power/power_service/power.h,,
@@ -1283,6 +1284,9 @@ Function,+,furi_hal_rtc_get_boot_mode,FuriHalRtcBootMode,
Function,+,furi_hal_rtc_get_datetime,void,FuriHalRtcDateTime*
Function,+,furi_hal_rtc_get_fault_data,uint32_t,
Function,+,furi_hal_rtc_get_heap_track_mode,FuriHalRtcHeapTrackMode,
Function,+,furi_hal_rtc_get_locale_dateformat,FuriHalRtcLocaleDateFormat,
Function,+,furi_hal_rtc_get_locale_timeformat,FuriHalRtcLocaleTimeFormat,
Function,+,furi_hal_rtc_get_locale_units,FuriHalRtcLocaleUnits,
Function,+,furi_hal_rtc_get_log_level,uint8_t,
Function,+,furi_hal_rtc_get_pin_fails,uint32_t,
Function,+,furi_hal_rtc_get_register,uint32_t,FuriHalRtcRegister
@@ -1296,11 +1300,18 @@ Function,+,furi_hal_rtc_set_datetime,void,FuriHalRtcDateTime*
Function,+,furi_hal_rtc_set_fault_data,void,uint32_t
Function,+,furi_hal_rtc_set_flag,void,FuriHalRtcFlag
Function,+,furi_hal_rtc_set_heap_track_mode,void,FuriHalRtcHeapTrackMode
Function,+,furi_hal_rtc_set_locale_dateformat,void,FuriHalRtcLocaleDateFormat
Function,+,furi_hal_rtc_set_locale_timeformat,void,FuriHalRtcLocaleTimeFormat
Function,+,furi_hal_rtc_set_locale_units,void,FuriHalRtcLocaleUnits
Function,+,furi_hal_rtc_set_log_level,void,uint8_t
Function,+,furi_hal_rtc_set_pin_fails,void,uint32_t
Function,+,furi_hal_rtc_set_register,void,"FuriHalRtcRegister, uint32_t"
Function,+,furi_hal_rtc_validate_datetime,_Bool,FuriHalRtcDateTime*
Function,+,furi_hal_speaker_acquire,_Bool,uint32_t
Function,-,furi_hal_speaker_deinit,void,
Function,-,furi_hal_speaker_init,void,
Function,+,furi_hal_speaker_is_mine,_Bool,
Function,+,furi_hal_speaker_release,void,
Function,+,furi_hal_speaker_set_volume,void,float
Function,+,furi_hal_speaker_start,void,"float, float"
Function,+,furi_hal_speaker_stop,void,
@@ -1335,6 +1346,7 @@ Function,+,furi_hal_subghz_read_packet,void,"uint8_t*, uint8_t*"
Function,+,furi_hal_subghz_reset,void,
Function,+,furi_hal_subghz_rx,void,
Function,+,furi_hal_subghz_rx_pipe_not_empty,_Bool,
Function,+,furi_hal_subghz_set_async_mirror_pin,void,const GpioPin*
Function,+,furi_hal_subghz_set_frequency,uint32_t,uint32_t
Function,+,furi_hal_subghz_set_frequency_and_path,uint32_t,uint32_t
Function,+,furi_hal_subghz_set_path,void,FuriHalSubGhzPath
@@ -1752,6 +1764,16 @@ Function,+,loader_update_menu,void,
Function,+,loading_alloc,Loading*,
Function,+,loading_free,void,Loading*
Function,+,loading_get_view,View*,Loading*
Function,+,locale_celsius_to_fahrenheit,float,float
Function,+,locale_fahrenheit_to_celsius,float,float
Function,+,locale_format_date,void,"FuriString*, const FuriHalRtcDateTime*, const LocaleDateFormat, const char*"
Function,+,locale_format_time,void,"FuriString*, const FuriHalRtcDateTime*, const LocaleTimeFormat, const _Bool"
Function,+,locale_get_date_format,LocaleDateFormat,
Function,+,locale_get_measurement_unit,LocaleMeasurementUnits,
Function,+,locale_get_time_format,LocaleTimeFormat,
Function,+,locale_set_date_format,void,LocaleDateFormat
Function,+,locale_set_measurement_unit,void,LocaleMeasurementUnits
Function,+,locale_set_time_format,void,LocaleTimeFormat
Function,-,localtime,tm*,const time_t*
Function,-,localtime_r,tm*,"const time_t*, tm*"
Function,-,log,double,double
@@ -2830,6 +2852,14 @@ Function,-,subghz_protocol_decoder_secplus_v2_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_secplus_v2_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_secplus_v2_reset,void,void*
Function,-,subghz_protocol_decoder_secplus_v2_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*"
Function,-,subghz_protocol_decoder_smc5326_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_smc5326_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_smc5326_feed,void,"void*, _Bool, uint32_t"
Function,-,subghz_protocol_decoder_smc5326_free,void,void*
Function,-,subghz_protocol_decoder_smc5326_get_hash_data,uint8_t,void*
Function,-,subghz_protocol_decoder_smc5326_get_string,void,"void*, FuriString*"
Function,-,subghz_protocol_decoder_smc5326_reset,void,void*
Function,-,subghz_protocol_decoder_smc5326_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*"
Function,-,subghz_protocol_decoder_somfy_keytis_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_decoder_somfy_keytis_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_decoder_somfy_keytis_feed,void,"void*, _Bool, uint32_t"
@@ -3000,6 +3030,11 @@ Function,-,subghz_protocol_encoder_secplus_v2_deserialize,_Bool,"void*, FlipperF
Function,-,subghz_protocol_encoder_secplus_v2_free,void,void*
Function,-,subghz_protocol_encoder_secplus_v2_stop,void,void*
Function,-,subghz_protocol_encoder_secplus_v2_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_smc5326_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_smc5326_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_smc5326_free,void,void*
Function,-,subghz_protocol_encoder_smc5326_stop,void,void*
Function,-,subghz_protocol_encoder_smc5326_yield,LevelDuration,void*
Function,-,subghz_protocol_encoder_star_line_alloc,void*,SubGhzEnvironment*
Function,-,subghz_protocol_encoder_star_line_deserialize,_Bool,"void*, FlipperFormat*"
Function,-,subghz_protocol_encoder_star_line_free,void,void*
@@ -4820,6 +4855,9 @@ Variable,-,subghz_protocol_secplus_v1_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_secplus_v2,const SubGhzProtocol,
Variable,-,subghz_protocol_secplus_v2_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_secplus_v2_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_smc5326,const SubGhzProtocol,
Variable,-,subghz_protocol_smc5326_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_smc5326_encoder,const SubGhzProtocolEncoder,
Variable,-,subghz_protocol_somfy_keytis,const SubGhzProtocol,
Variable,-,subghz_protocol_somfy_keytis_decoder,const SubGhzProtocolDecoder,
Variable,-,subghz_protocol_somfy_keytis_encoder,const SubGhzProtocolEncoder,
1 entry status name type params
2 Version + 10.1 11.1
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
30 Header + applications/services/gui/view_stack.h
31 Header + applications/services/input/input.h
32 Header + applications/services/loader/loader.h
33 Header + applications/services/locale/locale.h
34 Header + applications/services/notification/notification.h
35 Header + applications/services/notification/notification_messages.h
36 Header + applications/services/power/power_service/power.h
1284 Function + furi_hal_rtc_get_datetime void FuriHalRtcDateTime*
1285 Function + furi_hal_rtc_get_fault_data uint32_t
1286 Function + furi_hal_rtc_get_heap_track_mode FuriHalRtcHeapTrackMode
1287 Function + furi_hal_rtc_get_locale_dateformat FuriHalRtcLocaleDateFormat
1288 Function + furi_hal_rtc_get_locale_timeformat FuriHalRtcLocaleTimeFormat
1289 Function + furi_hal_rtc_get_locale_units FuriHalRtcLocaleUnits
1290 Function + furi_hal_rtc_get_log_level uint8_t
1291 Function + furi_hal_rtc_get_pin_fails uint32_t
1292 Function + furi_hal_rtc_get_register uint32_t FuriHalRtcRegister
1300 Function + furi_hal_rtc_set_fault_data void uint32_t
1301 Function + furi_hal_rtc_set_flag void FuriHalRtcFlag
1302 Function + furi_hal_rtc_set_heap_track_mode void FuriHalRtcHeapTrackMode
1303 Function + furi_hal_rtc_set_locale_dateformat void FuriHalRtcLocaleDateFormat
1304 Function + furi_hal_rtc_set_locale_timeformat void FuriHalRtcLocaleTimeFormat
1305 Function + furi_hal_rtc_set_locale_units void FuriHalRtcLocaleUnits
1306 Function + furi_hal_rtc_set_log_level void uint8_t
1307 Function + furi_hal_rtc_set_pin_fails void uint32_t
1308 Function + furi_hal_rtc_set_register void FuriHalRtcRegister, uint32_t
1309 Function + furi_hal_rtc_validate_datetime _Bool FuriHalRtcDateTime*
1310 Function + furi_hal_speaker_acquire _Bool uint32_t
1311 Function - furi_hal_speaker_deinit void
1312 Function - furi_hal_speaker_init void
1313 Function + furi_hal_speaker_is_mine _Bool
1314 Function + furi_hal_speaker_release void
1315 Function + furi_hal_speaker_set_volume void float
1316 Function + furi_hal_speaker_start void float, float
1317 Function + furi_hal_speaker_stop void
1346 Function + furi_hal_subghz_reset void
1347 Function + furi_hal_subghz_rx void
1348 Function + furi_hal_subghz_rx_pipe_not_empty _Bool
1349 Function + furi_hal_subghz_set_async_mirror_pin void const GpioPin*
1350 Function + furi_hal_subghz_set_frequency uint32_t uint32_t
1351 Function + furi_hal_subghz_set_frequency_and_path uint32_t uint32_t
1352 Function + furi_hal_subghz_set_path void FuriHalSubGhzPath
1764 Function + loading_alloc Loading*
1765 Function + loading_free void Loading*
1766 Function + loading_get_view View* Loading*
1767 Function + locale_celsius_to_fahrenheit float float
1768 Function + locale_fahrenheit_to_celsius float float
1769 Function + locale_format_date void FuriString*, const FuriHalRtcDateTime*, const LocaleDateFormat, const char*
1770 Function + locale_format_time void FuriString*, const FuriHalRtcDateTime*, const LocaleTimeFormat, const _Bool
1771 Function + locale_get_date_format LocaleDateFormat
1772 Function + locale_get_measurement_unit LocaleMeasurementUnits
1773 Function + locale_get_time_format LocaleTimeFormat
1774 Function + locale_set_date_format void LocaleDateFormat
1775 Function + locale_set_measurement_unit void LocaleMeasurementUnits
1776 Function + locale_set_time_format void LocaleTimeFormat
1777 Function - localtime tm* const time_t*
1778 Function - localtime_r tm* const time_t*, tm*
1779 Function - log double double
2852 Function - subghz_protocol_decoder_secplus_v2_get_string void void*, FuriString*
2853 Function - subghz_protocol_decoder_secplus_v2_reset void void*
2854 Function - subghz_protocol_decoder_secplus_v2_serialize _Bool void*, FlipperFormat*, SubGhzRadioPreset*
2855 Function - subghz_protocol_decoder_smc5326_alloc void* SubGhzEnvironment*
2856 Function - subghz_protocol_decoder_smc5326_deserialize _Bool void*, FlipperFormat*
2857 Function - subghz_protocol_decoder_smc5326_feed void void*, _Bool, uint32_t
2858 Function - subghz_protocol_decoder_smc5326_free void void*
2859 Function - subghz_protocol_decoder_smc5326_get_hash_data uint8_t void*
2860 Function - subghz_protocol_decoder_smc5326_get_string void void*, FuriString*
2861 Function - subghz_protocol_decoder_smc5326_reset void void*
2862 Function - subghz_protocol_decoder_smc5326_serialize _Bool void*, FlipperFormat*, SubGhzRadioPreset*
2863 Function - subghz_protocol_decoder_somfy_keytis_alloc void* SubGhzEnvironment*
2864 Function - subghz_protocol_decoder_somfy_keytis_deserialize _Bool void*, FlipperFormat*
2865 Function - subghz_protocol_decoder_somfy_keytis_feed void void*, _Bool, uint32_t
3030 Function - subghz_protocol_encoder_secplus_v2_free void void*
3031 Function - subghz_protocol_encoder_secplus_v2_stop void void*
3032 Function - subghz_protocol_encoder_secplus_v2_yield LevelDuration void*
3033 Function - subghz_protocol_encoder_smc5326_alloc void* SubGhzEnvironment*
3034 Function - subghz_protocol_encoder_smc5326_deserialize _Bool void*, FlipperFormat*
3035 Function - subghz_protocol_encoder_smc5326_free void void*
3036 Function - subghz_protocol_encoder_smc5326_stop void void*
3037 Function - subghz_protocol_encoder_smc5326_yield LevelDuration void*
3038 Function - subghz_protocol_encoder_star_line_alloc void* SubGhzEnvironment*
3039 Function - subghz_protocol_encoder_star_line_deserialize _Bool void*, FlipperFormat*
3040 Function - subghz_protocol_encoder_star_line_free void void*
4855 Variable - subghz_protocol_secplus_v2 const SubGhzProtocol
4856 Variable - subghz_protocol_secplus_v2_decoder const SubGhzProtocolDecoder
4857 Variable - subghz_protocol_secplus_v2_encoder const SubGhzProtocolEncoder
4858 Variable - subghz_protocol_smc5326 const SubGhzProtocol
4859 Variable - subghz_protocol_smc5326_decoder const SubGhzProtocolDecoder
4860 Variable - subghz_protocol_smc5326_encoder const SubGhzProtocolEncoder
4861 Variable - subghz_protocol_somfy_keytis const SubGhzProtocol
4862 Variable - subghz_protocol_somfy_keytis_decoder const SubGhzProtocolDecoder
4863 Variable - subghz_protocol_somfy_keytis_encoder const SubGhzProtocolEncoder

View File

@@ -29,12 +29,15 @@ typedef struct {
uint8_t log_level : 4;
uint8_t log_reserved : 4;
uint8_t flags;
uint8_t boot_mode : 4;
uint8_t heap_track_mode : 2;
uint16_t reserved : 10;
} DeveloperReg;
FuriHalRtcBootMode boot_mode : 4;
FuriHalRtcHeapTrackMode heap_track_mode : 2;
FuriHalRtcLocaleUnits locale_units : 1;
FuriHalRtcLocaleTimeFormat locale_timeformat : 1;
FuriHalRtcLocaleDateFormat locale_dateformat : 2;
uint8_t reserved : 6;
} SystemReg;
_Static_assert(sizeof(DeveloperReg) == 4, "DeveloperReg size mismatch");
_Static_assert(sizeof(SystemReg) == 4, "SystemReg size mismatch");
#define FURI_HAL_RTC_SECONDS_PER_MINUTE 60
#define FURI_HAL_RTC_SECONDS_PER_HOUR (FURI_HAL_RTC_SECONDS_PER_MINUTE * 60)
@@ -172,7 +175,7 @@ void furi_hal_rtc_set_register(FuriHalRtcRegister reg, uint32_t value) {
void furi_hal_rtc_set_log_level(uint8_t level) {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
DeveloperReg* data = (DeveloperReg*)&data_reg;
SystemReg* data = (SystemReg*)&data_reg;
data->log_level = level;
furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg);
furi_log_set_level(level);
@@ -180,13 +183,13 @@ void furi_hal_rtc_set_log_level(uint8_t level) {
uint8_t furi_hal_rtc_get_log_level() {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
DeveloperReg* data = (DeveloperReg*)&data_reg;
SystemReg* data = (SystemReg*)&data_reg;
return data->log_level;
}
void furi_hal_rtc_set_flag(FuriHalRtcFlag flag) {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
DeveloperReg* data = (DeveloperReg*)&data_reg;
SystemReg* data = (SystemReg*)&data_reg;
data->flags |= flag;
furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg);
@@ -197,7 +200,7 @@ void furi_hal_rtc_set_flag(FuriHalRtcFlag flag) {
void furi_hal_rtc_reset_flag(FuriHalRtcFlag flag) {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
DeveloperReg* data = (DeveloperReg*)&data_reg;
SystemReg* data = (SystemReg*)&data_reg;
data->flags &= ~flag;
furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg);
@@ -208,34 +211,73 @@ void furi_hal_rtc_reset_flag(FuriHalRtcFlag flag) {
bool furi_hal_rtc_is_flag_set(FuriHalRtcFlag flag) {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
DeveloperReg* data = (DeveloperReg*)&data_reg;
SystemReg* data = (SystemReg*)&data_reg;
return data->flags & flag;
}
void furi_hal_rtc_set_boot_mode(FuriHalRtcBootMode mode) {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
DeveloperReg* data = (DeveloperReg*)&data_reg;
SystemReg* data = (SystemReg*)&data_reg;
data->boot_mode = mode;
furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg);
}
FuriHalRtcBootMode furi_hal_rtc_get_boot_mode() {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
DeveloperReg* data = (DeveloperReg*)&data_reg;
return (FuriHalRtcBootMode)data->boot_mode;
SystemReg* data = (SystemReg*)&data_reg;
return data->boot_mode;
}
void furi_hal_rtc_set_heap_track_mode(FuriHalRtcHeapTrackMode mode) {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
DeveloperReg* data = (DeveloperReg*)&data_reg;
SystemReg* data = (SystemReg*)&data_reg;
data->heap_track_mode = mode;
furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg);
}
FuriHalRtcHeapTrackMode furi_hal_rtc_get_heap_track_mode() {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
DeveloperReg* data = (DeveloperReg*)&data_reg;
return (FuriHalRtcHeapTrackMode)data->heap_track_mode;
SystemReg* data = (SystemReg*)&data_reg;
return data->heap_track_mode;
}
void furi_hal_rtc_set_locale_units(FuriHalRtcLocaleUnits value) {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
SystemReg* data = (SystemReg*)&data_reg;
data->locale_units = value;
furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg);
}
FuriHalRtcLocaleUnits furi_hal_rtc_get_locale_units() {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
SystemReg* data = (SystemReg*)&data_reg;
return data->locale_units;
}
void furi_hal_rtc_set_locale_timeformat(FuriHalRtcLocaleTimeFormat value) {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
SystemReg* data = (SystemReg*)&data_reg;
data->locale_timeformat = value;
furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg);
}
FuriHalRtcLocaleTimeFormat furi_hal_rtc_get_locale_timeformat() {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
SystemReg* data = (SystemReg*)&data_reg;
return data->locale_timeformat;
}
void furi_hal_rtc_set_locale_dateformat(FuriHalRtcLocaleDateFormat value) {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
SystemReg* data = (SystemReg*)&data_reg;
data->locale_dateformat = value;
furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg);
}
FuriHalRtcLocaleDateFormat furi_hal_rtc_get_locale_dateformat() {
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
SystemReg* data = (SystemReg*)&data_reg;
return data->locale_dateformat;
}
void furi_hal_rtc_set_datetime(FuriHalRtcDateTime* datetime) {

View File

@@ -1,23 +1,66 @@
#include <furi_hal_speaker.h>
#include <furi_hal_gpio.h>
#include <furi_hal_resources.h>
#include <furi_hal_power.h>
#include <stm32wbxx_ll_tim.h>
#include <furi_hal_cortex.h>
#define TAG "FuriHalSpeaker"
#define FURI_HAL_SPEAKER_TIMER TIM16
#define FURI_HAL_SPEAKER_CHANNEL LL_TIM_CHANNEL_CH1
#define FURI_HAL_SPEAKER_PRESCALER 500
#define FURI_HAL_SPEAKER_MAX_VOLUME 60
static FuriMutex* furi_hal_speaker_mutex = NULL;
// #define FURI_HAL_SPEAKER_NEW_VOLUME
void furi_hal_speaker_init() {
furi_assert(furi_hal_speaker_mutex == NULL);
furi_hal_speaker_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
FURI_CRITICAL_ENTER();
LL_TIM_DeInit(FURI_HAL_SPEAKER_TIMER);
FURI_CRITICAL_EXIT();
FURI_LOG_I(TAG, "Init OK");
}
furi_hal_gpio_init_ex(
&gpio_speaker, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn14TIM16);
void furi_hal_speaker_deinit() {
furi_check(furi_hal_speaker_mutex != NULL);
LL_TIM_DeInit(FURI_HAL_SPEAKER_TIMER);
furi_hal_gpio_init(&gpio_speaker, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
furi_mutex_free(furi_hal_speaker_mutex);
furi_hal_speaker_mutex = NULL;
}
bool furi_hal_speaker_acquire(uint32_t timeout) {
furi_check(!FURI_IS_IRQ_MODE());
if(furi_mutex_acquire(furi_hal_speaker_mutex, timeout) == FuriStatusOk) {
furi_hal_power_insomnia_enter();
furi_hal_gpio_init_ex(
&gpio_speaker, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn14TIM16);
return true;
} else {
return false;
}
}
void furi_hal_speaker_release() {
furi_check(!FURI_IS_IRQ_MODE());
furi_check(furi_hal_speaker_is_mine());
furi_hal_speaker_stop();
furi_hal_gpio_init(&gpio_speaker, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
furi_hal_power_insomnia_exit();
furi_check(furi_mutex_release(furi_hal_speaker_mutex) == FuriStatusOk);
}
bool furi_hal_speaker_is_mine() {
return (FURI_IS_IRQ_MODE()) ||
(furi_mutex_get_owner(furi_hal_speaker_mutex) == furi_thread_get_current_id());
}
static inline uint32_t furi_hal_speaker_calculate_autoreload(float frequency) {
@@ -54,6 +97,8 @@ static inline uint32_t furi_hal_speaker_calculate_compare(float volume) {
}
void furi_hal_speaker_start(float frequency, float volume) {
furi_check(furi_hal_speaker_is_mine());
if(volume <= 0) {
furi_hal_speaker_stop();
return;
@@ -75,6 +120,7 @@ void furi_hal_speaker_start(float frequency, float volume) {
}
void furi_hal_speaker_set_volume(float volume) {
furi_check(furi_hal_speaker_is_mine());
if(volume <= 0) {
furi_hal_speaker_stop();
return;
@@ -88,6 +134,7 @@ void furi_hal_speaker_set_volume(float volume) {
}
void furi_hal_speaker_stop() {
furi_check(furi_hal_speaker_is_mine());
LL_TIM_DisableAllOutputs(FURI_HAL_SPEAKER_TIMER);
LL_TIM_DisableCounter(FURI_HAL_SPEAKER_TIMER);
}

View File

@@ -3,7 +3,6 @@
#include <furi_hal_version.h>
#include <furi_hal_rtc.h>
#include <furi_hal_gpio.h>
#include <furi_hal_spi.h>
#include <furi_hal_interrupt.h>
#include <furi_hal_resources.h>
@@ -18,39 +17,26 @@
#define TAG "FuriHalSubGhz"
/*
* Uncomment define to enable duplication of
* IO GO0 CC1101 to an external comb.
* Debug pin can be assigned
* gpio_ext_pc0
* gpio_ext_pc1
* gpio_ext_pc3
* gpio_ext_pb2
* gpio_ext_pb3
* gpio_ext_pa4
* gpio_ext_pa6
* gpio_ext_pa7
* Attention this setting switches pin to output.
* Make sure it is not connected directly to power or ground
*/
//#define SUBGHZ_DEBUG_CC1101_PIN gpio_ext_pa7
#ifdef SUBGHZ_DEBUG_CC1101_PIN
uint32_t subghz_debug_gpio_buff[2];
#endif
static uint32_t furi_hal_subghz_debug_gpio_buff[2];
typedef struct {
volatile SubGhzState state;
volatile SubGhzRegulation regulation;
volatile FuriHalSubGhzPreset preset;
const GpioPin* async_mirror_pin;
} FuriHalSubGhz;
volatile FuriHalSubGhz furi_hal_subghz = {
.state = SubGhzStateInit,
.regulation = SubGhzRegulationTxRx,
.preset = FuriHalSubGhzPresetIDLE,
.async_mirror_pin = NULL,
};
void furi_hal_subghz_set_async_mirror_pin(const GpioPin* pin) {
furi_hal_subghz.async_mirror_pin = pin;
}
void furi_hal_subghz_init() {
furi_assert(furi_hal_subghz.state == SubGhzStateInit);
furi_hal_subghz.state = SubGhzStateIdle;
@@ -406,6 +392,29 @@ void furi_hal_subghz_set_path(FuriHalSubGhzPath path) {
furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
}
static bool furi_hal_subghz_start_debug() {
bool ret = false;
if(furi_hal_subghz.async_mirror_pin != NULL) {
furi_hal_gpio_init(
furi_hal_subghz.async_mirror_pin,
GpioModeOutputPushPull,
GpioPullNo,
GpioSpeedVeryHigh);
ret = true;
}
return ret;
}
static bool furi_hal_subghz_stop_debug() {
bool ret = false;
if(furi_hal_subghz.async_mirror_pin != NULL) {
furi_hal_gpio_init(
furi_hal_subghz.async_mirror_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
ret = true;
}
return ret;
}
volatile uint32_t furi_hal_subghz_capture_delta_duration = 0;
volatile FuriHalSubGhzCaptureCallback furi_hal_subghz_capture_callback = NULL;
volatile void* furi_hal_subghz_capture_callback_context = NULL;
@@ -416,9 +425,9 @@ static void furi_hal_subghz_capture_ISR() {
LL_TIM_ClearFlag_CC1(TIM2);
furi_hal_subghz_capture_delta_duration = LL_TIM_IC_GetCaptureCH1(TIM2);
if(furi_hal_subghz_capture_callback) {
#ifdef SUBGHZ_DEBUG_CC1101_PIN
furi_hal_gpio_write(&SUBGHZ_DEBUG_CC1101_PIN, false);
#endif
if(furi_hal_subghz.async_mirror_pin != NULL)
furi_hal_gpio_write(furi_hal_subghz.async_mirror_pin, false);
furi_hal_subghz_capture_callback(
true,
furi_hal_subghz_capture_delta_duration,
@@ -429,9 +438,9 @@ static void furi_hal_subghz_capture_ISR() {
if(LL_TIM_IsActiveFlag_CC2(TIM2)) {
LL_TIM_ClearFlag_CC2(TIM2);
if(furi_hal_subghz_capture_callback) {
#ifdef SUBGHZ_DEBUG_CC1101_PIN
furi_hal_gpio_write(&SUBGHZ_DEBUG_CC1101_PIN, true);
#endif
if(furi_hal_subghz.async_mirror_pin != NULL)
furi_hal_gpio_write(furi_hal_subghz.async_mirror_pin, true);
furi_hal_subghz_capture_callback(
false,
LL_TIM_IC_GetCaptureCH2(TIM2) - furi_hal_subghz_capture_delta_duration,
@@ -493,10 +502,8 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void*
LL_TIM_SetCounter(TIM2, 0);
LL_TIM_EnableCounter(TIM2);
#ifdef SUBGHZ_DEBUG_CC1101_PIN
furi_hal_gpio_init(
&SUBGHZ_DEBUG_CC1101_PIN, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
#endif
// Start debug
furi_hal_subghz_start_debug();
// Switch to RX
furi_hal_subghz_rx();
@@ -512,9 +519,8 @@ void furi_hal_subghz_stop_async_rx() {
FURI_CRITICAL_ENTER();
LL_TIM_DeInit(TIM2);
#ifdef SUBGHZ_DEBUG_CC1101_PIN
furi_hal_gpio_init(&SUBGHZ_DEBUG_CC1101_PIN, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
#endif
// Stop debug
furi_hal_subghz_stop_debug();
FURI_CRITICAL_EXIT();
furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, NULL, NULL);
@@ -707,30 +713,27 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
LL_TIM_SetCounter(TIM2, 0);
LL_TIM_EnableCounter(TIM2);
#ifdef SUBGHZ_DEBUG_CC1101_PIN
furi_hal_gpio_init(
&SUBGHZ_DEBUG_CC1101_PIN, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
// Start debug
if(furi_hal_subghz_start_debug()) {
const GpioPin* gpio = furi_hal_subghz.async_mirror_pin;
furi_hal_subghz_debug_gpio_buff[0] = (uint32_t)gpio->pin << GPIO_NUMBER;
furi_hal_subghz_debug_gpio_buff[1] = gpio->pin;
const GpioPin* gpio = &SUBGHZ_DEBUG_CC1101_PIN;
subghz_debug_gpio_buff[0] = (uint32_t)gpio->pin << GPIO_NUMBER;
subghz_debug_gpio_buff[1] = gpio->pin;
dma_config.MemoryOrM2MDstAddress = (uint32_t)subghz_debug_gpio_buff;
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (gpio->port->BSRR);
dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
dma_config.Mode = LL_DMA_MODE_CIRCULAR;
dma_config.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
dma_config.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
dma_config.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD;
dma_config.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD;
dma_config.NbData = 2;
dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP;
dma_config.Priority = LL_DMA_PRIORITY_VERYHIGH;
LL_DMA_Init(DMA1, LL_DMA_CHANNEL_2, &dma_config);
LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_2, 2);
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2);
#endif
dma_config.MemoryOrM2MDstAddress = (uint32_t)furi_hal_subghz_debug_gpio_buff;
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (gpio->port->BSRR);
dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
dma_config.Mode = LL_DMA_MODE_CIRCULAR;
dma_config.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
dma_config.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
dma_config.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD;
dma_config.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD;
dma_config.NbData = 2;
dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP;
dma_config.Priority = LL_DMA_PRIORITY_VERYHIGH;
LL_DMA_Init(DMA1, LL_DMA_CHANNEL_2, &dma_config);
LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_2, 2);
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2);
}
return true;
}
@@ -764,10 +767,10 @@ void furi_hal_subghz_stop_async_tx() {
// Deinitialize GPIO
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
#ifdef SUBGHZ_DEBUG_CC1101_PIN
LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_2);
furi_hal_gpio_init(&SUBGHZ_DEBUG_CC1101_PIN, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
#endif
// Stop debug
if(furi_hal_subghz_stop_debug()) {
LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_2);
}
FURI_CRITICAL_EXIT();

View File

@@ -59,53 +59,194 @@ typedef enum {
FuriHalRtcRegisterMAX, /**< Service value, do not use */
} FuriHalRtcRegister;
typedef enum {
FuriHalRtcLocaleUnitsMetric = 0, /**< Metric measurement units */
FuriHalRtcLocaleUnitsImperial = 1, /**< Imperial measurement units */
} FuriHalRtcLocaleUnits;
typedef enum {
FuriHalRtcLocaleTimeFormat24h = 0, /**< 24-hour format */
FuriHalRtcLocaleTimeFormat12h = 1, /**< 12-hour format */
} FuriHalRtcLocaleTimeFormat;
typedef enum {
FuriHalRtcLocaleDateFormatDMY = 0, /**< Day/Month/Year */
FuriHalRtcLocaleDateFormatMDY = 1, /**< Month/Day/Year */
FuriHalRtcLocaleDateFormatYMD = 2, /**< Year/Month/Day */
} FuriHalRtcLocaleDateFormat;
/** Early initialization */
void furi_hal_rtc_init_early();
/** Early deinitialization */
/** Early de-initialization */
void furi_hal_rtc_deinit_early();
/** Initialize RTC subsystem */
void furi_hal_rtc_init();
/** Get RTC register content
*
* @param[in] reg The register identifier
*
* @return content of the register
*/
uint32_t furi_hal_rtc_get_register(FuriHalRtcRegister reg);
/** Set register content
*
* @param[in] reg The register identifier
* @param[in] value The value to store into register
*/
void furi_hal_rtc_set_register(FuriHalRtcRegister reg, uint32_t value);
/** Set Log Level value
*
* @param[in] level The level to store
*/
void furi_hal_rtc_set_log_level(uint8_t level);
/** Get Log Level value
*
* @return The Log Level value
*/
uint8_t furi_hal_rtc_get_log_level();
/** Set RTC Flag
*
* @param[in] flag The flag to set
*/
void furi_hal_rtc_set_flag(FuriHalRtcFlag flag);
/** Reset RTC Flag
*
* @param[in] flag The flag to reset
*/
void furi_hal_rtc_reset_flag(FuriHalRtcFlag flag);
/** Check if RTC Flag is set
*
* @param[in] flag The flag to check
*
* @return true if set
*/
bool furi_hal_rtc_is_flag_set(FuriHalRtcFlag flag);
/** Set RTC boot mode
*
* @param[in] mode The mode to set
*/
void furi_hal_rtc_set_boot_mode(FuriHalRtcBootMode mode);
/** Get RTC boot mode
*
* @return The RTC boot mode.
*/
FuriHalRtcBootMode furi_hal_rtc_get_boot_mode();
/** Set Heap Track mode
*
* @param[in] mode The mode to set
*/
void furi_hal_rtc_set_heap_track_mode(FuriHalRtcHeapTrackMode mode);
/** Get RTC Heap Track mode
*
* @return The RTC heap track mode.
*/
FuriHalRtcHeapTrackMode furi_hal_rtc_get_heap_track_mode();
/** Set locale units
*
* @param[in] mode The RTC Locale Units
*/
void furi_hal_rtc_set_locale_units(FuriHalRtcLocaleUnits value);
/** Get RTC Locale Units
*
* @return The RTC Locale Units.
*/
FuriHalRtcLocaleUnits furi_hal_rtc_get_locale_units();
/** Set RTC Locale Time Format
*
* @param[in] value The RTC Locale Time Format
*/
void furi_hal_rtc_set_locale_timeformat(FuriHalRtcLocaleTimeFormat value);
/** Get RTC Locale Time Format
*
* @return The RTC Locale Time Format.
*/
FuriHalRtcLocaleTimeFormat furi_hal_rtc_get_locale_timeformat();
/** Set RTC Locale Date Format
*
* @param[in] value The RTC Locale Date Format
*/
void furi_hal_rtc_set_locale_dateformat(FuriHalRtcLocaleDateFormat value);
/** Get RTC Locale Date Format
*
* @return The RTC Locale Date Format
*/
FuriHalRtcLocaleDateFormat furi_hal_rtc_get_locale_dateformat();
/** Set RTC Date Time
*
* @param datetime The date time to set
*/
void furi_hal_rtc_set_datetime(FuriHalRtcDateTime* datetime);
/** Get RTC Date Time
*
* @param datetime The datetime
*/
void furi_hal_rtc_get_datetime(FuriHalRtcDateTime* datetime);
/** Validate Date Time
*
* @param datetime The datetime to validate
*
* @return { description_of_the_return_value }
*/
bool furi_hal_rtc_validate_datetime(FuriHalRtcDateTime* datetime);
/** Set RTC Fault Data
*
* @param[in] value The value
*/
void furi_hal_rtc_set_fault_data(uint32_t value);
/** Get RTC Fault Data
*
* @return RTC Fault Data value
*/
uint32_t furi_hal_rtc_get_fault_data();
/** Set Pin Fails count
*
* @param[in] value The Pin Fails count
*/
void furi_hal_rtc_set_pin_fails(uint32_t value);
/** Get Pin Fails count
*
* @return Pin Fails Count
*/
uint32_t furi_hal_rtc_get_pin_fails();
/** Get UNIX Timestamp
*
* @return Unix Timestamp in seconds from UNIX epoch start
*/
uint32_t furi_hal_rtc_get_timestamp();
/** Convert DateTime to UNIX timestamp
*
* @param datetime The datetime
*
* @return UNIX Timestamp in seconds from UNIX epoch start
*/
uint32_t furi_hal_rtc_datetime_to_timestamp(FuriHalRtcDateTime* datetime);
#ifdef __cplusplus

View File

@@ -4,16 +4,63 @@
*/
#pragma once
#include <furi.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Init speaker */
void furi_hal_speaker_init();
/** Deinit speaker */
void furi_hal_speaker_deinit();
/** Acquire speaker ownership
*
* @warning You must acquire speaker ownership before use
*
* @param timeout Timeout during which speaker ownership must be acquired
*
* @return bool returns true on success
*/
FURI_WARN_UNUSED bool furi_hal_speaker_acquire(uint32_t timeout);
/** Release speaker ownership
*
* @warning You must release speaker ownership after use
*/
void furi_hal_speaker_release();
/** Check current process speaker ownership
*
* @warning always returns true if called from ISR
*
* @return bool returns true if process owns speaker
*/
bool furi_hal_speaker_is_mine();
/** Play a note
*
* @warning no ownership check if called from ISR
*
* @param frequency The frequency
* @param volume The volume
*/
void furi_hal_speaker_start(float frequency, float volume);
/** Set volume
*
* @warning no ownership check if called from ISR
*
* @param volume The volume
*/
void furi_hal_speaker_set_volume(float volume);
/** Stop playback
*
* @warning no ownership check if called from ISR
*/
void furi_hal_speaker_stop();
#ifdef __cplusplus

View File

@@ -9,6 +9,7 @@
#include <stdint.h>
#include <stddef.h>
#include <toolbox/level_duration.h>
#include <furi_hal_gpio.h>
#ifdef __cplusplus
extern "C" {
@@ -34,9 +35,9 @@ typedef enum {
/** Switchable Radio Paths */
typedef enum {
FuriHalSubGhzPathIsolate, /**< Isolate Radio from antenna */
FuriHalSubGhzPath433, /**< Center Frquency: 433MHz. Path 1: SW1RF1-SW2RF2, LCLCL */
FuriHalSubGhzPath315, /**< Center Frquency: 315MHz. Path 2: SW1RF2-SW2RF1, LCLCLCL */
FuriHalSubGhzPath868, /**< Center Frquency: 868MHz. Path 3: SW1RF3-SW2RF3, LCLC */
FuriHalSubGhzPath433, /**< Center Frequency: 433MHz. Path 1: SW1RF1-SW2RF2, LCLCL */
FuriHalSubGhzPath315, /**< Center Frequency: 315MHz. Path 2: SW1RF2-SW2RF1, LCLCLCL */
FuriHalSubGhzPath868, /**< Center Frequency: 868MHz. Path 3: SW1RF3-SW2RF3, LCLC */
} FuriHalSubGhzPath;
/** SubGhz state */
@@ -60,8 +61,17 @@ typedef enum {
SubGhzRegulationTxRx, /**TxRx*/
} SubGhzRegulation;
/* Mirror RX/TX async modulation signal to specified pin
*
* @warning Configures pin to output mode. Make sure it is not connected
* directly to power or ground.
*
* @param[in] pin pointer to the gpio pin structure or NULL to disable
*/
void furi_hal_subghz_set_async_mirror_pin(const GpioPin* pin);
/** Initialize and switch to power save mode Used by internal API-HAL
* initalization routine Can be used to reinitialize device to safe state and
* initialization routine Can be used to reinitialize device to safe state and
* send it to sleep
*/
void furi_hal_subghz_init();
@@ -105,13 +115,13 @@ void furi_hal_subghz_load_patable(const uint8_t data[8]);
*/
void furi_hal_subghz_write_packet(const uint8_t* data, uint8_t size);
/** Check if recieve pipe is not empty
/** Check if receive pipe is not empty
*
* @return true if not empty
*/
bool furi_hal_subghz_rx_pipe_not_empty();
/** Check if recieved data crc is valid
/** Check if received data crc is valid
*
* @return true if valid
*/
@@ -132,7 +142,7 @@ void furi_hal_subghz_flush_rx();
*/
void furi_hal_subghz_flush_tx();
/** Shutdown Issue spwd command
/** Shutdown Issue SPWD command
* @warning registers content will be lost
*/
void furi_hal_subghz_shutdown();
@@ -146,7 +156,7 @@ void furi_hal_subghz_reset();
*/
void furi_hal_subghz_idle();
/** Switch to Recieve
/** Switch to Receive
*/
void furi_hal_subghz_rx();
@@ -172,7 +182,7 @@ uint8_t furi_hal_subghz_get_lqi();
*
* @param value frequency in Hz
*
* @return true if frequncy is valid, otherwise false
* @return true if frequency is valid, otherwise false
*/
bool furi_hal_subghz_is_frequency_valid(uint32_t value);
@@ -181,7 +191,7 @@ bool furi_hal_subghz_is_frequency_valid(uint32_t value);
*
* @param value frequency in Hz
*
* @return real frequency in herz
* @return real frequency in Hz
*/
uint32_t furi_hal_subghz_set_frequency_and_path(uint32_t value);
@@ -197,7 +207,7 @@ bool furi_hal_subghz_is_tx_allowed(uint32_t value);
*
* @param value frequency in Hz
*
* @return real frequency in herz
* @return real frequency in Hz
*/
uint32_t furi_hal_subghz_set_frequency(uint32_t value);

View File

@@ -11,6 +11,10 @@ extern "C" {
#include <cmsis_compiler.h>
#ifndef FURI_WARN_UNUSED
#define FURI_WARN_UNUSED __attribute__((warn_unused_result))
#endif
#ifndef FURI_IS_IRQ_MASKED
#define FURI_IS_IRQ_MASKED() (__get_PRIMASK() != 0U)
#endif

View File

@@ -1,6 +1,7 @@
#include "lfrfid_protocols.h"
#include "protocol_em4100.h"
#include "protocol_h10301.h"
#include "protocol_idteck.h"
#include "protocol_indala26.h"
#include "protocol_io_prox_xsf.h"
#include "protocol_awid.h"
@@ -19,6 +20,7 @@
const ProtocolBase* lfrfid_protocols[] = {
[LFRFIDProtocolEM4100] = &protocol_em4100,
[LFRFIDProtocolH10301] = &protocol_h10301,
[LFRFIDProtocolIdteck] = &protocol_idteck,
[LFRFIDProtocolIndala26] = &protocol_indala26,
[LFRFIDProtocolIOProxXSF] = &protocol_io_prox_xsf,
[LFRFIDProtocolAwid] = &protocol_awid,

View File

@@ -10,6 +10,7 @@ typedef enum {
typedef enum {
LFRFIDProtocolEM4100,
LFRFIDProtocolH10301,
LFRFIDProtocolIdteck,
LFRFIDProtocolIndala26,
LFRFIDProtocolIOProxXSF,
LFRFIDProtocolAwid,

View File

@@ -0,0 +1,269 @@
#include <furi.h>
#include <toolbox/protocols/protocol.h>
#include <lfrfid/tools/bit_lib.h>
#include "lfrfid_protocols.h"
// Example: 4944544B 351FBE4B
// 01001001 01000100 01010100 01001011 00110101 00011111 10111110 01001011
// 4 9 4 4 5 4 4 B 3 5 1 F B E 4 B
// 0100 1001 0100 0100 0101 0100 0100 1011 0011 0101 0001 1111 1011 1110 0100 1011
#define IDTECK_PREAMBLE_BIT_SIZE (32)
#define IDTECK_PREAMBLE_DATA_SIZE (8)
#define IDTECK_ENCODED_BIT_SIZE (64)
#define IDTECK_ENCODED_DATA_SIZE (((IDTECK_ENCODED_BIT_SIZE) / 8) + IDTECK_PREAMBLE_DATA_SIZE)
#define IDTECK_ENCODED_DATA_LAST ((IDTECK_ENCODED_BIT_SIZE) / 8)
#define IDTECK_DECODED_BIT_SIZE (64)
#define IDTECK_DECODED_DATA_SIZE (8)
#define IDTECK_US_PER_BIT (255)
#define IDTECK_ENCODER_PULSES_PER_BIT (16)
typedef struct {
uint8_t data_index;
uint8_t bit_clock_index;
bool last_bit;
bool current_polarity;
bool pulse_phase;
} ProtocolIdteckEncoder;
typedef struct {
uint8_t encoded_data[IDTECK_ENCODED_DATA_SIZE];
uint8_t negative_encoded_data[IDTECK_ENCODED_DATA_SIZE];
uint8_t corrupted_encoded_data[IDTECK_ENCODED_DATA_SIZE];
uint8_t corrupted_negative_encoded_data[IDTECK_ENCODED_DATA_SIZE];
uint8_t data[IDTECK_DECODED_DATA_SIZE];
ProtocolIdteckEncoder encoder;
} ProtocolIdteck;
ProtocolIdteck* protocol_idteck_alloc(void) {
ProtocolIdteck* protocol = malloc(sizeof(ProtocolIdteck));
return protocol;
};
void protocol_idteck_free(ProtocolIdteck* protocol) {
free(protocol);
};
uint8_t* protocol_idteck_get_data(ProtocolIdteck* protocol) {
return protocol->data;
};
void protocol_idteck_decoder_start(ProtocolIdteck* protocol) {
memset(protocol->encoded_data, 0, IDTECK_ENCODED_DATA_SIZE);
memset(protocol->negative_encoded_data, 0, IDTECK_ENCODED_DATA_SIZE);
memset(protocol->corrupted_encoded_data, 0, IDTECK_ENCODED_DATA_SIZE);
memset(protocol->corrupted_negative_encoded_data, 0, IDTECK_ENCODED_DATA_SIZE);
};
static bool protocol_idteck_check_preamble(uint8_t* data, size_t bit_index) {
// Preamble 01001001 01000100 01010100 01001011
if(*(uint32_t*)&data[bit_index / 8] != 0b01001011010101000100010001001001) return false;
return true;
}
static bool protocol_idteck_can_be_decoded(uint8_t* data) {
if(!protocol_idteck_check_preamble(data, 0)) return false;
return true;
}
static bool protocol_idteck_decoder_feed_internal(bool polarity, uint32_t time, uint8_t* data) {
time += (IDTECK_US_PER_BIT / 2);
size_t bit_count = (time / IDTECK_US_PER_BIT);
bool result = false;
if(bit_count < IDTECK_ENCODED_BIT_SIZE) {
for(size_t i = 0; i < bit_count; i++) {
bit_lib_push_bit(data, IDTECK_ENCODED_DATA_SIZE, polarity);
if(protocol_idteck_can_be_decoded(data)) {
result = true;
break;
}
}
}
return result;
}
static void protocol_idteck_decoder_save(uint8_t* data_to, const uint8_t* data_from) {
bit_lib_copy_bits(data_to, 0, 64, data_from, 0);
}
bool protocol_idteck_decoder_feed(ProtocolIdteck* protocol, bool level, uint32_t duration) {
bool result = false;
if(duration > (IDTECK_US_PER_BIT / 2)) {
if(protocol_idteck_decoder_feed_internal(level, duration, protocol->encoded_data)) {
protocol_idteck_decoder_save(protocol->data, protocol->encoded_data);
FURI_LOG_D("Idteck", "Positive");
result = true;
return result;
}
if(protocol_idteck_decoder_feed_internal(
!level, duration, protocol->negative_encoded_data)) {
protocol_idteck_decoder_save(protocol->data, protocol->negative_encoded_data);
FURI_LOG_D("Idteck", "Negative");
result = true;
return result;
}
}
if(duration > (IDTECK_US_PER_BIT / 4)) {
// Try to decode wrong phase synced data
if(level) {
duration += 120;
} else {
if(duration > 120) {
duration -= 120;
}
}
if(protocol_idteck_decoder_feed_internal(
level, duration, protocol->corrupted_encoded_data)) {
protocol_idteck_decoder_save(protocol->data, protocol->corrupted_encoded_data);
FURI_LOG_D("Idteck", "Positive Corrupted");
result = true;
return result;
}
if(protocol_idteck_decoder_feed_internal(
!level, duration, protocol->corrupted_negative_encoded_data)) {
protocol_idteck_decoder_save(
protocol->data, protocol->corrupted_negative_encoded_data);
FURI_LOG_D("Idteck", "Negative Corrupted");
result = true;
return result;
}
}
return result;
};
bool protocol_idteck_encoder_start(ProtocolIdteck* protocol) {
memset(protocol->encoded_data, 0, IDTECK_ENCODED_DATA_SIZE);
*(uint32_t*)&protocol->encoded_data[0] = 0b01001011010101000100010001001001;
bit_lib_copy_bits(protocol->encoded_data, 32, 32, protocol->data, 32);
protocol->encoder.last_bit =
bit_lib_get_bit(protocol->encoded_data, IDTECK_ENCODED_BIT_SIZE - 1);
protocol->encoder.data_index = 0;
protocol->encoder.current_polarity = true;
protocol->encoder.pulse_phase = true;
protocol->encoder.bit_clock_index = 0;
return true;
};
LevelDuration protocol_idteck_encoder_yield(ProtocolIdteck* protocol) {
LevelDuration level_duration;
ProtocolIdteckEncoder* encoder = &protocol->encoder;
if(encoder->pulse_phase) {
level_duration = level_duration_make(encoder->current_polarity, 1);
encoder->pulse_phase = false;
} else {
level_duration = level_duration_make(!encoder->current_polarity, 1);
encoder->pulse_phase = true;
encoder->bit_clock_index++;
if(encoder->bit_clock_index >= IDTECK_ENCODER_PULSES_PER_BIT) {
encoder->bit_clock_index = 0;
bool current_bit = bit_lib_get_bit(protocol->encoded_data, encoder->data_index);
if(current_bit != encoder->last_bit) {
encoder->current_polarity = !encoder->current_polarity;
}
encoder->last_bit = current_bit;
bit_lib_increment_index(encoder->data_index, IDTECK_ENCODED_BIT_SIZE);
}
}
return level_duration;
};
// factory code
static uint32_t get_fc(const uint8_t* data) {
uint32_t fc = 0;
fc = bit_lib_get_bits_32(data, 0, 32);
return fc;
}
// card number
static uint32_t get_card(const uint8_t* data) {
uint32_t cn = 0;
cn = bit_lib_get_bits_32(data, 32, 32);
return cn;
}
void protocol_idteck_render_data_internal(ProtocolIdteck* protocol, FuriString* result, bool brief) {
const uint32_t fc = get_fc(protocol->data);
const uint32_t card = get_card(protocol->data);
if(brief) {
furi_string_printf(result, "FC: %08lX\r\nCard: %08lX", fc, card);
} else {
furi_string_printf(
result,
"FC: %08lX\r\n"
"Card: %08lX\r\n",
fc,
card);
}
}
void protocol_idteck_render_data(ProtocolIdteck* protocol, FuriString* result) {
protocol_idteck_render_data_internal(protocol, result, false);
}
void protocol_idteck_render_brief_data(ProtocolIdteck* protocol, FuriString* result) {
protocol_idteck_render_data_internal(protocol, result, true);
}
bool protocol_idteck_write_data(ProtocolIdteck* protocol, void* data) {
LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data;
bool result = false;
protocol_idteck_encoder_start(protocol);
if(request->write_type == LFRFIDWriteTypeT5577) {
request->t5577.block[0] = LFRFID_T5577_BITRATE_RF_32 | LFRFID_T5577_MODULATION_PSK1 |
(2 << LFRFID_T5577_MAXBLOCK_SHIFT);
request->t5577.block[1] = bit_lib_get_bits_32(protocol->encoded_data, 0, 32);
request->t5577.block[2] = bit_lib_get_bits_32(protocol->encoded_data, 32, 32);
request->t5577.blocks_to_write = 3;
result = true;
}
return result;
};
const ProtocolBase protocol_idteck = {
.name = "Idteck",
.manufacturer = "IDTECK",
.data_size = IDTECK_DECODED_DATA_SIZE,
.features = LFRFIDFeaturePSK,
.validate_count = 6,
.alloc = (ProtocolAlloc)protocol_idteck_alloc,
.free = (ProtocolFree)protocol_idteck_free,
.get_data = (ProtocolGetData)protocol_idteck_get_data,
.decoder =
{
.start = (ProtocolDecoderStart)protocol_idteck_decoder_start,
.feed = (ProtocolDecoderFeed)protocol_idteck_decoder_feed,
},
.encoder =
{
.start = (ProtocolEncoderStart)protocol_idteck_encoder_start,
.yield = (ProtocolEncoderYield)protocol_idteck_encoder_yield,
},
.render_data = (ProtocolRenderData)protocol_idteck_render_data,
.render_brief_data = (ProtocolRenderData)protocol_idteck_render_brief_data,
.write_data = (ProtocolWriteData)protocol_idteck_write_data,
};

View File

@@ -0,0 +1,4 @@
#pragma once
#include <toolbox/protocols/protocol.h>
extern const ProtocolBase protocol_idteck;

View File

@@ -12,7 +12,7 @@ const SubGhzProtocol* subghz_protocol_registry_items[] = {
&subghz_protocol_chamb_code, &subghz_protocol_power_smart, &subghz_protocol_marantec,
&subghz_protocol_bett, &subghz_protocol_doitrand, &subghz_protocol_phoenix_v2,
&subghz_protocol_honeywell_wdb, &subghz_protocol_magellan, &subghz_protocol_intertechno_v3,
&subghz_protocol_clemsa, &subghz_protocol_ansonic,
&subghz_protocol_clemsa, &subghz_protocol_ansonic, &subghz_protocol_smc5326,
};
const SubGhzProtocolRegistry subghz_protocol_registry = {

View File

@@ -36,6 +36,7 @@
#include "intertechno_v3.h"
#include "clemsa.h"
#include "ansonic.h"
#include "smc5326.h"
#ifdef __cplusplus
extern "C" {

View File

@@ -0,0 +1,387 @@
#include "smc5326.h"
#include "../blocks/const.h"
#include "../blocks/decoder.h"
#include "../blocks/encoder.h"
#include "../blocks/generic.h"
#include "../blocks/math.h"
/*
* Help
* https://datasheetspdf.com/pdf-file/532079/Aslic/AX5326-4/1
*
*/
#define TAG "SubGhzProtocolSMC5326"
#define DIP_P 0b11 //(+)
#define DIP_O 0b10 //(0)
#define DIP_N 0b00 //(-)
#define DIP_PATTERN "%c%c%c%c%c%c%c%c"
#define SHOW_DIP_P(dip, check_dip) \
((((dip >> 0xE) & 0x3) == check_dip) ? '*' : '_'), \
((((dip >> 0xC) & 0x3) == check_dip) ? '*' : '_'), \
((((dip >> 0xA) & 0x3) == check_dip) ? '*' : '_'), \
((((dip >> 0x8) & 0x3) == check_dip) ? '*' : '_'), \
((((dip >> 0x6) & 0x3) == check_dip) ? '*' : '_'), \
((((dip >> 0x4) & 0x3) == check_dip) ? '*' : '_'), \
((((dip >> 0x2) & 0x3) == check_dip) ? '*' : '_'), \
((((dip >> 0x0) & 0x3) == check_dip) ? '*' : '_')
static const SubGhzBlockConst subghz_protocol_smc5326_const = {
.te_short = 300,
.te_long = 900,
.te_delta = 200,
.min_count_bit_for_found = 25,
};
struct SubGhzProtocolDecoderSMC5326 {
SubGhzProtocolDecoderBase base;
SubGhzBlockDecoder decoder;
SubGhzBlockGeneric generic;
uint32_t te;
uint32_t last_data;
};
struct SubGhzProtocolEncoderSMC5326 {
SubGhzProtocolEncoderBase base;
SubGhzProtocolBlockEncoder encoder;
SubGhzBlockGeneric generic;
uint32_t te;
};
typedef enum {
SMC5326DecoderStepReset = 0,
SMC5326DecoderStepSaveDuration,
SMC5326DecoderStepCheckDuration,
} SMC5326DecoderStep;
const SubGhzProtocolDecoder subghz_protocol_smc5326_decoder = {
.alloc = subghz_protocol_decoder_smc5326_alloc,
.free = subghz_protocol_decoder_smc5326_free,
.feed = subghz_protocol_decoder_smc5326_feed,
.reset = subghz_protocol_decoder_smc5326_reset,
.get_hash_data = subghz_protocol_decoder_smc5326_get_hash_data,
.serialize = subghz_protocol_decoder_smc5326_serialize,
.deserialize = subghz_protocol_decoder_smc5326_deserialize,
.get_string = subghz_protocol_decoder_smc5326_get_string,
};
const SubGhzProtocolEncoder subghz_protocol_smc5326_encoder = {
.alloc = subghz_protocol_encoder_smc5326_alloc,
.free = subghz_protocol_encoder_smc5326_free,
.deserialize = subghz_protocol_encoder_smc5326_deserialize,
.stop = subghz_protocol_encoder_smc5326_stop,
.yield = subghz_protocol_encoder_smc5326_yield,
};
const SubGhzProtocol subghz_protocol_smc5326 = {
.name = SUBGHZ_PROTOCOL_SMC5326_NAME,
.type = SubGhzProtocolTypeStatic,
.flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_868 | SubGhzProtocolFlag_315 |
SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Load |
SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send,
.decoder = &subghz_protocol_smc5326_decoder,
.encoder = &subghz_protocol_smc5326_encoder,
};
void* subghz_protocol_encoder_smc5326_alloc(SubGhzEnvironment* environment) {
UNUSED(environment);
SubGhzProtocolEncoderSMC5326* instance = malloc(sizeof(SubGhzProtocolEncoderSMC5326));
instance->base.protocol = &subghz_protocol_smc5326;
instance->generic.protocol_name = instance->base.protocol->name;
instance->encoder.repeat = 10;
instance->encoder.size_upload = 128;
instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration));
instance->encoder.is_running = false;
return instance;
}
void subghz_protocol_encoder_smc5326_free(void* context) {
furi_assert(context);
SubGhzProtocolEncoderSMC5326* instance = context;
free(instance->encoder.upload);
free(instance);
}
/**
* Generating an upload from data.
* @param instance Pointer to a SubGhzProtocolEncoderSMC5326 instance
* @return true On success
*/
static bool subghz_protocol_encoder_smc5326_get_upload(SubGhzProtocolEncoderSMC5326* instance) {
furi_assert(instance);
size_t index = 0;
size_t size_upload = (instance->generic.data_count_bit * 2) + 2;
if(size_upload > instance->encoder.size_upload) {
FURI_LOG_E(TAG, "Size upload exceeds allocated encoder buffer.");
return false;
} else {
instance->encoder.size_upload = size_upload;
}
//Send key data
for(uint8_t i = instance->generic.data_count_bit; i > 0; i--) {
if(bit_read(instance->generic.data, i - 1)) {
//send bit 1
instance->encoder.upload[index++] =
level_duration_make(true, (uint32_t)instance->te * 3);
instance->encoder.upload[index++] = level_duration_make(false, (uint32_t)instance->te);
} else {
//send bit 0
instance->encoder.upload[index++] = level_duration_make(true, (uint32_t)instance->te);
instance->encoder.upload[index++] =
level_duration_make(false, (uint32_t)instance->te * 3);
}
}
//Send Stop bit
instance->encoder.upload[index++] = level_duration_make(true, (uint32_t)instance->te);
//Send PT_GUARD
instance->encoder.upload[index++] = level_duration_make(false, (uint32_t)instance->te * 25);
return true;
}
bool subghz_protocol_encoder_smc5326_deserialize(void* context, FlipperFormat* flipper_format) {
furi_assert(context);
SubGhzProtocolEncoderSMC5326* instance = context;
bool res = false;
do {
if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) {
FURI_LOG_E(TAG, "Deserialize error");
break;
}
if(!flipper_format_rewind(flipper_format)) {
FURI_LOG_E(TAG, "Rewind error");
break;
}
if(!flipper_format_read_uint32(flipper_format, "TE", (uint32_t*)&instance->te, 1)) {
FURI_LOG_E(TAG, "Missing TE");
break;
}
if(instance->generic.data_count_bit !=
subghz_protocol_smc5326_const.min_count_bit_for_found) {
FURI_LOG_E(TAG, "Wrong number of bits in key");
break;
}
//optional parameter parameter
flipper_format_read_uint32(
flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1);
if(!subghz_protocol_encoder_smc5326_get_upload(instance)) break;
instance->encoder.is_running = true;
res = true;
} while(false);
return res;
}
void subghz_protocol_encoder_smc5326_stop(void* context) {
SubGhzProtocolEncoderSMC5326* instance = context;
instance->encoder.is_running = false;
}
LevelDuration subghz_protocol_encoder_smc5326_yield(void* context) {
SubGhzProtocolEncoderSMC5326* instance = context;
if(instance->encoder.repeat == 0 || !instance->encoder.is_running) {
instance->encoder.is_running = false;
return level_duration_reset();
}
LevelDuration ret = instance->encoder.upload[instance->encoder.front];
if(++instance->encoder.front == instance->encoder.size_upload) {
instance->encoder.repeat--;
instance->encoder.front = 0;
}
return ret;
}
void* subghz_protocol_decoder_smc5326_alloc(SubGhzEnvironment* environment) {
UNUSED(environment);
SubGhzProtocolDecoderSMC5326* instance = malloc(sizeof(SubGhzProtocolDecoderSMC5326));
instance->base.protocol = &subghz_protocol_smc5326;
instance->generic.protocol_name = instance->base.protocol->name;
return instance;
}
void subghz_protocol_decoder_smc5326_free(void* context) {
furi_assert(context);
SubGhzProtocolDecoderSMC5326* instance = context;
free(instance);
}
void subghz_protocol_decoder_smc5326_reset(void* context) {
furi_assert(context);
SubGhzProtocolDecoderSMC5326* instance = context;
instance->decoder.parser_step = SMC5326DecoderStepReset;
instance->last_data = 0;
}
void subghz_protocol_decoder_smc5326_feed(void* context, bool level, uint32_t duration) {
furi_assert(context);
SubGhzProtocolDecoderSMC5326* instance = context;
switch(instance->decoder.parser_step) {
case SMC5326DecoderStepReset:
if((!level) && (DURATION_DIFF(duration, subghz_protocol_smc5326_const.te_short * 24) <
subghz_protocol_smc5326_const.te_delta * 12)) {
//Found Preambula
instance->decoder.parser_step = SMC5326DecoderStepSaveDuration;
instance->decoder.decode_data = 0;
instance->decoder.decode_count_bit = 0;
instance->te = 0;
}
break;
case SMC5326DecoderStepSaveDuration:
//save duration
if(level) {
instance->decoder.te_last = duration;
instance->te += duration;
instance->decoder.parser_step = SMC5326DecoderStepCheckDuration;
}
break;
case SMC5326DecoderStepCheckDuration:
if(!level) {
if(duration >= ((uint32_t)subghz_protocol_smc5326_const.te_long * 2)) {
instance->decoder.parser_step = SMC5326DecoderStepSaveDuration;
if(instance->decoder.decode_count_bit ==
subghz_protocol_smc5326_const.min_count_bit_for_found) {
if((instance->last_data == instance->decoder.decode_data) &&
instance->last_data) {
instance->te /= (instance->decoder.decode_count_bit * 4 + 1);
instance->generic.data = instance->decoder.decode_data;
instance->generic.data_count_bit = instance->decoder.decode_count_bit;
if(instance->base.callback)
instance->base.callback(&instance->base, instance->base.context);
}
instance->last_data = instance->decoder.decode_data;
}
instance->decoder.decode_data = 0;
instance->decoder.decode_count_bit = 0;
instance->te = 0;
break;
}
instance->te += duration;
if((DURATION_DIFF(instance->decoder.te_last, subghz_protocol_smc5326_const.te_short) <
subghz_protocol_smc5326_const.te_delta) &&
(DURATION_DIFF(duration, subghz_protocol_smc5326_const.te_long) <
subghz_protocol_smc5326_const.te_delta * 3)) {
subghz_protocol_blocks_add_bit(&instance->decoder, 0);
instance->decoder.parser_step = SMC5326DecoderStepSaveDuration;
} else if(
(DURATION_DIFF(instance->decoder.te_last, subghz_protocol_smc5326_const.te_long) <
subghz_protocol_smc5326_const.te_delta * 3) &&
(DURATION_DIFF(duration, subghz_protocol_smc5326_const.te_short) <
subghz_protocol_smc5326_const.te_delta)) {
subghz_protocol_blocks_add_bit(&instance->decoder, 1);
instance->decoder.parser_step = SMC5326DecoderStepSaveDuration;
} else {
instance->decoder.parser_step = SMC5326DecoderStepReset;
}
} else {
instance->decoder.parser_step = SMC5326DecoderStepReset;
}
break;
}
}
uint8_t subghz_protocol_decoder_smc5326_get_hash_data(void* context) {
furi_assert(context);
SubGhzProtocolDecoderSMC5326* instance = context;
return subghz_protocol_blocks_get_hash_data(
&instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
}
bool subghz_protocol_decoder_smc5326_serialize(
void* context,
FlipperFormat* flipper_format,
SubGhzRadioPreset* preset) {
furi_assert(context);
SubGhzProtocolDecoderSMC5326* instance = context;
bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
if(res && !flipper_format_write_uint32(flipper_format, "TE", &instance->te, 1)) {
FURI_LOG_E(TAG, "Unable to add TE");
res = false;
}
return res;
}
bool subghz_protocol_decoder_smc5326_deserialize(void* context, FlipperFormat* flipper_format) {
furi_assert(context);
SubGhzProtocolDecoderSMC5326* instance = context;
bool res = false;
do {
if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) {
FURI_LOG_E(TAG, "Deserialize error");
break;
}
if(instance->generic.data_count_bit !=
subghz_protocol_smc5326_const.min_count_bit_for_found) {
FURI_LOG_E(TAG, "Wrong number of bits in key");
break;
}
if(!flipper_format_rewind(flipper_format)) {
FURI_LOG_E(TAG, "Rewind error");
break;
}
if(!flipper_format_read_uint32(flipper_format, "TE", (uint32_t*)&instance->te, 1)) {
FURI_LOG_E(TAG, "Missing TE");
break;
}
res = true;
} while(false);
return res;
}
static void subghz_protocol_smc5326_get_event_serialize(uint8_t event, FuriString* output) {
furi_string_cat_printf(
output,
"%s%s%s%s\r\n",
(((event >> 6) & 0x3) == 0x3 ? "B1 " : ""),
(((event >> 4) & 0x3) == 0x3 ? "B2 " : ""),
(((event >> 2) & 0x3) == 0x3 ? "B3 " : ""),
(((event >> 0) & 0x3) == 0x3 ? "B4 " : ""));
}
void subghz_protocol_decoder_smc5326_get_string(void* context, FuriString* output) {
furi_assert(context);
SubGhzProtocolDecoderSMC5326* instance = context;
uint32_t data = (uint32_t)((instance->generic.data >> 9) & 0xFFFF);
furi_string_cat_printf(
output,
"%s %dbit\r\n"
"Key:%07lX Te:%ldus\r\n"
" +: " DIP_PATTERN "\r\n"
" o: " DIP_PATTERN " ",
instance->generic.protocol_name,
instance->generic.data_count_bit,
(uint32_t)(instance->generic.data & 0x1FFFFFF),
instance->te,
SHOW_DIP_P(data, DIP_P),
SHOW_DIP_P(data, DIP_O));
subghz_protocol_smc5326_get_event_serialize(instance->generic.data >> 1, output);
furi_string_cat_printf(output, " -: " DIP_PATTERN "\r\n", SHOW_DIP_P(data, DIP_N));
}

View File

@@ -0,0 +1,107 @@
#pragma once
#include "base.h"
#define SUBGHZ_PROTOCOL_SMC5326_NAME "SMC5326"
typedef struct SubGhzProtocolDecoderSMC5326 SubGhzProtocolDecoderSMC5326;
typedef struct SubGhzProtocolEncoderSMC5326 SubGhzProtocolEncoderSMC5326;
extern const SubGhzProtocolDecoder subghz_protocol_smc5326_decoder;
extern const SubGhzProtocolEncoder subghz_protocol_smc5326_encoder;
extern const SubGhzProtocol subghz_protocol_smc5326;
/**
* Allocate SubGhzProtocolEncoderSMC5326.
* @param environment Pointer to a SubGhzEnvironment instance
* @return SubGhzProtocolEncoderSMC5326* pointer to a SubGhzProtocolEncoderSMC5326 instance
*/
void* subghz_protocol_encoder_smc5326_alloc(SubGhzEnvironment* environment);
/**
* Free SubGhzProtocolEncoderSMC5326.
* @param context Pointer to a SubGhzProtocolEncoderSMC5326 instance
*/
void subghz_protocol_encoder_smc5326_free(void* context);
/**
* Deserialize and generating an upload to send.
* @param context Pointer to a SubGhzProtocolEncoderSMC5326 instance
* @param flipper_format Pointer to a FlipperFormat instance
* @return true On success
*/
bool subghz_protocol_encoder_smc5326_deserialize(void* context, FlipperFormat* flipper_format);
/**
* Forced transmission stop.
* @param context Pointer to a SubGhzProtocolEncoderSMC5326 instance
*/
void subghz_protocol_encoder_smc5326_stop(void* context);
/**
* Getting the level and duration of the upload to be loaded into DMA.
* @param context Pointer to a SubGhzProtocolEncoderSMC5326 instance
* @return LevelDuration
*/
LevelDuration subghz_protocol_encoder_smc5326_yield(void* context);
/**
* Allocate SubGhzProtocolDecoderSMC5326.
* @param environment Pointer to a SubGhzEnvironment instance
* @return SubGhzProtocolDecoderSMC5326* pointer to a SubGhzProtocolDecoderSMC5326 instance
*/
void* subghz_protocol_decoder_smc5326_alloc(SubGhzEnvironment* environment);
/**
* Free SubGhzProtocolDecoderSMC5326.
* @param context Pointer to a SubGhzProtocolDecoderSMC5326 instance
*/
void subghz_protocol_decoder_smc5326_free(void* context);
/**
* Reset decoder SubGhzProtocolDecoderSMC5326.
* @param context Pointer to a SubGhzProtocolDecoderSMC5326 instance
*/
void subghz_protocol_decoder_smc5326_reset(void* context);
/**
* Parse a raw sequence of levels and durations received from the air.
* @param context Pointer to a SubGhzProtocolDecoderSMC5326 instance
* @param level Signal level true-high false-low
* @param duration Duration of this level in, us
*/
void subghz_protocol_decoder_smc5326_feed(void* context, bool level, uint32_t duration);
/**
* Getting the hash sum of the last randomly received parcel.
* @param context Pointer to a SubGhzProtocolDecoderSMC5326 instance
* @return hash Hash sum
*/
uint8_t subghz_protocol_decoder_smc5326_get_hash_data(void* context);
/**
* Serialize data SubGhzProtocolDecoderSMC5326.
* @param context Pointer to a SubGhzProtocolDecoderSMC5326 instance
* @param flipper_format Pointer to a FlipperFormat instance
* @param preset The modulation on which the signal was received, SubGhzRadioPreset
* @return true On success
*/
bool subghz_protocol_decoder_smc5326_serialize(
void* context,
FlipperFormat* flipper_format,
SubGhzRadioPreset* preset);
/**
* Deserialize data SubGhzProtocolDecoderSMC5326.
* @param context Pointer to a SubGhzProtocolDecoderSMC5326 instance
* @param flipper_format Pointer to a FlipperFormat instance
* @return true On success
*/
bool subghz_protocol_decoder_smc5326_deserialize(void* context, FlipperFormat* flipper_format);
/**
* Getting a textual representation of the received data.
* @param context Pointer to a SubGhzProtocolDecoderSMC5326 instance
* @param output Resulting text
*/
void subghz_protocol_decoder_smc5326_get_string(void* context, FuriString* output);

View File

@@ -24,7 +24,7 @@ def flp_serial_by_name(flp_name):
return ""
UPDATE_TIMEOUT = 30
UPDATE_TIMEOUT = 60
def main():