mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2025-12-13 13:09:49 +04:00
Compare commits
1 Commits
unlshd-072
...
subghz_pro
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fc6adcbeb1 |
@@ -36,6 +36,13 @@ Min level: 1
|
||||
Max level: 1
|
||||
Weight: 3
|
||||
|
||||
Name: L1_Happy_holidays_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 14
|
||||
Min level: 1
|
||||
Max level: 3
|
||||
Weight: 4
|
||||
|
||||
Name: L1_Read_books_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 8
|
||||
@@ -69,7 +76,7 @@ Min butthurt: 0
|
||||
Max butthurt: 9
|
||||
Min level: 1
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
Weight: 4
|
||||
|
||||
Name: L1_Painting_128x64
|
||||
Min butthurt: 0
|
||||
@@ -85,33 +92,12 @@ Min level: 1
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
|
||||
Name: L1_Senpai_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 5
|
||||
Min level: 1
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
|
||||
Name: L1_Kaiju_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 10
|
||||
Min level: 1
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
|
||||
Name: L1_My_dude_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 8
|
||||
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: 3
|
||||
Weight: 4
|
||||
|
||||
Name: L2_Furippa2_128x64
|
||||
Min butthurt: 0
|
||||
@@ -134,13 +120,6 @@ Min level: 2
|
||||
Max level: 2
|
||||
Weight: 3
|
||||
|
||||
Name: L2_Dj_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 8
|
||||
Min level: 2
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
|
||||
Name: L3_Furippa3_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 6
|
||||
@@ -162,30 +141,9 @@ Min level: 3
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
|
||||
Name: L1_Sad_song_128x64
|
||||
Min butthurt: 8
|
||||
Max butthurt: 13
|
||||
Name: L1_Sleigh_ride_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 14
|
||||
Min level: 1
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
|
||||
Name: L2_Coding_in_the_shell_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 12
|
||||
Min level: 2
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
|
||||
Name: L2_Secret_door_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 12
|
||||
Min level: 2
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
|
||||
Name: L3_Freedom_2_dolphins_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 12
|
||||
Min level: 3
|
||||
Max level: 3
|
||||
Weight: 5
|
||||
Weight: 4
|
||||
|
||||
@@ -1,677 +0,0 @@
|
||||
diff --git a/applications/services/notification/notification_app.c b/applications/services/notification/notification_app.c
|
||||
index 9baa738..91ad7c1 100644
|
||||
--- a/applications/services/notification/notification_app.c
|
||||
+++ b/applications/services/notification/notification_app.c
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "notification.h"
|
||||
#include "notification_messages.h"
|
||||
#include "notification_app.h"
|
||||
+#include "applications/settings/notification_settings/rgb_backlight.h"
|
||||
|
||||
#define TAG "NotificationSrv"
|
||||
|
||||
@@ -589,6 +590,7 @@ int32_t notification_srv(void* p) {
|
||||
break;
|
||||
case SaveSettingsMessage:
|
||||
notification_save_settings(app);
|
||||
+ rgb_backlight_save_settings();
|
||||
break;
|
||||
}
|
||||
|
||||
diff --git a/applications/settings/notification_settings/notification_settings_app.c b/applications/settings/notification_settings/notification_settings_app.c
|
||||
index 2a1d988..dda86f3 100644
|
||||
--- a/applications/settings/notification_settings/notification_settings_app.c
|
||||
+++ b/applications/settings/notification_settings/notification_settings_app.c
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <gui/modules/variable_item_list.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <lib/toolbox/value_index.h>
|
||||
+#include <applications/settings/notification_settings/rgb_backlight.h>
|
||||
|
||||
#define MAX_NOTIFICATION_SETTINGS 4
|
||||
|
||||
@@ -13,6 +14,8 @@ typedef struct {
|
||||
VariableItemList* variable_item_list;
|
||||
} NotificationAppSettings;
|
||||
|
||||
+static VariableItem* temp_item;
|
||||
+
|
||||
static const NotificationSequence sequence_note_c = {
|
||||
&message_note_c5,
|
||||
&message_delay_100,
|
||||
@@ -168,6 +171,59 @@ static void vibro_changed(VariableItem* item) {
|
||||
notification_message(app->notification, &sequence_single_vibro);
|
||||
}
|
||||
|
||||
+// Set RGB backlight color
|
||||
+static void color_changed(VariableItem* item) {
|
||||
+ NotificationAppSettings* app = variable_item_get_context(item);
|
||||
+ uint8_t index = variable_item_get_current_value_index(item);
|
||||
+ rgb_backlight_set_color(index);
|
||||
+ variable_item_set_current_value_text(item, rgb_backlight_get_color_text(index));
|
||||
+ notification_message(app->notification, &sequence_display_backlight_on);
|
||||
+}
|
||||
+
|
||||
+// TODO: refactor and fix this
|
||||
+static void color_set_custom_red(VariableItem* item) {
|
||||
+ NotificationAppSettings* app = variable_item_get_context(item);
|
||||
+ uint8_t index = variable_item_get_current_value_index(item);
|
||||
+ rgb_backlight_set_custom_color(index, 0);
|
||||
+ char valtext[4] = {};
|
||||
+ snprintf(valtext, sizeof(valtext), "%d", index);
|
||||
+ variable_item_set_current_value_text(item, valtext);
|
||||
+ rgb_backlight_set_color(13);
|
||||
+ rgb_backlight_update(app->notification->settings.display_brightness * 0xFF, true);
|
||||
+ // Set to custom color explicitly
|
||||
+ variable_item_set_current_value_index(temp_item, 13);
|
||||
+ variable_item_set_current_value_text(temp_item, rgb_backlight_get_color_text(13));
|
||||
+ notification_message(app->notification, &sequence_display_backlight_on);
|
||||
+}
|
||||
+static void color_set_custom_green(VariableItem* item) {
|
||||
+ NotificationAppSettings* app = variable_item_get_context(item);
|
||||
+ uint8_t index = variable_item_get_current_value_index(item);
|
||||
+ rgb_backlight_set_custom_color(index, 1);
|
||||
+ char valtext[4] = {};
|
||||
+ snprintf(valtext, sizeof(valtext), "%d", index);
|
||||
+ variable_item_set_current_value_text(item, valtext);
|
||||
+ rgb_backlight_set_color(13);
|
||||
+ rgb_backlight_update(app->notification->settings.display_brightness * 0xFF, true);
|
||||
+ // Set to custom color explicitly
|
||||
+ variable_item_set_current_value_index(temp_item, 13);
|
||||
+ variable_item_set_current_value_text(temp_item, rgb_backlight_get_color_text(13));
|
||||
+ notification_message(app->notification, &sequence_display_backlight_on);
|
||||
+}
|
||||
+static void color_set_custom_blue(VariableItem* item) {
|
||||
+ NotificationAppSettings* app = variable_item_get_context(item);
|
||||
+ uint8_t index = variable_item_get_current_value_index(item);
|
||||
+ rgb_backlight_set_custom_color(index, 2);
|
||||
+ char valtext[4] = {};
|
||||
+ snprintf(valtext, sizeof(valtext), "%d", index);
|
||||
+ variable_item_set_current_value_text(item, valtext);
|
||||
+ rgb_backlight_set_color(13);
|
||||
+ rgb_backlight_update(app->notification->settings.display_brightness * 0xFF, true);
|
||||
+ // Set to custom color explicitly
|
||||
+ variable_item_set_current_value_index(temp_item, 13);
|
||||
+ variable_item_set_current_value_text(temp_item, rgb_backlight_get_color_text(13));
|
||||
+ notification_message(app->notification, &sequence_display_backlight_on);
|
||||
+}
|
||||
+
|
||||
static uint32_t notification_app_settings_exit(void* context) {
|
||||
UNUSED(context);
|
||||
return VIEW_NONE;
|
||||
@@ -192,8 +248,40 @@ static NotificationAppSettings* alloc_settings() {
|
||||
variable_item_set_current_value_index(item, value_index);
|
||||
variable_item_set_current_value_text(item, contrast_text[value_index]);
|
||||
|
||||
+ // RGB Colors
|
||||
+ item = variable_item_list_add(
|
||||
+ app->variable_item_list, "LCD Color", rgb_backlight_get_color_count(), color_changed, app);
|
||||
+ value_index = rgb_backlight_get_settings()->display_color_index;
|
||||
+ variable_item_set_current_value_index(item, value_index);
|
||||
+ variable_item_set_current_value_text(item, rgb_backlight_get_color_text(value_index));
|
||||
+ temp_item = item;
|
||||
+
|
||||
+ // Custom Color - REFACTOR THIS
|
||||
+ item = variable_item_list_add(
|
||||
+ app->variable_item_list, "Custom Red", 255, color_set_custom_red, app);
|
||||
+ value_index = rgb_backlight_get_settings()->custom_r;
|
||||
+ variable_item_set_current_value_index(item, value_index);
|
||||
+ char valtext[4] = {};
|
||||
+ snprintf(valtext, sizeof(valtext), "%d", value_index);
|
||||
+ variable_item_set_current_value_text(item, valtext);
|
||||
+
|
||||
+ item = variable_item_list_add(
|
||||
+ app->variable_item_list, "Custom Green", 255, color_set_custom_green, app);
|
||||
+ value_index = rgb_backlight_get_settings()->custom_g;
|
||||
+ variable_item_set_current_value_index(item, value_index);
|
||||
+ snprintf(valtext, sizeof(valtext), "%d", value_index);
|
||||
+ variable_item_set_current_value_text(item, valtext);
|
||||
+
|
||||
+ item = variable_item_list_add(
|
||||
+ app->variable_item_list, "Custom Blue", 255, color_set_custom_blue, app);
|
||||
+ value_index = rgb_backlight_get_settings()->custom_b;
|
||||
+ variable_item_set_current_value_index(item, value_index);
|
||||
+ snprintf(valtext, sizeof(valtext), "%d", value_index);
|
||||
+ variable_item_set_current_value_text(item, valtext);
|
||||
+ // End of RGB
|
||||
+
|
||||
item = variable_item_list_add(
|
||||
- app->variable_item_list, "LCD Backlight", BACKLIGHT_COUNT, backlight_changed, app);
|
||||
+ app->variable_item_list, "LCD Brightness", BACKLIGHT_COUNT, backlight_changed, app);
|
||||
value_index = value_index_float(
|
||||
app->notification->settings.display_brightness, backlight_value, BACKLIGHT_COUNT);
|
||||
variable_item_set_current_value_index(item, value_index);
|
||||
diff --git a/applications/settings/notification_settings/rgb_backlight.c b/applications/settings/notification_settings/rgb_backlight.c
|
||||
new file mode 100644
|
||||
index 0000000..98f0d3a
|
||||
--- /dev/null
|
||||
+++ b/applications/settings/notification_settings/rgb_backlight.c
|
||||
@@ -0,0 +1,217 @@
|
||||
+/*
|
||||
+ RGB backlight FlipperZero driver
|
||||
+ Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
|
||||
+
|
||||
+ This program is free software: you can redistribute it and/or modify
|
||||
+ it under the terms of the GNU General Public License as published by
|
||||
+ the Free Software Foundation, either version 3 of the License, or
|
||||
+ (at your option) any later version.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ GNU General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU General Public License
|
||||
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
+*/
|
||||
+
|
||||
+#include "rgb_backlight.h"
|
||||
+#include <furi_hal.h>
|
||||
+#include <storage/storage.h>
|
||||
+
|
||||
+#define RGB_BACKLIGHT_SETTINGS_VERSION 6
|
||||
+#define RGB_BACKLIGHT_SETTINGS_FILE_NAME ".rgb_backlight.settings"
|
||||
+#define RGB_BACKLIGHT_SETTINGS_PATH INT_PATH(RGB_BACKLIGHT_SETTINGS_FILE_NAME)
|
||||
+
|
||||
+#define COLOR_COUNT (sizeof(colors) / sizeof(RGBBacklightColor))
|
||||
+
|
||||
+#define TAG "RGB Backlight"
|
||||
+
|
||||
+static RGBBacklightSettings rgb_settings = {
|
||||
+ .version = RGB_BACKLIGHT_SETTINGS_VERSION,
|
||||
+ .display_color_index = 0,
|
||||
+ .custom_r = 254,
|
||||
+ .custom_g = 254,
|
||||
+ .custom_b = 254,
|
||||
+ .settings_is_loaded = false};
|
||||
+
|
||||
+static const RGBBacklightColor colors[] = {
|
||||
+ {"Orange", 255, 60, 0},
|
||||
+ {"Yellow", 255, 144, 0},
|
||||
+ {"Spring", 167, 255, 0},
|
||||
+ {"Lime", 0, 255, 0},
|
||||
+ {"Aqua", 0, 255, 127},
|
||||
+ {"Cyan", 0, 210, 210},
|
||||
+ {"Azure", 0, 127, 255},
|
||||
+ {"Blue", 0, 0, 255},
|
||||
+ {"Purple", 127, 0, 255},
|
||||
+ {"Magenta", 210, 0, 210},
|
||||
+ {"Pink", 255, 0, 127},
|
||||
+ {"Red", 255, 0, 0},
|
||||
+ {"White", 254, 210, 200},
|
||||
+ {"Custom", 0, 0, 0},
|
||||
+};
|
||||
+
|
||||
+uint8_t rgb_backlight_get_color_count(void) {
|
||||
+ return COLOR_COUNT;
|
||||
+}
|
||||
+
|
||||
+const char* rgb_backlight_get_color_text(uint8_t index) {
|
||||
+ return colors[index].name;
|
||||
+}
|
||||
+
|
||||
+void rgb_backlight_load_settings(void) {
|
||||
+ // Do not load settings if we are in other boot modes than normal
|
||||
+ if(furi_hal_rtc_get_boot_mode() != FuriHalRtcBootModeNormal) {
|
||||
+ rgb_settings.settings_is_loaded = true;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // Wait for all required services to start and create their records
|
||||
+ uint8_t timeout = 0;
|
||||
+ while(!furi_record_exists(RECORD_STORAGE)) {
|
||||
+ timeout++;
|
||||
+ if(timeout > 150) {
|
||||
+ rgb_settings.settings_is_loaded = true;
|
||||
+ return;
|
||||
+ }
|
||||
+ furi_delay_ms(5);
|
||||
+ }
|
||||
+
|
||||
+ RGBBacklightSettings settings;
|
||||
+ File* file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
|
||||
+ const size_t settings_size = sizeof(RGBBacklightSettings);
|
||||
+
|
||||
+ FURI_LOG_D(TAG, "loading settings from \"%s\"", RGB_BACKLIGHT_SETTINGS_PATH);
|
||||
+ bool fs_result =
|
||||
+ storage_file_open(file, RGB_BACKLIGHT_SETTINGS_PATH, FSAM_READ, FSOM_OPEN_EXISTING);
|
||||
+
|
||||
+ if(fs_result) {
|
||||
+ uint16_t bytes_count = storage_file_read(file, &settings, settings_size);
|
||||
+
|
||||
+ if(bytes_count != settings_size) {
|
||||
+ fs_result = false;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if(fs_result) {
|
||||
+ FURI_LOG_D(TAG, "load success");
|
||||
+ if(settings.version != RGB_BACKLIGHT_SETTINGS_VERSION) {
|
||||
+ FURI_LOG_E(
|
||||
+ TAG,
|
||||
+ "version(%d != %d) mismatch",
|
||||
+ settings.version,
|
||||
+ RGB_BACKLIGHT_SETTINGS_VERSION);
|
||||
+ } else {
|
||||
+ memcpy(&rgb_settings, &settings, settings_size);
|
||||
+ }
|
||||
+ } else {
|
||||
+ FURI_LOG_E(TAG, "load failed, %s", storage_file_get_error_desc(file));
|
||||
+ }
|
||||
+
|
||||
+ storage_file_close(file);
|
||||
+ storage_file_free(file);
|
||||
+ furi_record_close(RECORD_STORAGE);
|
||||
+ rgb_settings.settings_is_loaded = true;
|
||||
+};
|
||||
+
|
||||
+void rgb_backlight_save_settings(void) {
|
||||
+ RGBBacklightSettings settings;
|
||||
+ File* file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
|
||||
+ const size_t settings_size = sizeof(RGBBacklightSettings);
|
||||
+
|
||||
+ FURI_LOG_D(TAG, "saving settings to \"%s\"", RGB_BACKLIGHT_SETTINGS_PATH);
|
||||
+
|
||||
+ memcpy(&settings, &rgb_settings, settings_size);
|
||||
+
|
||||
+ bool fs_result =
|
||||
+ storage_file_open(file, RGB_BACKLIGHT_SETTINGS_PATH, FSAM_WRITE, FSOM_CREATE_ALWAYS);
|
||||
+
|
||||
+ if(fs_result) {
|
||||
+ uint16_t bytes_count = storage_file_write(file, &settings, settings_size);
|
||||
+
|
||||
+ if(bytes_count != settings_size) {
|
||||
+ fs_result = false;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if(fs_result) {
|
||||
+ FURI_LOG_D(TAG, "save success");
|
||||
+ } else {
|
||||
+ FURI_LOG_E(TAG, "save failed, %s", storage_file_get_error_desc(file));
|
||||
+ }
|
||||
+
|
||||
+ storage_file_close(file);
|
||||
+ storage_file_free(file);
|
||||
+ furi_record_close(RECORD_STORAGE);
|
||||
+};
|
||||
+
|
||||
+RGBBacklightSettings* rgb_backlight_get_settings(void) {
|
||||
+ if(!rgb_settings.settings_is_loaded) {
|
||||
+ rgb_backlight_load_settings();
|
||||
+ }
|
||||
+ return &rgb_settings;
|
||||
+}
|
||||
+
|
||||
+void rgb_backlight_set_color(uint8_t color_index) {
|
||||
+ if(color_index > (rgb_backlight_get_color_count() - 1)) color_index = 0;
|
||||
+ rgb_settings.display_color_index = color_index;
|
||||
+}
|
||||
+
|
||||
+void rgb_backlight_set_custom_color(uint8_t color, uint8_t index) {
|
||||
+ if(index > 2) return;
|
||||
+ if(index == 0) {
|
||||
+ rgb_settings.custom_r = color;
|
||||
+ } else if(index == 1) {
|
||||
+ rgb_settings.custom_g = color;
|
||||
+ } else if(index == 2) {
|
||||
+ rgb_settings.custom_b = color;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void rgb_backlight_update(uint8_t brightness, bool bypass) {
|
||||
+ if(!rgb_settings.settings_is_loaded) {
|
||||
+ rgb_backlight_load_settings();
|
||||
+ }
|
||||
+
|
||||
+ if(!bypass) {
|
||||
+ static uint8_t last_color_index = 255;
|
||||
+ static uint8_t last_brightness = 123;
|
||||
+
|
||||
+ if(last_brightness == brightness && last_color_index == rgb_settings.display_color_index) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ last_brightness = brightness;
|
||||
+ last_color_index = rgb_settings.display_color_index;
|
||||
+ }
|
||||
+
|
||||
+ for(uint8_t i = 0; i < SK6805_get_led_count(); i++) {
|
||||
+ if(rgb_settings.display_color_index == 13) {
|
||||
+ uint8_t r = rgb_settings.custom_r * (brightness / 255.0f);
|
||||
+ uint8_t g = rgb_settings.custom_g * (brightness / 255.0f);
|
||||
+ uint8_t b = rgb_settings.custom_b * (brightness / 255.0f);
|
||||
+
|
||||
+ SK6805_set_led_color(i, r, g, b);
|
||||
+ } else {
|
||||
+ if((colors[rgb_settings.display_color_index].red == 0) &&
|
||||
+ (colors[rgb_settings.display_color_index].green == 0) &&
|
||||
+ (colors[rgb_settings.display_color_index].blue == 0)) {
|
||||
+ uint8_t r = colors[0].red * (brightness / 255.0f);
|
||||
+ uint8_t g = colors[0].green * (brightness / 255.0f);
|
||||
+ uint8_t b = colors[0].blue * (brightness / 255.0f);
|
||||
+
|
||||
+ SK6805_set_led_color(i, r, g, b);
|
||||
+ } else {
|
||||
+ uint8_t r = colors[rgb_settings.display_color_index].red * (brightness / 255.0f);
|
||||
+ uint8_t g = colors[rgb_settings.display_color_index].green * (brightness / 255.0f);
|
||||
+ uint8_t b = colors[rgb_settings.display_color_index].blue * (brightness / 255.0f);
|
||||
+
|
||||
+ SK6805_set_led_color(i, r, g, b);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ SK6805_update();
|
||||
+}
|
||||
diff --git a/applications/settings/notification_settings/rgb_backlight.h b/applications/settings/notification_settings/rgb_backlight.h
|
||||
new file mode 100644
|
||||
index 0000000..68dacda
|
||||
--- /dev/null
|
||||
+++ b/applications/settings/notification_settings/rgb_backlight.h
|
||||
@@ -0,0 +1,91 @@
|
||||
+/*
|
||||
+ RGB backlight FlipperZero driver
|
||||
+ Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
|
||||
+
|
||||
+ This program is free software: you can redistribute it and/or modify
|
||||
+ it under the terms of the GNU General Public License as published by
|
||||
+ the Free Software Foundation, either version 3 of the License, or
|
||||
+ (at your option) any later version.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ GNU General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU General Public License
|
||||
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
+*/
|
||||
+
|
||||
+#include <furi.h>
|
||||
+#include "SK6805.h"
|
||||
+
|
||||
+typedef struct {
|
||||
+ char* name;
|
||||
+ uint8_t red;
|
||||
+ uint8_t green;
|
||||
+ uint8_t blue;
|
||||
+} RGBBacklightColor;
|
||||
+
|
||||
+typedef struct {
|
||||
+ uint8_t version;
|
||||
+ uint8_t display_color_index;
|
||||
+ uint8_t custom_r;
|
||||
+ uint8_t custom_g;
|
||||
+ uint8_t custom_b;
|
||||
+ bool settings_is_loaded;
|
||||
+} RGBBacklightSettings;
|
||||
+
|
||||
+/**
|
||||
+ * @brief Получить текущие настройки RGB-подсветки
|
||||
+ *
|
||||
+ * @return Указатель на структуру настроек
|
||||
+ */
|
||||
+RGBBacklightSettings* rgb_backlight_get_settings(void);
|
||||
+
|
||||
+/**
|
||||
+ * @brief Загрузить настройки подсветки с SD-карты
|
||||
+ */
|
||||
+void rgb_backlight_load_settings(void);
|
||||
+
|
||||
+/**
|
||||
+ * @brief Сохранить текущие настройки RGB-подсветки
|
||||
+ */
|
||||
+void rgb_backlight_save_settings(void);
|
||||
+
|
||||
+/**
|
||||
+ * @brief Применить текущие настройки RGB-подсветки
|
||||
+ *
|
||||
+ * @param brightness Яркость свечения (0-255)
|
||||
+ * @param bypass Применить настройки принудительно
|
||||
+ */
|
||||
+void rgb_backlight_update(uint8_t brightness, bool bypass);
|
||||
+
|
||||
+/**
|
||||
+ * @brief Установить цвет RGB-подсветки
|
||||
+ *
|
||||
+ * @param color_index Индекс цвета (0 - rgb_backlight_get_color_count())
|
||||
+ */
|
||||
+void rgb_backlight_set_color(uint8_t color_index);
|
||||
+
|
||||
+/**
|
||||
+ * @brief Set custom color values by index - 0=R 1=G 2=B
|
||||
+ *
|
||||
+ * @param color - color value (0-255)
|
||||
+ * @param index - color index (0-2) 0=R 1=G 2=B
|
||||
+ */
|
||||
+void rgb_backlight_set_custom_color(uint8_t color, uint8_t index);
|
||||
+
|
||||
+/**
|
||||
+ * @brief Получить количество доступных цветов
|
||||
+ *
|
||||
+ * @return Число доступных вариантов цвета
|
||||
+ */
|
||||
+uint8_t rgb_backlight_get_color_count(void);
|
||||
+
|
||||
+/**
|
||||
+ * @brief Получить текстовое название цвета
|
||||
+ *
|
||||
+ * @param index Индекс из доступных вариантов цвета
|
||||
+ * @return Указатель на строку с названием цвета
|
||||
+ */
|
||||
+const char* rgb_backlight_get_color_text(uint8_t index);
|
||||
\ No newline at end of file
|
||||
diff --git a/lib/drivers/SK6805.c b/lib/drivers/SK6805.c
|
||||
new file mode 100644
|
||||
index 0000000..572e1df
|
||||
--- /dev/null
|
||||
+++ b/lib/drivers/SK6805.c
|
||||
@@ -0,0 +1,101 @@
|
||||
+/*
|
||||
+ SK6805 FlipperZero driver
|
||||
+ Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
|
||||
+
|
||||
+ This program is free software: you can redistribute it and/or modify
|
||||
+ it under the terms of the GNU General Public License as published by
|
||||
+ the Free Software Foundation, either version 3 of the License, or
|
||||
+ (at your option) any later version.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ GNU General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU General Public License
|
||||
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
+*/
|
||||
+
|
||||
+#include "SK6805.h"
|
||||
+#include <furi_hal.h>
|
||||
+
|
||||
+/* Настройки */
|
||||
+#define SK6805_LED_COUNT 3 //Количество светодиодов на плате подсветки
|
||||
+#define SK6805_LED_PIN &led_pin //Порт подключения светодиодов
|
||||
+
|
||||
+#ifdef FURI_DEBUG
|
||||
+#define DEBUG_PIN &gpio_ext_pa7
|
||||
+#define DEBUG_INIT() \
|
||||
+ furi_hal_gpio_init(DEBUG_PIN, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh)
|
||||
+#define DEBUG_SET_HIGH() furi_hal_gpio_write(DEBUG_PIN, true)
|
||||
+#define DEBUG_SET_LOW() furi_hal_gpio_write(DEBUG_PIN, false)
|
||||
+#else
|
||||
+#define DEBUG_INIT()
|
||||
+#define DEBUG_SET_HIGH()
|
||||
+#define DEBUG_SET_LOW()
|
||||
+#endif
|
||||
+
|
||||
+static const GpioPin led_pin = {.port = GPIOA, .pin = LL_GPIO_PIN_8};
|
||||
+static uint8_t led_buffer[SK6805_LED_COUNT][3];
|
||||
+
|
||||
+void SK6805_init(void) {
|
||||
+ DEBUG_INIT();
|
||||
+ furi_hal_gpio_write(SK6805_LED_PIN, false);
|
||||
+ furi_hal_gpio_init(SK6805_LED_PIN, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||
+}
|
||||
+
|
||||
+uint8_t SK6805_get_led_count(void) {
|
||||
+ return (const uint8_t)SK6805_LED_COUNT;
|
||||
+}
|
||||
+void SK6805_set_led_color(uint8_t led_index, uint8_t r, uint8_t g, uint8_t b) {
|
||||
+ furi_check(led_index < SK6805_LED_COUNT);
|
||||
+
|
||||
+ led_buffer[led_index][0] = g;
|
||||
+ led_buffer[led_index][1] = r;
|
||||
+ led_buffer[led_index][2] = b;
|
||||
+}
|
||||
+
|
||||
+void SK6805_update(void) {
|
||||
+ SK6805_init();
|
||||
+ FURI_CRITICAL_ENTER();
|
||||
+ uint32_t end;
|
||||
+ /* Последовательная отправка цветов светодиодов */
|
||||
+ for(uint8_t lednumber = 0; lednumber < SK6805_LED_COUNT; lednumber++) {
|
||||
+ //Последовательная отправка цветов светодиода
|
||||
+ for(uint8_t color = 0; color < 3; color++) {
|
||||
+ //Последовательная отправка битов цвета
|
||||
+ uint8_t i = 0b10000000;
|
||||
+ while(i != 0) {
|
||||
+ if(led_buffer[lednumber][color] & (i)) {
|
||||
+ furi_hal_gpio_write(SK6805_LED_PIN, true);
|
||||
+ DEBUG_SET_HIGH();
|
||||
+ end = DWT->CYCCNT + 30;
|
||||
+ //T1H 600 us (615 us)
|
||||
+ while(DWT->CYCCNT < end) {
|
||||
+ }
|
||||
+ furi_hal_gpio_write(SK6805_LED_PIN, false);
|
||||
+ DEBUG_SET_LOW();
|
||||
+ end = DWT->CYCCNT + 26;
|
||||
+ //T1L 600 us (587 us)
|
||||
+ while(DWT->CYCCNT < end) {
|
||||
+ }
|
||||
+ } else {
|
||||
+ furi_hal_gpio_write(SK6805_LED_PIN, true);
|
||||
+ DEBUG_SET_HIGH();
|
||||
+ end = DWT->CYCCNT + 11;
|
||||
+ //T0H 300 ns (312 ns)
|
||||
+ while(DWT->CYCCNT < end) {
|
||||
+ }
|
||||
+ furi_hal_gpio_write(SK6805_LED_PIN, false);
|
||||
+ DEBUG_SET_LOW();
|
||||
+ end = DWT->CYCCNT + 43;
|
||||
+ //T0L 900 ns (890 ns)
|
||||
+ while(DWT->CYCCNT < end) {
|
||||
+ }
|
||||
+ }
|
||||
+ i >>= 1;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ FURI_CRITICAL_EXIT();
|
||||
+}
|
||||
diff --git a/lib/drivers/SK6805.h b/lib/drivers/SK6805.h
|
||||
new file mode 100644
|
||||
index 0000000..7c58956
|
||||
--- /dev/null
|
||||
+++ b/lib/drivers/SK6805.h
|
||||
@@ -0,0 +1,51 @@
|
||||
+/*
|
||||
+ SK6805 FlipperZero driver
|
||||
+ Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
|
||||
+
|
||||
+ This program is free software: you can redistribute it and/or modify
|
||||
+ it under the terms of the GNU General Public License as published by
|
||||
+ the Free Software Foundation, either version 3 of the License, or
|
||||
+ (at your option) any later version.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ GNU General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU General Public License
|
||||
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
+*/
|
||||
+
|
||||
+#ifndef SK6805_H_
|
||||
+#define SK6805_H_
|
||||
+
|
||||
+#include <furi.h>
|
||||
+
|
||||
+/**
|
||||
+ * @brief Инициализация линии управления подсветкой
|
||||
+ */
|
||||
+void SK6805_init(void);
|
||||
+
|
||||
+/**
|
||||
+ * @brief Получить количество светодиодов в подсветке
|
||||
+ *
|
||||
+ * @return Количество светодиодов
|
||||
+ */
|
||||
+uint8_t SK6805_get_led_count(void);
|
||||
+
|
||||
+/**
|
||||
+ * @brief Установить цвет свечения светодиода
|
||||
+ *
|
||||
+ * @param led_index номер светодиода (от 0 до SK6805_get_led_count())
|
||||
+ * @param r значение красного (0-255)
|
||||
+ * @param g значение зелёного (0-255)
|
||||
+ * @param b значение синего (0-255)
|
||||
+ */
|
||||
+void SK6805_set_led_color(uint8_t led_index, uint8_t r, uint8_t g, uint8_t b);
|
||||
+
|
||||
+/**
|
||||
+ * @brief Обновление состояния подсветки дисплея
|
||||
+ */
|
||||
+void SK6805_update(void);
|
||||
+
|
||||
+#endif /* SK6805_H_ */
|
||||
\ No newline at end of file
|
||||
diff --git a/targets/f7/furi_hal/furi_hal_light.c b/targets/f7/furi_hal/furi_hal_light.c
|
||||
index 83e1603..45798ca 100644
|
||||
--- a/targets/f7/furi_hal/furi_hal_light.c
|
||||
+++ b/targets/f7/furi_hal/furi_hal_light.c
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <furi_hal_light.h>
|
||||
#include <lp5562.h>
|
||||
#include <stdint.h>
|
||||
+#include <applications/settings/notification_settings/rgb_backlight.h>
|
||||
|
||||
#define LED_CURRENT_RED 50
|
||||
#define LED_CURRENT_GREEN 50
|
||||
@@ -31,22 +32,21 @@ void furi_hal_light_init() {
|
||||
}
|
||||
|
||||
void furi_hal_light_set(Light light, uint8_t value) {
|
||||
- furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
|
||||
- if(light & LightRed) {
|
||||
- lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelRed, value);
|
||||
- }
|
||||
- if(light & LightGreen) {
|
||||
- lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelGreen, value);
|
||||
- }
|
||||
- if(light & LightBlue) {
|
||||
- lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelBlue, value);
|
||||
- }
|
||||
if(light & LightBacklight) {
|
||||
- uint8_t prev = lp5562_get_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelWhite);
|
||||
- lp5562_execute_ramp(
|
||||
- &furi_hal_i2c_handle_power, LP5562Engine1, LP5562ChannelWhite, prev, value, 100);
|
||||
+ rgb_backlight_update(value, false);
|
||||
+ } else {
|
||||
+ furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
|
||||
+ if(light & LightRed) {
|
||||
+ lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelRed, value);
|
||||
+ }
|
||||
+ if(light & LightGreen) {
|
||||
+ lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelGreen, value);
|
||||
+ }
|
||||
+ if(light & LightBlue) {
|
||||
+ lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelBlue, value);
|
||||
+ }
|
||||
+ furi_hal_i2c_release(&furi_hal_i2c_handle_power);
|
||||
}
|
||||
- furi_hal_i2c_release(&furi_hal_i2c_handle_power);
|
||||
}
|
||||
|
||||
void furi_hal_light_blink_start(Light light, uint8_t brightness, uint16_t on_time, uint16_t period) {
|
||||
318
.drone.yml
318
.drone.yml
@@ -11,53 +11,27 @@ steps:
|
||||
image: alpine/git
|
||||
commands:
|
||||
- git submodule sync
|
||||
- git -c protocol.version=2 submodule update --init --force --recursive --jobs 4
|
||||
- git -c protocol.version=2 submodule update --init --force --recursive
|
||||
- git submodule foreach git config --local gc.auto 0
|
||||
- git log -1 --format='%H'
|
||||
|
||||
- name: "Build clean"
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
commands:
|
||||
- export DIST_SUFFIX=${DRONE_TAG}c
|
||||
- export WORKFLOW_BRANCH_OR_TAG=release-cfw
|
||||
- export FORCE_NO_DIRTY=yes
|
||||
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
||||
- rm -rf applications/main/clock_app/resources/apps/
|
||||
- rm -rf build/
|
||||
- rm -rf dist/
|
||||
- rm -rf .sconsign.dblite
|
||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||
- mkdir artifacts-clean
|
||||
- mv dist/f7-C/* artifacts-clean/
|
||||
- ls -laS artifacts-clean
|
||||
- ls -laS artifacts-clean/f7-update-${DRONE_TAG}c
|
||||
environment:
|
||||
FBT_TOOLS_CUSTOM_LINK:
|
||||
from_secret: fbt_link
|
||||
|
||||
- name: "Build default"
|
||||
- name: "Build firmware"
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
commands:
|
||||
- export DIST_SUFFIX=${DRONE_TAG}
|
||||
- export WORKFLOW_BRANCH_OR_TAG=release-cfw
|
||||
- export FORCE_NO_DIRTY=yes
|
||||
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
||||
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-base.tgz
|
||||
- tar zxf all-the-apps-base.tgz
|
||||
- mkdir -p applications/main/clock_app/resources/apps
|
||||
- mkdir -p applications/main/clock_app/resources/apps_data
|
||||
- cp -R base_pack_build/artifacts-base/* applications/main/clock_app/resources/apps/
|
||||
- cp -R base_pack_build/apps_data/* applications/main/clock_app/resources/apps_data/
|
||||
- rm -rf base_pack_build
|
||||
- rm -rf all-the-apps-base.tgz
|
||||
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||
- mkdir artifacts-default
|
||||
- mv dist/f7-C/* artifacts-default/
|
||||
- ls -laS artifacts-default
|
||||
- ls -laS artifacts-default/f7-update-${DRONE_TAG}
|
||||
- sed -i 's/(version)/'${DRONE_TAG}'/g' CHANGELOG.md
|
||||
- echo '# [Install via Web Updater](https://lab.flipper.net/?url=https://unleashedflip.com/fw/${DRONE_TAG}/flipper-z-f7-update-'${DRONE_TAG}'.tgz&channel=release-cfw&version='${DRONE_TAG}')' >> CHANGELOG.md
|
||||
- echo '' >> CHANGELOG.md
|
||||
- echo '### [Version without custom animations - Install via Web Updater](https://lab.flipper.net/?url=https://unleashedflip.com/fw_no_anim/flipper-z-f7-update-'${DRONE_TAG}'n.tgz&channel=release-cfw&version='${DRONE_TAG}'n)' >> CHANGELOG.md
|
||||
- echo '' >> CHANGELOG.md
|
||||
- echo '### [Version with extra apps - Install via Web Updater](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'e.tgz&channel=release-cfw&version='${DRONE_TAG}'e)' >> CHANGELOG.md
|
||||
environment:
|
||||
FBT_TOOLS_CUSTOM_LINK:
|
||||
from_secret: fbt_link
|
||||
@@ -66,15 +40,12 @@ steps:
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
commands:
|
||||
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-extra.tgz
|
||||
- tar zxf all-the-apps-extra.tgz
|
||||
- mkdir -p applications/main/clock_app/resources/apps
|
||||
- cp -R extra_pack_build/artifacts-extra/* applications/main/clock_app/resources/apps/
|
||||
- rm -rf extra_pack_build
|
||||
- git clone https://github.com/xMasterX/unleashed-extra-pack.git
|
||||
- cp -R unleashed-extra-pack/apps/* assets/resources/apps/
|
||||
- rm -rf unleashed-extra-pack
|
||||
- export DIST_SUFFIX=${DRONE_TAG}e
|
||||
- export WORKFLOW_BRANCH_OR_TAG=release-cfw
|
||||
- export FORCE_NO_DIRTY=yes
|
||||
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
||||
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||
- mkdir artifacts-extra-apps
|
||||
@@ -85,64 +56,22 @@ steps:
|
||||
FBT_TOOLS_CUSTOM_LINK:
|
||||
from_secret: fbt_link
|
||||
|
||||
- name: "Build with RGB patch"
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
commands:
|
||||
- git apply .ci_files/rgb.patch
|
||||
- export DIST_SUFFIX=${DRONE_TAG}r
|
||||
- export WORKFLOW_BRANCH_OR_TAG=release-cfw-rgb
|
||||
- export FORCE_NO_DIRTY=yes
|
||||
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
||||
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||
- mkdir artifacts-rgb-patch
|
||||
- mv dist/f7-C/* artifacts-rgb-patch/
|
||||
- ls -laS artifacts-rgb-patch
|
||||
- ls -laS artifacts-rgb-patch/f7-update-${DRONE_TAG}r
|
||||
environment:
|
||||
FBT_TOOLS_CUSTOM_LINK:
|
||||
from_secret: fbt_link
|
||||
|
||||
- name: "Build with ofw anims"
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
commands:
|
||||
- git clean -df
|
||||
- git checkout -- .
|
||||
- rm -f assets/dolphin/external/manifest.txt
|
||||
- cp .ci_files/anims_ofw.txt assets/dolphin/external/manifest.txt
|
||||
- rm -rf applications/main/clock_app/resources/apps/
|
||||
- rm -rf assets/resources/apps/
|
||||
- export DIST_SUFFIX=${DRONE_TAG}n
|
||||
- export WORKFLOW_BRANCH_OR_TAG=no-custom-anims
|
||||
- export FORCE_NO_DIRTY=yes
|
||||
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
||||
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-base.tgz
|
||||
- tar zxf all-the-apps-base.tgz
|
||||
- mkdir -p applications/main/clock_app/resources/apps
|
||||
- mkdir -p applications/main/clock_app/resources/apps_data
|
||||
- cp -R base_pack_build/artifacts-base/* applications/main/clock_app/resources/apps/
|
||||
- cp -R base_pack_build/apps_data/* applications/main/clock_app/resources/apps_data/
|
||||
- rm -rf base_pack_build
|
||||
- rm -rf all-the-apps-base.tgz
|
||||
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||
- mkdir artifacts-ofw-anims
|
||||
- mv dist/f7-C/* artifacts-ofw-anims/
|
||||
- ls -laS artifacts-ofw-anims
|
||||
- ls -laS artifacts-ofw-anims/f7-update-${DRONE_TAG}n
|
||||
- sed -i 's/(version)/'${DRONE_TAG}'/g' CHANGELOG.md
|
||||
- echo '# [Install via Web Updater](https://lab.flipper.net/?url=https://unleashedflip.com/fw/${DRONE_TAG}/flipper-z-f7-update-'${DRONE_TAG}'.tgz&channel=release-cfw&version='${DRONE_TAG}')' >> CHANGELOG.md
|
||||
- echo '' >> CHANGELOG.md
|
||||
- echo '### [Version with only main apps - Install via Web Updater](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'c.tgz&channel=release-cfw&version='${DRONE_TAG}'c)' >> CHANGELOG.md
|
||||
- echo '' >> CHANGELOG.md
|
||||
- echo '### [Version without custom animations - Install via Web Updater](https://lab.flipper.net/?url=https://unleashedflip.com/fw_no_anim/flipper-z-f7-update-'${DRONE_TAG}'n.tgz&channel=release-cfw&version='${DRONE_TAG}'n)' >> CHANGELOG.md
|
||||
- echo '' >> CHANGELOG.md
|
||||
- echo '### [Version with RGB patch - only for hardware mod! - Install via Web Updater](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'r.tgz&channel=release-cfw&version='${DRONE_TAG}'r)' >> CHANGELOG.md
|
||||
- echo '' >> CHANGELOG.md
|
||||
- echo '## [Version with Extra apps - Install via Web Updater](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'e.tgz&channel=release-cfw&version='${DRONE_TAG}'e)' >> CHANGELOG.md
|
||||
environment:
|
||||
FBT_TOOLS_CUSTOM_LINK:
|
||||
from_secret: fbt_link
|
||||
@@ -151,24 +80,16 @@ steps:
|
||||
image: kramos/alpine-zip
|
||||
commands:
|
||||
- cp artifacts-extra-apps/flipper-z-f7-update-${DRONE_TAG}e.tgz .
|
||||
- cp artifacts-rgb-patch/flipper-z-f7-update-${DRONE_TAG}r.tgz .
|
||||
- cp artifacts-clean/flipper-z-f7-update-${DRONE_TAG}c.tgz .
|
||||
- cp artifacts-ofw-anims/flipper-z-f7-update-${DRONE_TAG}n.tgz .
|
||||
- cp artifacts-default/flipper-z-f7-update-${DRONE_TAG}.tgz .
|
||||
- zip -r artifacts-extra-apps/flipper-z-f7-update-${DRONE_TAG}e.zip artifacts-extra-apps/f7-update-${DRONE_TAG}e
|
||||
- zip -r artifacts-rgb-patch/flipper-z-f7-update-${DRONE_TAG}r.zip artifacts-rgb-patch/f7-update-${DRONE_TAG}r
|
||||
- zip -r artifacts-clean/flipper-z-f7-update-${DRONE_TAG}c.zip artifacts-clean/f7-update-${DRONE_TAG}c
|
||||
- zip -r artifacts-ofw-anims/flipper-z-f7-update-${DRONE_TAG}n.zip artifacts-ofw-anims/f7-update-${DRONE_TAG}n
|
||||
- zip -r artifacts-default/flipper-z-f7-update-${DRONE_TAG}.zip artifacts-default/f7-update-${DRONE_TAG}
|
||||
- tar czpf artifacts-default/flipper-z-any-scripts-${DRONE_TAG}.tgz scripts
|
||||
- tar czpf artifacts-default/flipper-z-any-scripts-${DRONE_TAG}.tgz scripts debug
|
||||
- rm -rf artifacts-extra-apps/f7-update-${DRONE_TAG}
|
||||
- rm -rf artifacts-rgb-patch/f7-update-${DRONE_TAG}
|
||||
- rm -rf artifacts-clean/f7-update-${DRONE_TAG}
|
||||
- rm -rf artifacts-ofw-anims/f7-update-${DRONE_TAG}
|
||||
- rm -rf artifacts-default/f7-update-${DRONE_TAG}
|
||||
- ls -laS artifacts-extra-apps
|
||||
- ls -laS artifacts-rgb-patch
|
||||
- ls -laS artifacts-clean
|
||||
- ls -laS artifacts-ofw-anims
|
||||
- ls -laS artifacts-default
|
||||
- mv artifacts-default/ ${DRONE_TAG}
|
||||
@@ -225,36 +146,6 @@ steps:
|
||||
from_secret: dep_target_extra
|
||||
source: flipper-z-f7-update-${DRONE_TAG}e.tgz
|
||||
|
||||
- name: "Upload rgb patch version to updates srv"
|
||||
image: appleboy/drone-scp:linux-amd64
|
||||
settings:
|
||||
host:
|
||||
from_secret: dep_host
|
||||
username:
|
||||
from_secret: dep_user
|
||||
password:
|
||||
from_secret: dep_passwd
|
||||
port:
|
||||
from_secret: dep_port
|
||||
target:
|
||||
from_secret: dep_target_extra
|
||||
source: flipper-z-f7-update-${DRONE_TAG}r.tgz
|
||||
|
||||
- name: "Upload clean version to updates srv"
|
||||
image: appleboy/drone-scp:linux-amd64
|
||||
settings:
|
||||
host:
|
||||
from_secret: dep_host
|
||||
username:
|
||||
from_secret: dep_user
|
||||
password:
|
||||
from_secret: dep_passwd
|
||||
port:
|
||||
from_secret: dep_port
|
||||
target:
|
||||
from_secret: dep_target_extra
|
||||
source: flipper-z-f7-update-${DRONE_TAG}c.tgz
|
||||
|
||||
- name: "Do Github release"
|
||||
image: ddplugins/github-release
|
||||
pull: never
|
||||
@@ -269,8 +160,6 @@ steps:
|
||||
- ${DRONE_TAG}/*.zip
|
||||
- artifacts-ofw-anims/*.tgz
|
||||
- artifacts-extra-apps/*.tgz
|
||||
- artifacts-rgb-patch/*.tgz
|
||||
- artifacts-clean/*.tgz
|
||||
title: ${DRONE_TAG}
|
||||
note: CHANGELOG.md
|
||||
checksum:
|
||||
@@ -303,34 +192,22 @@ steps:
|
||||
Version: {{build.tag}}
|
||||
|
||||
|
||||
[-> Sponsor our project](https://boosty.to/mmxdev)
|
||||
|
||||
|
||||
[-Github - Changelog-](https://github.com/DarkFlippers/unleashed-firmware/releases/tag/${DRONE_TAG})
|
||||
|
||||
|
||||
[-How to install firmware-](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)
|
||||
|
||||
|
||||
[-Download latest extra apps pack-](https://github.com/xMasterX/all-the-plugins/releases/latest)
|
||||
[-Download latest extra apps pack-](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps)
|
||||
|
||||
|
||||
[-Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/${DRONE_TAG}/flipper-z-f7-update-${DRONE_TAG}.tgz&channel=release-cfw&version=${DRONE_TAG})
|
||||
|
||||
|
||||
[-Version with only main apps - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-${DRONE_TAG}c.tgz&channel=release-cfw&version=${DRONE_TAG}c)
|
||||
|
||||
|
||||
[-Version without custom animations - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_no_anim/flipper-z-f7-update-${DRONE_TAG}n.tgz&channel=release-cfw&version=${DRONE_TAG}n)
|
||||
|
||||
|
||||
[-Version with RGB patch - only for hardware mod! - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-${DRONE_TAG}r.tgz&channel=release-cfw&version=${DRONE_TAG}r)
|
||||
|
||||
|
||||
[-Version with RGB patch - only for hardware mod! - Direct download-](https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-${DRONE_TAG}r.tgz)
|
||||
|
||||
|
||||
[-Version with Extra apps - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-${DRONE_TAG}e.tgz&channel=release-cfw&version=${DRONE_TAG}e)"
|
||||
[-Version with extra apps - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-${DRONE_TAG}e.tgz&channel=release-cfw&version=${DRONE_TAG}e)"
|
||||
document:
|
||||
- ${DRONE_TAG}/flipper-z-f7-update-${DRONE_TAG}.tgz
|
||||
|
||||
@@ -341,22 +218,9 @@ steps:
|
||||
DISCORD_WEBHOOK:
|
||||
from_secret: dis_release_webhook
|
||||
commands:
|
||||
- wget "https://raw.githubusercontent.com/fieu/discord.sh/2253303efc0e7211ac2777d2535054cbb872f1e0/discord.sh"
|
||||
- wget "https://raw.githubusercontent.com/fieu/discord.sh/e1dc1a7595efad2cad8f072f0b3531c470f5b7c8/discord.sh"
|
||||
- chmod +x ./discord.sh
|
||||
- echo 'New Unleashed firmware released!\n\nVersion - '${DRONE_TAG}'\n\n[-> Sponsor our project](https://boosty.to/mmxdev)\n\n[[Github - Changelog]](https://github.com/DarkFlippers/unleashed-firmware/releases/tag/'${DRONE_TAG}')\n\n[-How to install firmware-](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)\n\n[-Download latest extra apps pack-](https://github.com/xMasterX/all-the-plugins/releases/latest)\n\n[-Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/'${DRONE_TAG}'/flipper-z-f7-update-'${DRONE_TAG}'.tgz&channel=release-cfw&version='${DRONE_TAG}')\n\n[-Version with only main apps - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'c.tgz&channel=release-cfw&version='${DRONE_TAG}'c)\n\n[-Version without custom animations - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_no_anim/flipper-z-f7-update-'${DRONE_TAG}'n.tgz&channel=release-cfw&version='${DRONE_TAG}'n)\n\n[-Version with RGB patch - only for hardware mod! - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'r.tgz&channel=release-cfw&version='${DRONE_TAG}'r)\n\n[-Version with RGB patch - only for hardware mod! - Direct download-](https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'r.tgz)\n\n[-Version with Extra apps - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'e.tgz&channel=release-cfw&version='${DRONE_TAG}'e)' > messagedisc.txt
|
||||
- ./discord.sh --text "$(jq -Rs . <messagedisc.txt | cut -c 2- | rev | cut -c 2- | rev)"
|
||||
|
||||
- name: "Send clean build to telegram"
|
||||
image: appleboy/drone-telegram
|
||||
settings:
|
||||
token:
|
||||
from_secret: tgtoken
|
||||
to:
|
||||
from_secret: tgid
|
||||
format: markdown
|
||||
message: "Build with only main apps:"
|
||||
document:
|
||||
- flipper-z-f7-update-${DRONE_TAG}c.tgz
|
||||
- ./discord.sh --text 'New Unleashed firmware released!\n\nVersion - '${DRONE_TAG}'\n\n[[Github - Changelog]](https://github.com/DarkFlippers/unleashed-firmware/releases/tag/'${DRONE_TAG}')\n\n[-How to install firmware-](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)\n\n[-Download latest extra apps pack-](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps)\n\n[-Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/'${DRONE_TAG}'/flipper-z-f7-update-'${DRONE_TAG}'.tgz&channel=release-cfw&version='${DRONE_TAG}')\n\n[-Version without custom animations - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_no_anim/flipper-z-f7-update-'${DRONE_TAG}'n.tgz&channel=release-cfw&version='${DRONE_TAG}'n)\n\n[-Version with extra apps - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'e.tgz&channel=release-cfw&version='${DRONE_TAG}'e)'
|
||||
|
||||
- name: "Send extra pack build to telegram"
|
||||
image: appleboy/drone-telegram
|
||||
@@ -375,7 +239,7 @@ trigger:
|
||||
- tag
|
||||
|
||||
node:
|
||||
typ: dev1
|
||||
typ: haupt
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
@@ -391,49 +255,16 @@ steps:
|
||||
image: alpine/git
|
||||
commands:
|
||||
- git submodule sync
|
||||
- git -c protocol.version=2 submodule update --init --force --recursive --jobs 4
|
||||
- git -c protocol.version=2 submodule update --init --force --recursive
|
||||
- git submodule foreach git config --local gc.auto 0
|
||||
- git log -1 --format='%H'
|
||||
|
||||
- name: "Build dev clean"
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
commands:
|
||||
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}c
|
||||
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw
|
||||
- export FORCE_NO_DIRTY=yes
|
||||
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
||||
- rm -rf applications/main/clock_app/resources/apps/
|
||||
- rm -rf build/
|
||||
- rm -rf dist/
|
||||
- rm -rf .sconsign.dblite
|
||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||
- mkdir artifacts-clean
|
||||
- mv dist/f7-C/* artifacts-clean/
|
||||
- ls -laS artifacts-clean
|
||||
- ls -laS artifacts-clean/f7-update-${DRONE_BUILD_NUMBER}c
|
||||
environment:
|
||||
FBT_TOOLS_CUSTOM_LINK:
|
||||
from_secret: fbt_link
|
||||
|
||||
|
||||
- name: "Build dev default"
|
||||
- name: "Build dev FW"
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
commands:
|
||||
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}
|
||||
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw
|
||||
- export FORCE_NO_DIRTY=yes
|
||||
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
||||
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-base.tgz
|
||||
- tar zxf all-the-apps-base.tgz
|
||||
- mkdir -p applications/main/clock_app/resources/apps
|
||||
- mkdir -p applications/main/clock_app/resources/apps_data
|
||||
- cp -R base_pack_build/artifacts-base/* applications/main/clock_app/resources/apps/
|
||||
- cp -R base_pack_build/apps_data/* applications/main/clock_app/resources/apps_data/
|
||||
- rm -rf base_pack_build
|
||||
- rm -rf all-the-apps-base.tgz
|
||||
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||
- mkdir artifacts-default
|
||||
- mv dist/f7-C/* artifacts-default/
|
||||
@@ -447,15 +278,12 @@ steps:
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
commands:
|
||||
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-extra.tgz
|
||||
- tar zxf all-the-apps-extra.tgz
|
||||
- mkdir -p applications/main/clock_app/resources/apps
|
||||
- cp -R extra_pack_build/artifacts-extra/* applications/main/clock_app/resources/apps/
|
||||
- rm -rf extra_pack_build
|
||||
- git clone https://github.com/xMasterX/unleashed-extra-pack.git
|
||||
- cp -R unleashed-extra-pack/apps/* assets/resources/apps/
|
||||
- rm -rf unleashed-extra-pack
|
||||
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}e
|
||||
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw
|
||||
- export FORCE_NO_DIRTY=yes
|
||||
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
||||
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||
- mkdir artifacts-extra-apps
|
||||
@@ -466,31 +294,10 @@ steps:
|
||||
FBT_TOOLS_CUSTOM_LINK:
|
||||
from_secret: fbt_link
|
||||
|
||||
- name: "Build dev with rgb patch"
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
commands:
|
||||
- git apply .ci_files/rgb.patch
|
||||
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}r
|
||||
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw-rgb
|
||||
- export FORCE_NO_DIRTY=yes
|
||||
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
||||
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||
- mkdir artifacts-rgb-patch
|
||||
- mv dist/f7-C/* artifacts-rgb-patch/
|
||||
- ls -laS artifacts-rgb-patch
|
||||
- ls -laS artifacts-rgb-patch/f7-update-${DRONE_BUILD_NUMBER}r
|
||||
environment:
|
||||
FBT_TOOLS_CUSTOM_LINK:
|
||||
from_secret: fbt_link
|
||||
|
||||
- name: "Bundle self-update packages"
|
||||
image: kramos/alpine-zip
|
||||
commands:
|
||||
- cp artifacts-extra-apps/flipper-z-f7-update-${DRONE_BUILD_NUMBER}e.tgz .
|
||||
- cp artifacts-rgb-patch/flipper-z-f7-update-${DRONE_BUILD_NUMBER}r.tgz .
|
||||
- cp artifacts-clean/flipper-z-f7-update-${DRONE_BUILD_NUMBER}c.tgz .
|
||||
- cp artifacts-default/flipper-z-f7-update-${DRONE_BUILD_NUMBER}.tgz .
|
||||
- rm -rf artifacts-default/f7-update-${DRONE_BUILD_NUMBER}
|
||||
- ls -laS artifacts-default
|
||||
@@ -548,36 +355,6 @@ steps:
|
||||
from_secret: dep_target_extra
|
||||
source: flipper-z-f7-update-${DRONE_BUILD_NUMBER}e.tgz
|
||||
|
||||
- name: "Upload rgb patch version to updates srv"
|
||||
image: appleboy/drone-scp:linux-amd64
|
||||
settings:
|
||||
host:
|
||||
from_secret: dep_host
|
||||
username:
|
||||
from_secret: dep_user
|
||||
password:
|
||||
from_secret: dep_passwd
|
||||
port:
|
||||
from_secret: dep_port
|
||||
target:
|
||||
from_secret: dep_target_extra
|
||||
source: flipper-z-f7-update-${DRONE_BUILD_NUMBER}r.tgz
|
||||
|
||||
- name: "Upload clean version to updates srv"
|
||||
image: appleboy/drone-scp:linux-amd64
|
||||
settings:
|
||||
host:
|
||||
from_secret: dep_host
|
||||
username:
|
||||
from_secret: dep_user
|
||||
password:
|
||||
from_secret: dep_passwd
|
||||
port:
|
||||
from_secret: dep_port
|
||||
target:
|
||||
from_secret: dep_target_extra
|
||||
source: flipper-z-f7-update-${DRONE_BUILD_NUMBER}c.tgz
|
||||
|
||||
- name: "Trigger update server reindex"
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
@@ -589,7 +366,7 @@ steps:
|
||||
commands:
|
||||
- curl -X POST -F 'key='$UPD_KEY'' $UPD_URL
|
||||
|
||||
- name: "Send message to telegram"
|
||||
- name: "Send files to telegram"
|
||||
image: appleboy/drone-telegram
|
||||
settings:
|
||||
token:
|
||||
@@ -602,51 +379,19 @@ steps:
|
||||
|
||||
Build: {{build.number}}
|
||||
|
||||
Commit: https://github.com/DarkFlippers/unleashed-firmware/commit/{{commit.sha}}
|
||||
SHA: {{commit.sha}}
|
||||
|
||||
|
||||
|
||||
[-> Sponsor our project](https://boosty.to/mmxdev)
|
||||
Commit: {{commit.message}}
|
||||
|
||||
|
||||
[-Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/dev/flipper-z-f7-update-${DRONE_BUILD_NUMBER}.tgz&channel=dev-cfw&version=${DRONE_BUILD_NUMBER})
|
||||
|
||||
|
||||
[-Version with only main apps - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-${DRONE_BUILD_NUMBER}c.tgz&channel=dev-cfw&version=${DRONE_BUILD_NUMBER}c)
|
||||
|
||||
|
||||
[-Version with RGB patch - only for hardware mod! - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-${DRONE_BUILD_NUMBER}r.tgz&channel=dev-cfw&version=${DRONE_BUILD_NUMBER}r)
|
||||
[-Version with extra apps - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-${DRONE_BUILD_NUMBER}e.tgz&channel=dev-cfw&version=${DRONE_BUILD_NUMBER}e)
|
||||
|
||||
|
||||
[-Version with RGB patch - only for hardware mod! - Direct download-](https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-${DRONE_BUILD_NUMBER}r.tgz)
|
||||
|
||||
|
||||
[-Version with Extra apps - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-${DRONE_BUILD_NUMBER}e.tgz&channel=dev-cfw&version=${DRONE_BUILD_NUMBER}e)"
|
||||
|
||||
- name: "Send build to telegram"
|
||||
image: appleboy/drone-telegram
|
||||
settings:
|
||||
token:
|
||||
from_secret: tgtoken
|
||||
to:
|
||||
from_secret: tgid_dev
|
||||
format: markdown
|
||||
message: "Regular Build:"
|
||||
[-Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/dev/flipper-z-f7-update-${DRONE_BUILD_NUMBER}.tgz&channel=dev-cfw&version=${DRONE_BUILD_NUMBER})"
|
||||
document:
|
||||
- dev/flipper-z-f7-update-${DRONE_BUILD_NUMBER}.tgz
|
||||
|
||||
- name: "Send clean build to telegram"
|
||||
image: appleboy/drone-telegram
|
||||
settings:
|
||||
token:
|
||||
from_secret: tgtoken
|
||||
to:
|
||||
from_secret: tgid_dev
|
||||
format: markdown
|
||||
message: "Clean (Main apps only) Build:"
|
||||
document:
|
||||
- flipper-z-f7-update-${DRONE_BUILD_NUMBER}c.tgz
|
||||
|
||||
- name: "Send extra pack build to telegram"
|
||||
image: appleboy/drone-telegram
|
||||
settings:
|
||||
@@ -666,10 +411,9 @@ steps:
|
||||
DISCORD_WEBHOOK:
|
||||
from_secret: dis_dev_webhook
|
||||
commands:
|
||||
- wget "https://raw.githubusercontent.com/fieu/discord.sh/2253303efc0e7211ac2777d2535054cbb872f1e0/discord.sh"
|
||||
- wget "https://raw.githubusercontent.com/fieu/discord.sh/e1dc1a7595efad2cad8f072f0b3531c470f5b7c8/discord.sh"
|
||||
- chmod +x ./discord.sh
|
||||
- echo 'Unleashed firmware dev build successful!\n\nBuild - '${DRONE_BUILD_NUMBER}'\n\nCommit - https://github.com/DarkFlippers/unleashed-firmware/commit/'${DRONE_COMMIT_SHA}'\n\n[-> Sponsor our project](https://boosty.to/mmxdev)\n\n[-Version with Extra apps - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'e.tgz&channel=dev-cfw&version='${DRONE_BUILD_NUMBER}'e)\n\n[-Version with only main apps - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'c.tgz&channel=dev-cfw&version='${DRONE_BUILD_NUMBER}'c)\n\n[-Version with RGB patch - only for hardware mod! - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'r.tgz&channel=dev-cfw&version='${DRONE_BUILD_NUMBER}'r)\n\n[-Version with RGB patch - only for hardware mod! - Direct download-](https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'r.tgz)\n\n[-Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/dev/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'.tgz&channel=dev-cfw&version='${DRONE_BUILD_NUMBER}')' > messagedisc.txt
|
||||
- ./discord.sh --text "$(jq -Rs . <messagedisc.txt | cut -c 2- | rev | cut -c 2- | rev)"
|
||||
- ./discord.sh --text 'Unleashed firmware dev build successful!\n\nBuild - '${DRONE_BUILD_NUMBER}'\n\nSHA - '${DRONE_COMMIT_SHA}'\n\n[-Version with extra apps - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'e.tgz&channel=dev-cfw&version='${DRONE_BUILD_NUMBER}'e)\n\n[-Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/dev/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'.tgz&channel=dev-cfw&version='${DRONE_BUILD_NUMBER}')'
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
@@ -678,4 +422,4 @@ trigger:
|
||||
- push
|
||||
|
||||
node:
|
||||
typ: dev1
|
||||
typ: haupt
|
||||
|
||||
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@@ -2,4 +2,4 @@
|
||||
* @xMasterX
|
||||
|
||||
# Assets
|
||||
/assets/resources/infrared/assets/ @amec0e @Leptopt1los @xMasterX
|
||||
/assets/resources/infrared/ @xMasterX @amec0e
|
||||
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@@ -1,4 +1,4 @@
|
||||
patreon: mmxdev
|
||||
ko_fi: masterx
|
||||
custom:
|
||||
[
|
||||
"https://boosty.to/mmxdev",
|
||||
|
||||
114
.github/workflows/codeql.yml
vendored
114
.github/workflows/codeql.yml
vendored
@@ -1,114 +0,0 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
run-name: "CodeQL Analyze ${{ github.ref_name }} by @${{ github.ACTOR }}"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["dev"]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
# Runner size impacts CodeQL analysis time. To learn more, please see:
|
||||
# - https://gh.io/recommended-hardware-resources-for-running-codeql
|
||||
# - https://gh.io/supported-runners-and-hardware-resources
|
||||
# - https://gh.io/using-larger-runners
|
||||
# Consider using larger runners for possible analysis time improvements.
|
||||
runs-on: [ "ubuntu-latest" ]
|
||||
timeout-minutes: 60
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: ["cpp"]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby', 'swift' ]
|
||||
# Use only 'java' to analyze code written in Java, Kotlin or both
|
||||
# Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
|
||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||
env:
|
||||
PATH_SARIF_DIR: ".github/results.sarif"
|
||||
PATH_SARIF_FILE: ".github/results.sarif/${{ matrix.language }}.sarif"
|
||||
FBT_NO_SYNC: 0
|
||||
DIST_SUFFIX: "codeql"
|
||||
WORKFLOW_BRANCH_OR_TAG: release-cfw
|
||||
LANG_CATEGORY: "/language:${{matrix.language}}"
|
||||
|
||||
steps:
|
||||
- name: Checkout Firmware Files
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
clean: "true"
|
||||
submodules: "true"
|
||||
fetch-depth: "0"
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
setup-python-dependencies: true
|
||||
|
||||
- name: Resolve CodeQL Build Env
|
||||
uses: github/codeql-action/resolve-environment@v2
|
||||
with:
|
||||
language: ${{ matrix.language }}
|
||||
#debug: true
|
||||
|
||||
- name: Build Firmware
|
||||
shell: bash
|
||||
if: ${{ success() }}
|
||||
run: |
|
||||
./fbt COMPACT=1 DEBUG=0 FBT_NO_SYNC=${{ env.FBT_NO_SYNC }}
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
if: ${{ success() }}
|
||||
with:
|
||||
threads: 4
|
||||
category: "${{ env.LANG_CATEGORY }}"
|
||||
output: "${{ env.PATH_SARIF_DIR }}"
|
||||
upload-database: false
|
||||
upload: "failure-only" # disable the upload here - we will upload in a different action
|
||||
|
||||
- name: Filter dirs for SARIF
|
||||
uses: advanced-security/filter-sarif@v1
|
||||
if: ${{ success() }}
|
||||
with:
|
||||
# filter out all test files unless they contain a sql-injection vulnerability
|
||||
patterns: |
|
||||
-build/**
|
||||
-dist/**
|
||||
-toolchain/**
|
||||
-lib/**
|
||||
input: "${{ env.PATH_SARIF_FILE }}"
|
||||
output: "${{ env.PATH_SARIF_FILE }}"
|
||||
|
||||
- name: Upload CodeQL SARIF
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
if: ${{ success() }}
|
||||
with:
|
||||
category: "${{ env.LANG_CATEGORY }}"
|
||||
sarif_file: "${{ env.PATH_SARIF_FILE }}"
|
||||
|
||||
# optional: for debugging the uploaded sarif
|
||||
# - name: Upload loc as a Build Artifact
|
||||
# uses: actions/upload-artifact@v3
|
||||
# with:
|
||||
# name: sarif-results
|
||||
# path: sarif-results
|
||||
# retention-days: 1
|
||||
30
.gitignore
vendored
30
.gitignore
vendored
@@ -1,8 +1,6 @@
|
||||
*~
|
||||
*.swp
|
||||
*.swo
|
||||
*.gdb_history
|
||||
*.old
|
||||
|
||||
|
||||
# LSP
|
||||
@@ -30,31 +28,28 @@ bindings/
|
||||
.mxproject
|
||||
Brewfile.lock.json
|
||||
|
||||
# Visual Studio Code
|
||||
.vscode/
|
||||
|
||||
# Kate
|
||||
.kateproject
|
||||
.kateconfig
|
||||
|
||||
# legendary cmake's
|
||||
build
|
||||
CMakeLists.txt
|
||||
|
||||
# bundle output
|
||||
dist
|
||||
|
||||
# kde
|
||||
.directory
|
||||
null.d
|
||||
|
||||
# SCons
|
||||
.sconsign.dblite
|
||||
|
||||
|
||||
# Visual Studio Code
|
||||
/.vscode
|
||||
|
||||
# bundle output
|
||||
/dist
|
||||
/artifacts-default
|
||||
/artifacts-ofw-anims
|
||||
/artifacts-rgb-patch
|
||||
/artifacts-extra-apps
|
||||
/artifacts-clean
|
||||
|
||||
# SCons build dir
|
||||
/build
|
||||
build/
|
||||
|
||||
# Toolchain
|
||||
/toolchain
|
||||
@@ -65,8 +60,5 @@ openocd.log
|
||||
# PVS Studio temporary files
|
||||
.PVS-Studio/
|
||||
PVS-Studio.log
|
||||
*.PVS-Studio.*
|
||||
|
||||
.gdbinit
|
||||
|
||||
/fbt_options_local.py
|
||||
26
.gitmodules
vendored
26
.gitmodules
vendored
@@ -1,6 +1,9 @@
|
||||
[submodule "lib/mlib"]
|
||||
path = lib/mlib
|
||||
url = https://github.com/P-p-H-d/mlib.git
|
||||
[submodule "lib/STM32CubeWB"]
|
||||
path = lib/STM32CubeWB
|
||||
url = https://github.com/Flipper-Zero/STM32CubeWB.git
|
||||
[submodule "lib/littlefs"]
|
||||
path = lib/littlefs
|
||||
url = https://github.com/littlefs-project/littlefs.git
|
||||
@@ -10,7 +13,6 @@
|
||||
[submodule "assets/protobuf"]
|
||||
path = assets/protobuf
|
||||
url = https://github.com/flipperdevices/flipperzero-protobuf.git
|
||||
shallow = false
|
||||
[submodule "lib/libusb_stm32"]
|
||||
path = lib/libusb_stm32
|
||||
url = https://github.com/flipperdevices/libusb_stm32.git
|
||||
@@ -26,19 +28,9 @@
|
||||
[submodule "lib/cxxheaderparser"]
|
||||
path = lib/cxxheaderparser
|
||||
url = https://github.com/robotpy/cxxheaderparser.git
|
||||
[submodule "lib/heatshrink"]
|
||||
path = lib/heatshrink
|
||||
url = https://github.com/flipperdevices/heatshrink.git
|
||||
[submodule "lib/st_cmsis_device_wb"]
|
||||
path = lib/stm32wb_cmsis
|
||||
url = https://github.com/STMicroelectronics/cmsis_device_wb
|
||||
[submodule "lib/stm32wbxx_hal_driver"]
|
||||
path = lib/stm32wb_hal
|
||||
url = https://github.com/STMicroelectronics/stm32wbxx_hal_driver
|
||||
[submodule "lib/stm32wb_copro"]
|
||||
path = lib/stm32wb_copro
|
||||
url = https://github.com/flipperdevices/stm32wb_copro.git
|
||||
[submodule "subghz_remote"]
|
||||
path = applications/main/subghz_remote
|
||||
url = https://github.com/DarkFlippers/SubGHz_Remote.git
|
||||
branch = ufw_main_app
|
||||
[submodule "applications/plugins/subbrute"]
|
||||
path = applications/plugins/subbrute
|
||||
url = https://github.com/derskythe/flipperzero-subbrute.git
|
||||
[submodule "applications/plugins/dap_link/lib/free-dap"]
|
||||
path = applications/plugins/dap_link/lib/free-dap
|
||||
url = https://github.com/ataradov/free-dap.git
|
||||
|
||||
@@ -44,6 +44,3 @@
|
||||
|
||||
# Functions that always return the same error code
|
||||
//-V:picopass_device_decrypt:1048
|
||||
|
||||
# Examples
|
||||
//V_EXCLUDE_PATH applications/examples/
|
||||
@@ -1 +1 @@
|
||||
--ignore-ccache -C gccarm --rules-config .pvsconfig -e lib/cmsis_core -e lib/fatfs -e lib/fnv1a-hash -e lib/FreeRTOS-Kernel -e lib/heatshrink -e lib/libusb_stm32 -e lib/littlefs -e lib/mbedtls -e lib/microtar -e lib/mlib -e lib/stm32wb_cmsis -e lib/stm32wb_copro -e lib/stm32wb_hal -e lib/u8g2 -e lib/nanopb -e lib/mjs -e */arm-none-eabi/*
|
||||
--ignore-ccache -C gccarm --rules-config .pvsconfig -e lib/fatfs -e lib/fnv1a-hash -e lib/FreeRTOS-Kernel -e lib/heatshrink -e lib/libusb_stm32 -e lib/littlefs -e lib/mbedtls -e lib/micro-ecc -e lib/microtar -e lib/mlib -e lib/qrcode -e lib/ST25RFAL002 -e lib/STM32CubeWB -e lib/u8g2 -e lib/nanopb -e */arm-none-eabi/* -e applications/plugins/dap_link/lib/free-dap
|
||||
|
||||
9
.vscode/.gitignore
vendored
9
.vscode/.gitignore
vendored
@@ -1,5 +1,4 @@
|
||||
/c_cpp_properties.json
|
||||
/extensions.json
|
||||
/launch.json
|
||||
/settings.json
|
||||
/tasks.json
|
||||
./c_cpp_properties.json
|
||||
./launch.json
|
||||
./settings.json
|
||||
./tasks.json
|
||||
|
||||
2
.vscode/ReadMe.md
vendored
2
.vscode/ReadMe.md
vendored
@@ -1,4 +1,4 @@
|
||||
# Visual Studio Code workspace for Flipper Zero {#vscode}
|
||||
# Visual Studio Code workspace for Flipper Zero
|
||||
|
||||
## Setup
|
||||
|
||||
|
||||
32
.vscode/example/c_cpp_properties.json
vendored
Normal file
32
.vscode/example/c_cpp_properties.json
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Win32",
|
||||
"compilerPath": "${workspaceFolder}/toolchain/x86_64-windows/bin/arm-none-eabi-gcc.exe",
|
||||
"intelliSenseMode": "gcc-arm",
|
||||
"compileCommands": "${workspaceFolder}/build/latest/compile_commands.json",
|
||||
"configurationProvider": "ms-vscode.cpptools",
|
||||
"cStandard": "gnu17",
|
||||
"cppStandard": "c++17"
|
||||
},
|
||||
{
|
||||
"name": "Linux",
|
||||
"compilerPath": "${workspaceFolder}/toolchain/x86_64-linux/bin/arm-none-eabi-gcc",
|
||||
"intelliSenseMode": "gcc-arm",
|
||||
"compileCommands": "${workspaceFolder}/build/latest/compile_commands.json",
|
||||
"configurationProvider": "ms-vscode.cpptools",
|
||||
"cStandard": "gnu17",
|
||||
"cppStandard": "c++17"
|
||||
},
|
||||
{
|
||||
"name": "Mac",
|
||||
"compilerPath": "${workspaceFolder}/toolchain/x86_64-darwin/bin/arm-none-eabi-gcc",
|
||||
"intelliSenseMode": "gcc-arm",
|
||||
"compileCommands": "${workspaceFolder}/build/latest/compile_commands.json",
|
||||
"configurationProvider": "ms-vscode.cpptools",
|
||||
"cStandard": "gnu17",
|
||||
"cppStandard": "c++17"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
19
.vscode/example/clangd/extensions.json
vendored
19
.vscode/example/clangd/extensions.json
vendored
@@ -1,19 +0,0 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
||||
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
||||
// List of extensions which should be recommended for users of this workspace.
|
||||
"recommendations": [
|
||||
"ms-python.black-formatter",
|
||||
"llvm-vs-code-extensions.vscode-clangd",
|
||||
"amiralizadeh9480.cpp-helper",
|
||||
"marus25.cortex-debug",
|
||||
"zxh404.vscode-proto3",
|
||||
"augustocdias.tasks-shell-input"
|
||||
],
|
||||
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
||||
"unwantedRecommendations": [
|
||||
"twxs.cmake",
|
||||
"ms-vscode.cpptools",
|
||||
"ms-vscode.cmake-tools"
|
||||
]
|
||||
}
|
||||
29
.vscode/example/cpptools/c_cpp_properties.json
vendored
29
.vscode/example/cpptools/c_cpp_properties.json
vendored
@@ -1,29 +0,0 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Win32",
|
||||
"compilerPath": "${workspaceFolder}/toolchain/x86_64-windows/bin/arm-none-eabi-gcc.exe",
|
||||
"intelliSenseMode": "gcc-arm",
|
||||
"compileCommands": "${workspaceFolder}/build/latest/compile_commands.json",
|
||||
"cStandard": "gnu23",
|
||||
"cppStandard": "c++20"
|
||||
},
|
||||
{
|
||||
"name": "Linux",
|
||||
"compilerPath": "${workspaceFolder}/toolchain/x86_64-linux/bin/arm-none-eabi-gcc",
|
||||
"intelliSenseMode": "gcc-arm",
|
||||
"compileCommands": "${workspaceFolder}/build/latest/compile_commands.json",
|
||||
"cStandard": "gnu23",
|
||||
"cppStandard": "c++20"
|
||||
},
|
||||
{
|
||||
"name": "Mac",
|
||||
"compilerPath": "${workspaceFolder}/toolchain/x86_64-darwin/bin/arm-none-eabi-gcc",
|
||||
"intelliSenseMode": "gcc-arm",
|
||||
"compileCommands": "${workspaceFolder}/build/latest/compile_commands.json",
|
||||
"cStandard": "gnu23",
|
||||
"cppStandard": "c++20"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
20
.vscode/example/cpptools/extensions.json
vendored
20
.vscode/example/cpptools/extensions.json
vendored
@@ -1,20 +0,0 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
||||
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
||||
// List of extensions which should be recommended for users of this workspace.
|
||||
"recommendations": [
|
||||
"ms-python.black-formatter",
|
||||
"ms-vscode.cpptools",
|
||||
"amiralizadeh9480.cpp-helper",
|
||||
"marus25.cortex-debug",
|
||||
"zxh404.vscode-proto3",
|
||||
"augustocdias.tasks-shell-input",
|
||||
"rioj7.command-variable"
|
||||
],
|
||||
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
||||
"unwantedRecommendations": [
|
||||
"llvm-vs-code-extensions.vscode-clangd",
|
||||
"twxs.cmake",
|
||||
"ms-vscode.cmake-tools"
|
||||
]
|
||||
}
|
||||
46
.vscode/example/launch.json
vendored
46
.vscode/example/launch.json
vendored
@@ -11,10 +11,10 @@
|
||||
"args": {
|
||||
"useSingleResult": true,
|
||||
"env": {
|
||||
"PATH": "${workspaceFolder}${command:extension.commandvariable.envListSep}${env:PATH}"
|
||||
"PATH": "${workspaceFolder};${env:PATH}"
|
||||
},
|
||||
"command": "fbt -s get_blackmagic",
|
||||
"description": "Get Blackmagic device"
|
||||
"command": "./fbt get_blackmagic",
|
||||
"description": "Get Blackmagic device",
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -27,21 +27,20 @@
|
||||
"type": "cortex-debug",
|
||||
"servertype": "openocd",
|
||||
"device": "stlink",
|
||||
"svdFile": "./scripts/debug/STM32WB55_CM4.svd",
|
||||
"svdFile": "./debug/STM32WB55_CM4.svd",
|
||||
// If you're debugging early in the boot process, before OS scheduler is running,
|
||||
// you have to comment out the following line.
|
||||
"rtos": "FreeRTOS",
|
||||
"configFiles": [
|
||||
"interface/stlink.cfg",
|
||||
"./scripts/debug/stm32wbx.cfg",
|
||||
"./debug/stm32wbx.cfg",
|
||||
],
|
||||
"postAttachCommands": [
|
||||
"source scripts/debug/flipperversion.py",
|
||||
"fw-version",
|
||||
// "compare-sections",
|
||||
"source scripts/debug/flipperapps.py",
|
||||
"source debug/flipperapps.py",
|
||||
"fap-set-debug-elf-root build/latest/.extapps",
|
||||
// "source scripts/debug/FreeRTOS/FreeRTOS.py",
|
||||
// "source debug/FreeRTOS/FreeRTOS.py",
|
||||
// "svd_load debug/STM32WB55_CM4.svd"
|
||||
]
|
||||
// "showDevDebugOutput": "raw",
|
||||
},
|
||||
@@ -53,16 +52,14 @@
|
||||
"type": "cortex-debug",
|
||||
"servertype": "external",
|
||||
"gdbTarget": "${input:BLACKMAGIC}",
|
||||
"svdFile": "./scripts/debug/STM32WB55_CM4.svd",
|
||||
"svdFile": "./debug/STM32WB55_CM4.svd",
|
||||
"rtos": "FreeRTOS",
|
||||
"postAttachCommands": [
|
||||
"monitor swdp_scan",
|
||||
"attach 1",
|
||||
"set confirm off",
|
||||
"set mem inaccessible-by-default off",
|
||||
"source scripts/debug/flipperversion.py",
|
||||
"fw-version",
|
||||
"source scripts/debug/flipperapps.py",
|
||||
"source debug/flipperapps.py",
|
||||
"fap-set-debug-elf-root build/latest/.extapps",
|
||||
// "compare-sections",
|
||||
]
|
||||
@@ -77,12 +74,10 @@
|
||||
"servertype": "jlink",
|
||||
"interface": "swd",
|
||||
"device": "STM32WB55RG",
|
||||
"svdFile": "./scripts/debug/STM32WB55_CM4.svd",
|
||||
"svdFile": "./debug/STM32WB55_CM4.svd",
|
||||
"rtos": "FreeRTOS",
|
||||
"postAttachCommands": [
|
||||
"source scripts/debug/flipperversion.py",
|
||||
"fw-version",
|
||||
"source scripts/debug/flipperapps.py",
|
||||
"source debug/flipperapps.py",
|
||||
"fap-set-debug-elf-root build/latest/.extapps",
|
||||
]
|
||||
// "showDevDebugOutput": "raw",
|
||||
@@ -95,20 +90,27 @@
|
||||
"type": "cortex-debug",
|
||||
"servertype": "openocd",
|
||||
"device": "cmsis-dap",
|
||||
"svdFile": "./scripts/debug/STM32WB55_CM4.svd",
|
||||
"svdFile": "./debug/STM32WB55_CM4.svd",
|
||||
"rtos": "FreeRTOS",
|
||||
"configFiles": [
|
||||
"interface/cmsis-dap.cfg",
|
||||
"./scripts/debug/stm32wbx.cfg",
|
||||
"./debug/stm32wbx.cfg",
|
||||
],
|
||||
"postAttachCommands": [
|
||||
"source scripts/debug/flipperversion.py",
|
||||
"fw-version",
|
||||
"source scripts/debug/flipperapps.py",
|
||||
"source debug/flipperapps.py",
|
||||
"fap-set-debug-elf-root build/latest/.extapps",
|
||||
],
|
||||
// "showDevDebugOutput": "raw",
|
||||
},
|
||||
{
|
||||
"name": "fbt debug",
|
||||
"type": "python",
|
||||
"request": "launch",
|
||||
"program": "./lib/scons/scripts/scons.py",
|
||||
"args": [
|
||||
"plugin_dist"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "python debug",
|
||||
"type": "python",
|
||||
|
||||
25
.vscode/example/settings.json
vendored
25
.vscode/example/settings.json
vendored
@@ -1,24 +1,25 @@
|
||||
{
|
||||
"C_Cpp.default.cStandard": "gnu23",
|
||||
"C_Cpp.default.cppStandard": "c++20",
|
||||
"C_Cpp.default.cStandard": "gnu17",
|
||||
"C_Cpp.default.cppStandard": "c++17",
|
||||
"python.formatting.provider": "black",
|
||||
"workbench.tree.indent": 12,
|
||||
"cortex-debug.enableTelemetry": false,
|
||||
"cortex-debug.variableUseNaturalFormat": true,
|
||||
"cortex-debug.showRTOS": true,
|
||||
"cortex-debug.armToolchainPath": "${workspaceFolder}/toolchain/current/bin",
|
||||
"cortex-debug.openocdPath": "${workspaceFolder}/toolchain/current/bin/openocd",
|
||||
"cortex-debug.gdbPath": "${workspaceFolder}/toolchain/current/bin/arm-none-eabi-gdb-py3",
|
||||
"cortex-debug.armToolchainPath.windows": "${workspaceFolder}/toolchain/x86_64-windows/bin",
|
||||
"cortex-debug.armToolchainPath.linux": "${workspaceFolder}/toolchain/x86_64-linux/bin",
|
||||
"cortex-debug.armToolchainPath.osx": "${workspaceFolder}/toolchain/x86_64-darwin/bin",
|
||||
"cortex-debug.openocdPath.windows": "${workspaceFolder}/toolchain/x86_64-windows/openocd/bin/openocd.exe",
|
||||
"cortex-debug.openocdPath.linux": "${workspaceFolder}/toolchain/x86_64-linux/openocd/bin/openocd",
|
||||
"cortex-debug.openocdPath.osx": "${workspaceFolder}/toolchain/x86_64-darwin/openocd/bin/openocd",
|
||||
"cortex-debug.gdbPath.windows": "${workspaceFolder}/toolchain/x86_64-windows/bin/arm-none-eabi-gdb-py.bat",
|
||||
"cortex-debug.gdbPath.linux": "${workspaceFolder}/toolchain/x86_64-linux/bin/arm-none-eabi-gdb-py",
|
||||
"cortex-debug.gdbPath.osx": "${workspaceFolder}/toolchain/x86_64-darwin/bin/arm-none-eabi-gdb-py",
|
||||
"editor.formatOnSave": true,
|
||||
"files.associations": {
|
||||
"*.scons": "python",
|
||||
"SConscript": "python",
|
||||
"SConstruct": "python",
|
||||
"*.fam": "python",
|
||||
},
|
||||
"clangd.arguments": [
|
||||
// We might be able to tighten this a bit more to only include the correct toolchain.
|
||||
"--query-driver=**",
|
||||
"--compile-commands-dir=${workspaceFolder}/build/latest"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
48
.vscode/example/tasks.json
vendored
48
.vscode/example/tasks.json
vendored
@@ -4,41 +4,41 @@
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "[Release] Build Firmware",
|
||||
"label": "[Release] Build",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0"
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Build Firmware",
|
||||
"label": "[Debug] Build",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt"
|
||||
},
|
||||
{
|
||||
"label": "[FBT] Format",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt format"
|
||||
},
|
||||
{
|
||||
"label": "[FBT] Clear",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt -c"
|
||||
},
|
||||
{
|
||||
"label": "[Release] Flash (SWD)",
|
||||
"label": "[Release] Flash (ST-Link)",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash"
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Flash (SWD)",
|
||||
"label": "[Debug] Flash (ST-Link)",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt FORCE=1 flash"
|
||||
},
|
||||
{
|
||||
"label": "[Release] Flash (blackmagic)",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash_blackmagic"
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Flash (blackmagic)",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt FORCE=1 flash_blackmagic"
|
||||
},
|
||||
{
|
||||
"label": "[Release] Flash (JLink)",
|
||||
"group": "build",
|
||||
@@ -123,29 +123,17 @@
|
||||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 fap_dist"
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Build App",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt build APPSRC=${relativeFileDirname}"
|
||||
},
|
||||
{
|
||||
"label": "[Release] Build App",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 build APPSRC=${relativeFileDirname}"
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Launch App on Flipper",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt launch APPSRC=${relativeFileDirname}"
|
||||
"command": "./fbt launch_app APPSRC=${relativeFileDirname}"
|
||||
},
|
||||
{
|
||||
"label": "[Release] Launch App on Flipper",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 launch APPSRC=${relativeFileDirname}"
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 launch_app APPSRC=${relativeFileDirname}"
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Launch App on Flipper with Serial Console",
|
||||
|
||||
18
.vscode/extensions.json
vendored
Normal file
18
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
||||
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
||||
// List of extensions which should be recommended for users of this workspace.
|
||||
"recommendations": [
|
||||
"ms-python.black-formatter",
|
||||
"ms-vscode.cpptools",
|
||||
"amiralizadeh9480.cpp-helper",
|
||||
"marus25.cortex-debug",
|
||||
"zxh404.vscode-proto3",
|
||||
"augustocdias.tasks-shell-input"
|
||||
],
|
||||
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
||||
"unwantedRecommendations": [
|
||||
"twxs.cmake",
|
||||
"ms-vscode.cmake-tools"
|
||||
]
|
||||
}
|
||||
157
CHANGELOG.md
157
CHANGELOG.md
@@ -1,143 +1,44 @@
|
||||
## New changes
|
||||
* NFC: **EMV Fixes and imporvements** (old saved files may be not compatible now) (by @wosk & @Leptopt1los | PR #702)
|
||||
* NFC: **Parsers refactoring** (by @Leptopt1los)
|
||||
* NFC: **Kazan parser improved** - token parse option added (by @Leptopt1los)
|
||||
* NFC: **Update ndef parser**, mf classic dict changes (by @Willy-JL)
|
||||
* RFID: Test swap of em4100 t5577 blocks (details in issue 3463 OFW)
|
||||
* RFID: Fix RAW read crash (by @Willy-JL)
|
||||
* Infrared: Update universal remote assets (by @amec0e | PR #718 #719)
|
||||
* SubGHz: Add 430.50 mhz (by @MizumasuShoichi | PR #721)
|
||||
* SubGHz: **Magellan Event Code Update** (by @wooferguy | PR #713)
|
||||
* SubGHz: Reduce subghz add manually scene flash size (by @Willy-JL)
|
||||
* SubGHz: Fix led blink on decode raw > signal info (by @Willy-JL)
|
||||
* HID App: apply fix for ms teams on macos (by @cpressland)
|
||||
* HID App: merge official fw hid app keyboard changes
|
||||
* Misc: Use non prefixed names for regular files with random name
|
||||
* Misc: Revert usb cdc config changes to verify issue (storage timeout during firmware update) (OFW 3452)
|
||||
* Misc: Fixes for text box and uart echo demo app, remove duplicated emv parser plugin (by @Willy-JL)
|
||||
* Expansion `is_connected` API to check for VGM (by @HaxSam)
|
||||
* New JavaScript Modules `UsbDisk`,`badusb.quit() + altstring`,`SubGHz`,`Submenu`,`BleBeacon`,`Keyboard`,`Math`,`GPIO`, `textbox` (by @Willy-JL, @Spooks4576, @Sil333033, @oldip)
|
||||
* Apps: **BadBT renamed and moved from Apps-Bluetooth to Apps-Tools as BadKB**
|
||||
* Apps: Added **FindMy Flipper** app
|
||||
* Apps: NFC Magic - **Gen4 improvements**
|
||||
* Apps: **Check out Apps updates by following** [this link](https://github.com/xMasterX/all-the-plugins/commits/dev)
|
||||
* OFW: BLE/GAP fixes
|
||||
* OFW: Add support for Pioneer SR IR remotes
|
||||
* OFW: fbt/ufbt: Ensure POSIX paths are passed to GDB on all platforms
|
||||
* OFW: Add support for DEFAULT_STRING_DELAY in Bad USB App
|
||||
* OFW: Adding F13-F24 function key support to BadUSB
|
||||
* OFW PR 3532: NFC UI fixes (by gornekich)
|
||||
* OFW PR 3504: NFC: **Slix privacy password reveal and Desfire detect fix** (by gornekich)
|
||||
* OFW: **Infrared fixes and more**
|
||||
* OFW: NFC Parsers cosmetic fixes
|
||||
* OFW: NFC wording fixes
|
||||
* OFW: **Fix iButton emulation regression**
|
||||
* OFW: Add the Freedom_2_dolphins animation
|
||||
* OFW: Infrared: Add Fujitsu ASYG24KMTB
|
||||
* OFW: Asynchronous Infrared remote manipulation
|
||||
* OFW: Fix troika 4K keys
|
||||
* OFW: Archive: Fix item focus after aborting the Delete operation
|
||||
* OFW: Troyka parser improvements (by UL Team)
|
||||
* OFW: NFC: Fix washcity plugin verify function being to greedy
|
||||
* OFW: Parser for Santiago, Chile BIP transit card
|
||||
* OFW: WiFi board: fixed update script on Windows (unfortunately also Mac and Linux)
|
||||
* OFW: Gui: reset canvas orientation and frame when entering direct draw mode
|
||||
* OFW: FBT/uFBT: Enable C++20/GNU23 in VSCode IntelliSense
|
||||
* OFW: Toolchain fixes
|
||||
* OFW: Quote $FBT_TOOLCHAIN_PATH to avoid splitting
|
||||
* OFW: **ble: profile rework**
|
||||
* OFW: lfrfid/em4100: added support for different bit rates (16clk was added back into UL, still not reading properly)
|
||||
* OFW: T5577 lib: write with mask function added
|
||||
* OFW: Archive: fixed Apps tab ext filter
|
||||
* OFW: FuriHalRtc refactor: new datetime lib (by UL Team)
|
||||
* OFW: bit_lib and nfc_util refactor (by UL Team)
|
||||
* OFW: Gui text box: fix formatted string memory reservation
|
||||
* OFW: JS debug disabled, archive and file browser fixes
|
||||
* OFW: VSCode integration fixes for new toolchain
|
||||
* OFW: **FIX ISO15693 emulation**
|
||||
* OFW: JS serial module renamed, uart channel selection
|
||||
* OFW: mjs: minor fixes
|
||||
* OFW: **JavaScript runner**
|
||||
* OFW: Fixed MyKey check LockID
|
||||
* OFW: Check universal remote files before loading
|
||||
* OFW: NFC: fix retry scene navigation logic
|
||||
* OFW: Expansion module service improvements
|
||||
* OFW: New toolchain with gcc 12 (+ aarch64 support!)
|
||||
* OFW: HID app: keyboard modifiers fix
|
||||
* OFW: CLI: cat command crash workaround
|
||||
* OFW: NFC: Custom UID entry when adding manually
|
||||
* OFW: Added NFC plugin; Some parser
|
||||
* OFW: **Slix disable privacy** (Unlock SLIX-L)
|
||||
* OFW: NFC: **Add support for Gallagher access control** (MIFARE Classic only)
|
||||
* OFW: furi/core/timer: resolve timer handle use-after-free post deletion
|
||||
* OFW: FuriHal: various GPIO improvements
|
||||
* OFW: GUI: canvas commit callback has been moved to canvas. Direct Draw apps can now be streamed via RPC.
|
||||
* OFW: nfc app: fix incorrect protocol detection in save scene (by UL Team)
|
||||
* OFW: NFC: **MFC Unlock with Dictionary**
|
||||
* OFW: ITSO Parser (UK)
|
||||
* OFW: NFC: fix application opening from browser
|
||||
* OFW: Rework more info scene for Ultralight cards
|
||||
* OFW: NFC UI refactor
|
||||
* OFW: Add an NFC parser for the San Francisco Bay Area "Clipper" transit card.
|
||||
* OFW: Fix nfc_protocol_support_scene_save_name_on_event crash
|
||||
* OFW: NFC: Display unread Mifare Classic bytes as question marks
|
||||
* OFW: Troika layout fixes
|
||||
* OFW: NFC: MF Classic parsers read() fix (dictionary attack skip)
|
||||
<br><br>
|
||||
#### Known NFC post-refactor regressions list:
|
||||
- Mifare Mini clones reading is broken (original mini working fine) (OFW)
|
||||
- NFC CLI was removed with refactoring (OFW) (will be back soon)
|
||||
- Current list of affected apps: https://github.com/xMasterX/all-the-plugins/tree/dev/apps_broken_by_last_refactors
|
||||
- Also in app **Enhanced Sub-GHz Chat** - NFC part was temporarily removed to make app usable, NFC part of the app requires remaking it with new nfc stack
|
||||
### New changes
|
||||
* SubGHz: **Nice ON2E (Nice One)** support (by @assasinfil | PR #335)
|
||||
* SubGHz: Remove 467.75 From freq analyzer since it has too much noise (Frequency is still can be used, just excluded from FA to avoid false detections)
|
||||
* Archive and FileBrowser: **Fixed more navigation issues** (by @Willy-JL | PR #334)
|
||||
* Plugins -> SubGHz Bruteforcer: Fix Linear Delta 3 repeats (now its more stable and we will be sure signal is received correctly)
|
||||
* Plugins: Updated TOTP (Authenticator) [(by akopachov)](https://github.com/akopachov/flipper-zero_authenticator)
|
||||
* OFW: **Fix Cyfral & Metakom emulation (My temp fix removed and proper fix from OFW applied)**
|
||||
* OFW: BadUSB: disable CDC mode, USB mode switch fix
|
||||
* OFW: Updater visual fixes
|
||||
|
||||
----
|
||||
#### [🎲 Download latest extra apps pack](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps)
|
||||
|
||||
[-> How to install firmware](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)
|
||||
|
||||
[-> Download qFlipper (official link)](https://flipperzero.one/update)
|
||||
|
||||
## Please support development of the project
|
||||
|Service|Remark|Link/Wallet|
|
||||
|-|-|-|
|
||||
|**Patreon**||https://patreon.com/mmxdev|
|
||||
|**Boosty**|patreon alternative|https://boosty.to/mmxdev|
|
||||
|cloudtips|only RU payments accepted|https://pay.cloudtips.ru/p/7b3e9d65|
|
||||
|YooMoney|only RU payments accepted|https://yoomoney.ru/fundraise/XA49mgQLPA0.221209|
|
||||
|USDT|(TRC20)|`TSXcitMSnWXUFqiUfEXrTVpVewXy2cYhrs`|
|
||||
|BCH||`qquxfyzntuqufy2dx0hrfr4sndp0tucvky4sw8qyu3`|
|
||||
|ETH|(BSC/ERC20-Tokens)|`darkflippers.eth` (or `0xFebF1bBc8229418FF2408C07AF6Afa49152fEc6a`)|
|
||||
|BTC||`bc1q0np836jk9jwr4dd7p6qv66d04vamtqkxrecck9`|
|
||||
|DOGE||`D6R6gYgBn5LwTNmPyvAQR6bZ9EtGgFCpvv`|
|
||||
|LTC||`ltc1q3ex4ejkl0xpx3znwrmth4lyuadr5qgv8tmq8z9`|
|
||||
|XMR|(Monero)| `41xUz92suUu1u5Mu4qkrcs52gtfpu9rnZRdBpCJ244KRHf6xXSvVFevdf2cnjS7RAeYr5hn9MsEfxKoFDRSctFjG5fv1Mhn`|
|
||||
|TON||`EQCOqcnYkvzOZUV_9bPE_8oTbOrOF03MnF-VcJyjisTZmpGf`|
|
||||
* Boosty: https://boosty.to/mmxdev
|
||||
* Ko-Fi: https://ko-fi.com/masterx
|
||||
* cloudtips (only RU payments accepted): https://pay.cloudtips.ru/p/7b3e9d65
|
||||
* YooMoney (only RU payments accepted): https://yoomoney.ru/fundraise/XA49mgQLPA0.221209
|
||||
* USDT(TRC20): `TSXcitMSnWXUFqiUfEXrTVpVewXy2cYhrs`
|
||||
* BCH: `qquxfyzntuqufy2dx0hrfr4sndp0tucvky4sw8qyu3`
|
||||
* ETH/BSC/ERC20-Tokens: `darkflippers.eth` (or `0xFebF1bBc8229418FF2408C07AF6Afa49152fEc6a`)
|
||||
* BTC: `bc1q0np836jk9jwr4dd7p6qv66d04vamtqkxrecck9`
|
||||
* DOGE: `D6R6gYgBn5LwTNmPyvAQR6bZ9EtGgFCpvv`
|
||||
* LTC: `ltc1q3ex4ejkl0xpx3znwrmth4lyuadr5qgv8tmq8z9`
|
||||
* XMR (Monero): `41xUz92suUu1u5Mu4qkrcs52gtfpu9rnZRdBpCJ244KRHf6xXSvVFevdf2cnjS7RAeYr5hn9MsEfxKoFDRSctFjG5fv1Mhn`
|
||||
* TON: `EQCOqcnYkvzOZUV_9bPE_8oTbOrOF03MnF-VcJyjisTZmpGf`
|
||||
|
||||
#### Thanks to our sponsors who supported project in the past and special thanks to sponsors who supports us on regular basis:
|
||||
ClaraCrazy, Pathfinder [Count Zero cDc], callmezimbra, Quen0n, MERRON, grvpvl (lvpvrg), art_col, ThurstonWaffles, Moneron, UterGrooll, LUCFER, Northpirate, zloepuzo, T.Rat, Alexey B., ionelife, ...
|
||||
### 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 update option - Web Updater**
|
||||
**Recommended option - Web Updater**
|
||||
|
||||
### What `n`, `r`, `e`, ` `, `c` means? What I need to download if I don't want to use Web updater?
|
||||
What build I should download and what this name means - `flipper-z-f7-update-(version)(n / r / e / c).tgz` ? <br>
|
||||
`flipper-z` = for Flipper Zero device<br>
|
||||
`f7` = Hardware version - same for all flipper zero devices<br>
|
||||
`update` = Update package, contains updater, all assets (plugins, IR libs, etc.), and firmware itself<br>
|
||||
`(version)` = Firmware version<br>
|
||||
| Designation | 3 Custom Animation | [Base Apps](https://github.com/xMasterX/all-the-plugins#default-pack) | [Extra Apps](https://github.com/xMasterX/all-the-plugins#extra-pack) | ⚠️RGB mode* |
|
||||
|-----|:---:|:---:|:---:|:---:|
|
||||
| ` ` | ✅ | ✅ | | |
|
||||
| `c` | ✅ | | | |
|
||||
| `n` | | ✅ | | |
|
||||
| `e` | ✅ | ✅ | ✅ | |
|
||||
| `r` | ✅ | ✅ | ✅ | ⚠️ |
|
||||
|
||||
⚠️This is [hardware mod](https://github.com/quen0n/flipperzero-firmware-rgb#readme), works only on modded flippers! do not install on non modded device!
|
||||
|
||||
Firmware Self-update package (update from microSD) - `flipper-z-f7-update-(version).tgz` for mobile app / qFlipper / web<br>
|
||||
Archive of `scripts` folder (contains scripts for FW/plugins development) - `flipper-z-any-scripts-(version).tgz`<br>
|
||||
SDK files for plugins development and uFBT - `flipper-z-f7-sdk-(version).zip`
|
||||
What means `n` or `e` in - `flipper-z-f7-update-(version)(n / e).tgz` ? - `n` means this build comes without our custom animations, only official flipper animations,
|
||||
`e` means build has extra apps pack preinstalled
|
||||
|
||||
Self-update package (update from microSD) - `flipper-z-f7-update-(version).zip` or download `.tgz` for mobile app / qFlipper
|
||||
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ Almost everything in flipper firmware is built around this concept.
|
||||
# C coding style
|
||||
|
||||
- Tab is 4 spaces
|
||||
- Use `./fbt format` to reformat source code and check style guide before commit
|
||||
- Use `fbt format` to reformat source code and check style guide before commit
|
||||
|
||||
## Naming
|
||||
|
||||
|
||||
308
ReadMe.md
308
ReadMe.md
@@ -3,233 +3,226 @@
|
||||
<img src="https://user-images.githubusercontent.com/10697207/186202043-26947e28-b1cc-459a-8f20-ffcc7fc0c71c.png" align="center" alt="fzCUSTOM" border="0">
|
||||
</a>
|
||||
</h3>
|
||||
<div align="center" id="badges">
|
||||
<a href="https://discord.unleashedflip.com">
|
||||
<img src="https://img.shields.io/discord/937479784148115456?style=flat-square&logo=discord&label=Discord&color=%237289DA&link=https%3A%2F%2Fdiscord.unleashedflip.com%2F" alt="Discord server"/>
|
||||
</a>
|
||||
<a href="https://t.me/flipperzero_unofficial">
|
||||
<img src="https://img.shields.io/endpoint?label=EN%20Channel&style=flat-square&url=https%3A%2F%2Fmogyo.ro%2Fquart-apis%2Ftgmembercount%3Fchat_id%3Dflipperzero_unofficial" alt="EN TG channel"/>
|
||||
</a>
|
||||
<a href="https://t.me/flipperzero_unofficial_ru">
|
||||
<img src="https://img.shields.io/endpoint?label=RU%20Channel&style=flat-square&url=https%3A%2F%2Fmogyo.ro%2Fquart-apis%2Ftgmembercount%3Fchat_id%3Dflipperzero_unofficial_ru" alt="RU TG channel"/>
|
||||
</a>
|
||||
<a href="https://t.me/flipperzero_unofficial_ua">
|
||||
<img src="https://img.shields.io/endpoint?label=UA%20Channel&style=flat-square&url=https%3A%2F%2Fmogyo.ro%2Fquart-apis%2Ftgmembercount%3Fchat_id%3Dflipperzero_unofficial_ua" alt="UA TG channel"/>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
### Welcome to the Flipper Zero Unleashed Firmware repo!
|
||||
|
||||
#### **This firmware is a fork from** [flipperdevices/flipperzero-firmware](https://github.com/flipperdevices/flipperzero-firmware)
|
||||
**This firmware is a fork from** [flipperdevices/flipperzero-firmware](https://github.com/flipperdevices/flipperzero-firmware)
|
||||
|
||||
<br>
|
||||
|
||||
### Most stable custom firmware focused on new features and improvements of original firmware components, with almost no UI changes
|
||||
Our goal is to make all features possible on this device without any limitations!
|
||||
|
||||
Please help us implement emulation for all Sub-GHz dynamic (rolling code) protocols!
|
||||
|
||||
<br>
|
||||
|
||||
##### This software is for experimental purposes only and is not meant for any illegal activity/purposes. <br> We do not condone illegal activity and strongly encourage keeping transmissions to legal/valid uses allowed by law. <br> Also, this software is made without any support from Flipper Devices and is in no way related to the official devs.
|
||||
|
||||
### This software is for experimental purposes only and is not meant for any illegal activity/purposes. <br> We do not condone illegal activity and strongly encourage keeping transmissions to legal/valid uses allowed by law. <br> Also, this software is made without any support from Flipper Devices and is in no way related to the official devs.
|
||||
|
||||
<br>
|
||||
Our Discord Community:
|
||||
<br>
|
||||
<a href="https://discord.unleashedflip.com"><img src="https://discordapp.com/api/guilds/937479784148115456/widget.png?style=banner4" alt="Unofficial Discord Community" target="_blank"></a>
|
||||
|
||||
## FAQ (frequently asked questions)
|
||||
[Follow this link to find answers to most asked questions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/FAQ.md)
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
## Dev builds (unstable)
|
||||
## Dev builds
|
||||
- https://dev.unleashedflip.com/
|
||||
- https://t.me/kotnehleb
|
||||
## Releases in Telegram
|
||||
- https://t.me/unleashed_fw
|
||||
|
||||
# What's changed
|
||||
- **Sub-GHz** *lib & hal*
|
||||
- Regional TX restrictions removed
|
||||
- Extra Sub-GHz frequencies
|
||||
- Frequency range can be extended in settings file (Warning: It can damage Flipper's hardware)
|
||||
- Many rolling code [protocols](https://github.com/DarkFlippers/unleashed-firmware#current-modified-and-new-sub-ghz-protocols-list) now have the ability to save & send captured signals
|
||||
- FAAC SLH (Spa) & BFT Mitto (keeloq secure with seed) manual creation
|
||||
- External CC1101 module support [(by quen0n)](https://github.com/DarkFlippers/unleashed-firmware/pull/307)
|
||||
- **Sub-GHz** *Main App*
|
||||
- Save last used frequency [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77)
|
||||
- New frequency analyzer [(by ClusterM)](https://github.com/DarkFlippers/unleashed-firmware/pull/43)
|
||||
- Press OK in frequency analyzer to use detected frequency in Read modes [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77)
|
||||
- Long press OK button in Sub-GHz Frequency analyzer to switch to Read menu [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/79)
|
||||
- New option to use timestamps + protocol name when you saving file, instead of random name or timestamp only - Enable in `Radio Settings -> Protocol Names = ON`
|
||||
- Read mode UI improvements (shows time when signal was received) (by @wosk)
|
||||
- External CC1101 module support (Hardware SPI used)
|
||||
- **Hold right in received signal list to delete selected signal**
|
||||
- **Custom buttons for Keeloq / Alutech AT4N / Nice Flor S / Somfy Telis / Security+ 2.0 / CAME Atomo** - now you can use arrow buttons to send signal with different button code
|
||||
- `Add manually` menu extended with new protocols
|
||||
- FAAC SLH, BFT Mitto / Somfy Telis / Nice Flor S / CAME Atomo, etc.. manual creation with programming new remote into receiver (use button 0xF for BFT Mitto, 0x8 (Prog) on Somfy Telis, (right arrow button for other protocols))
|
||||
- Debug mode counter increase settings (+1 -> +5, +10, default: +1)
|
||||
- Debug PIN output settings for protocol development
|
||||
|
||||
- **Sub-GHz apps** *by unleashed team*
|
||||
- Sub-GHz Bruteforce - static code brute-force plugin |
|
||||
- Time delay (between signals) setting (hold Up in main screen(says Up to Save)) + configure repeats in protocols list by pressing right button on selected protocol
|
||||
- Load your own file and select bytes you want to bruteforce or use preconfigured options in protocols list
|
||||
- Sub-GHz Remote - remote control for 5 sub-ghz files | bind one file for each button
|
||||
- use the built-in constructor or make config file by following this [instruction](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemotePlugin.md)
|
||||
- **Infrared**
|
||||
- Recompiled IR TV Universal Remote for ALL buttons
|
||||
- Universal remotes for Projectors, Fans, A/Cs and Audio(soundbars, etc.) -> Also always updated and verified by our team
|
||||
- Infrared -> `RCA` Protocol
|
||||
- Infrared -> Debug TX PIN output settings
|
||||
- **NFC/RFID/iButton**
|
||||
* LFRFID/iButton Fuzzer plugins
|
||||
* Extra Mifare Classic keys
|
||||
* EMV Protocol + Public data parser (by @Leptopt1los and @wosk)
|
||||
* NFC/LFRFID - Stop emulation after 5 mins to avoid antenna damage (by @Leptopt1los)
|
||||
* NFC `Add manually` -> Mifare Classic with custom UID
|
||||
* NFC parsers: Umarsh, Zolotaya Korona, Kazan, Metromoney, Moscow Social Card, Troika (reworked) and [many others](https://github.com/DarkFlippers/unleashed-firmware/tree/dev/applications/main/nfc/plugins/supported_cards) (by @Leptopt1los and @assasinfil)
|
||||
- **Quality of life & other features**
|
||||
- Customizable Flipper name **Update! Now can be changed in Settings->Desktop** (by @xMasterX and @Willy-JL)
|
||||
- Text Input UI element -> Cursor feature (by @Willy-JL)
|
||||
- Byte Input Mini editor -> **Press UP** multiple times until the nibble editor appears (by @gid9798)
|
||||
- Clock on Desktop -> `Settings -> Desktop -> Show Clock` (by @gid9798)
|
||||
- Battery percentage display with different styles `Settings -> Desktop -> Battery View`
|
||||
- More games in Dummy Mode -> click or hold any of arrow buttons
|
||||
- Lock device with pin(or regular lock if pin not set) by holding UP button on main screen [(by an4tur0r)](https://github.com/DarkFlippers/unleashed-firmware/pull/107)
|
||||
- **BadBT** plugin (BT version of BadKB) [(by Willy-JL, ClaraCrazy, XFW contributors)](https://github.com/ClaraCrazy/Flipper-Xtreme/tree/dev/applications/main/bad_kb) - (See in Applications->Tools) - (aka BadUSB via Bluetooth)
|
||||
- BadUSB -> Keyboard layouts [(by rien > dummy-decoy)](https://github.com/dummy-decoy/flipperzero-firmware/tree/dummy_decoy/bad_usb_keyboard_layout)
|
||||
- Custom community plugins and games added + all known working apps can be downloaded in extra pack in every release
|
||||
- Other small fixes and changes throughout
|
||||
- See other changes in readme below
|
||||
* Sub-GHz regional TX restrictions removed
|
||||
* Sub-GHz frequency range can be extended in settings file (Warning: It can damage Flipper's hardware)
|
||||
* Many rolling code protocols now have the ability to save & send captured signals
|
||||
* FAAC SLH (Spa) & BFT Mitto (secure with seed) manual creation
|
||||
* Sub-GHz static code brute-force plugin
|
||||
* LFRFID Fuzzer plugin
|
||||
* Custom community plugins and games added + all known working apps can be downloaded in extra pack in every release
|
||||
* Extra Sub-GHz frequencies + extra Mifare Classic keys
|
||||
* Picopass/iClass plugin included in releases
|
||||
* Recompiled IR TV Universal Remote for ALL buttons
|
||||
* Universal remote for Projectors, Fans, A/Cs and Audio(soundbars, etc.)
|
||||
* BadUSB keyboard layouts
|
||||
* Customizable Flipper name
|
||||
* Sub-GHz -> Press OK in frequency analyzer to use detected frequency in Read modes
|
||||
* Sub-GHz -> Long press OK button in Sub-GHz Frequency analyzer to switch to Read menu
|
||||
* Sub-GHz -> External CC1101 module support
|
||||
* Other small fixes and changes throughout
|
||||
* See other changes in changelog and in readme below
|
||||
|
||||
Also check the [changelog in releases](https://github.com/DarkFlippers/unleashed-firmware/releases) for latest updates!
|
||||
Also check the changelog in releases for latest updates!
|
||||
|
||||
### Current modified and new Sub-GHz protocols list:
|
||||
Thanks to Official team (to their SubGHz Developer, Skorp) for implementing decoders for these protocols in OFW.
|
||||
Thanks to Official team (to thier SubGHz Developer, Skorp) for implementing decoders for these protocols.
|
||||
|
||||
Keeloq [Not ALL systems supported for decode or emulation!] - [Supported manufacturers list](https://pastes.io/raw/unuj9bhe4m)
|
||||
Encoders/sending made by Eng1n33r & @xMasterX:
|
||||
|
||||
Encoders or sending made by @xMasterX:
|
||||
- Nero Radio 57bit (+ 56bit encoder improvements)
|
||||
- CAME 12bit/24bit encoder fixes (Fixes now merged in OFW)
|
||||
- Keeloq: Dea Mio, Genius Bravo, GSN, HCS101, AN-Motors, JCM Tech, MHouse, Nice Smilo, DTM Neo, FAAC RC,XT, Mutancode, Normstahl, Beninca + Allmatic, Stilmatic, CAME Space, Aprimatic (model TR and similar), Centurion Nova (thanks Carlos !)
|
||||
|
||||
Encoders or sending made by @Eng1n33r(first implementation in Q2 2022) & @xMasterX (current version):
|
||||
- CAME Atomo -> Update! check out new [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||
- Nice Flor S -> How to create new remote - [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||
- FAAC SLH (Spa) -> Update!!! Check out new [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||
- Keeloq: BFT Mitto -> Update! Check out new [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||
- Keeloq [Not ALL systems supported for decode or emulation yet!] - [Supported manufacturers list](https://0bin.net/paste/VwR2lNJY#WH9vnPgvcp7w6zVKucFCuNREKAcOij8KsJ6vqLfMn3b)
|
||||
- Keeloq: HCS101
|
||||
- Keeloq: AN-Motors
|
||||
- Keeloq: JCM Tech
|
||||
- Keeloq: MHouse
|
||||
- Keeloq: Nice Smilo
|
||||
- Keeloq: DTM Neo
|
||||
- Keeloq: FAAC RC,XT
|
||||
- Keeloq: Mutancode
|
||||
- Keeloq: Normstahl
|
||||
- CAME Atomo
|
||||
- Nice Flor S
|
||||
- FAAC SLH (Spa) [External seed calculation required (For info contact me in Discord: Nano#8998)]
|
||||
- BFT Mitto [External seed calculation required (For info contact me in Discord: Nano#8998)]
|
||||
- Security+ v1 & v2
|
||||
- Star Line
|
||||
- Security+ v1 & v2 (encoders was made in OFW)
|
||||
|
||||
Encoders made by @assasinfil & @xMasterX:
|
||||
- Somfy Telis -> How to create new remote - [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||
- Somfy Telis
|
||||
- Somfy Keytis
|
||||
- KingGates Stylo 4k
|
||||
- Alutech AT-4N -> How to create new remote - [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||
- Nice ON2E (Nice One) -> How to create new remote - [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||
- Alutech AT-4N
|
||||
- Nice ON2E (Nice One)
|
||||
|
||||
## Please support development of the project
|
||||
The majority of this project is developed and maintained by me, @xMasterX.
|
||||
I'm unemployed, and the only income I receive is from your donations.
|
||||
I'm unemployed because of the war, and the only income I receive is from your donations.
|
||||
Our team is small and the guys are working on this project as much as they can solely based on the enthusiasm they have for this project and the community.
|
||||
- @Leptopt1los - NFC, RFID, IR Assets (only ACs), Plugins, and many other things
|
||||
- @gid9798 - SubGHz, Plugins, many other things
|
||||
- @assasinfil - SubGHz protocols, NFC parsers
|
||||
- @assasinfil - SubGHz
|
||||
- @Svaarich - UI design and animations
|
||||
- @amec0e - Infrared assets
|
||||
- @Amec0e - Infrared assets
|
||||
- Community moderators in Telegram, Discord, and Reddit
|
||||
- And of course our GitHub community. Your PRs are a very important part of this firmware and open-source development.
|
||||
|
||||
The amount of work done on this project is huge and we need your support, no matter how large or small. Even if you just say, "Thank you Unleashed firmware developers!" somewhere. Doing so will help us continue our work and will help drive us to make the firmware better every time.
|
||||
Also, regarding our releases, every build has and always will be free and open-source. There will be no paywall releases or closed-source apps within the firmware. As long as I am working on this project it will never happen.
|
||||
You can support us by using links or addresses below:
|
||||
|Service|Remark|Link/Wallet|
|
||||
|-|-|-|
|
||||
|**Patreon**||https://patreon.com/mmxdev|
|
||||
|**Boosty**|patreon alternative|https://boosty.to/mmxdev|
|
||||
|cloudtips|only RU payments accepted|https://pay.cloudtips.ru/p/7b3e9d65|
|
||||
|YooMoney|only RU payments accepted|https://yoomoney.ru/fundraise/XA49mgQLPA0.221209|
|
||||
|USDT|(TRC20)|`TSXcitMSnWXUFqiUfEXrTVpVewXy2cYhrs`|
|
||||
|BCH||`qquxfyzntuqufy2dx0hrfr4sndp0tucvky4sw8qyu3`|
|
||||
|ETH|(BSC/ERC20-Tokens)|`darkflippers.eth` (or `0xFebF1bBc8229418FF2408C07AF6Afa49152fEc6a`)|
|
||||
|BTC||`bc1q0np836jk9jwr4dd7p6qv66d04vamtqkxrecck9`|
|
||||
|DOGE||`D6R6gYgBn5LwTNmPyvAQR6bZ9EtGgFCpvv`|
|
||||
|LTC||`ltc1q3ex4ejkl0xpx3znwrmth4lyuadr5qgv8tmq8z9`|
|
||||
|XMR|(Monero)| `41xUz92suUu1u5Mu4qkrcs52gtfpu9rnZRdBpCJ244KRHf6xXSvVFevdf2cnjS7RAeYr5hn9MsEfxKoFDRSctFjG5fv1Mhn`|
|
||||
|TON||`EQCOqcnYkvzOZUV_9bPE_8oTbOrOF03MnF-VcJyjisTZmpGf`|
|
||||
* Boosty: https://boosty.to/mmxdev
|
||||
* Ko-Fi: https://ko-fi.com/masterx
|
||||
* cloudtips (only RU payments accepted): https://pay.cloudtips.ru/p/7b3e9d65
|
||||
* YooMoney (only RU payments accepted): https://yoomoney.ru/fundraise/XA49mgQLPA0.221209
|
||||
* USDT(TRC20): `TSXcitMSnWXUFqiUfEXrTVpVewXy2cYhrs`
|
||||
* BCH: `qquxfyzntuqufy2dx0hrfr4sndp0tucvky4sw8qyu3`
|
||||
* ETH/BSC/ERC20-Tokens: `darkflippers.eth` (or `0xFebF1bBc8229418FF2408C07AF6Afa49152fEc6a`)
|
||||
* BTC: `bc1q0np836jk9jwr4dd7p6qv66d04vamtqkxrecck9`
|
||||
* DOGE: `D6R6gYgBn5LwTNmPyvAQR6bZ9EtGgFCpvv`
|
||||
* LTC: `ltc1q3ex4ejkl0xpx3znwrmth4lyuadr5qgv8tmq8z9`
|
||||
* XMR (Monero): `41xUz92suUu1u5Mu4qkrcs52gtfpu9rnZRdBpCJ244KRHf6xXSvVFevdf2cnjS7RAeYr5hn9MsEfxKoFDRSctFjG5fv1Mhn`
|
||||
* TON: `EQCOqcnYkvzOZUV_9bPE_8oTbOrOF03MnF-VcJyjisTZmpGf`
|
||||
|
||||
## Community apps included
|
||||
### Community apps included:
|
||||
|
||||
### [🎲 Download Extra plugins for Unleashed](https://github.com/xMasterX/all-the-plugins/releases/latest)
|
||||
### [List of Extra pack](https://github.com/xMasterX/all-the-plugins/tree/dev#extra-pack) | [List of Base *(Default)* pack](https://github.com/xMasterX/all-the-plugins/tree/dev#default-pack)
|
||||
- **RFID Fuzzer** [(by Ganapati & @xMasterX)](https://github.com/DarkFlippers/unleashed-firmware/pull/54) & New protocols by @mvanzanten
|
||||
- **Sub-GHz bruteforcer** [(by @derskythe & xMasterX)](https://github.com/derskythe/flipperzero-subbrute) [(original by Ganapati & xMasterX)](https://github.com/DarkFlippers/unleashed-firmware/pull/57)
|
||||
- **Sub-GHz playlist** [(by darmiel)](https://github.com/DarkFlippers/unleashed-firmware/pull/62)
|
||||
- ESP8266 Deauther plugin [(by SequoiaSan)](https://github.com/SequoiaSan/FlipperZero-Wifi-ESP8266-Deauther-Module)
|
||||
- WiFi Scanner plugin [(by SequoiaSan)](https://github.com/SequoiaSan/FlipperZero-WiFi-Scanner_Module)
|
||||
- MultiConverter plugin [(by theisolinearchip)](https://github.com/theisolinearchip/flipperzero_stuff)
|
||||
- USB Keyboard plugin [(by huuck)](https://github.com/huuck/FlipperZeroUSBKeyboard)
|
||||
- WAV Player [(OFW: DrZlo13)](https://github.com/flipperdevices/flipperzero-firmware/tree/zlo/wav-player) - Fixed and improved by [LTVA1](https://github.com/LTVA1/wav_player)
|
||||
- Barcode generator plugin [(original by McAzzaMan)](https://github.com/McAzzaMan/flipperzero-firmware/tree/UPC-A_Barcode_Generator/applications/barcode_generator) - [EAN-8 and refactoring](https://github.com/DarkFlippers/unleashed-firmware/pull/154) by @msvsergey
|
||||
- GPIO: Sentry Safe plugin [(by H4ckd4ddy)](https://github.com/H4ckd4ddy/flipperzero-sentry-safe-plugin)
|
||||
- ESP32: WiFi Marauder companion plugin [(by 0xchocolate)](https://github.com/0xchocolate/flipperzero-firmware-with-wifi-marauder-companion)
|
||||
- NRF24: Sniffer & MouseJacker (with changes) [(by mothball187)](https://github.com/mothball187/flipperzero-nrf24/tree/main/mousejacker)
|
||||
- Simple Clock (timer by GMMan) [(original by CompaqDisc)](https://gist.github.com/CompaqDisc/4e329c501bd03c1e801849b81f48ea61)
|
||||
- **Sub-GHz Remote** (UniversalRF Remix) [(by @darmiel & @xMasterX)](https://github.com/darmiel/flipper-playlist/tree/feat/unirf-protocols) (original by @ESurge)
|
||||
- Spectrum Analyzer (with changes) [(by jolcese)](https://github.com/jolcese/flipperzero-firmware/tree/spectrum/applications/spectrum_analyzer) - [Ultra Narrow mode & scan channels non-consecutively](https://github.com/theY4Kman/flipperzero-firmware/commits?author=theY4Kman)
|
||||
- Metronome [(by panki27)](https://github.com/panki27/Metronome)
|
||||
- DTMF Dolphin [(by litui)](https://github.com/litui/dtmf_dolphin)
|
||||
- **TOTP (Authenticator)** [(by akopachov)](https://github.com/akopachov/flipper-zero_authenticator)
|
||||
- GPS [(by ezod)](https://github.com/ezod/flipperzero-gps) works with module `NMEA 0183` via UART (13TX, 14RX, GND pins on Flipper)
|
||||
- i2c Tools [(by NaejEL)](https://github.com/NaejEL/flipperzero-i2ctools) - C0 -> SCL / C1 -> SDA / GND -> GND | 3v3 logic levels only!
|
||||
- HC-SR04 Distance sensor - Ported and modified by @xMasterX [(original by Sanqui)](https://github.com/Sanqui/flipperzero-firmware/tree/hc_sr04) - How to connect -> (5V -> VCC) / (GND -> GND) / (13|TX -> Trig) / (14|RX -> Echo)
|
||||
- Morse Code [(by wh00hw)](https://github.com/wh00hw/MorseCodeFAP)
|
||||
- **Unitemp - Temperature sensors reader** (DHT11/22, DS18B20, BMP280, HTU21x and more) [(by quen0n)](https://github.com/quen0n/unitemp-flipperzero)
|
||||
- BH1750 - Lightmeter [(by oleksiikutuzov)](https://github.com/oleksiikutuzov/flipperzero-lightmeter)
|
||||
- **iButton Fuzzer** [(by xMasterX)](https://github.com/xMasterX/ibutton-fuzzer)
|
||||
- HEX Viewer [(by QtRoS)](https://github.com/QtRoS/flipper-zero-hex-viewer)
|
||||
- POCSAG Pager [(by xMasterX & Shmuma)](https://github.com/xMasterX/flipper-pager)
|
||||
- Text Viewer [(by kowalski7cc & kyhwana)](https://github.com/kowalski7cc/flipper-zero-text-viewer/tree/refactor-text-app)
|
||||
- **UART Terminal** [(by cool4uma)](https://github.com/cool4uma/UART_Terminal/tree/main)
|
||||
- **ProtoView** [(by antirez)](https://github.com/antirez/protoview)
|
||||
|
||||
See full list and sources here: [xMasterX/all-the-plugins](https://github.com/xMasterX/all-the-plugins/tree/dev)
|
||||
Games:
|
||||
- DOOM (fixed) [(by p4nic4ttack)](https://github.com/p4nic4ttack/doom-flipper-zero/)
|
||||
- Zombiez [(Reworked By DevMilanIan)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/240) [(Original By Dooskington)](https://github.com/Dooskington/flipperzero-zombiez)
|
||||
- Flappy Bird [(by DroomOne)](https://github.com/DroomOne/flipperzero-firmware/tree/dev/applications/flappy_bird)
|
||||
- Arkanoid (refactored by xMasterX) [(by gotnull)](https://github.com/gotnull/flipperzero-firmware-wPlugins)
|
||||
- Tic Tac Toe (refactored by xMasterX) [(by gotnull)](https://github.com/gotnull/flipperzero-firmware-wPlugins)
|
||||
- Tetris (with fixes) [(by jeffplang)](https://github.com/jeffplang/flipperzero-firmware/tree/tetris_game/applications/tetris_game)
|
||||
- Minesweeper [(by panki27)](https://github.com/panki27/minesweeper)
|
||||
- Heap Defence (aka Stack Attack) - Ported to latest firmware by @xMasterX - [(original by wquinoa & Vedmein)](https://github.com/Vedmein/flipperzero-firmware/tree/hd/svisto-perdelki)
|
||||
- Game15 [(by x27)](https://github.com/x27/flipperzero-game15)
|
||||
- Solitaire [(by teeebor)](https://github.com/teeebor/flipper_games)
|
||||
- BlackJack [(by teeebor)](https://github.com/teeebor/flipper_games)
|
||||
- 2048 game [(by eugene-kirzhanov)](https://github.com/eugene-kirzhanov/flipper-zero-2048-game)
|
||||
|
||||
### Official Flipper Zero Apps Catalog [web version](https://lab.flipper.net/apps) or mobile app
|
||||
### Other changes
|
||||
|
||||
- BadUSB -> Keyboard layouts [(by rien > dummy-decoy)](https://github.com/dummy-decoy/flipperzero-firmware/tree/dummy_decoy/bad_usb_keyboard_layout)
|
||||
- Sub-GHz -> External CC1101 module support - [(by quen0n)](https://github.com/DarkFlippers/unleashed-firmware/pull/307)
|
||||
- Sub-GHz -> New frequency analyzer - [(by ClusterM)](https://github.com/DarkFlippers/unleashed-firmware/pull/43)
|
||||
- Sub-GHz -> Save last used frequency [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77)
|
||||
- Sub-GHz -> Press OK in frequency analyzer to use detected frequency in Read modes [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77)
|
||||
- Sub-GHz -> Long press OK button in Sub-GHz Frequency analyzer to switch to Read menu [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/79)
|
||||
- Lock device with pin(or regular lock if pin not set) by holding UP button on main screen [(by an4tur0r)](https://github.com/DarkFlippers/unleashed-firmware/pull/107)
|
||||
|
||||
# Instructions
|
||||
## First look at official docs [docs.flipper.net](https://docs.flipper.net/)
|
||||
## [How to install](/documentation/HowToInstall.md) - [versions info](/CHANGELOG.md#recommended-update-option---web-updater): `n`,` `,`e`...
|
||||
## Firmware & Development
|
||||
## [- How to install firmware](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)
|
||||
|
||||
### - **[How to build](/documentation/HowToBuild.md#how-to-build-by-yourself) | [Project-structure](#project-structure)**
|
||||
## [- How to build firmware](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToBuild.md)
|
||||
|
||||
### - **CLion IDE** - How to setup workspace for flipper firmware development [by Savely Krasovsky](https://krasovs.ky/2022/11/01/flipper-zero-clion.html)
|
||||
## [- How to connect external CC1101 module](https://github.com/quen0n/flipperzero-ext-cc1101)
|
||||
|
||||
### - **"Hello world!"** - plugin tutorial [English<sub> by DroomOne</sub> ](https://github.com/DroomOne/Flipper-Plugin-Tutorial) | [Russian<sub> by Pavel Yakovlev</sub>](https://yakovlev.me/hello-flipper-zero/)
|
||||
## [- BadUSB: how to add new keyboard layouts](https://github.com/dummy-decoy/flipperzero_badusb_kl)
|
||||
|
||||
### - [How to write your own app](https://flipper.atmanos.com/docs/overview/intro). Docs by atmanos **⚠️outdated API**
|
||||
## [- How to change Flipper name](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/CustomFlipperName.md)
|
||||
|
||||
## Firmware & main Apps feature
|
||||
### **Plugins**
|
||||
|
||||
### - System: [How to change Flipper name](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/CustomFlipperName.md)
|
||||
## [- 🎲 Download Extra plugins for Unleashed](https://github.com/xMasterX/unleashed-extra-pack)
|
||||
|
||||
### - BadUSB: [How to add new keyboard layouts](https://github.com/dummy-decoy/flipperzero_badusb_kl)
|
||||
## [- Configure Sub-GHz Remote App](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemotePlugin.md)
|
||||
|
||||
### - Infrared: [How to make captures to add them into Universal IR remotes](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/InfraredCaptures.md)
|
||||
## [- TOTP (Authenticator) config description](https://github.com/akopachov/flipper-zero_authenticator/blob/master/docs/conf-file_description.md)
|
||||
|
||||
## **Sub-GHz**
|
||||
## [- Barcode Generator](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/BarcodeGenerator.md)
|
||||
|
||||
### - [How to use Flipper as new remote (Nice FlorS, BFT Mitto, Somfy Telis, Aprimatic, AN-Motors, etc..)](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||
## [- Multi Converter](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/MultiConverter.md)
|
||||
|
||||
### - External Radio: [How to connect CC1101 module](https://github.com/quen0n/flipperzero-ext-cc1101)
|
||||
## [- WAV Player sample files & how to convert](https://github.com/UberGuidoZ/Flipper/tree/main/Wav_Player#readme)
|
||||
|
||||
### - Transmission is blocked? [How to extend Sub-GHz frequency range](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/DangerousSettings.md)
|
||||
## [- Sub-GHz playlist generator script](https://github.com/darmiel/flipper-scripts/blob/main/playlist/playlist_creator_by_chunk.py)
|
||||
|
||||
### - [How to add extra Sub-GHz frequencies](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzSettings.md)
|
||||
### **Plugins that works with external hardware**
|
||||
|
||||
### - [~~Configure Sub-GHz Remote App~~](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemotePlugin.md) Not recommended, please use embedded configurator
|
||||
## [- How to use: Unitemp - Temperature sensors reader](https://github.com/quen0n/unitemp-flipperzero#readme)
|
||||
|
||||
## **Plugins**
|
||||
## [- How to use: [NMEA] GPS](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/applications/plugins/gps_nmea_uart/README.md)
|
||||
|
||||
### - TOTP (Authenticator): [config description](https://github.com/akopachov/flipper-zero_authenticator/blob/master/docs/conf-file_description.md)
|
||||
## [- How to use: i2c Tools](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/applications/plugins/flipper_i2ctools/README.md)
|
||||
|
||||
### - Barcode Generator: [How to use](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/BarcodeGenerator.md)
|
||||
## [- How to use: [NRF24] plugins](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/NRF24.md)
|
||||
|
||||
### - Multi Converter: [How to use](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/MultiConverter.md)
|
||||
## [- How to use: [WiFi] Scanner](https://github.com/SequoiaSan/FlipperZero-WiFi-Scanner_Module#readme)
|
||||
|
||||
### - WAV Player: [sample files & how to convert](https://github.com/UberGuidoZ/Flipper/tree/main/Wav_Player#readme)
|
||||
## [- How to use: [ESP8266] Deauther](https://github.com/SequoiaSan/FlipperZero-Wifi-ESP8266-Deauther-Module#readme)
|
||||
|
||||
### - Sub-GHz playlist: [generator script](https://github.com/darmiel/flipper-scripts/blob/main/playlist/playlist_creator_by_chunk.py)
|
||||
## [- How to use: [ESP32] WiFi Marauder](https://github.com/UberGuidoZ/Flipper/tree/main/Wifi_DevBoard)
|
||||
|
||||
## **Plugins that works with external hardware** [GPIO]
|
||||
## [- [WiFi] Scanner - Web Flasher for module firmware](https://sequoiasan.github.io/FlipperZero-WiFi-Scanner_Module/)
|
||||
|
||||
### - Unitemp - Temperature sensors reader: [How to use & supported sensors](https://github.com/quen0n/unitemp-flipperzero#readme)
|
||||
## [- [ESP8266] Deauther - Web Flasher for module firmware](https://sequoiasan.github.io/FlipperZero-Wifi-ESP8266-Deauther-Module/)
|
||||
|
||||
### - [NMEA] GPS: [How to use](https://github.com/xMasterX/all-the-plugins/blob/dev/base_pack/gps_nmea_uart/README.md)
|
||||
## [- Windows: How to Upload .bin to ESP32/ESP8266](https://github.com/SequoiaSan/Guide-How-To-Upload-bin-to-ESP8266-ESP32)
|
||||
|
||||
### - i2c Tools [How to use](https://github.com/xMasterX/all-the-plugins/blob/dev/base_pack/flipper_i2ctools/README.md)
|
||||
## [- How to use: [GPIO] SentrySafe plugin](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SentrySafe.md)
|
||||
|
||||
### - [NRF24] plugins: [How to use](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/NRF24.md)
|
||||
### **Sub-GHz**
|
||||
|
||||
## [- Transmission is blocked? - How to extend Sub-GHz frequency range](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/DangerousSettings.md)
|
||||
|
||||
### - [WiFi] Scanner: [How to use](https://github.com/SequoiaSan/FlipperZero-WiFi-Scanner_Module#readme) | [Web Flasher](https://sequoiasan.github.io/FlipperZero-WiFi-Scanner_Module/)
|
||||
|
||||
### - [ESP8266] Deauther: [How to use](https://github.com/SequoiaSan/FlipperZero-Wifi-ESP8266-Deauther-Module#readme) | [Web Flasher](https://sequoiasan.github.io/FlipperZero-Wifi-ESP8266-Deauther-Module/)
|
||||
|
||||
### - [ESP32] WiFi Marauder: [How to use](https://github.com/UberGuidoZ/Flipper/tree/main/Wifi_DevBoard)<sub> docs by UberGuidoZ</sub> | [Marauder repo](https://github.com/justcallmekoko/ESP32Marauder)
|
||||
|
||||
### - [ESP32-CAM] Camera Suite: [How to use](https://github.com/CodyTolene/Flipper-Zero-Camera-Suite)
|
||||
|
||||
### - How to Upload `.bin` to ESP32/ESP8266: [Windows](https://github.com/SequoiaSan/Guide-How-To-Upload-bin-to-ESP8266-ESP32) | [FAP "ESP flasher"](https://github.com/0xchocolate/flipperzero-esp-flasher)
|
||||
|
||||
### - [GPIO] SentrySafe plugin: [How to use](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SentrySafe.md)
|
||||
## [- How to add extra Sub-GHz frequencies](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzSettings.md)
|
||||
|
||||
<br>
|
||||
<br>
|
||||
@@ -237,13 +230,18 @@ See full list and sources here: [xMasterX/all-the-plugins](https://github.com/xM
|
||||
# Where I can find IR, Sub-GHz, ... files, DBs, and other stuff?
|
||||
## [UberGuidoZ Playground - Large collection of files - Github](https://github.com/UberGuidoZ/Flipper)
|
||||
## [Awesome Flipper Zero - Github](https://github.com/djsime1/awesome-flipperzero)
|
||||
## [CAME-12bit, NICE-12bit, Linear-10bit, PT-2240 - Sub-GHz fixed code bruteforce](https://github.com/tobiabocchi/flipperzero-bruteforce)
|
||||
## [SMC5326, UNILARM - Sub-GHz fixed code bruteforce](https://github.com/Hong5489/flipperzero-gate-bruteforce)
|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
||||
# Links
|
||||
|
||||
* Official Docs: [docs.flipper.net](https://docs.flipper.net/)
|
||||
* Unofficial Discord: [discord.unleashedflip.com](https://discord.unleashedflip.com)
|
||||
* Docs by atmanos / How to write your own app (outdated API): [https://flipper.atmanos.com/docs/overview/intro](https://flipper.atmanos.com/docs/overview/intro)
|
||||
|
||||
* Official Docs: [http://docs.flipperzero.one](http://docs.flipperzero.one)
|
||||
* Official Forum: [forum.flipperzero.one](https://forum.flipperzero.one/)
|
||||
|
||||
# Project structure
|
||||
|
||||
195
SConstruct
195
SConstruct
@@ -7,7 +7,7 @@
|
||||
# construction of certain targets behind command-line options.
|
||||
|
||||
import os
|
||||
from fbt.util import open_browser_action
|
||||
from fbt.util import path_as_posix
|
||||
|
||||
DefaultEnvironment(tools=[])
|
||||
|
||||
@@ -45,7 +45,6 @@ distenv = coreenv.Clone(
|
||||
],
|
||||
ENV=os.environ,
|
||||
UPDATE_BUNDLE_DIR="dist/${DIST_DIR}/f${TARGET_HW}-update-${DIST_SUFFIX}",
|
||||
VSCODE_LANG_SERVER=ARGUMENTS.get("LANG_SERVER", "cpptools"),
|
||||
)
|
||||
|
||||
firmware_env = distenv.AddFwProject(
|
||||
@@ -66,24 +65,21 @@ if GetOption("fullenv") or any(
|
||||
|
||||
# Target for self-update package
|
||||
dist_basic_arguments = [
|
||||
"${ARGS}",
|
||||
"--bundlever",
|
||||
"${UPDATE_VERSION_STRING}",
|
||||
'"${UPDATE_VERSION_STRING}"',
|
||||
]
|
||||
dist_radio_arguments = [
|
||||
"--radio",
|
||||
"${ROOT_DIR.abspath}/${COPRO_STACK_BIN_DIR}/${COPRO_STACK_BIN}",
|
||||
'"${ROOT_DIR.abspath}/${COPRO_STACK_BIN_DIR}/${COPRO_STACK_BIN}"',
|
||||
"--radiotype",
|
||||
"${COPRO_STACK_TYPE}",
|
||||
"${COPRO_DISCLAIMER}",
|
||||
"--obdata",
|
||||
"${ROOT_DIR.abspath}/${COPRO_OB_DATA}",
|
||||
"--stackversion",
|
||||
"${COPRO_CUBE_VERSION}",
|
||||
'"${ROOT_DIR.abspath}/${COPRO_OB_DATA}"',
|
||||
]
|
||||
dist_resource_arguments = [
|
||||
"-r",
|
||||
firmware_env.subst("${RESOURCES_ROOT}"),
|
||||
'"${ROOT_DIR.abspath}/assets/resources"',
|
||||
]
|
||||
dist_splash_arguments = (
|
||||
[
|
||||
@@ -96,7 +92,7 @@ if GetOption("fullenv") or any(
|
||||
|
||||
selfupdate_dist = distenv.DistCommand(
|
||||
"updater_package",
|
||||
(distenv["DIST_DEPENDS"], firmware_env["FW_RESOURCES_MANIFEST"]),
|
||||
(distenv["DIST_DEPENDS"], firmware_env["FW_RESOURCES"]),
|
||||
DIST_EXTRA=[
|
||||
*dist_basic_arguments,
|
||||
*dist_radio_arguments,
|
||||
@@ -129,8 +125,7 @@ if GetOption("fullenv") or any(
|
||||
|
||||
# Installation over USB & CLI
|
||||
usb_update_package = distenv.AddUsbFlashTarget(
|
||||
"#build/usbinstall.flag",
|
||||
(firmware_env["FW_RESOURCES_MANIFEST"], selfupdate_dist),
|
||||
"#build/usbinstall.flag", (firmware_env["FW_RESOURCES"], selfupdate_dist)
|
||||
)
|
||||
distenv.Alias("flash_usb_full", usb_update_package)
|
||||
|
||||
@@ -144,52 +139,42 @@ if GetOption("fullenv") or any(
|
||||
basic_dist = distenv.DistCommand("fw_dist", distenv["DIST_DEPENDS"])
|
||||
distenv.Default(basic_dist)
|
||||
|
||||
dist_dir_name = distenv.GetProjectDirName()
|
||||
dist_dir = distenv.Dir(f"#/dist/{dist_dir_name}")
|
||||
external_apps_artifacts = firmware_env["FW_EXTAPPS"]
|
||||
external_app_list = external_apps_artifacts.application_map.values()
|
||||
|
||||
dist_dir = distenv.GetProjetDirName()
|
||||
fap_dist = [
|
||||
distenv.Install(
|
||||
dist_dir.Dir("debug_elf"),
|
||||
list(app_artifact.debug for app_artifact in external_app_list),
|
||||
distenv.Dir(f"#/dist/{dist_dir}/apps/debug_elf"),
|
||||
list(
|
||||
app_artifact.debug
|
||||
for app_artifact in firmware_env["FW_EXTAPPS"].applications.values()
|
||||
),
|
||||
),
|
||||
*(
|
||||
distenv.Install(
|
||||
dist_dir.File(dist_entry[1]).dir,
|
||||
app_artifact.compact,
|
||||
f"#/dist/{dist_dir}/apps/{app_artifact.app.fap_category}",
|
||||
app_artifact.compact[0],
|
||||
)
|
||||
for app_artifact in external_app_list
|
||||
for dist_entry in app_artifact.dist_entries
|
||||
for app_artifact in firmware_env["FW_EXTAPPS"].applications.values()
|
||||
),
|
||||
]
|
||||
Depends(
|
||||
fap_dist,
|
||||
list(app_artifact.validator for app_artifact in external_app_list),
|
||||
list(
|
||||
app_artifact.validator
|
||||
for app_artifact in firmware_env["FW_EXTAPPS"].applications.values()
|
||||
),
|
||||
)
|
||||
Alias("fap_dist", fap_dist)
|
||||
# distenv.Default(fap_dist)
|
||||
|
||||
distenv.Depends(firmware_env["FW_RESOURCES"], firmware_env["FW_EXTAPPS"].resources_dist)
|
||||
|
||||
# Copy all faps to device
|
||||
|
||||
fap_deploy = distenv.PhonyTarget(
|
||||
"fap_deploy",
|
||||
Action(
|
||||
[
|
||||
[
|
||||
"${PYTHON3}",
|
||||
"${FBT_SCRIPT_DIR}/storage.py",
|
||||
"-p",
|
||||
"${FLIP_PORT}",
|
||||
"send",
|
||||
"${SOURCE}",
|
||||
"/ext/apps",
|
||||
"${ARGS}",
|
||||
]
|
||||
]
|
||||
),
|
||||
source=firmware_env.Dir(("${RESOURCES_ROOT}/apps")),
|
||||
"${PYTHON3} ${ROOT_DIR}/scripts/storage.py send ${SOURCE} /ext/apps",
|
||||
source=Dir("#/assets/resources/apps"),
|
||||
)
|
||||
Depends(fap_deploy, firmware_env["FW_RESOURCES_MANIFEST"])
|
||||
|
||||
|
||||
# Target for bundling core2 package for qFlipper
|
||||
@@ -200,17 +185,29 @@ copro_dist = distenv.CoproBuilder(
|
||||
distenv.AlwaysBuild(copro_dist)
|
||||
distenv.Alias("copro_dist", copro_dist)
|
||||
|
||||
|
||||
firmware_flash = distenv.AddFwFlashTarget(firmware_env)
|
||||
firmware_flash = distenv.AddOpenOCDFlashTarget(firmware_env)
|
||||
distenv.Alias("flash", firmware_flash)
|
||||
|
||||
# To be implemented in fwflash.py
|
||||
firmware_jflash = distenv.AddJFlashTarget(firmware_env)
|
||||
distenv.Alias("jflash", firmware_jflash)
|
||||
|
||||
distenv.PhonyTarget(
|
||||
firmware_bm_flash = distenv.PhonyTarget(
|
||||
"flash_blackmagic",
|
||||
"$GDB $GDBOPTS $SOURCES $GDBFLASH",
|
||||
source=firmware_env["FW_ELF"],
|
||||
GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}",
|
||||
GDBREMOTE="${BLACKMAGIC_ADDR}",
|
||||
GDBFLASH=[
|
||||
"-ex",
|
||||
"load",
|
||||
"-ex",
|
||||
"quit",
|
||||
],
|
||||
)
|
||||
|
||||
gdb_backtrace_all_threads = distenv.PhonyTarget(
|
||||
"gdb_trace_all",
|
||||
[["${GDB}", "${GDBOPTS}", "${SOURCES}", "${GDBFLASH}"]],
|
||||
"$GDB $GDBOPTS $SOURCES $GDBFLASH",
|
||||
source=firmware_env["FW_ELF"],
|
||||
GDBOPTS="${GDBOPTS_BASE}",
|
||||
GDBREMOTE="${OPENOCD_GDB_PIPE}",
|
||||
@@ -229,6 +226,7 @@ firmware_debug = distenv.PhonyTarget(
|
||||
source=firmware_env["FW_ELF"],
|
||||
GDBOPTS="${GDBOPTS_BASE}",
|
||||
GDBREMOTE="${OPENOCD_GDB_PIPE}",
|
||||
FBT_FAP_DEBUG_ELF_ROOT=path_as_posix(firmware_env.subst("$FBT_FAP_DEBUG_ELF_ROOT")),
|
||||
)
|
||||
distenv.Depends(firmware_debug, firmware_flash)
|
||||
|
||||
@@ -238,83 +236,52 @@ distenv.PhonyTarget(
|
||||
source=firmware_env["FW_ELF"],
|
||||
GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}",
|
||||
GDBREMOTE="${BLACKMAGIC_ADDR}",
|
||||
FBT_FAP_DEBUG_ELF_ROOT=path_as_posix(firmware_env.subst("$FBT_FAP_DEBUG_ELF_ROOT")),
|
||||
)
|
||||
|
||||
# Debug alien elf
|
||||
debug_other_opts = [
|
||||
"-ex",
|
||||
"source ${FBT_DEBUG_DIR}/PyCortexMDebug/PyCortexMDebug.py",
|
||||
# "-ex",
|
||||
# "source ${FBT_DEBUG_DIR}/FreeRTOS/FreeRTOS.py",
|
||||
"-ex",
|
||||
"source ${FBT_DEBUG_DIR}/flipperversion.py",
|
||||
"-ex",
|
||||
"fw-version",
|
||||
]
|
||||
|
||||
distenv.PhonyTarget(
|
||||
"debug_other",
|
||||
"${GDBPYCOM}",
|
||||
GDBOPTS="${GDBOPTS_BASE}",
|
||||
GDBREMOTE="${OPENOCD_GDB_PIPE}",
|
||||
GDBPYOPTS=debug_other_opts,
|
||||
GDBPYOPTS='-ex "source ${FBT_DEBUG_DIR}/PyCortexMDebug/PyCortexMDebug.py" ',
|
||||
)
|
||||
|
||||
distenv.PhonyTarget(
|
||||
"debug_other_blackmagic",
|
||||
"${GDBPYCOM}",
|
||||
GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}",
|
||||
GDBREMOTE="${BLACKMAGIC_ADDR}",
|
||||
GDBPYOPTS=debug_other_opts,
|
||||
GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}",
|
||||
GDBREMOTE="$${BLACKMAGIC_ADDR}",
|
||||
)
|
||||
|
||||
|
||||
# Just start OpenOCD
|
||||
distenv.PhonyTarget(
|
||||
"openocd",
|
||||
[["${OPENOCDCOM}", "${ARGS}"]],
|
||||
"${OPENOCDCOM}",
|
||||
)
|
||||
|
||||
# Linter
|
||||
distenv.PhonyTarget(
|
||||
"lint",
|
||||
[
|
||||
[
|
||||
"${PYTHON3}",
|
||||
"${FBT_SCRIPT_DIR}/lint.py",
|
||||
"check",
|
||||
"${LINT_SOURCES}",
|
||||
"${ARGS}",
|
||||
]
|
||||
],
|
||||
"${PYTHON3} ${FBT_SCRIPT_DIR}/lint.py check ${LINT_SOURCES}",
|
||||
LINT_SOURCES=[n.srcnode() for n in firmware_env["LINT_SOURCES"]],
|
||||
)
|
||||
|
||||
distenv.PhonyTarget(
|
||||
"format",
|
||||
[
|
||||
[
|
||||
"${PYTHON3}",
|
||||
"${FBT_SCRIPT_DIR}/lint.py",
|
||||
"format",
|
||||
"${LINT_SOURCES}",
|
||||
"${ARGS}",
|
||||
]
|
||||
],
|
||||
"${PYTHON3} ${FBT_SCRIPT_DIR}/lint.py format ${LINT_SOURCES}",
|
||||
LINT_SOURCES=[n.srcnode() for n in firmware_env["LINT_SOURCES"]],
|
||||
)
|
||||
|
||||
# PY_LINT_SOURCES contains recursively-built modules' SConscript files
|
||||
# PY_LINT_SOURCES contains recursively-built modules' SConscript files + application manifests
|
||||
# Here we add additional Python files residing in repo root
|
||||
firmware_env.Append(
|
||||
PY_LINT_SOURCES=[
|
||||
# Py code folders
|
||||
"site_scons",
|
||||
"scripts",
|
||||
"applications",
|
||||
"applications_user",
|
||||
"assets",
|
||||
"targets",
|
||||
# Extra files
|
||||
"SConstruct",
|
||||
"firmware.scons",
|
||||
@@ -323,20 +290,8 @@ firmware_env.Append(
|
||||
)
|
||||
|
||||
|
||||
black_commandline = [
|
||||
[
|
||||
"@${PYTHON3}",
|
||||
"-m",
|
||||
"black",
|
||||
"${PY_BLACK_ARGS}",
|
||||
"${PY_LINT_SOURCES}",
|
||||
"${ARGS}",
|
||||
]
|
||||
]
|
||||
black_base_args = [
|
||||
"--include",
|
||||
'"(\\.scons|\\.py|SConscript|SConstruct|\\.fam)$"',
|
||||
]
|
||||
black_commandline = "@${PYTHON3} -m black ${PY_BLACK_ARGS} ${PY_LINT_SOURCES}"
|
||||
black_base_args = ["--include", '"\\.scons|\\.py|SConscript|SConstruct"']
|
||||
|
||||
distenv.PhonyTarget(
|
||||
"lint_py",
|
||||
@@ -357,30 +312,7 @@ distenv.PhonyTarget(
|
||||
)
|
||||
|
||||
# Start Flipper CLI via PySerial's miniterm
|
||||
distenv.PhonyTarget(
|
||||
"cli",
|
||||
[
|
||||
[
|
||||
"${PYTHON3}",
|
||||
"${FBT_SCRIPT_DIR}/serial_cli.py",
|
||||
"-p",
|
||||
"${FLIP_PORT}",
|
||||
"${ARGS}",
|
||||
]
|
||||
],
|
||||
)
|
||||
|
||||
# Update WiFi devboard firmware with release channel
|
||||
distenv.PhonyTarget(
|
||||
"devboard_flash",
|
||||
[
|
||||
[
|
||||
"${PYTHON3}",
|
||||
"${FBT_SCRIPT_DIR}/wifi_board.py",
|
||||
"${ARGS}",
|
||||
]
|
||||
],
|
||||
)
|
||||
distenv.PhonyTarget("cli", "${PYTHON3} ${FBT_SCRIPT_DIR}/serial_cli.py")
|
||||
|
||||
|
||||
# Find blackmagic probe
|
||||
@@ -394,26 +326,13 @@ distenv.PhonyTarget(
|
||||
distenv.PhonyTarget(
|
||||
"get_stlink",
|
||||
distenv.Action(
|
||||
lambda **_: distenv.GetDevices(),
|
||||
lambda **kw: distenv.GetDevices(),
|
||||
None,
|
||||
),
|
||||
)
|
||||
|
||||
# Prepare vscode environment
|
||||
VSCODE_LANG_SERVER = cmd_environment["LANG_SERVER"]
|
||||
vscode_dist = distenv.Install(
|
||||
"#.vscode",
|
||||
[
|
||||
distenv.Glob("#.vscode/example/*.json"),
|
||||
distenv.Glob(f"#.vscode/example/{VSCODE_LANG_SERVER}/*.json"),
|
||||
],
|
||||
)
|
||||
vscode_dist = distenv.Install("#.vscode", distenv.Glob("#.vscode/example/*"))
|
||||
distenv.Precious(vscode_dist)
|
||||
distenv.NoClean(vscode_dist)
|
||||
distenv.Alias("vscode_dist", (vscode_dist, firmware_env["FW_CDB"]))
|
||||
|
||||
# Configure shell with build tools
|
||||
distenv.PhonyTarget(
|
||||
"env",
|
||||
"@echo $( ${FBT_SCRIPT_DIR.abspath}/toolchain/fbtenv.sh $)",
|
||||
)
|
||||
distenv.Alias("vscode_dist", vscode_dist)
|
||||
|
||||
@@ -26,6 +26,7 @@ Applications for main Flipper menu.
|
||||
|
||||
- `archive` - Archive and file manager
|
||||
- `bad_usb` - Bad USB application
|
||||
- `fap_loader` - External applications loader
|
||||
- `gpio` - GPIO application: includes USART bridge and GPIO control
|
||||
- `ibutton` - iButton application, onewire keys and more
|
||||
- `infrared` - Infrared application, controls your IR devices
|
||||
@@ -35,11 +36,22 @@ Applications for main Flipper menu.
|
||||
- `u2f` - U2F Application
|
||||
|
||||
|
||||
## plugins
|
||||
|
||||
Extra apps for Plugins & App Loader menus.
|
||||
|
||||
- `bt_hid_app` - BT Remote controller
|
||||
- `music_player` - Music player app (demo)
|
||||
- `picopass` - Picopass tool
|
||||
- `snake_game` - Snake game application
|
||||
|
||||
|
||||
## services
|
||||
|
||||
Background services providing system APIs to applications.
|
||||
|
||||
- `applications.h` - Firmware application list header
|
||||
|
||||
- `bt` - BLE service and application
|
||||
- `cli` - Console service and API
|
||||
- `crypto` - Crypto cli tools
|
||||
@@ -71,10 +83,7 @@ Small applications providing configuration for basic firmware and its services.
|
||||
|
||||
## system
|
||||
|
||||
Utility apps not visible in other menus, plus few external apps pre-packaged with the firmware.
|
||||
Utility apps not visible in other menus.
|
||||
|
||||
- `hid_app` - BLE & USB HID remote
|
||||
- `js_app` - JS engine runner
|
||||
- `snake_game` - Snake game
|
||||
- `storage_move_to_sd` - Data migration tool for internal storage
|
||||
- `updater` - Update service & application
|
||||
|
||||
@@ -34,7 +34,7 @@ void AccessorApp::run(void) {
|
||||
AccessorApp::AccessorApp()
|
||||
: text_store{0} {
|
||||
notification = static_cast<NotificationApp*>(furi_record_open(RECORD_NOTIFICATION));
|
||||
onewire_host = onewire_host_alloc(&gpio_ibutton);
|
||||
onewire_host = onewire_host_alloc(&ibutton_gpio);
|
||||
furi_hal_power_enable_otg();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "accessor_view_manager.h"
|
||||
#include "accessor_event.h"
|
||||
#include "callback_connector.h"
|
||||
#include <callback-connector.h>
|
||||
|
||||
AccessorAppViewManager::AccessorAppViewManager() {
|
||||
event_queue = furi_message_queue_alloc(10, sizeof(AccessorEvent));
|
||||
|
||||
@@ -4,6 +4,7 @@ App(
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
targets=["f7"],
|
||||
entry_point="accessor_app",
|
||||
cdefines=["APP_ACCESSOR"],
|
||||
requires=["gui"],
|
||||
stack_size=4 * 1024,
|
||||
order=40,
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
#ifndef CALLBACKCONNECTOR_H
|
||||
#define CALLBACKCONNECTOR_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <functional>
|
||||
namespace cbc {
|
||||
namespace Details {
|
||||
|
||||
template <std::size_t Tag, typename T, typename Ret, typename... Args>
|
||||
class FuncMemberWrapper {
|
||||
public:
|
||||
FuncMemberWrapper() = delete;
|
||||
using member_fun_t = Ret (T::*)(Args...);
|
||||
using const_member_fun_t = Ret (T::*)(Args...) const;
|
||||
static auto instantiate(T* t, member_fun_t ptr) {
|
||||
obj = t;
|
||||
member = ptr;
|
||||
return MetaCall;
|
||||
}
|
||||
|
||||
static auto instantiate(T* t, const_member_fun_t ptr) {
|
||||
obj = t;
|
||||
const_member = ptr;
|
||||
return ConstMetaCall;
|
||||
}
|
||||
|
||||
private:
|
||||
static auto MetaCall(Args... args) {
|
||||
return (*obj.*member)(args...);
|
||||
}
|
||||
static auto ConstMetaCall(Args... args) {
|
||||
return (*obj.*const_member)(args...);
|
||||
}
|
||||
static T* obj;
|
||||
static member_fun_t member;
|
||||
static const_member_fun_t const_member;
|
||||
};
|
||||
template <std::size_t Tag, typename T, typename Ret, typename... Args>
|
||||
T* FuncMemberWrapper<Tag, T, Ret, Args...>::obj{};
|
||||
|
||||
template <std::size_t Tag, typename T, typename Ret, typename... Args>
|
||||
typename FuncMemberWrapper<Tag, T, Ret, Args...>::member_fun_t
|
||||
FuncMemberWrapper<Tag, T, Ret, Args...>::member{};
|
||||
|
||||
template <std::size_t Tag, typename T, typename Ret, typename... Args>
|
||||
typename FuncMemberWrapper<Tag, T, Ret, Args...>::const_member_fun_t
|
||||
FuncMemberWrapper<Tag, T, Ret, Args...>::const_member{};
|
||||
|
||||
template <typename Functor, typename Ret, typename... Args>
|
||||
struct FunctorWrapper {
|
||||
public:
|
||||
static std::function<Ret(Args...)> functor;
|
||||
static auto instatiate(Functor fn) {
|
||||
functor = std::move(fn);
|
||||
return MetaCall;
|
||||
}
|
||||
|
||||
private:
|
||||
static auto MetaCall(Args... args) {
|
||||
return functor(args...);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Functor, typename Ret, typename... Args>
|
||||
std::function<Ret(Args...)> FunctorWrapper<Functor, Ret, Args...>::functor;
|
||||
|
||||
template <typename Functor, typename Ret, typename T, typename... Args>
|
||||
auto deducer(Functor obj, Ret (T::*)(Args...) const) {
|
||||
return FunctorWrapper<Functor, Ret, Args...>::instatiate(std::move(obj));
|
||||
}
|
||||
|
||||
template <typename Functor, typename Ret, typename T, typename... Args>
|
||||
auto deducer(Functor obj, Ret (T::*)(Args...)) {
|
||||
return FunctorWrapper<Functor, Ret, Args...>::instatiate(std::move(obj));
|
||||
}
|
||||
|
||||
template <std::size_t tag, typename T, typename Ret, typename... Args>
|
||||
auto const_instantiate(T* t, Ret (T::*ptr)(Args...) const) {
|
||||
return FuncMemberWrapper<tag, T, Ret, Args...>::instantiate(t, ptr);
|
||||
}
|
||||
|
||||
template <std::size_t tag, typename T, typename Func>
|
||||
auto const_instantiate(T* t, Func ptr) {
|
||||
return const_instantiate(t, ptr);
|
||||
}
|
||||
|
||||
} //end of Details scope
|
||||
|
||||
template <std::size_t tag = 0, typename T, typename Ret, typename... Args>
|
||||
auto obtain_connector(T* t, Ret (T::*ptr)(Args...)) {
|
||||
return Details::FuncMemberWrapper<tag, T, Ret, Args...>::instantiate(t, ptr);
|
||||
}
|
||||
|
||||
template <std::size_t tag = 0, typename T, typename Ret, typename... Args>
|
||||
auto obtain_connector(T* t, Ret (T::*ptr)(Args...) const) {
|
||||
return Details::FuncMemberWrapper<tag, T, Ret, Args...>::instantiate(t, ptr);
|
||||
}
|
||||
|
||||
template <typename Functor>
|
||||
auto obtain_connector(Functor functor) {
|
||||
return Details::deducer(std::move(functor), &Functor::operator());
|
||||
}
|
||||
} //end of cbc scope
|
||||
|
||||
#endif // __cplusplus
|
||||
#endif // CALLBACKCONNECTOR_H
|
||||
@@ -2,12 +2,12 @@
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
unsigned long WIEGAND::_cardTempHigh = 0;
|
||||
unsigned long WIEGAND::_cardTemp = 0;
|
||||
unsigned long WIEGAND::_lastWiegand = 0;
|
||||
volatile unsigned long WIEGAND::_cardTempHigh = 0;
|
||||
volatile unsigned long WIEGAND::_cardTemp = 0;
|
||||
volatile unsigned long WIEGAND::_lastWiegand = 0;
|
||||
unsigned long WIEGAND::_code = 0;
|
||||
unsigned long WIEGAND::_codeHigh = 0;
|
||||
int WIEGAND::_bitCount = 0;
|
||||
volatile int WIEGAND::_bitCount = 0;
|
||||
int WIEGAND::_wiegandType = 0;
|
||||
|
||||
constexpr uint32_t clocks_in_ms = 64 * 1000;
|
||||
@@ -98,7 +98,10 @@ void WIEGAND::ReadD1() {
|
||||
_lastWiegand = DWT->CYCCNT; // Keep track of last wiegand bit received
|
||||
}
|
||||
|
||||
unsigned long WIEGAND::GetCardId(unsigned long* codehigh, unsigned long* codelow, char bitlength) {
|
||||
unsigned long WIEGAND::GetCardId(
|
||||
volatile unsigned long* codehigh,
|
||||
volatile unsigned long* codelow,
|
||||
char bitlength) {
|
||||
if(bitlength == 26) // EM tag
|
||||
return (*codelow & 0x1FFFFFE) >> 1;
|
||||
|
||||
@@ -171,7 +174,7 @@ bool WIEGAND::DoWiegandConversion() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO FL-3490: Handle validation failure case!
|
||||
// TODO: Handle validation failure case!
|
||||
} else if(4 == _bitCount) {
|
||||
// 4-bit Wiegand codes have no data integrity check so we just
|
||||
// read the LOW nibble.
|
||||
|
||||
@@ -15,13 +15,15 @@ public:
|
||||
|
||||
private:
|
||||
static bool DoWiegandConversion();
|
||||
static unsigned long
|
||||
GetCardId(unsigned long* codehigh, unsigned long* codelow, char bitlength);
|
||||
static unsigned long GetCardId(
|
||||
volatile unsigned long* codehigh,
|
||||
volatile unsigned long* codelow,
|
||||
char bitlength);
|
||||
|
||||
static unsigned long _cardTempHigh;
|
||||
static unsigned long _cardTemp;
|
||||
static unsigned long _lastWiegand;
|
||||
static int _bitCount;
|
||||
static volatile unsigned long _cardTempHigh;
|
||||
static volatile unsigned long _cardTemp;
|
||||
static volatile unsigned long _lastWiegand;
|
||||
static volatile int _bitCount;
|
||||
static int _wiegandType;
|
||||
static unsigned long _code;
|
||||
static unsigned long _codeHigh;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "../accessor_app.h"
|
||||
#include "../accessor_view_manager.h"
|
||||
#include "../accessor_event.h"
|
||||
#include "callback_connector.h"
|
||||
#include <callback-connector.h>
|
||||
#include "accessor_scene_start.h"
|
||||
|
||||
void AccessorSceneStart::on_enter(AccessorApp* app) {
|
||||
|
||||
@@ -7,11 +7,10 @@ App(
|
||||
"vibro_test",
|
||||
"keypad_test",
|
||||
"usb_test",
|
||||
"usb_mouse",
|
||||
"uart_echo",
|
||||
"USB_Mouse",
|
||||
"UART_Echo",
|
||||
"display_test",
|
||||
"text_box_test",
|
||||
"file_browser_test",
|
||||
"speaker_debug",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -3,6 +3,7 @@ App(
|
||||
name="Battery Test",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
entry_point="battery_test_app",
|
||||
cdefines=["APP_BATTERY_TEST"],
|
||||
requires=[
|
||||
"gui",
|
||||
"power",
|
||||
|
||||
@@ -12,8 +12,7 @@ void battery_test_dialog_callback(DialogExResult result, void* context) {
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t battery_test_exit_confirm_view(void* context) {
|
||||
UNUSED(context);
|
||||
uint32_t battery_test_exit_confirm_view() {
|
||||
return BatteryTestAppViewExitDialog;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ App(
|
||||
name="Blink Test",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
entry_point="blink_test_app",
|
||||
cdefines=["APP_BLINK"],
|
||||
requires=["gui"],
|
||||
stack_size=1 * 1024,
|
||||
order=10,
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
App(
|
||||
appid="ccid_test",
|
||||
name="CCID Debug",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
entry_point="ccid_test_app",
|
||||
requires=[
|
||||
"gui",
|
||||
],
|
||||
provides=[
|
||||
"ccid_test",
|
||||
],
|
||||
stack_size=1 * 1024,
|
||||
order=120,
|
||||
fap_category="Debug",
|
||||
)
|
||||
@@ -1,169 +0,0 @@
|
||||
#include <stdint.h>
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
#include <gui/view.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/modules/submenu.h>
|
||||
#include <gui/gui.h>
|
||||
|
||||
#include "iso7816_t0_apdu.h"
|
||||
|
||||
typedef enum {
|
||||
EventTypeInput,
|
||||
} EventType;
|
||||
|
||||
typedef struct {
|
||||
Gui* gui;
|
||||
ViewPort* view_port;
|
||||
FuriMessageQueue* event_queue;
|
||||
FuriHalUsbCcidConfig ccid_cfg;
|
||||
} CcidTestApp;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
InputEvent input;
|
||||
};
|
||||
EventType type;
|
||||
} CcidTestAppEvent;
|
||||
|
||||
typedef enum {
|
||||
CcidTestSubmenuIndexInsertSmartcard,
|
||||
CcidTestSubmenuIndexRemoveSmartcard,
|
||||
CcidTestSubmenuIndexInsertSmartcardReader
|
||||
} SubmenuIndex;
|
||||
|
||||
void icc_power_on_callback(uint8_t* atrBuffer, uint32_t* atrlen, void* context) {
|
||||
UNUSED(context);
|
||||
|
||||
iso7816_answer_to_reset(atrBuffer, atrlen);
|
||||
}
|
||||
|
||||
//dataBlock points to the buffer
|
||||
//dataBlockLen tells reader how nany bytes should be read
|
||||
void xfr_datablock_callback(
|
||||
const uint8_t* dataBlock,
|
||||
uint32_t dataBlockLen,
|
||||
uint8_t* responseDataBlock,
|
||||
uint32_t* responseDataBlockLen,
|
||||
void* context) {
|
||||
UNUSED(context);
|
||||
|
||||
struct ISO7816_Command_APDU commandAPDU;
|
||||
iso7816_read_command_apdu(&commandAPDU, dataBlock, dataBlockLen);
|
||||
|
||||
struct ISO7816_Response_APDU responseAPDU;
|
||||
//class not supported
|
||||
responseAPDU.SW1 = 0x6E;
|
||||
responseAPDU.SW2 = 0x00;
|
||||
|
||||
iso7816_write_response_apdu(&responseAPDU, responseDataBlock, responseDataBlockLen);
|
||||
}
|
||||
|
||||
static const CcidCallbacks ccid_cb = {
|
||||
icc_power_on_callback,
|
||||
xfr_datablock_callback,
|
||||
};
|
||||
|
||||
static void ccid_test_app_render_callback(Canvas* canvas, void* ctx) {
|
||||
UNUSED(ctx);
|
||||
canvas_clear(canvas);
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str(canvas, 0, 10, "CCID Test App");
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str(canvas, 0, 63, "Hold [back] to exit");
|
||||
}
|
||||
|
||||
static void ccid_test_app_input_callback(InputEvent* input_event, void* ctx) {
|
||||
FuriMessageQueue* event_queue = ctx;
|
||||
|
||||
CcidTestAppEvent event;
|
||||
event.type = EventTypeInput;
|
||||
event.input = *input_event;
|
||||
furi_message_queue_put(event_queue, &event, FuriWaitForever);
|
||||
}
|
||||
|
||||
uint32_t ccid_test_exit(void* context) {
|
||||
UNUSED(context);
|
||||
return VIEW_NONE;
|
||||
}
|
||||
|
||||
CcidTestApp* ccid_test_app_alloc() {
|
||||
CcidTestApp* app = malloc(sizeof(CcidTestApp));
|
||||
|
||||
// Gui
|
||||
app->gui = furi_record_open(RECORD_GUI);
|
||||
|
||||
//viewport
|
||||
app->view_port = view_port_alloc();
|
||||
gui_add_view_port(app->gui, app->view_port, GuiLayerFullscreen);
|
||||
view_port_draw_callback_set(app->view_port, ccid_test_app_render_callback, NULL);
|
||||
|
||||
//message queue
|
||||
app->event_queue = furi_message_queue_alloc(8, sizeof(CcidTestAppEvent));
|
||||
furi_check(app->event_queue);
|
||||
view_port_input_callback_set(app->view_port, ccid_test_app_input_callback, app->event_queue);
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
void ccid_test_app_free(CcidTestApp* app) {
|
||||
furi_assert(app);
|
||||
|
||||
//message queue
|
||||
furi_message_queue_free(app->event_queue);
|
||||
|
||||
//view port
|
||||
gui_remove_view_port(app->gui, app->view_port);
|
||||
view_port_free(app->view_port);
|
||||
|
||||
// Close gui record
|
||||
furi_record_close(RECORD_GUI);
|
||||
app->gui = NULL;
|
||||
|
||||
// Free rest
|
||||
free(app);
|
||||
}
|
||||
|
||||
int32_t ccid_test_app(void* p) {
|
||||
UNUSED(p);
|
||||
|
||||
//setup view
|
||||
CcidTestApp* app = ccid_test_app_alloc();
|
||||
|
||||
//setup CCID USB
|
||||
// On linux: set VID PID using: /usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Info.plist
|
||||
app->ccid_cfg.vid = 0x1234;
|
||||
app->ccid_cfg.pid = 0x5678;
|
||||
|
||||
FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config();
|
||||
furi_hal_usb_unlock();
|
||||
furi_hal_ccid_set_callbacks((CcidCallbacks*)&ccid_cb);
|
||||
furi_check(furi_hal_usb_set_config(&usb_ccid, &app->ccid_cfg) == true);
|
||||
|
||||
//handle button events
|
||||
CcidTestAppEvent event;
|
||||
while(1) {
|
||||
FuriStatus event_status =
|
||||
furi_message_queue_get(app->event_queue, &event, FuriWaitForever);
|
||||
|
||||
if(event_status == FuriStatusOk) {
|
||||
if(event.type == EventTypeInput) {
|
||||
if(event.input.type == InputTypeLong && event.input.key == InputKeyBack) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
view_port_update(app->view_port);
|
||||
}
|
||||
|
||||
//tear down USB
|
||||
furi_hal_usb_set_config(usb_mode_prev, NULL);
|
||||
furi_hal_ccid_set_callbacks(NULL);
|
||||
|
||||
//teardown view
|
||||
ccid_test_app_free(app);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/* Implements rudimentary iso7816-3 support for APDU (T=0) */
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <furi.h>
|
||||
#include "iso7816_t0_apdu.h"
|
||||
|
||||
void iso7816_answer_to_reset(uint8_t* dataBuffer, uint32_t* atrlen) {
|
||||
//minimum valid ATR: https://smartcard-atr.apdu.fr/parse?ATR=3B+00
|
||||
uint8_t AtrBuffer[2] = {
|
||||
0x3B, //TS (direct convention)
|
||||
0x00 // T0 (Y(1): b0000, K: 0 (historical bytes))
|
||||
};
|
||||
*atrlen = 2;
|
||||
|
||||
memcpy(dataBuffer, AtrBuffer, sizeof(uint8_t) * (*atrlen));
|
||||
}
|
||||
|
||||
void iso7816_read_command_apdu(
|
||||
struct ISO7816_Command_APDU* command,
|
||||
const uint8_t* dataBuffer,
|
||||
uint32_t dataLen) {
|
||||
UNUSED(dataLen);
|
||||
command->CLA = dataBuffer[0];
|
||||
command->INS = dataBuffer[1];
|
||||
command->P1 = dataBuffer[2];
|
||||
command->P2 = dataBuffer[3];
|
||||
command->Lc = dataBuffer[4];
|
||||
}
|
||||
|
||||
void iso7816_write_response_apdu(
|
||||
const struct ISO7816_Response_APDU* response,
|
||||
uint8_t* dataBuffer,
|
||||
uint32_t* dataLen) {
|
||||
dataBuffer[0] = response->SW1;
|
||||
dataBuffer[1] = response->SW2;
|
||||
*dataLen = 2;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
#ifndef _ISO7816_T0_APDU_H_
|
||||
#define _ISO7816_T0_APDU_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct ISO7816_Command_APDU {
|
||||
//header
|
||||
uint8_t CLA;
|
||||
uint8_t INS;
|
||||
uint8_t P1;
|
||||
uint8_t P2;
|
||||
|
||||
//body
|
||||
uint8_t Lc;
|
||||
uint8_t Le;
|
||||
} FURI_PACKED;
|
||||
|
||||
struct ISO7816_Response_APDU {
|
||||
uint8_t SW1;
|
||||
uint8_t SW2;
|
||||
} FURI_PACKED;
|
||||
|
||||
void iso7816_answer_to_reset(uint8_t* atrBuffer, uint32_t* atrlen);
|
||||
void iso7816_read_command_apdu(
|
||||
struct ISO7816_Command_APDU* command,
|
||||
const uint8_t* dataBuffer,
|
||||
uint32_t dataLen);
|
||||
void iso7816_write_response_apdu(
|
||||
const struct ISO7816_Response_APDU* response,
|
||||
uint8_t* dataBuffer,
|
||||
uint32_t* dataLen);
|
||||
#endif //_ISO7816_T0_APDU_H_
|
||||
@@ -1,9 +0,0 @@
|
||||
App(
|
||||
appid="crash_test",
|
||||
name="Crash Test",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
entry_point="crash_test_app",
|
||||
requires=["gui"],
|
||||
stack_size=1 * 1024,
|
||||
fap_category="Debug",
|
||||
)
|
||||
@@ -1,128 +0,0 @@
|
||||
#include <furi_hal.h>
|
||||
#include <furi.h>
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/modules/submenu.h>
|
||||
|
||||
#define TAG "CrashTest"
|
||||
|
||||
typedef struct {
|
||||
Gui* gui;
|
||||
ViewDispatcher* view_dispatcher;
|
||||
Submenu* submenu;
|
||||
} CrashTest;
|
||||
|
||||
typedef enum {
|
||||
CrashTestViewSubmenu,
|
||||
} CrashTestView;
|
||||
|
||||
typedef enum {
|
||||
CrashTestSubmenuCheck,
|
||||
CrashTestSubmenuCheckMessage,
|
||||
CrashTestSubmenuAssert,
|
||||
CrashTestSubmenuAssertMessage,
|
||||
CrashTestSubmenuCrash,
|
||||
CrashTestSubmenuHalt,
|
||||
} CrashTestSubmenu;
|
||||
|
||||
static void crash_test_submenu_callback(void* context, uint32_t index) {
|
||||
CrashTest* instance = (CrashTest*)context;
|
||||
UNUSED(instance);
|
||||
|
||||
switch(index) {
|
||||
case CrashTestSubmenuCheck:
|
||||
furi_check(false);
|
||||
break;
|
||||
case CrashTestSubmenuCheckMessage:
|
||||
furi_check(false, "Crash test: furi_check with message");
|
||||
break;
|
||||
case CrashTestSubmenuAssert:
|
||||
furi_assert(false);
|
||||
break;
|
||||
case CrashTestSubmenuAssertMessage:
|
||||
furi_assert(false, "Crash test: furi_assert with message");
|
||||
break;
|
||||
case CrashTestSubmenuCrash:
|
||||
furi_crash("Crash test: furi_crash");
|
||||
break;
|
||||
case CrashTestSubmenuHalt:
|
||||
furi_halt("Crash test: furi_halt");
|
||||
break;
|
||||
default:
|
||||
furi_crash("Programming error");
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t crash_test_exit_callback(void* context) {
|
||||
UNUSED(context);
|
||||
return VIEW_NONE;
|
||||
}
|
||||
|
||||
CrashTest* crash_test_alloc() {
|
||||
CrashTest* instance = malloc(sizeof(CrashTest));
|
||||
|
||||
View* view = NULL;
|
||||
|
||||
instance->gui = furi_record_open(RECORD_GUI);
|
||||
instance->view_dispatcher = view_dispatcher_alloc();
|
||||
view_dispatcher_enable_queue(instance->view_dispatcher);
|
||||
view_dispatcher_attach_to_gui(
|
||||
instance->view_dispatcher, instance->gui, ViewDispatcherTypeFullscreen);
|
||||
|
||||
// Menu
|
||||
instance->submenu = submenu_alloc();
|
||||
view = submenu_get_view(instance->submenu);
|
||||
view_set_previous_callback(view, crash_test_exit_callback);
|
||||
view_dispatcher_add_view(instance->view_dispatcher, CrashTestViewSubmenu, view);
|
||||
submenu_add_item(
|
||||
instance->submenu, "Check", CrashTestSubmenuCheck, crash_test_submenu_callback, instance);
|
||||
submenu_add_item(
|
||||
instance->submenu,
|
||||
"Check with message",
|
||||
CrashTestSubmenuCheckMessage,
|
||||
crash_test_submenu_callback,
|
||||
instance);
|
||||
submenu_add_item(
|
||||
instance->submenu, "Assert", CrashTestSubmenuAssert, crash_test_submenu_callback, instance);
|
||||
submenu_add_item(
|
||||
instance->submenu,
|
||||
"Assert with message",
|
||||
CrashTestSubmenuAssertMessage,
|
||||
crash_test_submenu_callback,
|
||||
instance);
|
||||
submenu_add_item(
|
||||
instance->submenu, "Crash", CrashTestSubmenuCrash, crash_test_submenu_callback, instance);
|
||||
submenu_add_item(
|
||||
instance->submenu, "Halt", CrashTestSubmenuHalt, crash_test_submenu_callback, instance);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void crash_test_free(CrashTest* instance) {
|
||||
view_dispatcher_remove_view(instance->view_dispatcher, CrashTestViewSubmenu);
|
||||
submenu_free(instance->submenu);
|
||||
|
||||
view_dispatcher_free(instance->view_dispatcher);
|
||||
furi_record_close(RECORD_GUI);
|
||||
|
||||
free(instance);
|
||||
}
|
||||
|
||||
int32_t crash_test_run(CrashTest* instance) {
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, CrashTestViewSubmenu);
|
||||
view_dispatcher_run(instance->view_dispatcher);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t crash_test_app(void* p) {
|
||||
UNUSED(p);
|
||||
|
||||
CrashTest* instance = crash_test_alloc();
|
||||
|
||||
int32_t ret = crash_test_run(instance);
|
||||
|
||||
crash_test_free(instance);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -71,7 +71,7 @@ static void direct_draw_run(DirectDraw* instance) {
|
||||
size_t counter = 0;
|
||||
float fps = 0;
|
||||
|
||||
furi_thread_set_current_priority(FuriThreadPriorityIdle);
|
||||
vTaskPrioritySet(furi_thread_get_current_id(), FuriThreadPriorityIdle);
|
||||
|
||||
do {
|
||||
size_t elapsed = DWT->CYCCNT - start;
|
||||
|
||||
@@ -3,8 +3,9 @@ App(
|
||||
name="Display Test",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
entry_point="display_test_app",
|
||||
cdefines=["APP_DISPLAY_TEST"],
|
||||
requires=["gui"],
|
||||
fap_libs=["u8g2"],
|
||||
fap_libs=["misc"],
|
||||
stack_size=1 * 1024,
|
||||
order=120,
|
||||
fap_category="Debug",
|
||||
|
||||
9
applications/debug/example_custom_font/application.fam
Normal file
9
applications/debug/example_custom_font/application.fam
Normal file
@@ -0,0 +1,9 @@
|
||||
App(
|
||||
appid="example_custom_font",
|
||||
name="Example: custom font",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
entry_point="example_custom_font_main",
|
||||
requires=["gui"],
|
||||
stack_size=1 * 1024,
|
||||
fap_category="Debug",
|
||||
)
|
||||
@@ -1,7 +1,3 @@
|
||||
/**
|
||||
* @file example_custom_font.c
|
||||
* @brief Custom font example.
|
||||
*/
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
App(
|
||||
appid="expansion_test",
|
||||
name="Expansion Module Test",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
entry_point="expansion_test_app",
|
||||
requires=["expansion_start"],
|
||||
fap_libs=["assets"],
|
||||
stack_size=1 * 1024,
|
||||
order=20,
|
||||
fap_category="Debug",
|
||||
fap_file_assets="assets",
|
||||
)
|
||||
@@ -1,9 +0,0 @@
|
||||
"Did you ever hear the tragedy of Darth Plagueis the Wise?"
|
||||
"No."
|
||||
"I thought not. It's not a story the Jedi would tell you. It's a Sith legend. Darth Plagueis... was a Dark Lord of the Sith so powerful and so wise, he could use the Force to influence the midi-chlorians... to create... life. He had such a knowledge of the dark side, he could even keep the ones he cared about... from dying."
|
||||
"He could actually... save people from death?"
|
||||
"The dark side of the Force is a pathway to many abilities... some consider to be unnatural."
|
||||
"Wh– What happened to him?"
|
||||
"He became so powerful, the only thing he was afraid of was... losing his power. Which eventually, of course, he did. Unfortunately, he taught his apprentice everything he knew. Then his apprentice killed him in his sleep. It's ironic. He could save others from death, but not himself."
|
||||
"Is it possible to learn this power?"
|
||||
"Not from a Jedi."
|
||||
@@ -1,457 +0,0 @@
|
||||
/**
|
||||
* @file expansion_test.c
|
||||
* @brief Expansion module support testing application.
|
||||
*
|
||||
* Before running, connect pins using the following scheme:
|
||||
* 13 -> 16 (USART TX to LPUART RX)
|
||||
* 14 -> 15 (USART RX to LPUART TX)
|
||||
*
|
||||
* What this application does:
|
||||
*
|
||||
* - Enables module support and emulates the module on a single device
|
||||
* (hence the above connection),
|
||||
* - Connects to the expansion module service, sets baud rate,
|
||||
* - Starts the RPC session,
|
||||
* - Creates a directory at `/ext/ExpansionTest` and writes a file
|
||||
* named `test.txt` under it,
|
||||
* - Plays an audiovisual alert (sound and blinking display),
|
||||
* - Waits 10 cycles of idle loop,
|
||||
* - Stops the RPC session,
|
||||
* - Waits another 10 cycles of idle loop,
|
||||
* - Exits (plays a sound if any of the above steps failed).
|
||||
*/
|
||||
#include <furi.h>
|
||||
|
||||
#include <furi_hal_resources.h>
|
||||
|
||||
#include <furi_hal_serial.h>
|
||||
#include <furi_hal_serial_control.h>
|
||||
|
||||
#include <pb.h>
|
||||
#include <pb_decode.h>
|
||||
#include <pb_encode.h>
|
||||
|
||||
#include <flipper.pb.h>
|
||||
|
||||
#include <storage/storage.h>
|
||||
#include <expansion/expansion.h>
|
||||
#include <notification/notification_messages.h>
|
||||
#include <expansion/expansion_protocol.h>
|
||||
|
||||
#define TAG "ExpansionTest"
|
||||
|
||||
#define TEST_DIR_PATH EXT_PATH(TAG)
|
||||
#define TEST_FILE_NAME "test.txt"
|
||||
#define TEST_FILE_PATH EXT_PATH(TAG "/" TEST_FILE_NAME)
|
||||
|
||||
#define HOST_SERIAL_ID (FuriHalSerialIdLpuart)
|
||||
#define MODULE_SERIAL_ID (FuriHalSerialIdUsart)
|
||||
|
||||
#define RECEIVE_BUFFER_SIZE (sizeof(ExpansionFrame) + sizeof(ExpansionFrameChecksum))
|
||||
|
||||
typedef enum {
|
||||
ExpansionTestAppFlagData = 1U << 0,
|
||||
ExpansionTestAppFlagExit = 1U << 1,
|
||||
} ExpansionTestAppFlag;
|
||||
|
||||
#define EXPANSION_TEST_APP_ALL_FLAGS (ExpansionTestAppFlagData | ExpansionTestAppFlagExit)
|
||||
|
||||
typedef struct {
|
||||
FuriThreadId thread_id;
|
||||
Expansion* expansion;
|
||||
FuriHalSerialHandle* handle;
|
||||
FuriStreamBuffer* buf;
|
||||
ExpansionFrame frame;
|
||||
PB_Main msg;
|
||||
Storage* storage;
|
||||
} ExpansionTestApp;
|
||||
|
||||
static void expansion_test_app_serial_rx_callback(
|
||||
FuriHalSerialHandle* handle,
|
||||
FuriHalSerialRxEvent event,
|
||||
void* context) {
|
||||
furi_assert(handle);
|
||||
furi_assert(context);
|
||||
ExpansionTestApp* app = context;
|
||||
|
||||
if(event == FuriHalSerialRxEventData) {
|
||||
const uint8_t data = furi_hal_serial_async_rx(handle);
|
||||
furi_stream_buffer_send(app->buf, &data, sizeof(data), 0);
|
||||
furi_thread_flags_set(app->thread_id, ExpansionTestAppFlagData);
|
||||
}
|
||||
}
|
||||
|
||||
static ExpansionTestApp* expansion_test_app_alloc() {
|
||||
ExpansionTestApp* instance = malloc(sizeof(ExpansionTestApp));
|
||||
instance->buf = furi_stream_buffer_alloc(RECEIVE_BUFFER_SIZE, 1);
|
||||
return instance;
|
||||
}
|
||||
|
||||
static void expansion_test_app_free(ExpansionTestApp* instance) {
|
||||
furi_stream_buffer_free(instance->buf);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
static void expansion_test_app_start(ExpansionTestApp* instance) {
|
||||
instance->thread_id = furi_thread_get_current_id();
|
||||
instance->expansion = furi_record_open(RECORD_EXPANSION);
|
||||
instance->handle = furi_hal_serial_control_acquire(MODULE_SERIAL_ID);
|
||||
furi_check(instance->handle);
|
||||
// Configure the serial port
|
||||
furi_hal_serial_init(instance->handle, EXPANSION_PROTOCOL_DEFAULT_BAUD_RATE);
|
||||
// Start waiting for the initial pulse
|
||||
expansion_set_listen_serial(instance->expansion, HOST_SERIAL_ID);
|
||||
|
||||
furi_hal_serial_async_rx_start(
|
||||
instance->handle, expansion_test_app_serial_rx_callback, instance, false);
|
||||
}
|
||||
|
||||
static void expansion_test_app_stop(ExpansionTestApp* instance) {
|
||||
// Disable expansion module support
|
||||
expansion_disable(instance->expansion);
|
||||
// Give back the module handle
|
||||
furi_hal_serial_control_release(instance->handle);
|
||||
// Restore expansion user settings
|
||||
expansion_enable(instance->expansion);
|
||||
furi_record_close(RECORD_EXPANSION);
|
||||
}
|
||||
|
||||
static inline bool expansion_test_app_is_success_response(const ExpansionFrame* response) {
|
||||
return response->header.type == ExpansionFrameTypeStatus &&
|
||||
response->content.status.error == ExpansionFrameErrorNone;
|
||||
}
|
||||
|
||||
static inline bool expansion_test_app_is_success_rpc_message(const PB_Main* message) {
|
||||
return (message->command_status == PB_CommandStatus_OK ||
|
||||
message->command_status == PB_CommandStatus_ERROR_STORAGE_EXIST) &&
|
||||
(message->which_content == PB_Main_empty_tag);
|
||||
}
|
||||
|
||||
static size_t expansion_test_app_receive_callback(uint8_t* data, size_t data_size, void* context) {
|
||||
ExpansionTestApp* instance = context;
|
||||
|
||||
size_t received_size = 0;
|
||||
|
||||
while(true) {
|
||||
received_size += furi_stream_buffer_receive(
|
||||
instance->buf, data + received_size, data_size - received_size, 0);
|
||||
if(received_size == data_size) break;
|
||||
|
||||
const uint32_t flags = furi_thread_flags_wait(
|
||||
EXPANSION_TEST_APP_ALL_FLAGS, FuriFlagWaitAny, EXPANSION_PROTOCOL_TIMEOUT_MS);
|
||||
|
||||
// Exit on any error
|
||||
if(flags & FuriFlagError) break;
|
||||
}
|
||||
|
||||
return received_size;
|
||||
}
|
||||
|
||||
static size_t
|
||||
expansion_test_app_send_callback(const uint8_t* data, size_t data_size, void* context) {
|
||||
ExpansionTestApp* instance = context;
|
||||
|
||||
furi_hal_serial_tx(instance->handle, data, data_size);
|
||||
furi_hal_serial_tx_wait_complete(instance->handle);
|
||||
|
||||
return data_size;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_receive_frame(ExpansionTestApp* instance, ExpansionFrame* frame) {
|
||||
return expansion_protocol_decode(frame, expansion_test_app_receive_callback, instance) ==
|
||||
ExpansionProtocolStatusOk;
|
||||
}
|
||||
|
||||
static bool
|
||||
expansion_test_app_send_status_response(ExpansionTestApp* instance, ExpansionFrameError error) {
|
||||
ExpansionFrame frame = {
|
||||
.header.type = ExpansionFrameTypeStatus,
|
||||
.content.status.error = error,
|
||||
};
|
||||
return expansion_protocol_encode(&frame, expansion_test_app_send_callback, instance) ==
|
||||
ExpansionProtocolStatusOk;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_send_heartbeat(ExpansionTestApp* instance) {
|
||||
ExpansionFrame frame = {
|
||||
.header.type = ExpansionFrameTypeHeartbeat,
|
||||
.content.heartbeat = {},
|
||||
};
|
||||
return expansion_protocol_encode(&frame, expansion_test_app_send_callback, instance) ==
|
||||
ExpansionProtocolStatusOk;
|
||||
}
|
||||
|
||||
static bool
|
||||
expansion_test_app_send_baud_rate_request(ExpansionTestApp* instance, uint32_t baud_rate) {
|
||||
ExpansionFrame frame = {
|
||||
.header.type = ExpansionFrameTypeBaudRate,
|
||||
.content.baud_rate.baud = baud_rate,
|
||||
};
|
||||
return expansion_protocol_encode(&frame, expansion_test_app_send_callback, instance) ==
|
||||
ExpansionProtocolStatusOk;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_send_control_request(
|
||||
ExpansionTestApp* instance,
|
||||
ExpansionFrameControlCommand command) {
|
||||
ExpansionFrame frame = {
|
||||
.header.type = ExpansionFrameTypeControl,
|
||||
.content.control.command = command,
|
||||
};
|
||||
return expansion_protocol_encode(&frame, expansion_test_app_send_callback, instance) ==
|
||||
ExpansionProtocolStatusOk;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_send_data_request(
|
||||
ExpansionTestApp* instance,
|
||||
const uint8_t* data,
|
||||
size_t data_size) {
|
||||
furi_assert(data_size <= EXPANSION_PROTOCOL_MAX_DATA_SIZE);
|
||||
|
||||
ExpansionFrame frame = {
|
||||
.header.type = ExpansionFrameTypeData,
|
||||
.content.data.size = data_size,
|
||||
};
|
||||
|
||||
memcpy(frame.content.data.bytes, data, data_size);
|
||||
return expansion_protocol_encode(&frame, expansion_test_app_send_callback, instance) ==
|
||||
ExpansionProtocolStatusOk;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_rpc_encode_callback(
|
||||
pb_ostream_t* stream,
|
||||
const pb_byte_t* data,
|
||||
size_t data_size) {
|
||||
ExpansionTestApp* instance = stream->state;
|
||||
|
||||
size_t size_sent = 0;
|
||||
|
||||
while(size_sent < data_size) {
|
||||
const size_t current_size = MIN(data_size - size_sent, EXPANSION_PROTOCOL_MAX_DATA_SIZE);
|
||||
if(!expansion_test_app_send_data_request(instance, data + size_sent, current_size)) break;
|
||||
if(!expansion_test_app_receive_frame(instance, &instance->frame)) break;
|
||||
if(!expansion_test_app_is_success_response(&instance->frame)) break;
|
||||
size_sent += current_size;
|
||||
}
|
||||
|
||||
return size_sent == data_size;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_send_rpc_request(ExpansionTestApp* instance, PB_Main* message) {
|
||||
pb_ostream_t stream = {
|
||||
.callback = expansion_test_app_rpc_encode_callback,
|
||||
.state = instance,
|
||||
.max_size = SIZE_MAX,
|
||||
.bytes_written = 0,
|
||||
.errmsg = NULL,
|
||||
};
|
||||
|
||||
const bool success = pb_encode_ex(&stream, &PB_Main_msg, message, PB_ENCODE_DELIMITED);
|
||||
pb_release(&PB_Main_msg, message);
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_receive_rpc_request(ExpansionTestApp* instance, PB_Main* message) {
|
||||
bool success = false;
|
||||
|
||||
do {
|
||||
if(!expansion_test_app_receive_frame(instance, &instance->frame)) break;
|
||||
if(!expansion_test_app_send_status_response(instance, ExpansionFrameErrorNone)) break;
|
||||
if(instance->frame.header.type != ExpansionFrameTypeData) break;
|
||||
pb_istream_t stream = pb_istream_from_buffer(
|
||||
instance->frame.content.data.bytes, instance->frame.content.data.size);
|
||||
if(!pb_decode_ex(&stream, &PB_Main_msg, message, PB_DECODE_DELIMITED)) break;
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_send_presence(ExpansionTestApp* instance) {
|
||||
// Send pulses to emulate module insertion
|
||||
const uint8_t init = 0xAA;
|
||||
furi_hal_serial_tx(instance->handle, &init, sizeof(init));
|
||||
furi_hal_serial_tx_wait_complete(instance->handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_wait_ready(ExpansionTestApp* instance) {
|
||||
bool success = false;
|
||||
|
||||
do {
|
||||
if(!expansion_test_app_receive_frame(instance, &instance->frame)) break;
|
||||
if(instance->frame.header.type != ExpansionFrameTypeHeartbeat) break;
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_handshake(ExpansionTestApp* instance) {
|
||||
bool success = false;
|
||||
|
||||
do {
|
||||
if(!expansion_test_app_send_baud_rate_request(instance, 230400)) break;
|
||||
if(!expansion_test_app_receive_frame(instance, &instance->frame)) break;
|
||||
if(!expansion_test_app_is_success_response(&instance->frame)) break;
|
||||
furi_hal_serial_set_br(instance->handle, 230400);
|
||||
furi_delay_ms(EXPANSION_PROTOCOL_BAUD_CHANGE_DT_MS);
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_start_rpc(ExpansionTestApp* instance) {
|
||||
bool success = false;
|
||||
|
||||
do {
|
||||
if(!expansion_test_app_send_control_request(instance, ExpansionFrameControlCommandStartRpc))
|
||||
break;
|
||||
if(!expansion_test_app_receive_frame(instance, &instance->frame)) break;
|
||||
if(!expansion_test_app_is_success_response(&instance->frame)) break;
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_rpc_mkdir(ExpansionTestApp* instance) {
|
||||
bool success = false;
|
||||
|
||||
instance->msg.command_id++;
|
||||
instance->msg.command_status = PB_CommandStatus_OK;
|
||||
instance->msg.which_content = PB_Main_storage_mkdir_request_tag;
|
||||
instance->msg.has_next = false;
|
||||
instance->msg.content.storage_mkdir_request.path = TEST_DIR_PATH;
|
||||
|
||||
do {
|
||||
if(!expansion_test_app_send_rpc_request(instance, &instance->msg)) break;
|
||||
if(!expansion_test_app_receive_rpc_request(instance, &instance->msg)) break;
|
||||
if(!expansion_test_app_is_success_rpc_message(&instance->msg)) break;
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_rpc_write(ExpansionTestApp* instance) {
|
||||
bool success = false;
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
File* file = storage_file_alloc(storage);
|
||||
|
||||
do {
|
||||
if(!storage_file_open(file, APP_ASSETS_PATH(TEST_FILE_NAME), FSAM_READ, FSOM_OPEN_EXISTING))
|
||||
break;
|
||||
|
||||
const uint64_t file_size = storage_file_size(file);
|
||||
|
||||
instance->msg.command_id++;
|
||||
instance->msg.command_status = PB_CommandStatus_OK;
|
||||
instance->msg.which_content = PB_Main_storage_write_request_tag;
|
||||
instance->msg.has_next = false;
|
||||
instance->msg.content.storage_write_request.path = TEST_FILE_PATH;
|
||||
instance->msg.content.storage_write_request.has_file = true;
|
||||
instance->msg.content.storage_write_request.file.data =
|
||||
malloc(PB_BYTES_ARRAY_T_ALLOCSIZE(file_size));
|
||||
instance->msg.content.storage_write_request.file.data->size = file_size;
|
||||
|
||||
const size_t bytes_read = storage_file_read(
|
||||
file, instance->msg.content.storage_write_request.file.data->bytes, file_size);
|
||||
|
||||
if(bytes_read != file_size) {
|
||||
pb_release(&PB_Main_msg, &instance->msg);
|
||||
break;
|
||||
}
|
||||
|
||||
if(!expansion_test_app_send_rpc_request(instance, &instance->msg)) break;
|
||||
if(!expansion_test_app_receive_rpc_request(instance, &instance->msg)) break;
|
||||
if(!expansion_test_app_is_success_rpc_message(&instance->msg)) break;
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
storage_file_free(file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_rpc_alert(ExpansionTestApp* instance) {
|
||||
bool success = false;
|
||||
|
||||
instance->msg.command_id++;
|
||||
instance->msg.command_status = PB_CommandStatus_OK;
|
||||
instance->msg.which_content = PB_Main_system_play_audiovisual_alert_request_tag;
|
||||
instance->msg.has_next = false;
|
||||
|
||||
do {
|
||||
if(!expansion_test_app_send_rpc_request(instance, &instance->msg)) break;
|
||||
if(!expansion_test_app_receive_rpc_request(instance, &instance->msg)) break;
|
||||
if(instance->msg.which_content != PB_Main_empty_tag) break;
|
||||
if(instance->msg.command_status != PB_CommandStatus_OK) break;
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_idle(ExpansionTestApp* instance, uint32_t num_cycles) {
|
||||
uint32_t num_cycles_done;
|
||||
for(num_cycles_done = 0; num_cycles_done < num_cycles; ++num_cycles_done) {
|
||||
if(!expansion_test_app_send_heartbeat(instance)) break;
|
||||
if(!expansion_test_app_receive_frame(instance, &instance->frame)) break;
|
||||
if(instance->frame.header.type != ExpansionFrameTypeHeartbeat) break;
|
||||
furi_delay_ms(EXPANSION_PROTOCOL_TIMEOUT_MS - 50);
|
||||
}
|
||||
|
||||
return num_cycles_done == num_cycles;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_stop_rpc(ExpansionTestApp* instance) {
|
||||
bool success = false;
|
||||
|
||||
do {
|
||||
if(!expansion_test_app_send_control_request(instance, ExpansionFrameControlCommandStopRpc))
|
||||
break;
|
||||
if(!expansion_test_app_receive_frame(instance, &instance->frame)) break;
|
||||
if(!expansion_test_app_is_success_response(&instance->frame)) break;
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
int32_t expansion_test_app(void* p) {
|
||||
UNUSED(p);
|
||||
|
||||
ExpansionTestApp* instance = expansion_test_app_alloc();
|
||||
expansion_test_app_start(instance);
|
||||
|
||||
bool success = false;
|
||||
|
||||
do {
|
||||
if(!expansion_test_app_send_presence(instance)) break;
|
||||
if(!expansion_test_app_wait_ready(instance)) break;
|
||||
if(!expansion_test_app_handshake(instance)) break;
|
||||
if(!expansion_test_app_start_rpc(instance)) break;
|
||||
if(!expansion_test_app_rpc_mkdir(instance)) break;
|
||||
if(!expansion_test_app_rpc_write(instance)) break;
|
||||
if(!expansion_test_app_rpc_alert(instance)) break;
|
||||
if(!expansion_test_app_idle(instance, 10)) break;
|
||||
if(!expansion_test_app_stop_rpc(instance)) break;
|
||||
if(!expansion_test_app_idle(instance, 10)) break;
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
expansion_test_app_stop(instance);
|
||||
expansion_test_app_free(instance);
|
||||
|
||||
if(!success) {
|
||||
NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
|
||||
notification_message(notification, &sequence_error);
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3,6 +3,7 @@ App(
|
||||
name="File Browser Test",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
entry_point="file_browser_app",
|
||||
cdefines=["APP_FILE_BROWSER_TEST"],
|
||||
requires=["gui"],
|
||||
stack_size=2 * 1024,
|
||||
order=150,
|
||||
|
||||
@@ -3,6 +3,7 @@ App(
|
||||
name="Keypad Test",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
entry_point="keypad_test_app",
|
||||
cdefines=["APP_KEYPAD_TEST"],
|
||||
requires=["gui"],
|
||||
stack_size=1 * 1024,
|
||||
order=30,
|
||||
|
||||
@@ -11,7 +11,6 @@ typedef struct {
|
||||
uint16_t left;
|
||||
uint16_t right;
|
||||
uint16_t ok;
|
||||
FuriMutex* mutex;
|
||||
} KeypadTestState;
|
||||
|
||||
static void keypad_test_reset_state(KeypadTestState* state) {
|
||||
@@ -23,8 +22,7 @@ static void keypad_test_reset_state(KeypadTestState* state) {
|
||||
}
|
||||
|
||||
static void keypad_test_render_callback(Canvas* canvas, void* ctx) {
|
||||
KeypadTestState* state = ctx;
|
||||
furi_mutex_acquire(state->mutex, FuriWaitForever);
|
||||
KeypadTestState* state = (KeypadTestState*)acquire_mutex((ValueMutex*)ctx, 25);
|
||||
canvas_clear(canvas);
|
||||
char strings[5][20];
|
||||
|
||||
@@ -53,7 +51,7 @@ static void keypad_test_render_callback(Canvas* canvas, void* ctx) {
|
||||
|
||||
canvas_draw_str(canvas, 10, 63, "[back] - reset, hold to exit");
|
||||
|
||||
furi_mutex_release(state->mutex);
|
||||
release_mutex((ValueMutex*)ctx, state);
|
||||
}
|
||||
|
||||
static void keypad_test_input_callback(InputEvent* input_event, void* ctx) {
|
||||
@@ -66,17 +64,17 @@ int32_t keypad_test_app(void* p) {
|
||||
FuriMessageQueue* event_queue = furi_message_queue_alloc(32, sizeof(InputEvent));
|
||||
furi_check(event_queue);
|
||||
|
||||
KeypadTestState state = {{false, false, false, false, false}, 0, 0, 0, 0, 0, NULL};
|
||||
state.mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
KeypadTestState _state = {{false, false, false, false, false}, 0, 0, 0, 0, 0};
|
||||
|
||||
if(!state.mutex) {
|
||||
ValueMutex state_mutex;
|
||||
if(!init_mutex(&state_mutex, &_state, sizeof(KeypadTestState))) {
|
||||
FURI_LOG_E(TAG, "cannot create mutex");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ViewPort* view_port = view_port_alloc();
|
||||
|
||||
view_port_draw_callback_set(view_port, keypad_test_render_callback, &state);
|
||||
view_port_draw_callback_set(view_port, keypad_test_render_callback, &state_mutex);
|
||||
view_port_input_callback_set(view_port, keypad_test_input_callback, event_queue);
|
||||
|
||||
// Open GUI and register view_port
|
||||
@@ -85,7 +83,7 @@ int32_t keypad_test_app(void* p) {
|
||||
|
||||
InputEvent event;
|
||||
while(furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk) {
|
||||
furi_mutex_acquire(state.mutex, FuriWaitForever);
|
||||
KeypadTestState* state = (KeypadTestState*)acquire_mutex_block(&state_mutex);
|
||||
FURI_LOG_I(
|
||||
TAG,
|
||||
"key: %s type: %s",
|
||||
@@ -94,54 +92,54 @@ int32_t keypad_test_app(void* p) {
|
||||
|
||||
if(event.key == InputKeyRight) {
|
||||
if(event.type == InputTypePress) {
|
||||
state.press[0] = true;
|
||||
state->press[0] = true;
|
||||
} else if(event.type == InputTypeRelease) {
|
||||
state.press[0] = false;
|
||||
state->press[0] = false;
|
||||
} else if(event.type == InputTypeShort) {
|
||||
++state.right;
|
||||
++state->right;
|
||||
}
|
||||
} else if(event.key == InputKeyLeft) {
|
||||
if(event.type == InputTypePress) {
|
||||
state.press[1] = true;
|
||||
state->press[1] = true;
|
||||
} else if(event.type == InputTypeRelease) {
|
||||
state.press[1] = false;
|
||||
state->press[1] = false;
|
||||
} else if(event.type == InputTypeShort) {
|
||||
++state.left;
|
||||
++state->left;
|
||||
}
|
||||
} else if(event.key == InputKeyUp) {
|
||||
if(event.type == InputTypePress) {
|
||||
state.press[2] = true;
|
||||
state->press[2] = true;
|
||||
} else if(event.type == InputTypeRelease) {
|
||||
state.press[2] = false;
|
||||
state->press[2] = false;
|
||||
} else if(event.type == InputTypeShort) {
|
||||
++state.up;
|
||||
++state->up;
|
||||
}
|
||||
} else if(event.key == InputKeyDown) {
|
||||
if(event.type == InputTypePress) {
|
||||
state.press[3] = true;
|
||||
state->press[3] = true;
|
||||
} else if(event.type == InputTypeRelease) {
|
||||
state.press[3] = false;
|
||||
state->press[3] = false;
|
||||
} else if(event.type == InputTypeShort) {
|
||||
++state.down;
|
||||
++state->down;
|
||||
}
|
||||
} else if(event.key == InputKeyOk) {
|
||||
if(event.type == InputTypePress) {
|
||||
state.press[4] = true;
|
||||
state->press[4] = true;
|
||||
} else if(event.type == InputTypeRelease) {
|
||||
state.press[4] = false;
|
||||
state->press[4] = false;
|
||||
} else if(event.type == InputTypeShort) {
|
||||
++state.ok;
|
||||
++state->ok;
|
||||
}
|
||||
} else if(event.key == InputKeyBack) {
|
||||
if(event.type == InputTypeLong) {
|
||||
furi_mutex_release(state.mutex);
|
||||
release_mutex(&state_mutex, state);
|
||||
break;
|
||||
} else if(event.type == InputTypeShort) {
|
||||
keypad_test_reset_state(&state);
|
||||
keypad_test_reset_state(state);
|
||||
}
|
||||
}
|
||||
|
||||
furi_mutex_release(state.mutex);
|
||||
release_mutex(&state_mutex, state);
|
||||
view_port_update(view_port);
|
||||
}
|
||||
|
||||
@@ -149,7 +147,7 @@ int32_t keypad_test_app(void* p) {
|
||||
gui_remove_view_port(gui, view_port);
|
||||
view_port_free(view_port);
|
||||
furi_message_queue_free(event_queue);
|
||||
furi_mutex_free(state.mutex);
|
||||
delete_mutex(&state_mutex);
|
||||
|
||||
furi_record_close(RECORD_GUI);
|
||||
|
||||
|
||||
@@ -6,11 +6,6 @@ static void comparator_trigger_callback(bool level, void* comp_ctx) {
|
||||
furi_hal_gpio_write(&gpio_ext_pa7, !level);
|
||||
}
|
||||
|
||||
void lfrfid_debug_view_tune_callback(void* context) {
|
||||
LfRfidDebug* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, 0xBA);
|
||||
}
|
||||
|
||||
void lfrfid_debug_scene_tune_on_enter(void* context) {
|
||||
LfRfidDebug* app = context;
|
||||
|
||||
@@ -19,9 +14,9 @@ void lfrfid_debug_scene_tune_on_enter(void* context) {
|
||||
furi_hal_rfid_comp_set_callback(comparator_trigger_callback, app);
|
||||
furi_hal_rfid_comp_start();
|
||||
|
||||
furi_hal_rfid_tim_read_start(125000, 0.5);
|
||||
|
||||
lfrfid_debug_view_tune_set_callback(app->tune_view, lfrfid_debug_view_tune_callback, app);
|
||||
furi_hal_rfid_pins_read();
|
||||
furi_hal_rfid_tim_read(125000, 0.5);
|
||||
furi_hal_rfid_tim_read_start();
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidDebugViewTune);
|
||||
}
|
||||
@@ -48,5 +43,6 @@ void lfrfid_debug_scene_tune_on_exit(void* context) {
|
||||
|
||||
furi_hal_gpio_init_simple(&gpio_ext_pa7, GpioModeAnalog);
|
||||
furi_hal_rfid_tim_read_stop();
|
||||
furi_hal_rfid_tim_reset();
|
||||
furi_hal_rfid_pins_reset();
|
||||
}
|
||||
|
||||
@@ -13,8 +13,6 @@ typedef struct {
|
||||
uint32_t ARR;
|
||||
uint32_t CCR;
|
||||
int pos;
|
||||
void (*update_callback)(void* context);
|
||||
void* update_context;
|
||||
} LfRfidTuneViewModel;
|
||||
|
||||
static void lfrfid_debug_view_tune_draw_callback(Canvas* canvas, void* _model) {
|
||||
@@ -153,18 +151,6 @@ static bool lfrfid_debug_view_tune_input_callback(InputEvent* event, void* conte
|
||||
consumed = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if(event->key == InputKeyLeft || event->key == InputKeyRight) {
|
||||
with_view_model(
|
||||
tune_view->view,
|
||||
LfRfidTuneViewModel * model,
|
||||
{
|
||||
if(model->update_callback) {
|
||||
model->update_callback(model->update_context);
|
||||
}
|
||||
},
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
@@ -175,7 +161,19 @@ LfRfidTuneView* lfrfid_debug_view_tune_alloc() {
|
||||
tune_view->view = view_alloc();
|
||||
view_set_context(tune_view->view, tune_view);
|
||||
view_allocate_model(tune_view->view, ViewModelTypeLocking, sizeof(LfRfidTuneViewModel));
|
||||
lfrfid_debug_view_tune_clean(tune_view);
|
||||
|
||||
with_view_model(
|
||||
tune_view->view,
|
||||
LfRfidTuneViewModel * model,
|
||||
{
|
||||
model->dirty = true;
|
||||
model->fine = false;
|
||||
model->ARR = 511;
|
||||
model->CCR = 255;
|
||||
model->pos = 0;
|
||||
},
|
||||
true);
|
||||
|
||||
view_set_draw_callback(tune_view->view, lfrfid_debug_view_tune_draw_callback);
|
||||
view_set_input_callback(tune_view->view, lfrfid_debug_view_tune_input_callback);
|
||||
|
||||
@@ -201,8 +199,6 @@ void lfrfid_debug_view_tune_clean(LfRfidTuneView* tune_view) {
|
||||
model->ARR = 511;
|
||||
model->CCR = 255;
|
||||
model->pos = 0;
|
||||
model->update_callback = NULL;
|
||||
model->update_context = NULL;
|
||||
},
|
||||
true);
|
||||
}
|
||||
@@ -236,17 +232,3 @@ uint32_t lfrfid_debug_view_tune_get_ccr(LfRfidTuneView* tune_view) {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void lfrfid_debug_view_tune_set_callback(
|
||||
LfRfidTuneView* tune_view,
|
||||
void (*callback)(void* context),
|
||||
void* context) {
|
||||
with_view_model(
|
||||
tune_view->view,
|
||||
LfRfidTuneViewModel * model,
|
||||
{
|
||||
model->update_callback = callback;
|
||||
model->update_context = context;
|
||||
},
|
||||
false);
|
||||
}
|
||||
|
||||
@@ -16,8 +16,3 @@ bool lfrfid_debug_view_tune_is_dirty(LfRfidTuneView* tune_view);
|
||||
uint32_t lfrfid_debug_view_tune_get_arr(LfRfidTuneView* tune_view);
|
||||
|
||||
uint32_t lfrfid_debug_view_tune_get_ccr(LfRfidTuneView* tune_view);
|
||||
|
||||
void lfrfid_debug_view_tune_set_callback(
|
||||
LfRfidTuneView* tune_view,
|
||||
void (*callback)(void* context),
|
||||
void* context);
|
||||
|
||||
@@ -3,6 +3,7 @@ App(
|
||||
name="Locale Test",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
entry_point="locale_test_app",
|
||||
cdefines=["APP_LOCALE"],
|
||||
requires=["gui", "locale"],
|
||||
stack_size=2 * 1024,
|
||||
order=70,
|
||||
|
||||
@@ -30,7 +30,7 @@ static void locale_test_view_draw_callback(Canvas* canvas, void* _model) {
|
||||
}
|
||||
canvas_draw_str(canvas, 0, 10, furi_string_get_cstr(tmp_string));
|
||||
|
||||
DateTime datetime;
|
||||
FuriHalRtcDateTime datetime;
|
||||
furi_hal_rtc_get_datetime(&datetime);
|
||||
|
||||
locale_format_time(tmp_string, &datetime, locale_get_time_format(), false);
|
||||
|
||||
@@ -21,51 +21,22 @@ static void rpc_debug_app_tick_event_callback(void* context) {
|
||||
scene_manager_handle_tick_event(app->scene_manager);
|
||||
}
|
||||
|
||||
static void
|
||||
rpc_debug_app_format_hex(const uint8_t* data, size_t data_size, char* buf, size_t buf_size) {
|
||||
if(data == NULL || data_size == 0) {
|
||||
strncpy(buf, "<Data empty>", buf_size);
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t byte_width = 3;
|
||||
const size_t line_width = 7;
|
||||
|
||||
data_size = MIN(data_size, buf_size / (byte_width + 1));
|
||||
|
||||
for(size_t i = 0; i < data_size; ++i) {
|
||||
char* p = buf + (i * byte_width);
|
||||
char sep = !((i + 1) % line_width) ? '\n' : ' ';
|
||||
snprintf(p, byte_width + 1, "%02X%c", data[i], sep);
|
||||
}
|
||||
|
||||
buf[buf_size - 1] = '\0';
|
||||
}
|
||||
|
||||
static void rpc_debug_app_rpc_command_callback(const RpcAppSystemEvent* event, void* context) {
|
||||
static void rpc_debug_app_rpc_command_callback(RpcAppSystemEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
RpcDebugApp* app = context;
|
||||
furi_assert(app->rpc);
|
||||
|
||||
if(event->type == RpcAppEventTypeSessionClose) {
|
||||
if(event == RpcAppEventSessionClose) {
|
||||
scene_manager_stop(app->scene_manager);
|
||||
view_dispatcher_stop(app->view_dispatcher);
|
||||
rpc_system_app_set_callback(app->rpc, NULL, NULL);
|
||||
app->rpc = NULL;
|
||||
} else if(event->type == RpcAppEventTypeAppExit) {
|
||||
} else if(event == RpcAppEventAppExit) {
|
||||
scene_manager_stop(app->scene_manager);
|
||||
view_dispatcher_stop(app->view_dispatcher);
|
||||
rpc_system_app_confirm(app->rpc, true);
|
||||
} else if(event->type == RpcAppEventTypeDataExchange) {
|
||||
furi_assert(event->data.type == RpcAppSystemEventDataTypeBytes);
|
||||
|
||||
rpc_debug_app_format_hex(
|
||||
event->data.bytes.ptr, event->data.bytes.size, app->text_store, TEXT_STORE_SIZE);
|
||||
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, RpcDebugAppCustomEventRpcDataExchange);
|
||||
rpc_system_app_confirm(app->rpc, RpcAppEventAppExit, true);
|
||||
} else {
|
||||
rpc_system_app_confirm(app->rpc, false);
|
||||
rpc_system_app_confirm(app->rpc, event, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,40 @@
|
||||
#include "../rpc_debug_app.h"
|
||||
|
||||
static void rpc_debug_app_scene_start_format_hex(
|
||||
const uint8_t* data,
|
||||
size_t data_size,
|
||||
char* buf,
|
||||
size_t buf_size) {
|
||||
furi_assert(data);
|
||||
furi_assert(buf);
|
||||
|
||||
const size_t byte_width = 3;
|
||||
const size_t line_width = 7;
|
||||
|
||||
data_size = MIN(data_size, buf_size / (byte_width + 1));
|
||||
|
||||
for(size_t i = 0; i < data_size; ++i) {
|
||||
char* p = buf + (i * byte_width);
|
||||
char sep = !((i + 1) % line_width) ? '\n' : ' ';
|
||||
snprintf(p, byte_width + 1, "%02X%c", data[i], sep);
|
||||
}
|
||||
|
||||
buf[buf_size - 1] = '\0';
|
||||
}
|
||||
|
||||
static void rpc_debug_app_scene_receive_data_exchange_callback(
|
||||
const uint8_t* data,
|
||||
size_t data_size,
|
||||
void* context) {
|
||||
RpcDebugApp* app = context;
|
||||
if(data) {
|
||||
rpc_debug_app_scene_start_format_hex(data, data_size, app->text_store, TEXT_STORE_SIZE);
|
||||
} else {
|
||||
strncpy(app->text_store, "<Data empty>", TEXT_STORE_SIZE);
|
||||
}
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, RpcDebugAppCustomEventRpcDataExchange);
|
||||
}
|
||||
|
||||
void rpc_debug_app_scene_receive_data_exchange_on_enter(void* context) {
|
||||
RpcDebugApp* app = context;
|
||||
strncpy(app->text_store, "Received data will appear here...", TEXT_STORE_SIZE);
|
||||
@@ -7,6 +42,8 @@ void rpc_debug_app_scene_receive_data_exchange_on_enter(void* context) {
|
||||
text_box_set_text(app->text_box, app->text_store);
|
||||
text_box_set_font(app->text_box, TextBoxFontHex);
|
||||
|
||||
rpc_system_app_set_data_exchange_callback(
|
||||
app->rpc, rpc_debug_app_scene_receive_data_exchange_callback, app);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, RpcDebugAppViewTextBox);
|
||||
}
|
||||
|
||||
@@ -16,7 +53,6 @@ bool rpc_debug_app_scene_receive_data_exchange_on_event(void* context, SceneMana
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == RpcDebugAppCustomEventRpcDataExchange) {
|
||||
rpc_system_app_confirm(app->rpc, true);
|
||||
notification_message(app->notifications, &sequence_blink_cyan_100);
|
||||
notification_message(app->notifications, &sequence_display_backlight_on);
|
||||
text_box_set_text(app->text_box, app->text_store);
|
||||
@@ -30,4 +66,5 @@ bool rpc_debug_app_scene_receive_data_exchange_on_event(void* context, SceneMana
|
||||
void rpc_debug_app_scene_receive_data_exchange_on_exit(void* context) {
|
||||
RpcDebugApp* app = context;
|
||||
text_box_reset(app->text_box);
|
||||
rpc_system_app_set_data_exchange_callback(app->rpc, NULL, NULL);
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
App(
|
||||
appid="speaker_debug",
|
||||
name="Speaker Debug",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
entry_point="speaker_debug_app",
|
||||
requires=["gui", "notification"],
|
||||
stack_size=2 * 1024,
|
||||
order=10,
|
||||
fap_category="Debug",
|
||||
fap_libs=["music_worker"],
|
||||
)
|
||||
@@ -1,120 +0,0 @@
|
||||
#include <furi.h>
|
||||
#include <notification/notification.h>
|
||||
#include <music_worker/music_worker.h>
|
||||
#include <cli/cli.h>
|
||||
#include <toolbox/args.h>
|
||||
|
||||
#define TAG "SpeakerDebug"
|
||||
#define CLI_COMMAND "speaker_debug"
|
||||
|
||||
typedef enum {
|
||||
SpeakerDebugAppMessageTypeStop,
|
||||
} SpeakerDebugAppMessageType;
|
||||
|
||||
typedef struct {
|
||||
SpeakerDebugAppMessageType type;
|
||||
} SpeakerDebugAppMessage;
|
||||
|
||||
typedef struct {
|
||||
MusicWorker* music_worker;
|
||||
FuriMessageQueue* message_queue;
|
||||
Cli* cli;
|
||||
} SpeakerDebugApp;
|
||||
|
||||
static SpeakerDebugApp* speaker_app_alloc() {
|
||||
SpeakerDebugApp* app = (SpeakerDebugApp*)malloc(sizeof(SpeakerDebugApp));
|
||||
app->music_worker = music_worker_alloc();
|
||||
app->message_queue = furi_message_queue_alloc(8, sizeof(SpeakerDebugAppMessage));
|
||||
app->cli = furi_record_open(RECORD_CLI);
|
||||
return app;
|
||||
}
|
||||
|
||||
static void speaker_app_free(SpeakerDebugApp* app) {
|
||||
music_worker_free(app->music_worker);
|
||||
furi_message_queue_free(app->message_queue);
|
||||
furi_record_close(RECORD_CLI);
|
||||
free(app);
|
||||
}
|
||||
|
||||
static void speaker_app_cli(Cli* cli, FuriString* args, void* context) {
|
||||
UNUSED(cli);
|
||||
|
||||
SpeakerDebugApp* app = (SpeakerDebugApp*)context;
|
||||
SpeakerDebugAppMessage message;
|
||||
FuriString* cmd = furi_string_alloc();
|
||||
|
||||
if(!args_read_string_and_trim(args, cmd)) {
|
||||
furi_string_free(cmd);
|
||||
printf("Usage:\r\n");
|
||||
printf("\t" CLI_COMMAND " stop\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(furi_string_cmp(cmd, "stop") == 0) {
|
||||
message.type = SpeakerDebugAppMessageTypeStop;
|
||||
FuriStatus status = furi_message_queue_put(app->message_queue, &message, 100);
|
||||
if(status != FuriStatusOk) {
|
||||
printf("Failed to send message\r\n");
|
||||
} else {
|
||||
printf("Stopping\r\n");
|
||||
}
|
||||
} else {
|
||||
printf("Usage:\r\n");
|
||||
printf("\t" CLI_COMMAND " stop\r\n");
|
||||
}
|
||||
|
||||
furi_string_free(cmd);
|
||||
}
|
||||
|
||||
static bool speaker_app_music_play(SpeakerDebugApp* app, const char* rtttl) {
|
||||
if(music_worker_is_playing(app->music_worker)) {
|
||||
music_worker_stop(app->music_worker);
|
||||
}
|
||||
|
||||
if(!music_worker_load_rtttl_from_string(app->music_worker, rtttl)) {
|
||||
FURI_LOG_E(TAG, "Failed to load RTTTL");
|
||||
return false;
|
||||
}
|
||||
|
||||
music_worker_set_volume(app->music_worker, 1.0f);
|
||||
music_worker_start(app->music_worker);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void speaker_app_music_stop(SpeakerDebugApp* app) {
|
||||
if(music_worker_is_playing(app->music_worker)) {
|
||||
music_worker_stop(app->music_worker);
|
||||
}
|
||||
}
|
||||
|
||||
static void speaker_app_run(SpeakerDebugApp* app, const char* arg) {
|
||||
if(!arg || !speaker_app_music_play(app, arg)) {
|
||||
FURI_LOG_E(TAG, "Provided RTTTL is invalid");
|
||||
return;
|
||||
}
|
||||
|
||||
cli_add_command(app->cli, CLI_COMMAND, CliCommandFlagParallelSafe, speaker_app_cli, app);
|
||||
|
||||
SpeakerDebugAppMessage message;
|
||||
FuriStatus status;
|
||||
while(true) {
|
||||
status = furi_message_queue_get(app->message_queue, &message, FuriWaitForever);
|
||||
|
||||
if(status == FuriStatusOk) {
|
||||
if(message.type == SpeakerDebugAppMessageTypeStop) {
|
||||
speaker_app_music_stop(app);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cli_delete_command(app->cli, CLI_COMMAND);
|
||||
}
|
||||
|
||||
int32_t speaker_debug_app(void* arg) {
|
||||
SpeakerDebugApp* app = speaker_app_alloc();
|
||||
speaker_app_run(app, arg);
|
||||
speaker_app_free(app);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
App(
|
||||
appid="subghz_test",
|
||||
name="Sub-Ghz test",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
targets=["f7"],
|
||||
entry_point="subghz_test_app",
|
||||
requires=["gui"],
|
||||
stack_size=4 * 1024,
|
||||
order=50,
|
||||
fap_icon="subghz_test_10px.png",
|
||||
fap_category="Debug",
|
||||
fap_icon_assets="images",
|
||||
fap_version="0.1",
|
||||
)
|
||||
@@ -1,7 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
typedef enum {
|
||||
//SubGhzTestCustomEvent
|
||||
SubGhzTestCustomEventStartId = 100,
|
||||
SubGhzTestCustomEventSceneShowOnlyRX,
|
||||
} SubGhzTestCustomEvent;
|
||||
@@ -1,38 +0,0 @@
|
||||
#include "subghz_test_frequency.h"
|
||||
|
||||
const uint32_t subghz_frequencies_testing[] = {
|
||||
/* 300 - 348 */
|
||||
300000000,
|
||||
304500000,
|
||||
310000000,
|
||||
312025000,
|
||||
313250000,
|
||||
313625000,
|
||||
315000000,
|
||||
315225000,
|
||||
321950000,
|
||||
348000000,
|
||||
/* 387 - 464 */
|
||||
387000000,
|
||||
433075000, /* LPD433 first */
|
||||
433825000,
|
||||
433920000, /* LPD433 mid */
|
||||
434420000,
|
||||
434775000, /* LPD433 last channels */
|
||||
438900000,
|
||||
464000000,
|
||||
/* 779 - 928 */
|
||||
779000000,
|
||||
868150000,
|
||||
868350000,
|
||||
868550000,
|
||||
915000000,
|
||||
925000000,
|
||||
926500000,
|
||||
927950000,
|
||||
928000000,
|
||||
};
|
||||
|
||||
const uint32_t subghz_frequencies_count_testing =
|
||||
sizeof(subghz_frequencies_testing) / sizeof(uint32_t);
|
||||
const uint32_t subghz_frequencies_433_92_testing = 13;
|
||||
@@ -1,6 +0,0 @@
|
||||
#pragma once
|
||||
#include "../subghz_test_app_i.h"
|
||||
|
||||
extern const uint32_t subghz_frequencies_testing[];
|
||||
extern const uint32_t subghz_frequencies_count_testing;
|
||||
extern const uint32_t subghz_frequencies_433_92_testing;
|
||||
@@ -1,18 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
#define SUBGHZ_TEST_VERSION_APP "0.1"
|
||||
#define SUBGHZ_TEST_DEVELOPED "SkorP"
|
||||
#define SUBGHZ_TEST_GITHUB "https://github.com/flipperdevices/flipperzero-firmware"
|
||||
|
||||
typedef enum {
|
||||
SubGhzTestViewVariableItemList,
|
||||
SubGhzTestViewSubmenu,
|
||||
SubGhzTestViewStatic,
|
||||
SubGhzTestViewCarrier,
|
||||
SubGhzTestViewPacket,
|
||||
SubGhzTestViewWidget,
|
||||
SubGhzTestViewPopup,
|
||||
} SubGhzTestView;
|
||||
@@ -1,244 +0,0 @@
|
||||
#include "math.h"
|
||||
|
||||
uint64_t subghz_protocol_blocks_reverse_key(uint64_t key, uint8_t bit_count) {
|
||||
uint64_t reverse_key = 0;
|
||||
for(uint8_t i = 0; i < bit_count; i++) {
|
||||
reverse_key = reverse_key << 1 | bit_read(key, i);
|
||||
}
|
||||
return reverse_key;
|
||||
}
|
||||
|
||||
uint8_t subghz_protocol_blocks_get_parity(uint64_t key, uint8_t bit_count) {
|
||||
uint8_t parity = 0;
|
||||
for(uint8_t i = 0; i < bit_count; i++) {
|
||||
parity += bit_read(key, i);
|
||||
}
|
||||
return parity & 0x01;
|
||||
}
|
||||
|
||||
uint8_t subghz_protocol_blocks_crc4(
|
||||
uint8_t const message[],
|
||||
size_t size,
|
||||
uint8_t polynomial,
|
||||
uint8_t init) {
|
||||
uint8_t remainder = init << 4; // LSBs are unused
|
||||
uint8_t poly = polynomial << 4;
|
||||
uint8_t bit;
|
||||
|
||||
while(size--) {
|
||||
remainder ^= *message++;
|
||||
for(bit = 0; bit < 8; bit++) {
|
||||
if(remainder & 0x80) {
|
||||
remainder = (remainder << 1) ^ poly;
|
||||
} else {
|
||||
remainder = (remainder << 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return remainder >> 4 & 0x0f; // discard the LSBs
|
||||
}
|
||||
|
||||
uint8_t subghz_protocol_blocks_crc7(
|
||||
uint8_t const message[],
|
||||
size_t size,
|
||||
uint8_t polynomial,
|
||||
uint8_t init) {
|
||||
uint8_t remainder = init << 1; // LSB is unused
|
||||
uint8_t poly = polynomial << 1;
|
||||
|
||||
for(size_t byte = 0; byte < size; ++byte) {
|
||||
remainder ^= message[byte];
|
||||
for(uint8_t bit = 0; bit < 8; ++bit) {
|
||||
if(remainder & 0x80) {
|
||||
remainder = (remainder << 1) ^ poly;
|
||||
} else {
|
||||
remainder = (remainder << 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return remainder >> 1 & 0x7f; // discard the LSB
|
||||
}
|
||||
|
||||
uint8_t subghz_protocol_blocks_crc8(
|
||||
uint8_t const message[],
|
||||
size_t size,
|
||||
uint8_t polynomial,
|
||||
uint8_t init) {
|
||||
uint8_t remainder = init;
|
||||
|
||||
for(size_t byte = 0; byte < size; ++byte) {
|
||||
remainder ^= message[byte];
|
||||
for(uint8_t bit = 0; bit < 8; ++bit) {
|
||||
if(remainder & 0x80) {
|
||||
remainder = (remainder << 1) ^ polynomial;
|
||||
} else {
|
||||
remainder = (remainder << 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return remainder;
|
||||
}
|
||||
|
||||
uint8_t subghz_protocol_blocks_crc8le(
|
||||
uint8_t const message[],
|
||||
size_t size,
|
||||
uint8_t polynomial,
|
||||
uint8_t init) {
|
||||
uint8_t remainder = subghz_protocol_blocks_reverse_key(init, 8);
|
||||
polynomial = subghz_protocol_blocks_reverse_key(polynomial, 8);
|
||||
|
||||
for(size_t byte = 0; byte < size; ++byte) {
|
||||
remainder ^= message[byte];
|
||||
for(uint8_t bit = 0; bit < 8; ++bit) {
|
||||
if(remainder & 1) {
|
||||
remainder = (remainder >> 1) ^ polynomial;
|
||||
} else {
|
||||
remainder = (remainder >> 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return remainder;
|
||||
}
|
||||
|
||||
uint16_t subghz_protocol_blocks_crc16lsb(
|
||||
uint8_t const message[],
|
||||
size_t size,
|
||||
uint16_t polynomial,
|
||||
uint16_t init) {
|
||||
uint16_t remainder = init;
|
||||
|
||||
for(size_t byte = 0; byte < size; ++byte) {
|
||||
remainder ^= message[byte];
|
||||
for(uint8_t bit = 0; bit < 8; ++bit) {
|
||||
if(remainder & 1) {
|
||||
remainder = (remainder >> 1) ^ polynomial;
|
||||
} else {
|
||||
remainder = (remainder >> 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return remainder;
|
||||
}
|
||||
|
||||
uint16_t subghz_protocol_blocks_crc16(
|
||||
uint8_t const message[],
|
||||
size_t size,
|
||||
uint16_t polynomial,
|
||||
uint16_t init) {
|
||||
uint16_t remainder = init;
|
||||
|
||||
for(size_t byte = 0; byte < size; ++byte) {
|
||||
remainder ^= message[byte] << 8;
|
||||
for(uint8_t bit = 0; bit < 8; ++bit) {
|
||||
if(remainder & 0x8000) {
|
||||
remainder = (remainder << 1) ^ polynomial;
|
||||
} else {
|
||||
remainder = (remainder << 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return remainder;
|
||||
}
|
||||
|
||||
uint8_t subghz_protocol_blocks_lfsr_digest8(
|
||||
uint8_t const message[],
|
||||
size_t size,
|
||||
uint8_t gen,
|
||||
uint8_t key) {
|
||||
uint8_t sum = 0;
|
||||
for(size_t byte = 0; byte < size; ++byte) {
|
||||
uint8_t data = message[byte];
|
||||
for(int i = 7; i >= 0; --i) {
|
||||
// XOR key into sum if data bit is set
|
||||
if((data >> i) & 1) sum ^= key;
|
||||
|
||||
// roll the key right (actually the LSB is dropped here)
|
||||
// and apply the gen (needs to include the dropped LSB as MSB)
|
||||
if(key & 1)
|
||||
key = (key >> 1) ^ gen;
|
||||
else
|
||||
key = (key >> 1);
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
uint8_t subghz_protocol_blocks_lfsr_digest8_reflect(
|
||||
uint8_t const message[],
|
||||
size_t size,
|
||||
uint8_t gen,
|
||||
uint8_t key) {
|
||||
uint8_t sum = 0;
|
||||
// Process message from last byte to first byte (reflected)
|
||||
for(int byte = size - 1; byte >= 0; --byte) {
|
||||
uint8_t data = message[byte];
|
||||
// Process individual bits of each byte (reflected)
|
||||
for(uint8_t i = 0; i < 8; ++i) {
|
||||
// XOR key into sum if data bit is set
|
||||
if((data >> i) & 1) {
|
||||
sum ^= key;
|
||||
}
|
||||
|
||||
// roll the key left (actually the LSB is dropped here)
|
||||
// and apply the gen (needs to include the dropped lsb as MSB)
|
||||
if(key & 0x80)
|
||||
key = (key << 1) ^ gen;
|
||||
else
|
||||
key = (key << 1);
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
uint16_t subghz_protocol_blocks_lfsr_digest16(
|
||||
uint8_t const message[],
|
||||
size_t size,
|
||||
uint16_t gen,
|
||||
uint16_t key) {
|
||||
uint16_t sum = 0;
|
||||
for(size_t byte = 0; byte < size; ++byte) {
|
||||
uint8_t data = message[byte];
|
||||
for(int8_t i = 7; i >= 0; --i) {
|
||||
// if data bit is set then xor with key
|
||||
if((data >> i) & 1) sum ^= key;
|
||||
|
||||
// roll the key right (actually the LSB is dropped here)
|
||||
// and apply the gen (needs to include the dropped LSB as MSB)
|
||||
if(key & 1)
|
||||
key = (key >> 1) ^ gen;
|
||||
else
|
||||
key = (key >> 1);
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
uint8_t subghz_protocol_blocks_add_bytes(uint8_t const message[], size_t size) {
|
||||
uint32_t result = 0;
|
||||
for(size_t i = 0; i < size; ++i) {
|
||||
result += message[i];
|
||||
}
|
||||
return (uint8_t)result;
|
||||
}
|
||||
|
||||
uint8_t subghz_protocol_blocks_parity8(uint8_t byte) {
|
||||
byte ^= byte >> 4;
|
||||
byte &= 0xf;
|
||||
return (0x6996 >> byte) & 1;
|
||||
}
|
||||
|
||||
uint8_t subghz_protocol_blocks_parity_bytes(uint8_t const message[], size_t size) {
|
||||
uint8_t result = 0;
|
||||
for(size_t i = 0; i < size; ++i) {
|
||||
result ^= subghz_protocol_blocks_parity8(message[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t subghz_protocol_blocks_xor_bytes(uint8_t const message[], size_t size) {
|
||||
uint8_t result = 0;
|
||||
for(size_t i = 0; i < size; ++i) {
|
||||
result ^= message[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -1,222 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define bit_read(value, bit) (((value) >> (bit)) & 0x01)
|
||||
#define bit_set(value, bit) \
|
||||
({ \
|
||||
__typeof__(value) _one = (1); \
|
||||
(value) |= (_one << (bit)); \
|
||||
})
|
||||
#define bit_clear(value, bit) \
|
||||
({ \
|
||||
__typeof__(value) _one = (1); \
|
||||
(value) &= ~(_one << (bit)); \
|
||||
})
|
||||
#define bit_write(value, bit, bitvalue) (bitvalue ? bit_set(value, bit) : bit_clear(value, bit))
|
||||
#define DURATION_DIFF(x, y) (((x) < (y)) ? ((y) - (x)) : ((x) - (y)))
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Flip the data bitwise
|
||||
*
|
||||
* @param key In data
|
||||
* @param bit_count number of data bits
|
||||
*
|
||||
* @return Reverse data
|
||||
*/
|
||||
uint64_t subghz_protocol_blocks_reverse_key(uint64_t key, uint8_t bit_count);
|
||||
|
||||
/** Get parity the data bitwise
|
||||
*
|
||||
* @param key In data
|
||||
* @param bit_count number of data bits
|
||||
*
|
||||
* @return parity
|
||||
*/
|
||||
uint8_t subghz_protocol_blocks_get_parity(uint64_t key, uint8_t bit_count);
|
||||
|
||||
/** CRC-4
|
||||
*
|
||||
* @param message array of bytes to check
|
||||
* @param size number of bytes in message
|
||||
* @param polynomial CRC polynomial
|
||||
* @param init starting crc value
|
||||
*
|
||||
* @return CRC value
|
||||
*/
|
||||
uint8_t subghz_protocol_blocks_crc4(
|
||||
uint8_t const message[],
|
||||
size_t size,
|
||||
uint8_t polynomial,
|
||||
uint8_t init);
|
||||
|
||||
/** CRC-7
|
||||
*
|
||||
* @param message array of bytes to check
|
||||
* @param size number of bytes in message
|
||||
* @param polynomial CRC polynomial
|
||||
* @param init starting crc value
|
||||
*
|
||||
* @return CRC value
|
||||
*/
|
||||
uint8_t subghz_protocol_blocks_crc7(
|
||||
uint8_t const message[],
|
||||
size_t size,
|
||||
uint8_t polynomial,
|
||||
uint8_t init);
|
||||
|
||||
/** Generic Cyclic Redundancy Check CRC-8. Example polynomial: 0x31 = x8 + x5 +
|
||||
* x4 + 1 (x8 is implicit) Example polynomial: 0x80 = x8 + x7 (a normal
|
||||
* bit-by-bit parity XOR)
|
||||
*
|
||||
* @param message array of bytes to check
|
||||
* @param size number of bytes in message
|
||||
* @param polynomial byte is from x^7 to x^0 (x^8 is implicitly one)
|
||||
* @param init starting crc value
|
||||
*
|
||||
* @return CRC value
|
||||
*/
|
||||
uint8_t subghz_protocol_blocks_crc8(
|
||||
uint8_t const message[],
|
||||
size_t size,
|
||||
uint8_t polynomial,
|
||||
uint8_t init);
|
||||
|
||||
/** "Little-endian" Cyclic Redundancy Check CRC-8 LE Input and output are
|
||||
* reflected, i.e. least significant bit is shifted in first
|
||||
*
|
||||
* @param message array of bytes to check
|
||||
* @param size number of bytes in message
|
||||
* @param polynomial CRC polynomial
|
||||
* @param init starting crc value
|
||||
*
|
||||
* @return CRC value
|
||||
*/
|
||||
uint8_t subghz_protocol_blocks_crc8le(
|
||||
uint8_t const message[],
|
||||
size_t size,
|
||||
uint8_t polynomial,
|
||||
uint8_t init);
|
||||
|
||||
/** CRC-16 LSB. Input and output are reflected, i.e. least significant bit is
|
||||
* shifted in first. Note that poly and init already need to be reflected
|
||||
*
|
||||
* @param message array of bytes to check
|
||||
* @param size number of bytes in message
|
||||
* @param polynomial CRC polynomial
|
||||
* @param init starting crc value
|
||||
*
|
||||
* @return CRC value
|
||||
*/
|
||||
uint16_t subghz_protocol_blocks_crc16lsb(
|
||||
uint8_t const message[],
|
||||
size_t size,
|
||||
uint16_t polynomial,
|
||||
uint16_t init);
|
||||
|
||||
/** CRC-16
|
||||
*
|
||||
* @param message array of bytes to check
|
||||
* @param size number of bytes in message
|
||||
* @param polynomial CRC polynomial
|
||||
* @param init starting crc value
|
||||
*
|
||||
* @return CRC value
|
||||
*/
|
||||
uint16_t subghz_protocol_blocks_crc16(
|
||||
uint8_t const message[],
|
||||
size_t size,
|
||||
uint16_t polynomial,
|
||||
uint16_t init);
|
||||
|
||||
/** Digest-8 by "LFSR-based Toeplitz hash"
|
||||
*
|
||||
* @param message bytes of message data
|
||||
* @param size number of bytes to digest
|
||||
* @param gen key stream generator, needs to includes the MSB if the
|
||||
* LFSR is rolling
|
||||
* @param key initial key
|
||||
*
|
||||
* @return digest value
|
||||
*/
|
||||
uint8_t subghz_protocol_blocks_lfsr_digest8(
|
||||
uint8_t const message[],
|
||||
size_t size,
|
||||
uint8_t gen,
|
||||
uint8_t key);
|
||||
|
||||
/** Digest-8 by "LFSR-based Toeplitz hash", byte reflect, bit reflect
|
||||
*
|
||||
* @param message bytes of message data
|
||||
* @param size number of bytes to digest
|
||||
* @param gen key stream generator, needs to includes the MSB if the
|
||||
* LFSR is rolling
|
||||
* @param key initial key
|
||||
*
|
||||
* @return digest value
|
||||
*/
|
||||
uint8_t subghz_protocol_blocks_lfsr_digest8_reflect(
|
||||
uint8_t const message[],
|
||||
size_t size,
|
||||
uint8_t gen,
|
||||
uint8_t key);
|
||||
|
||||
/** Digest-16 by "LFSR-based Toeplitz hash"
|
||||
*
|
||||
* @param message bytes of message data
|
||||
* @param size number of bytes to digest
|
||||
* @param gen key stream generator, needs to includes the MSB if the
|
||||
* LFSR is rolling
|
||||
* @param key initial key
|
||||
*
|
||||
* @return digest value
|
||||
*/
|
||||
uint16_t subghz_protocol_blocks_lfsr_digest16(
|
||||
uint8_t const message[],
|
||||
size_t size,
|
||||
uint16_t gen,
|
||||
uint16_t key);
|
||||
|
||||
/** Compute Addition of a number of bytes
|
||||
*
|
||||
* @param message bytes of message data
|
||||
* @param size number of bytes to sum
|
||||
*
|
||||
* @return summation value
|
||||
*/
|
||||
uint8_t subghz_protocol_blocks_add_bytes(uint8_t const message[], size_t size);
|
||||
|
||||
/** Compute bit parity of a single byte (8 bits)
|
||||
*
|
||||
* @param byte single byte to check
|
||||
*
|
||||
* @return 1 odd parity, 0 even parity
|
||||
*/
|
||||
uint8_t subghz_protocol_blocks_parity8(uint8_t byte);
|
||||
|
||||
/** Compute bit parity of a number of bytes
|
||||
*
|
||||
* @param message bytes of message data
|
||||
* @param size number of bytes to sum
|
||||
*
|
||||
* @return 1 odd parity, 0 even parity
|
||||
*/
|
||||
uint8_t subghz_protocol_blocks_parity_bytes(uint8_t const message[], size_t size);
|
||||
|
||||
/** Compute XOR (byte-wide parity) of a number of bytes
|
||||
*
|
||||
* @param message bytes of message data
|
||||
* @param size number of bytes to sum
|
||||
*
|
||||
* @return summation value, per bit-position 1 odd parity, 0 even parity
|
||||
*/
|
||||
uint8_t subghz_protocol_blocks_xor_bytes(uint8_t const message[], size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,30 +0,0 @@
|
||||
#include "../subghz_test_app_i.h"
|
||||
|
||||
// Generate scene on_enter handlers array
|
||||
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter,
|
||||
void (*const subghz_test_scene_on_enter_handlers[])(void*) = {
|
||||
#include "subghz_test_scene_config.h"
|
||||
};
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_event handlers array
|
||||
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event,
|
||||
bool (*const subghz_test_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = {
|
||||
#include "subghz_test_scene_config.h"
|
||||
};
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_exit handlers array
|
||||
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit,
|
||||
void (*const subghz_test_scene_on_exit_handlers[])(void* context) = {
|
||||
#include "subghz_test_scene_config.h"
|
||||
};
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Initialize scene handlers configuration structure
|
||||
const SceneManagerHandlers subghz_test_scene_handlers = {
|
||||
.on_enter_handlers = subghz_test_scene_on_enter_handlers,
|
||||
.on_event_handlers = subghz_test_scene_on_event_handlers,
|
||||
.on_exit_handlers = subghz_test_scene_on_exit_handlers,
|
||||
.scene_num = SubGhzTestSceneNum,
|
||||
};
|
||||
@@ -1,29 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/scene_manager.h>
|
||||
|
||||
// Generate scene id and total number
|
||||
#define ADD_SCENE(prefix, name, id) SubGhzTestScene##id,
|
||||
typedef enum {
|
||||
#include "subghz_test_scene_config.h"
|
||||
SubGhzTestSceneNum,
|
||||
} SubGhzTestScene;
|
||||
#undef ADD_SCENE
|
||||
|
||||
extern const SceneManagerHandlers subghz_test_scene_handlers;
|
||||
|
||||
// Generate scene on_enter handlers declaration
|
||||
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*);
|
||||
#include "subghz_test_scene_config.h"
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_event handlers declaration
|
||||
#define ADD_SCENE(prefix, name, id) \
|
||||
bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event);
|
||||
#include "subghz_test_scene_config.h"
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_exit handlers declaration
|
||||
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context);
|
||||
#include "subghz_test_scene_config.h"
|
||||
#undef ADD_SCENE
|
||||
@@ -1,66 +0,0 @@
|
||||
#include "../subghz_test_app_i.h"
|
||||
|
||||
void subghz_test_scene_about_widget_callback(GuiButtonType result, InputType type, void* context) {
|
||||
SubGhzTestApp* app = context;
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_test_scene_about_on_enter(void* context) {
|
||||
SubGhzTestApp* app = context;
|
||||
|
||||
FuriString* temp_str;
|
||||
temp_str = furi_string_alloc();
|
||||
furi_string_printf(temp_str, "\e#%s\n", "Information");
|
||||
|
||||
furi_string_cat_printf(temp_str, "Version: %s\n", SUBGHZ_TEST_VERSION_APP);
|
||||
furi_string_cat_printf(temp_str, "Developed by: %s\n", SUBGHZ_TEST_DEVELOPED);
|
||||
furi_string_cat_printf(temp_str, "Github: %s\n\n", SUBGHZ_TEST_GITHUB);
|
||||
|
||||
furi_string_cat_printf(temp_str, "\e#%s\n", "Description");
|
||||
furi_string_cat_printf(
|
||||
temp_str,
|
||||
"This application is designed\nto test the functionality of the\nbuilt-in CC1101 module.\n\n");
|
||||
|
||||
widget_add_text_box_element(
|
||||
app->widget,
|
||||
0,
|
||||
0,
|
||||
128,
|
||||
14,
|
||||
AlignCenter,
|
||||
AlignBottom,
|
||||
"\e#\e! \e!\n",
|
||||
false);
|
||||
widget_add_text_box_element(
|
||||
app->widget,
|
||||
0,
|
||||
2,
|
||||
128,
|
||||
14,
|
||||
AlignCenter,
|
||||
AlignBottom,
|
||||
"\e#\e! Sub-Ghz Test \e!\n",
|
||||
false);
|
||||
widget_add_text_scroll_element(app->widget, 0, 16, 128, 50, furi_string_get_cstr(temp_str));
|
||||
furi_string_free(temp_str);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, SubGhzTestViewWidget);
|
||||
}
|
||||
|
||||
bool subghz_test_scene_about_on_event(void* context, SceneManagerEvent event) {
|
||||
SubGhzTestApp* app = context;
|
||||
bool consumed = false;
|
||||
UNUSED(app);
|
||||
UNUSED(event);
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void subghz_test_scene_about_on_exit(void* context) {
|
||||
SubGhzTestApp* app = context;
|
||||
|
||||
// Clear views
|
||||
widget_reset(app->widget);
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
#include "../subghz_test_app_i.h"
|
||||
|
||||
void subghz_test_scene_carrier_callback(SubGhzTestCarrierEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzTestApp* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, event);
|
||||
}
|
||||
|
||||
void subghz_test_scene_carrier_on_enter(void* context) {
|
||||
SubGhzTestApp* app = context;
|
||||
subghz_test_carrier_set_callback(
|
||||
app->subghz_test_carrier, subghz_test_scene_carrier_callback, app);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, SubGhzTestViewCarrier);
|
||||
}
|
||||
|
||||
bool subghz_test_scene_carrier_on_event(void* context, SceneManagerEvent event) {
|
||||
SubGhzTestApp* app = context;
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubGhzTestCarrierEventOnlyRx) {
|
||||
scene_manager_next_scene(app->scene_manager, SubGhzTestSceneShowOnlyRx);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void subghz_test_scene_carrier_on_exit(void* context) {
|
||||
UNUSED(context);
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
ADD_SCENE(subghz_test, start, Start)
|
||||
ADD_SCENE(subghz_test, about, About)
|
||||
ADD_SCENE(subghz_test, carrier, Carrier)
|
||||
ADD_SCENE(subghz_test, packet, Packet)
|
||||
ADD_SCENE(subghz_test, static, Static)
|
||||
ADD_SCENE(subghz_test, show_only_rx, ShowOnlyRx)
|
||||
@@ -1,29 +0,0 @@
|
||||
#include "../subghz_test_app_i.h"
|
||||
|
||||
void subghz_test_scene_packet_callback(SubGhzTestPacketEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzTestApp* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, event);
|
||||
}
|
||||
|
||||
void subghz_test_scene_packet_on_enter(void* context) {
|
||||
SubGhzTestApp* app = context;
|
||||
subghz_test_packet_set_callback(
|
||||
app->subghz_test_packet, subghz_test_scene_packet_callback, app);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, SubGhzTestViewPacket);
|
||||
}
|
||||
|
||||
bool subghz_test_scene_packet_on_event(void* context, SceneManagerEvent event) {
|
||||
SubGhzTestApp* app = context;
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubGhzTestPacketEventOnlyRx) {
|
||||
scene_manager_next_scene(app->scene_manager, SubGhzTestSceneShowOnlyRx);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void subghz_test_scene_packet_on_exit(void* context) {
|
||||
UNUSED(context);
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
#include "../subghz_test_app_i.h"
|
||||
#include <subghz_test_icons.h>
|
||||
|
||||
void subghz_test_scene_show_only_rx_popup_callback(void* context) {
|
||||
SubGhzTestApp* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, SubGhzTestCustomEventSceneShowOnlyRX);
|
||||
}
|
||||
|
||||
void subghz_test_scene_show_only_rx_on_enter(void* context) {
|
||||
SubGhzTestApp* app = context;
|
||||
|
||||
// Setup view
|
||||
Popup* popup = app->popup;
|
||||
|
||||
const char* header_text = "Transmission is blocked";
|
||||
const char* message_text = "Transmission on\nthis frequency is\nrestricted in\nyour region";
|
||||
if(!furi_hal_region_is_provisioned()) {
|
||||
header_text = "Firmware update needed";
|
||||
message_text = "Please update\nfirmware before\nusing this feature\nflipp.dev/upd";
|
||||
}
|
||||
|
||||
popup_set_header(popup, header_text, 63, 3, AlignCenter, AlignTop);
|
||||
popup_set_text(popup, message_text, 0, 17, AlignLeft, AlignTop);
|
||||
popup_set_icon(popup, 72, 17, &I_DolphinCommon_56x48);
|
||||
|
||||
popup_set_timeout(popup, 1500);
|
||||
popup_set_context(popup, app);
|
||||
popup_set_callback(popup, subghz_test_scene_show_only_rx_popup_callback);
|
||||
popup_enable_timeout(popup);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, SubGhzTestViewPopup);
|
||||
}
|
||||
|
||||
bool subghz_test_scene_show_only_rx_on_event(void* context, SceneManagerEvent event) {
|
||||
SubGhzTestApp* app = context;
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubGhzTestCustomEventSceneShowOnlyRX) {
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void subghz_test_scene_show_only_rx_on_exit(void* context) {
|
||||
SubGhzTestApp* app = context;
|
||||
Popup* popup = app->popup;
|
||||
|
||||
popup_reset(popup);
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
#include "../subghz_test_app_i.h"
|
||||
|
||||
typedef enum {
|
||||
SubmenuIndexSubGhzTestCarrier,
|
||||
SubmenuIndexSubGhzTestPacket,
|
||||
SubmenuIndexSubGhzTestStatic,
|
||||
SubmenuIndexSubGhzTestAbout,
|
||||
} SubmenuIndex;
|
||||
|
||||
void subghz_test_scene_start_submenu_callback(void* context, uint32_t index) {
|
||||
SubGhzTestApp* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void subghz_test_scene_start_on_enter(void* context) {
|
||||
SubGhzTestApp* app = context;
|
||||
Submenu* submenu = app->submenu;
|
||||
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Carrier",
|
||||
SubmenuIndexSubGhzTestCarrier,
|
||||
subghz_test_scene_start_submenu_callback,
|
||||
app);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Packet",
|
||||
SubmenuIndexSubGhzTestPacket,
|
||||
subghz_test_scene_start_submenu_callback,
|
||||
app);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Static",
|
||||
SubmenuIndexSubGhzTestStatic,
|
||||
subghz_test_scene_start_submenu_callback,
|
||||
app);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"About",
|
||||
SubmenuIndexSubGhzTestAbout,
|
||||
subghz_test_scene_start_submenu_callback,
|
||||
app);
|
||||
|
||||
submenu_set_selected_item(
|
||||
submenu, scene_manager_get_scene_state(app->scene_manager, SubGhzTestSceneStart));
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, SubGhzTestViewSubmenu);
|
||||
}
|
||||
|
||||
bool subghz_test_scene_start_on_event(void* context, SceneManagerEvent event) {
|
||||
SubGhzTestApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexSubGhzTestAbout) {
|
||||
scene_manager_next_scene(app->scene_manager, SubGhzTestSceneAbout);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexSubGhzTestCarrier) {
|
||||
scene_manager_next_scene(app->scene_manager, SubGhzTestSceneCarrier);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexSubGhzTestPacket) {
|
||||
scene_manager_next_scene(app->scene_manager, SubGhzTestScenePacket);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexSubGhzTestStatic) {
|
||||
scene_manager_next_scene(app->scene_manager, SubGhzTestSceneStatic);
|
||||
consumed = true;
|
||||
}
|
||||
scene_manager_set_scene_state(app->scene_manager, SubGhzTestSceneStart, event.event);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void subghz_test_scene_start_on_exit(void* context) {
|
||||
SubGhzTestApp* app = context;
|
||||
submenu_reset(app->submenu);
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
#include "../subghz_test_app_i.h"
|
||||
|
||||
void subghz_test_scene_static_callback(SubGhzTestStaticEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzTestApp* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, event);
|
||||
}
|
||||
|
||||
void subghz_test_scene_static_on_enter(void* context) {
|
||||
SubGhzTestApp* app = context;
|
||||
subghz_test_static_set_callback(
|
||||
app->subghz_test_static, subghz_test_scene_static_callback, app);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, SubGhzTestViewStatic);
|
||||
}
|
||||
|
||||
bool subghz_test_scene_static_on_event(void* context, SceneManagerEvent event) {
|
||||
SubGhzTestApp* app = context;
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubGhzTestStaticEventOnlyRx) {
|
||||
scene_manager_next_scene(app->scene_manager, SubGhzTestSceneShowOnlyRx);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void subghz_test_scene_static_on_exit(void* context) {
|
||||
UNUSED(context);
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 181 B |
@@ -1,139 +0,0 @@
|
||||
#include "subghz_test_app_i.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
static bool subghz_test_app_custom_event_callback(void* context, uint32_t event) {
|
||||
furi_assert(context);
|
||||
SubGhzTestApp* app = context;
|
||||
return scene_manager_handle_custom_event(app->scene_manager, event);
|
||||
}
|
||||
|
||||
static bool subghz_test_app_back_event_callback(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzTestApp* app = context;
|
||||
return scene_manager_handle_back_event(app->scene_manager);
|
||||
}
|
||||
|
||||
static void subghz_test_app_tick_event_callback(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzTestApp* app = context;
|
||||
scene_manager_handle_tick_event(app->scene_manager);
|
||||
}
|
||||
|
||||
SubGhzTestApp* subghz_test_app_alloc() {
|
||||
SubGhzTestApp* app = malloc(sizeof(SubGhzTestApp));
|
||||
|
||||
// GUI
|
||||
app->gui = furi_record_open(RECORD_GUI);
|
||||
|
||||
// View Dispatcher
|
||||
app->view_dispatcher = view_dispatcher_alloc();
|
||||
app->scene_manager = scene_manager_alloc(&subghz_test_scene_handlers, app);
|
||||
view_dispatcher_enable_queue(app->view_dispatcher);
|
||||
|
||||
view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
|
||||
view_dispatcher_set_custom_event_callback(
|
||||
app->view_dispatcher, subghz_test_app_custom_event_callback);
|
||||
view_dispatcher_set_navigation_event_callback(
|
||||
app->view_dispatcher, subghz_test_app_back_event_callback);
|
||||
view_dispatcher_set_tick_event_callback(
|
||||
app->view_dispatcher, subghz_test_app_tick_event_callback, 100);
|
||||
|
||||
view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
|
||||
|
||||
// Open Notification record
|
||||
app->notifications = furi_record_open(RECORD_NOTIFICATION);
|
||||
|
||||
// SubMenu
|
||||
app->submenu = submenu_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, SubGhzTestViewSubmenu, submenu_get_view(app->submenu));
|
||||
|
||||
// Widget
|
||||
app->widget = widget_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, SubGhzTestViewWidget, widget_get_view(app->widget));
|
||||
|
||||
// Popup
|
||||
app->popup = popup_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, SubGhzTestViewPopup, popup_get_view(app->popup));
|
||||
|
||||
// Carrier Test Module
|
||||
app->subghz_test_carrier = subghz_test_carrier_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher,
|
||||
SubGhzTestViewCarrier,
|
||||
subghz_test_carrier_get_view(app->subghz_test_carrier));
|
||||
|
||||
// Packet Test
|
||||
app->subghz_test_packet = subghz_test_packet_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher,
|
||||
SubGhzTestViewPacket,
|
||||
subghz_test_packet_get_view(app->subghz_test_packet));
|
||||
|
||||
// Static send
|
||||
app->subghz_test_static = subghz_test_static_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher,
|
||||
SubGhzTestViewStatic,
|
||||
subghz_test_static_get_view(app->subghz_test_static));
|
||||
|
||||
scene_manager_next_scene(app->scene_manager, SubGhzTestSceneStart);
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
void subghz_test_app_free(SubGhzTestApp* app) {
|
||||
furi_assert(app);
|
||||
|
||||
// Submenu
|
||||
view_dispatcher_remove_view(app->view_dispatcher, SubGhzTestViewSubmenu);
|
||||
submenu_free(app->submenu);
|
||||
|
||||
// Widget
|
||||
view_dispatcher_remove_view(app->view_dispatcher, SubGhzTestViewWidget);
|
||||
widget_free(app->widget);
|
||||
|
||||
// Popup
|
||||
view_dispatcher_remove_view(app->view_dispatcher, SubGhzTestViewPopup);
|
||||
popup_free(app->popup);
|
||||
|
||||
// Carrier Test
|
||||
view_dispatcher_remove_view(app->view_dispatcher, SubGhzTestViewCarrier);
|
||||
subghz_test_carrier_free(app->subghz_test_carrier);
|
||||
|
||||
// Packet Test
|
||||
view_dispatcher_remove_view(app->view_dispatcher, SubGhzTestViewPacket);
|
||||
subghz_test_packet_free(app->subghz_test_packet);
|
||||
|
||||
// Static
|
||||
view_dispatcher_remove_view(app->view_dispatcher, SubGhzTestViewStatic);
|
||||
subghz_test_static_free(app->subghz_test_static);
|
||||
|
||||
// View dispatcher
|
||||
view_dispatcher_free(app->view_dispatcher);
|
||||
scene_manager_free(app->scene_manager);
|
||||
|
||||
// Notifications
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
app->notifications = NULL;
|
||||
|
||||
// Close records
|
||||
furi_record_close(RECORD_GUI);
|
||||
|
||||
free(app);
|
||||
}
|
||||
|
||||
int32_t subghz_test_app(void* p) {
|
||||
UNUSED(p);
|
||||
SubGhzTestApp* subghz_test_app = subghz_test_app_alloc();
|
||||
|
||||
view_dispatcher_run(subghz_test_app->view_dispatcher);
|
||||
|
||||
subghz_test_app_free(subghz_test_app);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
#include "subghz_test_app_i.h"
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#define TAG "SubGhzTest"
|
||||
@@ -1,32 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "helpers/subghz_test_types.h"
|
||||
#include "helpers/subghz_test_event.h"
|
||||
|
||||
#include "scenes/subghz_test_scene.h"
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <gui/modules/submenu.h>
|
||||
#include <gui/modules/widget.h>
|
||||
#include <gui/modules/popup.h>
|
||||
#include <notification/notification_messages.h>
|
||||
|
||||
#include "views/subghz_test_static.h"
|
||||
#include "views/subghz_test_carrier.h"
|
||||
#include "views/subghz_test_packet.h"
|
||||
|
||||
typedef struct SubGhzTestApp SubGhzTestApp;
|
||||
|
||||
struct SubGhzTestApp {
|
||||
Gui* gui;
|
||||
ViewDispatcher* view_dispatcher;
|
||||
SceneManager* scene_manager;
|
||||
NotificationApp* notifications;
|
||||
Submenu* submenu;
|
||||
Widget* widget;
|
||||
Popup* popup;
|
||||
SubGhzTestStatic* subghz_test_static;
|
||||
SubGhzTestCarrier* subghz_test_carrier;
|
||||
SubGhzTestPacket* subghz_test_packet;
|
||||
};
|
||||
@@ -1,258 +0,0 @@
|
||||
#include "subghz_test_carrier.h"
|
||||
#include "../subghz_test_app_i.h"
|
||||
#include "../helpers/subghz_test_frequency.h"
|
||||
#include <lib/subghz/devices/cc1101_configs.h>
|
||||
|
||||
#include <math.h>
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <input/input.h>
|
||||
|
||||
struct SubGhzTestCarrier {
|
||||
View* view;
|
||||
FuriTimer* timer;
|
||||
SubGhzTestCarrierCallback callback;
|
||||
// const SubGhzDevice* radio_device;
|
||||
void* context;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
SubGhzTestCarrierModelStatusRx,
|
||||
SubGhzTestCarrierModelStatusTx,
|
||||
} SubGhzTestCarrierModelStatus;
|
||||
|
||||
typedef struct {
|
||||
uint8_t frequency;
|
||||
uint32_t real_frequency;
|
||||
FuriHalSubGhzPath path;
|
||||
float rssi;
|
||||
SubGhzTestCarrierModelStatus status;
|
||||
} SubGhzTestCarrierModel;
|
||||
|
||||
void subghz_test_carrier_set_callback(
|
||||
SubGhzTestCarrier* subghz_test_carrier,
|
||||
SubGhzTestCarrierCallback callback,
|
||||
void* context) {
|
||||
furi_assert(subghz_test_carrier);
|
||||
furi_assert(callback);
|
||||
subghz_test_carrier->callback = callback;
|
||||
subghz_test_carrier->context = context;
|
||||
}
|
||||
|
||||
void subghz_test_carrier_draw(Canvas* canvas, SubGhzTestCarrierModel* model) {
|
||||
char buffer[64];
|
||||
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str(canvas, 0, 8, "CC1101 Basic Test");
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
// Frequency
|
||||
snprintf(
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
"Freq: %03ld.%03ld.%03ld Hz",
|
||||
model->real_frequency / 1000000 % 1000,
|
||||
model->real_frequency / 1000 % 1000,
|
||||
model->real_frequency % 1000);
|
||||
canvas_draw_str(canvas, 0, 20, buffer);
|
||||
// Path
|
||||
char* path_name = "Unknown";
|
||||
if(model->path == FuriHalSubGhzPathIsolate) {
|
||||
path_name = "isolate";
|
||||
} else if(model->path == FuriHalSubGhzPath433) {
|
||||
path_name = "433MHz";
|
||||
} else if(model->path == FuriHalSubGhzPath315) {
|
||||
path_name = "315MHz";
|
||||
} else if(model->path == FuriHalSubGhzPath868) {
|
||||
path_name = "868MHz";
|
||||
}
|
||||
snprintf(buffer, sizeof(buffer), "Path: %d - %s", model->path, path_name);
|
||||
canvas_draw_str(canvas, 0, 31, buffer);
|
||||
if(model->status == SubGhzTestCarrierModelStatusRx) {
|
||||
snprintf(
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
"RSSI: %ld.%ld dBm",
|
||||
(int32_t)(model->rssi),
|
||||
(int32_t)fabs(model->rssi * 10) % 10);
|
||||
canvas_draw_str(canvas, 0, 42, buffer);
|
||||
} else {
|
||||
canvas_draw_str(canvas, 0, 42, "TX");
|
||||
}
|
||||
}
|
||||
|
||||
bool subghz_test_carrier_input(InputEvent* event, void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzTestCarrier* subghz_test_carrier = context;
|
||||
// const SubGhzDevice* radio_device = subghz_test_carrier->radio_device;
|
||||
|
||||
if(event->key == InputKeyBack || event->type != InputTypeShort) {
|
||||
return false;
|
||||
}
|
||||
|
||||
with_view_model(
|
||||
subghz_test_carrier->view,
|
||||
SubGhzTestCarrierModel * model,
|
||||
{
|
||||
furi_hal_subghz_idle();
|
||||
// subghz_devices_idle(radio_device);
|
||||
|
||||
if(event->key == InputKeyLeft) {
|
||||
if(model->frequency > 0) model->frequency--;
|
||||
} else if(event->key == InputKeyRight) {
|
||||
if(model->frequency < subghz_frequencies_count_testing - 1) model->frequency++;
|
||||
} else if(event->key == InputKeyDown) {
|
||||
if(model->path > 0) model->path--;
|
||||
} else if(event->key == InputKeyUp) {
|
||||
if(model->path < FuriHalSubGhzPath868) model->path++;
|
||||
} else if(event->key == InputKeyOk) {
|
||||
if(model->status == SubGhzTestCarrierModelStatusTx) {
|
||||
model->status = SubGhzTestCarrierModelStatusRx;
|
||||
} else {
|
||||
model->status = SubGhzTestCarrierModelStatusTx;
|
||||
}
|
||||
}
|
||||
|
||||
model->real_frequency =
|
||||
furi_hal_subghz_set_frequency(subghz_frequencies_testing[model->frequency]);
|
||||
furi_hal_subghz_set_path(model->path);
|
||||
// model->real_frequency = subghz_devices_set_frequency(
|
||||
// radio_device, subghz_frequencies_testing[model->frequency]);
|
||||
|
||||
if(model->status == SubGhzTestCarrierModelStatusRx) {
|
||||
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_subghz_rx();
|
||||
// furi_hal_gpio_init(
|
||||
// subghz_devices_get_data_gpio(radio_device),
|
||||
// GpioModeInput,
|
||||
// GpioPullNo,
|
||||
// GpioSpeedLow);
|
||||
// subghz_devices_set_rx(radio_device);
|
||||
} else {
|
||||
furi_hal_gpio_init(
|
||||
&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_write(&gpio_cc1101_g0, true);
|
||||
if(!furi_hal_subghz_tx()) {
|
||||
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
|
||||
subghz_test_carrier->callback(
|
||||
SubGhzTestCarrierEventOnlyRx, subghz_test_carrier->context);
|
||||
}
|
||||
// if(!subghz_devices_set_tx(radio_device)) {
|
||||
// furi_hal_gpio_init(
|
||||
// subghz_devices_get_data_gpio(radio_device),
|
||||
// GpioModeInput,
|
||||
// GpioPullNo,
|
||||
// GpioSpeedLow);
|
||||
// subghz_test_carrier->callback(
|
||||
// SubGhzTestCarrierEventOnlyRx, subghz_test_carrier->context);
|
||||
// }
|
||||
}
|
||||
},
|
||||
true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void subghz_test_carrier_enter(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzTestCarrier* subghz_test_carrier = context;
|
||||
// furi_assert(subghz_test_carrier->radio_device);
|
||||
// const SubGhzDevice* radio_device = subghz_test_carrier->radio_device;
|
||||
|
||||
furi_hal_subghz_reset();
|
||||
furi_hal_subghz_load_custom_preset(subghz_device_cc1101_preset_ook_650khz_async_regs);
|
||||
|
||||
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
// subghz_devices_reset(radio_device);
|
||||
// subghz_devices_load_preset(radio_device, FuriHalSubGhzPresetOok650Async, NULL);
|
||||
|
||||
// furi_hal_gpio_init(
|
||||
// subghz_devices_get_data_gpio(radio_device), GpioModeInput, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
with_view_model(
|
||||
subghz_test_carrier->view,
|
||||
SubGhzTestCarrierModel * model,
|
||||
{
|
||||
model->frequency = subghz_frequencies_433_92_testing; // 433
|
||||
model->real_frequency =
|
||||
furi_hal_subghz_set_frequency(subghz_frequencies_testing[model->frequency]);
|
||||
// model->real_frequency = subghz_devices_set_frequency(
|
||||
// radio_device, subghz_frequencies_testing[model->frequency]);
|
||||
model->path = FuriHalSubGhzPathIsolate; // isolate
|
||||
model->rssi = 0.0f;
|
||||
model->status = SubGhzTestCarrierModelStatusRx;
|
||||
},
|
||||
true);
|
||||
|
||||
furi_hal_subghz_rx();
|
||||
// subghz_devices_set_rx(radio_device);
|
||||
|
||||
furi_timer_start(subghz_test_carrier->timer, furi_kernel_get_tick_frequency() / 4);
|
||||
}
|
||||
|
||||
void subghz_test_carrier_exit(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzTestCarrier* subghz_test_carrier = context;
|
||||
|
||||
furi_timer_stop(subghz_test_carrier->timer);
|
||||
|
||||
// Reinitialize IC to default state
|
||||
furi_hal_subghz_sleep();
|
||||
// subghz_devices_sleep(subghz_test_carrier->radio_device);
|
||||
}
|
||||
|
||||
void subghz_test_carrier_rssi_timer_callback(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzTestCarrier* subghz_test_carrier = context;
|
||||
|
||||
with_view_model(
|
||||
subghz_test_carrier->view,
|
||||
SubGhzTestCarrierModel * model,
|
||||
{
|
||||
if(model->status == SubGhzTestCarrierModelStatusRx) {
|
||||
model->rssi = furi_hal_subghz_get_rssi();
|
||||
// model->rssi = subghz_devices_get_rssi(subghz_test_carrier->radio_device);
|
||||
}
|
||||
},
|
||||
false);
|
||||
}
|
||||
|
||||
SubGhzTestCarrier* subghz_test_carrier_alloc() {
|
||||
SubGhzTestCarrier* subghz_test_carrier = malloc(sizeof(SubGhzTestCarrier));
|
||||
|
||||
// View allocation and configuration
|
||||
subghz_test_carrier->view = view_alloc();
|
||||
view_allocate_model(
|
||||
subghz_test_carrier->view, ViewModelTypeLocking, sizeof(SubGhzTestCarrierModel));
|
||||
view_set_context(subghz_test_carrier->view, subghz_test_carrier);
|
||||
view_set_draw_callback(subghz_test_carrier->view, (ViewDrawCallback)subghz_test_carrier_draw);
|
||||
view_set_input_callback(subghz_test_carrier->view, subghz_test_carrier_input);
|
||||
view_set_enter_callback(subghz_test_carrier->view, subghz_test_carrier_enter);
|
||||
view_set_exit_callback(subghz_test_carrier->view, subghz_test_carrier_exit);
|
||||
|
||||
subghz_test_carrier->timer = furi_timer_alloc(
|
||||
subghz_test_carrier_rssi_timer_callback, FuriTimerTypePeriodic, subghz_test_carrier);
|
||||
|
||||
return subghz_test_carrier;
|
||||
}
|
||||
|
||||
void subghz_test_carrier_free(SubGhzTestCarrier* subghz_test_carrier) {
|
||||
furi_assert(subghz_test_carrier);
|
||||
furi_timer_free(subghz_test_carrier->timer);
|
||||
view_free(subghz_test_carrier->view);
|
||||
free(subghz_test_carrier);
|
||||
}
|
||||
|
||||
View* subghz_test_carrier_get_view(SubGhzTestCarrier* subghz_test_carrier) {
|
||||
furi_assert(subghz_test_carrier);
|
||||
return subghz_test_carrier->view;
|
||||
}
|
||||
|
||||
// void subghz_test_carrier_set_radio(
|
||||
// SubGhzTestCarrier* subghz_test_carrier,
|
||||
// const SubGhzDevice* radio_device) {
|
||||
// furi_assert(subghz_test_carrier);
|
||||
// subghz_test_carrier->radio_device = radio_device;
|
||||
// }
|
||||
@@ -3,6 +3,7 @@ App(
|
||||
name="Text Box Test",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
entry_point="text_box_test_app",
|
||||
cdefines=["APP_TEXT_BOX_TEST"],
|
||||
requires=["gui"],
|
||||
stack_size=1 * 1024,
|
||||
order=140,
|
||||
|
||||
@@ -53,17 +53,15 @@ static void (*text_box_test_render[])(Canvas* canvas) = {
|
||||
|
||||
typedef struct {
|
||||
uint32_t idx;
|
||||
FuriMutex* mutex;
|
||||
} TextBoxTestState;
|
||||
|
||||
static void text_box_test_render_callback(Canvas* canvas, void* ctx) {
|
||||
TextBoxTestState* state = ctx;
|
||||
furi_mutex_acquire(state->mutex, FuriWaitForever);
|
||||
TextBoxTestState* state = acquire_mutex((ValueMutex*)ctx, 25);
|
||||
canvas_clear(canvas);
|
||||
|
||||
text_box_test_render[state->idx](canvas);
|
||||
|
||||
furi_mutex_release(state->mutex);
|
||||
release_mutex((ValueMutex*)ctx, state);
|
||||
}
|
||||
|
||||
static void text_box_test_input_callback(InputEvent* input_event, void* ctx) {
|
||||
@@ -76,17 +74,17 @@ int32_t text_box_test_app(void* p) {
|
||||
FuriMessageQueue* event_queue = furi_message_queue_alloc(32, sizeof(InputEvent));
|
||||
furi_check(event_queue);
|
||||
|
||||
TextBoxTestState state = {.idx = 0, .mutex = NULL};
|
||||
state.mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
TextBoxTestState _state = {.idx = 0};
|
||||
|
||||
if(!state.mutex) {
|
||||
ValueMutex state_mutex;
|
||||
if(!init_mutex(&state_mutex, &_state, sizeof(TextBoxTestState))) {
|
||||
FURI_LOG_E(TAG, "Cannot create mutex");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ViewPort* view_port = view_port_alloc();
|
||||
|
||||
view_port_draw_callback_set(view_port, text_box_test_render_callback, &state);
|
||||
view_port_draw_callback_set(view_port, text_box_test_render_callback, &state_mutex);
|
||||
view_port_input_callback_set(view_port, text_box_test_input_callback, event_queue);
|
||||
|
||||
// Open GUI and register view_port
|
||||
@@ -96,24 +94,24 @@ int32_t text_box_test_app(void* p) {
|
||||
uint32_t test_renders_num = COUNT_OF(text_box_test_render);
|
||||
InputEvent event;
|
||||
while(furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk) {
|
||||
furi_mutex_acquire(state.mutex, FuriWaitForever);
|
||||
TextBoxTestState* state = acquire_mutex_block(&state_mutex);
|
||||
|
||||
if(event.type == InputTypeShort) {
|
||||
if(event.key == InputKeyRight) {
|
||||
if(state.idx < test_renders_num - 1) {
|
||||
state.idx++;
|
||||
if(state->idx < test_renders_num - 1) {
|
||||
state->idx++;
|
||||
}
|
||||
} else if(event.key == InputKeyLeft) {
|
||||
if(state.idx > 0) {
|
||||
state.idx--;
|
||||
if(state->idx > 0) {
|
||||
state->idx--;
|
||||
}
|
||||
} else if(event.key == InputKeyBack) {
|
||||
furi_mutex_release(state.mutex);
|
||||
release_mutex(&state_mutex, state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
furi_mutex_release(state.mutex);
|
||||
release_mutex(&state_mutex, state);
|
||||
view_port_update(view_port);
|
||||
}
|
||||
|
||||
@@ -121,7 +119,7 @@ int32_t text_box_test_app(void* p) {
|
||||
gui_remove_view_port(gui, view_port);
|
||||
view_port_free(view_port);
|
||||
furi_message_queue_free(event_queue);
|
||||
furi_mutex_free(state.mutex);
|
||||
delete_mutex(&state_mutex);
|
||||
|
||||
furi_record_close(RECORD_GUI);
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
App(
|
||||
appid="uart_echo",
|
||||
appid="UART_Echo",
|
||||
name="UART Echo",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="uart_echo_app",
|
||||
cdefines=["APP_UART_ECHO"],
|
||||
requires=["gui"],
|
||||
stack_size=2 * 1024,
|
||||
order=70,
|
||||
fap_icon="uart_10px.png",
|
||||
fap_category="Debug",
|
||||
fap_category="GPIO",
|
||||
)
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <notification/notification.h>
|
||||
#include <notification/notification_messages.h>
|
||||
#include <gui/elements.h>
|
||||
#include <furi_hal_uart.h>
|
||||
#include <furi_hal_console.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/modules/dialog_ex.h>
|
||||
|
||||
#include <notification/notification.h>
|
||||
#include <notification/notification_messages.h>
|
||||
|
||||
#define LINES_ON_SCREEN 6
|
||||
#define COLUMNS_ON_SCREEN 21
|
||||
#define TAG "UartEcho"
|
||||
#define DEFAULT_BAUD_RATE 230400
|
||||
|
||||
typedef struct UartDumpModel UartDumpModel;
|
||||
|
||||
@@ -23,7 +20,6 @@ typedef struct {
|
||||
View* view;
|
||||
FuriThread* worker_thread;
|
||||
FuriStreamBuffer* rx_stream;
|
||||
FuriHalSerialHandle* serial_handle;
|
||||
} UartEchoApp;
|
||||
|
||||
typedef struct {
|
||||
@@ -41,16 +37,10 @@ struct UartDumpModel {
|
||||
typedef enum {
|
||||
WorkerEventReserved = (1 << 0), // Reserved for StreamBuffer internal event
|
||||
WorkerEventStop = (1 << 1),
|
||||
WorkerEventRxData = (1 << 2),
|
||||
WorkerEventRxIdle = (1 << 3),
|
||||
WorkerEventRxOverrunError = (1 << 4),
|
||||
WorkerEventRxFramingError = (1 << 5),
|
||||
WorkerEventRxNoiseError = (1 << 6),
|
||||
WorkerEventRx = (1 << 2),
|
||||
} WorkerEventFlags;
|
||||
|
||||
#define WORKER_EVENTS_MASK \
|
||||
(WorkerEventStop | WorkerEventRxData | WorkerEventRxIdle | WorkerEventRxOverrunError | \
|
||||
WorkerEventRxFramingError | WorkerEventRxNoiseError)
|
||||
#define WORKER_EVENTS_MASK (WorkerEventStop | WorkerEventRx)
|
||||
|
||||
const NotificationSequence sequence_notification = {
|
||||
&message_display_backlight_on,
|
||||
@@ -99,39 +89,14 @@ static uint32_t uart_echo_exit(void* context) {
|
||||
return VIEW_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
uart_echo_on_irq_cb(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* context) {
|
||||
static void uart_echo_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
|
||||
furi_assert(context);
|
||||
UNUSED(handle);
|
||||
UartEchoApp* app = context;
|
||||
volatile FuriHalSerialRxEvent event_copy = event;
|
||||
UNUSED(event_copy);
|
||||
|
||||
WorkerEventFlags flag = 0;
|
||||
|
||||
if(event & FuriHalSerialRxEventData) {
|
||||
uint8_t data = furi_hal_serial_async_rx(handle);
|
||||
if(ev == UartIrqEventRXNE) {
|
||||
furi_stream_buffer_send(app->rx_stream, &data, 1, 0);
|
||||
flag |= WorkerEventRxData;
|
||||
furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventRx);
|
||||
}
|
||||
|
||||
if(event & FuriHalSerialRxEventIdle) {
|
||||
//idle line detected, packet transmission may have ended
|
||||
flag |= WorkerEventRxIdle;
|
||||
}
|
||||
|
||||
//error detected
|
||||
if(event & FuriHalSerialRxEventFrameError) {
|
||||
flag |= WorkerEventRxFramingError;
|
||||
}
|
||||
if(event & FuriHalSerialRxEventNoiseError) {
|
||||
flag |= WorkerEventRxNoiseError;
|
||||
}
|
||||
if(event & FuriHalSerialRxEventOverrunError) {
|
||||
flag |= WorkerEventRxOverrunError;
|
||||
}
|
||||
|
||||
furi_thread_flags_set(furi_thread_get_id(app->worker_thread), flag);
|
||||
}
|
||||
|
||||
static void uart_echo_push_to_list(UartDumpModel* model, const char data) {
|
||||
@@ -186,13 +151,13 @@ static int32_t uart_echo_worker(void* context) {
|
||||
furi_check((events & FuriFlagError) == 0);
|
||||
|
||||
if(events & WorkerEventStop) break;
|
||||
if(events & WorkerEventRxData) {
|
||||
if(events & WorkerEventRx) {
|
||||
size_t length = 0;
|
||||
do {
|
||||
uint8_t data[64];
|
||||
length = furi_stream_buffer_receive(app->rx_stream, data, 64, 0);
|
||||
if(length > 0) {
|
||||
furi_hal_serial_tx(app->serial_handle, data, length);
|
||||
furi_hal_uart_tx(FuriHalUartIdUSART1, data, length);
|
||||
with_view_model(
|
||||
app->view,
|
||||
UartDumpModel * model,
|
||||
@@ -209,29 +174,12 @@ static int32_t uart_echo_worker(void* context) {
|
||||
with_view_model(
|
||||
app->view, UartDumpModel * model, { UNUSED(model); }, true);
|
||||
}
|
||||
|
||||
if(events & WorkerEventRxIdle) {
|
||||
furi_hal_serial_tx(app->serial_handle, (uint8_t*)"\r\nDetect IDLE\r\n", 15);
|
||||
}
|
||||
|
||||
if(events &
|
||||
(WorkerEventRxOverrunError | WorkerEventRxFramingError | WorkerEventRxNoiseError)) {
|
||||
if(events & WorkerEventRxOverrunError) {
|
||||
furi_hal_serial_tx(app->serial_handle, (uint8_t*)"\r\nDetect ORE\r\n", 14);
|
||||
}
|
||||
if(events & WorkerEventRxFramingError) {
|
||||
furi_hal_serial_tx(app->serial_handle, (uint8_t*)"\r\nDetect FE\r\n", 13);
|
||||
}
|
||||
if(events & WorkerEventRxNoiseError) {
|
||||
furi_hal_serial_tx(app->serial_handle, (uint8_t*)"\r\nDetect NE\r\n", 13);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static UartEchoApp* uart_echo_app_alloc(uint32_t baudrate) {
|
||||
static UartEchoApp* uart_echo_app_alloc() {
|
||||
UartEchoApp* app = malloc(sizeof(UartEchoApp));
|
||||
|
||||
app->rx_stream = furi_stream_buffer_alloc(2048, 1);
|
||||
@@ -271,11 +219,9 @@ static UartEchoApp* uart_echo_app_alloc(uint32_t baudrate) {
|
||||
furi_thread_start(app->worker_thread);
|
||||
|
||||
// Enable uart listener
|
||||
app->serial_handle = furi_hal_serial_control_acquire(FuriHalSerialIdUsart);
|
||||
furi_check(app->serial_handle);
|
||||
furi_hal_serial_init(app->serial_handle, baudrate);
|
||||
|
||||
furi_hal_serial_async_rx_start(app->serial_handle, uart_echo_on_irq_cb, app, true);
|
||||
furi_hal_console_disable();
|
||||
furi_hal_uart_set_br(FuriHalUartIdUSART1, 115200);
|
||||
furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, uart_echo_on_irq_cb, app);
|
||||
|
||||
return app;
|
||||
}
|
||||
@@ -283,9 +229,7 @@ static UartEchoApp* uart_echo_app_alloc(uint32_t baudrate) {
|
||||
static void uart_echo_app_free(UartEchoApp* app) {
|
||||
furi_assert(app);
|
||||
|
||||
furi_hal_serial_async_rx_stop(app->serial_handle);
|
||||
furi_hal_serial_deinit(app->serial_handle);
|
||||
furi_hal_serial_control_release(app->serial_handle);
|
||||
furi_hal_console_enable(); // this will also clear IRQ callback so thread is no longer referenced
|
||||
|
||||
furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventStop);
|
||||
furi_thread_join(app->worker_thread);
|
||||
@@ -319,18 +263,8 @@ static void uart_echo_app_free(UartEchoApp* app) {
|
||||
}
|
||||
|
||||
int32_t uart_echo_app(void* p) {
|
||||
uint32_t baudrate = DEFAULT_BAUD_RATE;
|
||||
if(p) {
|
||||
const char* baudrate_str = p;
|
||||
if(sscanf(baudrate_str, "%lu", &baudrate) != 1) {
|
||||
FURI_LOG_E(TAG, "Invalid baudrate: %s", baudrate_str);
|
||||
baudrate = DEFAULT_BAUD_RATE;
|
||||
}
|
||||
}
|
||||
|
||||
FURI_LOG_I(TAG, "Using baudrate: %lu", baudrate);
|
||||
|
||||
UartEchoApp* app = uart_echo_app_alloc(baudrate);
|
||||
UNUSED(p);
|
||||
UartEchoApp* app = uart_echo_app_alloc();
|
||||
view_dispatcher_run(app->view_dispatcher);
|
||||
uart_echo_app_free(app);
|
||||
return 0;
|
||||
|
||||
@@ -3,9 +3,7 @@ App(
|
||||
apptype=FlipperAppType.STARTUP,
|
||||
entry_point="unit_tests_on_system_start",
|
||||
cdefines=["APP_UNIT_TESTS"],
|
||||
requires=["system_settings"],
|
||||
provides=["delay_test"],
|
||||
resources="resources",
|
||||
order=100,
|
||||
)
|
||||
|
||||
|
||||
@@ -1,740 +0,0 @@
|
||||
#include <furi.h>
|
||||
#include "../minunit.h"
|
||||
#include <bit_lib/bit_lib.h>
|
||||
|
||||
MU_TEST(test_bit_lib_increment_index) {
|
||||
uint32_t index = 0;
|
||||
|
||||
// test increment
|
||||
for(uint32_t i = 0; i < 31; ++i) {
|
||||
bit_lib_increment_index(index, 32);
|
||||
mu_assert_int_eq(i + 1, index);
|
||||
}
|
||||
|
||||
// test wrap around
|
||||
for(uint32_t i = 0; i < 512; ++i) {
|
||||
bit_lib_increment_index(index, 32);
|
||||
mu_assert_int_less_than(32, index);
|
||||
}
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_is_set) {
|
||||
uint32_t value = 0x0000FFFF;
|
||||
|
||||
for(uint32_t i = 0; i < 16; ++i) {
|
||||
mu_check(bit_lib_bit_is_set(value, i));
|
||||
mu_check(!bit_lib_bit_is_not_set(value, i));
|
||||
}
|
||||
|
||||
for(uint32_t i = 16; i < 32; ++i) {
|
||||
mu_check(!bit_lib_bit_is_set(value, i));
|
||||
mu_check(bit_lib_bit_is_not_set(value, i));
|
||||
}
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_push) {
|
||||
#define TEST_BIT_LIB_PUSH_DATA_SIZE 4
|
||||
uint8_t data[TEST_BIT_LIB_PUSH_DATA_SIZE] = {0};
|
||||
uint8_t expected_data_1[TEST_BIT_LIB_PUSH_DATA_SIZE] = {0x00, 0x00, 0x0F, 0xFF};
|
||||
uint8_t expected_data_2[TEST_BIT_LIB_PUSH_DATA_SIZE] = {0x00, 0xFF, 0xF0, 0x00};
|
||||
uint8_t expected_data_3[TEST_BIT_LIB_PUSH_DATA_SIZE] = {0xFF, 0x00, 0x00, 0xFF};
|
||||
uint8_t expected_data_4[TEST_BIT_LIB_PUSH_DATA_SIZE] = {0xFF, 0xFF, 0xFF, 0xFF};
|
||||
uint8_t expected_data_5[TEST_BIT_LIB_PUSH_DATA_SIZE] = {0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t expected_data_6[TEST_BIT_LIB_PUSH_DATA_SIZE] = {0xCC, 0xCC, 0xCC, 0xCC};
|
||||
|
||||
for(uint32_t i = 0; i < 12; ++i) {
|
||||
bit_lib_push_bit(data, TEST_BIT_LIB_PUSH_DATA_SIZE, true);
|
||||
}
|
||||
mu_assert_mem_eq(expected_data_1, data, TEST_BIT_LIB_PUSH_DATA_SIZE);
|
||||
|
||||
for(uint32_t i = 0; i < 12; ++i) {
|
||||
bit_lib_push_bit(data, TEST_BIT_LIB_PUSH_DATA_SIZE, false);
|
||||
}
|
||||
mu_assert_mem_eq(expected_data_2, data, TEST_BIT_LIB_PUSH_DATA_SIZE);
|
||||
|
||||
for(uint32_t i = 0; i < 4; ++i) {
|
||||
bit_lib_push_bit(data, TEST_BIT_LIB_PUSH_DATA_SIZE, false);
|
||||
}
|
||||
for(uint32_t i = 0; i < 8; ++i) {
|
||||
bit_lib_push_bit(data, TEST_BIT_LIB_PUSH_DATA_SIZE, true);
|
||||
}
|
||||
mu_assert_mem_eq(expected_data_3, data, TEST_BIT_LIB_PUSH_DATA_SIZE);
|
||||
|
||||
for(uint32_t i = 0; i < TEST_BIT_LIB_PUSH_DATA_SIZE * 8; ++i) {
|
||||
bit_lib_push_bit(data, TEST_BIT_LIB_PUSH_DATA_SIZE, true);
|
||||
}
|
||||
mu_assert_mem_eq(expected_data_4, data, TEST_BIT_LIB_PUSH_DATA_SIZE);
|
||||
|
||||
for(uint32_t i = 0; i < TEST_BIT_LIB_PUSH_DATA_SIZE * 8; ++i) {
|
||||
bit_lib_push_bit(data, TEST_BIT_LIB_PUSH_DATA_SIZE, false);
|
||||
}
|
||||
mu_assert_mem_eq(expected_data_5, data, TEST_BIT_LIB_PUSH_DATA_SIZE);
|
||||
|
||||
for(uint32_t i = 0; i < TEST_BIT_LIB_PUSH_DATA_SIZE * 2; ++i) {
|
||||
bit_lib_push_bit(data, TEST_BIT_LIB_PUSH_DATA_SIZE, true);
|
||||
bit_lib_push_bit(data, TEST_BIT_LIB_PUSH_DATA_SIZE, true);
|
||||
bit_lib_push_bit(data, TEST_BIT_LIB_PUSH_DATA_SIZE, false);
|
||||
bit_lib_push_bit(data, TEST_BIT_LIB_PUSH_DATA_SIZE, false);
|
||||
}
|
||||
mu_assert_mem_eq(expected_data_6, data, TEST_BIT_LIB_PUSH_DATA_SIZE);
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_set_bit) {
|
||||
uint8_t value[2] = {0x00, 0xFF};
|
||||
bit_lib_set_bit(value, 15, false);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x00, 0xFE}), 2);
|
||||
bit_lib_set_bit(value, 14, false);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x00, 0xFC}), 2);
|
||||
bit_lib_set_bit(value, 13, false);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x00, 0xF8}), 2);
|
||||
bit_lib_set_bit(value, 12, false);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x00, 0xF0}), 2);
|
||||
bit_lib_set_bit(value, 11, false);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x00, 0xE0}), 2);
|
||||
bit_lib_set_bit(value, 10, false);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x00, 0xC0}), 2);
|
||||
bit_lib_set_bit(value, 9, false);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x00, 0x80}), 2);
|
||||
bit_lib_set_bit(value, 8, false);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x00, 0x00}), 2);
|
||||
|
||||
bit_lib_set_bit(value, 7, true);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x01, 0x00}), 2);
|
||||
bit_lib_set_bit(value, 6, true);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x03, 0x00}), 2);
|
||||
bit_lib_set_bit(value, 5, true);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x07, 0x00}), 2);
|
||||
bit_lib_set_bit(value, 4, true);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x0F, 0x00}), 2);
|
||||
bit_lib_set_bit(value, 3, true);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x1F, 0x00}), 2);
|
||||
bit_lib_set_bit(value, 2, true);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x3F, 0x00}), 2);
|
||||
bit_lib_set_bit(value, 1, true);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0x7F, 0x00}), 2);
|
||||
bit_lib_set_bit(value, 0, true);
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0xFF, 0x00}), 2);
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_set_bits) {
|
||||
uint8_t value[2] = {0b00000000, 0b11111111};
|
||||
// set 4 bits to 0b0100 from 12 index
|
||||
bit_lib_set_bits(value, 12, 0b0100, 4);
|
||||
// [0100]
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0b00000000, 0b11110100}), 2);
|
||||
|
||||
// set 2 bits to 0b11 from 11 index
|
||||
bit_lib_set_bits(value, 11, 0b11, 2);
|
||||
// [11]
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0b00000000, 0b11111100}), 2);
|
||||
|
||||
// set 3 bits to 0b111 from 0 index
|
||||
bit_lib_set_bits(value, 0, 0b111, 3);
|
||||
// [111]
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0b11100000, 0b11111100}), 2);
|
||||
|
||||
// set 8 bits to 0b11111000 from 3 index
|
||||
bit_lib_set_bits(value, 3, 0b11111000, 8);
|
||||
// [11111 000]
|
||||
mu_assert_mem_eq(value, ((uint8_t[]){0b11111111, 0b00011100}), 2);
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_get_bit) {
|
||||
uint8_t value[2] = {0b00000000, 0b11111111};
|
||||
for(uint32_t i = 0; i < 8; ++i) {
|
||||
mu_check(bit_lib_get_bit(value, i) == false);
|
||||
}
|
||||
for(uint32_t i = 8; i < 16; ++i) {
|
||||
mu_check(bit_lib_get_bit(value, i) == true);
|
||||
}
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_get_bits) {
|
||||
uint8_t value[2] = {0b00000000, 0b11111111};
|
||||
mu_assert_int_eq(0b00000000, bit_lib_get_bits(value, 0, 8));
|
||||
mu_assert_int_eq(0b00000001, bit_lib_get_bits(value, 1, 8));
|
||||
mu_assert_int_eq(0b00000011, bit_lib_get_bits(value, 2, 8));
|
||||
mu_assert_int_eq(0b00000111, bit_lib_get_bits(value, 3, 8));
|
||||
mu_assert_int_eq(0b00001111, bit_lib_get_bits(value, 4, 8));
|
||||
mu_assert_int_eq(0b00011111, bit_lib_get_bits(value, 5, 8));
|
||||
mu_assert_int_eq(0b00111111, bit_lib_get_bits(value, 6, 8));
|
||||
mu_assert_int_eq(0b01111111, bit_lib_get_bits(value, 7, 8));
|
||||
mu_assert_int_eq(0b11111111, bit_lib_get_bits(value, 8, 8));
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_get_bits_16) {
|
||||
uint8_t value[2] = {0b00001001, 0b10110001};
|
||||
mu_assert_int_eq(0b0, bit_lib_get_bits_16(value, 0, 1));
|
||||
mu_assert_int_eq(0b00, bit_lib_get_bits_16(value, 0, 2));
|
||||
mu_assert_int_eq(0b000, bit_lib_get_bits_16(value, 0, 3));
|
||||
mu_assert_int_eq(0b0000, bit_lib_get_bits_16(value, 0, 4));
|
||||
mu_assert_int_eq(0b00001, bit_lib_get_bits_16(value, 0, 5));
|
||||
mu_assert_int_eq(0b000010, bit_lib_get_bits_16(value, 0, 6));
|
||||
mu_assert_int_eq(0b0000100, bit_lib_get_bits_16(value, 0, 7));
|
||||
mu_assert_int_eq(0b00001001, bit_lib_get_bits_16(value, 0, 8));
|
||||
mu_assert_int_eq(0b000010011, bit_lib_get_bits_16(value, 0, 9));
|
||||
mu_assert_int_eq(0b0000100110, bit_lib_get_bits_16(value, 0, 10));
|
||||
mu_assert_int_eq(0b00001001101, bit_lib_get_bits_16(value, 0, 11));
|
||||
mu_assert_int_eq(0b000010011011, bit_lib_get_bits_16(value, 0, 12));
|
||||
mu_assert_int_eq(0b0000100110110, bit_lib_get_bits_16(value, 0, 13));
|
||||
mu_assert_int_eq(0b00001001101100, bit_lib_get_bits_16(value, 0, 14));
|
||||
mu_assert_int_eq(0b000010011011000, bit_lib_get_bits_16(value, 0, 15));
|
||||
mu_assert_int_eq(0b0000100110110001, bit_lib_get_bits_16(value, 0, 16));
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_get_bits_32) {
|
||||
uint8_t value[4] = {0b00001001, 0b10110001, 0b10001100, 0b01100010};
|
||||
mu_assert_int_eq(0b0, bit_lib_get_bits_32(value, 0, 1));
|
||||
mu_assert_int_eq(0b00, bit_lib_get_bits_32(value, 0, 2));
|
||||
mu_assert_int_eq(0b000, bit_lib_get_bits_32(value, 0, 3));
|
||||
mu_assert_int_eq(0b0000, bit_lib_get_bits_32(value, 0, 4));
|
||||
mu_assert_int_eq(0b00001, bit_lib_get_bits_32(value, 0, 5));
|
||||
mu_assert_int_eq(0b000010, bit_lib_get_bits_32(value, 0, 6));
|
||||
mu_assert_int_eq(0b0000100, bit_lib_get_bits_32(value, 0, 7));
|
||||
mu_assert_int_eq(0b00001001, bit_lib_get_bits_32(value, 0, 8));
|
||||
mu_assert_int_eq(0b000010011, bit_lib_get_bits_32(value, 0, 9));
|
||||
mu_assert_int_eq(0b0000100110, bit_lib_get_bits_32(value, 0, 10));
|
||||
mu_assert_int_eq(0b00001001101, bit_lib_get_bits_32(value, 0, 11));
|
||||
mu_assert_int_eq(0b000010011011, bit_lib_get_bits_32(value, 0, 12));
|
||||
mu_assert_int_eq(0b0000100110110, bit_lib_get_bits_32(value, 0, 13));
|
||||
mu_assert_int_eq(0b00001001101100, bit_lib_get_bits_32(value, 0, 14));
|
||||
mu_assert_int_eq(0b000010011011000, bit_lib_get_bits_32(value, 0, 15));
|
||||
mu_assert_int_eq(0b0000100110110001, bit_lib_get_bits_32(value, 0, 16));
|
||||
mu_assert_int_eq(0b00001001101100011, bit_lib_get_bits_32(value, 0, 17));
|
||||
mu_assert_int_eq(0b000010011011000110, bit_lib_get_bits_32(value, 0, 18));
|
||||
mu_assert_int_eq(0b0000100110110001100, bit_lib_get_bits_32(value, 0, 19));
|
||||
mu_assert_int_eq(0b00001001101100011000, bit_lib_get_bits_32(value, 0, 20));
|
||||
mu_assert_int_eq(0b000010011011000110001, bit_lib_get_bits_32(value, 0, 21));
|
||||
mu_assert_int_eq(0b0000100110110001100011, bit_lib_get_bits_32(value, 0, 22));
|
||||
mu_assert_int_eq(0b00001001101100011000110, bit_lib_get_bits_32(value, 0, 23));
|
||||
mu_assert_int_eq(0b000010011011000110001100, bit_lib_get_bits_32(value, 0, 24));
|
||||
mu_assert_int_eq(0b0000100110110001100011000, bit_lib_get_bits_32(value, 0, 25));
|
||||
mu_assert_int_eq(0b00001001101100011000110001, bit_lib_get_bits_32(value, 0, 26));
|
||||
mu_assert_int_eq(0b000010011011000110001100011, bit_lib_get_bits_32(value, 0, 27));
|
||||
mu_assert_int_eq(0b0000100110110001100011000110, bit_lib_get_bits_32(value, 0, 28));
|
||||
mu_assert_int_eq(0b00001001101100011000110001100, bit_lib_get_bits_32(value, 0, 29));
|
||||
mu_assert_int_eq(0b000010011011000110001100011000, bit_lib_get_bits_32(value, 0, 30));
|
||||
mu_assert_int_eq(0b0000100110110001100011000110001, bit_lib_get_bits_32(value, 0, 31));
|
||||
mu_assert_int_eq(0b00001001101100011000110001100010, bit_lib_get_bits_32(value, 0, 32));
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_get_bits_64) {
|
||||
uint8_t value[8] = {
|
||||
0b00001001,
|
||||
0b10110001,
|
||||
0b10001100,
|
||||
0b01100010,
|
||||
0b00001001,
|
||||
0b10110001,
|
||||
0b10001100,
|
||||
0b01100010};
|
||||
mu_assert_int_eq(0b0, bit_lib_get_bits_64(value, 0, 1));
|
||||
mu_assert_int_eq(0b00, bit_lib_get_bits_64(value, 0, 2));
|
||||
mu_assert_int_eq(0b000, bit_lib_get_bits_64(value, 0, 3));
|
||||
mu_assert_int_eq(0b0000, bit_lib_get_bits_64(value, 0, 4));
|
||||
mu_assert_int_eq(0b00001, bit_lib_get_bits_64(value, 0, 5));
|
||||
mu_assert_int_eq(0b000010, bit_lib_get_bits_64(value, 0, 6));
|
||||
mu_assert_int_eq(0b0000100, bit_lib_get_bits_64(value, 0, 7));
|
||||
mu_assert_int_eq(0b00001001, bit_lib_get_bits_64(value, 0, 8));
|
||||
mu_assert_int_eq(0b000010011, bit_lib_get_bits_64(value, 0, 9));
|
||||
mu_assert_int_eq(0b0000100110, bit_lib_get_bits_64(value, 0, 10));
|
||||
mu_assert_int_eq(0b00001001101, bit_lib_get_bits_64(value, 0, 11));
|
||||
mu_assert_int_eq(0b000010011011, bit_lib_get_bits_64(value, 0, 12));
|
||||
mu_assert_int_eq(0b0000100110110, bit_lib_get_bits_64(value, 0, 13));
|
||||
mu_assert_int_eq(0b00001001101100, bit_lib_get_bits_64(value, 0, 14));
|
||||
mu_assert_int_eq(0b000010011011000, bit_lib_get_bits_64(value, 0, 15));
|
||||
mu_assert_int_eq(0b0000100110110001, bit_lib_get_bits_64(value, 0, 16));
|
||||
mu_assert_int_eq(0b00001001101100011, bit_lib_get_bits_64(value, 0, 17));
|
||||
mu_assert_int_eq(0b000010011011000110, bit_lib_get_bits_64(value, 0, 18));
|
||||
mu_assert_int_eq(0b0000100110110001100, bit_lib_get_bits_64(value, 0, 19));
|
||||
mu_assert_int_eq(0b00001001101100011000, bit_lib_get_bits_64(value, 0, 20));
|
||||
mu_assert_int_eq(0b000010011011000110001, bit_lib_get_bits_64(value, 0, 21));
|
||||
mu_assert_int_eq(0b0000100110110001100011, bit_lib_get_bits_64(value, 0, 22));
|
||||
mu_assert_int_eq(0b00001001101100011000110, bit_lib_get_bits_64(value, 0, 23));
|
||||
mu_assert_int_eq(0b000010011011000110001100, bit_lib_get_bits_64(value, 0, 24));
|
||||
mu_assert_int_eq(0b0000100110110001100011000, bit_lib_get_bits_64(value, 0, 25));
|
||||
mu_assert_int_eq(0b00001001101100011000110001, bit_lib_get_bits_64(value, 0, 26));
|
||||
mu_assert_int_eq(0b000010011011000110001100011, bit_lib_get_bits_64(value, 0, 27));
|
||||
mu_assert_int_eq(0b0000100110110001100011000110, bit_lib_get_bits_64(value, 0, 28));
|
||||
mu_assert_int_eq(0b00001001101100011000110001100, bit_lib_get_bits_64(value, 0, 29));
|
||||
mu_assert_int_eq(0b000010011011000110001100011000, bit_lib_get_bits_64(value, 0, 30));
|
||||
mu_assert_int_eq(0b0000100110110001100011000110001, bit_lib_get_bits_64(value, 0, 31));
|
||||
mu_assert_int_eq(0b00001001101100011000110001100010, bit_lib_get_bits_64(value, 0, 32));
|
||||
|
||||
uint64_t res = bit_lib_get_bits_64(value, 0, 33);
|
||||
uint64_t expected = 0b000010011011000110001100011000100;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 34);
|
||||
expected = 0b0000100110110001100011000110001000;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 35);
|
||||
expected = 0b00001001101100011000110001100010000;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 36);
|
||||
expected = 0b000010011011000110001100011000100000;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 37);
|
||||
expected = 0b0000100110110001100011000110001000001;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 38);
|
||||
expected = 0b00001001101100011000110001100010000010;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 39);
|
||||
expected = 0b000010011011000110001100011000100000100;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 40);
|
||||
expected = 0b0000100110110001100011000110001000001001;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 41);
|
||||
expected = 0b00001001101100011000110001100010000010011;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 42);
|
||||
expected = 0b000010011011000110001100011000100000100110;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 43);
|
||||
expected = 0b0000100110110001100011000110001000001001101;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 44);
|
||||
expected = 0b00001001101100011000110001100010000010011011;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 45);
|
||||
expected = 0b000010011011000110001100011000100000100110110;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 46);
|
||||
expected = 0b0000100110110001100011000110001000001001101100;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 47);
|
||||
expected = 0b00001001101100011000110001100010000010011011000;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 48);
|
||||
expected = 0b000010011011000110001100011000100000100110110001;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 49);
|
||||
expected = 0b0000100110110001100011000110001000001001101100011;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 50);
|
||||
expected = 0b00001001101100011000110001100010000010011011000110;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 51);
|
||||
expected = 0b000010011011000110001100011000100000100110110001100;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 52);
|
||||
expected = 0b0000100110110001100011000110001000001001101100011000;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 53);
|
||||
expected = 0b00001001101100011000110001100010000010011011000110001;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 54);
|
||||
expected = 0b000010011011000110001100011000100000100110110001100011;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 55);
|
||||
expected = 0b0000100110110001100011000110001000001001101100011000110;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 56);
|
||||
expected = 0b00001001101100011000110001100010000010011011000110001100;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 57);
|
||||
expected = 0b000010011011000110001100011000100000100110110001100011000;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 58);
|
||||
expected = 0b0000100110110001100011000110001000001001101100011000110001;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 59);
|
||||
expected = 0b00001001101100011000110001100010000010011011000110001100011;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 60);
|
||||
expected = 0b000010011011000110001100011000100000100110110001100011000110;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 61);
|
||||
expected = 0b0000100110110001100011000110001000001001101100011000110001100;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 62);
|
||||
expected = 0b00001001101100011000110001100010000010011011000110001100011000;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 63);
|
||||
expected = 0b000010011011000110001100011000100000100110110001100011000110001;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
|
||||
res = bit_lib_get_bits_64(value, 0, 64);
|
||||
expected = 0b0000100110110001100011000110001000001001101100011000110001100010;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_test_parity_u32) {
|
||||
// test even parity
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000000, BitLibParityEven), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000001, BitLibParityEven), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000010, BitLibParityEven), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000011, BitLibParityEven), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000100, BitLibParityEven), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000101, BitLibParityEven), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000110, BitLibParityEven), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000111, BitLibParityEven), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001000, BitLibParityEven), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001001, BitLibParityEven), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001010, BitLibParityEven), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001011, BitLibParityEven), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001100, BitLibParityEven), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001101, BitLibParityEven), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001110, BitLibParityEven), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001111, BitLibParityEven), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00010000, BitLibParityEven), 1);
|
||||
|
||||
// test odd parity
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000000, BitLibParityOdd), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000001, BitLibParityOdd), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000010, BitLibParityOdd), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000011, BitLibParityOdd), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000100, BitLibParityOdd), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000101, BitLibParityOdd), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000110, BitLibParityOdd), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000111, BitLibParityOdd), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001000, BitLibParityOdd), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001001, BitLibParityOdd), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001010, BitLibParityOdd), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001011, BitLibParityOdd), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001100, BitLibParityOdd), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001101, BitLibParityOdd), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001110, BitLibParityOdd), 0);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00001111, BitLibParityOdd), 1);
|
||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00010000, BitLibParityOdd), 0);
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_test_parity) {
|
||||
// next data contains valid parity for 1-3 nibble and invalid for 4 nibble
|
||||
uint8_t data_always_0_parity[2] = {0b11101110, 0b11101111};
|
||||
uint8_t data_always_1_parity[2] = {0b00010001, 0b00010000};
|
||||
uint8_t data_always_odd_parity[2] = {0b00000011, 0b11110111};
|
||||
uint8_t data_always_even_parity[2] = {0b00010111, 0b10110011};
|
||||
|
||||
// test alawys 0 parity
|
||||
mu_check(bit_lib_test_parity(data_always_0_parity, 0, 12, BitLibParityAlways0, 4));
|
||||
mu_check(bit_lib_test_parity(data_always_0_parity, 4, 8, BitLibParityAlways0, 4));
|
||||
mu_check(bit_lib_test_parity(data_always_0_parity, 8, 4, BitLibParityAlways0, 4));
|
||||
mu_check(bit_lib_test_parity(data_always_1_parity, 12, 4, BitLibParityAlways0, 4));
|
||||
|
||||
mu_check(!bit_lib_test_parity(data_always_0_parity, 0, 16, BitLibParityAlways0, 4));
|
||||
mu_check(!bit_lib_test_parity(data_always_0_parity, 4, 12, BitLibParityAlways0, 4));
|
||||
mu_check(!bit_lib_test_parity(data_always_0_parity, 8, 8, BitLibParityAlways0, 4));
|
||||
mu_check(!bit_lib_test_parity(data_always_0_parity, 12, 4, BitLibParityAlways0, 4));
|
||||
|
||||
// test alawys 1 parity
|
||||
mu_check(bit_lib_test_parity(data_always_1_parity, 0, 12, BitLibParityAlways1, 4));
|
||||
mu_check(bit_lib_test_parity(data_always_1_parity, 4, 8, BitLibParityAlways1, 4));
|
||||
mu_check(bit_lib_test_parity(data_always_1_parity, 8, 4, BitLibParityAlways1, 4));
|
||||
mu_check(bit_lib_test_parity(data_always_0_parity, 12, 4, BitLibParityAlways1, 4));
|
||||
|
||||
mu_check(!bit_lib_test_parity(data_always_1_parity, 0, 16, BitLibParityAlways1, 4));
|
||||
mu_check(!bit_lib_test_parity(data_always_1_parity, 4, 12, BitLibParityAlways1, 4));
|
||||
mu_check(!bit_lib_test_parity(data_always_1_parity, 8, 8, BitLibParityAlways1, 4));
|
||||
mu_check(!bit_lib_test_parity(data_always_1_parity, 12, 4, BitLibParityAlways1, 4));
|
||||
|
||||
// test odd parity
|
||||
mu_check(bit_lib_test_parity(data_always_odd_parity, 0, 12, BitLibParityOdd, 4));
|
||||
mu_check(bit_lib_test_parity(data_always_odd_parity, 4, 8, BitLibParityOdd, 4));
|
||||
mu_check(bit_lib_test_parity(data_always_odd_parity, 8, 4, BitLibParityOdd, 4));
|
||||
mu_check(bit_lib_test_parity(data_always_even_parity, 12, 4, BitLibParityOdd, 4));
|
||||
|
||||
mu_check(!bit_lib_test_parity(data_always_odd_parity, 0, 16, BitLibParityOdd, 4));
|
||||
mu_check(!bit_lib_test_parity(data_always_odd_parity, 4, 12, BitLibParityOdd, 4));
|
||||
mu_check(!bit_lib_test_parity(data_always_odd_parity, 8, 8, BitLibParityOdd, 4));
|
||||
mu_check(!bit_lib_test_parity(data_always_odd_parity, 12, 4, BitLibParityOdd, 4));
|
||||
|
||||
// test even parity
|
||||
mu_check(bit_lib_test_parity(data_always_even_parity, 0, 12, BitLibParityEven, 4));
|
||||
mu_check(bit_lib_test_parity(data_always_even_parity, 4, 8, BitLibParityEven, 4));
|
||||
mu_check(bit_lib_test_parity(data_always_even_parity, 8, 4, BitLibParityEven, 4));
|
||||
mu_check(bit_lib_test_parity(data_always_odd_parity, 12, 4, BitLibParityEven, 4));
|
||||
|
||||
mu_check(!bit_lib_test_parity(data_always_even_parity, 0, 16, BitLibParityEven, 4));
|
||||
mu_check(!bit_lib_test_parity(data_always_even_parity, 4, 12, BitLibParityEven, 4));
|
||||
mu_check(!bit_lib_test_parity(data_always_even_parity, 8, 8, BitLibParityEven, 4));
|
||||
mu_check(!bit_lib_test_parity(data_always_even_parity, 12, 4, BitLibParityEven, 4));
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_remove_bit_every_nth) {
|
||||
// TODO FL-3494: more tests
|
||||
uint8_t data_i[1] = {0b00001111};
|
||||
uint8_t data_o[1] = {0b00011111};
|
||||
size_t length;
|
||||
|
||||
length = bit_lib_remove_bit_every_nth(data_i, 0, 8, 3);
|
||||
mu_assert_int_eq(6, length);
|
||||
mu_assert_mem_eq(data_o, data_i, 1);
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_reverse_bits) {
|
||||
uint8_t data_1_i[2] = {0b11001010, 0b00011111};
|
||||
uint8_t data_1_o[2] = {0b11111000, 0b01010011};
|
||||
|
||||
// reverse bits [0..15]
|
||||
bit_lib_reverse_bits(data_1_i, 0, 16);
|
||||
mu_assert_mem_eq(data_1_o, data_1_i, 2);
|
||||
|
||||
uint8_t data_2_i[2] = {0b11001010, 0b00011111};
|
||||
uint8_t data_2_o[2] = {0b11001000, 0b01011111};
|
||||
|
||||
// reverse bits [4..11]
|
||||
bit_lib_reverse_bits(data_2_i, 4, 8);
|
||||
mu_assert_mem_eq(data_2_o, data_2_i, 2);
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_copy_bits) {
|
||||
uint8_t data_1_i[2] = {0b11001010, 0b00011111};
|
||||
uint8_t data_1_o[2] = {0};
|
||||
|
||||
// data_1_o[0..15] = data_1_i[0..15]
|
||||
bit_lib_copy_bits(data_1_o, 0, 16, data_1_i, 0);
|
||||
mu_assert_mem_eq(data_1_i, data_1_o, 2);
|
||||
|
||||
memset(data_1_o, 0, 2);
|
||||
// data_1_o[4..11] = data_1_i[0..7]
|
||||
bit_lib_copy_bits(data_1_o, 4, 8, data_1_i, 0);
|
||||
mu_assert_mem_eq(((uint8_t[]){0b00001100, 0b10100000}), data_1_o, 2);
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_get_bit_count) {
|
||||
mu_assert_int_eq(0, bit_lib_get_bit_count(0));
|
||||
mu_assert_int_eq(1, bit_lib_get_bit_count(0b1));
|
||||
mu_assert_int_eq(1, bit_lib_get_bit_count(0b10));
|
||||
mu_assert_int_eq(2, bit_lib_get_bit_count(0b11));
|
||||
mu_assert_int_eq(4, bit_lib_get_bit_count(0b11000011));
|
||||
mu_assert_int_eq(6, bit_lib_get_bit_count(0b11000011000011));
|
||||
mu_assert_int_eq(8, bit_lib_get_bit_count(0b11111111));
|
||||
mu_assert_int_eq(16, bit_lib_get_bit_count(0b11111110000000000000000111111111));
|
||||
mu_assert_int_eq(32, bit_lib_get_bit_count(0b11111111111111111111111111111111));
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_reverse_16_fast) {
|
||||
mu_assert_int_eq(0b0000000000000000, bit_lib_reverse_16_fast(0b0000000000000000));
|
||||
mu_assert_int_eq(0b1000000000000000, bit_lib_reverse_16_fast(0b0000000000000001));
|
||||
mu_assert_int_eq(0b1100000000000000, bit_lib_reverse_16_fast(0b0000000000000011));
|
||||
mu_assert_int_eq(0b0000100000001001, bit_lib_reverse_16_fast(0b1001000000010000));
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_crc16) {
|
||||
uint8_t data[9] = {'1', '2', '3', '4', '5', '6', '7', '8', '9'};
|
||||
uint8_t data_size = 9;
|
||||
|
||||
// Algorithm
|
||||
// Check Poly Init RefIn RefOut XorOut
|
||||
// CRC-16/CCITT-FALSE
|
||||
// 0x29B1 0x1021 0xFFFF false false 0x0000
|
||||
mu_assert_int_eq(0x29B1, bit_lib_crc16(data, data_size, 0x1021, 0xFFFF, false, false, 0x0000));
|
||||
// CRC-16/ARC
|
||||
// 0xBB3D 0x8005 0x0000 true true 0x0000
|
||||
mu_assert_int_eq(0xBB3D, bit_lib_crc16(data, data_size, 0x8005, 0x0000, true, true, 0x0000));
|
||||
// CRC-16/AUG-CCITT
|
||||
// 0xE5CC 0x1021 0x1D0F false false 0x0000
|
||||
mu_assert_int_eq(0xE5CC, bit_lib_crc16(data, data_size, 0x1021, 0x1D0F, false, false, 0x0000));
|
||||
// CRC-16/BUYPASS
|
||||
// 0xFEE8 0x8005 0x0000 false false 0x0000
|
||||
mu_assert_int_eq(0xFEE8, bit_lib_crc16(data, data_size, 0x8005, 0x0000, false, false, 0x0000));
|
||||
// CRC-16/CDMA2000
|
||||
// 0x4C06 0xC867 0xFFFF false false 0x0000
|
||||
mu_assert_int_eq(0x4C06, bit_lib_crc16(data, data_size, 0xC867, 0xFFFF, false, false, 0x0000));
|
||||
// CRC-16/DDS-110
|
||||
// 0x9ECF 0x8005 0x800D false false 0x0000
|
||||
mu_assert_int_eq(0x9ECF, bit_lib_crc16(data, data_size, 0x8005, 0x800D, false, false, 0x0000));
|
||||
// CRC-16/DECT-R
|
||||
// 0x007E 0x0589 0x0000 false false 0x0001
|
||||
mu_assert_int_eq(0x007E, bit_lib_crc16(data, data_size, 0x0589, 0x0000, false, false, 0x0001));
|
||||
// CRC-16/DECT-X
|
||||
// 0x007F 0x0589 0x0000 false false 0x0000
|
||||
mu_assert_int_eq(0x007F, bit_lib_crc16(data, data_size, 0x0589, 0x0000, false, false, 0x0000));
|
||||
// CRC-16/DNP
|
||||
// 0xEA82 0x3D65 0x0000 true true 0xFFFF
|
||||
mu_assert_int_eq(0xEA82, bit_lib_crc16(data, data_size, 0x3D65, 0x0000, true, true, 0xFFFF));
|
||||
// CRC-16/EN-13757
|
||||
// 0xC2B7 0x3D65 0x0000 false false 0xFFFF
|
||||
mu_assert_int_eq(0xC2B7, bit_lib_crc16(data, data_size, 0x3D65, 0x0000, false, false, 0xFFFF));
|
||||
// CRC-16/GENIBUS
|
||||
// 0xD64E 0x1021 0xFFFF false false 0xFFFF
|
||||
mu_assert_int_eq(0xD64E, bit_lib_crc16(data, data_size, 0x1021, 0xFFFF, false, false, 0xFFFF));
|
||||
// CRC-16/MAXIM
|
||||
// 0x44C2 0x8005 0x0000 true true 0xFFFF
|
||||
mu_assert_int_eq(0x44C2, bit_lib_crc16(data, data_size, 0x8005, 0x0000, true, true, 0xFFFF));
|
||||
// CRC-16/MCRF4XX
|
||||
// 0x6F91 0x1021 0xFFFF true true 0x0000
|
||||
mu_assert_int_eq(0x6F91, bit_lib_crc16(data, data_size, 0x1021, 0xFFFF, true, true, 0x0000));
|
||||
// CRC-16/RIELLO
|
||||
// 0x63D0 0x1021 0xB2AA true true 0x0000
|
||||
mu_assert_int_eq(0x63D0, bit_lib_crc16(data, data_size, 0x1021, 0xB2AA, true, true, 0x0000));
|
||||
// CRC-16/T10-DIF
|
||||
// 0xD0DB 0x8BB7 0x0000 false false 0x0000
|
||||
mu_assert_int_eq(0xD0DB, bit_lib_crc16(data, data_size, 0x8BB7, 0x0000, false, false, 0x0000));
|
||||
// CRC-16/TELEDISK
|
||||
// 0x0FB3 0xA097 0x0000 false false 0x0000
|
||||
mu_assert_int_eq(0x0FB3, bit_lib_crc16(data, data_size, 0xA097, 0x0000, false, false, 0x0000));
|
||||
// CRC-16/TMS37157
|
||||
// 0x26B1 0x1021 0x89EC true true 0x0000
|
||||
mu_assert_int_eq(0x26B1, bit_lib_crc16(data, data_size, 0x1021, 0x89EC, true, true, 0x0000));
|
||||
// CRC-16/USB
|
||||
// 0xB4C8 0x8005 0xFFFF true true 0xFFFF
|
||||
mu_assert_int_eq(0xB4C8, bit_lib_crc16(data, data_size, 0x8005, 0xFFFF, true, true, 0xFFFF));
|
||||
// CRC-A
|
||||
// 0xBF05 0x1021 0xC6C6 true true 0x0000
|
||||
mu_assert_int_eq(0xBF05, bit_lib_crc16(data, data_size, 0x1021, 0xC6C6, true, true, 0x0000));
|
||||
// CRC-16/KERMIT
|
||||
// 0x2189 0x1021 0x0000 true true 0x0000
|
||||
mu_assert_int_eq(0x2189, bit_lib_crc16(data, data_size, 0x1021, 0x0000, true, true, 0x0000));
|
||||
// CRC-16/MODBUS
|
||||
// 0x4B37 0x8005 0xFFFF true true 0x0000
|
||||
mu_assert_int_eq(0x4B37, bit_lib_crc16(data, data_size, 0x8005, 0xFFFF, true, true, 0x0000));
|
||||
// CRC-16/X-25
|
||||
// 0x906E 0x1021 0xFFFF true true 0xFFFF
|
||||
mu_assert_int_eq(0x906E, bit_lib_crc16(data, data_size, 0x1021, 0xFFFF, true, true, 0xFFFF));
|
||||
// CRC-16/XMODEM
|
||||
// 0x31C3 0x1021 0x0000 false false 0x0000
|
||||
mu_assert_int_eq(0x31C3, bit_lib_crc16(data, data_size, 0x1021, 0x0000, false, false, 0x0000));
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_num_to_bytes_be) {
|
||||
uint8_t src[8] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
|
||||
uint8_t dest[8];
|
||||
|
||||
bit_lib_num_to_bytes_be(0x01, 1, dest);
|
||||
mu_assert_mem_eq(src, dest, sizeof(src[0]));
|
||||
|
||||
bit_lib_num_to_bytes_be(0x0123456789ABCDEF, 4, dest);
|
||||
mu_assert_mem_eq(src + 4, dest, 4 * sizeof(src[0]));
|
||||
|
||||
bit_lib_num_to_bytes_be(0x0123456789ABCDEF, 8, dest);
|
||||
mu_assert_mem_eq(src, dest, 8 * sizeof(src[0]));
|
||||
|
||||
bit_lib_num_to_bytes_be(bit_lib_bytes_to_num_be(src, 8), 8, dest);
|
||||
mu_assert_mem_eq(src, dest, 8 * sizeof(src[0]));
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_num_to_bytes_le) {
|
||||
uint8_t dest[8];
|
||||
|
||||
uint8_t n2b_le_expected_1[] = {0x01};
|
||||
bit_lib_num_to_bytes_le(0x01, 1, dest);
|
||||
mu_assert_mem_eq(n2b_le_expected_1, dest, sizeof(n2b_le_expected_1[0]));
|
||||
|
||||
uint8_t n2b_le_expected_2[] = {0xEF, 0xCD, 0xAB, 0x89};
|
||||
bit_lib_num_to_bytes_le(0x0123456789ABCDEF, 4, dest);
|
||||
mu_assert_mem_eq(n2b_le_expected_2, dest, 4 * sizeof(n2b_le_expected_2[0]));
|
||||
|
||||
uint8_t n2b_le_expected_3[] = {0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01};
|
||||
bit_lib_num_to_bytes_le(0x0123456789ABCDEF, 8, dest);
|
||||
mu_assert_mem_eq(n2b_le_expected_3, dest, 8 * sizeof(n2b_le_expected_3[0]));
|
||||
|
||||
bit_lib_num_to_bytes_le(bit_lib_bytes_to_num_le(n2b_le_expected_3, 8), 8, dest);
|
||||
mu_assert_mem_eq(n2b_le_expected_3, dest, 8 * sizeof(n2b_le_expected_3[0]));
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_bytes_to_num_be) {
|
||||
uint8_t src[8] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
|
||||
uint64_t res;
|
||||
|
||||
res = bit_lib_bytes_to_num_be(src, 1);
|
||||
mu_assert_int_eq(0x01, res);
|
||||
|
||||
res = bit_lib_bytes_to_num_be(src, 4);
|
||||
mu_assert_int_eq(0x01234567, res);
|
||||
|
||||
res = bit_lib_bytes_to_num_be(src, 8);
|
||||
uint64_t expected = 0x0123456789ABCDEF;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_bytes_to_num_le) {
|
||||
uint8_t src[8] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
|
||||
uint64_t res;
|
||||
|
||||
res = bit_lib_bytes_to_num_le(src, 1);
|
||||
mu_assert_int_eq(0x01, res);
|
||||
|
||||
res = bit_lib_bytes_to_num_le(src, 4);
|
||||
mu_assert_int_eq(0x67452301, res);
|
||||
|
||||
res = bit_lib_bytes_to_num_le(src, 8);
|
||||
uint64_t expected = 0xEFCDAB8967452301;
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
}
|
||||
|
||||
MU_TEST(test_bit_lib_bytes_to_num_bcd) {
|
||||
uint8_t src[8] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
|
||||
uint64_t res;
|
||||
bool is_bcd_res;
|
||||
|
||||
res = bit_lib_bytes_to_num_bcd(src, 1, &is_bcd_res);
|
||||
mu_assert_int_eq(01, res);
|
||||
mu_assert_int_eq(true, is_bcd_res);
|
||||
|
||||
res = bit_lib_bytes_to_num_bcd(src, 4, &is_bcd_res);
|
||||
mu_assert_int_eq(1234567, res);
|
||||
mu_assert_int_eq(true, is_bcd_res);
|
||||
|
||||
uint8_t digits[5] = {0x98, 0x76, 0x54, 0x32, 0x10};
|
||||
uint64_t expected = 9876543210;
|
||||
res = bit_lib_bytes_to_num_bcd(digits, 5, &is_bcd_res);
|
||||
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||
mu_assert_int_eq(true, is_bcd_res);
|
||||
|
||||
res = bit_lib_bytes_to_num_bcd(src, 8, &is_bcd_res);
|
||||
mu_assert_int_eq(false, is_bcd_res);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(test_bit_lib) {
|
||||
MU_RUN_TEST(test_bit_lib_increment_index);
|
||||
MU_RUN_TEST(test_bit_lib_is_set);
|
||||
MU_RUN_TEST(test_bit_lib_push);
|
||||
MU_RUN_TEST(test_bit_lib_set_bit);
|
||||
MU_RUN_TEST(test_bit_lib_set_bits);
|
||||
MU_RUN_TEST(test_bit_lib_get_bit);
|
||||
MU_RUN_TEST(test_bit_lib_get_bits);
|
||||
MU_RUN_TEST(test_bit_lib_get_bits_16);
|
||||
MU_RUN_TEST(test_bit_lib_get_bits_32);
|
||||
MU_RUN_TEST(test_bit_lib_get_bits_64);
|
||||
MU_RUN_TEST(test_bit_lib_test_parity_u32);
|
||||
MU_RUN_TEST(test_bit_lib_test_parity);
|
||||
MU_RUN_TEST(test_bit_lib_remove_bit_every_nth);
|
||||
MU_RUN_TEST(test_bit_lib_copy_bits);
|
||||
MU_RUN_TEST(test_bit_lib_reverse_bits);
|
||||
MU_RUN_TEST(test_bit_lib_get_bit_count);
|
||||
MU_RUN_TEST(test_bit_lib_reverse_16_fast);
|
||||
MU_RUN_TEST(test_bit_lib_crc16);
|
||||
MU_RUN_TEST(test_bit_lib_num_to_bytes_be);
|
||||
MU_RUN_TEST(test_bit_lib_num_to_bytes_le);
|
||||
MU_RUN_TEST(test_bit_lib_bytes_to_num_be);
|
||||
MU_RUN_TEST(test_bit_lib_bytes_to_num_le);
|
||||
MU_RUN_TEST(test_bit_lib_bytes_to_num_bcd);
|
||||
}
|
||||
|
||||
int run_minunit_test_bit_lib() {
|
||||
MU_RUN_SUITE(test_bit_lib);
|
||||
return MU_EXIT_CODE;
|
||||
}
|
||||
@@ -28,7 +28,7 @@ void bt_test_alloc() {
|
||||
}
|
||||
|
||||
void bt_test_free() {
|
||||
furi_check(bt_test);
|
||||
furi_assert(bt_test);
|
||||
free(bt_test->nvm_ram_buff_ref);
|
||||
free(bt_test->nvm_ram_buff_dut);
|
||||
bt_keys_storage_free(bt_test->bt_keys_storage);
|
||||
@@ -89,7 +89,7 @@ static void bt_test_keys_remove_test_file() {
|
||||
}
|
||||
|
||||
MU_TEST(bt_test_keys_storage_serial_profile) {
|
||||
furi_check(bt_test);
|
||||
furi_assert(bt_test);
|
||||
|
||||
bt_test_keys_remove_test_file();
|
||||
bt_test_keys_storage_profile();
|
||||
|
||||
@@ -1,191 +0,0 @@
|
||||
#include <furi.h>
|
||||
#include "../minunit.h"
|
||||
|
||||
#include <datetime/datetime.h>
|
||||
|
||||
MU_TEST(test_datetime_validate_datetime_correct_min) {
|
||||
DateTime correct_min = {0, 0, 0, 1, 1, 2000, 1};
|
||||
bool result = datetime_validate_datetime(&correct_min);
|
||||
|
||||
mu_assert_int_eq(true, result);
|
||||
}
|
||||
|
||||
MU_TEST(test_datetime_validate_datetime_correct_max) {
|
||||
DateTime correct_max = {23, 59, 59, 31, 12, 2099, 7};
|
||||
bool result = datetime_validate_datetime(&correct_max);
|
||||
|
||||
mu_assert_int_eq(true, result);
|
||||
}
|
||||
|
||||
MU_TEST(test_datetime_validate_datetime_incorrect_second) {
|
||||
DateTime incorrect_sec = {0, 0, 60, 1, 1, 2000, 1};
|
||||
bool result = datetime_validate_datetime(&incorrect_sec);
|
||||
|
||||
mu_assert_int_eq(false, result);
|
||||
}
|
||||
|
||||
MU_TEST(test_datetime_validate_datetime_incorrect_minute) {
|
||||
DateTime incorrect_min = {0, 60, 0, 1, 1, 2000, 1};
|
||||
bool result = datetime_validate_datetime(&incorrect_min);
|
||||
|
||||
mu_assert_int_eq(false, result);
|
||||
}
|
||||
|
||||
MU_TEST(test_datetime_validate_datetime_incorrect_hour) {
|
||||
DateTime incorrect_hour = {24, 0, 0, 1, 1, 2000, 1};
|
||||
bool result = datetime_validate_datetime(&incorrect_hour);
|
||||
|
||||
mu_assert_int_eq(false, result);
|
||||
}
|
||||
|
||||
MU_TEST(test_datetime_validate_datetime_incorrect_day_min) {
|
||||
DateTime incorrect_day_min = {0, 0, 0, 0, 1, 2000, 1};
|
||||
bool result = datetime_validate_datetime(&incorrect_day_min);
|
||||
|
||||
mu_assert_int_eq(false, result);
|
||||
}
|
||||
|
||||
MU_TEST(test_datetime_validate_datetime_incorrect_day_max) {
|
||||
DateTime incorrect_day_max = {0, 0, 0, 32, 1, 2000, 1};
|
||||
bool result = datetime_validate_datetime(&incorrect_day_max);
|
||||
|
||||
mu_assert_int_eq(false, result);
|
||||
}
|
||||
|
||||
MU_TEST(test_datetime_validate_datetime_incorrect_month_min) {
|
||||
DateTime incorrect_month_min = {0, 0, 0, 1, 0, 2000, 1};
|
||||
bool result = datetime_validate_datetime(&incorrect_month_min);
|
||||
|
||||
mu_assert_int_eq(false, result);
|
||||
}
|
||||
|
||||
MU_TEST(test_datetime_validate_datetime_incorrect_month_max) {
|
||||
DateTime incorrect_month_max = {0, 0, 0, 1, 13, 2000, 1};
|
||||
bool result = datetime_validate_datetime(&incorrect_month_max);
|
||||
|
||||
mu_assert_int_eq(false, result);
|
||||
}
|
||||
|
||||
MU_TEST(test_datetime_validate_datetime_incorrect_year_min) {
|
||||
DateTime incorrect_year_min = {0, 0, 0, 1, 1, 1999, 1};
|
||||
bool result = datetime_validate_datetime(&incorrect_year_min);
|
||||
|
||||
mu_assert_int_eq(false, result);
|
||||
}
|
||||
|
||||
MU_TEST(test_datetime_validate_datetime_incorrect_year_max) {
|
||||
DateTime incorrect_year_max = {0, 0, 0, 1, 1, 2100, 1};
|
||||
bool result = datetime_validate_datetime(&incorrect_year_max);
|
||||
|
||||
mu_assert_int_eq(false, result);
|
||||
}
|
||||
|
||||
MU_TEST(test_datetime_validate_datetime_incorrect_weekday_min) {
|
||||
DateTime incorrect_weekday_min = {0, 0, 0, 1, 1, 2000, 0};
|
||||
bool result = datetime_validate_datetime(&incorrect_weekday_min);
|
||||
|
||||
mu_assert_int_eq(false, result);
|
||||
}
|
||||
|
||||
MU_TEST(test_datetime_validate_datetime_incorrect_weekday_max) {
|
||||
DateTime incorrect_weekday_max = {0, 0, 0, 1, 1, 2000, 8};
|
||||
bool result = datetime_validate_datetime(&incorrect_weekday_max);
|
||||
|
||||
mu_assert_int_eq(false, result);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(test_datetime_validate_datetime) {
|
||||
MU_RUN_TEST(test_datetime_validate_datetime_correct_min);
|
||||
MU_RUN_TEST(test_datetime_validate_datetime_correct_max);
|
||||
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_second);
|
||||
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_minute);
|
||||
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_hour);
|
||||
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_day_min);
|
||||
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_day_max);
|
||||
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_month_min);
|
||||
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_month_max);
|
||||
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_year_min);
|
||||
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_year_max);
|
||||
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_weekday_min);
|
||||
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_weekday_max);
|
||||
}
|
||||
|
||||
MU_TEST(test_datetime_timestamp_to_datetime_min) {
|
||||
uint32_t test_value = 0;
|
||||
DateTime min_datetime_expected = {0, 0, 0, 1, 1, 1970, 4};
|
||||
|
||||
DateTime result = {0};
|
||||
datetime_timestamp_to_datetime(test_value, &result);
|
||||
|
||||
mu_assert_mem_eq(&min_datetime_expected, &result, sizeof(result));
|
||||
}
|
||||
|
||||
MU_TEST(test_datetime_timestamp_to_datetime_max) {
|
||||
uint32_t test_value = UINT32_MAX;
|
||||
DateTime max_datetime_expected = {6, 28, 15, 7, 2, 2106, 7};
|
||||
|
||||
DateTime result = {0};
|
||||
datetime_timestamp_to_datetime(test_value, &result);
|
||||
|
||||
mu_assert_mem_eq(&max_datetime_expected, &result, sizeof(result));
|
||||
}
|
||||
|
||||
MU_TEST(test_datetime_timestamp_to_datetime_to_timestamp) {
|
||||
uint32_t test_value = random();
|
||||
|
||||
DateTime datetime = {0};
|
||||
datetime_timestamp_to_datetime(test_value, &datetime);
|
||||
|
||||
uint32_t result = datetime_datetime_to_timestamp(&datetime);
|
||||
|
||||
mu_assert_int_eq(test_value, result);
|
||||
}
|
||||
|
||||
MU_TEST(test_datetime_timestamp_to_datetime_weekday) {
|
||||
uint32_t test_value = 1709748421; // Wed Mar 06 18:07:01 2024 UTC
|
||||
|
||||
DateTime datetime = {0};
|
||||
datetime_timestamp_to_datetime(test_value, &datetime);
|
||||
|
||||
mu_assert_int_eq(datetime.hour, 18);
|
||||
mu_assert_int_eq(datetime.minute, 7);
|
||||
mu_assert_int_eq(datetime.second, 1);
|
||||
mu_assert_int_eq(datetime.day, 6);
|
||||
mu_assert_int_eq(datetime.month, 3);
|
||||
mu_assert_int_eq(datetime.weekday, 3);
|
||||
mu_assert_int_eq(datetime.year, 2024);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(test_datetime_timestamp_to_datetime_suite) {
|
||||
MU_RUN_TEST(test_datetime_timestamp_to_datetime_min);
|
||||
MU_RUN_TEST(test_datetime_timestamp_to_datetime_max);
|
||||
MU_RUN_TEST(test_datetime_timestamp_to_datetime_to_timestamp);
|
||||
MU_RUN_TEST(test_datetime_timestamp_to_datetime_weekday);
|
||||
}
|
||||
|
||||
MU_TEST(test_datetime_datetime_to_timestamp_min) {
|
||||
DateTime min_datetime = {0, 0, 0, 1, 1, 1970, 0};
|
||||
|
||||
uint32_t result = datetime_datetime_to_timestamp(&min_datetime);
|
||||
mu_assert_int_eq(0, result);
|
||||
}
|
||||
|
||||
MU_TEST(test_datetime_datetime_to_timestamp_max) {
|
||||
DateTime max_datetime = {6, 28, 15, 7, 2, 2106, 0};
|
||||
|
||||
uint32_t result = datetime_datetime_to_timestamp(&max_datetime);
|
||||
mu_assert_int_eq(UINT32_MAX, result);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(test_datetime_datetime_to_timestamp_suite) {
|
||||
MU_RUN_TEST(test_datetime_datetime_to_timestamp_min);
|
||||
MU_RUN_TEST(test_datetime_datetime_to_timestamp_max);
|
||||
}
|
||||
|
||||
int run_minunit_test_datetime() {
|
||||
MU_RUN_SUITE(test_datetime_timestamp_to_datetime_suite);
|
||||
MU_RUN_SUITE(test_datetime_datetime_to_timestamp_suite);
|
||||
MU_RUN_SUITE(test_datetime_validate_datetime);
|
||||
|
||||
return MU_EXIT_CODE;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
#include <dialogs/dialogs.h>
|
||||
|
||||
#include "../minunit.h"
|
||||
|
||||
MU_TEST(test_dialog_file_browser_set_basic_options_should_init_all_fields) {
|
||||
mu_assert(
|
||||
sizeof(DialogsFileBrowserOptions) == 28,
|
||||
"Changes to `DialogsFileBrowserOptions` should also be reflected in `dialog_file_browser_set_basic_options`");
|
||||
|
||||
DialogsFileBrowserOptions options;
|
||||
dialog_file_browser_set_basic_options(&options, ".fap", NULL);
|
||||
// note: this assertions can safely be changed, their primary purpose is to remind the maintainer
|
||||
// to update `dialog_file_browser_set_basic_options` by including all structure fields in it
|
||||
mu_assert_string_eq(".fap", options.extension);
|
||||
mu_assert_null(options.base_path);
|
||||
mu_assert(options.skip_assets, "`skip_assets` should default to `true");
|
||||
mu_assert(options.hide_dot_files, "`hide_dot_files` should default to `true");
|
||||
mu_assert_null(options.icon);
|
||||
mu_assert(options.hide_ext, "`hide_ext` should default to `true");
|
||||
mu_assert_null(options.item_loader_callback);
|
||||
mu_assert_null(options.item_loader_context);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(dialogs_file_browser_options) {
|
||||
MU_RUN_TEST(test_dialog_file_browser_set_basic_options_should_init_all_fields);
|
||||
}
|
||||
|
||||
int run_minunit_test_dialogs_file_browser_options() {
|
||||
MU_RUN_SUITE(dialogs_file_browser_options);
|
||||
|
||||
return MU_EXIT_CODE;
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
#include "../minunit.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi_hal_random.h>
|
||||
|
||||
#include <expansion/expansion_protocol.h>
|
||||
|
||||
#define EXPANSION_TEST_GARBAGE_MAGIC (0xB19AF)
|
||||
#define EXPANSION_TEST_GARBAGE_BUF_SIZE (0x100U)
|
||||
#define EXPANSION_TEST_GARBAGE_ITERATIONS (100U)
|
||||
|
||||
MU_TEST(test_expansion_encoded_size) {
|
||||
ExpansionFrame frame = {};
|
||||
|
||||
frame.header.type = ExpansionFrameTypeHeartbeat;
|
||||
mu_assert_int_eq(1, expansion_frame_get_encoded_size(&frame));
|
||||
|
||||
frame.header.type = ExpansionFrameTypeStatus;
|
||||
mu_assert_int_eq(2, expansion_frame_get_encoded_size(&frame));
|
||||
|
||||
frame.header.type = ExpansionFrameTypeBaudRate;
|
||||
mu_assert_int_eq(5, expansion_frame_get_encoded_size(&frame));
|
||||
|
||||
frame.header.type = ExpansionFrameTypeControl;
|
||||
mu_assert_int_eq(2, expansion_frame_get_encoded_size(&frame));
|
||||
|
||||
frame.header.type = ExpansionFrameTypeData;
|
||||
for(size_t i = 0; i <= EXPANSION_PROTOCOL_MAX_DATA_SIZE; ++i) {
|
||||
frame.content.data.size = i;
|
||||
mu_assert_int_eq(i + 2, expansion_frame_get_encoded_size(&frame));
|
||||
}
|
||||
}
|
||||
|
||||
MU_TEST(test_expansion_remaining_size) {
|
||||
ExpansionFrame frame = {};
|
||||
|
||||
size_t remaining_size;
|
||||
mu_check(expansion_frame_get_remaining_size(&frame, 0, &remaining_size));
|
||||
mu_assert_int_eq(1, remaining_size);
|
||||
|
||||
frame.header.type = ExpansionFrameTypeHeartbeat;
|
||||
mu_check(expansion_frame_get_remaining_size(&frame, 0, &remaining_size));
|
||||
mu_assert_int_eq(1, remaining_size);
|
||||
mu_check(expansion_frame_get_remaining_size(&frame, 1, &remaining_size));
|
||||
mu_assert_int_eq(0, remaining_size);
|
||||
mu_check(expansion_frame_get_remaining_size(&frame, 100, &remaining_size));
|
||||
mu_assert_int_eq(0, remaining_size);
|
||||
|
||||
frame.header.type = ExpansionFrameTypeStatus;
|
||||
mu_check(expansion_frame_get_remaining_size(&frame, 0, &remaining_size));
|
||||
mu_assert_int_eq(1, remaining_size);
|
||||
mu_check(expansion_frame_get_remaining_size(&frame, 1, &remaining_size));
|
||||
mu_assert_int_eq(1, remaining_size);
|
||||
mu_check(expansion_frame_get_remaining_size(&frame, 2, &remaining_size));
|
||||
mu_assert_int_eq(0, remaining_size);
|
||||
mu_check(expansion_frame_get_remaining_size(&frame, 100, &remaining_size));
|
||||
mu_assert_int_eq(0, remaining_size);
|
||||
|
||||
frame.header.type = ExpansionFrameTypeBaudRate;
|
||||
mu_check(expansion_frame_get_remaining_size(&frame, 0, &remaining_size));
|
||||
mu_assert_int_eq(1, remaining_size);
|
||||
mu_check(expansion_frame_get_remaining_size(&frame, 1, &remaining_size));
|
||||
mu_assert_int_eq(4, remaining_size);
|
||||
mu_check(expansion_frame_get_remaining_size(&frame, 5, &remaining_size));
|
||||
mu_assert_int_eq(0, remaining_size);
|
||||
mu_check(expansion_frame_get_remaining_size(&frame, 100, &remaining_size));
|
||||
mu_assert_int_eq(0, remaining_size);
|
||||
|
||||
frame.header.type = ExpansionFrameTypeControl;
|
||||
mu_check(expansion_frame_get_remaining_size(&frame, 0, &remaining_size));
|
||||
mu_assert_int_eq(1, remaining_size);
|
||||
mu_check(expansion_frame_get_remaining_size(&frame, 1, &remaining_size));
|
||||
mu_assert_int_eq(1, remaining_size);
|
||||
mu_check(expansion_frame_get_remaining_size(&frame, 2, &remaining_size));
|
||||
mu_assert_int_eq(0, remaining_size);
|
||||
mu_check(expansion_frame_get_remaining_size(&frame, 100, &remaining_size));
|
||||
mu_assert_int_eq(0, remaining_size);
|
||||
|
||||
frame.header.type = ExpansionFrameTypeData;
|
||||
frame.content.data.size = EXPANSION_PROTOCOL_MAX_DATA_SIZE;
|
||||
mu_check(expansion_frame_get_remaining_size(&frame, 0, &remaining_size));
|
||||
mu_assert_int_eq(1, remaining_size);
|
||||
mu_check(expansion_frame_get_remaining_size(&frame, 1, &remaining_size));
|
||||
mu_assert_int_eq(1, remaining_size);
|
||||
mu_check(expansion_frame_get_remaining_size(&frame, 2, &remaining_size));
|
||||
mu_assert_int_eq(EXPANSION_PROTOCOL_MAX_DATA_SIZE, remaining_size);
|
||||
for(size_t i = 0; i <= EXPANSION_PROTOCOL_MAX_DATA_SIZE; ++i) {
|
||||
mu_check(expansion_frame_get_remaining_size(&frame, i + 2, &remaining_size));
|
||||
mu_assert_int_eq(EXPANSION_PROTOCOL_MAX_DATA_SIZE - i, remaining_size);
|
||||
}
|
||||
mu_check(expansion_frame_get_remaining_size(&frame, 100, &remaining_size));
|
||||
mu_assert_int_eq(0, remaining_size);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
void* data_out;
|
||||
size_t size_available;
|
||||
size_t size_sent;
|
||||
} TestExpansionSendStream;
|
||||
|
||||
static size_t test_expansion_send_callback(const uint8_t* data, size_t data_size, void* context) {
|
||||
TestExpansionSendStream* stream = context;
|
||||
const size_t size_sent = MIN(data_size, stream->size_available);
|
||||
|
||||
memcpy(stream->data_out + stream->size_sent, data, size_sent);
|
||||
|
||||
stream->size_available -= size_sent;
|
||||
stream->size_sent += size_sent;
|
||||
|
||||
return size_sent;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const void* data_in;
|
||||
size_t size_available;
|
||||
size_t size_received;
|
||||
} TestExpansionReceiveStream;
|
||||
|
||||
static size_t test_expansion_receive_callback(uint8_t* data, size_t data_size, void* context) {
|
||||
TestExpansionReceiveStream* stream = context;
|
||||
const size_t size_received = MIN(data_size, stream->size_available);
|
||||
|
||||
memcpy(data, stream->data_in + stream->size_received, size_received);
|
||||
|
||||
stream->size_available -= size_received;
|
||||
stream->size_received += size_received;
|
||||
|
||||
return size_received;
|
||||
}
|
||||
|
||||
MU_TEST(test_expansion_encode_decode_frame) {
|
||||
const ExpansionFrame frame_in = {
|
||||
.header.type = ExpansionFrameTypeData,
|
||||
.content.data.size = 8,
|
||||
.content.data.bytes = {0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xca, 0xfe},
|
||||
};
|
||||
|
||||
uint8_t encoded_data[sizeof(ExpansionFrame) + sizeof(ExpansionFrameChecksum)];
|
||||
memset(encoded_data, 0, sizeof(encoded_data));
|
||||
|
||||
TestExpansionSendStream send_stream = {
|
||||
.data_out = &encoded_data,
|
||||
.size_available = sizeof(encoded_data),
|
||||
.size_sent = 0,
|
||||
};
|
||||
|
||||
const size_t encoded_size = expansion_frame_get_encoded_size(&frame_in);
|
||||
|
||||
mu_assert_int_eq(
|
||||
expansion_protocol_encode(&frame_in, test_expansion_send_callback, &send_stream),
|
||||
ExpansionProtocolStatusOk);
|
||||
mu_assert_int_eq(encoded_size + sizeof(ExpansionFrameChecksum), send_stream.size_sent);
|
||||
mu_assert_int_eq(
|
||||
expansion_protocol_get_checksum((const uint8_t*)&frame_in, encoded_size),
|
||||
encoded_data[encoded_size]);
|
||||
mu_assert_mem_eq(&frame_in, &encoded_data, encoded_size);
|
||||
|
||||
TestExpansionReceiveStream stream = {
|
||||
.data_in = encoded_data,
|
||||
.size_available = send_stream.size_sent,
|
||||
.size_received = 0,
|
||||
};
|
||||
|
||||
ExpansionFrame frame_out;
|
||||
|
||||
mu_assert_int_eq(
|
||||
expansion_protocol_decode(&frame_out, test_expansion_receive_callback, &stream),
|
||||
ExpansionProtocolStatusOk);
|
||||
mu_assert_int_eq(encoded_size + sizeof(ExpansionFrameChecksum), stream.size_received);
|
||||
mu_assert_mem_eq(&frame_in, &frame_out, encoded_size);
|
||||
}
|
||||
|
||||
MU_TEST(test_expansion_garbage_input) {
|
||||
uint8_t garbage_data[EXPANSION_TEST_GARBAGE_BUF_SIZE];
|
||||
for(uint32_t i = 0; i < EXPANSION_TEST_GARBAGE_ITERATIONS; ++i) {
|
||||
furi_hal_random_fill_buf(garbage_data, sizeof(garbage_data));
|
||||
size_t remaining_size = EXPANSION_TEST_GARBAGE_MAGIC;
|
||||
if(expansion_frame_get_remaining_size(
|
||||
(ExpansionFrame*)garbage_data, sizeof(garbage_data), &remaining_size)) {
|
||||
// If by chance the garbage data is a valid frame, then the result
|
||||
// must be 0 because the amount of data provided is more than enough
|
||||
mu_assert_int_eq(0, remaining_size);
|
||||
} else {
|
||||
// If the frame is invalid, the remaining_size parameter should be untouched
|
||||
mu_assert_int_eq(EXPANSION_TEST_GARBAGE_MAGIC, remaining_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(test_expansion_suite) {
|
||||
MU_RUN_TEST(test_expansion_encoded_size);
|
||||
MU_RUN_TEST(test_expansion_remaining_size);
|
||||
MU_RUN_TEST(test_expansion_encode_decode_frame);
|
||||
MU_RUN_TEST(test_expansion_garbage_input);
|
||||
}
|
||||
|
||||
int run_minunit_test_expansion() {
|
||||
MU_RUN_SUITE(test_expansion_suite);
|
||||
return MU_EXIT_CODE;
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void test_furi_memmgr() {
|
||||
void* ptr;
|
||||
@@ -27,6 +26,7 @@ void test_furi_memmgr() {
|
||||
mu_assert_int_eq(66, ((uint8_t*)ptr)[i]);
|
||||
}
|
||||
|
||||
// TODO: fix realloc to copy only old size, and write testcase that leftover of reallocated memory is zero-initialized
|
||||
free(ptr);
|
||||
|
||||
// allocate and zero-initialize array (calloc)
|
||||
|
||||
@@ -3,29 +3,18 @@
|
||||
#include <furi.h>
|
||||
#include "../minunit.h"
|
||||
|
||||
#define TEST_RECORD_NAME "test/holding"
|
||||
|
||||
void test_furi_create_open() {
|
||||
// Test that record does not exist
|
||||
mu_check(furi_record_exists(TEST_RECORD_NAME) == false);
|
||||
|
||||
// Create record
|
||||
// 1. Create record
|
||||
uint8_t test_data = 0;
|
||||
furi_record_create(TEST_RECORD_NAME, (void*)&test_data);
|
||||
furi_record_create("test/holding", (void*)&test_data);
|
||||
|
||||
// Test that record exists
|
||||
mu_check(furi_record_exists(TEST_RECORD_NAME) == true);
|
||||
|
||||
// Open it
|
||||
void* record = furi_record_open(TEST_RECORD_NAME);
|
||||
// 2. Open it
|
||||
void* record = furi_record_open("test/holding");
|
||||
mu_assert_pointers_eq(record, &test_data);
|
||||
|
||||
// Close it
|
||||
furi_record_close(TEST_RECORD_NAME);
|
||||
// 3. Close it
|
||||
furi_record_close("test/holding");
|
||||
|
||||
// Clean up
|
||||
furi_record_destroy(TEST_RECORD_NAME);
|
||||
|
||||
// Test that record does not exist
|
||||
mu_check(furi_record_exists(TEST_RECORD_NAME) == false);
|
||||
// 4. Clean up
|
||||
furi_record_destroy("test/holding");
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ MU_TEST(mu_test_furi_string_mem) {
|
||||
mu_check(string != NULL);
|
||||
mu_check(!furi_string_empty(string));
|
||||
|
||||
// TODO FL-3493: how to test furi_string_reserve?
|
||||
// TODO: how to test furi_string_reserve?
|
||||
|
||||
// test furi_string_reset
|
||||
furi_string_reset(string);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
// v2 tests
|
||||
void test_furi_create_open();
|
||||
void test_furi_valuemutex();
|
||||
void test_furi_concurrent_access();
|
||||
void test_furi_pubsub();
|
||||
|
||||
@@ -29,6 +30,10 @@ MU_TEST(mu_test_furi_create_open) {
|
||||
test_furi_create_open();
|
||||
}
|
||||
|
||||
MU_TEST(mu_test_furi_valuemutex) {
|
||||
test_furi_valuemutex();
|
||||
}
|
||||
|
||||
MU_TEST(mu_test_furi_pubsub) {
|
||||
test_furi_pubsub();
|
||||
}
|
||||
@@ -46,6 +51,7 @@ MU_TEST_SUITE(test_suite) {
|
||||
|
||||
// v2 tests
|
||||
MU_RUN_TEST(mu_test_furi_create_open);
|
||||
MU_RUN_TEST(mu_test_furi_valuemutex);
|
||||
MU_RUN_TEST(mu_test_furi_pubsub);
|
||||
MU_RUN_TEST(mu_test_furi_memmgr);
|
||||
}
|
||||
|
||||
41
applications/debug/unit_tests/furi/furi_valuemutex_test.c
Normal file
41
applications/debug/unit_tests/furi/furi_valuemutex_test.c
Normal file
@@ -0,0 +1,41 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <furi.h>
|
||||
|
||||
#include "../minunit.h"
|
||||
|
||||
void test_furi_valuemutex() {
|
||||
const int init_value = 0xdeadbeef;
|
||||
const int changed_value = 0x12345678;
|
||||
|
||||
int value = init_value;
|
||||
bool result;
|
||||
ValueMutex valuemutex;
|
||||
|
||||
// init mutex case
|
||||
result = init_mutex(&valuemutex, &value, sizeof(value));
|
||||
mu_assert(result, "init mutex failed");
|
||||
|
||||
// acquire mutex case
|
||||
int* value_pointer = acquire_mutex(&valuemutex, 100);
|
||||
mu_assert_pointers_eq(value_pointer, &value);
|
||||
|
||||
// second acquire mutex case
|
||||
int* value_pointer_second = acquire_mutex(&valuemutex, 100);
|
||||
mu_assert_pointers_eq(value_pointer_second, NULL);
|
||||
|
||||
// change value case
|
||||
*value_pointer = changed_value;
|
||||
mu_assert_int_eq(value, changed_value);
|
||||
|
||||
// release mutex case
|
||||
result = release_mutex(&valuemutex, &value);
|
||||
mu_assert(result, "release mutex failed");
|
||||
|
||||
// TODO
|
||||
//acquire mutex blocking case
|
||||
//write mutex blocking case
|
||||
//read mutex blocking case
|
||||
|
||||
mu_check(delete_mutex(&valuemutex));
|
||||
}
|
||||
@@ -1,602 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include "../minunit.h"
|
||||
|
||||
static const uint8_t key_ctr_1[32] = {
|
||||
0x77, 0x6B, 0xEF, 0xF2, 0x85, 0x1D, 0xB0, 0x6F, 0x4C, 0x8A, 0x05, 0x42, 0xC8, 0x69, 0x6F, 0x6C,
|
||||
0x6A, 0x81, 0xAF, 0x1E, 0xEC, 0x96, 0xB4, 0xD3, 0x7F, 0xC1, 0xD6, 0x89, 0xE6, 0xC1, 0xC1, 0x04,
|
||||
};
|
||||
static const uint8_t iv_ctr_1[16] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x60,
|
||||
0xDB,
|
||||
0x56,
|
||||
0x72,
|
||||
0xC9,
|
||||
0x7A,
|
||||
0xA8,
|
||||
0xF0,
|
||||
0xB2,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x01,
|
||||
};
|
||||
static const uint8_t pt_ctr_1[16] = {
|
||||
0x53,
|
||||
0x69,
|
||||
0x6E,
|
||||
0x67,
|
||||
0x6C,
|
||||
0x65,
|
||||
0x20,
|
||||
0x62,
|
||||
0x6C,
|
||||
0x6F,
|
||||
0x63,
|
||||
0x6B,
|
||||
0x20,
|
||||
0x6D,
|
||||
0x73,
|
||||
0x67,
|
||||
};
|
||||
static const uint8_t tv_ctr_ct_1[16] = {
|
||||
0x14,
|
||||
0x5A,
|
||||
0xD0,
|
||||
0x1D,
|
||||
0xBF,
|
||||
0x82,
|
||||
0x4E,
|
||||
0xC7,
|
||||
0x56,
|
||||
0x08,
|
||||
0x63,
|
||||
0xDC,
|
||||
0x71,
|
||||
0xE3,
|
||||
0xE0,
|
||||
0xC0,
|
||||
};
|
||||
|
||||
static const uint8_t key_ctr_2[32] = {
|
||||
0x77, 0x6B, 0xEF, 0xF2, 0x85, 0x1D, 0xB0, 0x6F, 0x4C, 0x8A, 0x05, 0x42, 0xC8, 0x69, 0x6F, 0x6C,
|
||||
0x6A, 0x81, 0xAF, 0x1E, 0xEC, 0x96, 0xB4, 0xD3, 0x7F, 0xC1, 0xD6, 0x89, 0xE6, 0xC1, 0xC1, 0x04,
|
||||
};
|
||||
static const uint8_t iv_ctr_2[16] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x60,
|
||||
0xDB,
|
||||
0x56,
|
||||
0x72,
|
||||
0xC9,
|
||||
0x7A,
|
||||
0xA8,
|
||||
0xF0,
|
||||
0xB2,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x01,
|
||||
};
|
||||
static const uint8_t pt_ctr_2[0] = {};
|
||||
//static const uint8_t tv_ctr_ct_2[0] = {};
|
||||
|
||||
static const uint8_t key_ctr_3[32] = {
|
||||
0xF6, 0xD6, 0x6D, 0x6B, 0xD5, 0x2D, 0x59, 0xBB, 0x07, 0x96, 0x36, 0x58, 0x79, 0xEF, 0xF8, 0x86,
|
||||
0xC6, 0x6D, 0xD5, 0x1A, 0x5B, 0x6A, 0x99, 0x74, 0x4B, 0x50, 0x59, 0x0C, 0x87, 0xA2, 0x38, 0x84,
|
||||
};
|
||||
static const uint8_t iv_ctr_3[16] = {
|
||||
0x00,
|
||||
0xFA,
|
||||
0xAC,
|
||||
0x24,
|
||||
0xC1,
|
||||
0x58,
|
||||
0x5E,
|
||||
0xF1,
|
||||
0x5A,
|
||||
0x43,
|
||||
0xD8,
|
||||
0x75,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x01,
|
||||
};
|
||||
static const uint8_t pt_ctr_3[32] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
};
|
||||
static const uint8_t tv_ctr_ct_3[32] = {
|
||||
0xF0, 0x5E, 0x23, 0x1B, 0x38, 0x94, 0x61, 0x2C, 0x49, 0xEE, 0x00, 0x0B, 0x80, 0x4E, 0xB2, 0xA9,
|
||||
0xB8, 0x30, 0x6B, 0x50, 0x8F, 0x83, 0x9D, 0x6A, 0x55, 0x30, 0x83, 0x1D, 0x93, 0x44, 0xAF, 0x1C,
|
||||
};
|
||||
|
||||
static const uint8_t key_ctr_4[32] = {
|
||||
0xFF, 0x7A, 0x61, 0x7C, 0xE6, 0x91, 0x48, 0xE4, 0xF1, 0x72, 0x6E, 0x2F, 0x43, 0x58, 0x1D, 0xE2,
|
||||
0xAA, 0x62, 0xD9, 0xF8, 0x05, 0x53, 0x2E, 0xDF, 0xF1, 0xEE, 0xD6, 0x87, 0xFB, 0x54, 0x15, 0x3D,
|
||||
};
|
||||
static const uint8_t iv_ctr_4[16] = {
|
||||
0x00,
|
||||
0x1C,
|
||||
0xC5,
|
||||
0xB7,
|
||||
0x51,
|
||||
0xA5,
|
||||
0x1D,
|
||||
0x70,
|
||||
0xA1,
|
||||
0xC1,
|
||||
0x11,
|
||||
0x48,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x01,
|
||||
};
|
||||
static const uint8_t pt_ctr_4[36] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
|
||||
0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23,
|
||||
};
|
||||
static const uint8_t tv_ctr_ct_4[36] = {
|
||||
0xEB, 0x6C, 0x52, 0x82, 0x1D, 0x0B, 0xBB, 0xF7, 0xCE, 0x75, 0x94, 0x46,
|
||||
0x2A, 0xCA, 0x4F, 0xAA, 0xB4, 0x07, 0xDF, 0x86, 0x65, 0x69, 0xFD, 0x07,
|
||||
0xF4, 0x8C, 0xC0, 0xB5, 0x83, 0xD6, 0x07, 0x1F, 0x1E, 0xC0, 0xE6, 0xB8,
|
||||
};
|
||||
|
||||
static const uint8_t key_ctr_5[32] = {
|
||||
0xFF, 0x7A, 0x61, 0x7C, 0xE6, 0x91, 0x48, 0xE4, 0xF1, 0x72, 0x6E, 0x2F, 0x43, 0x58, 0x1D, 0xE2,
|
||||
0xAA, 0x62, 0xD9, 0xF8, 0x05, 0x53, 0x2E, 0xDF, 0xF1, 0xEE, 0xD6, 0x87, 0xFB, 0x54, 0x15, 0x3D,
|
||||
};
|
||||
static const uint8_t iv_ctr_5[16] = {
|
||||
0x00,
|
||||
0x1C,
|
||||
0xC5,
|
||||
0xB7,
|
||||
0x51,
|
||||
0xA5,
|
||||
0x1D,
|
||||
0x70,
|
||||
0xA1,
|
||||
0xC1,
|
||||
0x11,
|
||||
0x48,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x01,
|
||||
};
|
||||
static const uint8_t pt_ctr_5[0] = {};
|
||||
//static const uint8_t tv_ctr_ct_5[0] = {};
|
||||
|
||||
static const uint8_t key_gcm_1[32] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
static const uint8_t iv_gcm_1[16] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
};
|
||||
static const uint8_t pt_gcm_1[0] = {};
|
||||
//static const uint8_t tv_gcm_ct_1[0] = {};
|
||||
static const uint8_t aad_gcm_1[0] = {};
|
||||
static const uint8_t tv_gcm_tag_1[16] = {
|
||||
0x53,
|
||||
0x0F,
|
||||
0x8A,
|
||||
0xFB,
|
||||
0xC7,
|
||||
0x45,
|
||||
0x36,
|
||||
0xB9,
|
||||
0xA9,
|
||||
0x63,
|
||||
0xB4,
|
||||
0xF1,
|
||||
0xC4,
|
||||
0xCB,
|
||||
0x73,
|
||||
0x8B,
|
||||
};
|
||||
|
||||
static const uint8_t key_gcm_2[32] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
static const uint8_t iv_gcm_2[16] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
};
|
||||
static const uint8_t pt_gcm_2[16] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
};
|
||||
static const uint8_t tv_gcm_ct_2[16] = {
|
||||
0xCE,
|
||||
0xA7,
|
||||
0x40,
|
||||
0x3D,
|
||||
0x4D,
|
||||
0x60,
|
||||
0x6B,
|
||||
0x6E,
|
||||
0x07,
|
||||
0x4E,
|
||||
0xC5,
|
||||
0xD3,
|
||||
0xBA,
|
||||
0xF3,
|
||||
0x9D,
|
||||
0x18,
|
||||
};
|
||||
static const uint8_t aad_gcm_2[0] = {};
|
||||
static const uint8_t tv_gcm_tag_2[16] = {
|
||||
0xD0,
|
||||
0xD1,
|
||||
0xC8,
|
||||
0xA7,
|
||||
0x99,
|
||||
0x99,
|
||||
0x6B,
|
||||
0xF0,
|
||||
0x26,
|
||||
0x5B,
|
||||
0x98,
|
||||
0xB5,
|
||||
0xD4,
|
||||
0x8A,
|
||||
0xB9,
|
||||
0x19,
|
||||
};
|
||||
|
||||
static const uint8_t key_gcm_3[32] = {
|
||||
0xFE, 0xFF, 0xE9, 0x92, 0x86, 0x65, 0x73, 0x1C, 0x6D, 0x6A, 0x8F, 0x94, 0x67, 0x30, 0x83, 0x08,
|
||||
0xFE, 0xFF, 0xE9, 0x92, 0x86, 0x65, 0x73, 0x1C, 0x6D, 0x6A, 0x8F, 0x94, 0x67, 0x30, 0x83, 0x08,
|
||||
};
|
||||
static const uint8_t iv_gcm_3[16] = {
|
||||
0xCA,
|
||||
0xFE,
|
||||
0xBA,
|
||||
0xBE,
|
||||
0xFA,
|
||||
0xCE,
|
||||
0xDB,
|
||||
0xAD,
|
||||
0xDE,
|
||||
0xCA,
|
||||
0xF8,
|
||||
0x88,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
};
|
||||
static const uint8_t pt_gcm_3[64] = {
|
||||
0xD9, 0x31, 0x32, 0x25, 0xF8, 0x84, 0x06, 0xE5, 0xA5, 0x59, 0x09, 0xC5, 0xAF, 0xF5, 0x26, 0x9A,
|
||||
0x86, 0xA7, 0xA9, 0x53, 0x15, 0x34, 0xF7, 0xDA, 0x2E, 0x4C, 0x30, 0x3D, 0x8A, 0x31, 0x8A, 0x72,
|
||||
0x1C, 0x3C, 0x0C, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2F, 0xCF, 0x0E, 0x24, 0x49, 0xA6, 0xB5, 0x25,
|
||||
0xB1, 0x6A, 0xED, 0xF5, 0xAA, 0x0D, 0xE6, 0x57, 0xBA, 0x63, 0x7B, 0x39, 0x1A, 0xAF, 0xD2, 0x55,
|
||||
};
|
||||
static const uint8_t tv_gcm_ct_3[64] = {
|
||||
0x52, 0x2D, 0xC1, 0xF0, 0x99, 0x56, 0x7D, 0x07, 0xF4, 0x7F, 0x37, 0xA3, 0x2A, 0x84, 0x42, 0x7D,
|
||||
0x64, 0x3A, 0x8C, 0xDC, 0xBF, 0xE5, 0xC0, 0xC9, 0x75, 0x98, 0xA2, 0xBD, 0x25, 0x55, 0xD1, 0xAA,
|
||||
0x8C, 0xB0, 0x8E, 0x48, 0x59, 0x0D, 0xBB, 0x3D, 0xA7, 0xB0, 0x8B, 0x10, 0x56, 0x82, 0x88, 0x38,
|
||||
0xC5, 0xF6, 0x1E, 0x63, 0x93, 0xBA, 0x7A, 0x0A, 0xBC, 0xC9, 0xF6, 0x62, 0x89, 0x80, 0x15, 0xAD,
|
||||
};
|
||||
static const uint8_t aad_gcm_3[0] = {};
|
||||
static const uint8_t tv_gcm_tag_3[16] = {
|
||||
0xB0,
|
||||
0x94,
|
||||
0xDA,
|
||||
0xC5,
|
||||
0xD9,
|
||||
0x34,
|
||||
0x71,
|
||||
0xBD,
|
||||
0xEC,
|
||||
0x1A,
|
||||
0x50,
|
||||
0x22,
|
||||
0x70,
|
||||
0xE3,
|
||||
0xCC,
|
||||
0x6C,
|
||||
};
|
||||
|
||||
static const uint8_t key_gcm_4[32] = {
|
||||
0xFE, 0xFF, 0xE9, 0x92, 0x86, 0x65, 0x73, 0x1C, 0x6D, 0x6A, 0x8F, 0x94, 0x67, 0x30, 0x83, 0x08,
|
||||
0xFE, 0xFF, 0xE9, 0x92, 0x86, 0x65, 0x73, 0x1C, 0x6D, 0x6A, 0x8F, 0x94, 0x67, 0x30, 0x83, 0x08,
|
||||
};
|
||||
static const uint8_t iv_gcm_4[16] = {
|
||||
0xCA,
|
||||
0xFE,
|
||||
0xBA,
|
||||
0xBE,
|
||||
0xFA,
|
||||
0xCE,
|
||||
0xDB,
|
||||
0xAD,
|
||||
0xDE,
|
||||
0xCA,
|
||||
0xF8,
|
||||
0x88,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
};
|
||||
static const uint8_t pt_gcm_4[60] = {
|
||||
0xD9, 0x31, 0x32, 0x25, 0xF8, 0x84, 0x06, 0xE5, 0xA5, 0x59, 0x09, 0xC5, 0xAF, 0xF5, 0x26,
|
||||
0x9A, 0x86, 0xA7, 0xA9, 0x53, 0x15, 0x34, 0xF7, 0xDA, 0x2E, 0x4C, 0x30, 0x3D, 0x8A, 0x31,
|
||||
0x8A, 0x72, 0x1C, 0x3C, 0x0C, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2F, 0xCF, 0x0E, 0x24, 0x49,
|
||||
0xA6, 0xB5, 0x25, 0xB1, 0x6A, 0xED, 0xF5, 0xAA, 0x0D, 0xE6, 0x57, 0xBA, 0x63, 0x7B, 0x39,
|
||||
};
|
||||
static const uint8_t tv_gcm_ct_4[60] = {
|
||||
0x52, 0x2D, 0xC1, 0xF0, 0x99, 0x56, 0x7D, 0x07, 0xF4, 0x7F, 0x37, 0xA3, 0x2A, 0x84, 0x42,
|
||||
0x7D, 0x64, 0x3A, 0x8C, 0xDC, 0xBF, 0xE5, 0xC0, 0xC9, 0x75, 0x98, 0xA2, 0xBD, 0x25, 0x55,
|
||||
0xD1, 0xAA, 0x8C, 0xB0, 0x8E, 0x48, 0x59, 0x0D, 0xBB, 0x3D, 0xA7, 0xB0, 0x8B, 0x10, 0x56,
|
||||
0x82, 0x88, 0x38, 0xC5, 0xF6, 0x1E, 0x63, 0x93, 0xBA, 0x7A, 0x0A, 0xBC, 0xC9, 0xF6, 0x62,
|
||||
};
|
||||
static const uint8_t aad_gcm_4[20] = {
|
||||
0xFE, 0xED, 0xFA, 0xCE, 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED,
|
||||
0xFA, 0xCE, 0xDE, 0xAD, 0xBE, 0xEF, 0xAB, 0xAD, 0xDA, 0xD2,
|
||||
};
|
||||
static const uint8_t tv_gcm_tag_4[16] = {
|
||||
0x76,
|
||||
0xFC,
|
||||
0x6E,
|
||||
0xCE,
|
||||
0x0F,
|
||||
0x4E,
|
||||
0x17,
|
||||
0x68,
|
||||
0xCD,
|
||||
0xDF,
|
||||
0x88,
|
||||
0x53,
|
||||
0xBB,
|
||||
0x2D,
|
||||
0x55,
|
||||
0x1B,
|
||||
};
|
||||
|
||||
static void furi_hal_crypto_ctr_setup() {
|
||||
}
|
||||
|
||||
static void furi_hal_crypto_ctr_teardown() {
|
||||
}
|
||||
|
||||
static void furi_hal_crypto_gcm_setup() {
|
||||
}
|
||||
|
||||
static void furi_hal_crypto_gcm_teardown() {
|
||||
}
|
||||
|
||||
MU_TEST(furi_hal_crypto_ctr_1) {
|
||||
bool ret = false;
|
||||
uint8_t ct[sizeof(pt_ctr_1)];
|
||||
|
||||
ret = furi_hal_crypto_ctr(key_ctr_1, iv_ctr_1, pt_ctr_1, ct, sizeof(pt_ctr_1));
|
||||
mu_assert(ret, "CTR 1 failed");
|
||||
mu_assert_mem_eq(tv_ctr_ct_1, ct, sizeof(pt_ctr_1));
|
||||
}
|
||||
|
||||
MU_TEST(furi_hal_crypto_ctr_2) {
|
||||
bool ret = false;
|
||||
uint8_t ct[sizeof(pt_ctr_2)];
|
||||
|
||||
ret = furi_hal_crypto_ctr(key_ctr_2, iv_ctr_2, pt_ctr_2, ct, sizeof(pt_ctr_2));
|
||||
mu_assert(ret, "CTR 2 failed");
|
||||
//mu_assert_mem_eq(tv_ctr_ct_2, ct, sizeof(pt_ctr_2));
|
||||
}
|
||||
|
||||
MU_TEST(furi_hal_crypto_ctr_3) {
|
||||
bool ret = false;
|
||||
uint8_t ct[sizeof(pt_ctr_3)];
|
||||
|
||||
ret = furi_hal_crypto_ctr(key_ctr_3, iv_ctr_3, pt_ctr_3, ct, sizeof(pt_ctr_3));
|
||||
mu_assert(ret, "CTR 3 failed");
|
||||
mu_assert_mem_eq(tv_ctr_ct_3, ct, sizeof(pt_ctr_3));
|
||||
}
|
||||
|
||||
MU_TEST(furi_hal_crypto_ctr_4) {
|
||||
bool ret = false;
|
||||
uint8_t ct[sizeof(pt_ctr_4)];
|
||||
|
||||
ret = furi_hal_crypto_ctr(key_ctr_4, iv_ctr_4, pt_ctr_4, ct, sizeof(pt_ctr_4));
|
||||
mu_assert(ret, "CTR 4 failed");
|
||||
mu_assert_mem_eq(tv_ctr_ct_4, ct, sizeof(pt_ctr_4));
|
||||
}
|
||||
|
||||
MU_TEST(furi_hal_crypto_ctr_5) {
|
||||
bool ret = false;
|
||||
uint8_t ct[sizeof(pt_ctr_5)];
|
||||
|
||||
ret = furi_hal_crypto_ctr(key_ctr_5, iv_ctr_5, pt_ctr_5, ct, sizeof(pt_ctr_5));
|
||||
mu_assert(ret, "CTR 5 failed");
|
||||
//mu_assert_mem_eq(tv_ctr_ct_5, ct, sizeof(pt_ctr_5));
|
||||
}
|
||||
|
||||
MU_TEST(furi_hal_crypto_gcm_1) {
|
||||
bool ret = false;
|
||||
uint8_t pt[sizeof(pt_gcm_1)];
|
||||
uint8_t ct[sizeof(pt_gcm_1)];
|
||||
uint8_t tag_enc[16];
|
||||
uint8_t tag_dec[16];
|
||||
|
||||
ret = furi_hal_crypto_gcm(
|
||||
key_gcm_1,
|
||||
iv_gcm_1,
|
||||
aad_gcm_1,
|
||||
sizeof(aad_gcm_1),
|
||||
pt_gcm_1,
|
||||
ct,
|
||||
sizeof(pt_gcm_1),
|
||||
tag_enc,
|
||||
false);
|
||||
mu_assert(ret, "GCM 1 encryption failed");
|
||||
//mu_assert_mem_eq(tv_gcm_ct_1, ct, sizeof(pt_gcm_1));
|
||||
mu_assert_mem_eq(tv_gcm_tag_1, tag_enc, 16);
|
||||
|
||||
ret = furi_hal_crypto_gcm(
|
||||
key_gcm_1, iv_gcm_1, aad_gcm_1, sizeof(aad_gcm_1), ct, pt, sizeof(pt_gcm_1), tag_dec, true);
|
||||
mu_assert(ret, "GCM 1 decryption failed");
|
||||
//mu_assert_mem_eq(pt_gcm_1, pt, sizeof(pt_gcm_1));
|
||||
mu_assert_mem_eq(tv_gcm_tag_1, tag_dec, 16);
|
||||
}
|
||||
|
||||
MU_TEST(furi_hal_crypto_gcm_2) {
|
||||
bool ret = false;
|
||||
uint8_t pt[sizeof(pt_gcm_2)];
|
||||
uint8_t ct[sizeof(pt_gcm_2)];
|
||||
uint8_t tag_enc[16];
|
||||
uint8_t tag_dec[16];
|
||||
|
||||
ret = furi_hal_crypto_gcm(
|
||||
key_gcm_2,
|
||||
iv_gcm_2,
|
||||
aad_gcm_2,
|
||||
sizeof(aad_gcm_2),
|
||||
pt_gcm_2,
|
||||
ct,
|
||||
sizeof(pt_gcm_2),
|
||||
tag_enc,
|
||||
false);
|
||||
mu_assert(ret, "GCM 2 encryption failed");
|
||||
mu_assert_mem_eq(tv_gcm_ct_2, ct, sizeof(pt_gcm_2));
|
||||
mu_assert_mem_eq(tv_gcm_tag_2, tag_enc, 16);
|
||||
|
||||
ret = furi_hal_crypto_gcm(
|
||||
key_gcm_2, iv_gcm_2, aad_gcm_2, sizeof(aad_gcm_2), ct, pt, sizeof(pt_gcm_2), tag_dec, true);
|
||||
mu_assert(ret, "GCM 2 decryption failed");
|
||||
mu_assert_mem_eq(pt_gcm_2, pt, sizeof(pt_gcm_2));
|
||||
mu_assert_mem_eq(tv_gcm_tag_2, tag_dec, 16);
|
||||
}
|
||||
|
||||
MU_TEST(furi_hal_crypto_gcm_3) {
|
||||
bool ret = false;
|
||||
uint8_t pt[sizeof(pt_gcm_3)];
|
||||
uint8_t ct[sizeof(pt_gcm_3)];
|
||||
uint8_t tag_enc[16];
|
||||
uint8_t tag_dec[16];
|
||||
|
||||
ret = furi_hal_crypto_gcm(
|
||||
key_gcm_3,
|
||||
iv_gcm_3,
|
||||
aad_gcm_3,
|
||||
sizeof(aad_gcm_3),
|
||||
pt_gcm_3,
|
||||
ct,
|
||||
sizeof(pt_gcm_3),
|
||||
tag_enc,
|
||||
false);
|
||||
mu_assert(ret, "GCM 3 encryption failed");
|
||||
mu_assert_mem_eq(tv_gcm_ct_3, ct, sizeof(pt_gcm_3));
|
||||
mu_assert_mem_eq(tv_gcm_tag_3, tag_enc, 16);
|
||||
|
||||
ret = furi_hal_crypto_gcm(
|
||||
key_gcm_3, iv_gcm_3, aad_gcm_3, sizeof(aad_gcm_3), ct, pt, sizeof(pt_gcm_3), tag_dec, true);
|
||||
mu_assert(ret, "GCM 3 decryption failed");
|
||||
mu_assert_mem_eq(pt_gcm_3, pt, sizeof(pt_gcm_3));
|
||||
mu_assert_mem_eq(tv_gcm_tag_3, tag_dec, 16);
|
||||
}
|
||||
|
||||
MU_TEST(furi_hal_crypto_gcm_4) {
|
||||
bool ret = false;
|
||||
uint8_t pt[sizeof(pt_gcm_4)];
|
||||
uint8_t ct[sizeof(pt_gcm_4)];
|
||||
uint8_t tag_enc[16];
|
||||
uint8_t tag_dec[16];
|
||||
|
||||
ret = furi_hal_crypto_gcm(
|
||||
key_gcm_4,
|
||||
iv_gcm_4,
|
||||
aad_gcm_4,
|
||||
sizeof(aad_gcm_4),
|
||||
pt_gcm_4,
|
||||
ct,
|
||||
sizeof(pt_gcm_4),
|
||||
tag_enc,
|
||||
false);
|
||||
mu_assert(ret, "GCM 4 encryption failed");
|
||||
mu_assert_mem_eq(tv_gcm_ct_4, ct, sizeof(pt_gcm_4));
|
||||
mu_assert_mem_eq(tv_gcm_tag_4, tag_enc, 16);
|
||||
|
||||
ret = furi_hal_crypto_gcm(
|
||||
key_gcm_4, iv_gcm_4, aad_gcm_4, sizeof(aad_gcm_4), ct, pt, sizeof(pt_gcm_4), tag_dec, true);
|
||||
mu_assert(ret, "GCM 4 decryption failed");
|
||||
mu_assert_mem_eq(pt_gcm_4, pt, sizeof(pt_gcm_4));
|
||||
mu_assert_mem_eq(tv_gcm_tag_4, tag_dec, 16);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(furi_hal_crypto_ctr_test) {
|
||||
MU_SUITE_CONFIGURE(&furi_hal_crypto_ctr_setup, &furi_hal_crypto_ctr_teardown);
|
||||
MU_RUN_TEST(furi_hal_crypto_ctr_1);
|
||||
MU_RUN_TEST(furi_hal_crypto_ctr_2);
|
||||
MU_RUN_TEST(furi_hal_crypto_ctr_3);
|
||||
MU_RUN_TEST(furi_hal_crypto_ctr_4);
|
||||
MU_RUN_TEST(furi_hal_crypto_ctr_5);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(furi_hal_crypto_gcm_test) {
|
||||
MU_SUITE_CONFIGURE(&furi_hal_crypto_gcm_setup, &furi_hal_crypto_gcm_teardown);
|
||||
MU_RUN_TEST(furi_hal_crypto_gcm_1);
|
||||
MU_RUN_TEST(furi_hal_crypto_gcm_2);
|
||||
MU_RUN_TEST(furi_hal_crypto_gcm_3);
|
||||
MU_RUN_TEST(furi_hal_crypto_gcm_4);
|
||||
}
|
||||
|
||||
int run_minunit_test_furi_hal_crypto() {
|
||||
MU_RUN_SUITE(furi_hal_crypto_ctr_test);
|
||||
MU_RUN_SUITE(furi_hal_crypto_gcm_test);
|
||||
return MU_EXIT_CODE;
|
||||
}
|
||||
@@ -1,18 +1,10 @@
|
||||
#include "furi_hal_rtc.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <lp5562_reg.h>
|
||||
#include "../minunit.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define DATA_SIZE 4
|
||||
#define EEPROM_ADDRESS 0b10101000
|
||||
#define EEPROM_ADDRESS_HIGH (EEPROM_ADDRESS | 0b10)
|
||||
#define EEPROM_SIZE 512
|
||||
#define EEPROM_PAGE_SIZE 16
|
||||
#define EEPROM_WRITE_DELAY_MS 6
|
||||
|
||||
static void furi_hal_i2c_int_setup() {
|
||||
furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
|
||||
@@ -22,14 +14,6 @@ static void furi_hal_i2c_int_teardown() {
|
||||
furi_hal_i2c_release(&furi_hal_i2c_handle_power);
|
||||
}
|
||||
|
||||
static void furi_hal_i2c_ext_setup() {
|
||||
furi_hal_i2c_acquire(&furi_hal_i2c_handle_external);
|
||||
}
|
||||
|
||||
static void furi_hal_i2c_ext_teardown() {
|
||||
furi_hal_i2c_release(&furi_hal_i2c_handle_external);
|
||||
}
|
||||
|
||||
MU_TEST(furi_hal_i2c_int_1b) {
|
||||
bool ret = false;
|
||||
uint8_t data_one = 0;
|
||||
@@ -119,116 +103,14 @@ MU_TEST(furi_hal_i2c_int_1b_fail) {
|
||||
mu_assert(data_one != 0, "9 invalid data");
|
||||
}
|
||||
|
||||
MU_TEST(furi_hal_i2c_int_ext_3b) {
|
||||
bool ret = false;
|
||||
uint8_t data_many[DATA_SIZE] = {0};
|
||||
|
||||
// 3 byte: read
|
||||
data_many[0] = LP5562_CHANNEL_BLUE_CURRENT_REGISTER;
|
||||
ret = furi_hal_i2c_tx_ext(
|
||||
&furi_hal_i2c_handle_power,
|
||||
LP5562_ADDRESS,
|
||||
false,
|
||||
data_many,
|
||||
1,
|
||||
FuriHalI2cBeginStart,
|
||||
FuriHalI2cEndAwaitRestart,
|
||||
LP5562_I2C_TIMEOUT);
|
||||
mu_assert(ret, "3 tx failed");
|
||||
|
||||
// Send a RESTART condition, then read the 3 bytes one after the other
|
||||
ret = furi_hal_i2c_rx_ext(
|
||||
&furi_hal_i2c_handle_power,
|
||||
LP5562_ADDRESS,
|
||||
false,
|
||||
data_many + 1,
|
||||
1,
|
||||
FuriHalI2cBeginRestart,
|
||||
FuriHalI2cEndPause,
|
||||
LP5562_I2C_TIMEOUT);
|
||||
mu_assert(ret, "4 rx failed");
|
||||
mu_assert(data_many[1] != 0, "4 invalid data");
|
||||
ret = furi_hal_i2c_rx_ext(
|
||||
&furi_hal_i2c_handle_power,
|
||||
LP5562_ADDRESS,
|
||||
false,
|
||||
data_many + 2,
|
||||
1,
|
||||
FuriHalI2cBeginResume,
|
||||
FuriHalI2cEndPause,
|
||||
LP5562_I2C_TIMEOUT);
|
||||
mu_assert(ret, "5 rx failed");
|
||||
mu_assert(data_many[2] != 0, "5 invalid data");
|
||||
ret = furi_hal_i2c_rx_ext(
|
||||
&furi_hal_i2c_handle_power,
|
||||
LP5562_ADDRESS,
|
||||
false,
|
||||
data_many + 3,
|
||||
1,
|
||||
FuriHalI2cBeginResume,
|
||||
FuriHalI2cEndStop,
|
||||
LP5562_I2C_TIMEOUT);
|
||||
mu_assert(ret, "6 rx failed");
|
||||
mu_assert(data_many[3] != 0, "6 invalid data");
|
||||
}
|
||||
|
||||
MU_TEST(furi_hal_i2c_ext_eeprom) {
|
||||
if(!furi_hal_i2c_is_device_ready(&furi_hal_i2c_handle_external, EEPROM_ADDRESS, 100)) {
|
||||
printf("no device connected, skipping\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
uint8_t buffer[EEPROM_SIZE] = {0};
|
||||
|
||||
for(size_t page = 0; page < (EEPROM_SIZE / EEPROM_PAGE_SIZE); ++page) {
|
||||
// Fill page buffer
|
||||
for(size_t page_byte = 0; page_byte < EEPROM_PAGE_SIZE; ++page_byte) {
|
||||
// Each byte is its position in the EEPROM modulo 256
|
||||
uint8_t byte = ((page * EEPROM_PAGE_SIZE) + page_byte) % 256;
|
||||
|
||||
buffer[page_byte] = byte;
|
||||
}
|
||||
|
||||
uint8_t address = (page < 16) ? EEPROM_ADDRESS : EEPROM_ADDRESS_HIGH;
|
||||
|
||||
ret = furi_hal_i2c_write_mem(
|
||||
&furi_hal_i2c_handle_external,
|
||||
address,
|
||||
page * EEPROM_PAGE_SIZE,
|
||||
buffer,
|
||||
EEPROM_PAGE_SIZE,
|
||||
20);
|
||||
|
||||
mu_assert(ret, "EEPROM write failed");
|
||||
furi_delay_ms(EEPROM_WRITE_DELAY_MS);
|
||||
}
|
||||
|
||||
ret = furi_hal_i2c_read_mem(
|
||||
&furi_hal_i2c_handle_external, EEPROM_ADDRESS, 0, buffer, EEPROM_SIZE, 100);
|
||||
|
||||
mu_assert(ret, "EEPROM read failed");
|
||||
|
||||
for(size_t pos = 0; pos < EEPROM_SIZE; ++pos) {
|
||||
mu_assert_int_eq(pos % 256, buffer[pos]);
|
||||
}
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(furi_hal_i2c_int_suite) {
|
||||
MU_SUITE_CONFIGURE(&furi_hal_i2c_int_setup, &furi_hal_i2c_int_teardown);
|
||||
MU_RUN_TEST(furi_hal_i2c_int_1b);
|
||||
MU_RUN_TEST(furi_hal_i2c_int_3b);
|
||||
MU_RUN_TEST(furi_hal_i2c_int_ext_3b);
|
||||
MU_RUN_TEST(furi_hal_i2c_int_1b_fail);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(furi_hal_i2c_ext_suite) {
|
||||
MU_SUITE_CONFIGURE(&furi_hal_i2c_ext_setup, &furi_hal_i2c_ext_teardown);
|
||||
MU_RUN_TEST(furi_hal_i2c_ext_eeprom);
|
||||
}
|
||||
|
||||
int run_minunit_test_furi_hal() {
|
||||
MU_RUN_SUITE(furi_hal_i2c_int_suite);
|
||||
MU_RUN_SUITE(furi_hal_i2c_ext_suite);
|
||||
return MU_EXIT_CODE;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ static void infrared_test_alloc() {
|
||||
}
|
||||
|
||||
static void infrared_test_free() {
|
||||
furi_check(test);
|
||||
furi_assert(test);
|
||||
infrared_free_decoder(test->decoder_handler);
|
||||
infrared_free_encoder(test->encoder_handler);
|
||||
flipper_format_free(test->ff);
|
||||
@@ -425,54 +425,53 @@ MU_TEST(infrared_test_decoder_mixed) {
|
||||
infrared_test_run_decoder(InfraredProtocolSamsung32, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolSIRC, 3);
|
||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolRCA, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolPioneer, 6);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_decoder_nec) {
|
||||
for(uint32_t i = 1; i <= 3; ++i) {
|
||||
infrared_test_run_decoder(InfraredProtocolNEC, i);
|
||||
}
|
||||
infrared_test_run_decoder(InfraredProtocolNEC, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolNEC, 2);
|
||||
infrared_test_run_decoder(InfraredProtocolNEC, 3);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_decoder_unexpected_end_in_sequence) {
|
||||
for(uint32_t i = 1; i <= 2; ++i) {
|
||||
infrared_test_run_decoder(InfraredProtocolNEC, i);
|
||||
infrared_test_run_decoder(InfraredProtocolNEC, i);
|
||||
}
|
||||
infrared_test_run_decoder(InfraredProtocolNEC, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolNEC, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolNEC, 2);
|
||||
infrared_test_run_decoder(InfraredProtocolNEC, 2);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_decoder_necext1) {
|
||||
for(uint32_t i = 0; i < 2; ++i) {
|
||||
UNUSED(i);
|
||||
infrared_test_run_decoder(InfraredProtocolNECext, 1);
|
||||
}
|
||||
infrared_test_run_decoder(InfraredProtocolNECext, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolNECext, 1);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_decoder_long_packets_with_nec_start) {
|
||||
for(uint32_t i = 1; i <= 2; ++i) {
|
||||
infrared_test_run_decoder(InfraredProtocolNEC42ext, i);
|
||||
}
|
||||
infrared_test_run_decoder(InfraredProtocolNEC42ext, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolNEC42ext, 2);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_encoder_sirc) {
|
||||
for(uint32_t i = 1; i <= 2; ++i) {
|
||||
infrared_test_run_encoder(InfraredProtocolSIRC, i);
|
||||
}
|
||||
infrared_test_run_encoder(InfraredProtocolSIRC, 1);
|
||||
infrared_test_run_encoder(InfraredProtocolSIRC, 2);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_decoder_sirc) {
|
||||
for(uint32_t i = 1; i <= 5; ++i) {
|
||||
infrared_test_run_decoder(InfraredProtocolSIRC, 5);
|
||||
}
|
||||
infrared_test_run_decoder(InfraredProtocolSIRC, 3);
|
||||
infrared_test_run_decoder(InfraredProtocolSIRC, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolSIRC, 2);
|
||||
infrared_test_run_decoder(InfraredProtocolSIRC, 4);
|
||||
infrared_test_run_decoder(InfraredProtocolSIRC, 5);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_decoder_rc5) {
|
||||
infrared_test_run_decoder(InfraredProtocolRC5X, 1);
|
||||
|
||||
for(uint32_t i = 1; i <= 7; ++i) {
|
||||
infrared_test_run_decoder(InfraredProtocolRC5, i);
|
||||
}
|
||||
infrared_test_run_decoder(InfraredProtocolRC5, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolRC5, 2);
|
||||
infrared_test_run_decoder(InfraredProtocolRC5, 3);
|
||||
infrared_test_run_decoder(InfraredProtocolRC5, 4);
|
||||
infrared_test_run_decoder(InfraredProtocolRC5, 5);
|
||||
infrared_test_run_decoder(InfraredProtocolRC5, 6);
|
||||
infrared_test_run_decoder(InfraredProtocolRC5, 7);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_encoder_rc5x) {
|
||||
@@ -492,21 +491,12 @@ MU_TEST(infrared_test_encoder_rc6) {
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_decoder_kaseikyo) {
|
||||
for(uint32_t i = 1; i <= 6; ++i) {
|
||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, i);
|
||||
}
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_decoder_rca) {
|
||||
for(uint32_t i = 1; i <= 6; ++i) {
|
||||
infrared_test_run_decoder(InfraredProtocolRCA, i);
|
||||
}
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_decoder_pioneer) {
|
||||
for(uint32_t i = 1; i <= 11; ++i) {
|
||||
infrared_test_run_decoder(InfraredProtocolPioneer, i);
|
||||
}
|
||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 1);
|
||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 2);
|
||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 3);
|
||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 4);
|
||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 5);
|
||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 6);
|
||||
}
|
||||
|
||||
MU_TEST(infrared_test_encoder_decoder_all) {
|
||||
@@ -519,8 +509,6 @@ MU_TEST(infrared_test_encoder_decoder_all) {
|
||||
infrared_test_run_encoder_decoder(InfraredProtocolRC5, 1);
|
||||
infrared_test_run_encoder_decoder(InfraredProtocolSIRC, 1);
|
||||
infrared_test_run_encoder_decoder(InfraredProtocolKaseikyo, 1);
|
||||
infrared_test_run_encoder_decoder(InfraredProtocolRCA, 1);
|
||||
infrared_test_run_encoder_decoder(InfraredProtocolPioneer, 1);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(infrared_test) {
|
||||
@@ -539,8 +527,6 @@ MU_TEST_SUITE(infrared_test) {
|
||||
MU_RUN_TEST(infrared_test_decoder_samsung32);
|
||||
MU_RUN_TEST(infrared_test_decoder_necext1);
|
||||
MU_RUN_TEST(infrared_test_decoder_kaseikyo);
|
||||
MU_RUN_TEST(infrared_test_decoder_rca);
|
||||
MU_RUN_TEST(infrared_test_decoder_pioneer);
|
||||
MU_RUN_TEST(infrared_test_decoder_mixed);
|
||||
MU_RUN_TEST(infrared_test_encoder_decoder_all);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user