Compare commits
63 Commits
nfcrefacto
...
unlshd-058
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a676f7afa | ||
|
|
ca479303a1 | ||
|
|
5e649d8c41 | ||
|
|
0bc626ba1d | ||
|
|
3821ee7709 | ||
|
|
cb17189b15 | ||
|
|
80e8167054 | ||
|
|
eede5ed29e | ||
|
|
360fef7777 | ||
|
|
b83da5d3cb | ||
|
|
ae5d28fbc5 | ||
|
|
f4cd7c0100 | ||
|
|
7b68fd30ec | ||
|
|
ac222f1b0c | ||
|
|
b0e8e68909 | ||
|
|
ef5f6e2f70 | ||
|
|
30f6da3fa3 | ||
|
|
3a47154cdb | ||
|
|
d953d35991 | ||
|
|
4b74d13e10 | ||
|
|
98bf353287 | ||
|
|
eb8c751b31 | ||
|
|
9abad8704f | ||
|
|
6716c0f792 | ||
|
|
35f7ec6c07 | ||
|
|
a524fd7674 | ||
|
|
ff27fd3094 | ||
|
|
977ac09fe6 | ||
|
|
1a88e01899 | ||
|
|
6e710c5164 | ||
|
|
fd56ac3400 | ||
|
|
1d801c38f9 | ||
|
|
8afdb5b7b4 | ||
|
|
83624b1dee | ||
|
|
56adcf1ad8 | ||
|
|
ad27f87a0c | ||
|
|
346cf299ee | ||
|
|
05489fda7d | ||
|
|
1b12526357 | ||
|
|
802035d92e | ||
|
|
a24d0f1958 | ||
|
|
da68f2e4ed | ||
|
|
8f16dbb8e7 | ||
|
|
49e458f1b5 | ||
|
|
5cf46d2aa9 | ||
|
|
beedf54e75 | ||
|
|
70ccb89c3d | ||
|
|
5ea43a2a4b | ||
|
|
41f60dbbf4 | ||
|
|
827341ec08 | ||
|
|
5c36043d03 | ||
|
|
cf5811f8d9 | ||
|
|
ec6a169bf8 | ||
|
|
f1dec87c1b | ||
|
|
ab29951a99 | ||
|
|
bbe9f88bbe | ||
|
|
9188bf0013 | ||
|
|
f33ed59567 | ||
|
|
3fd8c80861 | ||
|
|
7b8ac3a5a0 | ||
|
|
6fef957001 | ||
|
|
0de1c9df89 | ||
|
|
a0e8cfbe97 |
@@ -161,17 +161,3 @@ Max butthurt: 5
|
|||||||
Min level: 1
|
Min level: 1
|
||||||
Max level: 3
|
Max level: 3
|
||||||
Weight: 4
|
Weight: 4
|
||||||
|
|
||||||
Name: L1_Sad_song_128x64
|
|
||||||
Min butthurt: 8
|
|
||||||
Max butthurt: 13
|
|
||||||
Min level: 1
|
|
||||||
Max level: 3
|
|
||||||
Weight: 4
|
|
||||||
|
|
||||||
Name: L2_Coding_in_the_shell_128x64
|
|
||||||
Min butthurt: 0
|
|
||||||
Max butthurt: 12
|
|
||||||
Min level: 2
|
|
||||||
Max level: 3
|
|
||||||
Weight: 4
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
diff --git a/applications/services/notification/notification_app.c b/applications/services/notification/notification_app.c
|
diff --git a/applications/services/notification/notification_app.c b/applications/services/notification/notification_app.c
|
||||||
index 5769ced..c5d3088 100644
|
index 2f947fe..03c4c76 100644
|
||||||
--- a/applications/services/notification/notification_app.c
|
--- a/applications/services/notification/notification_app.c
|
||||||
+++ b/applications/services/notification/notification_app.c
|
+++ b/applications/services/notification/notification_app.c
|
||||||
@@ -9,6 +9,7 @@
|
@@ -9,6 +9,7 @@
|
||||||
@@ -10,7 +10,7 @@ index 5769ced..c5d3088 100644
|
|||||||
|
|
||||||
#define TAG "NotificationSrv"
|
#define TAG "NotificationSrv"
|
||||||
|
|
||||||
@@ -589,6 +590,7 @@ int32_t notification_srv(void* p) {
|
@@ -579,6 +580,7 @@ int32_t notification_srv(void* p) {
|
||||||
break;
|
break;
|
||||||
case SaveSettingsMessage:
|
case SaveSettingsMessage:
|
||||||
notification_save_settings(app);
|
notification_save_settings(app);
|
||||||
@@ -19,7 +19,7 @@ index 5769ced..c5d3088 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
diff --git a/applications/settings/notification_settings/notification_settings_app.c b/applications/settings/notification_settings/notification_settings_app.c
|
diff --git a/applications/settings/notification_settings/notification_settings_app.c b/applications/settings/notification_settings/notification_settings_app.c
|
||||||
index 1955012..19d953d 100644
|
index 565d4f1..bae9299 100644
|
||||||
--- a/applications/settings/notification_settings/notification_settings_app.c
|
--- a/applications/settings/notification_settings/notification_settings_app.c
|
||||||
+++ b/applications/settings/notification_settings/notification_settings_app.c
|
+++ b/applications/settings/notification_settings/notification_settings_app.c
|
||||||
@@ -3,6 +3,7 @@
|
@@ -3,6 +3,7 @@
|
||||||
@@ -30,20 +30,10 @@ index 1955012..19d953d 100644
|
|||||||
|
|
||||||
#define MAX_NOTIFICATION_SETTINGS 4
|
#define MAX_NOTIFICATION_SETTINGS 4
|
||||||
|
|
||||||
@@ -20,6 +21,8 @@ static const NotificationSequence sequence_note_c = {
|
@@ -162,6 +163,14 @@ static void vibro_changed(VariableItem* item) {
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
+static VariableItem* temp_item;
|
|
||||||
+
|
|
||||||
#define CONTRAST_COUNT 11
|
|
||||||
const char* const contrast_text[CONTRAST_COUNT] = {
|
|
||||||
"-5",
|
|
||||||
@@ -156,6 +159,59 @@ static void vibro_changed(VariableItem* item) {
|
|
||||||
notification_message(app->notification, &sequence_single_vibro);
|
notification_message(app->notification, &sequence_single_vibro);
|
||||||
}
|
}
|
||||||
|
|
||||||
+// Set RGB backlight color
|
|
||||||
+static void color_changed(VariableItem* item) {
|
+static void color_changed(VariableItem* item) {
|
||||||
+ NotificationAppSettings* app = variable_item_get_context(item);
|
+ NotificationAppSettings* app = variable_item_get_context(item);
|
||||||
+ uint8_t index = variable_item_get_current_value_index(item);
|
+ uint8_t index = variable_item_get_current_value_index(item);
|
||||||
@@ -51,102 +41,31 @@ index 1955012..19d953d 100644
|
|||||||
+ variable_item_set_current_value_text(item, rgb_backlight_get_color_text(index));
|
+ variable_item_set_current_value_text(item, rgb_backlight_get_color_text(index));
|
||||||
+ notification_message(app->notification, &sequence_display_backlight_on);
|
+ 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) {
|
static uint32_t notification_app_settings_exit(void* context) {
|
||||||
UNUSED(context);
|
UNUSED(context);
|
||||||
return VIEW_NONE;
|
return VIEW_NONE;
|
||||||
@@ -180,8 +236,40 @@ static NotificationAppSettings* alloc_settings() {
|
@@ -187,7 +196,13 @@ static NotificationAppSettings* alloc_settings() {
|
||||||
variable_item_set_current_value_index(item, value_index);
|
|
||||||
variable_item_set_current_value_text(item, contrast_text[value_index]);
|
variable_item_set_current_value_text(item, contrast_text[value_index]);
|
||||||
|
|
||||||
+ // RGB Colors
|
item = variable_item_list_add(
|
||||||
+ item = variable_item_list_add(
|
- app->variable_item_list, "LCD Backlight", BACKLIGHT_COUNT, backlight_changed, app);
|
||||||
+ app->variable_item_list, "LCD Color", rgb_backlight_get_color_count(), color_changed, app);
|
+ app->variable_item_list, "LCD Color", rgb_backlight_get_color_count(), color_changed, app);
|
||||||
+ value_index = rgb_backlight_get_settings()->display_color_index;
|
+ value_index = rgb_backlight_get_settings()->display_color_index;
|
||||||
+ variable_item_set_current_value_index(item, value_index);
|
+ variable_item_set_current_value_index(item, value_index);
|
||||||
+ variable_item_set_current_value_text(item, rgb_backlight_get_color_text(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(
|
+ 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);
|
+ app->variable_item_list, "LCD Brightness", BACKLIGHT_COUNT, backlight_changed, app);
|
||||||
value_index = value_index_float(
|
value_index = value_index_float(
|
||||||
app->notification->settings.display_brightness, backlight_value, BACKLIGHT_COUNT);
|
app->notification->settings.display_brightness, backlight_value, BACKLIGHT_COUNT);
|
||||||
variable_item_set_current_value_index(item, value_index);
|
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
|
diff --git a/applications/settings/notification_settings/rgb_backlight.c b/applications/settings/notification_settings/rgb_backlight.c
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000..98f0d3a
|
index 0000000..269b544
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/applications/settings/notification_settings/rgb_backlight.c
|
+++ b/applications/settings/notification_settings/rgb_backlight.c
|
||||||
@@ -0,0 +1,217 @@
|
@@ -0,0 +1,171 @@
|
||||||
+/*
|
+/*
|
||||||
+ RGB backlight FlipperZero driver
|
+ RGB backlight FlipperZero driver
|
||||||
+ Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
|
+ Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
|
||||||
@@ -169,9 +88,9 @@ index 0000000..98f0d3a
|
|||||||
+#include <furi_hal.h>
|
+#include <furi_hal.h>
|
||||||
+#include <storage/storage.h>
|
+#include <storage/storage.h>
|
||||||
+
|
+
|
||||||
+#define RGB_BACKLIGHT_SETTINGS_VERSION 6
|
+#define RGB_BACKLIGHT_SETTINGS_VERSION 5
|
||||||
+#define RGB_BACKLIGHT_SETTINGS_FILE_NAME ".rgb_backlight.settings"
|
+#define RGB_BACKLIGHT_SETTINGS_FILE_NAME ".rgb_backlight.settings"
|
||||||
+#define RGB_BACKLIGHT_SETTINGS_PATH INT_PATH(RGB_BACKLIGHT_SETTINGS_FILE_NAME)
|
+#define RGB_BACKLIGHT_SETTINGS_PATH EXT_PATH(RGB_BACKLIGHT_SETTINGS_FILE_NAME)
|
||||||
+
|
+
|
||||||
+#define COLOR_COUNT (sizeof(colors) / sizeof(RGBBacklightColor))
|
+#define COLOR_COUNT (sizeof(colors) / sizeof(RGBBacklightColor))
|
||||||
+
|
+
|
||||||
@@ -180,14 +99,11 @@ index 0000000..98f0d3a
|
|||||||
+static RGBBacklightSettings rgb_settings = {
|
+static RGBBacklightSettings rgb_settings = {
|
||||||
+ .version = RGB_BACKLIGHT_SETTINGS_VERSION,
|
+ .version = RGB_BACKLIGHT_SETTINGS_VERSION,
|
||||||
+ .display_color_index = 0,
|
+ .display_color_index = 0,
|
||||||
+ .custom_r = 254,
|
|
||||||
+ .custom_g = 254,
|
|
||||||
+ .custom_b = 254,
|
|
||||||
+ .settings_is_loaded = false};
|
+ .settings_is_loaded = false};
|
||||||
+
|
+
|
||||||
+static const RGBBacklightColor colors[] = {
|
+static const RGBBacklightColor colors[] = {
|
||||||
+ {"Orange", 255, 60, 0},
|
+ {"Orange", 255, 79, 0},
|
||||||
+ {"Yellow", 255, 144, 0},
|
+ {"Yellow", 255, 170, 0},
|
||||||
+ {"Spring", 167, 255, 0},
|
+ {"Spring", 167, 255, 0},
|
||||||
+ {"Lime", 0, 255, 0},
|
+ {"Lime", 0, 255, 0},
|
||||||
+ {"Aqua", 0, 255, 127},
|
+ {"Aqua", 0, 255, 127},
|
||||||
@@ -198,8 +114,7 @@ index 0000000..98f0d3a
|
|||||||
+ {"Magenta", 210, 0, 210},
|
+ {"Magenta", 210, 0, 210},
|
||||||
+ {"Pink", 255, 0, 127},
|
+ {"Pink", 255, 0, 127},
|
||||||
+ {"Red", 255, 0, 0},
|
+ {"Red", 255, 0, 0},
|
||||||
+ {"White", 254, 210, 200},
|
+ {"White", 140, 140, 140},
|
||||||
+ {"Custom", 0, 0, 0},
|
|
||||||
+};
|
+};
|
||||||
+
|
+
|
||||||
+uint8_t rgb_backlight_get_color_count(void) {
|
+uint8_t rgb_backlight_get_color_count(void) {
|
||||||
@@ -211,28 +126,18 @@ index 0000000..98f0d3a
|
|||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+void rgb_backlight_load_settings(void) {
|
+void rgb_backlight_load_settings(void) {
|
||||||
+ // Do not load settings if we are in other boot modes than normal
|
+ //Не загружать данные из внутренней памяти при загрузке в режиме DFU
|
||||||
+ if(furi_hal_rtc_get_boot_mode() != FuriHalRtcBootModeNormal) {
|
+ FuriHalRtcBootMode bm = furi_hal_rtc_get_boot_mode();
|
||||||
|
+ if(bm == FuriHalRtcBootModeDfu) {
|
||||||
+ rgb_settings.settings_is_loaded = true;
|
+ rgb_settings.settings_is_loaded = true;
|
||||||
+ return;
|
+ 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;
|
+ RGBBacklightSettings settings;
|
||||||
+ File* file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
|
+ File* file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
|
||||||
+ const size_t settings_size = sizeof(RGBBacklightSettings);
|
+ const size_t settings_size = sizeof(RGBBacklightSettings);
|
||||||
+
|
+
|
||||||
+ FURI_LOG_D(TAG, "loading settings from \"%s\"", RGB_BACKLIGHT_SETTINGS_PATH);
|
+ FURI_LOG_I(TAG, "loading settings from \"%s\"", RGB_BACKLIGHT_SETTINGS_PATH);
|
||||||
+ bool fs_result =
|
+ bool fs_result =
|
||||||
+ storage_file_open(file, RGB_BACKLIGHT_SETTINGS_PATH, FSAM_READ, FSOM_OPEN_EXISTING);
|
+ storage_file_open(file, RGB_BACKLIGHT_SETTINGS_PATH, FSAM_READ, FSOM_OPEN_EXISTING);
|
||||||
+
|
+
|
||||||
@@ -245,7 +150,7 @@ index 0000000..98f0d3a
|
|||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ if(fs_result) {
|
+ if(fs_result) {
|
||||||
+ FURI_LOG_D(TAG, "load success");
|
+ FURI_LOG_I(TAG, "load success");
|
||||||
+ if(settings.version != RGB_BACKLIGHT_SETTINGS_VERSION) {
|
+ if(settings.version != RGB_BACKLIGHT_SETTINGS_VERSION) {
|
||||||
+ FURI_LOG_E(
|
+ FURI_LOG_E(
|
||||||
+ TAG,
|
+ TAG,
|
||||||
@@ -270,7 +175,7 @@ index 0000000..98f0d3a
|
|||||||
+ File* file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
|
+ File* file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
|
||||||
+ const size_t settings_size = sizeof(RGBBacklightSettings);
|
+ const size_t settings_size = sizeof(RGBBacklightSettings);
|
||||||
+
|
+
|
||||||
+ FURI_LOG_D(TAG, "saving settings to \"%s\"", RGB_BACKLIGHT_SETTINGS_PATH);
|
+ FURI_LOG_I(TAG, "saving settings to \"%s\"", RGB_BACKLIGHT_SETTINGS_PATH);
|
||||||
+
|
+
|
||||||
+ memcpy(&settings, &rgb_settings, settings_size);
|
+ memcpy(&settings, &rgb_settings, settings_size);
|
||||||
+
|
+
|
||||||
@@ -286,7 +191,7 @@ index 0000000..98f0d3a
|
|||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ if(fs_result) {
|
+ if(fs_result) {
|
||||||
+ FURI_LOG_D(TAG, "save success");
|
+ FURI_LOG_I(TAG, "save success");
|
||||||
+ } else {
|
+ } else {
|
||||||
+ FURI_LOG_E(TAG, "save failed, %s", storage_file_get_error_desc(file));
|
+ FURI_LOG_E(TAG, "save failed, %s", storage_file_get_error_desc(file));
|
||||||
+ }
|
+ }
|
||||||
@@ -308,68 +213,36 @@ index 0000000..98f0d3a
|
|||||||
+ rgb_settings.display_color_index = color_index;
|
+ rgb_settings.display_color_index = color_index;
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+void rgb_backlight_set_custom_color(uint8_t color, uint8_t index) {
|
+void rgb_backlight_update(uint8_t brightness) {
|
||||||
+ 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) {
|
+ if(!rgb_settings.settings_is_loaded) {
|
||||||
+ rgb_backlight_load_settings();
|
+ rgb_backlight_load_settings();
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ if(!bypass) {
|
+ static uint8_t last_color_index = 255;
|
||||||
+ static uint8_t last_color_index = 255;
|
+ static uint8_t last_brightness = 123;
|
||||||
+ static uint8_t last_brightness = 123;
|
|
||||||
+
|
+
|
||||||
+ if(last_brightness == brightness && last_color_index == rgb_settings.display_color_index) {
|
+ if(last_brightness == brightness && last_color_index == rgb_settings.display_color_index)
|
||||||
+ return;
|
+ return;
|
||||||
+ }
|
|
||||||
+
|
+
|
||||||
+ last_brightness = brightness;
|
+ last_brightness = brightness;
|
||||||
+ last_color_index = rgb_settings.display_color_index;
|
+ last_color_index = rgb_settings.display_color_index;
|
||||||
+ }
|
|
||||||
+
|
+
|
||||||
+ for(uint8_t i = 0; i < SK6805_get_led_count(); i++) {
|
+ for(uint8_t i = 0; i < SK6805_get_led_count(); i++) {
|
||||||
+ if(rgb_settings.display_color_index == 13) {
|
+ uint8_t r = colors[rgb_settings.display_color_index].red * (brightness / 255.0f);
|
||||||
+ uint8_t r = rgb_settings.custom_r * (brightness / 255.0f);
|
+ uint8_t g = colors[rgb_settings.display_color_index].green * (brightness / 255.0f);
|
||||||
+ uint8_t g = rgb_settings.custom_g * (brightness / 255.0f);
|
+ uint8_t b = colors[rgb_settings.display_color_index].blue * (brightness / 255.0f);
|
||||||
+ uint8_t b = rgb_settings.custom_b * (brightness / 255.0f);
|
|
||||||
+
|
+
|
||||||
+ SK6805_set_led_color(i, r, g, b);
|
+ 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();
|
+ SK6805_update();
|
||||||
+}
|
+}
|
||||||
diff --git a/applications/settings/notification_settings/rgb_backlight.h b/applications/settings/notification_settings/rgb_backlight.h
|
diff --git a/applications/settings/notification_settings/rgb_backlight.h b/applications/settings/notification_settings/rgb_backlight.h
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000..68dacda
|
index 0000000..b63d223
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/applications/settings/notification_settings/rgb_backlight.h
|
+++ b/applications/settings/notification_settings/rgb_backlight.h
|
||||||
@@ -0,0 +1,91 @@
|
@@ -0,0 +1,79 @@
|
||||||
+/*
|
+/*
|
||||||
+ RGB backlight FlipperZero driver
|
+ RGB backlight FlipperZero driver
|
||||||
+ Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
|
+ Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
|
||||||
@@ -401,9 +274,6 @@ index 0000000..68dacda
|
|||||||
+typedef struct {
|
+typedef struct {
|
||||||
+ uint8_t version;
|
+ uint8_t version;
|
||||||
+ uint8_t display_color_index;
|
+ uint8_t display_color_index;
|
||||||
+ uint8_t custom_r;
|
|
||||||
+ uint8_t custom_g;
|
|
||||||
+ uint8_t custom_b;
|
|
||||||
+ bool settings_is_loaded;
|
+ bool settings_is_loaded;
|
||||||
+} RGBBacklightSettings;
|
+} RGBBacklightSettings;
|
||||||
+
|
+
|
||||||
@@ -428,9 +298,8 @@ index 0000000..68dacda
|
|||||||
+ * @brief Применить текущие настройки RGB-подсветки
|
+ * @brief Применить текущие настройки RGB-подсветки
|
||||||
+ *
|
+ *
|
||||||
+ * @param brightness Яркость свечения (0-255)
|
+ * @param brightness Яркость свечения (0-255)
|
||||||
+ * @param bypass Применить настройки принудительно
|
|
||||||
+ */
|
+ */
|
||||||
+void rgb_backlight_update(uint8_t brightness, bool bypass);
|
+void rgb_backlight_update(uint8_t brightness);
|
||||||
+
|
+
|
||||||
+/**
|
+/**
|
||||||
+ * @brief Установить цвет RGB-подсветки
|
+ * @brief Установить цвет RGB-подсветки
|
||||||
@@ -440,14 +309,6 @@ index 0000000..68dacda
|
|||||||
+void rgb_backlight_set_color(uint8_t color_index);
|
+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 Получить количество доступных цветов
|
+ * @brief Получить количество доступных цветов
|
||||||
+ *
|
+ *
|
||||||
+ * @return Число доступных вариантов цвета
|
+ * @return Число доступных вариантов цвета
|
||||||
@@ -463,7 +324,7 @@ index 0000000..68dacda
|
|||||||
+const char* rgb_backlight_get_color_text(uint8_t index);
|
+const char* rgb_backlight_get_color_text(uint8_t index);
|
||||||
\ No newline at end of file
|
\ No newline at end of file
|
||||||
diff --git a/firmware/targets/f7/furi_hal/furi_hal_light.c b/firmware/targets/f7/furi_hal/furi_hal_light.c
|
diff --git a/firmware/targets/f7/furi_hal/furi_hal_light.c b/firmware/targets/f7/furi_hal/furi_hal_light.c
|
||||||
index 83e1603..45798ca 100644
|
index 83e1603..cad5b86 100644
|
||||||
--- a/firmware/targets/f7/furi_hal/furi_hal_light.c
|
--- a/firmware/targets/f7/furi_hal/furi_hal_light.c
|
||||||
+++ b/firmware/targets/f7/furi_hal/furi_hal_light.c
|
+++ b/firmware/targets/f7/furi_hal/furi_hal_light.c
|
||||||
@@ -3,6 +3,7 @@
|
@@ -3,6 +3,7 @@
|
||||||
@@ -492,7 +353,7 @@ index 83e1603..45798ca 100644
|
|||||||
- uint8_t prev = lp5562_get_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelWhite);
|
- uint8_t prev = lp5562_get_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelWhite);
|
||||||
- lp5562_execute_ramp(
|
- lp5562_execute_ramp(
|
||||||
- &furi_hal_i2c_handle_power, LP5562Engine1, LP5562ChannelWhite, prev, value, 100);
|
- &furi_hal_i2c_handle_power, LP5562Engine1, LP5562ChannelWhite, prev, value, 100);
|
||||||
+ rgb_backlight_update(value, false);
|
+ rgb_backlight_update(value);
|
||||||
+ } else {
|
+ } else {
|
||||||
+ furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
|
+ furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
|
||||||
+ if(light & LightRed) {
|
+ if(light & LightRed) {
|
||||||
|
|||||||
176
.drone.yml
@@ -15,42 +15,16 @@ steps:
|
|||||||
- git submodule foreach git config --local gc.auto 0
|
- git submodule foreach git config --local gc.auto 0
|
||||||
- git log -1 --format='%H'
|
- git log -1 --format='%H'
|
||||||
|
|
||||||
- name: "Build clean"
|
- name: "Build firmware"
|
||||||
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"
|
|
||||||
image: hfdj/fztools
|
image: hfdj/fztools
|
||||||
pull: never
|
pull: never
|
||||||
commands:
|
commands:
|
||||||
- export DIST_SUFFIX=${DRONE_TAG}
|
- export DIST_SUFFIX=${DRONE_TAG}
|
||||||
- export WORKFLOW_BRANCH_OR_TAG=release-cfw
|
- export WORKFLOW_BRANCH_OR_TAG=release-cfw
|
||||||
- export FORCE_NO_DIRTY=yes
|
- rm -rf assets/resources/apps/
|
||||||
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
- rm -rf build/
|
||||||
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-base.tgz
|
- rm -rf dist/
|
||||||
- tar zxvf all-the-apps-base.tgz
|
- rm -rf .sconsign.dblite
|
||||||
- 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
|
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||||
- mkdir artifacts-default
|
- mkdir artifacts-default
|
||||||
- mv dist/f7-C/* artifacts-default/
|
- mv dist/f7-C/* artifacts-default/
|
||||||
@@ -64,14 +38,12 @@ steps:
|
|||||||
image: hfdj/fztools
|
image: hfdj/fztools
|
||||||
pull: never
|
pull: never
|
||||||
commands:
|
commands:
|
||||||
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-extra.tgz
|
- git clone https://github.com/xMasterX/all-the-plugins.git
|
||||||
- tar zxvf all-the-apps-extra.tgz
|
- cp -R all-the-plugins/apps/* assets/resources/apps/
|
||||||
- cp -R extra_pack_build/artifacts-extra/* applications/main/clock_app/resources/apps/
|
- rm -rf all-the-plugins
|
||||||
- rm -rf extra_pack_build
|
|
||||||
- export DIST_SUFFIX=${DRONE_TAG}e
|
- export DIST_SUFFIX=${DRONE_TAG}e
|
||||||
- export WORKFLOW_BRANCH_OR_TAG=release-cfw
|
- export WORKFLOW_BRANCH_OR_TAG=release-cfw
|
||||||
- export FORCE_NO_DIRTY=yes
|
- export FORCE_NO_DIRTY=yes
|
||||||
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
|
||||||
- rm -f build/f7-firmware-C/toolbox/version.*
|
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||||
- mkdir artifacts-extra-apps
|
- mkdir artifacts-extra-apps
|
||||||
@@ -90,7 +62,6 @@ steps:
|
|||||||
- export DIST_SUFFIX=${DRONE_TAG}r
|
- export DIST_SUFFIX=${DRONE_TAG}r
|
||||||
- export WORKFLOW_BRANCH_OR_TAG=release-cfw-rgb
|
- export WORKFLOW_BRANCH_OR_TAG=release-cfw-rgb
|
||||||
- export FORCE_NO_DIRTY=yes
|
- export FORCE_NO_DIRTY=yes
|
||||||
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
|
||||||
- rm -f build/f7-firmware-C/toolbox/version.*
|
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||||
- mkdir artifacts-rgb-patch
|
- mkdir artifacts-rgb-patch
|
||||||
@@ -109,19 +80,10 @@ steps:
|
|||||||
- git checkout -- .
|
- git checkout -- .
|
||||||
- rm -f assets/dolphin/external/manifest.txt
|
- rm -f assets/dolphin/external/manifest.txt
|
||||||
- cp .ci_files/anims_ofw.txt 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 DIST_SUFFIX=${DRONE_TAG}n
|
||||||
- export WORKFLOW_BRANCH_OR_TAG=no-custom-anims
|
- export WORKFLOW_BRANCH_OR_TAG=no-custom-anims
|
||||||
- export FORCE_NO_DIRTY=yes
|
- 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 zxvf all-the-apps-base.tgz
|
|
||||||
- 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.*
|
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||||
- mkdir artifacts-ofw-anims
|
- mkdir artifacts-ofw-anims
|
||||||
@@ -131,8 +93,6 @@ steps:
|
|||||||
- sed -i 's/(version)/'${DRONE_TAG}'/g' CHANGELOG.md
|
- 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 '# [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 '' >> 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 '### [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 '' >> 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 '### [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
|
||||||
@@ -147,23 +107,19 @@ steps:
|
|||||||
commands:
|
commands:
|
||||||
- cp artifacts-extra-apps/flipper-z-f7-update-${DRONE_TAG}e.tgz .
|
- 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-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-ofw-anims/flipper-z-f7-update-${DRONE_TAG}n.tgz .
|
||||||
- cp artifacts-default/flipper-z-f7-update-${DRONE_TAG}.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-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-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-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}
|
- 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
|
||||||
- rm -rf artifacts-extra-apps/f7-update-${DRONE_TAG}
|
- rm -rf artifacts-extra-apps/f7-update-${DRONE_TAG}
|
||||||
- rm -rf artifacts-rgb-patch/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-ofw-anims/f7-update-${DRONE_TAG}
|
||||||
- rm -rf artifacts-default/f7-update-${DRONE_TAG}
|
- rm -rf artifacts-default/f7-update-${DRONE_TAG}
|
||||||
- ls -laS artifacts-extra-apps
|
- ls -laS artifacts-extra-apps
|
||||||
- ls -laS artifacts-rgb-patch
|
- ls -laS artifacts-rgb-patch
|
||||||
- ls -laS artifacts-clean
|
|
||||||
- ls -laS artifacts-ofw-anims
|
- ls -laS artifacts-ofw-anims
|
||||||
- ls -laS artifacts-default
|
- ls -laS artifacts-default
|
||||||
- mv artifacts-default/ ${DRONE_TAG}
|
- mv artifacts-default/ ${DRONE_TAG}
|
||||||
@@ -235,21 +191,6 @@ steps:
|
|||||||
from_secret: dep_target_extra
|
from_secret: dep_target_extra
|
||||||
source: flipper-z-f7-update-${DRONE_TAG}r.tgz
|
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"
|
- name: "Do Github release"
|
||||||
image: ddplugins/github-release
|
image: ddplugins/github-release
|
||||||
pull: never
|
pull: never
|
||||||
@@ -265,7 +206,6 @@ steps:
|
|||||||
- artifacts-ofw-anims/*.tgz
|
- artifacts-ofw-anims/*.tgz
|
||||||
- artifacts-extra-apps/*.tgz
|
- artifacts-extra-apps/*.tgz
|
||||||
- artifacts-rgb-patch/*.tgz
|
- artifacts-rgb-patch/*.tgz
|
||||||
- artifacts-clean/*.tgz
|
|
||||||
title: ${DRONE_TAG}
|
title: ${DRONE_TAG}
|
||||||
note: CHANGELOG.md
|
note: CHANGELOG.md
|
||||||
checksum:
|
checksum:
|
||||||
@@ -307,15 +247,12 @@ steps:
|
|||||||
[-How to install firmware-](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)
|
[-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://github.com/xMasterX/all-the-plugins/archive/refs/heads/main.zip)
|
||||||
|
|
||||||
|
|
||||||
[-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})
|
[-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 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)
|
||||||
|
|
||||||
|
|
||||||
@@ -338,19 +275,7 @@ steps:
|
|||||||
commands:
|
commands:
|
||||||
- wget "https://raw.githubusercontent.com/fieu/discord.sh/e1dc1a7595efad2cad8f072f0b3531c470f5b7c8/discord.sh"
|
- wget "https://raw.githubusercontent.com/fieu/discord.sh/e1dc1a7595efad2cad8f072f0b3531c470f5b7c8/discord.sh"
|
||||||
- chmod +x ./discord.sh
|
- chmod +x ./discord.sh
|
||||||
- ./discord.sh --text '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)'
|
- ./discord.sh --text '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/archive/refs/heads/main.zip)\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 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)'
|
||||||
|
|
||||||
- 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
|
|
||||||
|
|
||||||
- name: "Send extra pack build to telegram"
|
- name: "Send extra pack build to telegram"
|
||||||
image: appleboy/drone-telegram
|
image: appleboy/drone-telegram
|
||||||
@@ -389,43 +314,16 @@ steps:
|
|||||||
- git submodule foreach git config --local gc.auto 0
|
- git submodule foreach git config --local gc.auto 0
|
||||||
- git log -1 --format='%H'
|
- git log -1 --format='%H'
|
||||||
|
|
||||||
- name: "Build dev clean"
|
- name: "Build dev FW"
|
||||||
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"
|
|
||||||
image: hfdj/fztools
|
image: hfdj/fztools
|
||||||
pull: never
|
pull: never
|
||||||
commands:
|
commands:
|
||||||
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}
|
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}
|
||||||
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw
|
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw
|
||||||
- export FORCE_NO_DIRTY=yes
|
- rm -rf assets/resources/apps/
|
||||||
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
- rm -rf build/
|
||||||
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-base.tgz
|
- rm -rf dist/
|
||||||
- tar zxvf all-the-apps-base.tgz
|
- rm -rf .sconsign.dblite
|
||||||
- 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
|
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||||
- mkdir artifacts-default
|
- mkdir artifacts-default
|
||||||
- mv dist/f7-C/* artifacts-default/
|
- mv dist/f7-C/* artifacts-default/
|
||||||
@@ -439,14 +337,12 @@ steps:
|
|||||||
image: hfdj/fztools
|
image: hfdj/fztools
|
||||||
pull: never
|
pull: never
|
||||||
commands:
|
commands:
|
||||||
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-extra.tgz
|
- git clone --branch dev https://github.com/xMasterX/all-the-plugins.git
|
||||||
- tar zxvf all-the-apps-extra.tgz
|
- cp -R all-the-plugins/apps/* assets/resources/apps/
|
||||||
- cp -R extra_pack_build/artifacts-extra/* applications/main/clock_app/resources/apps/
|
- rm -rf all-the-plugins
|
||||||
- rm -rf extra_pack_build
|
|
||||||
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}e
|
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}e
|
||||||
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw
|
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw
|
||||||
- export FORCE_NO_DIRTY=yes
|
- export FORCE_NO_DIRTY=yes
|
||||||
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
|
||||||
- rm -f build/f7-firmware-C/toolbox/version.*
|
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||||
- mkdir artifacts-extra-apps
|
- mkdir artifacts-extra-apps
|
||||||
@@ -465,7 +361,6 @@ steps:
|
|||||||
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}r
|
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}r
|
||||||
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw-rgb
|
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw-rgb
|
||||||
- export FORCE_NO_DIRTY=yes
|
- export FORCE_NO_DIRTY=yes
|
||||||
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
|
||||||
- rm -f build/f7-firmware-C/toolbox/version.*
|
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||||
- mkdir artifacts-rgb-patch
|
- mkdir artifacts-rgb-patch
|
||||||
@@ -481,7 +376,6 @@ steps:
|
|||||||
commands:
|
commands:
|
||||||
- cp artifacts-extra-apps/flipper-z-f7-update-${DRONE_BUILD_NUMBER}e.tgz .
|
- 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-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 .
|
- cp artifacts-default/flipper-z-f7-update-${DRONE_BUILD_NUMBER}.tgz .
|
||||||
- rm -rf artifacts-default/f7-update-${DRONE_BUILD_NUMBER}
|
- rm -rf artifacts-default/f7-update-${DRONE_BUILD_NUMBER}
|
||||||
- ls -laS artifacts-default
|
- ls -laS artifacts-default
|
||||||
@@ -554,21 +448,6 @@ steps:
|
|||||||
from_secret: dep_target_extra
|
from_secret: dep_target_extra
|
||||||
source: flipper-z-f7-update-${DRONE_BUILD_NUMBER}r.tgz
|
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"
|
- name: "Trigger update server reindex"
|
||||||
image: hfdj/fztools
|
image: hfdj/fztools
|
||||||
pull: never
|
pull: never
|
||||||
@@ -603,9 +482,6 @@ steps:
|
|||||||
[-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})
|
[-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 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)
|
||||||
|
|
||||||
|
|
||||||
@@ -626,18 +502,6 @@ steps:
|
|||||||
document:
|
document:
|
||||||
- dev/flipper-z-f7-update-${DRONE_BUILD_NUMBER}.tgz
|
- 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"
|
- name: "Send extra pack build to telegram"
|
||||||
image: appleboy/drone-telegram
|
image: appleboy/drone-telegram
|
||||||
settings:
|
settings:
|
||||||
@@ -659,7 +523,7 @@ steps:
|
|||||||
commands:
|
commands:
|
||||||
- wget "https://raw.githubusercontent.com/fieu/discord.sh/e1dc1a7595efad2cad8f072f0b3531c470f5b7c8/discord.sh"
|
- wget "https://raw.githubusercontent.com/fieu/discord.sh/e1dc1a7595efad2cad8f072f0b3531c470f5b7c8/discord.sh"
|
||||||
- chmod +x ./discord.sh
|
- chmod +x ./discord.sh
|
||||||
- ./discord.sh --text '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}')'
|
- ./discord.sh --text '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 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}')'
|
||||||
|
|
||||||
trigger:
|
trigger:
|
||||||
branch:
|
branch:
|
||||||
|
|||||||
2
.github/CODEOWNERS
vendored
@@ -2,4 +2,4 @@
|
|||||||
* @xMasterX
|
* @xMasterX
|
||||||
|
|
||||||
# Assets
|
# Assets
|
||||||
/assets/resources/infrared/assets/ @amec0e @Leptopt1los @xMasterX
|
/assets/resources/infrared/ @xMasterX @amec0e
|
||||||
1
.github/FUNDING.yml
vendored
@@ -1,4 +1,3 @@
|
|||||||
patreon: mmxdev
|
|
||||||
custom:
|
custom:
|
||||||
[
|
[
|
||||||
"https://boosty.to/mmxdev",
|
"https://boosty.to/mmxdev",
|
||||||
|
|||||||
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
|
|
||||||
1
.gitignore
vendored
@@ -51,7 +51,6 @@ null.d
|
|||||||
/artifacts-ofw-anims
|
/artifacts-ofw-anims
|
||||||
/artifacts-rgb-patch
|
/artifacts-rgb-patch
|
||||||
/artifacts-extra-apps
|
/artifacts-extra-apps
|
||||||
/artifacts-clean
|
|
||||||
|
|
||||||
# SCons build dir
|
# SCons build dir
|
||||||
/build
|
/build
|
||||||
|
|||||||
14
.gitmodules
vendored
@@ -10,7 +10,6 @@
|
|||||||
[submodule "assets/protobuf"]
|
[submodule "assets/protobuf"]
|
||||||
path = assets/protobuf
|
path = assets/protobuf
|
||||||
url = https://github.com/flipperdevices/flipperzero-protobuf.git
|
url = https://github.com/flipperdevices/flipperzero-protobuf.git
|
||||||
shallow = false
|
|
||||||
[submodule "lib/libusb_stm32"]
|
[submodule "lib/libusb_stm32"]
|
||||||
path = lib/libusb_stm32
|
path = lib/libusb_stm32
|
||||||
url = https://github.com/flipperdevices/libusb_stm32.git
|
url = https://github.com/flipperdevices/libusb_stm32.git
|
||||||
@@ -26,6 +25,12 @@
|
|||||||
[submodule "lib/cxxheaderparser"]
|
[submodule "lib/cxxheaderparser"]
|
||||||
path = lib/cxxheaderparser
|
path = lib/cxxheaderparser
|
||||||
url = https://github.com/robotpy/cxxheaderparser.git
|
url = https://github.com/robotpy/cxxheaderparser.git
|
||||||
|
[submodule "applications/external/dap_link/lib/free-dap"]
|
||||||
|
path = applications/external/dap_link/lib/free-dap
|
||||||
|
url = https://github.com/ataradov/free-dap.git
|
||||||
|
[submodule "applications/external/subbrute"]
|
||||||
|
path = applications/external/subbrute
|
||||||
|
url = https://github.com/DarkFlippers/flipperzero-subbrute.git
|
||||||
[submodule "lib/heatshrink"]
|
[submodule "lib/heatshrink"]
|
||||||
path = lib/heatshrink
|
path = lib/heatshrink
|
||||||
url = https://github.com/flipperdevices/heatshrink.git
|
url = https://github.com/flipperdevices/heatshrink.git
|
||||||
@@ -38,7 +43,6 @@
|
|||||||
[submodule "lib/stm32wb_copro"]
|
[submodule "lib/stm32wb_copro"]
|
||||||
path = lib/stm32wb_copro
|
path = lib/stm32wb_copro
|
||||||
url = https://github.com/flipperdevices/stm32wb_copro.git
|
url = https://github.com/flipperdevices/stm32wb_copro.git
|
||||||
[submodule "subghz_remote"]
|
[submodule "applications/external/multi_fuzzer"]
|
||||||
path = applications/main/subghz_remote
|
path = applications/external/multi_fuzzer
|
||||||
url = https://github.com/DarkFlippers/SubGHz_Remote.git
|
url = https://github.com/DarkFlippers/Multi_Fuzzer.git
|
||||||
branch = ufw_main_app
|
|
||||||
|
|||||||
@@ -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/micro-ecc -e lib/microtar -e lib/mlib -e lib/qrcode -e lib/stm32wb_cmsis -e lib/stm32wb_copro -e lib/stm32wb_hal -e lib/u8g2 -e lib/nanopb -e */arm-none-eabi/*
|
--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/micro-ecc -e lib/microtar -e lib/mlib -e lib/qrcode -e lib/ST25RFAL002 -e lib/stm32wb_cmsis -e lib/stm32wb_copro -e lib/stm32wb_hal -e lib/u8g2 -e lib/nanopb -e */arm-none-eabi/* -e applications/external/dap_link/lib/free-dap
|
||||||
|
|||||||
9
.vscode/.gitignore
vendored
@@ -1,5 +1,4 @@
|
|||||||
/c_cpp_properties.json
|
./c_cpp_properties.json
|
||||||
/extensions.json
|
./launch.json
|
||||||
/launch.json
|
./settings.json
|
||||||
/settings.json
|
./tasks.json
|
||||||
/tasks.json
|
|
||||||
|
|||||||
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"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
9
.vscode/example/settings.json
vendored
@@ -21,10 +21,5 @@
|
|||||||
"SConscript": "python",
|
"SConscript": "python",
|
||||||
"SConstruct": "python",
|
"SConstruct": "python",
|
||||||
"*.fam": "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"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|||||||
16
.vscode/example/tasks.json
vendored
@@ -28,17 +28,29 @@
|
|||||||
"command": "./fbt -c"
|
"command": "./fbt -c"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "[Release] Flash (SWD)",
|
"label": "[Release] Flash (ST-Link)",
|
||||||
"group": "build",
|
"group": "build",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash"
|
"command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "[Debug] Flash (SWD)",
|
"label": "[Debug] Flash (ST-Link)",
|
||||||
"group": "build",
|
"group": "build",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "./fbt FORCE=1 flash"
|
"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)",
|
"label": "[Release] Flash (JLink)",
|
||||||
"group": "build",
|
"group": "build",
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
],
|
],
|
||||||
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
||||||
"unwantedRecommendations": [
|
"unwantedRecommendations": [
|
||||||
"llvm-vs-code-extensions.vscode-clangd",
|
|
||||||
"twxs.cmake",
|
"twxs.cmake",
|
||||||
"ms-vscode.cmake-tools"
|
"ms-vscode.cmake-tools"
|
||||||
]
|
]
|
||||||
60
CHANGELOG.md
@@ -1,13 +1,14 @@
|
|||||||
## New changes
|
## New changes
|
||||||
* SubGHz: Add 4 more systems to Add Manually (untested!)
|
* SubGHz: OFW PR: change the operation of the TIM17 timer in CC1101_ext to 2µs -> **CAME Atomo and other protocols issues with external module should be fixed now**
|
||||||
* SubGHz: Add Manually fixes
|
* SubGHz: Temporatily revert new AM_Q in default modulations due to external CC1101 module issues
|
||||||
* SubGHz: Added NiceFlor-S to ignore options, removed colons. (by @G2Dolphin | PR #620)
|
* Plugins: NRF24 MouseJacker -> Fixed issue #551 - Wrong folder path
|
||||||
* Misc code cleanup
|
* Plugins: Spectrum Analyzer -> Add a Precise mode and other small changes (by @ALEEF02 | PR #550 #553)
|
||||||
* RGB: Fix white color on reboot, move settings, add custom color option
|
* Plugins: Updated Lightmeter [(by oleksiikutuzov)](https://github.com/oleksiikutuzov/flipperzero-lightmeter)
|
||||||
* **BLE Spam app** updated to latest version (Android, Windows support) (by @Willy-JL) -> (app can be found in builds ` `, `e`, `n`, `r`)
|
* Plugins: Various uFBT fixes (by @hedger)
|
||||||
* OFW: Fix double arrows and add proper indication
|
* Infrared: Universal remote assets - Add Xiaomi TV and (Daikin AC from OFW PR 2913 by minchogaydarov)
|
||||||
* OFW: SubGHz: add manually fix 12-bits is 0xFFF (or 0xFF0) CAME/NICE 12-bit
|
* OFW PR 2912: NFC: Fix key invalidation (again) (by AloneLiberty)
|
||||||
* OFW: Fix various crashes if debug libraries used
|
* OFW PR 2907: Fix about screen (by andzhr)
|
||||||
|
* OFW PR 2896: BadUSB - Added French Canadian layout (by francis2054)
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
@@ -16,20 +17,17 @@
|
|||||||
[-> Download qFlipper (official link)](https://flipperzero.one/update)
|
[-> Download qFlipper (official link)](https://flipperzero.one/update)
|
||||||
|
|
||||||
## Please support development of the project
|
## Please support development of the project
|
||||||
|Service|Remark|Link/Wallet|
|
* **Boosty** (patreon alternative): https://boosty.to/mmxdev
|
||||||
|-|-|-|
|
* cloudtips (only RU payments accepted): https://pay.cloudtips.ru/p/7b3e9d65
|
||||||
|**Patreon**||https://patreon.com/mmxdev|
|
* YooMoney (only RU payments accepted): https://yoomoney.ru/fundraise/XA49mgQLPA0.221209
|
||||||
|**Boosty**|patreon alternative|https://boosty.to/mmxdev|
|
* USDT(TRC20): `TSXcitMSnWXUFqiUfEXrTVpVewXy2cYhrs`
|
||||||
|cloudtips|only RU payments accepted|https://pay.cloudtips.ru/p/7b3e9d65|
|
* BCH: `qquxfyzntuqufy2dx0hrfr4sndp0tucvky4sw8qyu3`
|
||||||
|YooMoney|only RU payments accepted|https://yoomoney.ru/fundraise/XA49mgQLPA0.221209|
|
* ETH/BSC/ERC20-Tokens: `darkflippers.eth` (or `0xFebF1bBc8229418FF2408C07AF6Afa49152fEc6a`)
|
||||||
|USDT|(TRC20)|`TSXcitMSnWXUFqiUfEXrTVpVewXy2cYhrs`|
|
* BTC: `bc1q0np836jk9jwr4dd7p6qv66d04vamtqkxrecck9`
|
||||||
|BCH||`qquxfyzntuqufy2dx0hrfr4sndp0tucvky4sw8qyu3`|
|
* DOGE: `D6R6gYgBn5LwTNmPyvAQR6bZ9EtGgFCpvv`
|
||||||
|ETH|(BSC/ERC20-Tokens)|`darkflippers.eth` (or `0xFebF1bBc8229418FF2408C07AF6Afa49152fEc6a`)|
|
* LTC: `ltc1q3ex4ejkl0xpx3znwrmth4lyuadr5qgv8tmq8z9`
|
||||||
|BTC||`bc1q0np836jk9jwr4dd7p6qv66d04vamtqkxrecck9`|
|
* XMR (Monero): `41xUz92suUu1u5Mu4qkrcs52gtfpu9rnZRdBpCJ244KRHf6xXSvVFevdf2cnjS7RAeYr5hn9MsEfxKoFDRSctFjG5fv1Mhn`
|
||||||
|DOGE||`D6R6gYgBn5LwTNmPyvAQR6bZ9EtGgFCpvv`|
|
* TON: `EQCOqcnYkvzOZUV_9bPE_8oTbOrOF03MnF-VcJyjisTZmpGf`
|
||||||
|LTC||`ltc1q3ex4ejkl0xpx3znwrmth4lyuadr5qgv8tmq8z9`|
|
|
||||||
|XMR|(Monero)| `41xUz92suUu1u5Mu4qkrcs52gtfpu9rnZRdBpCJ244KRHf6xXSvVFevdf2cnjS7RAeYr5hn9MsEfxKoFDRSctFjG5fv1Mhn`|
|
|
||||||
|TON||`EQCOqcnYkvzOZUV_9bPE_8oTbOrOF03MnF-VcJyjisTZmpGf`|
|
|
||||||
|
|
||||||
#### Thanks to our sponsors:
|
#### Thanks to our sponsors:
|
||||||
callmezimbra, Quen0n, MERRON, grvpvl (lvpvrg), art_col, ThurstonWaffles, Moneron, UterGrooll, LUCFER, Northpirate, zloepuzo, T.Rat, Alexey B., ionelife, ...
|
callmezimbra, Quen0n, MERRON, grvpvl (lvpvrg), art_col, ThurstonWaffles, Moneron, UterGrooll, LUCFER, Northpirate, zloepuzo, T.Rat, Alexey B., ionelife, ...
|
||||||
@@ -38,21 +36,15 @@ and all other great people who supported our project and me (xMasterX), thanks t
|
|||||||
|
|
||||||
## **Recommended update option - Web Updater**
|
## **Recommended update option - Web Updater**
|
||||||
|
|
||||||
### What `n`, `r`, `e`, ` `, `c` means? What I need to download if I don't want to use Web updater?
|
### What `n`, `r`, `e` 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>
|
What build I should download and what this name means - `flipper-z-f7-update-(version)(n / r / e).tgz` ? <br>
|
||||||
`flipper-z` = for Flipper Zero device<br>
|
`flipper-z` = for Flipper Zero device<br>
|
||||||
`f7` = Hardware version - same for all flipper zero devices<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>
|
`update` = Update package, contains updater, all assets (plugins, IR libs, etc.), and firmware itself<br>
|
||||||
`(version)` = Firmware version<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* |
|
`n` = this build comes without our custom animations (we have only 3 of them), only official flipper animations<br>
|
||||||
|-----|:---:|:---:|:---:|:---:|
|
`e` = build has 🎲 [extra apps pack](https://github.com/xMasterX/all-the-plugins) preinstalled<br>
|
||||||
| ` ` | ✅ | ✅ | | |
|
`r` = RGB patch (+ extra apps) for flippers with rgb backlight mod (this is hardware mod!) (Works only on modded flippers!) (do not install on non modded device!)
|
||||||
| `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>
|
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>
|
Archive of `scripts` folder (contains scripts for FW/plugins development) - `flipper-z-any-scripts-(version).tgz`<br>
|
||||||
|
|||||||
280
ReadMe.md
@@ -3,20 +3,6 @@
|
|||||||
<img src="https://user-images.githubusercontent.com/10697207/186202043-26947e28-b1cc-459a-8f20-ffcc7fc0c71c.png" align="center" alt="fzCUSTOM" border="0">
|
<img src="https://user-images.githubusercontent.com/10697207/186202043-26947e28-b1cc-459a-8f20-ffcc7fc0c71c.png" align="center" alt="fzCUSTOM" border="0">
|
||||||
</a>
|
</a>
|
||||||
</h3>
|
</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!
|
### Welcome to the Flipper Zero Unleashed Firmware repo!
|
||||||
|
|
||||||
@@ -30,11 +16,14 @@
|
|||||||
|
|
||||||
##### 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>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
<br>
|
||||||
## FAQ (frequently asked questions)
|
<br>
|
||||||
[Follow this link to find answers to most asked questions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/FAQ.md)
|
|
||||||
|
|
||||||
## Dev builds (unstable)
|
## Dev builds (unstable)
|
||||||
- https://dev.unleashedflip.com/
|
- https://dev.unleashedflip.com/
|
||||||
@@ -43,59 +32,45 @@
|
|||||||
- https://t.me/unleashed_fw
|
- https://t.me/unleashed_fw
|
||||||
|
|
||||||
# What's changed
|
# What's changed
|
||||||
- **Sub-GHz** *lib & hal*
|
* Sub-GHz regional TX restrictions removed
|
||||||
- Regional TX restrictions removed
|
* Sub-GHz frequency range can be extended in settings file (Warning: It can damage Flipper's hardware)
|
||||||
- Extra Sub-GHz frequencies
|
* Many rolling code protocols now have the ability to save & send captured signals
|
||||||
- Frequency range can be extended in settings file (Warning: It can damage Flipper's hardware)
|
* FAAC SLH (Spa) & BFT Mitto (keeloq secure with seed) manual creation
|
||||||
- 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
|
* Sub-GHz static code brute-force plugin
|
||||||
- FAAC SLH (Spa) & BFT Mitto (keeloq secure with seed) manual creation
|
* LFRFID Fuzzer plugin
|
||||||
- External CC1101 module support [(by quen0n)](https://github.com/DarkFlippers/unleashed-firmware/pull/307)
|
* Custom community plugins and games added + all known working apps can be downloaded in extra pack in every release
|
||||||
- **Sub-GHz** *Main App*
|
* Extra Sub-GHz frequencies + extra Mifare Classic keys
|
||||||
- Save last used frequency [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77)
|
* Picopass/iClass plugin included in releases
|
||||||
- New frequency analyzer [(by ClusterM)](https://github.com/DarkFlippers/unleashed-firmware/pull/43)
|
* Recompiled IR TV Universal Remote for ALL buttons
|
||||||
- Press OK in frequency analyzer to use detected frequency in Read modes [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77)
|
* Universal remote for Projectors, Fans, A/Cs and Audio(soundbars, etc.)
|
||||||
- Long press OK button in Sub-GHz Frequency analyzer to switch to Read menu [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/79)
|
* Customizable Flipper name **Update! Now can be changed in Settings->Desktop** (by @xMasterX and @Willy-JL)
|
||||||
- New option to use timestamps + protocol name when you saving file, instead of random name - Enable in `Radio Settings -> Time in names = ON`
|
* Text Input UI element -> Cursor feature (by @Willy-JL)
|
||||||
- Read mode UI improvements (shows time when signal was received) (by @wosk)
|
- **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)
|
||||||
- External CC1101 module support (Hardware SPI used)
|
- BadUSB -> Keyboard layouts [(by rien > dummy-decoy)](https://github.com/dummy-decoy/flipperzero-firmware/tree/dummy_decoy/bad_usb_keyboard_layout)
|
||||||
- **Hold right in received signal list to delete selected signal**
|
- Sub-GHz -> External CC1101 module support - [(by quen0n)](https://github.com/DarkFlippers/unleashed-firmware/pull/307)
|
||||||
- **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
|
- Sub-GHz -> `Add manually` menu extended with new protocols
|
||||||
- `Add manually` menu extended with new protocols
|
- Sub-GHz -> New frequency analyzer - [(by ClusterM)](https://github.com/DarkFlippers/unleashed-firmware/pull/43)
|
||||||
- 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)
|
- Sub-GHz -> Save last used frequency [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77)
|
||||||
- Debug mode counter increase settings (+1 -> +5, +10, default: +1)
|
- Sub-GHz -> Press OK in frequency analyzer to use detected frequency in Read modes [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77)
|
||||||
- Debug PIN output settings for protocol development
|
- 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)
|
||||||
- **Sub-GHz apps** *by unleashed team*
|
* Sub-GHz -> Short press OK in frequency analyzer to save detected frequency for usage in Read modes
|
||||||
- Sub-GHz Bruteforce - static code brute-force plugin |
|
* Sub-GHz -> Long press OK button in Sub-GHz Frequency analyzer to switch to Read menu and automatically use selected frequency
|
||||||
- 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
|
* SubGHz -> New option to use timestamps + protocol name when you saving file, instead of random name - Enable in `Radio Settings -> Time in names = ON`
|
||||||
- Load your own file and select bytes you want to bruteforce or use preconfigured options in protocols list
|
* SubGHz Bruteforcer 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
|
||||||
- Sub-GHz Remote - remote control for 5 sub-ghz files | bind one file for each button
|
* SubGHz -> Read mode UI improvements (scrolling text, + shows time when signal was received) (by @wosk)
|
||||||
- use the built-in constructor or make config file by following this [instruction](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemotePlugin.md)
|
* Sub-GHz -> External CC1101 module support (Hardware SPI used)
|
||||||
- **Infrared**
|
* SubGHz -> **Hold right in received signal list to delete selected signal**
|
||||||
- Recompiled IR TV Universal Remote for ALL buttons
|
* SubGHz -> **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
|
||||||
- Universal remotes for Projectors, Fans, A/Cs and Audio(soundbars, etc.) -> Also always updated and verified by our team
|
* SubGHz -> 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)
|
||||||
- Infrared -> `RCA` Protocol
|
* SubGHz -> Debug mode counter increase settings (+1 -> +5, +10, default: +1)
|
||||||
- Infrared -> Debug TX PIN output settings
|
* SubGHz -> Debug PIN output settings for protocol development
|
||||||
- **NFC/RFID/iButton**
|
* Infrared -> `RCA` Protocol
|
||||||
* LFRFID/iButton Fuzzer plugins
|
* Infrared -> Debug TX PIN output settings
|
||||||
* Extra Mifare Classic keys
|
* Other small fixes and changes throughout
|
||||||
* `Add manually` -> Mifare Classic with custom UID
|
* See other changes in readme below
|
||||||
* Picopass/iClass plugin (now with emulation support!) included in releases
|
|
||||||
- **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
|
|
||||||
- Clock on Desktop -> `Settings -> Desktop -> Show Clock`
|
|
||||||
- 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
|
|
||||||
|
|
||||||
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:
|
### 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 their SubGHz Developer, Skorp) for implementing decoders for these protocols in OFW.
|
||||||
@@ -123,8 +98,8 @@ Encoders or sending made by @xMasterX:
|
|||||||
Encoders or sending made by @Eng1n33r(first implementation in Q2 2022) & @xMasterX (current version):
|
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)
|
- 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)
|
- 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)
|
- FAAC SLH (Spa) [External seed calculation required (For info contact me in Discord: @mmx7)]
|
||||||
- Keeloq: BFT Mitto -> 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)
|
||||||
- Star Line
|
- Star Line
|
||||||
- Security+ v1 & v2 (encoders was made in OFW)
|
- Security+ v1 & v2 (encoders was made in OFW)
|
||||||
|
|
||||||
@@ -139,109 +114,146 @@ Encoders made by @assasinfil & @xMasterX:
|
|||||||
The majority of this project is developed and maintained by me, @xMasterX.
|
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, 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.
|
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.
|
||||||
- @gid9798 - SubGHz, Plugins, many other things
|
- @assasinfil - SubGHz
|
||||||
- @assasinfil - SubGHz protocols
|
|
||||||
- @Svaarich - UI design and animations
|
- @Svaarich - UI design and animations
|
||||||
- @amec0e & @Leptopt1los - Infrared assets
|
- @Amec0e - Infrared assets
|
||||||
- Community moderators in Telegram, Discord, and Reddit
|
- 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.
|
- 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.
|
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.
|
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:
|
You can support us by using links or addresses below:
|
||||||
|Service|Remark|Link/Wallet|
|
* **Boosty** (patreon alternative): https://boosty.to/mmxdev
|
||||||
|-|-|-|
|
* cloudtips (only RU payments accepted): https://pay.cloudtips.ru/p/7b3e9d65
|
||||||
|**Patreon**||https://patreon.com/mmxdev|
|
* YooMoney (only RU payments accepted): https://yoomoney.ru/fundraise/XA49mgQLPA0.221209
|
||||||
|**Boosty**|patreon alternative|https://boosty.to/mmxdev|
|
* USDT(TRC20): `TSXcitMSnWXUFqiUfEXrTVpVewXy2cYhrs`
|
||||||
|cloudtips|only RU payments accepted|https://pay.cloudtips.ru/p/7b3e9d65|
|
* BCH: `qquxfyzntuqufy2dx0hrfr4sndp0tucvky4sw8qyu3`
|
||||||
|YooMoney|only RU payments accepted|https://yoomoney.ru/fundraise/XA49mgQLPA0.221209|
|
* ETH/BSC/ERC20-Tokens: `darkflippers.eth` (or `0xFebF1bBc8229418FF2408C07AF6Afa49152fEc6a`)
|
||||||
|USDT|(TRC20)|`TSXcitMSnWXUFqiUfEXrTVpVewXy2cYhrs`|
|
* BTC: `bc1q0np836jk9jwr4dd7p6qv66d04vamtqkxrecck9`
|
||||||
|BCH||`qquxfyzntuqufy2dx0hrfr4sndp0tucvky4sw8qyu3`|
|
* DOGE: `D6R6gYgBn5LwTNmPyvAQR6bZ9EtGgFCpvv`
|
||||||
|ETH|(BSC/ERC20-Tokens)|`darkflippers.eth` (or `0xFebF1bBc8229418FF2408C07AF6Afa49152fEc6a`)|
|
* LTC: `ltc1q3ex4ejkl0xpx3znwrmth4lyuadr5qgv8tmq8z9`
|
||||||
|BTC||`bc1q0np836jk9jwr4dd7p6qv66d04vamtqkxrecck9`|
|
* XMR (Monero): `41xUz92suUu1u5Mu4qkrcs52gtfpu9rnZRdBpCJ244KRHf6xXSvVFevdf2cnjS7RAeYr5hn9MsEfxKoFDRSctFjG5fv1Mhn`
|
||||||
|DOGE||`D6R6gYgBn5LwTNmPyvAQR6bZ9EtGgFCpvv`|
|
* TON: `EQCOqcnYkvzOZUV_9bPE_8oTbOrOF03MnF-VcJyjisTZmpGf`
|
||||||
|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)
|
- **RFID Fuzzer** [(by @gid9798)](https://github.com/DarkFlippers/Multi_Fuzzer) (original by Ganapati & xMasterX)
|
||||||
### [List of Extra pack](https://github.com/xMasterX/all-the-plugins/tree/dev#extra-pack) | [List of Base *(Deafult)* pack](https://github.com/xMasterX/all-the-plugins/tree/dev#default-pack)
|
- **iButton Fuzzer** [(by @gid9798)](https://github.com/DarkFlippers/Multi_Fuzzer) (original by xMasterX)
|
||||||
|
- **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)
|
||||||
|
- 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) -> Also outputs audio on `PA6` - `3(A6)` pin
|
||||||
|
- Barcode Generator [(by Kingal1337)](https://github.com/Kingal1337/flipper-barcode-generator)
|
||||||
|
- 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-wifi-marauder) - Saving .pcap on flipper microSD [by tcpassos](https://github.com/tcpassos/flipperzero-firmware-with-wifi-marauder-companion) -> Only with custom marauder build (It is necessary to uncomment "#define WRITE_PACKETS_SERIAL" in configs.h (in marauder fw) and compile the firmware for the wifi board.) Or download precompiled build -> [Download esp32_marauder_ver_flipper_sd_serial.bin](https://github.com/justcallmekoko/ESP32Marauder/releases/latest)
|
||||||
|
- 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** [(by @gid9798)](https://github.com/gid9798)
|
||||||
|
- 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)
|
||||||
|
- Lightmeter [(by oleksiikutuzov)](https://github.com/oleksiikutuzov/flipperzero-lightmeter)
|
||||||
|
- 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)
|
||||||
|
- **SWD Probe** [(by g3gg0)](https://github.com/g3gg0/flipper-swd_probe)
|
||||||
|
- IR Scope [(by kallanreed)](https://github.com/DarkFlippers/unleashed-firmware/pull/407)
|
||||||
|
- **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)
|
||||||
|
- **Mifare Nested** [(by AloneLiberty)](https://github.com/AloneLiberty/FlipperNested) - Works with PC and python app `FlipperNested`
|
||||||
|
- **NFC Maker** plugin (make tags with URLs, Wifi and other things) [(by Willy-JL)](https://github.com/ClaraCrazy/Flipper-Xtreme/tree/dev/applications/external/nfc_maker)
|
||||||
|
- ESP32-CAM -> Camera Suite [(by CodyTolene)](https://github.com/CodyTolene/Flipper-Zero-Camera-Suite)
|
||||||
|
|
||||||
See full list and sources here: [xMasterX/all-the-plugins](https://github.com/xMasterX/all-the-plugins/tree/dev)
|
Games:
|
||||||
|
- DOOM (ported and fixed by @xMasterX & @Svarich & @hedger) [(original 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)
|
||||||
|
- Bomberduck [(by leo-need-more-coffee)](https://github.com/leo-need-more-coffee/flipperzero-bomberduck)
|
||||||
|
- JetPack Joyride [(by timstrasser)](https://github.com/timstrasser)
|
||||||
|
|
||||||
### Official Flipper Zero Apps Catalog [web version](https://lab.flipper.net/apps) or mobile app
|
|
||||||
|
|
||||||
# Instructions
|
# Instructions
|
||||||
## First lock official docs [docs.flipper.net](https://docs.flipper.net/)
|
## [- How to install firmware](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)
|
||||||
## [How to install](/documentation/HowToInstall.md) - [versions info](/CHANGELOG.md#recommended-update-option---web-updater): `n`,` `,`e`...
|
|
||||||
## Firmware & Development
|
|
||||||
|
|
||||||
### - **[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
|
## [- How to use Mifare Nested plugin to recover keys](https://github.com/AloneLiberty/FlipperNested#how-to-use-it)
|
||||||
|
|
||||||
### - System: [How to change Flipper name](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/CustomFlipperName.md)
|
## [- How to make captures to add them into Universal IR remotes](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/InfraredCaptures.md)
|
||||||
|
|
||||||
### - BadUSB: [How to add new keyboard layouts](https://github.com/dummy-decoy/flipperzero_badusb_kl)
|
### **Sub-GHz**
|
||||||
|
|
||||||
### - Infrared: [How to make captures to add them into Universal IR remotes](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/InfraredCaptures.md)
|
## [- Transmission is blocked? - How to extend Sub-GHz frequency range](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/DangerousSettings.md)
|
||||||
|
|
||||||
## **Sub-GHz**
|
## [- How to add extra Sub-GHz frequencies](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzSettings.md)
|
||||||
|
|
||||||
### - External Radio: [How to connect CC1101 module](https://github.com/quen0n/flipperzero-ext-cc1101)
|
## [- 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)
|
||||||
|
|
||||||
### - Transmission is blocked? [How to extend Sub-GHz frequency range](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/DangerousSettings.md)
|
## [- Configure Sub-GHz Remote App](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemotePlugin.md)
|
||||||
|
|
||||||
### - [How to add extra Sub-GHz frequencies](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzSettings.md)
|
### **Plugins**
|
||||||
|
|
||||||
### - [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)
|
## [- 🎲 Download Extra plugins for Unleashed](https://github.com/xMasterX/all-the-plugins)
|
||||||
|
|
||||||
### - [~~Configure Sub-GHz Remote App~~](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemotePlugin.md) Not recomeded, please use embedded configurator
|
## [- TOTP (Authenticator) config description](https://github.com/akopachov/flipper-zero_authenticator/blob/master/docs/conf-file_description.md)
|
||||||
|
|
||||||
## **Plugins**
|
## [- Barcode Generator](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/BarcodeGenerator.md)
|
||||||
|
|
||||||
### - TOTP (Authenticator): [config description](https://github.com/akopachov/flipper-zero_authenticator/blob/master/docs/conf-file_description.md)
|
## [- Multi Converter](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/MultiConverter.md)
|
||||||
|
|
||||||
### - Mifare Nested plugin: [How to recover keys](https://github.com/AloneLiberty/FlipperNested#how-to-use-it)
|
## [- WAV Player sample files & how to convert](https://github.com/UberGuidoZ/Flipper/tree/main/Wav_Player#readme)
|
||||||
|
|
||||||
### - Barcode Generator: [How to use](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/BarcodeGenerator.md)
|
## [- Sub-GHz playlist generator script](https://github.com/darmiel/flipper-scripts/blob/main/playlist/playlist_creator_by_chunk.py)
|
||||||
|
|
||||||
### - Multi Converter: [How to use](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/MultiConverter.md)
|
### **Plugins that works with external hardware**
|
||||||
|
|
||||||
### - WAV Player: [sample files & how to convert](https://github.com/UberGuidoZ/Flipper/tree/main/Wav_Player#readme)
|
## [- How to use: Unitemp - Temperature sensors reader](https://github.com/quen0n/unitemp-flipperzero#readme)
|
||||||
|
|
||||||
### - Sub-GHz playlist: [generator script](https://github.com/darmiel/flipper-scripts/blob/main/playlist/playlist_creator_by_chunk.py)
|
## [- How to use: [NMEA] GPS](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/applications/external/gps_nmea_uart/README.md)
|
||||||
|
|
||||||
## **Plugins that works with external hardware** [GPIO]
|
## [- How to use: i2c Tools](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/applications/external/flipper_i2ctools/README.md)
|
||||||
|
|
||||||
### - Unitemp - Temperature sensors reader: [How to use & supported sensors](https://github.com/quen0n/unitemp-flipperzero#readme)
|
## [- How to use: [NRF24] plugins](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/NRF24.md)
|
||||||
|
|
||||||
### - [NMEA] GPS: [How to use](https://github.com/xMasterX/all-the-plugins/blob/dev/base_pack/gps_nmea_uart/README.md)
|
## [- How to use: [WiFi] Scanner](https://github.com/SequoiaSan/FlipperZero-WiFi-Scanner_Module#readme)
|
||||||
|
|
||||||
### - i2c Tools [How to use](https://github.com/xMasterX/all-the-plugins/blob/dev/base_pack/flipper_i2ctools/README.md)
|
## [- How to use: [ESP8266] Deauther](https://github.com/SequoiaSan/FlipperZero-Wifi-ESP8266-Deauther-Module#readme)
|
||||||
|
|
||||||
### - [NRF24] plugins: [How to use](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/NRF24.md)
|
## [- How to use: [ESP32] WiFi Marauder](https://github.com/UberGuidoZ/Flipper/tree/main/Wifi_DevBoard)
|
||||||
|
|
||||||
|
## [- How to use: [ESP32-CAM] Camera Suite](https://github.com/CodyTolene/Flipper-Zero-Camera-Suite)
|
||||||
|
|
||||||
### - [WiFi] Scanner: [How to use](https://github.com/SequoiaSan/FlipperZero-WiFi-Scanner_Module#readme) | [Web Flasher](https://sequoiasan.github.io/FlipperZero-WiFi-Scanner_Module/)
|
## [- [WiFi] Scanner - Web Flasher for module firmware](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/)
|
## [- [ESP8266] Deauther - Web Flasher for module firmware](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)
|
## [- Windows: How to Upload .bin to ESP32/ESP8266](https://github.com/SequoiaSan/Guide-How-To-Upload-bin-to-ESP8266-ESP32)
|
||||||
|
|
||||||
### - [ESP32-CAM] Camera Suite: [How to use](https://github.com/CodyTolene/Flipper-Zero-Camera-Suite)
|
## [- How to use: [GPIO] SentrySafe plugin](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SentrySafe.md)
|
||||||
|
|
||||||
### - 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)
|
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
@@ -255,7 +267,13 @@ See full list and sources here: [xMasterX/all-the-plugins](https://github.com/xM
|
|||||||
|
|
||||||
# Links
|
# Links
|
||||||
|
|
||||||
* Official Docs: [docs.flipper.net](https://docs.flipper.net/)
|
* Unofficial Discord: [discord.unleashedflip.com](https://discord.unleashedflip.com)
|
||||||
|
* Hello world - plugin tutorial (English): [https://github.com/DroomOne/Flipper-Plugin-Tutorial](https://github.com/DroomOne/Flipper-Plugin-Tutorial)
|
||||||
|
* Hello world - plugin tutorial (in Russian): [https://yakovlev.me/hello-flipper-zero/](https://yakovlev.me/hello-flipper-zero/)
|
||||||
|
* CLion IDE - How to setup workspace for flipper firmware development: [https://krasovs.ky/2022/11/01/flipper-zero-clion.html](https://krasovs.ky/2022/11/01/flipper-zero-clion.html)
|
||||||
|
* 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/)
|
* Official Forum: [forum.flipperzero.one](https://forum.flipperzero.one/)
|
||||||
|
|
||||||
# Project structure
|
# Project structure
|
||||||
|
|||||||
70
SConstruct
@@ -45,7 +45,6 @@ distenv = coreenv.Clone(
|
|||||||
],
|
],
|
||||||
ENV=os.environ,
|
ENV=os.environ,
|
||||||
UPDATE_BUNDLE_DIR="dist/${DIST_DIR}/f${TARGET_HW}-update-${DIST_SUFFIX}",
|
UPDATE_BUNDLE_DIR="dist/${DIST_DIR}/f${TARGET_HW}-update-${DIST_SUFFIX}",
|
||||||
VSCODE_LANG_SERVER=ARGUMENTS.get("LANG_SERVER", "cpptools"),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
firmware_env = distenv.AddFwProject(
|
firmware_env = distenv.AddFwProject(
|
||||||
@@ -67,22 +66,20 @@ if GetOption("fullenv") or any(
|
|||||||
# Target for self-update package
|
# Target for self-update package
|
||||||
dist_basic_arguments = [
|
dist_basic_arguments = [
|
||||||
"--bundlever",
|
"--bundlever",
|
||||||
"${UPDATE_VERSION_STRING}",
|
'"${UPDATE_VERSION_STRING}"',
|
||||||
]
|
]
|
||||||
dist_radio_arguments = [
|
dist_radio_arguments = [
|
||||||
"--radio",
|
"--radio",
|
||||||
"${ROOT_DIR.abspath}/${COPRO_STACK_BIN_DIR}/${COPRO_STACK_BIN}",
|
'"${ROOT_DIR.abspath}/${COPRO_STACK_BIN_DIR}/${COPRO_STACK_BIN}"',
|
||||||
"--radiotype",
|
"--radiotype",
|
||||||
"${COPRO_STACK_TYPE}",
|
"${COPRO_STACK_TYPE}",
|
||||||
"${COPRO_DISCLAIMER}",
|
"${COPRO_DISCLAIMER}",
|
||||||
"--obdata",
|
"--obdata",
|
||||||
"${ROOT_DIR.abspath}/${COPRO_OB_DATA}",
|
'"${ROOT_DIR.abspath}/${COPRO_OB_DATA}"',
|
||||||
"--stackversion",
|
|
||||||
"${COPRO_CUBE_VERSION}",
|
|
||||||
]
|
]
|
||||||
dist_resource_arguments = [
|
dist_resource_arguments = [
|
||||||
"-r",
|
"-r",
|
||||||
firmware_env.subst("${RESOURCES_ROOT}"),
|
'"${ROOT_DIR.abspath}/assets/resources"',
|
||||||
]
|
]
|
||||||
dist_splash_arguments = (
|
dist_splash_arguments = (
|
||||||
[
|
[
|
||||||
@@ -95,7 +92,7 @@ if GetOption("fullenv") or any(
|
|||||||
|
|
||||||
selfupdate_dist = distenv.DistCommand(
|
selfupdate_dist = distenv.DistCommand(
|
||||||
"updater_package",
|
"updater_package",
|
||||||
(distenv["DIST_DEPENDS"], firmware_env["FW_RESOURCES_MANIFEST"]),
|
(distenv["DIST_DEPENDS"], firmware_env["FW_RESOURCES"]),
|
||||||
DIST_EXTRA=[
|
DIST_EXTRA=[
|
||||||
*dist_basic_arguments,
|
*dist_basic_arguments,
|
||||||
*dist_radio_arguments,
|
*dist_radio_arguments,
|
||||||
@@ -128,8 +125,7 @@ if GetOption("fullenv") or any(
|
|||||||
|
|
||||||
# Installation over USB & CLI
|
# Installation over USB & CLI
|
||||||
usb_update_package = distenv.AddUsbFlashTarget(
|
usb_update_package = distenv.AddUsbFlashTarget(
|
||||||
"#build/usbinstall.flag",
|
"#build/usbinstall.flag", (firmware_env["FW_RESOURCES"], selfupdate_dist)
|
||||||
(firmware_env["FW_RESOURCES_MANIFEST"], selfupdate_dist),
|
|
||||||
)
|
)
|
||||||
distenv.Alias("flash_usb_full", usb_update_package)
|
distenv.Alias("flash_usb_full", usb_update_package)
|
||||||
|
|
||||||
@@ -167,25 +163,17 @@ Depends(
|
|||||||
list(app_artifact.validator for app_artifact in external_app_list),
|
list(app_artifact.validator for app_artifact in external_app_list),
|
||||||
)
|
)
|
||||||
Alias("fap_dist", fap_dist)
|
Alias("fap_dist", fap_dist)
|
||||||
|
# distenv.Default(fap_dist)
|
||||||
|
|
||||||
|
distenv.Depends(firmware_env["FW_RESOURCES"], external_apps_artifacts.resources_dist)
|
||||||
|
|
||||||
# Copy all faps to device
|
# Copy all faps to device
|
||||||
|
|
||||||
fap_deploy = distenv.PhonyTarget(
|
fap_deploy = distenv.PhonyTarget(
|
||||||
"fap_deploy",
|
"fap_deploy",
|
||||||
[
|
"${PYTHON3} ${FBT_SCRIPT_DIR}/storage.py -p ${FLIP_PORT} send ${SOURCE} /ext/apps",
|
||||||
[
|
source=Dir("#/assets/resources/apps"),
|
||||||
"${PYTHON3}",
|
|
||||||
"${FBT_SCRIPT_DIR}/storage.py",
|
|
||||||
"-p",
|
|
||||||
"${FLIP_PORT}",
|
|
||||||
"send",
|
|
||||||
"${SOURCE}",
|
|
||||||
"/ext/apps",
|
|
||||||
]
|
|
||||||
],
|
|
||||||
source=firmware_env.Dir(("${RESOURCES_ROOT}/apps")),
|
|
||||||
)
|
)
|
||||||
Depends(fap_deploy, firmware_env["FW_RESOURCES_MANIFEST"])
|
|
||||||
|
|
||||||
|
|
||||||
# Target for bundling core2 package for qFlipper
|
# Target for bundling core2 package for qFlipper
|
||||||
@@ -196,15 +184,27 @@ copro_dist = distenv.CoproBuilder(
|
|||||||
distenv.AlwaysBuild(copro_dist)
|
distenv.AlwaysBuild(copro_dist)
|
||||||
distenv.Alias("copro_dist", copro_dist)
|
distenv.Alias("copro_dist", copro_dist)
|
||||||
|
|
||||||
|
firmware_flash = distenv.AddOpenOCDFlashTarget(firmware_env)
|
||||||
firmware_flash = distenv.AddFwFlashTarget(firmware_env)
|
|
||||||
distenv.Alias("flash", firmware_flash)
|
distenv.Alias("flash", firmware_flash)
|
||||||
|
|
||||||
# To be implemented in fwflash.py
|
|
||||||
firmware_jflash = distenv.AddJFlashTarget(firmware_env)
|
firmware_jflash = distenv.AddJFlashTarget(firmware_env)
|
||||||
distenv.Alias("jflash", firmware_jflash)
|
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_trace_all",
|
||||||
"$GDB $GDBOPTS $SOURCES $GDBFLASH",
|
"$GDB $GDBOPTS $SOURCES $GDBFLASH",
|
||||||
source=firmware_env["FW_ELF"],
|
source=firmware_env["FW_ELF"],
|
||||||
@@ -323,10 +323,9 @@ distenv.PhonyTarget(
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Start Flipper CLI via PySerial's miniterm
|
# Start Flipper CLI via PySerial's miniterm
|
||||||
distenv.PhonyTarget("cli", "${PYTHON3} ${FBT_SCRIPT_DIR}/serial_cli.py -p ${FLIP_PORT}")
|
distenv.PhonyTarget(
|
||||||
|
"cli", "${PYTHON3} ${FBT_SCRIPT_DIR}/serial_cli.py -p ${FLIP_PORT}"
|
||||||
# Update WiFi devboard firmware
|
)
|
||||||
distenv.PhonyTarget("devboard_flash", "${PYTHON3} ${FBT_SCRIPT_DIR}/wifi_board.py")
|
|
||||||
|
|
||||||
|
|
||||||
# Find blackmagic probe
|
# Find blackmagic probe
|
||||||
@@ -346,14 +345,7 @@ distenv.PhonyTarget(
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Prepare vscode environment
|
# Prepare vscode environment
|
||||||
VSCODE_LANG_SERVER = cmd_environment["LANG_SERVER"]
|
vscode_dist = distenv.Install("#.vscode", distenv.Glob("#.vscode/example/*"))
|
||||||
vscode_dist = distenv.Install(
|
|
||||||
"#.vscode",
|
|
||||||
[
|
|
||||||
distenv.Glob("#.vscode/example/*.json"),
|
|
||||||
distenv.Glob(f"#.vscode/example/{VSCODE_LANG_SERVER}/*.json"),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
distenv.Precious(vscode_dist)
|
distenv.Precious(vscode_dist)
|
||||||
distenv.NoClean(vscode_dist)
|
distenv.NoClean(vscode_dist)
|
||||||
distenv.Alias("vscode_dist", vscode_dist)
|
distenv.Alias("vscode_dist", vscode_dist)
|
||||||
|
|||||||
@@ -35,6 +35,21 @@ Applications for main Flipper menu.
|
|||||||
- `u2f` - U2F Application
|
- `u2f` - U2F Application
|
||||||
|
|
||||||
|
|
||||||
|
## External
|
||||||
|
|
||||||
|
External applications deployed to SD Card
|
||||||
|
|
||||||
|
- `clock` - Clock application
|
||||||
|
- `dap_link` - DAP Link OnChip debugger
|
||||||
|
- `hid_app` - USB/BT Remote controller
|
||||||
|
- `music_player` - Music player app (demo)
|
||||||
|
- `nfc_magic` - NFC MFC Magic card application
|
||||||
|
- `picopass` - Picopass reader / writer
|
||||||
|
- `signal_generator` - Signal generator app: PWM and clock generator
|
||||||
|
- `snake_game` - Snake game application
|
||||||
|
- `spi_mem_manager` - SPI Memory reader / flasher
|
||||||
|
- `weather_station` - SubGHz weather station
|
||||||
|
|
||||||
## services
|
## services
|
||||||
|
|
||||||
Background services providing system APIs to applications.
|
Background services providing system APIs to applications.
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ bool WIEGAND::DoWiegandConversion() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO FL-3490: Handle validation failure case!
|
// TODO: Handle validation failure case!
|
||||||
} else if(4 == _bitCount) {
|
} else if(4 == _bitCount) {
|
||||||
// 4-bit Wiegand codes have no data integrity check so we just
|
// 4-bit Wiegand codes have no data integrity check so we just
|
||||||
// read the LOW nibble.
|
// read the LOW nibble.
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
App(
|
|
||||||
appid="ccid_test",
|
|
||||||
name="CCID Debug",
|
|
||||||
apptype=FlipperAppType.DEBUG,
|
|
||||||
entry_point="ccid_test_app",
|
|
||||||
cdefines=["CCID_TEST"],
|
|
||||||
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;
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
struct ISO7816_Response_APDU {
|
|
||||||
uint8_t SW1;
|
|
||||||
uint8_t SW2;
|
|
||||||
} __attribute__((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_
|
|
||||||
@@ -71,7 +71,7 @@ static void direct_draw_run(DirectDraw* instance) {
|
|||||||
size_t counter = 0;
|
size_t counter = 0;
|
||||||
float fps = 0;
|
float fps = 0;
|
||||||
|
|
||||||
furi_thread_set_current_priority(FuriThreadPriorityIdle);
|
vTaskPrioritySet(furi_thread_get_current_id(), FuriThreadPriorityIdle);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
size_t elapsed = DWT->CYCCNT - start;
|
size_t elapsed = DWT->CYCCNT - start;
|
||||||
|
|||||||
@@ -21,51 +21,22 @@ static void rpc_debug_app_tick_event_callback(void* context) {
|
|||||||
scene_manager_handle_tick_event(app->scene_manager);
|
scene_manager_handle_tick_event(app->scene_manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void rpc_debug_app_rpc_command_callback(RpcAppSystemEvent event, void* context) {
|
||||||
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) {
|
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
RpcDebugApp* app = context;
|
RpcDebugApp* app = context;
|
||||||
furi_assert(app->rpc);
|
furi_assert(app->rpc);
|
||||||
|
|
||||||
if(event->type == RpcAppEventTypeSessionClose) {
|
if(event == RpcAppEventSessionClose) {
|
||||||
scene_manager_stop(app->scene_manager);
|
scene_manager_stop(app->scene_manager);
|
||||||
view_dispatcher_stop(app->view_dispatcher);
|
view_dispatcher_stop(app->view_dispatcher);
|
||||||
rpc_system_app_set_callback(app->rpc, NULL, NULL);
|
rpc_system_app_set_callback(app->rpc, NULL, NULL);
|
||||||
app->rpc = NULL;
|
app->rpc = NULL;
|
||||||
} else if(event->type == RpcAppEventTypeAppExit) {
|
} else if(event == RpcAppEventAppExit) {
|
||||||
scene_manager_stop(app->scene_manager);
|
scene_manager_stop(app->scene_manager);
|
||||||
view_dispatcher_stop(app->view_dispatcher);
|
view_dispatcher_stop(app->view_dispatcher);
|
||||||
rpc_system_app_confirm(app->rpc, true);
|
rpc_system_app_confirm(app->rpc, RpcAppEventAppExit, 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);
|
|
||||||
} else {
|
} 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"
|
#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) {
|
void rpc_debug_app_scene_receive_data_exchange_on_enter(void* context) {
|
||||||
RpcDebugApp* app = context;
|
RpcDebugApp* app = context;
|
||||||
strncpy(app->text_store, "Received data will appear here...", TEXT_STORE_SIZE);
|
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_text(app->text_box, app->text_store);
|
||||||
text_box_set_font(app->text_box, TextBoxFontHex);
|
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);
|
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.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == RpcDebugAppCustomEventRpcDataExchange) {
|
if(event.event == RpcDebugAppCustomEventRpcDataExchange) {
|
||||||
rpc_system_app_confirm(app->rpc, true);
|
|
||||||
notification_message(app->notifications, &sequence_blink_cyan_100);
|
notification_message(app->notifications, &sequence_blink_cyan_100);
|
||||||
notification_message(app->notifications, &sequence_display_backlight_on);
|
notification_message(app->notifications, &sequence_display_backlight_on);
|
||||||
text_box_set_text(app->text_box, app->text_store);
|
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) {
|
void rpc_debug_app_scene_receive_data_exchange_on_exit(void* context) {
|
||||||
RpcDebugApp* app = context;
|
RpcDebugApp* app = context;
|
||||||
text_box_reset(app->text_box);
|
text_box_reset(app->text_box);
|
||||||
|
rpc_system_app_set_data_exchange_callback(app->rpc, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ static void subghz_test_packet_rx_callback(bool level, uint32_t duration, void*
|
|||||||
subghz_decoder_princeton_for_testing_parse(instance->decoder, level, duration);
|
subghz_decoder_princeton_for_testing_parse(instance->decoder, level, duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//todo
|
||||||
static void subghz_test_packet_rx_pt_callback(SubGhzDecoderPrinceton* parser, void* context) {
|
static void subghz_test_packet_rx_pt_callback(SubGhzDecoderPrinceton* parser, void* context) {
|
||||||
UNUSED(parser);
|
UNUSED(parser);
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
|
|||||||
@@ -3,9 +3,7 @@ App(
|
|||||||
apptype=FlipperAppType.STARTUP,
|
apptype=FlipperAppType.STARTUP,
|
||||||
entry_point="unit_tests_on_system_start",
|
entry_point="unit_tests_on_system_start",
|
||||||
cdefines=["APP_UNIT_TESTS"],
|
cdefines=["APP_UNIT_TESTS"],
|
||||||
requires=["system_settings"],
|
|
||||||
provides=["delay_test"],
|
provides=["delay_test"],
|
||||||
resources="resources",
|
|
||||||
order=100,
|
order=100,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ void bt_test_alloc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void bt_test_free() {
|
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_ref);
|
||||||
free(bt_test->nvm_ram_buff_dut);
|
free(bt_test->nvm_ram_buff_dut);
|
||||||
bt_keys_storage_free(bt_test->bt_keys_storage);
|
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) {
|
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_remove_test_file();
|
||||||
bt_test_keys_storage_profile();
|
bt_test_keys_storage_profile();
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ void test_furi_memmgr() {
|
|||||||
mu_assert_int_eq(66, ((uint8_t*)ptr)[i]);
|
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);
|
free(ptr);
|
||||||
|
|
||||||
// allocate and zero-initialize array (calloc)
|
// allocate and zero-initialize array (calloc)
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ MU_TEST(mu_test_furi_string_mem) {
|
|||||||
mu_check(string != NULL);
|
mu_check(string != NULL);
|
||||||
mu_check(!furi_string_empty(string));
|
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
|
// test furi_string_reset
|
||||||
furi_string_reset(string);
|
furi_string_reset(string);
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -5,11 +5,6 @@
|
|||||||
#include "../minunit.h"
|
#include "../minunit.h"
|
||||||
|
|
||||||
#define DATA_SIZE 4
|
#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() {
|
static void furi_hal_i2c_int_setup() {
|
||||||
furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
|
furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
|
||||||
@@ -19,14 +14,6 @@ static void furi_hal_i2c_int_teardown() {
|
|||||||
furi_hal_i2c_release(&furi_hal_i2c_handle_power);
|
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) {
|
MU_TEST(furi_hal_i2c_int_1b) {
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
uint8_t data_one = 0;
|
uint8_t data_one = 0;
|
||||||
@@ -116,116 +103,14 @@ MU_TEST(furi_hal_i2c_int_1b_fail) {
|
|||||||
mu_assert(data_one != 0, "9 invalid data");
|
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_TEST_SUITE(furi_hal_i2c_int_suite) {
|
||||||
MU_SUITE_CONFIGURE(&furi_hal_i2c_int_setup, &furi_hal_i2c_int_teardown);
|
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_1b);
|
||||||
MU_RUN_TEST(furi_hal_i2c_int_3b);
|
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_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() {
|
int run_minunit_test_furi_hal() {
|
||||||
MU_RUN_SUITE(furi_hal_i2c_int_suite);
|
MU_RUN_SUITE(furi_hal_i2c_int_suite);
|
||||||
MU_RUN_SUITE(furi_hal_i2c_ext_suite);
|
|
||||||
return MU_EXIT_CODE;
|
return MU_EXIT_CODE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ static void infrared_test_alloc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void infrared_test_free() {
|
static void infrared_test_free() {
|
||||||
furi_check(test);
|
furi_assert(test);
|
||||||
infrared_free_decoder(test->decoder_handler);
|
infrared_free_decoder(test->decoder_handler);
|
||||||
infrared_free_encoder(test->encoder_handler);
|
infrared_free_encoder(test->encoder_handler);
|
||||||
flipper_format_free(test->ff);
|
flipper_format_free(test->ff);
|
||||||
|
|||||||
@@ -311,7 +311,7 @@ MU_TEST(test_bit_lib_test_parity) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST(test_bit_lib_remove_bit_every_nth) {
|
MU_TEST(test_bit_lib_remove_bit_every_nth) {
|
||||||
// TODO FL-3494: more tests
|
// TODO: more tests
|
||||||
uint8_t data_i[1] = {0b00001111};
|
uint8_t data_i[1] = {0b00001111};
|
||||||
uint8_t data_o[1] = {0b00011111};
|
uint8_t data_o[1] = {0b00011111};
|
||||||
size_t length;
|
size_t length;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ MU_TEST(manifest_iteration_test) {
|
|||||||
ResourceManifestReader* manifest_reader = resource_manifest_reader_alloc(storage);
|
ResourceManifestReader* manifest_reader = resource_manifest_reader_alloc(storage);
|
||||||
do {
|
do {
|
||||||
// Open manifest file
|
// Open manifest file
|
||||||
if(!resource_manifest_reader_open(manifest_reader, EXT_PATH("unit_tests/Manifest_test"))) {
|
if(!resource_manifest_reader_open(manifest_reader, EXT_PATH("unit_tests/Manifest"))) {
|
||||||
result = false;
|
result = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,458 +0,0 @@
|
|||||||
#ifdef FW_CFG_unit_tests
|
|
||||||
|
|
||||||
#include <lib/nfc/nfc.h>
|
|
||||||
#include <lib/nfc/helpers/iso14443_crc.h>
|
|
||||||
#include <lib/nfc/protocols/iso14443_3a/iso14443_3a.h>
|
|
||||||
|
|
||||||
#include <furi/furi.h>
|
|
||||||
|
|
||||||
#define NFC_MAX_BUFFER_SIZE (256)
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
NfcTransportLogLevelWarning,
|
|
||||||
NfcTransportLogLevelInfo,
|
|
||||||
} NfcTransportLogLevel;
|
|
||||||
|
|
||||||
FuriMessageQueue* poller_queue = NULL;
|
|
||||||
FuriMessageQueue* listener_queue = NULL;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
NfcMessageTypeTx,
|
|
||||||
NfcMessageTypeTimeout,
|
|
||||||
NfcMessageTypeAbort,
|
|
||||||
} NfcMessageType;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint16_t data_bits;
|
|
||||||
uint8_t data[NFC_MAX_BUFFER_SIZE];
|
|
||||||
} NfcMessageData;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
NfcMessageType type;
|
|
||||||
NfcMessageData data;
|
|
||||||
} NfcMessage;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
NfcStateIdle,
|
|
||||||
NfcStateReady,
|
|
||||||
NfcStateReset,
|
|
||||||
} NfcState;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
Iso14443_3aColResStatusIdle,
|
|
||||||
Iso14443_3aColResStatusInProgress,
|
|
||||||
Iso14443_3aColResStatusDone,
|
|
||||||
} Iso14443_3aColResStatus;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
Iso14443_3aSensResp sens_resp;
|
|
||||||
Iso14443_3aSddResp sdd_resp[2];
|
|
||||||
Iso14443_3aSelResp sel_resp[2];
|
|
||||||
} Iso14443_3aColResData;
|
|
||||||
|
|
||||||
struct Nfc {
|
|
||||||
NfcState state;
|
|
||||||
|
|
||||||
Iso14443_3aColResStatus col_res_status;
|
|
||||||
Iso14443_3aColResData col_res_data;
|
|
||||||
|
|
||||||
NfcEventCallback callback;
|
|
||||||
void* context;
|
|
||||||
|
|
||||||
NfcMode mode;
|
|
||||||
|
|
||||||
FuriThread* worker_thread;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void nfc_test_print(
|
|
||||||
NfcTransportLogLevel log_level,
|
|
||||||
const char* message,
|
|
||||||
uint8_t* buffer,
|
|
||||||
uint16_t bits) {
|
|
||||||
FuriString* str = furi_string_alloc();
|
|
||||||
size_t bytes = (bits + 7) / 8;
|
|
||||||
|
|
||||||
for(size_t i = 0; i < bytes; i++) {
|
|
||||||
furi_string_cat_printf(str, " %02X", buffer[i]);
|
|
||||||
}
|
|
||||||
if(log_level == NfcTransportLogLevelWarning) {
|
|
||||||
FURI_LOG_W(message, "%s", furi_string_get_cstr(str));
|
|
||||||
} else {
|
|
||||||
FURI_LOG_I(message, "%s", furi_string_get_cstr(str));
|
|
||||||
}
|
|
||||||
|
|
||||||
furi_string_free(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void nfc_prepare_col_res_data(
|
|
||||||
Nfc* instance,
|
|
||||||
uint8_t* uid,
|
|
||||||
uint8_t uid_len,
|
|
||||||
uint8_t* atqa,
|
|
||||||
uint8_t sak) {
|
|
||||||
memcpy(instance->col_res_data.sens_resp.sens_resp, atqa, 2);
|
|
||||||
|
|
||||||
if(uid_len == 7) {
|
|
||||||
instance->col_res_data.sdd_resp[0].nfcid[0] = 0x88;
|
|
||||||
memcpy(&instance->col_res_data.sdd_resp[0].nfcid[1], uid, 3);
|
|
||||||
uint8_t bss = 0;
|
|
||||||
for(size_t i = 0; i < 4; i++) {
|
|
||||||
bss ^= instance->col_res_data.sdd_resp[0].nfcid[i];
|
|
||||||
}
|
|
||||||
instance->col_res_data.sdd_resp[0].bss = bss;
|
|
||||||
instance->col_res_data.sel_resp[0].sak = 0x04;
|
|
||||||
|
|
||||||
memcpy(instance->col_res_data.sdd_resp[1].nfcid, &uid[3], 4);
|
|
||||||
bss = 0;
|
|
||||||
for(size_t i = 0; i < 4; i++) {
|
|
||||||
bss ^= instance->col_res_data.sdd_resp[1].nfcid[i];
|
|
||||||
}
|
|
||||||
instance->col_res_data.sdd_resp[1].bss = bss;
|
|
||||||
instance->col_res_data.sel_resp[1].sak = sak;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
furi_crash("Not supporting not 7 bytes");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Nfc* nfc_alloc() {
|
|
||||||
Nfc* instance = malloc(sizeof(Nfc));
|
|
||||||
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
void nfc_free(Nfc* instance) {
|
|
||||||
furi_check(instance);
|
|
||||||
|
|
||||||
free(instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
void nfc_config(Nfc* instance, NfcMode mode, NfcTech tech) {
|
|
||||||
UNUSED(instance);
|
|
||||||
UNUSED(tech);
|
|
||||||
|
|
||||||
instance->mode = mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void nfc_set_fdt_poll_fc(Nfc* instance, uint32_t fdt_poll_fc) {
|
|
||||||
UNUSED(instance);
|
|
||||||
UNUSED(fdt_poll_fc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void nfc_set_fdt_listen_fc(Nfc* instance, uint32_t fdt_listen_fc) {
|
|
||||||
UNUSED(instance);
|
|
||||||
UNUSED(fdt_listen_fc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void nfc_set_mask_receive_time_fc(Nfc* instance, uint32_t mask_rx_time_fc) {
|
|
||||||
UNUSED(instance);
|
|
||||||
UNUSED(mask_rx_time_fc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void nfc_set_fdt_poll_poll_us(Nfc* instance, uint32_t fdt_poll_poll_us) {
|
|
||||||
UNUSED(instance);
|
|
||||||
UNUSED(fdt_poll_poll_us);
|
|
||||||
}
|
|
||||||
|
|
||||||
void nfc_set_guard_time_us(Nfc* instance, uint32_t guard_time_us) {
|
|
||||||
UNUSED(instance);
|
|
||||||
UNUSED(guard_time_us);
|
|
||||||
}
|
|
||||||
|
|
||||||
NfcError nfc_iso14443a_listener_set_col_res_data(
|
|
||||||
Nfc* instance,
|
|
||||||
uint8_t* uid,
|
|
||||||
uint8_t uid_len,
|
|
||||||
uint8_t* atqa,
|
|
||||||
uint8_t sak) {
|
|
||||||
furi_check(instance);
|
|
||||||
furi_check(uid);
|
|
||||||
furi_check(atqa);
|
|
||||||
|
|
||||||
nfc_prepare_col_res_data(instance, uid, uid_len, atqa, sak);
|
|
||||||
|
|
||||||
return NfcErrorNone;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t nfc_worker_poller(void* context) {
|
|
||||||
Nfc* instance = context;
|
|
||||||
furi_check(instance->callback);
|
|
||||||
|
|
||||||
instance->state = NfcStateReady;
|
|
||||||
NfcCommand command = NfcCommandContinue;
|
|
||||||
NfcEvent event = {};
|
|
||||||
|
|
||||||
while(true) {
|
|
||||||
event.type = NfcEventTypePollerReady;
|
|
||||||
command = instance->callback(event, instance->context);
|
|
||||||
if(command == NfcCommandStop) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
instance->state = NfcStateIdle;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void nfc_worker_listener_pass_col_res(Nfc* instance, uint8_t* rx_data, uint16_t rx_bits) {
|
|
||||||
furi_check(instance->col_res_status != Iso14443_3aColResStatusDone);
|
|
||||||
BitBuffer* tx_buffer = bit_buffer_alloc(NFC_MAX_BUFFER_SIZE);
|
|
||||||
|
|
||||||
bool processed = false;
|
|
||||||
|
|
||||||
if((rx_bits == 7) && (rx_data[0] == 0x52)) {
|
|
||||||
instance->col_res_status = Iso14443_3aColResStatusInProgress;
|
|
||||||
bit_buffer_copy_bytes(
|
|
||||||
tx_buffer,
|
|
||||||
instance->col_res_data.sens_resp.sens_resp,
|
|
||||||
sizeof(instance->col_res_data.sens_resp.sens_resp));
|
|
||||||
nfc_listener_tx(instance, tx_buffer);
|
|
||||||
processed = true;
|
|
||||||
} else if(rx_bits == 2 * 8) {
|
|
||||||
if((rx_data[0] == 0x93) && (rx_data[1] == 0x20)) {
|
|
||||||
bit_buffer_copy_bytes(
|
|
||||||
tx_buffer,
|
|
||||||
(const uint8_t*)&instance->col_res_data.sdd_resp[0],
|
|
||||||
sizeof(Iso14443_3aSddResp));
|
|
||||||
nfc_listener_tx(instance, tx_buffer);
|
|
||||||
processed = true;
|
|
||||||
} else if((rx_data[0] == 0x95) && (rx_data[1] == 0x20)) {
|
|
||||||
bit_buffer_copy_bytes(
|
|
||||||
tx_buffer,
|
|
||||||
(const uint8_t*)&instance->col_res_data.sdd_resp[1],
|
|
||||||
sizeof(Iso14443_3aSddResp));
|
|
||||||
nfc_listener_tx(instance, tx_buffer);
|
|
||||||
processed = true;
|
|
||||||
}
|
|
||||||
} else if(rx_bits == 9 * 8) {
|
|
||||||
if((rx_data[0] == 0x93) && (rx_data[1] == 0x70)) {
|
|
||||||
bit_buffer_set_size_bytes(tx_buffer, 1);
|
|
||||||
bit_buffer_set_byte(tx_buffer, 0, instance->col_res_data.sel_resp[0].sak);
|
|
||||||
iso14443_crc_append(Iso14443CrcTypeA, tx_buffer);
|
|
||||||
nfc_listener_tx(instance, tx_buffer);
|
|
||||||
processed = true;
|
|
||||||
} else if((rx_data[0] == 0x95) && (rx_data[1] == 0x70)) {
|
|
||||||
bit_buffer_set_size_bytes(tx_buffer, 1);
|
|
||||||
bit_buffer_set_byte(tx_buffer, 0, instance->col_res_data.sel_resp[1].sak);
|
|
||||||
iso14443_crc_append(Iso14443CrcTypeA, tx_buffer);
|
|
||||||
nfc_listener_tx(instance, tx_buffer);
|
|
||||||
instance->col_res_status = Iso14443_3aColResStatusDone;
|
|
||||||
NfcEvent event = {.type = NfcEventTypeListenerActivated};
|
|
||||||
instance->callback(event, instance->context);
|
|
||||||
|
|
||||||
processed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!processed) {
|
|
||||||
NfcMessage message = {.type = NfcMessageTypeTimeout};
|
|
||||||
furi_message_queue_put(poller_queue, &message, FuriWaitForever);
|
|
||||||
}
|
|
||||||
|
|
||||||
bit_buffer_free(tx_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t nfc_worker_listener(void* context) {
|
|
||||||
Nfc* instance = context;
|
|
||||||
furi_check(instance->callback);
|
|
||||||
|
|
||||||
NfcMessage message = {};
|
|
||||||
|
|
||||||
NfcEventData event_data = {};
|
|
||||||
event_data.buffer = bit_buffer_alloc(NFC_MAX_BUFFER_SIZE);
|
|
||||||
NfcEvent nfc_event = {.data = event_data};
|
|
||||||
|
|
||||||
while(true) {
|
|
||||||
furi_message_queue_get(listener_queue, &message, FuriWaitForever);
|
|
||||||
bit_buffer_copy_bits(event_data.buffer, message.data.data, message.data.data_bits);
|
|
||||||
if((message.data.data[0] == 0x52) && (message.data.data_bits == 7)) {
|
|
||||||
instance->col_res_status = Iso14443_3aColResStatusIdle;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(message.type == NfcMessageTypeAbort) {
|
|
||||||
break;
|
|
||||||
} else if(message.type == NfcMessageTypeTx) {
|
|
||||||
nfc_test_print(
|
|
||||||
NfcTransportLogLevelInfo, "RDR", message.data.data, message.data.data_bits);
|
|
||||||
if(instance->col_res_status != Iso14443_3aColResStatusDone) {
|
|
||||||
nfc_worker_listener_pass_col_res(
|
|
||||||
instance, message.data.data, message.data.data_bits);
|
|
||||||
} else {
|
|
||||||
instance->state = NfcStateReady;
|
|
||||||
nfc_event.type = NfcEventTypeRxEnd;
|
|
||||||
instance->callback(nfc_event, instance->context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
instance->state = NfcStateIdle;
|
|
||||||
instance->col_res_status = Iso14443_3aColResStatusIdle;
|
|
||||||
memset(&instance->col_res_data, 0, sizeof(instance->col_res_data));
|
|
||||||
bit_buffer_free(nfc_event.data.buffer);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void nfc_start(Nfc* instance, NfcEventCallback callback, void* context) {
|
|
||||||
furi_check(instance);
|
|
||||||
furi_check(instance->worker_thread == NULL);
|
|
||||||
|
|
||||||
if(instance->mode == NfcModeListener) {
|
|
||||||
furi_check(listener_queue == NULL);
|
|
||||||
// Check that poller didn't start
|
|
||||||
furi_check(poller_queue == NULL);
|
|
||||||
} else {
|
|
||||||
furi_check(poller_queue == NULL);
|
|
||||||
// Check that poller is started after listener
|
|
||||||
furi_check(listener_queue);
|
|
||||||
}
|
|
||||||
|
|
||||||
instance->callback = callback;
|
|
||||||
instance->context = context;
|
|
||||||
|
|
||||||
if(instance->mode == NfcModeListener) {
|
|
||||||
listener_queue = furi_message_queue_alloc(4, sizeof(NfcMessage));
|
|
||||||
} else {
|
|
||||||
poller_queue = furi_message_queue_alloc(4, sizeof(NfcMessage));
|
|
||||||
}
|
|
||||||
|
|
||||||
instance->worker_thread = furi_thread_alloc();
|
|
||||||
furi_thread_set_context(instance->worker_thread, instance);
|
|
||||||
furi_thread_set_priority(instance->worker_thread, FuriThreadPriorityHigh);
|
|
||||||
furi_thread_set_stack_size(instance->worker_thread, 8 * 1024);
|
|
||||||
|
|
||||||
if(instance->mode == NfcModeListener) {
|
|
||||||
furi_thread_set_name(instance->worker_thread, "NfcWorkerListener");
|
|
||||||
furi_thread_set_callback(instance->worker_thread, nfc_worker_listener);
|
|
||||||
} else {
|
|
||||||
furi_thread_set_name(instance->worker_thread, "NfcWorkerPoller");
|
|
||||||
furi_thread_set_callback(instance->worker_thread, nfc_worker_poller);
|
|
||||||
}
|
|
||||||
|
|
||||||
furi_thread_start(instance->worker_thread);
|
|
||||||
}
|
|
||||||
|
|
||||||
void nfc_stop(Nfc* instance) {
|
|
||||||
furi_check(instance);
|
|
||||||
furi_check(instance->worker_thread);
|
|
||||||
|
|
||||||
if(instance->mode == NfcModeListener) {
|
|
||||||
NfcMessage message = {.type = NfcMessageTypeAbort};
|
|
||||||
furi_message_queue_put(listener_queue, &message, FuriWaitForever);
|
|
||||||
furi_thread_join(instance->worker_thread);
|
|
||||||
|
|
||||||
furi_message_queue_free(listener_queue);
|
|
||||||
listener_queue = NULL;
|
|
||||||
|
|
||||||
furi_thread_free(instance->worker_thread);
|
|
||||||
instance->worker_thread = NULL;
|
|
||||||
} else {
|
|
||||||
furi_thread_join(instance->worker_thread);
|
|
||||||
|
|
||||||
furi_message_queue_free(poller_queue);
|
|
||||||
poller_queue = NULL;
|
|
||||||
|
|
||||||
furi_thread_free(instance->worker_thread);
|
|
||||||
instance->worker_thread = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called from worker thread
|
|
||||||
|
|
||||||
NfcError nfc_listener_tx(Nfc* instance, const BitBuffer* tx_buffer) {
|
|
||||||
furi_check(instance);
|
|
||||||
furi_check(poller_queue);
|
|
||||||
furi_check(listener_queue);
|
|
||||||
furi_check(tx_buffer);
|
|
||||||
|
|
||||||
NfcMessage message = {};
|
|
||||||
message.type = NfcMessageTypeTx;
|
|
||||||
message.data.data_bits = bit_buffer_get_size(tx_buffer);
|
|
||||||
bit_buffer_write_bytes(tx_buffer, message.data.data, bit_buffer_get_size_bytes(tx_buffer));
|
|
||||||
|
|
||||||
furi_message_queue_put(poller_queue, &message, FuriWaitForever);
|
|
||||||
|
|
||||||
return NfcErrorNone;
|
|
||||||
}
|
|
||||||
|
|
||||||
NfcError nfc_iso14443a_listener_tx_custom_parity(Nfc* instance, const BitBuffer* tx_buffer) {
|
|
||||||
return nfc_listener_tx(instance, tx_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
NfcError
|
|
||||||
nfc_poller_trx(Nfc* instance, const BitBuffer* tx_buffer, BitBuffer* rx_buffer, uint32_t fwt) {
|
|
||||||
furi_check(instance);
|
|
||||||
furi_check(tx_buffer);
|
|
||||||
furi_check(rx_buffer);
|
|
||||||
furi_check(poller_queue);
|
|
||||||
furi_check(listener_queue);
|
|
||||||
UNUSED(fwt);
|
|
||||||
|
|
||||||
NfcError error = NfcErrorNone;
|
|
||||||
|
|
||||||
NfcMessage message = {};
|
|
||||||
message.type = NfcMessageTypeTx;
|
|
||||||
message.data.data_bits = bit_buffer_get_size(tx_buffer);
|
|
||||||
bit_buffer_write_bytes(tx_buffer, message.data.data, bit_buffer_get_size_bytes(tx_buffer));
|
|
||||||
// Tx
|
|
||||||
furi_check(furi_message_queue_put(listener_queue, &message, FuriWaitForever) == FuriStatusOk);
|
|
||||||
// Rx
|
|
||||||
FuriStatus status = furi_message_queue_get(poller_queue, &message, 50);
|
|
||||||
|
|
||||||
if(status == FuriStatusErrorTimeout) {
|
|
||||||
error = NfcErrorTimeout;
|
|
||||||
} else if(message.type == NfcMessageTypeTx) {
|
|
||||||
bit_buffer_copy_bits(rx_buffer, message.data.data, message.data.data_bits);
|
|
||||||
nfc_test_print(
|
|
||||||
NfcTransportLogLevelWarning, "TAG", message.data.data, message.data.data_bits);
|
|
||||||
} else if(message.type == NfcMessageTypeTimeout) {
|
|
||||||
error = NfcErrorTimeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
NfcError nfc_iso14443a_poller_trx_custom_parity(
|
|
||||||
Nfc* instance,
|
|
||||||
const BitBuffer* tx_buffer,
|
|
||||||
BitBuffer* rx_buffer,
|
|
||||||
uint32_t fwt) {
|
|
||||||
return nfc_poller_trx(instance, tx_buffer, rx_buffer, fwt);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Technology specific API
|
|
||||||
|
|
||||||
NfcError nfc_iso14443a_poller_trx_short_frame(
|
|
||||||
Nfc* instance,
|
|
||||||
NfcIso14443aShortFrame frame,
|
|
||||||
BitBuffer* rx_buffer,
|
|
||||||
uint32_t fwt) {
|
|
||||||
UNUSED(frame);
|
|
||||||
|
|
||||||
BitBuffer* tx_buffer = bit_buffer_alloc(32);
|
|
||||||
bit_buffer_set_size(tx_buffer, 7);
|
|
||||||
bit_buffer_set_byte(tx_buffer, 0, 0x52);
|
|
||||||
|
|
||||||
NfcError error = nfc_poller_trx(instance, tx_buffer, rx_buffer, fwt);
|
|
||||||
|
|
||||||
bit_buffer_free(tx_buffer);
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
NfcError nfc_iso14443a_poller_trx_sdd_frame(
|
|
||||||
Nfc* instance,
|
|
||||||
const BitBuffer* tx_buffer,
|
|
||||||
BitBuffer* rx_buffer,
|
|
||||||
uint32_t fwt) {
|
|
||||||
return nfc_poller_trx(instance, tx_buffer, rx_buffer, fwt);
|
|
||||||
}
|
|
||||||
|
|
||||||
NfcError nfc_iso15693_listener_tx_sof(Nfc* instance) {
|
|
||||||
UNUSED(instance);
|
|
||||||
|
|
||||||
return NfcErrorNone;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
Filetype: Flipper NFC device
|
|
||||||
Version: 3
|
|
||||||
# Nfc device type can be UID, Mifare Ultralight, Mifare Classic
|
|
||||||
Device type: NTAG213
|
|
||||||
# UID, ATQA and SAK are common for all formats
|
|
||||||
UID: 04 AC 6B 72 BA 6C 80
|
|
||||||
ATQA: 00 44
|
|
||||||
SAK: 00
|
|
||||||
# Mifare Ultralight specific data
|
|
||||||
Data format version: 1
|
|
||||||
Signature: 2D AE BC AF 84 B8 85 87 C2 FB FE 76 13 58 86 72 8E 1D 3C B5 DA 24 23 44 E5 63 4D 4C 82 FB D7 18
|
|
||||||
Mifare version: 00 04 04 02 01 00 0F 03
|
|
||||||
Counter 0: 0
|
|
||||||
Tearing 0: 00
|
|
||||||
Counter 1: 0
|
|
||||||
Tearing 1: 00
|
|
||||||
Counter 2: 0
|
|
||||||
Tearing 2: 00
|
|
||||||
Pages total: 45
|
|
||||||
Pages read: 45
|
|
||||||
Page 0: 04 AC 6B 4B
|
|
||||||
Page 1: 72 BA 6C 80
|
|
||||||
Page 2: 24 48 00 00
|
|
||||||
Page 3: E1 10 12 00
|
|
||||||
Page 4: 00 00 41 50
|
|
||||||
Page 5: 00 00 31 31
|
|
||||||
Page 6: 00 20 09 28
|
|
||||||
Page 7: 00 03 31 59
|
|
||||||
Page 8: 91 DF D3 00
|
|
||||||
Page 9: 00 00 00 00
|
|
||||||
Page 10: 00 00 00 00
|
|
||||||
Page 11: 00 00 00 00
|
|
||||||
Page 12: 00 00 00 00
|
|
||||||
Page 13: 00 00 00 00
|
|
||||||
Page 14: 00 00 00 00
|
|
||||||
Page 15: 00 00 00 00
|
|
||||||
Page 16: 00 00 00 00
|
|
||||||
Page 17: 00 00 00 00
|
|
||||||
Page 18: 00 00 00 00
|
|
||||||
Page 19: 00 00 00 00
|
|
||||||
Page 20: 00 00 00 00
|
|
||||||
Page 21: 00 00 00 00
|
|
||||||
Page 22: 00 00 00 00
|
|
||||||
Page 23: 00 00 00 00
|
|
||||||
Page 24: 00 00 00 00
|
|
||||||
Page 25: 00 00 00 00
|
|
||||||
Page 26: 00 00 00 00
|
|
||||||
Page 27: 00 00 00 00
|
|
||||||
Page 28: 00 00 00 00
|
|
||||||
Page 29: 00 00 00 00
|
|
||||||
Page 30: 00 00 00 00
|
|
||||||
Page 31: 00 00 00 00
|
|
||||||
Page 32: 00 00 00 00
|
|
||||||
Page 33: 00 00 00 00
|
|
||||||
Page 34: 00 00 00 00
|
|
||||||
Page 35: 00 00 00 00
|
|
||||||
Page 36: 00 00 00 00
|
|
||||||
Page 37: 00 00 00 00
|
|
||||||
Page 38: 00 00 00 00
|
|
||||||
Page 39: 00 00 00 00
|
|
||||||
Page 40: 00 00 00 BD
|
|
||||||
Page 41: 04 00 00 04
|
|
||||||
Page 42: C0 05 00 00
|
|
||||||
Page 43: 95 3F 52 FF
|
|
||||||
Page 44: 00 00 00 00
|
|
||||||
Failed authentication attempts: 0
|
|
||||||
@@ -1,156 +0,0 @@
|
|||||||
Filetype: Flipper NFC device
|
|
||||||
Version: 3
|
|
||||||
# Nfc device type can be UID, Mifare Ultralight, Mifare Classic
|
|
||||||
Device type: NTAG215
|
|
||||||
# UID, ATQA and SAK are common for all formats
|
|
||||||
UID: 04 51 5C FA 6F 73 81
|
|
||||||
ATQA: 00 44
|
|
||||||
SAK: 00
|
|
||||||
# Mifare Ultralight specific data
|
|
||||||
Data format version: 1
|
|
||||||
Signature: 42 21 E4 6C 79 6A 81 5E EA 0D 93 6D 85 EE 4B 0C 2A 00 D5 77 F1 C5 67 F3 63 75 F8 EB 86 48 5E 6B
|
|
||||||
Mifare version: 00 04 04 02 01 00 11 03
|
|
||||||
Counter 0: 0
|
|
||||||
Tearing 0: 00
|
|
||||||
Counter 1: 0
|
|
||||||
Tearing 1: 00
|
|
||||||
Counter 2: 00
|
|
||||||
Tearing 2: 00
|
|
||||||
Pages total: 135
|
|
||||||
Pages read: 135
|
|
||||||
Page 0: 04 51 5C 81
|
|
||||||
Page 1: FA 6F 73 81
|
|
||||||
Page 2: 67 48 0F E0
|
|
||||||
Page 3: F1 10 FF EE
|
|
||||||
Page 4: A5 00 00 00
|
|
||||||
Page 5: 90 42 74 71
|
|
||||||
Page 6: FD 8F 50 61
|
|
||||||
Page 7: C5 65 1B 54
|
|
||||||
Page 8: EF 68 D0 8E
|
|
||||||
Page 9: 3D 35 DB 83
|
|
||||||
Page 10: D3 00 29 F6
|
|
||||||
Page 11: 42 2A A5 5C
|
|
||||||
Page 12: F1 69 0A FC
|
|
||||||
Page 13: B6 44 E9 6B
|
|
||||||
Page 14: 77 41 88 81
|
|
||||||
Page 15: 86 31 CB AD
|
|
||||||
Page 16: B1 DE F1 AB
|
|
||||||
Page 17: DF 96 C2 C5
|
|
||||||
Page 18: C1 26 99 96
|
|
||||||
Page 19: 85 AF 9F 0E
|
|
||||||
Page 20: 58 FE ED DC
|
|
||||||
Page 21: 0A 0A 00 01
|
|
||||||
Page 22: 03 C1 05 02
|
|
||||||
Page 23: 38 39 34 33
|
|
||||||
Page 24: 49 2D 4E 5C
|
|
||||||
Page 25: 5B 21 0F 44
|
|
||||||
Page 26: 3F 3F 76 69
|
|
||||||
Page 27: B4 72 D8 38
|
|
||||||
Page 28: A0 35 53 51
|
|
||||||
Page 29: 53 EB A6 7C
|
|
||||||
Page 30: 3E 8B 97 C0
|
|
||||||
Page 31: 00 7A 45 13
|
|
||||||
Page 32: 3A 8B D4 0F
|
|
||||||
Page 33: 31 C2 32 CC
|
|
||||||
Page 34: B4 24 A6 1B
|
|
||||||
Page 35: D3 F5 4A 1F
|
|
||||||
Page 36: CD 8F 1D 64
|
|
||||||
Page 37: 01 F4 DF C2
|
|
||||||
Page 38: 11 16 C2 C5
|
|
||||||
Page 39: 30 6D 49 AF
|
|
||||||
Page 40: 10 D4 7C 3C
|
|
||||||
Page 41: 6E 36 4E 08
|
|
||||||
Page 42: 95 76 BC 84
|
|
||||||
Page 43: 35 50 DD F0
|
|
||||||
Page 44: 21 0F EE D9
|
|
||||||
Page 45: 85 19 54 5F
|
|
||||||
Page 46: 3E A9 04 20
|
|
||||||
Page 47: 1B 97 E4 39
|
|
||||||
Page 48: FF 0A 45 F6
|
|
||||||
Page 49: 13 D4 3E DD
|
|
||||||
Page 50: 97 42 FC 67
|
|
||||||
Page 51: 6A AC 78 96
|
|
||||||
Page 52: D1 DA 25 23
|
|
||||||
Page 53: BF 4D B3 76
|
|
||||||
Page 54: F1 21 ED 15
|
|
||||||
Page 55: BD 55 11 C4
|
|
||||||
Page 56: 4E 8C E9 23
|
|
||||||
Page 57: C0 C4 6D 5A
|
|
||||||
Page 58: 58 25 FF 95
|
|
||||||
Page 59: 3C 2B 7A 57
|
|
||||||
Page 60: 66 BE A0 61
|
|
||||||
Page 61: BC FC 4A 31
|
|
||||||
Page 62: 4D AC EE 81
|
|
||||||
Page 63: BE 1A 86 04
|
|
||||||
Page 64: F6 D7 5E B3
|
|
||||||
Page 65: E7 A8 A2 86
|
|
||||||
Page 66: E9 40 AB 47
|
|
||||||
Page 67: C8 36 E4 3E
|
|
||||||
Page 68: A7 4D D3 EA
|
|
||||||
Page 69: 83 9A 64 F7
|
|
||||||
Page 70: 96 6B 5D BF
|
|
||||||
Page 71: 4E A2 A6 0F
|
|
||||||
Page 72: BD 3D BE 7C
|
|
||||||
Page 73: 22 0C 68 51
|
|
||||||
Page 74: 0F 9A B8 AE
|
|
||||||
Page 75: 38 2C C4 CD
|
|
||||||
Page 76: 53 D8 DD 18
|
|
||||||
Page 77: A6 5D 35 87
|
|
||||||
Page 78: C9 6D 99 59
|
|
||||||
Page 79: 61 9F B6 DC
|
|
||||||
Page 80: E6 22 0F 99
|
|
||||||
Page 81: 39 82 79 60
|
|
||||||
Page 82: 58 2E BE F7
|
|
||||||
Page 83: EF F7 95 62
|
|
||||||
Page 84: D5 06 1B 58
|
|
||||||
Page 85: 65 05 A9 08
|
|
||||||
Page 86: 75 ED 5D 90
|
|
||||||
Page 87: 5A E1 7E C9
|
|
||||||
Page 88: 35 D6 29 BB
|
|
||||||
Page 89: D0 67 6C F9
|
|
||||||
Page 90: A0 FF 0B 93
|
|
||||||
Page 91: 22 EA A3 3F
|
|
||||||
Page 92: E2 BD BD 58
|
|
||||||
Page 93: BE 93 D9 94
|
|
||||||
Page 94: 41 CC 7E 40
|
|
||||||
Page 95: E6 8C 5A 43
|
|
||||||
Page 96: 65 C1 24 94
|
|
||||||
Page 97: B9 97 61 13
|
|
||||||
Page 98: AD 74 FF 21
|
|
||||||
Page 99: 0F EC F6 03
|
|
||||||
Page 100: 89 5D 89 E5
|
|
||||||
Page 101: 8D 11 F8 D7
|
|
||||||
Page 102: 33 43 79 2E
|
|
||||||
Page 103: 23 E5 29 B5
|
|
||||||
Page 104: 53 98 13 FF
|
|
||||||
Page 105: E8 79 8B 33
|
|
||||||
Page 106: 45 6C 34 38
|
|
||||||
Page 107: 3B 69 28 D7
|
|
||||||
Page 108: D2 80 B0 2F
|
|
||||||
Page 109: D0 18 D5 DD
|
|
||||||
Page 110: 6C 2D D9 97
|
|
||||||
Page 111: CA 78 B4 A2
|
|
||||||
Page 112: B7 3E B8 79
|
|
||||||
Page 113: A2 BE 54 E4
|
|
||||||
Page 114: C8 28 0C 4A
|
|
||||||
Page 115: 81 E7 EC 1C
|
|
||||||
Page 116: 39 93 6F 70
|
|
||||||
Page 117: 75 77 5C FC
|
|
||||||
Page 118: 66 58 0C 1C
|
|
||||||
Page 119: 9F 70 2E C8
|
|
||||||
Page 120: 52 4A 52 BD
|
|
||||||
Page 121: 56 D5 6A 15
|
|
||||||
Page 122: 54 1B 33 90
|
|
||||||
Page 123: 44 11 C1 07
|
|
||||||
Page 124: 11 5C BA 80
|
|
||||||
Page 125: 10 14 20 9A
|
|
||||||
Page 126: 4A D8 E6 36
|
|
||||||
Page 127: DA B8 59 E5
|
|
||||||
Page 128: 5E 48 95 DA
|
|
||||||
Page 129: 96 6A 26 85
|
|
||||||
Page 130: 01 00 0F BD
|
|
||||||
Page 131: 00 00 00 04
|
|
||||||
Page 132: 5F 00 00 00
|
|
||||||
Page 133: 00 00 00 00
|
|
||||||
Page 134: 00 00 00 00
|
|
||||||
Failed authentication attempts: 0
|
|
||||||
@@ -1,252 +0,0 @@
|
|||||||
Filetype: Flipper NFC device
|
|
||||||
Version: 2
|
|
||||||
# Nfc device type can be UID, Mifare Ultralight, Mifare Classic, Bank card
|
|
||||||
Device type: NTAG216
|
|
||||||
# UID, ATQA and SAK are common for all formats
|
|
||||||
UID: 04 D9 65 0A 32 5E 80
|
|
||||||
ATQA: 44 00
|
|
||||||
SAK: 00
|
|
||||||
# Mifare Ultralight specific data
|
|
||||||
Data format version: 1
|
|
||||||
Signature: 48 2A F2 01 0F F2 F5 A7 9A D5 79 6E CB 14 54 48 98 D1 57 5D 8A 23 A9 B0 E8 20 02 3E CD C8 16 DB
|
|
||||||
Mifare version: 00 04 04 02 01 00 13 03
|
|
||||||
Counter 0: 0
|
|
||||||
Tearing 0: 00
|
|
||||||
Counter 1: 0
|
|
||||||
Tearing 1: 00
|
|
||||||
Counter 2: 0
|
|
||||||
Tearing 2: 00
|
|
||||||
Pages total: 231
|
|
||||||
Pages read: 231
|
|
||||||
Page 0: 04 D9 65 30
|
|
||||||
Page 1: 0A 32 5E 80
|
|
||||||
Page 2: E6 48 00 00
|
|
||||||
Page 3: E1 10 6D 00
|
|
||||||
Page 4: 03 37 D1 01
|
|
||||||
Page 5: 33 55 04 6D
|
|
||||||
Page 6: 2E 79 6F 75
|
|
||||||
Page 7: 74 75 62 65
|
|
||||||
Page 8: 2E 63 6F 6D
|
|
||||||
Page 9: 2F 77 61 74
|
|
||||||
Page 10: 63 68 3F 76
|
|
||||||
Page 11: 3D 62 78 71
|
|
||||||
Page 12: 4C 73 72 6C
|
|
||||||
Page 13: 61 6B 4B 38
|
|
||||||
Page 14: 26 66 65 61
|
|
||||||
Page 15: 74 75 72 65
|
|
||||||
Page 16: 3D 79 6F 75
|
|
||||||
Page 17: 74 75 2E 62
|
|
||||||
Page 18: 65 FE 00 00
|
|
||||||
Page 19: 00 00 00 00
|
|
||||||
Page 20: 00 00 00 00
|
|
||||||
Page 21: 00 00 00 00
|
|
||||||
Page 22: 00 00 00 00
|
|
||||||
Page 23: 00 00 00 00
|
|
||||||
Page 24: 00 00 00 00
|
|
||||||
Page 25: 00 00 00 00
|
|
||||||
Page 26: 00 00 00 00
|
|
||||||
Page 27: 00 00 00 00
|
|
||||||
Page 28: 00 00 00 00
|
|
||||||
Page 29: 00 00 00 00
|
|
||||||
Page 30: 00 00 00 00
|
|
||||||
Page 31: 00 00 00 00
|
|
||||||
Page 32: 00 00 00 00
|
|
||||||
Page 33: 00 00 00 00
|
|
||||||
Page 34: 00 00 00 00
|
|
||||||
Page 35: 00 00 00 00
|
|
||||||
Page 36: 00 00 00 00
|
|
||||||
Page 37: 00 00 00 00
|
|
||||||
Page 38: 00 00 00 00
|
|
||||||
Page 39: 00 00 00 00
|
|
||||||
Page 40: 00 00 00 00
|
|
||||||
Page 41: 00 00 00 00
|
|
||||||
Page 42: 00 00 00 00
|
|
||||||
Page 43: 00 00 00 00
|
|
||||||
Page 44: 00 00 00 00
|
|
||||||
Page 45: 00 00 00 00
|
|
||||||
Page 46: 00 00 00 00
|
|
||||||
Page 47: 00 00 00 00
|
|
||||||
Page 48: 00 00 00 00
|
|
||||||
Page 49: 00 00 00 00
|
|
||||||
Page 50: 00 00 00 00
|
|
||||||
Page 51: 00 00 00 00
|
|
||||||
Page 52: 00 00 00 00
|
|
||||||
Page 53: 00 00 00 00
|
|
||||||
Page 54: 00 00 00 00
|
|
||||||
Page 55: 00 00 00 00
|
|
||||||
Page 56: 00 00 00 00
|
|
||||||
Page 57: 00 00 00 00
|
|
||||||
Page 58: 00 00 00 00
|
|
||||||
Page 59: 00 00 00 00
|
|
||||||
Page 60: 00 00 00 00
|
|
||||||
Page 61: 00 00 00 00
|
|
||||||
Page 62: 00 00 00 00
|
|
||||||
Page 63: 00 00 00 00
|
|
||||||
Page 64: 00 00 00 00
|
|
||||||
Page 65: 00 00 00 00
|
|
||||||
Page 66: 00 00 00 00
|
|
||||||
Page 67: 00 00 00 00
|
|
||||||
Page 68: 00 00 00 00
|
|
||||||
Page 69: 00 00 00 00
|
|
||||||
Page 70: 00 00 00 00
|
|
||||||
Page 71: 00 00 00 00
|
|
||||||
Page 72: 00 00 00 00
|
|
||||||
Page 73: 00 00 00 00
|
|
||||||
Page 74: 00 00 00 00
|
|
||||||
Page 75: 00 00 00 00
|
|
||||||
Page 76: 00 00 00 00
|
|
||||||
Page 77: 00 00 00 00
|
|
||||||
Page 78: 00 00 00 00
|
|
||||||
Page 79: 00 00 00 00
|
|
||||||
Page 80: 00 00 00 00
|
|
||||||
Page 81: 00 00 00 00
|
|
||||||
Page 82: 00 00 00 00
|
|
||||||
Page 83: 00 00 00 00
|
|
||||||
Page 84: 00 00 00 00
|
|
||||||
Page 85: 00 00 00 00
|
|
||||||
Page 86: 00 00 00 00
|
|
||||||
Page 87: 00 00 00 00
|
|
||||||
Page 88: 00 00 00 00
|
|
||||||
Page 89: 00 00 00 00
|
|
||||||
Page 90: 00 00 00 00
|
|
||||||
Page 91: 00 00 00 00
|
|
||||||
Page 92: 00 00 00 00
|
|
||||||
Page 93: 00 00 00 00
|
|
||||||
Page 94: 00 00 00 00
|
|
||||||
Page 95: 00 00 00 00
|
|
||||||
Page 96: 00 00 00 00
|
|
||||||
Page 97: 00 00 00 00
|
|
||||||
Page 98: 00 00 00 00
|
|
||||||
Page 99: 00 00 00 00
|
|
||||||
Page 100: 00 00 00 00
|
|
||||||
Page 101: 00 00 00 00
|
|
||||||
Page 102: 00 00 00 00
|
|
||||||
Page 103: 00 00 00 00
|
|
||||||
Page 104: 00 00 00 00
|
|
||||||
Page 105: 00 00 00 00
|
|
||||||
Page 106: 00 00 00 00
|
|
||||||
Page 107: 00 00 00 00
|
|
||||||
Page 108: 00 00 00 00
|
|
||||||
Page 109: 00 00 00 00
|
|
||||||
Page 110: 00 00 00 00
|
|
||||||
Page 111: 00 00 00 00
|
|
||||||
Page 112: 00 00 00 00
|
|
||||||
Page 113: 00 00 00 00
|
|
||||||
Page 114: 00 00 00 00
|
|
||||||
Page 115: 00 00 00 00
|
|
||||||
Page 116: 00 00 00 00
|
|
||||||
Page 117: 00 00 00 00
|
|
||||||
Page 118: 00 00 00 00
|
|
||||||
Page 119: 00 00 00 00
|
|
||||||
Page 120: 00 00 00 00
|
|
||||||
Page 121: 00 00 00 00
|
|
||||||
Page 122: 00 00 00 00
|
|
||||||
Page 123: 00 00 00 00
|
|
||||||
Page 124: 00 00 00 00
|
|
||||||
Page 125: 00 00 00 00
|
|
||||||
Page 126: 00 00 00 00
|
|
||||||
Page 127: 00 00 00 00
|
|
||||||
Page 128: 00 00 00 00
|
|
||||||
Page 129: 00 00 00 00
|
|
||||||
Page 130: 00 00 00 00
|
|
||||||
Page 131: 00 00 00 00
|
|
||||||
Page 132: 00 00 00 00
|
|
||||||
Page 133: 00 00 00 00
|
|
||||||
Page 134: 00 00 00 00
|
|
||||||
Page 135: 00 00 00 00
|
|
||||||
Page 136: 00 00 00 00
|
|
||||||
Page 137: 00 00 00 00
|
|
||||||
Page 138: 00 00 00 00
|
|
||||||
Page 139: 00 00 00 00
|
|
||||||
Page 140: 00 00 00 00
|
|
||||||
Page 141: 00 00 00 00
|
|
||||||
Page 142: 00 00 00 00
|
|
||||||
Page 143: 00 00 00 00
|
|
||||||
Page 144: 00 00 00 00
|
|
||||||
Page 145: 00 00 00 00
|
|
||||||
Page 146: 00 00 00 00
|
|
||||||
Page 147: 00 00 00 00
|
|
||||||
Page 148: 00 00 00 00
|
|
||||||
Page 149: 00 00 00 00
|
|
||||||
Page 150: 00 00 00 00
|
|
||||||
Page 151: 00 00 00 00
|
|
||||||
Page 152: 00 00 00 00
|
|
||||||
Page 153: 00 00 00 00
|
|
||||||
Page 154: 00 00 00 00
|
|
||||||
Page 155: 00 00 00 00
|
|
||||||
Page 156: 00 00 00 00
|
|
||||||
Page 157: 00 00 00 00
|
|
||||||
Page 158: 00 00 00 00
|
|
||||||
Page 159: 00 00 00 00
|
|
||||||
Page 160: 00 00 00 00
|
|
||||||
Page 161: 00 00 00 00
|
|
||||||
Page 162: 00 00 00 00
|
|
||||||
Page 163: 00 00 00 00
|
|
||||||
Page 164: 00 00 00 00
|
|
||||||
Page 165: 00 00 00 00
|
|
||||||
Page 166: 00 00 00 00
|
|
||||||
Page 167: 00 00 00 00
|
|
||||||
Page 168: 00 00 00 00
|
|
||||||
Page 169: 00 00 00 00
|
|
||||||
Page 170: 00 00 00 00
|
|
||||||
Page 171: 00 00 00 00
|
|
||||||
Page 172: 00 00 00 00
|
|
||||||
Page 173: 00 00 00 00
|
|
||||||
Page 174: 00 00 00 00
|
|
||||||
Page 175: 00 00 00 00
|
|
||||||
Page 176: 00 00 00 00
|
|
||||||
Page 177: 00 00 00 00
|
|
||||||
Page 178: 00 00 00 00
|
|
||||||
Page 179: 00 00 00 00
|
|
||||||
Page 180: 00 00 00 00
|
|
||||||
Page 181: 00 00 00 00
|
|
||||||
Page 182: 00 00 00 00
|
|
||||||
Page 183: 00 00 00 00
|
|
||||||
Page 184: 00 00 00 00
|
|
||||||
Page 185: 00 00 00 00
|
|
||||||
Page 186: 00 00 00 00
|
|
||||||
Page 187: 00 00 00 00
|
|
||||||
Page 188: 00 00 00 00
|
|
||||||
Page 189: 00 00 00 00
|
|
||||||
Page 190: 00 00 00 00
|
|
||||||
Page 191: 00 00 00 00
|
|
||||||
Page 192: 00 00 00 00
|
|
||||||
Page 193: 00 00 00 00
|
|
||||||
Page 194: 00 00 00 00
|
|
||||||
Page 195: 00 00 00 00
|
|
||||||
Page 196: 00 00 00 00
|
|
||||||
Page 197: 00 00 00 00
|
|
||||||
Page 198: 00 00 00 00
|
|
||||||
Page 199: 00 00 00 00
|
|
||||||
Page 200: 00 00 00 00
|
|
||||||
Page 201: 00 00 00 00
|
|
||||||
Page 202: 00 00 00 00
|
|
||||||
Page 203: 00 00 00 00
|
|
||||||
Page 204: 00 00 00 00
|
|
||||||
Page 205: 00 00 00 00
|
|
||||||
Page 206: 00 00 00 00
|
|
||||||
Page 207: 00 00 00 00
|
|
||||||
Page 208: 00 00 00 00
|
|
||||||
Page 209: 00 00 00 00
|
|
||||||
Page 210: 00 00 00 00
|
|
||||||
Page 211: 00 00 00 00
|
|
||||||
Page 212: 00 00 00 00
|
|
||||||
Page 213: 00 00 00 00
|
|
||||||
Page 214: 00 00 00 00
|
|
||||||
Page 215: 00 00 00 00
|
|
||||||
Page 216: 00 00 00 00
|
|
||||||
Page 217: 00 00 00 00
|
|
||||||
Page 218: 00 00 00 00
|
|
||||||
Page 219: 00 00 00 00
|
|
||||||
Page 220: 00 00 00 00
|
|
||||||
Page 221: 00 00 00 00
|
|
||||||
Page 222: 00 00 00 00
|
|
||||||
Page 223: 00 00 00 00
|
|
||||||
Page 224: 00 00 00 00
|
|
||||||
Page 225: 00 00 00 00
|
|
||||||
Page 226: 00 00 00 BD
|
|
||||||
Page 227: 04 00 00 FF
|
|
||||||
Page 228: 00 05 00 00
|
|
||||||
Page 229: 00 00 00 00
|
|
||||||
Page 230: 00 00 00 00
|
|
||||||
Failed authentication attempts: 0
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
Filetype: Flipper NFC device
|
|
||||||
Version: 3
|
|
||||||
# Nfc device type can be UID, Mifare Ultralight, Mifare Classic
|
|
||||||
Device type: Mifare Ultralight 11
|
|
||||||
# UID, ATQA and SAK are common for all formats
|
|
||||||
UID: 04 15 74 F2 B0 5E 81
|
|
||||||
ATQA: 00 44
|
|
||||||
SAK: 00
|
|
||||||
# Mifare Ultralight specific data
|
|
||||||
Data format version: 1
|
|
||||||
Signature: A4 37 7D E5 8C 2F 88 D8 04 60 41 6E 3A C8 CD DB 19 94 26 12 C5 D0 12 B0 EB 88 05 72 89 F2 A5 61
|
|
||||||
Mifare version: 00 04 03 01 01 00 0B 03
|
|
||||||
Counter 0: 0
|
|
||||||
Tearing 0: BD
|
|
||||||
Counter 1: 0
|
|
||||||
Tearing 1: BD
|
|
||||||
Counter 2: 0
|
|
||||||
Tearing 2: BD
|
|
||||||
Pages total: 20
|
|
||||||
Pages read: 20
|
|
||||||
Page 0: 04 15 74 ED
|
|
||||||
Page 1: F2 B0 5E 81
|
|
||||||
Page 2: 9D 48 F8 FF
|
|
||||||
Page 3: C1 31 3E 3F
|
|
||||||
Page 4: B0 00 F0 02
|
|
||||||
Page 5: 2F B3 45 A0
|
|
||||||
Page 6: D4 9C 02 F2
|
|
||||||
Page 7: 4A B1 ED FF
|
|
||||||
Page 8: C8 01 00 02
|
|
||||||
Page 9: 4F B3 46 70
|
|
||||||
Page 10: EE F6 60 B0
|
|
||||||
Page 11: B6 C6 12 1B
|
|
||||||
Page 12: B9 1E 49 C3
|
|
||||||
Page 13: 49 DF 7A 57
|
|
||||||
Page 14: 08 52 2A 11
|
|
||||||
Page 15: 28 0A 28 59
|
|
||||||
Page 16: 00 00 00 FF
|
|
||||||
Page 17: 00 05 00 00
|
|
||||||
Page 18: FF FF FF FF
|
|
||||||
Page 19: 00 00 00 00
|
|
||||||
Failed authentication attempts: 0
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
Filetype: Flipper NFC device
|
|
||||||
Version: 3
|
|
||||||
# Nfc device type can be UID, Mifare Ultralight, Mifare Classic
|
|
||||||
Device type: Mifare Ultralight 21
|
|
||||||
# UID, ATQA and SAK are common for all formats
|
|
||||||
UID: 34 BF AB B1 AE 73 D6
|
|
||||||
ATQA: 00 44
|
|
||||||
SAK: 00
|
|
||||||
# Mifare Ultralight specific data
|
|
||||||
Data format version: 1
|
|
||||||
Signature: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
Mifare version: 00 34 21 01 01 00 0E 03
|
|
||||||
Counter 0: 0
|
|
||||||
Tearing 0: 00
|
|
||||||
Counter 1: 0
|
|
||||||
Tearing 1: 00
|
|
||||||
Counter 2: 0
|
|
||||||
Tearing 2: 00
|
|
||||||
Pages total: 41
|
|
||||||
Pages read: 41
|
|
||||||
Page 0: 34 BF AB A8
|
|
||||||
Page 1: B1 AE 73 D6
|
|
||||||
Page 2: BA 00 70 08
|
|
||||||
Page 3: FF FF FF FC
|
|
||||||
Page 4: 45 D9 BB A0
|
|
||||||
Page 5: 5D 9D FA 00
|
|
||||||
Page 6: 80 70 38 40
|
|
||||||
Page 7: 12 30 02 00
|
|
||||||
Page 8: 00 00 00 00
|
|
||||||
Page 9: 00 00 00 00
|
|
||||||
Page 10: AC A1 0D E4
|
|
||||||
Page 11: 80 70 38 40
|
|
||||||
Page 12: 00 57 A0 01
|
|
||||||
Page 13: 00 08 C1 40
|
|
||||||
Page 14: 00 00 00 00
|
|
||||||
Page 15: AC A1 0D E4
|
|
||||||
Page 16: 00 00 00 00
|
|
||||||
Page 17: 00 00 00 00
|
|
||||||
Page 18: 00 00 00 00
|
|
||||||
Page 19: 00 00 00 00
|
|
||||||
Page 20: 00 00 00 00
|
|
||||||
Page 21: 00 00 00 00
|
|
||||||
Page 22: 00 00 00 00
|
|
||||||
Page 23: 00 00 00 00
|
|
||||||
Page 24: 00 00 00 00
|
|
||||||
Page 25: 00 00 00 00
|
|
||||||
Page 26: 00 00 00 00
|
|
||||||
Page 27: 00 00 00 00
|
|
||||||
Page 28: 00 00 00 00
|
|
||||||
Page 29: 00 00 00 00
|
|
||||||
Page 30: 00 00 00 00
|
|
||||||
Page 31: 00 00 00 00
|
|
||||||
Page 32: 00 00 00 00
|
|
||||||
Page 33: 00 00 00 00
|
|
||||||
Page 34: 00 00 00 00
|
|
||||||
Page 35: 00 00 00 00
|
|
||||||
Page 36: 00 00 00 BD
|
|
||||||
Page 37: 00 00 00 FF
|
|
||||||
Page 38: 00 05 00 00
|
|
||||||
Page 39: FF FF FF FF
|
|
||||||
Page 40: 00 00 00 00
|
|
||||||
Failed authentication attempts: 0
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
Yo dawg, I heard you like md5...
|
|
||||||
@@ -13,13 +13,11 @@
|
|||||||
#include <pb.h>
|
#include <pb.h>
|
||||||
#include <pb_encode.h>
|
#include <pb_encode.h>
|
||||||
#include <m-list.h>
|
#include <m-list.h>
|
||||||
#include <lib/toolbox/md5_calc.h>
|
#include <lib/toolbox/md5.h>
|
||||||
#include <lib/toolbox/path.h>
|
#include <lib/toolbox/path.h>
|
||||||
#include <cli/cli.h>
|
#include <cli/cli.h>
|
||||||
#include <loader/loader.h>
|
#include <loader/loader.h>
|
||||||
#include <protobuf_version.h>
|
#include <protobuf_version.h>
|
||||||
|
|
||||||
#include <FreeRTOS.h>
|
|
||||||
#include <semphr.h>
|
#include <semphr.h>
|
||||||
|
|
||||||
LIST_DEF(MsgList, PB_Main, M_POD_OPLIST)
|
LIST_DEF(MsgList, PB_Main, M_POD_OPLIST)
|
||||||
@@ -38,7 +36,7 @@ typedef struct {
|
|||||||
FuriStreamBuffer* output_stream;
|
FuriStreamBuffer* output_stream;
|
||||||
SemaphoreHandle_t close_session_semaphore;
|
SemaphoreHandle_t close_session_semaphore;
|
||||||
SemaphoreHandle_t terminate_semaphore;
|
SemaphoreHandle_t terminate_semaphore;
|
||||||
uint32_t timeout;
|
TickType_t timeout;
|
||||||
} RpcSessionContext;
|
} RpcSessionContext;
|
||||||
|
|
||||||
static RpcSessionContext rpc_session[TEST_RPC_SESSIONS];
|
static RpcSessionContext rpc_session[TEST_RPC_SESSIONS];
|
||||||
@@ -69,6 +67,7 @@ static RpcSessionContext rpc_session[TEST_RPC_SESSIONS];
|
|||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
static void output_bytes_callback(void* ctx, uint8_t* got_bytes, size_t got_size);
|
static void output_bytes_callback(void* ctx, uint8_t* got_bytes, size_t got_size);
|
||||||
|
static void clean_directory(Storage* fs_api, const char* clean_dir);
|
||||||
static void
|
static void
|
||||||
test_rpc_add_empty_to_list(MsgList_t msg_list, PB_CommandStatus status, uint32_t command_id);
|
test_rpc_add_empty_to_list(MsgList_t msg_list, PB_CommandStatus status, uint32_t command_id);
|
||||||
static void test_rpc_encode_and_feed(MsgList_t msg_list, uint8_t session);
|
static void test_rpc_encode_and_feed(MsgList_t msg_list, uint8_t session);
|
||||||
@@ -150,41 +149,11 @@ static void test_rpc_teardown_second_session(void) {
|
|||||||
rpc_session[1].session = NULL;
|
rpc_session[1].session = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_rpc_storage_clean_directory(Storage* fs_api, const char* clean_dir) {
|
|
||||||
furi_check(fs_api);
|
|
||||||
furi_check(clean_dir);
|
|
||||||
storage_simply_remove_recursive(fs_api, clean_dir);
|
|
||||||
FS_Error error = storage_common_mkdir(fs_api, clean_dir);
|
|
||||||
furi_check(error == FSE_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_rpc_storage_create_file(Storage* fs_api, const char* path, size_t size) {
|
|
||||||
File* file = storage_file_alloc(fs_api);
|
|
||||||
|
|
||||||
bool success = false;
|
|
||||||
do {
|
|
||||||
if(!storage_file_open(file, path, FSAM_WRITE, FSOM_CREATE_ALWAYS)) break;
|
|
||||||
if(!storage_file_seek(file, size, true)) break;
|
|
||||||
success = true;
|
|
||||||
} while(false);
|
|
||||||
|
|
||||||
storage_file_close(file);
|
|
||||||
storage_file_free(file);
|
|
||||||
|
|
||||||
furi_check(success);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_rpc_storage_setup(void) {
|
static void test_rpc_storage_setup(void) {
|
||||||
test_rpc_setup();
|
test_rpc_setup();
|
||||||
|
|
||||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||||
test_rpc_storage_clean_directory(fs_api, TEST_DIR_NAME);
|
clean_directory(fs_api, TEST_DIR_NAME);
|
||||||
test_rpc_storage_create_file(fs_api, TEST_DIR_NAME "/file100", 100);
|
|
||||||
test_rpc_storage_create_file(fs_api, TEST_DIR_NAME "/file250", 250);
|
|
||||||
test_rpc_storage_create_file(fs_api, TEST_DIR_NAME "/file500", 200);
|
|
||||||
test_rpc_storage_create_file(fs_api, TEST_DIR_NAME "/file1000", 1000);
|
|
||||||
test_rpc_storage_create_file(fs_api, TEST_DIR_NAME "/file2500", 2500);
|
|
||||||
test_rpc_storage_create_file(fs_api, TEST_DIR_NAME "/file5000", 5000);
|
|
||||||
furi_record_close(RECORD_STORAGE);
|
furi_record_close(RECORD_STORAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,7 +161,7 @@ static void test_rpc_storage_teardown(void) {
|
|||||||
test_rpc_teardown();
|
test_rpc_teardown();
|
||||||
|
|
||||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||||
test_rpc_storage_clean_directory(fs_api, TEST_DIR_NAME);
|
clean_directory(fs_api, TEST_DIR_NAME);
|
||||||
furi_record_close(RECORD_STORAGE);
|
furi_record_close(RECORD_STORAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,6 +179,36 @@ static void test_rpc_session_terminated_callback(void* context) {
|
|||||||
xSemaphoreGive(callbacks_context->terminate_semaphore);
|
xSemaphoreGive(callbacks_context->terminate_semaphore);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void clean_directory(Storage* fs_api, const char* clean_dir) {
|
||||||
|
furi_check(fs_api);
|
||||||
|
furi_check(clean_dir);
|
||||||
|
|
||||||
|
File* dir = storage_file_alloc(fs_api);
|
||||||
|
if(storage_dir_open(dir, clean_dir)) {
|
||||||
|
FileInfo fileinfo;
|
||||||
|
char* name = malloc(MAX_NAME_LENGTH + 1);
|
||||||
|
while(storage_dir_read(dir, &fileinfo, name, MAX_NAME_LENGTH)) {
|
||||||
|
size_t size = strlen(clean_dir) + strlen(name) + 1 + 1;
|
||||||
|
char* fullname = malloc(size);
|
||||||
|
snprintf(fullname, size, "%s/%s", clean_dir, name);
|
||||||
|
if(file_info_is_dir(&fileinfo)) {
|
||||||
|
clean_directory(fs_api, fullname);
|
||||||
|
}
|
||||||
|
FS_Error error = storage_common_remove(fs_api, fullname);
|
||||||
|
furi_check(error == FSE_OK);
|
||||||
|
free(fullname);
|
||||||
|
}
|
||||||
|
free(name);
|
||||||
|
} else {
|
||||||
|
FS_Error error = storage_common_mkdir(fs_api, clean_dir);
|
||||||
|
(void)error;
|
||||||
|
furi_check(error == FSE_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
storage_dir_close(dir);
|
||||||
|
storage_file_free(dir);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_rpc_print_message_list(MsgList_t msg_list) {
|
static void test_rpc_print_message_list(MsgList_t msg_list) {
|
||||||
#if DEBUG_PRINT
|
#if DEBUG_PRINT
|
||||||
MsgList_reverse(msg_list);
|
MsgList_reverse(msg_list);
|
||||||
@@ -283,27 +282,6 @@ static void test_rpc_add_ping_to_list(MsgList_t msg_list, bool request, uint32_t
|
|||||||
response->which_content = (request == PING_REQUEST) ? PB_Main_system_ping_request_tag :
|
response->which_content = (request == PING_REQUEST) ? PB_Main_system_ping_request_tag :
|
||||||
PB_Main_system_ping_response_tag;
|
PB_Main_system_ping_response_tag;
|
||||||
}
|
}
|
||||||
static void test_rpc_fill_basic_message(PB_Main* message, uint16_t tag, uint32_t command_id) {
|
|
||||||
message->command_id = command_id;
|
|
||||||
message->command_status = PB_CommandStatus_OK;
|
|
||||||
message->cb_content.funcs.encode = NULL;
|
|
||||||
message->which_content = tag;
|
|
||||||
message->has_next = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_rpc_create_storage_list_request(
|
|
||||||
PB_Main* message,
|
|
||||||
const char* path,
|
|
||||||
bool include_md5,
|
|
||||||
uint32_t command_id,
|
|
||||||
uint32_t filter_max_size) {
|
|
||||||
furi_check(message);
|
|
||||||
furi_check(path);
|
|
||||||
test_rpc_fill_basic_message(message, PB_Main_storage_list_request_tag, command_id);
|
|
||||||
message->content.storage_list_request.path = strdup(path);
|
|
||||||
message->content.storage_list_request.include_md5 = include_md5;
|
|
||||||
message->content.storage_list_request.filter_max_size = filter_max_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_rpc_create_simple_message(
|
static void test_rpc_create_simple_message(
|
||||||
PB_Main* message,
|
PB_Main* message,
|
||||||
@@ -316,7 +294,11 @@ static void test_rpc_create_simple_message(
|
|||||||
if(str) {
|
if(str) {
|
||||||
str_copy = strdup(str);
|
str_copy = strdup(str);
|
||||||
}
|
}
|
||||||
test_rpc_fill_basic_message(message, tag, command_id);
|
message->command_id = command_id;
|
||||||
|
message->command_status = PB_CommandStatus_OK;
|
||||||
|
message->cb_content.funcs.encode = NULL;
|
||||||
|
message->which_content = tag;
|
||||||
|
message->has_next = false;
|
||||||
switch(tag) {
|
switch(tag) {
|
||||||
case PB_Main_storage_info_request_tag:
|
case PB_Main_storage_info_request_tag:
|
||||||
message->content.storage_info_request.path = str_copy;
|
message->content.storage_info_request.path = str_copy;
|
||||||
@@ -324,6 +306,9 @@ static void test_rpc_create_simple_message(
|
|||||||
case PB_Main_storage_stat_request_tag:
|
case PB_Main_storage_stat_request_tag:
|
||||||
message->content.storage_stat_request.path = str_copy;
|
message->content.storage_stat_request.path = str_copy;
|
||||||
break;
|
break;
|
||||||
|
case PB_Main_storage_list_request_tag:
|
||||||
|
message->content.storage_list_request.path = str_copy;
|
||||||
|
break;
|
||||||
case PB_Main_storage_mkdir_request_tag:
|
case PB_Main_storage_mkdir_request_tag:
|
||||||
message->content.storage_mkdir_request.path = str_copy;
|
message->content.storage_mkdir_request.path = str_copy;
|
||||||
break;
|
break;
|
||||||
@@ -434,7 +419,6 @@ static void
|
|||||||
}
|
}
|
||||||
mu_check(result_msg_file->size == expected_msg_file->size);
|
mu_check(result_msg_file->size == expected_msg_file->size);
|
||||||
mu_check(result_msg_file->type == expected_msg_file->type);
|
mu_check(result_msg_file->type == expected_msg_file->type);
|
||||||
mu_assert_string_eq(expected_msg_file->md5sum, result_msg_file->md5sum);
|
|
||||||
|
|
||||||
if(result_msg_file->data && result_msg_file->type != PB_Storage_File_FileType_DIR) {
|
if(result_msg_file->data && result_msg_file->type != PB_Storage_File_FileType_DIR) {
|
||||||
mu_check(!result_msg_file->data == !expected_msg_file->data); // Zlo: WTF???
|
mu_check(!result_msg_file->data == !expected_msg_file->data); // Zlo: WTF???
|
||||||
@@ -446,10 +430,10 @@ static void
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void test_rpc_compare_messages(PB_Main* result, PB_Main* expected) {
|
static void test_rpc_compare_messages(PB_Main* result, PB_Main* expected) {
|
||||||
mu_assert_int_eq(expected->command_id, result->command_id);
|
mu_check(result->command_id == expected->command_id);
|
||||||
mu_assert_int_eq(expected->command_status, result->command_status);
|
mu_check(result->command_status == expected->command_status);
|
||||||
mu_assert_int_eq(expected->has_next, result->has_next);
|
mu_check(result->has_next == expected->has_next);
|
||||||
mu_assert_int_eq(expected->which_content, result->which_content);
|
mu_check(result->which_content == expected->which_content);
|
||||||
if(result->command_status != PB_CommandStatus_OK) {
|
if(result->command_status != PB_CommandStatus_OK) {
|
||||||
mu_check(result->which_content == PB_Main_empty_tag);
|
mu_check(result->which_content == PB_Main_empty_tag);
|
||||||
}
|
}
|
||||||
@@ -546,7 +530,7 @@ static bool test_rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_
|
|||||||
RpcSessionContext* session_context = istream->state;
|
RpcSessionContext* session_context = istream->state;
|
||||||
size_t bytes_received = 0;
|
size_t bytes_received = 0;
|
||||||
|
|
||||||
uint32_t now = furi_get_tick();
|
TickType_t now = xTaskGetTickCount();
|
||||||
int32_t time_left = session_context->timeout - now;
|
int32_t time_left = session_context->timeout - now;
|
||||||
time_left = MAX(time_left, 0);
|
time_left = MAX(time_left, 0);
|
||||||
bytes_received =
|
bytes_received =
|
||||||
@@ -586,36 +570,13 @@ static void
|
|||||||
message->content.storage_list_response.file[2].name = str;
|
message->content.storage_list_response.file[2].name = str;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool test_rpc_system_storage_list_filter(
|
|
||||||
const FileInfo* fileinfo,
|
|
||||||
const char* name,
|
|
||||||
size_t filter_max_size) {
|
|
||||||
bool result = false;
|
|
||||||
|
|
||||||
do {
|
|
||||||
if(!path_contains_only_ascii(name)) break;
|
|
||||||
if(filter_max_size) {
|
|
||||||
if(fileinfo->size > filter_max_size) break;
|
|
||||||
}
|
|
||||||
result = true;
|
|
||||||
} while(false);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_rpc_storage_list_create_expected_list(
|
static void test_rpc_storage_list_create_expected_list(
|
||||||
MsgList_t msg_list,
|
MsgList_t msg_list,
|
||||||
const char* path,
|
const char* path,
|
||||||
uint32_t command_id,
|
uint32_t command_id) {
|
||||||
bool append_md5,
|
|
||||||
size_t filter_max_size) {
|
|
||||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||||
File* dir = storage_file_alloc(fs_api);
|
File* dir = storage_file_alloc(fs_api);
|
||||||
|
|
||||||
FuriString* md5 = furi_string_alloc();
|
|
||||||
FuriString* md5_path = furi_string_alloc();
|
|
||||||
File* file = storage_file_alloc(fs_api);
|
|
||||||
|
|
||||||
PB_Main response = {
|
PB_Main response = {
|
||||||
.command_id = command_id,
|
.command_id = command_id,
|
||||||
.has_next = false,
|
.has_next = false,
|
||||||
@@ -646,24 +607,13 @@ static void test_rpc_storage_list_create_expected_list(
|
|||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(test_rpc_system_storage_list_filter(&fileinfo, name, filter_max_size)) {
|
if(path_contains_only_ascii(name)) {
|
||||||
list->file[i].type = file_info_is_dir(&fileinfo) ? PB_Storage_File_FileType_DIR :
|
list->file[i].type = file_info_is_dir(&fileinfo) ? PB_Storage_File_FileType_DIR :
|
||||||
PB_Storage_File_FileType_FILE;
|
PB_Storage_File_FileType_FILE;
|
||||||
list->file[i].size = fileinfo.size;
|
list->file[i].size = fileinfo.size;
|
||||||
list->file[i].data = NULL;
|
list->file[i].data = NULL;
|
||||||
/* memory free inside rpc_encode_and_send() -> pb_release() */
|
/* memory free inside rpc_encode_and_send() -> pb_release() */
|
||||||
list->file[i].name = name;
|
list->file[i].name = name;
|
||||||
|
|
||||||
if(append_md5 && !file_info_is_dir(&fileinfo)) {
|
|
||||||
furi_string_printf(md5_path, "%s/%s", path, name);
|
|
||||||
|
|
||||||
if(md5_string_calc_file(file, furi_string_get_cstr(md5_path), md5, NULL)) {
|
|
||||||
char* md5sum = list->file[i].md5sum;
|
|
||||||
size_t md5sum_size = sizeof(list->file[i].md5sum);
|
|
||||||
snprintf(md5sum, md5sum_size, "%s", furi_string_get_cstr(md5));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -676,10 +626,6 @@ static void test_rpc_storage_list_create_expected_list(
|
|||||||
response.has_next = false;
|
response.has_next = false;
|
||||||
MsgList_push_back(msg_list, response);
|
MsgList_push_back(msg_list, response);
|
||||||
|
|
||||||
furi_string_free(md5);
|
|
||||||
furi_string_free(md5_path);
|
|
||||||
storage_file_free(file);
|
|
||||||
|
|
||||||
storage_dir_close(dir);
|
storage_dir_close(dir);
|
||||||
storage_file_free(dir);
|
storage_file_free(dir);
|
||||||
|
|
||||||
@@ -690,7 +636,7 @@ static void test_rpc_decode_and_compare(MsgList_t expected_msg_list, uint8_t ses
|
|||||||
furi_check(!MsgList_empty_p(expected_msg_list));
|
furi_check(!MsgList_empty_p(expected_msg_list));
|
||||||
furi_check(session < TEST_RPC_SESSIONS);
|
furi_check(session < TEST_RPC_SESSIONS);
|
||||||
|
|
||||||
rpc_session[session].timeout = furi_get_tick() + MAX_RECEIVE_OUTPUT_TIMEOUT;
|
rpc_session[session].timeout = xTaskGetTickCount() + MAX_RECEIVE_OUTPUT_TIMEOUT;
|
||||||
pb_istream_t istream = {
|
pb_istream_t istream = {
|
||||||
.callback = test_rpc_pb_stream_read,
|
.callback = test_rpc_pb_stream_read,
|
||||||
.state = &rpc_session[session],
|
.state = &rpc_session[session],
|
||||||
@@ -714,7 +660,7 @@ static void test_rpc_decode_and_compare(MsgList_t expected_msg_list, uint8_t ses
|
|||||||
pb_release(&PB_Main_msg, &result);
|
pb_release(&PB_Main_msg, &result);
|
||||||
}
|
}
|
||||||
|
|
||||||
rpc_session[session].timeout = furi_get_tick() + 50;
|
rpc_session[session].timeout = xTaskGetTickCount() + 50;
|
||||||
if(pb_decode_ex(&istream, &PB_Main_msg, &result, PB_DECODE_DELIMITED)) {
|
if(pb_decode_ex(&istream, &PB_Main_msg, &result, PB_DECODE_DELIMITED)) {
|
||||||
mu_fail("decoded more than expected");
|
mu_fail("decoded more than expected");
|
||||||
}
|
}
|
||||||
@@ -729,21 +675,16 @@ static void test_rpc_free_msg_list(MsgList_t msg_list) {
|
|||||||
MsgList_clear(msg_list);
|
MsgList_clear(msg_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_rpc_storage_list_run(
|
static void test_rpc_storage_list_run(const char* path, uint32_t command_id) {
|
||||||
const char* path,
|
|
||||||
uint32_t command_id,
|
|
||||||
bool md5,
|
|
||||||
size_t filter_max_size) {
|
|
||||||
PB_Main request;
|
PB_Main request;
|
||||||
MsgList_t expected_msg_list;
|
MsgList_t expected_msg_list;
|
||||||
MsgList_init(expected_msg_list);
|
MsgList_init(expected_msg_list);
|
||||||
|
|
||||||
test_rpc_create_storage_list_request(&request, path, md5, command_id, filter_max_size);
|
test_rpc_create_simple_message(&request, PB_Main_storage_list_request_tag, path, command_id);
|
||||||
if(!strcmp(path, "/")) {
|
if(!strcmp(path, "/")) {
|
||||||
test_rpc_storage_list_create_expected_list_root(expected_msg_list, command_id);
|
test_rpc_storage_list_create_expected_list_root(expected_msg_list, command_id);
|
||||||
} else {
|
} else {
|
||||||
test_rpc_storage_list_create_expected_list(
|
test_rpc_storage_list_create_expected_list(expected_msg_list, path, command_id);
|
||||||
expected_msg_list, path, command_id, md5, filter_max_size);
|
|
||||||
}
|
}
|
||||||
test_rpc_encode_and_feed_one(&request, 0);
|
test_rpc_encode_and_feed_one(&request, 0);
|
||||||
test_rpc_decode_and_compare(expected_msg_list, 0);
|
test_rpc_decode_and_compare(expected_msg_list, 0);
|
||||||
@@ -753,32 +694,15 @@ static void test_rpc_storage_list_run(
|
|||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST(test_storage_list) {
|
MU_TEST(test_storage_list) {
|
||||||
test_rpc_storage_list_run("/", ++command_id, false, 0);
|
test_rpc_storage_list_run("/", ++command_id);
|
||||||
test_rpc_storage_list_run(EXT_PATH("nfc"), ++command_id, false, 0);
|
test_rpc_storage_list_run(EXT_PATH("nfc"), ++command_id);
|
||||||
test_rpc_storage_list_run(STORAGE_INT_PATH_PREFIX, ++command_id, false, 0);
|
|
||||||
test_rpc_storage_list_run(STORAGE_EXT_PATH_PREFIX, ++command_id, false, 0);
|
|
||||||
test_rpc_storage_list_run(EXT_PATH("infrared"), ++command_id, false, 0);
|
|
||||||
test_rpc_storage_list_run(EXT_PATH("ibutton"), ++command_id, false, 0);
|
|
||||||
test_rpc_storage_list_run(EXT_PATH("lfrfid"), ++command_id, false, 0);
|
|
||||||
test_rpc_storage_list_run("error_path", ++command_id, false, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
MU_TEST(test_storage_list_md5) {
|
test_rpc_storage_list_run(STORAGE_INT_PATH_PREFIX, ++command_id);
|
||||||
test_rpc_storage_list_run("/", ++command_id, true, 0);
|
test_rpc_storage_list_run(STORAGE_EXT_PATH_PREFIX, ++command_id);
|
||||||
test_rpc_storage_list_run(EXT_PATH("nfc"), ++command_id, true, 0);
|
test_rpc_storage_list_run(EXT_PATH("infrared"), ++command_id);
|
||||||
test_rpc_storage_list_run(STORAGE_INT_PATH_PREFIX, ++command_id, true, 0);
|
test_rpc_storage_list_run(EXT_PATH("ibutton"), ++command_id);
|
||||||
test_rpc_storage_list_run(STORAGE_EXT_PATH_PREFIX, ++command_id, true, 0);
|
test_rpc_storage_list_run(EXT_PATH("lfrfid"), ++command_id);
|
||||||
test_rpc_storage_list_run(EXT_PATH("infrared"), ++command_id, true, 0);
|
test_rpc_storage_list_run("error_path", ++command_id);
|
||||||
test_rpc_storage_list_run(EXT_PATH("ibutton"), ++command_id, true, 0);
|
|
||||||
test_rpc_storage_list_run(EXT_PATH("lfrfid"), ++command_id, true, 0);
|
|
||||||
test_rpc_storage_list_run("error_path", ++command_id, true, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
MU_TEST(test_storage_list_size) {
|
|
||||||
test_rpc_storage_list_run(TEST_DIR_NAME, ++command_id, false, 0);
|
|
||||||
test_rpc_storage_list_run(TEST_DIR_NAME, ++command_id, false, 1);
|
|
||||||
test_rpc_storage_list_run(TEST_DIR_NAME, ++command_id, false, 1000);
|
|
||||||
test_rpc_storage_list_run(TEST_DIR_NAME, ++command_id, false, 2500);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1305,15 +1229,33 @@ MU_TEST(test_storage_mkdir) {
|
|||||||
static void test_storage_calculate_md5sum(const char* path, char* md5sum, size_t md5sum_size) {
|
static void test_storage_calculate_md5sum(const char* path, char* md5sum, size_t md5sum_size) {
|
||||||
Storage* api = furi_record_open(RECORD_STORAGE);
|
Storage* api = furi_record_open(RECORD_STORAGE);
|
||||||
File* file = storage_file_alloc(api);
|
File* file = storage_file_alloc(api);
|
||||||
FuriString* md5 = furi_string_alloc();
|
|
||||||
|
|
||||||
if(md5_string_calc_file(file, path, md5, NULL)) {
|
if(storage_file_open(file, path, FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||||
snprintf(md5sum, md5sum_size, "%s", furi_string_get_cstr(md5));
|
const uint16_t once_read_size = 512;
|
||||||
|
const uint8_t hash_size = MD5SUM_SIZE;
|
||||||
|
uint8_t* data = malloc(once_read_size);
|
||||||
|
uint8_t* hash = malloc(sizeof(uint8_t) * hash_size);
|
||||||
|
md5_context* md5_ctx = malloc(sizeof(md5_context));
|
||||||
|
|
||||||
|
md5_starts(md5_ctx);
|
||||||
|
while(true) {
|
||||||
|
uint16_t read_size = storage_file_read(file, data, once_read_size);
|
||||||
|
if(read_size == 0) break;
|
||||||
|
md5_update(md5_ctx, data, read_size);
|
||||||
|
}
|
||||||
|
md5_finish(md5_ctx, hash);
|
||||||
|
free(md5_ctx);
|
||||||
|
|
||||||
|
for(uint8_t i = 0; i < hash_size; i++) {
|
||||||
|
md5sum += snprintf(md5sum, md5sum_size, "%02x", hash[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(hash);
|
||||||
|
free(data);
|
||||||
} else {
|
} else {
|
||||||
furi_check(0);
|
furi_check(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
furi_string_free(md5);
|
|
||||||
storage_file_close(file);
|
storage_file_close(file);
|
||||||
storage_file_free(file);
|
storage_file_free(file);
|
||||||
|
|
||||||
@@ -1491,8 +1433,6 @@ MU_TEST_SUITE(test_rpc_storage) {
|
|||||||
MU_RUN_TEST(test_storage_info);
|
MU_RUN_TEST(test_storage_info);
|
||||||
MU_RUN_TEST(test_storage_stat);
|
MU_RUN_TEST(test_storage_stat);
|
||||||
MU_RUN_TEST(test_storage_list);
|
MU_RUN_TEST(test_storage_list);
|
||||||
MU_RUN_TEST(test_storage_list_md5);
|
|
||||||
MU_RUN_TEST(test_storage_list_size);
|
|
||||||
MU_RUN_TEST(test_storage_read);
|
MU_RUN_TEST(test_storage_read);
|
||||||
MU_RUN_TEST(test_storage_write_read);
|
MU_RUN_TEST(test_storage_write_read);
|
||||||
MU_RUN_TEST(test_storage_write);
|
MU_RUN_TEST(test_storage_write);
|
||||||
|
|||||||
@@ -582,49 +582,6 @@ MU_TEST(test_storage_common_migrate) {
|
|||||||
furi_record_close(RECORD_STORAGE);
|
furi_record_close(RECORD_STORAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MD5_HASH_SIZE (16)
|
|
||||||
#include <lib/toolbox/md5_calc.h>
|
|
||||||
|
|
||||||
MU_TEST(test_md5_calc) {
|
|
||||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
|
||||||
File* file = storage_file_alloc(storage);
|
|
||||||
|
|
||||||
const char* path = UNIT_TESTS_PATH("storage/md5.txt");
|
|
||||||
const char* md5_cstr = "2a456fa43e75088fdde41c93159d62a2";
|
|
||||||
const uint8_t md5[MD5_HASH_SIZE] = {
|
|
||||||
0x2a,
|
|
||||||
0x45,
|
|
||||||
0x6f,
|
|
||||||
0xa4,
|
|
||||||
0x3e,
|
|
||||||
0x75,
|
|
||||||
0x08,
|
|
||||||
0x8f,
|
|
||||||
0xdd,
|
|
||||||
0xe4,
|
|
||||||
0x1c,
|
|
||||||
0x93,
|
|
||||||
0x15,
|
|
||||||
0x9d,
|
|
||||||
0x62,
|
|
||||||
0xa2,
|
|
||||||
};
|
|
||||||
|
|
||||||
uint8_t md5_output[MD5_HASH_SIZE];
|
|
||||||
FuriString* md5_output_str = furi_string_alloc();
|
|
||||||
memset(md5_output, 0, MD5_HASH_SIZE);
|
|
||||||
|
|
||||||
mu_check(md5_calc_file(file, path, md5_output, NULL));
|
|
||||||
mu_check(md5_string_calc_file(file, path, md5_output_str, NULL));
|
|
||||||
|
|
||||||
mu_assert_mem_eq(md5, md5_output, MD5_HASH_SIZE);
|
|
||||||
mu_assert_string_eq(md5_cstr, furi_string_get_cstr(md5_output_str));
|
|
||||||
|
|
||||||
storage_file_free(file);
|
|
||||||
furi_string_free(md5_output_str);
|
|
||||||
furi_record_close(RECORD_STORAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
MU_TEST_SUITE(test_data_path) {
|
MU_TEST_SUITE(test_data_path) {
|
||||||
MU_RUN_TEST(test_storage_data_path);
|
MU_RUN_TEST(test_storage_data_path);
|
||||||
MU_RUN_TEST(test_storage_data_path_apps);
|
MU_RUN_TEST(test_storage_data_path_apps);
|
||||||
@@ -634,16 +591,11 @@ MU_TEST_SUITE(test_storage_common) {
|
|||||||
MU_RUN_TEST(test_storage_common_migrate);
|
MU_RUN_TEST(test_storage_common_migrate);
|
||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST_SUITE(test_md5_calc_suite) {
|
|
||||||
MU_RUN_TEST(test_md5_calc);
|
|
||||||
}
|
|
||||||
|
|
||||||
int run_minunit_test_storage() {
|
int run_minunit_test_storage() {
|
||||||
MU_RUN_SUITE(storage_file);
|
MU_RUN_SUITE(storage_file);
|
||||||
MU_RUN_SUITE(storage_dir);
|
MU_RUN_SUITE(storage_dir);
|
||||||
MU_RUN_SUITE(storage_rename);
|
MU_RUN_SUITE(storage_rename);
|
||||||
MU_RUN_SUITE(test_data_path);
|
MU_RUN_SUITE(test_data_path);
|
||||||
MU_RUN_SUITE(test_storage_common);
|
MU_RUN_SUITE(test_storage_common);
|
||||||
MU_RUN_SUITE(test_md5_calc_suite);
|
|
||||||
return MU_EXIT_CODE;
|
return MU_EXIT_CODE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
#include <lib/subghz/devices/devices.h>
|
#include <lib/subghz/devices/devices.h>
|
||||||
#include <lib/subghz/devices/cc1101_configs.h>
|
#include <lib/subghz/devices/cc1101_configs.h>
|
||||||
|
|
||||||
#define TAG "SubGhzTest"
|
#define TAG "SubGhz TEST"
|
||||||
#define KEYSTORE_DIR_NAME EXT_PATH("subghz/assets/keeloq_mfcodes")
|
#define KEYSTORE_DIR_NAME EXT_PATH("subghz/assets/keeloq_mfcodes")
|
||||||
#define CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo")
|
#define CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo")
|
||||||
#define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s")
|
#define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s")
|
||||||
@@ -42,6 +42,8 @@ static void subghz_test_rx_callback(
|
|||||||
|
|
||||||
static void subghz_test_init(void) {
|
static void subghz_test_init(void) {
|
||||||
environment_handler = subghz_environment_alloc();
|
environment_handler = subghz_environment_alloc();
|
||||||
|
subghz_environment_set_came_atomo_rainbow_table_file_name(
|
||||||
|
environment_handler, CAME_ATOMO_DIR_NAME);
|
||||||
subghz_environment_set_nice_flor_s_rainbow_table_file_name(
|
subghz_environment_set_nice_flor_s_rainbow_table_file_name(
|
||||||
environment_handler, NICE_FLOR_S_DIR_NAME);
|
environment_handler, NICE_FLOR_S_DIR_NAME);
|
||||||
subghz_environment_set_alutech_at_4n_rainbow_table_file_name(
|
subghz_environment_set_alutech_at_4n_rainbow_table_file_name(
|
||||||
@@ -96,9 +98,9 @@ static bool subghz_decoder_test(const char* path, const char* name_decoder) {
|
|||||||
}
|
}
|
||||||
subghz_file_encoder_worker_free(file_worker_encoder_handler);
|
subghz_file_encoder_worker_free(file_worker_encoder_handler);
|
||||||
}
|
}
|
||||||
FURI_LOG_T(TAG, "Decoder count parse %d", subghz_test_decoder_count);
|
FURI_LOG_T(TAG, "\r\n Decoder count parse \033[0;33m%d\033[0m ", subghz_test_decoder_count);
|
||||||
if(furi_get_tick() - test_start > TEST_TIMEOUT) {
|
if(furi_get_tick() - test_start > TEST_TIMEOUT) {
|
||||||
printf("Test decoder %s ERROR TimeOut\r\n", name_decoder);
|
printf("\033[0;31mTest decoder %s ERROR TimeOut\033[0m\r\n", name_decoder);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return subghz_test_decoder_count ? true : false;
|
return subghz_test_decoder_count ? true : false;
|
||||||
@@ -135,9 +137,9 @@ static bool subghz_decode_random_test(const char* path) {
|
|||||||
}
|
}
|
||||||
subghz_file_encoder_worker_free(file_worker_encoder_handler);
|
subghz_file_encoder_worker_free(file_worker_encoder_handler);
|
||||||
}
|
}
|
||||||
FURI_LOG_D(TAG, "Decoder count parse %d", subghz_test_decoder_count);
|
FURI_LOG_D(TAG, "\r\n Decoder count parse \033[0;33m%d\033[0m ", subghz_test_decoder_count);
|
||||||
if(furi_get_tick() - test_start > TEST_TIMEOUT * 10) {
|
if(furi_get_tick() - test_start > TEST_TIMEOUT * 10) {
|
||||||
printf("Random test ERROR TimeOut\r\n");
|
printf("\033[0;31mRandom test ERROR TimeOut\033[0m\r\n");
|
||||||
return false;
|
return false;
|
||||||
} else if(subghz_test_decoder_count == TEST_RANDOM_COUNT_PARSE) {
|
} else if(subghz_test_decoder_count == TEST_RANDOM_COUNT_PARSE) {
|
||||||
return true;
|
return true;
|
||||||
@@ -198,9 +200,10 @@ static bool subghz_encoder_test(const char* path) {
|
|||||||
subghz_transmitter_free(transmitter);
|
subghz_transmitter_free(transmitter);
|
||||||
}
|
}
|
||||||
flipper_format_free(fff_data_file);
|
flipper_format_free(fff_data_file);
|
||||||
FURI_LOG_T(TAG, "Decoder count parse %d", subghz_test_decoder_count);
|
FURI_LOG_T(TAG, "\r\n Decoder count parse \033[0;33m%d\033[0m ", subghz_test_decoder_count);
|
||||||
if(furi_get_tick() - test_start > TEST_TIMEOUT) {
|
if(furi_get_tick() - test_start > TEST_TIMEOUT) {
|
||||||
printf("Test encoder %s ERROR TimeOut\r\n", furi_string_get_cstr(temp_str));
|
printf(
|
||||||
|
"\033[0;31mTest encoder %s ERROR TimeOut\033[0m\r\n", furi_string_get_cstr(temp_str));
|
||||||
subghz_test_decoder_count = 0;
|
subghz_test_decoder_count = 0;
|
||||||
}
|
}
|
||||||
furi_string_free(temp_str);
|
furi_string_free(temp_str);
|
||||||
@@ -327,12 +330,7 @@ bool subghz_hal_async_tx_test_run(SubGhzHalAsyncTxTestType type) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FuriHalCortexTimer timer = furi_hal_cortex_timer_get(30000000);
|
|
||||||
|
|
||||||
while(!furi_hal_subghz_is_async_tx_complete()) {
|
while(!furi_hal_subghz_is_async_tx_complete()) {
|
||||||
if(furi_hal_cortex_timer_is_expired(timer)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
furi_delay_ms(10);
|
furi_delay_ms(10);
|
||||||
}
|
}
|
||||||
furi_hal_subghz_stop_async_tx();
|
furi_hal_subghz_stop_async_tx();
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
|
|
||||||
int run_minunit_test_furi();
|
int run_minunit_test_furi();
|
||||||
int run_minunit_test_furi_hal();
|
int run_minunit_test_furi_hal();
|
||||||
int run_minunit_test_furi_hal_crypto();
|
|
||||||
int run_minunit_test_furi_string();
|
int run_minunit_test_furi_string();
|
||||||
int run_minunit_test_infrared();
|
int run_minunit_test_infrared();
|
||||||
int run_minunit_test_rpc();
|
int run_minunit_test_rpc();
|
||||||
@@ -40,7 +39,6 @@ typedef struct {
|
|||||||
const UnitTest unit_tests[] = {
|
const UnitTest unit_tests[] = {
|
||||||
{.name = "furi", .entry = run_minunit_test_furi},
|
{.name = "furi", .entry = run_minunit_test_furi},
|
||||||
{.name = "furi_hal", .entry = run_minunit_test_furi_hal},
|
{.name = "furi_hal", .entry = run_minunit_test_furi_hal},
|
||||||
{.name = "furi_hal_crypto", .entry = run_minunit_test_furi_hal_crypto},
|
|
||||||
{.name = "furi_string", .entry = run_minunit_test_furi_string},
|
{.name = "furi_string", .entry = run_minunit_test_furi_string},
|
||||||
{.name = "storage", .entry = run_minunit_test_storage},
|
{.name = "storage", .entry = run_minunit_test_storage},
|
||||||
{.name = "stream", .entry = run_minunit_test_stream},
|
{.name = "stream", .entry = run_minunit_test_stream},
|
||||||
@@ -65,8 +63,8 @@ const UnitTest unit_tests[] = {
|
|||||||
void minunit_print_progress() {
|
void minunit_print_progress() {
|
||||||
static const char progress[] = {'\\', '|', '/', '-'};
|
static const char progress[] = {'\\', '|', '/', '-'};
|
||||||
static uint8_t progress_counter = 0;
|
static uint8_t progress_counter = 0;
|
||||||
static uint32_t last_tick = 0;
|
static TickType_t last_tick = 0;
|
||||||
uint32_t current_tick = furi_get_tick();
|
TickType_t current_tick = xTaskGetTickCount();
|
||||||
if(current_tick - last_tick > 20) {
|
if(current_tick - last_tick > 20) {
|
||||||
last_tick = current_tick;
|
last_tick = current_tick;
|
||||||
printf("[%c]\033[3D", progress[++progress_counter % COUNT_OF(progress)]);
|
printf("[%c]\033[3D", progress[++progress_counter % COUNT_OF(progress)]);
|
||||||
@@ -90,7 +88,7 @@ void unit_tests_cli(Cli* cli, FuriString* args, void* context) {
|
|||||||
Loader* loader = furi_record_open(RECORD_LOADER);
|
Loader* loader = furi_record_open(RECORD_LOADER);
|
||||||
NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
|
NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
|
||||||
|
|
||||||
// TODO FL-3491: lock device while test running
|
// TODO: lock device while test running
|
||||||
if(loader_is_locked(loader)) {
|
if(loader_is_locked(loader)) {
|
||||||
printf("RPC: stop all applications to run tests\r\n");
|
printf("RPC: stop all applications to run tests\r\n");
|
||||||
notification_message(notification, &sequence_blink_magenta_100);
|
notification_message(notification, &sequence_blink_magenta_100);
|
||||||
|
|||||||
@@ -7,5 +7,6 @@ App(
|
|||||||
requires=["gui"],
|
requires=["gui"],
|
||||||
stack_size=1 * 1024,
|
stack_size=1 * 1024,
|
||||||
order=60,
|
order=60,
|
||||||
|
fap_icon="../../external/mousejacker/mouse_10px.png",
|
||||||
fap_category="Debug",
|
fap_category="Debug",
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -15,13 +15,10 @@
|
|||||||
#include <cc1101.h>
|
#include <cc1101.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#define TAG "SubGhzDeviceCc1101Ext"
|
#define TAG "SubGhz_Device_CC1101_Ext"
|
||||||
|
|
||||||
#define SUBGHZ_DEVICE_CC1101_EXT_TX_GPIO &gpio_ext_pb2
|
#define SUBGHZ_DEVICE_CC1101_EXT_TX_GPIO &gpio_ext_pb2
|
||||||
#define SUBGHZ_DEVICE_CC1101_EXT_E07_AMP_GPIO &gpio_ext_pc3
|
#define SUBGHZ_DEVICE_CC1101_EXT_DANGEROUS_RANGE false
|
||||||
#define SUBGHZ_DEVICE_CC1101_EXT_FORCE_DANGEROUS_RANGE false
|
|
||||||
|
|
||||||
#define SUBGHZ_DEVICE_CC1101_CONFIG_VER 1
|
|
||||||
|
|
||||||
/* DMA Channels definition */
|
/* DMA Channels definition */
|
||||||
#define SUBGHZ_DEVICE_CC1101_EXT_DMA DMA2
|
#define SUBGHZ_DEVICE_CC1101_EXT_DMA DMA2
|
||||||
@@ -81,8 +78,6 @@ typedef struct {
|
|||||||
const GpioPin* g0_pin;
|
const GpioPin* g0_pin;
|
||||||
SubGhzDeviceCC1101ExtAsyncTx async_tx;
|
SubGhzDeviceCC1101ExtAsyncTx async_tx;
|
||||||
SubGhzDeviceCC1101ExtAsyncRx async_rx;
|
SubGhzDeviceCC1101ExtAsyncRx async_rx;
|
||||||
bool power_amp;
|
|
||||||
bool extended_range;
|
|
||||||
} SubGhzDeviceCC1101Ext;
|
} SubGhzDeviceCC1101Ext;
|
||||||
|
|
||||||
static SubGhzDeviceCC1101Ext* subghz_device_cc1101_ext = NULL;
|
static SubGhzDeviceCC1101Ext* subghz_device_cc1101_ext = NULL;
|
||||||
@@ -192,7 +187,7 @@ static bool subghz_device_cc1101_ext_check_init() {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool subghz_device_cc1101_ext_alloc(SubGhzDeviceConf* conf) {
|
bool subghz_device_cc1101_ext_alloc() {
|
||||||
furi_assert(subghz_device_cc1101_ext == NULL);
|
furi_assert(subghz_device_cc1101_ext == NULL);
|
||||||
subghz_device_cc1101_ext = malloc(sizeof(SubGhzDeviceCC1101Ext));
|
subghz_device_cc1101_ext = malloc(sizeof(SubGhzDeviceCC1101Ext));
|
||||||
subghz_device_cc1101_ext->state = SubGhzDeviceCC1101ExtStateInit;
|
subghz_device_cc1101_ext->state = SubGhzDeviceCC1101ExtStateInit;
|
||||||
@@ -200,35 +195,16 @@ bool subghz_device_cc1101_ext_alloc(SubGhzDeviceConf* conf) {
|
|||||||
subghz_device_cc1101_ext->async_mirror_pin = NULL;
|
subghz_device_cc1101_ext->async_mirror_pin = NULL;
|
||||||
subghz_device_cc1101_ext->spi_bus_handle = &furi_hal_spi_bus_handle_external;
|
subghz_device_cc1101_ext->spi_bus_handle = &furi_hal_spi_bus_handle_external;
|
||||||
subghz_device_cc1101_ext->g0_pin = SUBGHZ_DEVICE_CC1101_EXT_TX_GPIO;
|
subghz_device_cc1101_ext->g0_pin = SUBGHZ_DEVICE_CC1101_EXT_TX_GPIO;
|
||||||
subghz_device_cc1101_ext->power_amp = false;
|
|
||||||
subghz_device_cc1101_ext->extended_range = false;
|
|
||||||
if(conf) {
|
|
||||||
if(conf->ver == SUBGHZ_DEVICE_CC1101_CONFIG_VER) {
|
|
||||||
subghz_device_cc1101_ext->power_amp = conf->power_amp;
|
|
||||||
subghz_device_cc1101_ext->extended_range = conf->extended_range;
|
|
||||||
} else {
|
|
||||||
FURI_LOG_E(TAG, "Config version mismatch");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
subghz_device_cc1101_ext->async_rx.capture_delta_duration = 0;
|
subghz_device_cc1101_ext->async_rx.capture_delta_duration = 0;
|
||||||
|
|
||||||
furi_hal_spi_bus_handle_init(subghz_device_cc1101_ext->spi_bus_handle);
|
furi_hal_spi_bus_handle_init(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
if(subghz_device_cc1101_ext->power_amp) {
|
|
||||||
furi_hal_gpio_init_simple(SUBGHZ_DEVICE_CC1101_EXT_E07_AMP_GPIO, GpioModeOutputPushPull);
|
|
||||||
}
|
|
||||||
|
|
||||||
return subghz_device_cc1101_ext_check_init();
|
return subghz_device_cc1101_ext_check_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void subghz_device_cc1101_ext_free() {
|
void subghz_device_cc1101_ext_free() {
|
||||||
furi_assert(subghz_device_cc1101_ext != NULL);
|
furi_assert(subghz_device_cc1101_ext != NULL);
|
||||||
|
|
||||||
furi_hal_spi_bus_handle_deinit(subghz_device_cc1101_ext->spi_bus_handle);
|
furi_hal_spi_bus_handle_deinit(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
if(subghz_device_cc1101_ext->power_amp) {
|
|
||||||
furi_hal_gpio_init_simple(SUBGHZ_DEVICE_CC1101_EXT_E07_AMP_GPIO, GpioModeAnalog);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(subghz_device_cc1101_ext);
|
free(subghz_device_cc1101_ext);
|
||||||
subghz_device_cc1101_ext = NULL;
|
subghz_device_cc1101_ext = NULL;
|
||||||
}
|
}
|
||||||
@@ -245,7 +221,7 @@ bool subghz_device_cc1101_ext_is_connect() {
|
|||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
if(subghz_device_cc1101_ext == NULL) { // not initialized
|
if(subghz_device_cc1101_ext == NULL) { // not initialized
|
||||||
ret = subghz_device_cc1101_ext_alloc(NULL);
|
ret = subghz_device_cc1101_ext_alloc();
|
||||||
subghz_device_cc1101_ext_free();
|
subghz_device_cc1101_ext_free();
|
||||||
} else { // initialized
|
} else { // initialized
|
||||||
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
@@ -357,7 +333,7 @@ bool subghz_device_cc1101_ext_rx_pipe_not_empty() {
|
|||||||
(CC1101_STATUS_RXBYTES) | CC1101_BURST,
|
(CC1101_STATUS_RXBYTES) | CC1101_BURST,
|
||||||
(uint8_t*)status);
|
(uint8_t*)status);
|
||||||
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
// TODO: Find reason why RXFIFO_OVERFLOW doesnt work correctly
|
// TODO: you can add a buffer overflow flag if needed
|
||||||
if(status->NUM_RXBYTES > 0) {
|
if(status->NUM_RXBYTES > 0) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@@ -405,18 +381,12 @@ void subghz_device_cc1101_ext_idle() {
|
|||||||
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
cc1101_switch_to_idle(subghz_device_cc1101_ext->spi_bus_handle);
|
cc1101_switch_to_idle(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
if(subghz_device_cc1101_ext->power_amp) {
|
|
||||||
furi_hal_gpio_write(SUBGHZ_DEVICE_CC1101_EXT_E07_AMP_GPIO, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void subghz_device_cc1101_ext_rx() {
|
void subghz_device_cc1101_ext_rx() {
|
||||||
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
cc1101_switch_to_rx(subghz_device_cc1101_ext->spi_bus_handle);
|
cc1101_switch_to_rx(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
if(subghz_device_cc1101_ext->power_amp) {
|
|
||||||
furi_hal_gpio_write(SUBGHZ_DEVICE_CC1101_EXT_E07_AMP_GPIO, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool subghz_device_cc1101_ext_tx() {
|
bool subghz_device_cc1101_ext_tx() {
|
||||||
@@ -424,9 +394,6 @@ bool subghz_device_cc1101_ext_tx() {
|
|||||||
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
cc1101_switch_to_tx(subghz_device_cc1101_ext->spi_bus_handle);
|
cc1101_switch_to_tx(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
if(subghz_device_cc1101_ext->power_amp) {
|
|
||||||
furi_hal_gpio_write(SUBGHZ_DEVICE_CC1101_EXT_E07_AMP_GPIO, 1);
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -465,16 +432,14 @@ bool subghz_device_cc1101_ext_is_frequency_valid(uint32_t value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool subghz_device_cc1101_ext_is_tx_allowed(uint32_t value) {
|
bool subghz_device_cc1101_ext_is_tx_allowed(uint32_t value) {
|
||||||
if(!(SUBGHZ_DEVICE_CC1101_EXT_FORCE_DANGEROUS_RANGE ||
|
if(!(SUBGHZ_DEVICE_CC1101_EXT_DANGEROUS_RANGE) &&
|
||||||
subghz_device_cc1101_ext->extended_range) &&
|
|
||||||
!(value >= 299999755 && value <= 350000335) && // was increased from 348 to 350
|
!(value >= 299999755 && value <= 350000335) && // was increased from 348 to 350
|
||||||
!(value >= 386999938 && value <= 467750000) && // was increased from 464 to 467.75
|
!(value >= 386999938 && value <= 467750000) && // was increased from 464 to 467.75
|
||||||
!(value >= 778999847 && value <= 928000000)) {
|
!(value >= 778999847 && value <= 928000000)) {
|
||||||
FURI_LOG_I(TAG, "Frequency blocked - outside default range");
|
FURI_LOG_I(TAG, "Frequency blocked - outside default range");
|
||||||
return false;
|
return false;
|
||||||
} else if(
|
} else if(
|
||||||
(SUBGHZ_DEVICE_CC1101_EXT_FORCE_DANGEROUS_RANGE ||
|
(SUBGHZ_DEVICE_CC1101_EXT_DANGEROUS_RANGE) &&
|
||||||
subghz_device_cc1101_ext->extended_range) &&
|
|
||||||
!subghz_device_cc1101_ext_is_frequency_valid(value)) {
|
!subghz_device_cc1101_ext_is_frequency_valid(value)) {
|
||||||
FURI_LOG_I(TAG, "Frequency blocked - outside dangerous range");
|
FURI_LOG_I(TAG, "Frequency blocked - outside dangerous range");
|
||||||
return false;
|
return false;
|
||||||
@@ -564,7 +529,7 @@ void subghz_device_cc1101_ext_start_async_rx(
|
|||||||
furi_hal_bus_enable(FuriHalBusTIM17);
|
furi_hal_bus_enable(FuriHalBusTIM17);
|
||||||
|
|
||||||
// Configure TIM
|
// Configure TIM
|
||||||
//Set the timer resolution to 2 us
|
//Set the timer resolution to 2 <EFBFBD>s
|
||||||
LL_TIM_SetPrescaler(TIM17, (64 << 1) - 1);
|
LL_TIM_SetPrescaler(TIM17, (64 << 1) - 1);
|
||||||
LL_TIM_SetCounterMode(TIM17, LL_TIM_COUNTERMODE_UP);
|
LL_TIM_SetCounterMode(TIM17, LL_TIM_COUNTERMODE_UP);
|
||||||
LL_TIM_SetAutoReload(TIM17, 0xFFFF);
|
LL_TIM_SetAutoReload(TIM17, 0xFFFF);
|
||||||
@@ -745,7 +710,7 @@ bool subghz_device_cc1101_ext_start_async_tx(SubGhzDeviceCC1101ExtCallback callb
|
|||||||
furi_hal_bus_enable(FuriHalBusTIM17);
|
furi_hal_bus_enable(FuriHalBusTIM17);
|
||||||
|
|
||||||
// Configure TIM
|
// Configure TIM
|
||||||
// Set the timer resolution to 2 us
|
// Set the timer resolution to 2 <EFBFBD>s
|
||||||
LL_TIM_SetPrescaler(TIM17, (64 << 1) - 1);
|
LL_TIM_SetPrescaler(TIM17, (64 << 1) - 1);
|
||||||
LL_TIM_SetCounterMode(TIM17, LL_TIM_COUNTERMODE_UP);
|
LL_TIM_SetCounterMode(TIM17, LL_TIM_COUNTERMODE_UP);
|
||||||
LL_TIM_SetAutoReload(TIM17, 0xFFFF);
|
LL_TIM_SetAutoReload(TIM17, 0xFFFF);
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <lib/subghz/devices/preset.h>
|
#include <lib/subghz/devices/preset.h>
|
||||||
#include <lib/subghz/devices/types.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
@@ -35,7 +34,7 @@ const GpioPin* subghz_device_cc1101_ext_get_data_gpio();
|
|||||||
*
|
*
|
||||||
* @return true if success
|
* @return true if success
|
||||||
*/
|
*/
|
||||||
bool subghz_device_cc1101_ext_alloc(SubGhzDeviceConf* conf);
|
bool subghz_device_cc1101_ext_alloc();
|
||||||
|
|
||||||
/** Deinitialize device
|
/** Deinitialize device
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#include "cc1101_ext.h"
|
#include "cc1101_ext.h"
|
||||||
#include <lib/subghz/devices/cc1101_configs.h>
|
#include <lib/subghz/devices/cc1101_configs.h>
|
||||||
|
|
||||||
#define TAG "SubGhzDeviceCc1101Ext"
|
#define TAG "SubGhzDeviceCC1101Ext"
|
||||||
|
|
||||||
static bool subghz_device_cc1101_ext_interconnect_is_frequency_valid(uint32_t frequency) {
|
static bool subghz_device_cc1101_ext_interconnect_is_frequency_valid(uint32_t frequency) {
|
||||||
bool ret = subghz_device_cc1101_ext_is_frequency_valid(frequency);
|
bool ret = subghz_device_cc1101_ext_is_frequency_valid(frequency);
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ We recommend to use the `APP_ASSETS_PATH` macro to get the path to the Apps Asse
|
|||||||
|
|
||||||
## What is the difference between the Apps Assets folder and the Apps Data folder?
|
## What is the difference between the Apps Assets folder and the Apps Data folder?
|
||||||
|
|
||||||
The Apps Assets folder is used to store the data <u>provided</u> with the application. For example, if you want to create a game, you can store game levels (content data) in the Apps Assets folder.
|
The Apps Assets folder is used to store the data <u>provided</u> with the application. For example, if you want to create a game, you can store game levels (contant data) in the Apps Assets folder.
|
||||||
|
|
||||||
The Apps Data folder is used to store data <u>generated</u> by the application. For example, if you want to create a game, you can save the progress of the game (user-generated data) in the Apps Data folder.
|
The Apps Data folder is used to store data <u>generated</u> by the application. For example, if you want to create a game, you can save the progress of the game (user-generated data) in the Apps Data folder.
|
||||||
|
|
||||||
@@ -55,4 +55,4 @@ When app is launched, the `files` folder will be unpacked to the Apps Assets fol
|
|||||||
|
|
||||||
The data is unpacked when the application starts, if the application is launched for the first time, or if the data within the application is updated.
|
The data is unpacked when the application starts, if the application is launched for the first time, or if the data within the application is updated.
|
||||||
|
|
||||||
When an application is compiled, the contents of the "files" folder are hashed and stored within the application itself. When the application starts, this hash is compared to the hash stored in the `.assets.signature` file. If the hashes differ or the `.assets.signature` file does not exist, the application folder is deleted and the new data is unpacked.
|
When an application is compiled, the contents of the "files" folder are hashed and stored within the application itself. When the application starts, this hash is compared to the hash stored in the `.assets.signature` file. If the hashes differ or the `.assets.signature` file does not exist, the application folder is deleted and the new data is unpacked.
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <toolbox/stream/file_stream.h>
|
#include <toolbox/stream/file_stream.h>
|
||||||
|
|
||||||
// Define log tag
|
// Define log tag
|
||||||
#define TAG "ExampleAppsAssets"
|
#define TAG "example_apps_assets"
|
||||||
|
|
||||||
static void example_apps_data_print_file_content(Storage* storage, const char* path) {
|
static void example_apps_data_print_file_content(Storage* storage, const char* path) {
|
||||||
Stream* stream = file_stream_alloc(storage);
|
Stream* stream = file_stream_alloc(storage);
|
||||||
|
|||||||
@@ -19,6 +19,6 @@ We recommend to use the `APP_DATA_PATH` macro to get the path to the Apps Data f
|
|||||||
|
|
||||||
## What is the difference between the Apps Assets folder and the Apps Data folder?
|
## What is the difference between the Apps Assets folder and the Apps Data folder?
|
||||||
|
|
||||||
The Apps Assets folder is used to store the data <u>provided</u> with the application. For example, if you want to create a game, you can store game levels (content data) in the Apps Assets folder.
|
The Apps Assets folder is used to store the data <u>provided</u> with the application. For example, if you want to create a game, you can store game levels (contant data) in the Apps Assets folder.
|
||||||
|
|
||||||
The Apps Data folder is used to store data <u>generated</u> by the application. For example, if you want to create a game, you can save the progress of the game (user-generated data) in the Apps Data folder.
|
The Apps Data folder is used to store data <u>generated</u> by the application. For example, if you want to create a game, you can save the progress of the game (user-generated data) in the Apps Data folder.
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
#include <storage/storage.h>
|
#include <storage/storage.h>
|
||||||
|
|
||||||
// Define log tag
|
// Define log tag
|
||||||
#define TAG "ExampleAppsData"
|
#define TAG "example_apps_data"
|
||||||
|
|
||||||
// Application entry point
|
// Application entry point
|
||||||
int32_t example_apps_data_main(void* p) {
|
int32_t example_apps_data_main(void* p) {
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ App(
|
|||||||
entry_point="example_plugins_app",
|
entry_point="example_plugins_app",
|
||||||
stack_size=2 * 1024,
|
stack_size=2 * 1024,
|
||||||
fap_category="Examples",
|
fap_category="Examples",
|
||||||
sources=["*.c", "!plugin*.c"],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
App(
|
App(
|
||||||
@@ -22,7 +21,6 @@ App(
|
|||||||
apptype=FlipperAppType.PLUGIN,
|
apptype=FlipperAppType.PLUGIN,
|
||||||
entry_point="example_plugin1_ep",
|
entry_point="example_plugin1_ep",
|
||||||
requires=["example_plugins", "example_plugins_multi"],
|
requires=["example_plugins", "example_plugins_multi"],
|
||||||
sources=["plugin1.c"],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
App(
|
App(
|
||||||
@@ -30,5 +28,4 @@ App(
|
|||||||
apptype=FlipperAppType.PLUGIN,
|
apptype=FlipperAppType.PLUGIN,
|
||||||
entry_point="example_plugin2_ep",
|
entry_point="example_plugin2_ep",
|
||||||
requires=["example_plugins_multi"],
|
requires=["example_plugins_multi"],
|
||||||
sources=["plugin2.c"],
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
#include <loader/firmware_api/firmware_api.h>
|
#include <loader/firmware_api/firmware_api.h>
|
||||||
#include <storage/storage.h>
|
#include <storage/storage.h>
|
||||||
|
|
||||||
#define TAG "ExamplePlugins"
|
#define TAG "example_plugins"
|
||||||
|
|
||||||
int32_t example_plugins_app(void* p) {
|
int32_t example_plugins_app(void* p) {
|
||||||
UNUSED(p);
|
UNUSED(p);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
|
|
||||||
#define TAG "ExamplePlugins"
|
#define TAG "example_plugins"
|
||||||
|
|
||||||
int32_t example_plugins_multi_app(void* p) {
|
int32_t example_plugins_multi_app(void* p) {
|
||||||
UNUSED(p);
|
UNUSED(p);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
/* Common interface between a plugin and host application */
|
/* Common interface between a plugin and host applicaion */
|
||||||
|
|
||||||
#define PLUGIN_APP_ID "example_plugins"
|
#define PLUGIN_APP_ID "example_plugins"
|
||||||
#define PLUGIN_API_VERSION 1
|
#define PLUGIN_API_VERSION 1
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ App(
|
|||||||
entry_point="example_advanced_plugins_app",
|
entry_point="example_advanced_plugins_app",
|
||||||
stack_size=2 * 1024,
|
stack_size=2 * 1024,
|
||||||
fap_category="Examples",
|
fap_category="Examples",
|
||||||
sources=["*.c*", "!plugin*.c"],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
App(
|
App(
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include <loader/firmware_api/firmware_api.h>
|
#include <loader/firmware_api/firmware_api.h>
|
||||||
|
|
||||||
#define TAG "ExampleAdvancedPlugins"
|
#define TAG "example_advanced_plugins"
|
||||||
|
|
||||||
int32_t example_advanced_plugins_app(void* p) {
|
int32_t example_advanced_plugins_app(void* p) {
|
||||||
UNUSED(p);
|
UNUSED(p);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
/* Common interface between a plugin and host application */
|
/* Common interface between a plugin and host applicaion */
|
||||||
|
|
||||||
#define PLUGIN_APP_ID "example_plugins_advanced"
|
#define PLUGIN_APP_ID "example_plugins_advanced"
|
||||||
#define PLUGIN_API_VERSION 1
|
#define PLUGIN_API_VERSION 1
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ static void example_thermo_request_temperature(ExampleThermoContext* context) {
|
|||||||
bool success = false;
|
bool success = false;
|
||||||
do {
|
do {
|
||||||
/* Each communication with a 1-wire device starts by a reset.
|
/* Each communication with a 1-wire device starts by a reset.
|
||||||
The function will return true if a device responded with a presence pulse. */
|
The functon will return true if a device responded with a presence pulse. */
|
||||||
if(!onewire_host_reset(onewire)) break;
|
if(!onewire_host_reset(onewire)) break;
|
||||||
/* After the reset, a ROM operation must follow.
|
/* After the reset, a ROM operation must follow.
|
||||||
If there is only one device connected, the "Skip ROM" command is most appropriate
|
If there is only one device connected, the "Skip ROM" command is most appropriate
|
||||||
@@ -130,7 +130,7 @@ static void example_thermo_read_temperature(ExampleThermoContext* context) {
|
|||||||
size_t attempts_left = 10;
|
size_t attempts_left = 10;
|
||||||
do {
|
do {
|
||||||
/* Each communication with a 1-wire device starts by a reset.
|
/* Each communication with a 1-wire device starts by a reset.
|
||||||
The function will return true if a device responded with a presence pulse. */
|
The functon will return true if a device responded with a presence pulse. */
|
||||||
if(!onewire_host_reset(onewire)) continue;
|
if(!onewire_host_reset(onewire)) continue;
|
||||||
|
|
||||||
/* After the reset, a ROM operation must follow.
|
/* After the reset, a ROM operation must follow.
|
||||||
@@ -221,7 +221,8 @@ static void example_thermo_draw_callback(Canvas* canvas, void* ctx) {
|
|||||||
canvas_draw_line(canvas, 0, 16, 128, 16);
|
canvas_draw_line(canvas, 0, 16, 128, 16);
|
||||||
|
|
||||||
canvas_set_font(canvas, FontSecondary);
|
canvas_set_font(canvas, FontSecondary);
|
||||||
canvas_draw_str_aligned(canvas, middle_x, 30, AlignCenter, AlignBottom, "Connect thermometer");
|
canvas_draw_str_aligned(
|
||||||
|
canvas, middle_x, 30, AlignCenter, AlignBottom, "Connnect thermometer");
|
||||||
|
|
||||||
snprintf(
|
snprintf(
|
||||||
text_store,
|
text_store,
|
||||||
@@ -236,7 +237,7 @@ static void example_thermo_draw_callback(Canvas* canvas, void* ctx) {
|
|||||||
float temp;
|
float temp;
|
||||||
char temp_units;
|
char temp_units;
|
||||||
|
|
||||||
/* The application is locale-aware.
|
/* The applicaton is locale-aware.
|
||||||
Change Settings->System->Units to check it out. */
|
Change Settings->System->Units to check it out. */
|
||||||
switch(locale_get_measurement_unit()) {
|
switch(locale_get_measurement_unit()) {
|
||||||
case LocaleMeasurementUnitsMetric:
|
case LocaleMeasurementUnitsMetric:
|
||||||
@@ -354,7 +355,7 @@ int32_t example_thermo_main(void* p) {
|
|||||||
/* Allocate all of the necessary structures */
|
/* Allocate all of the necessary structures */
|
||||||
ExampleThermoContext* context = example_thermo_context_alloc();
|
ExampleThermoContext* context = example_thermo_context_alloc();
|
||||||
|
|
||||||
/* Start the application's main loop. It won't return until the application was requested to exit. */
|
/* Start the applicaton's main loop. It won't return until the application was requested to exit. */
|
||||||
example_thermo_run(context);
|
example_thermo_run(context);
|
||||||
|
|
||||||
/* Release all unneeded resources */
|
/* Release all unneeded resources */
|
||||||
|
|||||||
6
applications/external/application.fam
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# Placeholder
|
||||||
|
App(
|
||||||
|
appid="external_apps",
|
||||||
|
name="External apps bundle",
|
||||||
|
apptype=FlipperAppType.METAPACKAGE,
|
||||||
|
)
|
||||||
14
applications/external/arkanoid/application.fam
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
App(
|
||||||
|
appid="arkanoid",
|
||||||
|
name="Arkanoid",
|
||||||
|
apptype=FlipperAppType.EXTERNAL,
|
||||||
|
entry_point="arkanoid_game_app",
|
||||||
|
requires=["gui"],
|
||||||
|
stack_size=1 * 1024,
|
||||||
|
order=30,
|
||||||
|
fap_icon="arkanoid_10px.png",
|
||||||
|
fap_category="Games",
|
||||||
|
fap_author="@xMasterX & @gotnull",
|
||||||
|
fap_version="1.0",
|
||||||
|
fap_description="Arkanoid Game",
|
||||||
|
)
|
||||||
BIN
applications/external/arkanoid/arkanoid_10px.png
vendored
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
479
applications/external/arkanoid/arkanoid_game.c
vendored
Normal file
@@ -0,0 +1,479 @@
|
|||||||
|
#include <furi.h>
|
||||||
|
#include <gui/gui.h>
|
||||||
|
#include <input/input.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <gui/view.h>
|
||||||
|
#include <notification/notification.h>
|
||||||
|
#include <notification/notification_messages.h>
|
||||||
|
#include <dolphin/dolphin.h>
|
||||||
|
|
||||||
|
#define TAG "Arkanoid"
|
||||||
|
|
||||||
|
#define FLIPPER_LCD_WIDTH 128
|
||||||
|
#define FLIPPER_LCD_HEIGHT 64
|
||||||
|
#define MAX_SPEED 3
|
||||||
|
|
||||||
|
typedef enum { EventTypeTick, EventTypeKey } EventType;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
//Brick Bounds used in collision detection
|
||||||
|
int leftBrick;
|
||||||
|
int rightBrick;
|
||||||
|
int topBrick;
|
||||||
|
int bottomBrick;
|
||||||
|
bool isHit[4][13]; //Array of if bricks are hit or not
|
||||||
|
} BrickState;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int dx; //Initial movement of ball
|
||||||
|
int dy; //Initial movement of ball
|
||||||
|
int xb; //Balls starting possition
|
||||||
|
int yb; //Balls starting possition
|
||||||
|
bool released; //If the ball has been released by the player
|
||||||
|
//Ball Bounds used in collision detection
|
||||||
|
int leftBall;
|
||||||
|
int rightBall;
|
||||||
|
int topBall;
|
||||||
|
int bottomBall;
|
||||||
|
} BallState;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
FuriMutex* mutex;
|
||||||
|
BallState ball_state;
|
||||||
|
BrickState brick_state;
|
||||||
|
NotificationApp* notify;
|
||||||
|
unsigned int COLUMNS; //Columns of bricks
|
||||||
|
unsigned int ROWS; //Rows of bricks
|
||||||
|
bool initialDraw; //If the inital draw has happened
|
||||||
|
int xPaddle; //X position of paddle
|
||||||
|
char text[16]; //General string buffer
|
||||||
|
bool bounced; //Used to fix double bounce glitch
|
||||||
|
int lives; //Amount of lives
|
||||||
|
int level; //Current level
|
||||||
|
unsigned int score; //Score for the game
|
||||||
|
unsigned int brickCount; //Amount of bricks hit
|
||||||
|
int tick; //Tick counter
|
||||||
|
bool gameStarted; // Did the game start?
|
||||||
|
int speed; // Ball speed
|
||||||
|
} ArkanoidState;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
EventType type;
|
||||||
|
InputEvent input;
|
||||||
|
} GameEvent;
|
||||||
|
|
||||||
|
static const NotificationSequence sequence_short_sound = {
|
||||||
|
&message_note_c5,
|
||||||
|
&message_delay_50,
|
||||||
|
&message_sound_off,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
// generate number in range [min,max)
|
||||||
|
int rand_range(int min, int max) {
|
||||||
|
return min + rand() % (max - min);
|
||||||
|
}
|
||||||
|
|
||||||
|
void move_ball(Canvas* canvas, ArkanoidState* st) {
|
||||||
|
st->tick++;
|
||||||
|
|
||||||
|
int current_speed = abs(st->speed - 1 - MAX_SPEED);
|
||||||
|
if(st->tick % current_speed != 0 && st->tick % (current_speed + 1) != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(st->ball_state.released) {
|
||||||
|
//Move ball
|
||||||
|
if(abs(st->ball_state.dx) == 2) {
|
||||||
|
st->ball_state.xb += st->ball_state.dx / 2;
|
||||||
|
// 2x speed is really 1.5 speed
|
||||||
|
if((st->tick / current_speed) % 2 == 0) st->ball_state.xb += st->ball_state.dx / 2;
|
||||||
|
} else {
|
||||||
|
st->ball_state.xb += st->ball_state.dx;
|
||||||
|
}
|
||||||
|
st->ball_state.yb = st->ball_state.yb + st->ball_state.dy;
|
||||||
|
|
||||||
|
//Set bounds
|
||||||
|
st->ball_state.leftBall = st->ball_state.xb;
|
||||||
|
st->ball_state.rightBall = st->ball_state.xb + 2;
|
||||||
|
st->ball_state.topBall = st->ball_state.yb;
|
||||||
|
st->ball_state.bottomBall = st->ball_state.yb + 2;
|
||||||
|
|
||||||
|
//Bounce off top edge
|
||||||
|
if(st->ball_state.yb <= 0) {
|
||||||
|
st->ball_state.yb = 2;
|
||||||
|
st->ball_state.dy = -st->ball_state.dy;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Lose a life if bottom edge hit
|
||||||
|
if(st->ball_state.yb >= FLIPPER_LCD_HEIGHT) {
|
||||||
|
canvas_draw_frame(canvas, st->xPaddle, FLIPPER_LCD_HEIGHT - 1, 11, 1);
|
||||||
|
st->xPaddle = 54;
|
||||||
|
st->ball_state.yb = 60;
|
||||||
|
st->ball_state.released = false;
|
||||||
|
st->lives--;
|
||||||
|
st->gameStarted = false;
|
||||||
|
|
||||||
|
if(rand_range(0, 2) == 0) {
|
||||||
|
st->ball_state.dx = 1;
|
||||||
|
} else {
|
||||||
|
st->ball_state.dx = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Bounce off left side
|
||||||
|
if(st->ball_state.xb <= 0) {
|
||||||
|
st->ball_state.xb = 2;
|
||||||
|
st->ball_state.dx = -st->ball_state.dx;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Bounce off right side
|
||||||
|
if(st->ball_state.xb >= FLIPPER_LCD_WIDTH - 2) {
|
||||||
|
st->ball_state.xb = FLIPPER_LCD_WIDTH - 4;
|
||||||
|
st->ball_state.dx = -st->ball_state.dx;
|
||||||
|
// arduboy.tunes.tone(523, 250);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Bounce off paddle
|
||||||
|
if(st->ball_state.xb + 1 >= st->xPaddle && st->ball_state.xb <= st->xPaddle + 12 &&
|
||||||
|
st->ball_state.yb + 2 >= FLIPPER_LCD_HEIGHT - 1 &&
|
||||||
|
st->ball_state.yb <= FLIPPER_LCD_HEIGHT) {
|
||||||
|
st->ball_state.dy = -st->ball_state.dy;
|
||||||
|
st->ball_state.dx =
|
||||||
|
((st->ball_state.xb - (st->xPaddle + 6)) / 3); //Applies spin on the ball
|
||||||
|
// prevent straight bounce, but not prevent roguuemaster from stealing
|
||||||
|
if(st->ball_state.dx == 0) {
|
||||||
|
st->ball_state.dx = (rand_range(0, 2) == 1) ? 1 : -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Bounce off Bricks
|
||||||
|
for(unsigned int row = 0; row < st->ROWS; row++) {
|
||||||
|
for(unsigned int column = 0; column < st->COLUMNS; column++) {
|
||||||
|
if(!st->brick_state.isHit[row][column]) {
|
||||||
|
//Sets Brick bounds
|
||||||
|
st->brick_state.leftBrick = 10 * column;
|
||||||
|
st->brick_state.rightBrick = 10 * column + 10;
|
||||||
|
st->brick_state.topBrick = 6 * row + 1;
|
||||||
|
st->brick_state.bottomBrick = 6 * row + 7;
|
||||||
|
|
||||||
|
//If A collison has occured
|
||||||
|
if(st->ball_state.topBall <= st->brick_state.bottomBrick &&
|
||||||
|
st->ball_state.bottomBall >= st->brick_state.topBrick &&
|
||||||
|
st->ball_state.leftBall <= st->brick_state.rightBrick &&
|
||||||
|
st->ball_state.rightBall >= st->brick_state.leftBrick) {
|
||||||
|
st->score += st->level;
|
||||||
|
// Blink led when we hit some brick
|
||||||
|
notification_message(st->notify, &sequence_short_sound);
|
||||||
|
//notification_message(st->notify, &sequence_blink_white_100);
|
||||||
|
|
||||||
|
st->brickCount++;
|
||||||
|
st->brick_state.isHit[row][column] = true;
|
||||||
|
canvas_draw_frame(canvas, 10 * column, 2 + 6 * row, 8, 4);
|
||||||
|
|
||||||
|
//Vertical collision
|
||||||
|
if(st->ball_state.bottomBall > st->brick_state.bottomBrick ||
|
||||||
|
st->ball_state.topBall < st->brick_state.topBrick) {
|
||||||
|
//Only bounce once each ball move
|
||||||
|
if(!st->bounced) {
|
||||||
|
st->ball_state.dy = -st->ball_state.dy;
|
||||||
|
st->ball_state.yb += st->ball_state.dy;
|
||||||
|
st->bounced = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Hoizontal collision
|
||||||
|
if(st->ball_state.leftBall < st->brick_state.leftBrick ||
|
||||||
|
st->ball_state.rightBall > st->brick_state.rightBrick) {
|
||||||
|
//Only bounce once brick each ball move
|
||||||
|
if(!st->bounced) {
|
||||||
|
st->ball_state.dx = -st->ball_state.dx;
|
||||||
|
st->ball_state.xb += st->ball_state.dx;
|
||||||
|
st->bounced = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Reset Bounce
|
||||||
|
st->bounced = false;
|
||||||
|
} else {
|
||||||
|
//Ball follows paddle
|
||||||
|
st->ball_state.xb = st->xPaddle + 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_lives(Canvas* canvas, ArkanoidState* arkanoid_state) {
|
||||||
|
if(arkanoid_state->lives == 3) {
|
||||||
|
canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 7);
|
||||||
|
canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 7);
|
||||||
|
canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 8);
|
||||||
|
canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 8);
|
||||||
|
|
||||||
|
canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 11);
|
||||||
|
canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 11);
|
||||||
|
canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 12);
|
||||||
|
canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 12);
|
||||||
|
|
||||||
|
canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 15);
|
||||||
|
canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 15);
|
||||||
|
canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 16);
|
||||||
|
canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 16);
|
||||||
|
} else if(arkanoid_state->lives == 2) {
|
||||||
|
canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 7);
|
||||||
|
canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 7);
|
||||||
|
canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 8);
|
||||||
|
canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 8);
|
||||||
|
|
||||||
|
canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 11);
|
||||||
|
canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 11);
|
||||||
|
canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 12);
|
||||||
|
canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 12);
|
||||||
|
} else {
|
||||||
|
canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 7);
|
||||||
|
canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 7);
|
||||||
|
canvas_draw_dot(canvas, 4, FLIPPER_LCD_HEIGHT - 8);
|
||||||
|
canvas_draw_dot(canvas, 3, FLIPPER_LCD_HEIGHT - 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_score(Canvas* canvas, ArkanoidState* arkanoid_state) {
|
||||||
|
snprintf(arkanoid_state->text, sizeof(arkanoid_state->text), "%u", arkanoid_state->score);
|
||||||
|
canvas_draw_str_aligned(
|
||||||
|
canvas,
|
||||||
|
FLIPPER_LCD_WIDTH - 2,
|
||||||
|
FLIPPER_LCD_HEIGHT - 6,
|
||||||
|
AlignRight,
|
||||||
|
AlignBottom,
|
||||||
|
arkanoid_state->text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_ball(Canvas* canvas, ArkanoidState* ast) {
|
||||||
|
canvas_draw_dot(canvas, ast->ball_state.xb, ast->ball_state.yb);
|
||||||
|
canvas_draw_dot(canvas, ast->ball_state.xb + 1, ast->ball_state.yb);
|
||||||
|
canvas_draw_dot(canvas, ast->ball_state.xb, ast->ball_state.yb + 1);
|
||||||
|
canvas_draw_dot(canvas, ast->ball_state.xb + 1, ast->ball_state.yb + 1);
|
||||||
|
|
||||||
|
move_ball(canvas, ast);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_paddle(Canvas* canvas, ArkanoidState* arkanoid_state) {
|
||||||
|
canvas_draw_frame(canvas, arkanoid_state->xPaddle, FLIPPER_LCD_HEIGHT - 1, 11, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset_level(Canvas* canvas, ArkanoidState* arkanoid_state) {
|
||||||
|
//Undraw paddle
|
||||||
|
canvas_draw_frame(canvas, arkanoid_state->xPaddle, FLIPPER_LCD_HEIGHT - 1, 11, 1);
|
||||||
|
|
||||||
|
//Undraw ball
|
||||||
|
canvas_draw_dot(canvas, arkanoid_state->ball_state.xb, arkanoid_state->ball_state.yb);
|
||||||
|
canvas_draw_dot(canvas, arkanoid_state->ball_state.xb + 1, arkanoid_state->ball_state.yb);
|
||||||
|
canvas_draw_dot(canvas, arkanoid_state->ball_state.xb, arkanoid_state->ball_state.yb + 1);
|
||||||
|
canvas_draw_dot(canvas, arkanoid_state->ball_state.xb + 1, arkanoid_state->ball_state.yb + 1);
|
||||||
|
|
||||||
|
//Alter various variables to reset the game
|
||||||
|
arkanoid_state->xPaddle = 54;
|
||||||
|
arkanoid_state->ball_state.yb = 60;
|
||||||
|
arkanoid_state->brickCount = 0;
|
||||||
|
arkanoid_state->ball_state.released = false;
|
||||||
|
arkanoid_state->gameStarted = false;
|
||||||
|
|
||||||
|
// Reset all brick hit states
|
||||||
|
for(unsigned int row = 0; row < arkanoid_state->ROWS; row++) {
|
||||||
|
for(unsigned int column = 0; column < arkanoid_state->COLUMNS; column++) {
|
||||||
|
arkanoid_state->brick_state.isHit[row][column] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void arkanoid_state_init(ArkanoidState* arkanoid_state) {
|
||||||
|
// Init notification
|
||||||
|
arkanoid_state->notify = furi_record_open(RECORD_NOTIFICATION);
|
||||||
|
|
||||||
|
// Set the initial game state
|
||||||
|
arkanoid_state->COLUMNS = 13;
|
||||||
|
arkanoid_state->ROWS = 4;
|
||||||
|
arkanoid_state->ball_state.dx = -1;
|
||||||
|
arkanoid_state->ball_state.dy = -1;
|
||||||
|
arkanoid_state->speed = 2;
|
||||||
|
arkanoid_state->bounced = false;
|
||||||
|
arkanoid_state->lives = 3;
|
||||||
|
arkanoid_state->level = 1;
|
||||||
|
arkanoid_state->score = 0;
|
||||||
|
arkanoid_state->COLUMNS = 13;
|
||||||
|
arkanoid_state->COLUMNS = 13;
|
||||||
|
|
||||||
|
// Reset initial state
|
||||||
|
arkanoid_state->initialDraw = false;
|
||||||
|
arkanoid_state->gameStarted = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void arkanoid_draw_callback(Canvas* const canvas, void* ctx) {
|
||||||
|
furi_assert(ctx);
|
||||||
|
ArkanoidState* arkanoid_state = ctx;
|
||||||
|
furi_mutex_acquire(arkanoid_state->mutex, FuriWaitForever);
|
||||||
|
|
||||||
|
//Initial level draw
|
||||||
|
if(!arkanoid_state->initialDraw) {
|
||||||
|
arkanoid_state->initialDraw = true;
|
||||||
|
|
||||||
|
// Set default font for text
|
||||||
|
canvas_set_font(canvas, FontSecondary);
|
||||||
|
|
||||||
|
//Draws the new level
|
||||||
|
reset_level(canvas, arkanoid_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Draws new bricks and resets their values
|
||||||
|
for(unsigned int row = 0; row < arkanoid_state->ROWS; row++) {
|
||||||
|
for(unsigned int column = 0; column < arkanoid_state->COLUMNS; column++) {
|
||||||
|
if(!arkanoid_state->brick_state.isHit[row][column]) {
|
||||||
|
canvas_draw_frame(canvas, 10 * column, 2 + 6 * row, 8, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(arkanoid_state->lives > 0) {
|
||||||
|
draw_paddle(canvas, arkanoid_state);
|
||||||
|
draw_ball(canvas, arkanoid_state);
|
||||||
|
draw_score(canvas, arkanoid_state);
|
||||||
|
draw_lives(canvas, arkanoid_state);
|
||||||
|
|
||||||
|
if(arkanoid_state->brickCount == arkanoid_state->ROWS * arkanoid_state->COLUMNS) {
|
||||||
|
arkanoid_state->level++;
|
||||||
|
reset_level(canvas, arkanoid_state);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reset_level(canvas, arkanoid_state);
|
||||||
|
arkanoid_state->initialDraw = false;
|
||||||
|
arkanoid_state->lives = 3;
|
||||||
|
arkanoid_state->score = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
furi_mutex_release(arkanoid_state->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void arkanoid_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
|
||||||
|
furi_assert(event_queue);
|
||||||
|
|
||||||
|
GameEvent event = {.type = EventTypeKey, .input = *input_event};
|
||||||
|
furi_message_queue_put(event_queue, &event, FuriWaitForever);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void arkanoid_update_timer_callback(FuriMessageQueue* event_queue) {
|
||||||
|
furi_assert(event_queue);
|
||||||
|
|
||||||
|
GameEvent event = {.type = EventTypeTick};
|
||||||
|
furi_message_queue_put(event_queue, &event, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t arkanoid_game_app(void* p) {
|
||||||
|
UNUSED(p);
|
||||||
|
int32_t return_code = 0;
|
||||||
|
|
||||||
|
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(GameEvent));
|
||||||
|
|
||||||
|
ArkanoidState* arkanoid_state = malloc(sizeof(ArkanoidState));
|
||||||
|
arkanoid_state_init(arkanoid_state);
|
||||||
|
|
||||||
|
arkanoid_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||||
|
if(!arkanoid_state->mutex) {
|
||||||
|
FURI_LOG_E(TAG, "Cannot create mutex\r\n");
|
||||||
|
return_code = 255;
|
||||||
|
goto free_and_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set system callbacks
|
||||||
|
ViewPort* view_port = view_port_alloc();
|
||||||
|
view_port_draw_callback_set(view_port, arkanoid_draw_callback, arkanoid_state);
|
||||||
|
view_port_input_callback_set(view_port, arkanoid_input_callback, event_queue);
|
||||||
|
|
||||||
|
FuriTimer* timer =
|
||||||
|
furi_timer_alloc(arkanoid_update_timer_callback, FuriTimerTypePeriodic, event_queue);
|
||||||
|
furi_timer_start(timer, furi_kernel_get_tick_frequency() / 22);
|
||||||
|
|
||||||
|
// Open GUI and register view_port
|
||||||
|
Gui* gui = furi_record_open(RECORD_GUI);
|
||||||
|
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||||
|
|
||||||
|
// Call dolphin deed on game start
|
||||||
|
dolphin_deed(DolphinDeedPluginGameStart);
|
||||||
|
|
||||||
|
GameEvent event;
|
||||||
|
for(bool processing = true; processing;) {
|
||||||
|
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
|
||||||
|
furi_mutex_acquire(arkanoid_state->mutex, FuriWaitForever);
|
||||||
|
|
||||||
|
if(event_status == FuriStatusOk) {
|
||||||
|
// Key events
|
||||||
|
if(event.type == EventTypeKey) {
|
||||||
|
if(event.input.type == InputTypePress || event.input.type == InputTypeLong ||
|
||||||
|
event.input.type == InputTypeRepeat) {
|
||||||
|
switch(event.input.key) {
|
||||||
|
case InputKeyBack:
|
||||||
|
processing = false;
|
||||||
|
break;
|
||||||
|
case InputKeyRight:
|
||||||
|
if(arkanoid_state->xPaddle < FLIPPER_LCD_WIDTH - 12) {
|
||||||
|
arkanoid_state->xPaddle += 8;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case InputKeyLeft:
|
||||||
|
if(arkanoid_state->xPaddle > 0) {
|
||||||
|
arkanoid_state->xPaddle -= 8;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case InputKeyUp:
|
||||||
|
if(arkanoid_state->speed < MAX_SPEED) {
|
||||||
|
arkanoid_state->speed++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case InputKeyDown:
|
||||||
|
if(arkanoid_state->speed > 1) {
|
||||||
|
arkanoid_state->speed--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case InputKeyOk:
|
||||||
|
if(arkanoid_state->gameStarted == false) {
|
||||||
|
//Release ball if FIRE pressed
|
||||||
|
arkanoid_state->ball_state.released = true;
|
||||||
|
|
||||||
|
//Apply random direction to ball on release
|
||||||
|
if(rand_range(0, 2) == 0) {
|
||||||
|
arkanoid_state->ball_state.dx = 1;
|
||||||
|
} else {
|
||||||
|
arkanoid_state->ball_state.dx = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Makes sure the ball heads upwards
|
||||||
|
arkanoid_state->ball_state.dy = -1;
|
||||||
|
//start the game flag
|
||||||
|
arkanoid_state->gameStarted = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
view_port_update(view_port);
|
||||||
|
furi_mutex_release(arkanoid_state->mutex);
|
||||||
|
}
|
||||||
|
furi_timer_free(timer);
|
||||||
|
view_port_enabled_set(view_port, false);
|
||||||
|
gui_remove_view_port(gui, view_port);
|
||||||
|
furi_record_close(RECORD_GUI);
|
||||||
|
furi_record_close(RECORD_NOTIFICATION);
|
||||||
|
view_port_free(view_port);
|
||||||
|
furi_mutex_free(arkanoid_state->mutex);
|
||||||
|
|
||||||
|
free_and_exit:
|
||||||
|
free(arkanoid_state);
|
||||||
|
furi_message_queue_free(event_queue);
|
||||||
|
|
||||||
|
return return_code;
|
||||||
|
}
|
||||||
17
applications/external/avr_isp_programmer/application.fam
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
App(
|
||||||
|
appid="avr_isp",
|
||||||
|
name="AVR Flasher",
|
||||||
|
apptype=FlipperAppType.EXTERNAL,
|
||||||
|
entry_point="avr_isp_app",
|
||||||
|
requires=["gui"],
|
||||||
|
stack_size=4 * 1024,
|
||||||
|
order=20,
|
||||||
|
fap_icon="avr_app_icon_10x10.png",
|
||||||
|
fap_category="GPIO",
|
||||||
|
fap_icon_assets="images",
|
||||||
|
fap_private_libs=[
|
||||||
|
Lib(
|
||||||
|
name="driver",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
BIN
applications/external/avr_isp_programmer/avr_app_icon_10x10.png
vendored
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
179
applications/external/avr_isp_programmer/avr_isp_app.c
vendored
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
#include "avr_isp_app_i.h"
|
||||||
|
|
||||||
|
static bool avr_isp_app_custom_event_callback(void* context, uint32_t event) {
|
||||||
|
furi_assert(context);
|
||||||
|
AvrIspApp* app = context;
|
||||||
|
return scene_manager_handle_custom_event(app->scene_manager, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool avr_isp_app_back_event_callback(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
AvrIspApp* app = context;
|
||||||
|
return scene_manager_handle_back_event(app->scene_manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void avr_isp_app_tick_event_callback(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
AvrIspApp* app = context;
|
||||||
|
scene_manager_handle_tick_event(app->scene_manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
AvrIspApp* avr_isp_app_alloc() {
|
||||||
|
AvrIspApp* app = malloc(sizeof(AvrIspApp));
|
||||||
|
|
||||||
|
app->file_path = furi_string_alloc();
|
||||||
|
furi_string_set(app->file_path, STORAGE_APP_DATA_PATH_PREFIX);
|
||||||
|
app->error = AvrIspErrorNoError;
|
||||||
|
|
||||||
|
// GUI
|
||||||
|
app->gui = furi_record_open(RECORD_GUI);
|
||||||
|
|
||||||
|
// View Dispatcher
|
||||||
|
app->view_dispatcher = view_dispatcher_alloc();
|
||||||
|
app->scene_manager = scene_manager_alloc(&avr_isp_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, avr_isp_app_custom_event_callback);
|
||||||
|
view_dispatcher_set_navigation_event_callback(
|
||||||
|
app->view_dispatcher, avr_isp_app_back_event_callback);
|
||||||
|
view_dispatcher_set_tick_event_callback(
|
||||||
|
app->view_dispatcher, avr_isp_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, AvrIspViewSubmenu, submenu_get_view(app->submenu));
|
||||||
|
|
||||||
|
// Widget
|
||||||
|
app->widget = widget_alloc();
|
||||||
|
view_dispatcher_add_view(app->view_dispatcher, AvrIspViewWidget, widget_get_view(app->widget));
|
||||||
|
|
||||||
|
// Text Input
|
||||||
|
app->text_input = text_input_alloc();
|
||||||
|
view_dispatcher_add_view(
|
||||||
|
app->view_dispatcher, AvrIspViewTextInput, text_input_get_view(app->text_input));
|
||||||
|
|
||||||
|
// Popup
|
||||||
|
app->popup = popup_alloc();
|
||||||
|
view_dispatcher_add_view(app->view_dispatcher, AvrIspViewPopup, popup_get_view(app->popup));
|
||||||
|
|
||||||
|
//Dialog
|
||||||
|
app->dialogs = furi_record_open(RECORD_DIALOGS);
|
||||||
|
|
||||||
|
// Programmer view
|
||||||
|
app->avr_isp_programmer_view = avr_isp_programmer_view_alloc();
|
||||||
|
view_dispatcher_add_view(
|
||||||
|
app->view_dispatcher,
|
||||||
|
AvrIspViewProgrammer,
|
||||||
|
avr_isp_programmer_view_get_view(app->avr_isp_programmer_view));
|
||||||
|
|
||||||
|
// Reader view
|
||||||
|
app->avr_isp_reader_view = avr_isp_reader_view_alloc();
|
||||||
|
view_dispatcher_add_view(
|
||||||
|
app->view_dispatcher,
|
||||||
|
AvrIspViewReader,
|
||||||
|
avr_isp_reader_view_get_view(app->avr_isp_reader_view));
|
||||||
|
|
||||||
|
// Writer view
|
||||||
|
app->avr_isp_writer_view = avr_isp_writer_view_alloc();
|
||||||
|
view_dispatcher_add_view(
|
||||||
|
app->view_dispatcher,
|
||||||
|
AvrIspViewWriter,
|
||||||
|
avr_isp_writer_view_get_view(app->avr_isp_writer_view));
|
||||||
|
|
||||||
|
// Chip detect view
|
||||||
|
app->avr_isp_chip_detect_view = avr_isp_chip_detect_view_alloc();
|
||||||
|
view_dispatcher_add_view(
|
||||||
|
app->view_dispatcher,
|
||||||
|
AvrIspViewChipDetect,
|
||||||
|
avr_isp_chip_detect_view_get_view(app->avr_isp_chip_detect_view));
|
||||||
|
|
||||||
|
// Enable 5v power, multiple attempts to avoid issues with power chip protection false triggering
|
||||||
|
uint8_t attempts = 0;
|
||||||
|
while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) {
|
||||||
|
furi_hal_power_enable_otg();
|
||||||
|
furi_delay_ms(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
scene_manager_next_scene(app->scene_manager, AvrIspSceneStart);
|
||||||
|
|
||||||
|
return app;
|
||||||
|
} //-V773
|
||||||
|
|
||||||
|
void avr_isp_app_free(AvrIspApp* app) {
|
||||||
|
furi_assert(app);
|
||||||
|
|
||||||
|
// Disable 5v power
|
||||||
|
if(furi_hal_power_is_otg_enabled()) {
|
||||||
|
furi_hal_power_disable_otg();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Submenu
|
||||||
|
view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewSubmenu);
|
||||||
|
submenu_free(app->submenu);
|
||||||
|
|
||||||
|
// Widget
|
||||||
|
view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewWidget);
|
||||||
|
widget_free(app->widget);
|
||||||
|
|
||||||
|
// TextInput
|
||||||
|
view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewTextInput);
|
||||||
|
text_input_free(app->text_input);
|
||||||
|
|
||||||
|
// Popup
|
||||||
|
view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewPopup);
|
||||||
|
popup_free(app->popup);
|
||||||
|
|
||||||
|
//Dialog
|
||||||
|
furi_record_close(RECORD_DIALOGS);
|
||||||
|
|
||||||
|
// Programmer view
|
||||||
|
view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewProgrammer);
|
||||||
|
avr_isp_programmer_view_free(app->avr_isp_programmer_view);
|
||||||
|
|
||||||
|
// Reader view
|
||||||
|
view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewReader);
|
||||||
|
avr_isp_reader_view_free(app->avr_isp_reader_view);
|
||||||
|
|
||||||
|
// Writer view
|
||||||
|
view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewWriter);
|
||||||
|
avr_isp_writer_view_free(app->avr_isp_writer_view);
|
||||||
|
|
||||||
|
// Chip detect view
|
||||||
|
view_dispatcher_remove_view(app->view_dispatcher, AvrIspViewChipDetect);
|
||||||
|
avr_isp_chip_detect_view_free(app->avr_isp_chip_detect_view);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// Path strings
|
||||||
|
furi_string_free(app->file_path);
|
||||||
|
|
||||||
|
free(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t avr_isp_app(void* p) {
|
||||||
|
UNUSED(p);
|
||||||
|
AvrIspApp* avr_isp_app = avr_isp_app_alloc();
|
||||||
|
|
||||||
|
view_dispatcher_run(avr_isp_app->view_dispatcher);
|
||||||
|
|
||||||
|
avr_isp_app_free(avr_isp_app);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
31
applications/external/avr_isp_programmer/avr_isp_app_i.c
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#include "avr_isp_app_i.h"
|
||||||
|
#include <lib/toolbox/path.h>
|
||||||
|
#include <flipper_format/flipper_format_i.h>
|
||||||
|
|
||||||
|
#define TAG "AvrIsp"
|
||||||
|
|
||||||
|
bool avr_isp_load_from_file(AvrIspApp* app) {
|
||||||
|
furi_assert(app);
|
||||||
|
|
||||||
|
FuriString* file_path = furi_string_alloc();
|
||||||
|
FuriString* file_name = furi_string_alloc();
|
||||||
|
|
||||||
|
DialogsFileBrowserOptions browser_options;
|
||||||
|
dialog_file_browser_set_basic_options(
|
||||||
|
&browser_options, AVR_ISP_APP_EXTENSION, &I_avr_app_icon_10x10);
|
||||||
|
browser_options.base_path = STORAGE_APP_DATA_PATH_PREFIX;
|
||||||
|
|
||||||
|
// Input events and views are managed by file_select
|
||||||
|
bool res = dialog_file_browser_show(app->dialogs, file_path, app->file_path, &browser_options);
|
||||||
|
|
||||||
|
if(res) {
|
||||||
|
path_extract_dirname(furi_string_get_cstr(file_path), app->file_path);
|
||||||
|
path_extract_filename(file_path, file_name, true);
|
||||||
|
strncpy(app->file_name_tmp, furi_string_get_cstr(file_name), AVR_ISP_MAX_LEN_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
furi_string_free(file_name);
|
||||||
|
furi_string_free(file_path);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
44
applications/external/avr_isp_programmer/avr_isp_app_i.h
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "helpers/avr_isp_types.h"
|
||||||
|
#include <avr_isp_icons.h>
|
||||||
|
|
||||||
|
#include "scenes/avr_isp_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 <notification/notification_messages.h>
|
||||||
|
#include <gui/modules/text_input.h>
|
||||||
|
#include <dialogs/dialogs.h>
|
||||||
|
#include <storage/storage.h>
|
||||||
|
#include <gui/modules/popup.h>
|
||||||
|
|
||||||
|
#include "views/avr_isp_view_programmer.h"
|
||||||
|
#include "views/avr_isp_view_reader.h"
|
||||||
|
#include "views/avr_isp_view_writer.h"
|
||||||
|
#include "views/avr_isp_view_chip_detect.h"
|
||||||
|
|
||||||
|
#define AVR_ISP_MAX_LEN_NAME 64
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Gui* gui;
|
||||||
|
ViewDispatcher* view_dispatcher;
|
||||||
|
SceneManager* scene_manager;
|
||||||
|
NotificationApp* notifications;
|
||||||
|
DialogsApp* dialogs;
|
||||||
|
Popup* popup;
|
||||||
|
Submenu* submenu;
|
||||||
|
Widget* widget;
|
||||||
|
TextInput* text_input;
|
||||||
|
FuriString* file_path;
|
||||||
|
char file_name_tmp[AVR_ISP_MAX_LEN_NAME];
|
||||||
|
AvrIspProgrammerView* avr_isp_programmer_view;
|
||||||
|
AvrIspReaderView* avr_isp_reader_view;
|
||||||
|
AvrIspWriterView* avr_isp_writer_view;
|
||||||
|
AvrIspChipDetectView* avr_isp_chip_detect_view;
|
||||||
|
AvrIspError error;
|
||||||
|
} AvrIspApp;
|
||||||
|
|
||||||
|
bool avr_isp_load_from_file(AvrIspApp* app);
|
||||||
496
applications/external/avr_isp_programmer/helpers/avr_isp.c
vendored
Normal file
@@ -0,0 +1,496 @@
|
|||||||
|
#include "avr_isp.h"
|
||||||
|
#include "../lib/driver/avr_isp_prog_cmd.h"
|
||||||
|
#include "../lib/driver/avr_isp_spi_sw.h"
|
||||||
|
|
||||||
|
#include <furi.h>
|
||||||
|
|
||||||
|
#define AVR_ISP_PROG_TX_RX_BUF_SIZE 320
|
||||||
|
#define TAG "AvrIsp"
|
||||||
|
|
||||||
|
struct AvrIsp {
|
||||||
|
AvrIspSpiSw* spi;
|
||||||
|
bool pmode;
|
||||||
|
AvrIspCallback callback;
|
||||||
|
void* context;
|
||||||
|
};
|
||||||
|
|
||||||
|
AvrIsp* avr_isp_alloc(void) {
|
||||||
|
AvrIsp* instance = malloc(sizeof(AvrIsp));
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void avr_isp_free(AvrIsp* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
if(instance->spi) avr_isp_end_pmode(instance);
|
||||||
|
free(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
void avr_isp_set_tx_callback(AvrIsp* instance, AvrIspCallback callback, void* context) {
|
||||||
|
furi_assert(instance);
|
||||||
|
furi_assert(context);
|
||||||
|
|
||||||
|
instance->callback = callback;
|
||||||
|
instance->context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t avr_isp_spi_transaction(
|
||||||
|
AvrIsp* instance,
|
||||||
|
uint8_t cmd,
|
||||||
|
uint8_t addr_hi,
|
||||||
|
uint8_t addr_lo,
|
||||||
|
uint8_t data) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
avr_isp_spi_sw_txrx(instance->spi, cmd);
|
||||||
|
avr_isp_spi_sw_txrx(instance->spi, addr_hi);
|
||||||
|
avr_isp_spi_sw_txrx(instance->spi, addr_lo);
|
||||||
|
return avr_isp_spi_sw_txrx(instance->spi, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool avr_isp_set_pmode(AvrIsp* instance, uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
uint8_t res = 0;
|
||||||
|
avr_isp_spi_sw_txrx(instance->spi, a);
|
||||||
|
avr_isp_spi_sw_txrx(instance->spi, b);
|
||||||
|
res = avr_isp_spi_sw_txrx(instance->spi, c);
|
||||||
|
avr_isp_spi_sw_txrx(instance->spi, d);
|
||||||
|
return res == 0x53;
|
||||||
|
}
|
||||||
|
|
||||||
|
void avr_isp_end_pmode(AvrIsp* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
if(instance->pmode) {
|
||||||
|
avr_isp_spi_sw_res_set(instance->spi, true);
|
||||||
|
// We're about to take the target out of reset
|
||||||
|
// so configure SPI pins as input
|
||||||
|
if(instance->spi) avr_isp_spi_sw_free(instance->spi);
|
||||||
|
instance->spi = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
instance->pmode = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool avr_isp_start_pmode(AvrIsp* instance, AvrIspSpiSwSpeed spi_speed) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
// Reset target before driving PIN_SCK or PIN_MOSI
|
||||||
|
|
||||||
|
// SPI.begin() will configure SS as output,
|
||||||
|
// so SPI master mode is selected.
|
||||||
|
// We have defined RESET as pin 10,
|
||||||
|
// which for many arduino's is not the SS pin.
|
||||||
|
// So we have to configure RESET as output here,
|
||||||
|
// (reset_target() first sets the correct level)
|
||||||
|
if(instance->spi) avr_isp_spi_sw_free(instance->spi);
|
||||||
|
instance->spi = avr_isp_spi_sw_init(spi_speed);
|
||||||
|
|
||||||
|
avr_isp_spi_sw_res_set(instance->spi, false);
|
||||||
|
// See avr datasheets, chapter "SERIAL_PRG Programming Algorithm":
|
||||||
|
|
||||||
|
// Pulse RESET after PIN_SCK is low:
|
||||||
|
avr_isp_spi_sw_sck_set(instance->spi, false);
|
||||||
|
|
||||||
|
// discharge PIN_SCK, value arbitrally chosen
|
||||||
|
furi_delay_ms(20);
|
||||||
|
avr_isp_spi_sw_res_set(instance->spi, true);
|
||||||
|
|
||||||
|
// Pulse must be minimum 2 target CPU speed cycles
|
||||||
|
// so 100 usec is ok for CPU speeds above 20KHz
|
||||||
|
furi_delay_ms(1);
|
||||||
|
|
||||||
|
avr_isp_spi_sw_res_set(instance->spi, false);
|
||||||
|
|
||||||
|
// Send the enable programming command:
|
||||||
|
// datasheet: must be > 20 msec
|
||||||
|
furi_delay_ms(50);
|
||||||
|
if(avr_isp_set_pmode(instance, AVR_ISP_SET_PMODE)) {
|
||||||
|
instance->pmode = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool avr_isp_auto_set_spi_speed_start_pmode(AvrIsp* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
AvrIspSpiSwSpeed spi_speed[] = {
|
||||||
|
AvrIspSpiSwSpeed1Mhz,
|
||||||
|
AvrIspSpiSwSpeed400Khz,
|
||||||
|
AvrIspSpiSwSpeed250Khz,
|
||||||
|
AvrIspSpiSwSpeed125Khz,
|
||||||
|
AvrIspSpiSwSpeed60Khz,
|
||||||
|
AvrIspSpiSwSpeed40Khz,
|
||||||
|
AvrIspSpiSwSpeed20Khz,
|
||||||
|
AvrIspSpiSwSpeed10Khz,
|
||||||
|
AvrIspSpiSwSpeed5Khz,
|
||||||
|
AvrIspSpiSwSpeed1Khz,
|
||||||
|
};
|
||||||
|
for(uint8_t i = 0; i < COUNT_OF(spi_speed); i++) {
|
||||||
|
if(avr_isp_start_pmode(instance, spi_speed[i])) {
|
||||||
|
AvrIspSignature sig = avr_isp_read_signature(instance);
|
||||||
|
AvrIspSignature sig_examination = avr_isp_read_signature(instance); //-V656
|
||||||
|
uint8_t y = 0;
|
||||||
|
while(y < 8) {
|
||||||
|
if(memcmp((uint8_t*)&sig, (uint8_t*)&sig_examination, sizeof(AvrIspSignature)) !=
|
||||||
|
0)
|
||||||
|
break;
|
||||||
|
sig_examination = avr_isp_read_signature(instance);
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
if(y == 8) {
|
||||||
|
if(spi_speed[i] > AvrIspSpiSwSpeed1Mhz) {
|
||||||
|
if(i < (COUNT_OF(spi_speed) - 1)) {
|
||||||
|
avr_isp_end_pmode(instance);
|
||||||
|
i++;
|
||||||
|
return avr_isp_start_pmode(instance, spi_speed[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(instance->spi) {
|
||||||
|
avr_isp_spi_sw_free(instance->spi);
|
||||||
|
instance->spi = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void avr_isp_commit(AvrIsp* instance, uint16_t addr, uint8_t data) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
avr_isp_spi_transaction(instance, AVR_ISP_COMMIT(addr));
|
||||||
|
/* polling flash */
|
||||||
|
if(data == 0xFF) {
|
||||||
|
furi_delay_ms(5);
|
||||||
|
} else {
|
||||||
|
/* polling flash */
|
||||||
|
uint32_t starttime = furi_get_tick();
|
||||||
|
while((furi_get_tick() - starttime) < 30) {
|
||||||
|
if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FLASH_HI(addr)) != 0xFF) {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t avr_isp_current_page(AvrIsp* instance, uint32_t addr, uint16_t page_size) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
uint16_t page = 0;
|
||||||
|
switch(page_size) {
|
||||||
|
case 32:
|
||||||
|
page = addr & 0xFFFFFFF0;
|
||||||
|
break;
|
||||||
|
case 64:
|
||||||
|
page = addr & 0xFFFFFFE0;
|
||||||
|
break;
|
||||||
|
case 128:
|
||||||
|
page = addr & 0xFFFFFFC0;
|
||||||
|
break;
|
||||||
|
case 256:
|
||||||
|
page = addr & 0xFFFFFF80;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
page = addr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool avr_isp_flash_write_pages(
|
||||||
|
AvrIsp* instance,
|
||||||
|
uint16_t addr,
|
||||||
|
uint16_t page_size,
|
||||||
|
uint8_t* data,
|
||||||
|
uint32_t data_size) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
size_t x = 0;
|
||||||
|
uint16_t page = avr_isp_current_page(instance, addr, page_size);
|
||||||
|
|
||||||
|
while(x < data_size) {
|
||||||
|
if(page != avr_isp_current_page(instance, addr, page_size)) {
|
||||||
|
avr_isp_commit(instance, page, data[x - 1]);
|
||||||
|
page = avr_isp_current_page(instance, addr, page_size);
|
||||||
|
}
|
||||||
|
avr_isp_spi_transaction(instance, AVR_ISP_WRITE_FLASH_LO(addr, data[x++]));
|
||||||
|
avr_isp_spi_transaction(instance, AVR_ISP_WRITE_FLASH_HI(addr, data[x++]));
|
||||||
|
addr++;
|
||||||
|
}
|
||||||
|
avr_isp_commit(instance, page, data[x - 1]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool avr_isp_erase_chip(AvrIsp* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
bool ret = false;
|
||||||
|
if(!instance->pmode) avr_isp_auto_set_spi_speed_start_pmode(instance);
|
||||||
|
if(instance->pmode) {
|
||||||
|
avr_isp_spi_transaction(instance, AVR_ISP_ERASE_CHIP);
|
||||||
|
furi_delay_ms(100);
|
||||||
|
avr_isp_end_pmode(instance);
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
avr_isp_eeprom_write(AvrIsp* instance, uint16_t addr, uint8_t* data, uint32_t data_size) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
for(uint16_t i = 0; i < data_size; i++) {
|
||||||
|
avr_isp_spi_transaction(instance, AVR_ISP_WRITE_EEPROM(addr, data[i]));
|
||||||
|
furi_delay_ms(10);
|
||||||
|
addr++;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool avr_isp_write_page(
|
||||||
|
AvrIsp* instance,
|
||||||
|
uint32_t mem_type,
|
||||||
|
uint32_t mem_size,
|
||||||
|
uint16_t addr,
|
||||||
|
uint16_t page_size,
|
||||||
|
uint8_t* data,
|
||||||
|
uint32_t data_size) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
bool ret = false;
|
||||||
|
switch(mem_type) {
|
||||||
|
case STK_SET_FLASH_TYPE:
|
||||||
|
if((addr + data_size / 2) <= mem_size) {
|
||||||
|
ret = avr_isp_flash_write_pages(instance, addr, page_size, data, data_size);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STK_SET_EEPROM_TYPE:
|
||||||
|
if((addr + data_size) <= mem_size) {
|
||||||
|
ret = avr_isp_eeprom_write(instance, addr, data, data_size);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
furi_crash(TAG " Incorrect mem type.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool avr_isp_flash_read_page(
|
||||||
|
AvrIsp* instance,
|
||||||
|
uint16_t addr,
|
||||||
|
uint16_t page_size,
|
||||||
|
uint8_t* data,
|
||||||
|
uint32_t data_size) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
if(page_size > data_size) return false;
|
||||||
|
for(uint16_t i = 0; i < page_size; i += 2) {
|
||||||
|
data[i] = avr_isp_spi_transaction(instance, AVR_ISP_READ_FLASH_LO(addr));
|
||||||
|
data[i + 1] = avr_isp_spi_transaction(instance, AVR_ISP_READ_FLASH_HI(addr));
|
||||||
|
addr++;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool avr_isp_eeprom_read_page(
|
||||||
|
AvrIsp* instance,
|
||||||
|
uint16_t addr,
|
||||||
|
uint16_t page_size,
|
||||||
|
uint8_t* data,
|
||||||
|
uint32_t data_size) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
if(page_size > data_size) return false;
|
||||||
|
for(uint16_t i = 0; i < page_size; i++) {
|
||||||
|
data[i] = avr_isp_spi_transaction(instance, AVR_ISP_READ_EEPROM(addr));
|
||||||
|
addr++;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool avr_isp_read_page(
|
||||||
|
AvrIsp* instance,
|
||||||
|
uint32_t mem_type,
|
||||||
|
uint16_t addr,
|
||||||
|
uint16_t page_size,
|
||||||
|
uint8_t* data,
|
||||||
|
uint32_t data_size) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
bool res = false;
|
||||||
|
if(mem_type == STK_SET_FLASH_TYPE)
|
||||||
|
res = avr_isp_flash_read_page(instance, addr, page_size, data, data_size);
|
||||||
|
if(mem_type == STK_SET_EEPROM_TYPE)
|
||||||
|
res = avr_isp_eeprom_read_page(instance, addr, page_size, data, data_size);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
AvrIspSignature avr_isp_read_signature(AvrIsp* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
AvrIspSignature signature;
|
||||||
|
signature.vendor = avr_isp_spi_transaction(instance, AVR_ISP_READ_VENDOR);
|
||||||
|
signature.part_family = avr_isp_spi_transaction(instance, AVR_ISP_READ_PART_FAMILY);
|
||||||
|
signature.part_number = avr_isp_spi_transaction(instance, AVR_ISP_READ_PART_NUMBER);
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t avr_isp_read_lock_byte(AvrIsp* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
uint8_t data = 0;
|
||||||
|
uint32_t starttime = furi_get_tick();
|
||||||
|
while((furi_get_tick() - starttime) < 300) {
|
||||||
|
data = avr_isp_spi_transaction(instance, AVR_ISP_READ_LOCK_BYTE);
|
||||||
|
if(avr_isp_spi_transaction(instance, AVR_ISP_READ_LOCK_BYTE) == data) {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
data = 0x00;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool avr_isp_write_lock_byte(AvrIsp* instance, uint8_t lock) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
bool ret = false;
|
||||||
|
if(avr_isp_read_lock_byte(instance) == lock) {
|
||||||
|
ret = true;
|
||||||
|
} else {
|
||||||
|
avr_isp_spi_transaction(instance, AVR_ISP_WRITE_LOCK_BYTE(lock));
|
||||||
|
/* polling lock byte */
|
||||||
|
uint32_t starttime = furi_get_tick();
|
||||||
|
while((furi_get_tick() - starttime) < 30) {
|
||||||
|
if(avr_isp_spi_transaction(instance, AVR_ISP_READ_LOCK_BYTE) == lock) {
|
||||||
|
ret = true;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t avr_isp_read_fuse_low(AvrIsp* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
uint8_t data = 0;
|
||||||
|
uint32_t starttime = furi_get_tick();
|
||||||
|
while((furi_get_tick() - starttime) < 300) {
|
||||||
|
data = avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_LOW);
|
||||||
|
if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_LOW) == data) {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
data = 0x00;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool avr_isp_write_fuse_low(AvrIsp* instance, uint8_t lfuse) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
bool ret = false;
|
||||||
|
if(avr_isp_read_fuse_low(instance) == lfuse) {
|
||||||
|
ret = true;
|
||||||
|
} else {
|
||||||
|
avr_isp_spi_transaction(instance, AVR_ISP_WRITE_FUSE_LOW(lfuse));
|
||||||
|
/* polling fuse */
|
||||||
|
uint32_t starttime = furi_get_tick();
|
||||||
|
while((furi_get_tick() - starttime) < 30) {
|
||||||
|
if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_LOW) == lfuse) {
|
||||||
|
ret = true;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t avr_isp_read_fuse_high(AvrIsp* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
uint8_t data = 0;
|
||||||
|
uint32_t starttime = furi_get_tick();
|
||||||
|
while((furi_get_tick() - starttime) < 300) {
|
||||||
|
data = avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_HIGH);
|
||||||
|
if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_HIGH) == data) {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
data = 0x00;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool avr_isp_write_fuse_high(AvrIsp* instance, uint8_t hfuse) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
bool ret = false;
|
||||||
|
if(avr_isp_read_fuse_high(instance) == hfuse) {
|
||||||
|
ret = true;
|
||||||
|
} else {
|
||||||
|
avr_isp_spi_transaction(instance, AVR_ISP_WRITE_FUSE_HIGH(hfuse));
|
||||||
|
/* polling fuse */
|
||||||
|
uint32_t starttime = furi_get_tick();
|
||||||
|
while((furi_get_tick() - starttime) < 30) {
|
||||||
|
if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_HIGH) == hfuse) {
|
||||||
|
ret = true;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t avr_isp_read_fuse_extended(AvrIsp* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
uint8_t data = 0;
|
||||||
|
uint32_t starttime = furi_get_tick();
|
||||||
|
while((furi_get_tick() - starttime) < 300) {
|
||||||
|
data = avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_EXTENDED);
|
||||||
|
if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_EXTENDED) == data) {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
data = 0x00;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool avr_isp_write_fuse_extended(AvrIsp* instance, uint8_t efuse) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
bool ret = false;
|
||||||
|
if(avr_isp_read_fuse_extended(instance) == efuse) {
|
||||||
|
ret = true;
|
||||||
|
} else {
|
||||||
|
avr_isp_spi_transaction(instance, AVR_ISP_WRITE_FUSE_EXTENDED(efuse));
|
||||||
|
/* polling fuse */
|
||||||
|
uint32_t starttime = furi_get_tick();
|
||||||
|
while((furi_get_tick() - starttime) < 30) {
|
||||||
|
if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_EXTENDED) == efuse) {
|
||||||
|
ret = true;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void avr_isp_write_extended_addr(AvrIsp* instance, uint8_t extended_addr) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
avr_isp_spi_transaction(instance, AVR_ISP_EXTENDED_ADDR(extended_addr));
|
||||||
|
furi_delay_ms(10);
|
||||||
|
}
|
||||||
70
applications/external/avr_isp_programmer/helpers/avr_isp.h
vendored
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <furi_hal.h>
|
||||||
|
|
||||||
|
typedef struct AvrIsp AvrIsp;
|
||||||
|
typedef void (*AvrIspCallback)(void* context);
|
||||||
|
|
||||||
|
struct AvrIspSignature {
|
||||||
|
uint8_t vendor;
|
||||||
|
uint8_t part_family;
|
||||||
|
uint8_t part_number;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct AvrIspSignature AvrIspSignature;
|
||||||
|
|
||||||
|
AvrIsp* avr_isp_alloc(void);
|
||||||
|
|
||||||
|
void avr_isp_free(AvrIsp* instance);
|
||||||
|
|
||||||
|
void avr_isp_set_tx_callback(AvrIsp* instance, AvrIspCallback callback, void* context);
|
||||||
|
|
||||||
|
bool avr_isp_auto_set_spi_speed_start_pmode(AvrIsp* instance);
|
||||||
|
|
||||||
|
AvrIspSignature avr_isp_read_signature(AvrIsp* instance);
|
||||||
|
|
||||||
|
void avr_isp_end_pmode(AvrIsp* instance);
|
||||||
|
|
||||||
|
bool avr_isp_erase_chip(AvrIsp* instance);
|
||||||
|
|
||||||
|
uint8_t avr_isp_spi_transaction(
|
||||||
|
AvrIsp* instance,
|
||||||
|
uint8_t cmd,
|
||||||
|
uint8_t addr_hi,
|
||||||
|
uint8_t addr_lo,
|
||||||
|
uint8_t data);
|
||||||
|
|
||||||
|
bool avr_isp_read_page(
|
||||||
|
AvrIsp* instance,
|
||||||
|
uint32_t memtype,
|
||||||
|
uint16_t addr,
|
||||||
|
uint16_t page_size,
|
||||||
|
uint8_t* data,
|
||||||
|
uint32_t data_size);
|
||||||
|
|
||||||
|
bool avr_isp_write_page(
|
||||||
|
AvrIsp* instance,
|
||||||
|
uint32_t mem_type,
|
||||||
|
uint32_t mem_size,
|
||||||
|
uint16_t addr,
|
||||||
|
uint16_t page_size,
|
||||||
|
uint8_t* data,
|
||||||
|
uint32_t data_size);
|
||||||
|
|
||||||
|
uint8_t avr_isp_read_lock_byte(AvrIsp* instance);
|
||||||
|
|
||||||
|
bool avr_isp_write_lock_byte(AvrIsp* instance, uint8_t lock);
|
||||||
|
|
||||||
|
uint8_t avr_isp_read_fuse_low(AvrIsp* instance);
|
||||||
|
|
||||||
|
bool avr_isp_write_fuse_low(AvrIsp* instance, uint8_t lfuse);
|
||||||
|
|
||||||
|
uint8_t avr_isp_read_fuse_high(AvrIsp* instance);
|
||||||
|
|
||||||
|
bool avr_isp_write_fuse_high(AvrIsp* instance, uint8_t hfuse);
|
||||||
|
|
||||||
|
uint8_t avr_isp_read_fuse_extended(AvrIsp* instance);
|
||||||
|
|
||||||
|
bool avr_isp_write_fuse_extended(AvrIsp* instance, uint8_t efuse);
|
||||||
|
|
||||||
|
void avr_isp_write_extended_addr(AvrIsp* instance, uint8_t extended_addr);
|
||||||
23
applications/external/avr_isp_programmer/helpers/avr_isp_event.h
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
//SubmenuIndex
|
||||||
|
SubmenuIndexAvrIspProgrammer = 10,
|
||||||
|
SubmenuIndexAvrIspReader,
|
||||||
|
SubmenuIndexAvrIspWriter,
|
||||||
|
SubmenuIndexAvrIsWiring,
|
||||||
|
SubmenuIndexAvrIspAbout,
|
||||||
|
|
||||||
|
//AvrIspCustomEvent
|
||||||
|
AvrIspCustomEventSceneChipDetectOk = 100,
|
||||||
|
AvrIspCustomEventSceneReadingOk,
|
||||||
|
AvrIspCustomEventSceneWritingOk,
|
||||||
|
AvrIspCustomEventSceneErrorVerification,
|
||||||
|
AvrIspCustomEventSceneErrorReading,
|
||||||
|
AvrIspCustomEventSceneErrorWriting,
|
||||||
|
AvrIspCustomEventSceneErrorWritingFuse,
|
||||||
|
AvrIspCustomEventSceneInputName,
|
||||||
|
AvrIspCustomEventSceneSuccess,
|
||||||
|
AvrIspCustomEventSceneExit,
|
||||||
|
AvrIspCustomEventSceneExitStartMenu,
|
||||||
|
} AvrIspCustomEvent;
|
||||||
32
applications/external/avr_isp_programmer/helpers/avr_isp_types.h
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <furi.h>
|
||||||
|
#include <furi_hal.h>
|
||||||
|
|
||||||
|
#define AVR_ISP_VERSION_APP "0.1"
|
||||||
|
#define AVR_ISP_DEVELOPED "SkorP"
|
||||||
|
#define AVR_ISP_GITHUB "https://github.com/flipperdevices/flipperzero-firmware"
|
||||||
|
|
||||||
|
#define AVR_ISP_APP_FILE_VERSION 1
|
||||||
|
#define AVR_ISP_APP_FILE_TYPE "Flipper Dump AVR"
|
||||||
|
#define AVR_ISP_APP_EXTENSION ".avr"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
//AvrIspViewVariableItemList,
|
||||||
|
AvrIspViewSubmenu,
|
||||||
|
AvrIspViewProgrammer,
|
||||||
|
AvrIspViewReader,
|
||||||
|
AvrIspViewWriter,
|
||||||
|
AvrIspViewWidget,
|
||||||
|
AvrIspViewPopup,
|
||||||
|
AvrIspViewTextInput,
|
||||||
|
AvrIspViewChipDetect,
|
||||||
|
} AvrIspView;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
AvrIspErrorNoError,
|
||||||
|
AvrIspErrorReading,
|
||||||
|
AvrIspErrorWriting,
|
||||||
|
AvrIspErrorVerification,
|
||||||
|
AvrIspErrorWritingFuse,
|
||||||
|
} AvrIspError;
|
||||||
266
applications/external/avr_isp_programmer/helpers/avr_isp_worker.c
vendored
Normal file
@@ -0,0 +1,266 @@
|
|||||||
|
#include "avr_isp_worker.h"
|
||||||
|
#include <furi_hal_pwm.h>
|
||||||
|
#include "../lib/driver/avr_isp_prog.h"
|
||||||
|
#include "../lib/driver/avr_isp_prog_cmd.h"
|
||||||
|
#include "../lib/driver/avr_isp_chip_arr.h"
|
||||||
|
|
||||||
|
#include <furi.h>
|
||||||
|
|
||||||
|
#define TAG "AvrIspWorker"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
AvrIspWorkerEvtStop = (1 << 0),
|
||||||
|
|
||||||
|
AvrIspWorkerEvtRx = (1 << 1),
|
||||||
|
AvrIspWorkerEvtTxCoplete = (1 << 2),
|
||||||
|
AvrIspWorkerEvtTx = (1 << 3),
|
||||||
|
AvrIspWorkerEvtState = (1 << 4),
|
||||||
|
|
||||||
|
//AvrIspWorkerEvtCfg = (1 << 5),
|
||||||
|
|
||||||
|
} AvrIspWorkerEvt;
|
||||||
|
|
||||||
|
struct AvrIspWorker {
|
||||||
|
FuriThread* thread;
|
||||||
|
volatile bool worker_running;
|
||||||
|
uint8_t connect_usb;
|
||||||
|
AvrIspWorkerCallback callback;
|
||||||
|
void* context;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define AVR_ISP_WORKER_PROG_ALL_EVENTS (AvrIspWorkerEvtStop)
|
||||||
|
#define AVR_ISP_WORKER_ALL_EVENTS \
|
||||||
|
(AvrIspWorkerEvtTx | AvrIspWorkerEvtTxCoplete | AvrIspWorkerEvtRx | AvrIspWorkerEvtStop | \
|
||||||
|
AvrIspWorkerEvtState)
|
||||||
|
|
||||||
|
//########################/* VCP CDC */#############################################
|
||||||
|
#include "usb_cdc.h"
|
||||||
|
#include <cli/cli_vcp.h>
|
||||||
|
#include <cli/cli.h>
|
||||||
|
#include <furi_hal_usb_cdc.h>
|
||||||
|
|
||||||
|
#define AVR_ISP_VCP_CDC_CH 1
|
||||||
|
#define AVR_ISP_VCP_CDC_PKT_LEN CDC_DATA_SZ
|
||||||
|
#define AVR_ISP_VCP_UART_RX_BUF_SIZE (AVR_ISP_VCP_CDC_PKT_LEN * 5)
|
||||||
|
|
||||||
|
static void vcp_on_cdc_tx_complete(void* context);
|
||||||
|
static void vcp_on_cdc_rx(void* context);
|
||||||
|
static void vcp_state_callback(void* context, uint8_t state);
|
||||||
|
static void vcp_on_cdc_control_line(void* context, uint8_t state);
|
||||||
|
static void vcp_on_line_config(void* context, struct usb_cdc_line_coding* config);
|
||||||
|
|
||||||
|
static const CdcCallbacks cdc_cb = {
|
||||||
|
vcp_on_cdc_tx_complete,
|
||||||
|
vcp_on_cdc_rx,
|
||||||
|
vcp_state_callback,
|
||||||
|
vcp_on_cdc_control_line,
|
||||||
|
vcp_on_line_config,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* VCP callbacks */
|
||||||
|
|
||||||
|
static void vcp_on_cdc_tx_complete(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
AvrIspWorker* instance = context;
|
||||||
|
furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerEvtTxCoplete);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vcp_on_cdc_rx(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
AvrIspWorker* instance = context;
|
||||||
|
furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerEvtRx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vcp_state_callback(void* context, uint8_t state) {
|
||||||
|
UNUSED(context);
|
||||||
|
|
||||||
|
AvrIspWorker* instance = context;
|
||||||
|
instance->connect_usb = state;
|
||||||
|
furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerEvtState);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vcp_on_cdc_control_line(void* context, uint8_t state) {
|
||||||
|
UNUSED(context);
|
||||||
|
UNUSED(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vcp_on_line_config(void* context, struct usb_cdc_line_coding* config) {
|
||||||
|
UNUSED(context);
|
||||||
|
UNUSED(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void avr_isp_worker_vcp_cdc_init(void* context) {
|
||||||
|
furi_hal_usb_unlock();
|
||||||
|
Cli* cli = furi_record_open(RECORD_CLI);
|
||||||
|
//close cli
|
||||||
|
cli_session_close(cli);
|
||||||
|
//disable callbacks VCP_CDC=0
|
||||||
|
furi_hal_cdc_set_callbacks(0, NULL, NULL);
|
||||||
|
//set 2 cdc
|
||||||
|
furi_check(furi_hal_usb_set_config(&usb_cdc_dual, NULL) == true);
|
||||||
|
//open cli VCP_CDC=0
|
||||||
|
cli_session_open(cli, &cli_vcp);
|
||||||
|
furi_record_close(RECORD_CLI);
|
||||||
|
|
||||||
|
furi_hal_cdc_set_callbacks(AVR_ISP_VCP_CDC_CH, (CdcCallbacks*)&cdc_cb, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void avr_isp_worker_vcp_cdc_deinit(void) {
|
||||||
|
//disable callbacks AVR_ISP_VCP_CDC_CH
|
||||||
|
furi_hal_cdc_set_callbacks(AVR_ISP_VCP_CDC_CH, NULL, NULL);
|
||||||
|
|
||||||
|
Cli* cli = furi_record_open(RECORD_CLI);
|
||||||
|
//close cli
|
||||||
|
cli_session_close(cli);
|
||||||
|
furi_hal_usb_unlock();
|
||||||
|
//set 1 cdc
|
||||||
|
furi_check(furi_hal_usb_set_config(&usb_cdc_single, NULL) == true);
|
||||||
|
//open cli VCP_CDC=0
|
||||||
|
cli_session_open(cli, &cli_vcp);
|
||||||
|
furi_record_close(RECORD_CLI);
|
||||||
|
}
|
||||||
|
|
||||||
|
//#################################################################################
|
||||||
|
|
||||||
|
static int32_t avr_isp_worker_prog_thread(void* context) {
|
||||||
|
AvrIspProg* prog = context;
|
||||||
|
FURI_LOG_D(TAG, "AvrIspProgWorker Start");
|
||||||
|
while(1) {
|
||||||
|
if(furi_thread_flags_get() & AvrIspWorkerEvtStop) break;
|
||||||
|
avr_isp_prog_avrisp(prog);
|
||||||
|
}
|
||||||
|
FURI_LOG_D(TAG, "AvrIspProgWorker Stop");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void avr_isp_worker_prog_tx_data(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
AvrIspWorker* instance = context;
|
||||||
|
furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerEvtTx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Worker thread
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @return exit code
|
||||||
|
*/
|
||||||
|
static int32_t avr_isp_worker_thread(void* context) {
|
||||||
|
AvrIspWorker* instance = context;
|
||||||
|
avr_isp_worker_vcp_cdc_init(instance);
|
||||||
|
|
||||||
|
/* start PWM on &gpio_ext_pa4 */
|
||||||
|
furi_hal_pwm_start(FuriHalPwmOutputIdLptim2PA4, 4000000, 50);
|
||||||
|
|
||||||
|
AvrIspProg* prog = avr_isp_prog_init();
|
||||||
|
avr_isp_prog_set_tx_callback(prog, avr_isp_worker_prog_tx_data, instance);
|
||||||
|
|
||||||
|
uint8_t buf[AVR_ISP_VCP_UART_RX_BUF_SIZE];
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
FuriThread* prog_thread =
|
||||||
|
furi_thread_alloc_ex("AvrIspProgWorker", 1024, avr_isp_worker_prog_thread, prog);
|
||||||
|
furi_thread_start(prog_thread);
|
||||||
|
|
||||||
|
FURI_LOG_D(TAG, "Start");
|
||||||
|
|
||||||
|
while(instance->worker_running) {
|
||||||
|
uint32_t events =
|
||||||
|
furi_thread_flags_wait(AVR_ISP_WORKER_ALL_EVENTS, FuriFlagWaitAny, FuriWaitForever);
|
||||||
|
|
||||||
|
if(events & AvrIspWorkerEvtRx) {
|
||||||
|
if(avr_isp_prog_spaces_rx(prog) >= AVR_ISP_VCP_CDC_PKT_LEN) {
|
||||||
|
len = furi_hal_cdc_receive(AVR_ISP_VCP_CDC_CH, buf, AVR_ISP_VCP_CDC_PKT_LEN);
|
||||||
|
// for(uint8_t i = 0; i < len; i++) {
|
||||||
|
// FURI_LOG_I(TAG, "--> %X", buf[i]);
|
||||||
|
// }
|
||||||
|
avr_isp_prog_rx(prog, buf, len);
|
||||||
|
} else {
|
||||||
|
furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerEvtRx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if((events & AvrIspWorkerEvtTxCoplete) || (events & AvrIspWorkerEvtTx)) {
|
||||||
|
len = avr_isp_prog_tx(prog, buf, AVR_ISP_VCP_CDC_PKT_LEN);
|
||||||
|
|
||||||
|
// for(uint8_t i = 0; i < len; i++) {
|
||||||
|
// FURI_LOG_I(TAG, "<-- %X", buf[i]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
if(len > 0) furi_hal_cdc_send(AVR_ISP_VCP_CDC_CH, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(events & AvrIspWorkerEvtStop) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(events & AvrIspWorkerEvtState) {
|
||||||
|
if(instance->callback)
|
||||||
|
instance->callback(instance->context, (bool)instance->connect_usb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FURI_LOG_D(TAG, "Stop");
|
||||||
|
|
||||||
|
furi_thread_flags_set(furi_thread_get_id(prog_thread), AvrIspWorkerEvtStop);
|
||||||
|
avr_isp_prog_exit(prog);
|
||||||
|
furi_delay_ms(10);
|
||||||
|
furi_thread_join(prog_thread);
|
||||||
|
furi_thread_free(prog_thread);
|
||||||
|
|
||||||
|
avr_isp_prog_free(prog);
|
||||||
|
furi_hal_pwm_stop(FuriHalPwmOutputIdLptim2PA4);
|
||||||
|
avr_isp_worker_vcp_cdc_deinit();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
AvrIspWorker* avr_isp_worker_alloc(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
UNUSED(context);
|
||||||
|
AvrIspWorker* instance = malloc(sizeof(AvrIspWorker));
|
||||||
|
|
||||||
|
instance->thread = furi_thread_alloc_ex("AvrIspWorker", 2048, avr_isp_worker_thread, instance);
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void avr_isp_worker_free(AvrIspWorker* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
furi_check(!instance->worker_running);
|
||||||
|
furi_thread_free(instance->thread);
|
||||||
|
free(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
void avr_isp_worker_set_callback(
|
||||||
|
AvrIspWorker* instance,
|
||||||
|
AvrIspWorkerCallback callback,
|
||||||
|
void* context) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
instance->callback = callback;
|
||||||
|
instance->context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
void avr_isp_worker_start(AvrIspWorker* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
furi_assert(!instance->worker_running);
|
||||||
|
|
||||||
|
instance->worker_running = true;
|
||||||
|
|
||||||
|
furi_thread_start(instance->thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
void avr_isp_worker_stop(AvrIspWorker* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
furi_assert(instance->worker_running);
|
||||||
|
|
||||||
|
instance->worker_running = false;
|
||||||
|
furi_thread_flags_set(furi_thread_get_id(instance->thread), AvrIspWorkerEvtStop);
|
||||||
|
|
||||||
|
furi_thread_join(instance->thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool avr_isp_worker_is_running(AvrIspWorker* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
return instance->worker_running;
|
||||||
|
}
|
||||||
49
applications/external/avr_isp_programmer/helpers/avr_isp_worker.h
vendored
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <furi_hal.h>
|
||||||
|
|
||||||
|
typedef struct AvrIspWorker AvrIspWorker;
|
||||||
|
|
||||||
|
typedef void (*AvrIspWorkerCallback)(void* context, bool connect_usb);
|
||||||
|
|
||||||
|
/** Allocate AvrIspWorker
|
||||||
|
*
|
||||||
|
* @param context AvrIsp* context
|
||||||
|
* @return AvrIspWorker*
|
||||||
|
*/
|
||||||
|
AvrIspWorker* avr_isp_worker_alloc(void* context);
|
||||||
|
|
||||||
|
/** Free AvrIspWorker
|
||||||
|
*
|
||||||
|
* @param instance AvrIspWorker instance
|
||||||
|
*/
|
||||||
|
void avr_isp_worker_free(AvrIspWorker* instance);
|
||||||
|
|
||||||
|
/** Callback AvrIspWorker
|
||||||
|
*
|
||||||
|
* @param instance AvrIspWorker instance
|
||||||
|
* @param callback AvrIspWorkerOverrunCallback callback
|
||||||
|
* @param context
|
||||||
|
*/
|
||||||
|
void avr_isp_worker_set_callback(
|
||||||
|
AvrIspWorker* instance,
|
||||||
|
AvrIspWorkerCallback callback,
|
||||||
|
void* context);
|
||||||
|
|
||||||
|
/** Start AvrIspWorker
|
||||||
|
*
|
||||||
|
* @param instance AvrIspWorker instance
|
||||||
|
*/
|
||||||
|
void avr_isp_worker_start(AvrIspWorker* instance);
|
||||||
|
|
||||||
|
/** Stop AvrIspWorker
|
||||||
|
*
|
||||||
|
* @param instance AvrIspWorker instance
|
||||||
|
*/
|
||||||
|
void avr_isp_worker_stop(AvrIspWorker* instance);
|
||||||
|
|
||||||
|
/** Check if worker is running
|
||||||
|
* @param instance AvrIspWorker instance
|
||||||
|
* @return bool - true if running
|
||||||
|
*/
|
||||||
|
bool avr_isp_worker_is_running(AvrIspWorker* instance);
|
||||||
1157
applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.c
vendored
Normal file
99
applications/external/avr_isp_programmer/helpers/avr_isp_worker_rw.h
vendored
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <furi_hal.h>
|
||||||
|
|
||||||
|
typedef struct AvrIspWorkerRW AvrIspWorkerRW;
|
||||||
|
|
||||||
|
typedef void (*AvrIspWorkerRWCallback)(
|
||||||
|
void* context,
|
||||||
|
const char* name,
|
||||||
|
bool detect_chip,
|
||||||
|
uint32_t flash_size);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
AvrIspWorkerRWStatusILDE = 0,
|
||||||
|
AvrIspWorkerRWStatusEndReading = 1,
|
||||||
|
AvrIspWorkerRWStatusEndVerification = 2,
|
||||||
|
AvrIspWorkerRWStatusEndWriting = 3,
|
||||||
|
AvrIspWorkerRWStatusEndWritingFuse = 4,
|
||||||
|
|
||||||
|
AvrIspWorkerRWStatusErrorReading = (-1),
|
||||||
|
AvrIspWorkerRWStatusErrorVerification = (-2),
|
||||||
|
AvrIspWorkerRWStatusErrorWriting = (-3),
|
||||||
|
AvrIspWorkerRWStatusErrorWritingFuse = (-4),
|
||||||
|
|
||||||
|
AvrIspWorkerRWStatusReserved = 0x7FFFFFFF, ///< Prevents enum down-size compiler optimization.
|
||||||
|
} AvrIspWorkerRWStatus;
|
||||||
|
|
||||||
|
typedef void (*AvrIspWorkerRWStatusCallback)(void* context, AvrIspWorkerRWStatus status);
|
||||||
|
|
||||||
|
AvrIspWorkerRW* avr_isp_worker_rw_alloc(void* context);
|
||||||
|
|
||||||
|
void avr_isp_worker_rw_free(AvrIspWorkerRW* instance);
|
||||||
|
|
||||||
|
void avr_isp_worker_rw_start(AvrIspWorkerRW* instance);
|
||||||
|
|
||||||
|
void avr_isp_worker_rw_stop(AvrIspWorkerRW* instance);
|
||||||
|
|
||||||
|
bool avr_isp_worker_rw_is_running(AvrIspWorkerRW* instance);
|
||||||
|
|
||||||
|
void avr_isp_worker_rw_set_callback(
|
||||||
|
AvrIspWorkerRW* instance,
|
||||||
|
AvrIspWorkerRWCallback callback,
|
||||||
|
void* context);
|
||||||
|
|
||||||
|
void avr_isp_worker_rw_set_callback_status(
|
||||||
|
AvrIspWorkerRW* instance,
|
||||||
|
AvrIspWorkerRWStatusCallback callback_status,
|
||||||
|
void* context_status);
|
||||||
|
|
||||||
|
bool avr_isp_worker_rw_detect_chip(AvrIspWorkerRW* instance);
|
||||||
|
|
||||||
|
float avr_isp_worker_rw_get_progress_flash(AvrIspWorkerRW* instance);
|
||||||
|
|
||||||
|
float avr_isp_worker_rw_get_progress_eeprom(AvrIspWorkerRW* instance);
|
||||||
|
|
||||||
|
bool avr_isp_worker_rw_read_dump(
|
||||||
|
AvrIspWorkerRW* instance,
|
||||||
|
const char* file_path,
|
||||||
|
const char* file_name);
|
||||||
|
|
||||||
|
void avr_isp_worker_rw_read_dump_start(
|
||||||
|
AvrIspWorkerRW* instance,
|
||||||
|
const char* file_path,
|
||||||
|
const char* file_name);
|
||||||
|
|
||||||
|
bool avr_isp_worker_rw_verification(
|
||||||
|
AvrIspWorkerRW* instance,
|
||||||
|
const char* file_path,
|
||||||
|
const char* file_name);
|
||||||
|
|
||||||
|
void avr_isp_worker_rw_verification_start(
|
||||||
|
AvrIspWorkerRW* instance,
|
||||||
|
const char* file_path,
|
||||||
|
const char* file_name);
|
||||||
|
|
||||||
|
bool avr_isp_worker_rw_check_hex(
|
||||||
|
AvrIspWorkerRW* instance,
|
||||||
|
const char* file_path,
|
||||||
|
const char* file_name);
|
||||||
|
|
||||||
|
bool avr_isp_worker_rw_write_dump(
|
||||||
|
AvrIspWorkerRW* instance,
|
||||||
|
const char* file_path,
|
||||||
|
const char* file_name);
|
||||||
|
|
||||||
|
void avr_isp_worker_rw_write_dump_start(
|
||||||
|
AvrIspWorkerRW* instance,
|
||||||
|
const char* file_path,
|
||||||
|
const char* file_name);
|
||||||
|
|
||||||
|
bool avr_isp_worker_rw_write_fuse(
|
||||||
|
AvrIspWorkerRW* instance,
|
||||||
|
const char* file_path,
|
||||||
|
const char* file_name);
|
||||||
|
|
||||||
|
void avr_isp_worker_rw_write_fuse_start(
|
||||||
|
AvrIspWorkerRW* instance,
|
||||||
|
const char* file_path,
|
||||||
|
const char* file_name);
|
||||||
321
applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.c
vendored
Normal file
@@ -0,0 +1,321 @@
|
|||||||
|
#include "flipper_i32hex_file.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <storage/storage.h>
|
||||||
|
#include <toolbox/stream/stream.h>
|
||||||
|
#include <toolbox/stream/file_stream.h>
|
||||||
|
#include <toolbox/hex.h>
|
||||||
|
|
||||||
|
//https://en.wikipedia.org/wiki/Intel_HEX
|
||||||
|
|
||||||
|
#define TAG "FlipperI32HexFile"
|
||||||
|
|
||||||
|
#define COUNT_BYTE_PAYLOAD 32 //how much payload will be used
|
||||||
|
|
||||||
|
#define I32HEX_TYPE_DATA 0x00
|
||||||
|
#define I32HEX_TYPE_END_OF_FILE 0x01
|
||||||
|
#define I32HEX_TYPE_EXT_LINEAR_ADDR 0x04
|
||||||
|
#define I32HEX_TYPE_START_LINEAR_ADDR 0x05
|
||||||
|
|
||||||
|
struct FlipperI32HexFile {
|
||||||
|
uint32_t addr;
|
||||||
|
uint32_t addr_last;
|
||||||
|
Storage* storage;
|
||||||
|
Stream* stream;
|
||||||
|
FuriString* str_data;
|
||||||
|
FlipperI32HexFileStatus file_open;
|
||||||
|
};
|
||||||
|
|
||||||
|
FlipperI32HexFile* flipper_i32hex_file_open_write(const char* name, uint32_t start_addr) {
|
||||||
|
furi_assert(name);
|
||||||
|
|
||||||
|
FlipperI32HexFile* instance = malloc(sizeof(FlipperI32HexFile));
|
||||||
|
instance->addr = start_addr;
|
||||||
|
instance->addr_last = 0;
|
||||||
|
instance->storage = furi_record_open(RECORD_STORAGE);
|
||||||
|
instance->stream = file_stream_alloc(instance->storage);
|
||||||
|
|
||||||
|
if(file_stream_open(instance->stream, name, FSAM_WRITE, FSOM_CREATE_ALWAYS)) {
|
||||||
|
instance->file_open = FlipperI32HexFileStatusOpenFileWrite;
|
||||||
|
FURI_LOG_D(TAG, "Open write file %s", name);
|
||||||
|
} else {
|
||||||
|
FURI_LOG_E(TAG, "Failed to open file %s", name);
|
||||||
|
instance->file_open = FlipperI32HexFileStatusErrorNoOpenFile;
|
||||||
|
}
|
||||||
|
instance->str_data = furi_string_alloc(instance->storage);
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
FlipperI32HexFile* flipper_i32hex_file_open_read(const char* name) {
|
||||||
|
furi_assert(name);
|
||||||
|
|
||||||
|
FlipperI32HexFile* instance = malloc(sizeof(FlipperI32HexFile));
|
||||||
|
instance->addr = 0;
|
||||||
|
instance->addr_last = 0;
|
||||||
|
instance->storage = furi_record_open(RECORD_STORAGE);
|
||||||
|
instance->stream = file_stream_alloc(instance->storage);
|
||||||
|
|
||||||
|
if(file_stream_open(instance->stream, name, FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||||
|
instance->file_open = FlipperI32HexFileStatusOpenFileRead;
|
||||||
|
FURI_LOG_D(TAG, "Open read file %s", name);
|
||||||
|
} else {
|
||||||
|
FURI_LOG_E(TAG, "Failed to open file %s", name);
|
||||||
|
instance->file_open = FlipperI32HexFileStatusErrorNoOpenFile;
|
||||||
|
}
|
||||||
|
instance->str_data = furi_string_alloc(instance->storage);
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void flipper_i32hex_file_close(FlipperI32HexFile* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
furi_string_free(instance->str_data);
|
||||||
|
file_stream_close(instance->stream);
|
||||||
|
stream_free(instance->stream);
|
||||||
|
furi_record_close(RECORD_STORAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
FlipperI32HexFileRet flipper_i32hex_file_bin_to_i32hex_set_data(
|
||||||
|
FlipperI32HexFile* instance,
|
||||||
|
uint8_t* data,
|
||||||
|
uint32_t data_size) {
|
||||||
|
furi_assert(instance);
|
||||||
|
furi_assert(data);
|
||||||
|
|
||||||
|
FlipperI32HexFileRet ret = {.status = FlipperI32HexFileStatusOK, .data_size = 0};
|
||||||
|
if(instance->file_open != FlipperI32HexFileStatusOpenFileWrite) {
|
||||||
|
ret.status = FlipperI32HexFileStatusErrorFileWrite;
|
||||||
|
}
|
||||||
|
uint8_t count_byte = 0;
|
||||||
|
uint32_t ind = 0;
|
||||||
|
uint8_t crc = 0;
|
||||||
|
|
||||||
|
furi_string_reset(instance->str_data);
|
||||||
|
|
||||||
|
if((instance->addr_last & 0xFF0000) < (instance->addr & 0xFF0000)) {
|
||||||
|
crc = 0x02 + 0x04 + ((instance->addr >> 24) & 0xFF) + ((instance->addr >> 16) & 0xFF);
|
||||||
|
crc = 0x01 + ~crc;
|
||||||
|
//I32HEX_TYPE_EXT_LINEAR_ADDR
|
||||||
|
furi_string_cat_printf(
|
||||||
|
instance->str_data, ":02000004%04lX%02X\r\n", (instance->addr >> 16), crc);
|
||||||
|
instance->addr_last = instance->addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(ind < data_size) {
|
||||||
|
if((ind + COUNT_BYTE_PAYLOAD) > data_size) {
|
||||||
|
count_byte = data_size - ind;
|
||||||
|
} else {
|
||||||
|
count_byte = COUNT_BYTE_PAYLOAD;
|
||||||
|
}
|
||||||
|
//I32HEX_TYPE_DATA
|
||||||
|
furi_string_cat_printf(
|
||||||
|
instance->str_data, ":%02X%04lX00", count_byte, (instance->addr & 0xFFFF));
|
||||||
|
crc = count_byte + ((instance->addr >> 8) & 0xFF) + (instance->addr & 0xFF);
|
||||||
|
|
||||||
|
for(uint32_t i = 0; i < count_byte; i++) {
|
||||||
|
furi_string_cat_printf(instance->str_data, "%02X", *data);
|
||||||
|
crc += *data++;
|
||||||
|
}
|
||||||
|
crc = 0x01 + ~crc;
|
||||||
|
furi_string_cat_printf(instance->str_data, "%02X\r\n", crc);
|
||||||
|
|
||||||
|
ind += count_byte;
|
||||||
|
instance->addr += count_byte;
|
||||||
|
}
|
||||||
|
if(instance->file_open) stream_write_string(instance->stream, instance->str_data);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
FlipperI32HexFileRet flipper_i32hex_file_bin_to_i32hex_set_end_line(FlipperI32HexFile* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
FlipperI32HexFileRet ret = {.status = FlipperI32HexFileStatusOK, .data_size = 0};
|
||||||
|
if(instance->file_open != FlipperI32HexFileStatusOpenFileWrite) {
|
||||||
|
ret.status = FlipperI32HexFileStatusErrorFileWrite;
|
||||||
|
}
|
||||||
|
furi_string_reset(instance->str_data);
|
||||||
|
//I32HEX_TYPE_END_OF_FILE
|
||||||
|
furi_string_cat_printf(instance->str_data, ":00000001FF\r\n");
|
||||||
|
if(instance->file_open) stream_write_string(instance->stream, instance->str_data);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void flipper_i32hex_file_bin_to_i32hex_set_addr(FlipperI32HexFile* instance, uint32_t addr) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
instance->addr = addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* flipper_i32hex_file_get_string(FlipperI32HexFile* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
return furi_string_get_cstr(instance->str_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static FlipperI32HexFileRet flipper_i32hex_file_parse_line(
|
||||||
|
FlipperI32HexFile* instance,
|
||||||
|
const char* str,
|
||||||
|
uint8_t* data,
|
||||||
|
uint32_t data_size) {
|
||||||
|
furi_assert(instance);
|
||||||
|
furi_assert(data);
|
||||||
|
|
||||||
|
char* str1;
|
||||||
|
uint32_t data_wrire_ind = 0;
|
||||||
|
uint32_t data_len = 0;
|
||||||
|
FlipperI32HexFileRet ret = {.status = FlipperI32HexFileStatusErrorData, .data_size = 0};
|
||||||
|
|
||||||
|
//Search for start of data I32HEX
|
||||||
|
str1 = strstr(str, ":");
|
||||||
|
do {
|
||||||
|
if(str1 == NULL) {
|
||||||
|
ret.status = FlipperI32HexFileStatusErrorData;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
str1++;
|
||||||
|
if(!hex_char_to_uint8(*str1, str1[1], data + data_wrire_ind)) {
|
||||||
|
ret.status = FlipperI32HexFileStatusErrorData;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
str1++;
|
||||||
|
if(++data_wrire_ind > data_size) {
|
||||||
|
ret.status = FlipperI32HexFileStatusErrorOverflow;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
data_len = 5 + data[0]; // +5 bytes per header and crc
|
||||||
|
while(data_len > data_wrire_ind) {
|
||||||
|
str1++;
|
||||||
|
if(!hex_char_to_uint8(*str1, str1[1], data + data_wrire_ind)) {
|
||||||
|
ret.status = FlipperI32HexFileStatusErrorData;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
str1++;
|
||||||
|
if(++data_wrire_ind > data_size) {
|
||||||
|
ret.status = FlipperI32HexFileStatusErrorOverflow;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret.status = FlipperI32HexFileStatusOK;
|
||||||
|
ret.data_size = data_wrire_ind;
|
||||||
|
|
||||||
|
} while(0);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool flipper_i32hex_file_check_data(uint8_t* data, uint32_t data_size) {
|
||||||
|
furi_assert(data);
|
||||||
|
|
||||||
|
uint8_t crc = 0;
|
||||||
|
uint32_t data_read_ind = 0;
|
||||||
|
if(data[0] > data_size) return false;
|
||||||
|
while(data_read_ind < data_size - 1) {
|
||||||
|
crc += data[data_read_ind++];
|
||||||
|
}
|
||||||
|
return data[data_size - 1] == ((1 + ~crc) & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
static FlipperI32HexFileRet flipper_i32hex_file_parse(
|
||||||
|
FlipperI32HexFile* instance,
|
||||||
|
const char* str,
|
||||||
|
uint8_t* data,
|
||||||
|
uint32_t data_size) {
|
||||||
|
furi_assert(instance);
|
||||||
|
furi_assert(data);
|
||||||
|
|
||||||
|
FlipperI32HexFileRet ret = flipper_i32hex_file_parse_line(instance, str, data, data_size);
|
||||||
|
|
||||||
|
if((ret.status == FlipperI32HexFileStatusOK) && (ret.data_size > 4)) {
|
||||||
|
switch(data[3]) {
|
||||||
|
case I32HEX_TYPE_DATA:
|
||||||
|
if(flipper_i32hex_file_check_data(data, ret.data_size)) {
|
||||||
|
ret.data_size -= 5;
|
||||||
|
memcpy(data, data + 4, ret.data_size);
|
||||||
|
ret.status = FlipperI32HexFileStatusData;
|
||||||
|
} else {
|
||||||
|
ret.status = FlipperI32HexFileStatusErrorCrc;
|
||||||
|
ret.data_size = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case I32HEX_TYPE_END_OF_FILE:
|
||||||
|
if(flipper_i32hex_file_check_data(data, ret.data_size)) {
|
||||||
|
ret.status = FlipperI32HexFileStatusEofFile;
|
||||||
|
ret.data_size = 0;
|
||||||
|
} else {
|
||||||
|
ret.status = FlipperI32HexFileStatusErrorCrc;
|
||||||
|
ret.data_size = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case I32HEX_TYPE_EXT_LINEAR_ADDR:
|
||||||
|
if(flipper_i32hex_file_check_data(data, ret.data_size)) {
|
||||||
|
data[0] = data[4];
|
||||||
|
data[1] = data[5];
|
||||||
|
data[3] = 0;
|
||||||
|
data[4] = 0;
|
||||||
|
ret.status = FlipperI32HexFileStatusUdateAddr;
|
||||||
|
ret.data_size = 4;
|
||||||
|
} else {
|
||||||
|
ret.status = FlipperI32HexFileStatusErrorCrc;
|
||||||
|
ret.data_size = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case I32HEX_TYPE_START_LINEAR_ADDR:
|
||||||
|
ret.status = FlipperI32HexFileStatusErrorUnsupportedCommand;
|
||||||
|
ret.data_size = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret.status = FlipperI32HexFileStatusErrorUnsupportedCommand;
|
||||||
|
ret.data_size = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ret.status = FlipperI32HexFileStatusErrorData;
|
||||||
|
ret.data_size = 0;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool flipper_i32hex_file_check(FlipperI32HexFile* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
uint32_t data_size = 280;
|
||||||
|
uint8_t data[280] = {0};
|
||||||
|
bool ret = true;
|
||||||
|
|
||||||
|
if(instance->file_open != FlipperI32HexFileStatusOpenFileRead) {
|
||||||
|
FURI_LOG_E(TAG, "File is not open");
|
||||||
|
ret = false;
|
||||||
|
} else {
|
||||||
|
stream_rewind(instance->stream);
|
||||||
|
|
||||||
|
while(stream_read_line(instance->stream, instance->str_data)) {
|
||||||
|
FlipperI32HexFileRet parse_ret = flipper_i32hex_file_parse(
|
||||||
|
instance, furi_string_get_cstr(instance->str_data), data, data_size);
|
||||||
|
|
||||||
|
if(parse_ret.status < 0) {
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stream_rewind(instance->stream);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
FlipperI32HexFileRet flipper_i32hex_file_i32hex_to_bin_get_data(
|
||||||
|
FlipperI32HexFile* instance,
|
||||||
|
uint8_t* data,
|
||||||
|
uint32_t data_size) {
|
||||||
|
furi_assert(instance);
|
||||||
|
furi_assert(data);
|
||||||
|
|
||||||
|
FlipperI32HexFileRet ret = {.status = FlipperI32HexFileStatusOK, .data_size = 0};
|
||||||
|
if(instance->file_open != FlipperI32HexFileStatusOpenFileRead) {
|
||||||
|
ret.status = FlipperI32HexFileStatusErrorFileRead;
|
||||||
|
} else {
|
||||||
|
stream_read_line(instance->stream, instance->str_data);
|
||||||
|
ret = flipper_i32hex_file_parse(
|
||||||
|
instance, furi_string_get_cstr(instance->str_data), data, data_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
55
applications/external/avr_isp_programmer/helpers/flipper_i32hex_file.h
vendored
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <furi_hal.h>
|
||||||
|
|
||||||
|
typedef struct FlipperI32HexFile FlipperI32HexFile;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FlipperI32HexFileStatusOK = 0,
|
||||||
|
FlipperI32HexFileStatusData = 2,
|
||||||
|
FlipperI32HexFileStatusUdateAddr = 3,
|
||||||
|
FlipperI32HexFileStatusEofFile = 4,
|
||||||
|
FlipperI32HexFileStatusOpenFileWrite = 5,
|
||||||
|
FlipperI32HexFileStatusOpenFileRead = 6,
|
||||||
|
|
||||||
|
// Errors
|
||||||
|
FlipperI32HexFileStatusErrorCrc = (-1),
|
||||||
|
FlipperI32HexFileStatusErrorOverflow = (-2),
|
||||||
|
FlipperI32HexFileStatusErrorData = (-3),
|
||||||
|
FlipperI32HexFileStatusErrorUnsupportedCommand = (-4),
|
||||||
|
FlipperI32HexFileStatusErrorNoOpenFile = (-5),
|
||||||
|
FlipperI32HexFileStatusErrorFileWrite = (-6),
|
||||||
|
FlipperI32HexFileStatusErrorFileRead = (-7),
|
||||||
|
|
||||||
|
FlipperI32HexFileStatusReserved =
|
||||||
|
0x7FFFFFFF, ///< Prevents enum down-size compiler optimization.
|
||||||
|
} FlipperI32HexFileStatus;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
FlipperI32HexFileStatus status;
|
||||||
|
uint32_t data_size;
|
||||||
|
} FlipperI32HexFileRet;
|
||||||
|
|
||||||
|
FlipperI32HexFile* flipper_i32hex_file_open_write(const char* name, uint32_t start_addr);
|
||||||
|
|
||||||
|
FlipperI32HexFile* flipper_i32hex_file_open_read(const char* name);
|
||||||
|
|
||||||
|
void flipper_i32hex_file_close(FlipperI32HexFile* instance);
|
||||||
|
|
||||||
|
FlipperI32HexFileRet flipper_i32hex_file_bin_to_i32hex_set_data(
|
||||||
|
FlipperI32HexFile* instance,
|
||||||
|
uint8_t* data,
|
||||||
|
uint32_t data_size);
|
||||||
|
|
||||||
|
FlipperI32HexFileRet flipper_i32hex_file_bin_to_i32hex_set_end_line(FlipperI32HexFile* instance);
|
||||||
|
|
||||||
|
const char* flipper_i32hex_file_get_string(FlipperI32HexFile* instance);
|
||||||
|
|
||||||
|
void flipper_i32hex_file_bin_to_i32hex_set_addr(FlipperI32HexFile* instance, uint32_t addr);
|
||||||
|
|
||||||
|
bool flipper_i32hex_file_check(FlipperI32HexFile* instance);
|
||||||
|
|
||||||
|
FlipperI32HexFileRet flipper_i32hex_file_i32hex_to_bin_get_data(
|
||||||
|
FlipperI32HexFile* instance,
|
||||||
|
uint8_t* data,
|
||||||
|
uint32_t data_size);
|
||||||
BIN
applications/external/avr_isp_programmer/images/avr_app_icon_10x10.png
vendored
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
applications/external/avr_isp_programmer/images/avr_wiring.png
vendored
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
applications/external/avr_isp_programmer/images/chif_not_found_83x37.png
vendored
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
applications/external/avr_isp_programmer/images/chip_error_70x22.png
vendored
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
applications/external/avr_isp_programmer/images/chip_long_70x22.png
vendored
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
applications/external/avr_isp_programmer/images/chip_not_found_83x37.png
vendored
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
applications/external/avr_isp_programmer/images/dolphin_nice_96x59.png
vendored
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
applications/external/avr_isp_programmer/images/isp_active_128x53.png
vendored
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
applications/external/avr_isp_programmer/images/link_waiting_77x56.png
vendored
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
386
applications/external/avr_isp_programmer/lib/driver/avr_isp_chip_arr.c
vendored
Normal file
@@ -0,0 +1,386 @@
|
|||||||
|
#include "avr_isp_chip_arr.h"
|
||||||
|
|
||||||
|
#include <furi.h>
|
||||||
|
|
||||||
|
//https://github.com/avrdudes/avrdude/blob/master/src/avrintel.c
|
||||||
|
|
||||||
|
const AvrIspChipArr avr_isp_chip_arr[] = { // Value of -1 typically means unknown
|
||||||
|
//{mcu_name, mcuid, family, {sig, na, ture}, flstart, flsize, pgsiz, nb, bootsz, eestart, eesize, ep, rambeg, ramsiz, nf, nl, ni}, // Source
|
||||||
|
{"ATtiny4", 0, F_AVR8L, {0x1E, 0x8F, 0x0A}, 0, 0x00200, 0x010, 0, 0, 0, 0, 0, 0x0040, 0x0020, 1, 1, 10}, // atdf, avr-gcc 12.2.0, avrdude, boot size (manual)
|
||||||
|
{"ATtiny5", 1, F_AVR8L, {0x1E, 0x8F, 0x09}, 0, 0x00200, 0x010, 0, 0, 0, 0, 0, 0x0040, 0x0020, 1, 1, 11}, // atdf, avr-gcc 12.2.0, avrdude, boot size (manual)
|
||||||
|
{"ATtiny9", 2, F_AVR8L, {0x1E, 0x90, 0x08}, 0, 0x00400, 0x010, 0, 0, 0, 0, 0, 0x0040, 0x0020, 1, 1, 10}, // atdf, avr-gcc 12.2.0, avrdude, boot size (manual)
|
||||||
|
{"ATtiny10", 3, F_AVR8L, {0x1E, 0x90, 0x03}, 0, 0x00400, 0x010, 0, 0, 0, 0, 0, 0x0040, 0x0020, 1, 1, 11}, // atdf, avr-gcc 12.2.0, avrdude, boot size (manual)
|
||||||
|
{"ATtiny20", 4, F_AVR8L, {0x1E, 0x91, 0x0F}, 0, 0x00800, 0x020, 0, 0, 0, 0, 0, 0x0040, 0x0080, 1, 1, 17}, // atdf, avr-gcc 12.2.0, avrdude, boot size (manual)
|
||||||
|
{"ATtiny40", 5, F_AVR8L, {0x1E, 0x92, 0x0E}, 0, 0x01000, 0x040, 0, 0, 0, 0, 0, 0x0040, 0x0100, 1, 1, 18}, // atdf, avr-gcc 12.2.0, avrdude, boot size (manual)
|
||||||
|
{"ATtiny102", 6, F_AVR8L, {0x1E, 0x90, 0x0C}, 0, 0x00400, 0x010, 0, 0, 0, 0, 0, 0x0040, 0x0020, 1, 1, 16}, // atdf, avrdude, boot size (manual)
|
||||||
|
{"ATtiny104", 7, F_AVR8L, {0x1E, 0x90, 0x0B}, 0, 0x00400, 0x010, 0, 0, 0, 0, 0, 0x0040, 0x0020, 1, 1, 16}, // atdf, avrdude, boot size (manual)
|
||||||
|
|
||||||
|
{"ATtiny11", 8, F_AVR8, {0x1E, 0x90, 0x04}, 0, 0x00400, 0x001, 0, 0, 0, 0x0040, 1, 0x0060, 0x0020, 1, 1, 5}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny12", 9, F_AVR8, {0x1E, 0x90, 0x05}, 0, 0x00400, 0x001, 0, 0, 0, 0x0040, 2, 0x0060, 0x0020, 1, 1, 6}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny13", 10, F_AVR8, {0x1E, 0x90, 0x07}, 0, 0x00400, 0x020, 0, 0, 0, 0x0040, 4, 0x0060, 0x0040, 2, 1, 10}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny13A", 11, F_AVR8, {0x1E, 0x90, 0x07}, 0, 0x00400, 0x020, 0, 0, 0, 0x0040, 4, 0x0060, 0x0040, 2, 1, 10}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny15", 12, F_AVR8, {0x1E, 0x90, 0x06}, 0, 0x00400, 0x001, 0, 0, 0, 0x0040, 2, 0x0060, 0x0020, 1, 1, 9}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny22", 13, F_AVR8, {0x1E, 0x91, 0x06}, 0, 0x00800, -1, 0, 0, -1, -1, -1, 0x0060, 0x0080, 1, 1, 3}, // avr-gcc 12.2.0, boot size (manual)
|
||||||
|
{"ATtiny24", 14, F_AVR8, {0x1E, 0x91, 0x0B}, 0, 0x00800, 0x020, 0, 0, 0, 0x0080, 4, 0x0060, 0x0080, 3, 1, 17}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny24A", 15, F_AVR8, {0x1E, 0x91, 0x0B}, 0, 0x00800, 0x020, 0, 0, 0, 0x0080, 4, 0x0060, 0x0080, 3, 1, 17}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny25", 16, F_AVR8, {0x1E, 0x91, 0x08}, 0, 0x00800, 0x020, 0, 0, 0, 0x0080, 4, 0x0060, 0x0080, 3, 1, 15}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny26", 17, F_AVR8, {0x1E, 0x91, 0x09}, 0, 0x00800, 0x020, 0, 0, 0, 0x0080, 4, 0x0060, 0x0080, 2, 1, 12}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny28", 18, F_AVR8, {0x1E, 0x91, 0x07}, 0, 0x00800, 0x002, 0, 0, 0, 0, 0, 0x0060, 0x0020, 1, 1, 6}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny43U", 19, F_AVR8, {0x1E, 0x92, 0x0C}, 0, 0x01000, 0x040, 0, 0, 0, 0x0040, 4, 0x0060, 0x0100, 3, 1, 16}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny44", 20, F_AVR8, {0x1E, 0x92, 0x07}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0060, 0x0100, 3, 1, 17}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny44A", 21, F_AVR8, {0x1E, 0x92, 0x07}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0060, 0x0100, 3, 1, 17}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny45", 22, F_AVR8, {0x1E, 0x92, 0x06}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0060, 0x0100, 3, 1, 15}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny48", 23, F_AVR8, {0x1E, 0x92, 0x09}, 0, 0x01000, 0x040, 0, 0, 0, 0x0040, 4, 0x0100, 0x0100, 3, 1, 20}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny84", 24, F_AVR8, {0x1E, 0x93, 0x0C}, 0, 0x02000, 0x040, 0, 0, 0, 0x0200, 4, 0x0060, 0x0200, 3, 1, 17}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny84A", 25, F_AVR8, {0x1E, 0x93, 0x0C}, 0, 0x02000, 0x040, 0, 0, 0, 0x0200, 4, 0x0060, 0x0200, 3, 1, 17}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny85", 26, F_AVR8, {0x1E, 0x93, 0x0B}, 0, 0x02000, 0x040, 0, 0, 0, 0x0200, 4, 0x0060, 0x0200, 3, 1, 15}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny87", 27, F_AVR8, {0x1E, 0x93, 0x87}, 0, 0x02000, 0x080, 0, 0, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 20}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny88", 28, F_AVR8, {0x1E, 0x93, 0x11}, 0, 0x02000, 0x040, 0, 0, 0, 0x0040, 4, 0x0100, 0x0200, 3, 1, 20}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny167", 29, F_AVR8, {0x1E, 0x94, 0x87}, 0, 0x04000, 0x080, 0, 0, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 20}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny261", 30, F_AVR8, {0x1E, 0x91, 0x0C}, 0, 0x00800, 0x020, 0, 0, 0, 0x0080, 4, 0x0060, 0x0080, 3, 1, 19}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny261A", 31, F_AVR8, {0x1E, 0x91, 0x0C}, 0, 0x00800, 0x020, 0, 0, 0, 0x0080, 4, 0x0060, 0x0080, 3, 1, 19}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny441", 32, F_AVR8, {0x1E, 0x92, 0x15}, 0, 0x01000, 0x010, 0, 0, 0, 0x0100, 4, 0x0100, 0x0100, 3, 1, 30}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny461", 33, F_AVR8, {0x1E, 0x92, 0x08}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0060, 0x0100, 3, 1, 19}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny461A", 34, F_AVR8, {0x1E, 0x92, 0x08}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0060, 0x0100, 3, 1, 19}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny828", 35, F_AVR8, {0x1E, 0x93, 0x14}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0100, 4, 0x0100, 0x0200, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny828R", 36, F_AVR8, {0x1E, 0x93, 0x14}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0100, 4, 0x0100, 0x0200, 3, 1, 26}, // avrdude, from ATtiny828
|
||||||
|
{"ATtiny841", 37, F_AVR8, {0x1E, 0x93, 0x15}, 0, 0x02000, 0x010, 0, 0, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 30}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny861", 38, F_AVR8, {0x1E, 0x93, 0x0D}, 0, 0x02000, 0x040, 0, 0, 0, 0x0200, 4, 0x0060, 0x0200, 3, 1, 19}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny861A", 39, F_AVR8, {0x1E, 0x93, 0x0D}, 0, 0x02000, 0x040, 0, 0, 0, 0x0200, 4, 0x0060, 0x0200, 3, 1, 19}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny1634", 40, F_AVR8, {0x1E, 0x94, 0x12}, 0, 0x04000, 0x020, 0, 0, 0, 0x0100, 4, 0x0100, 0x0400, 3, 1, 28}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny1634R", 41, F_AVR8, {0x1E, 0x94, 0x12}, 0, 0x04000, 0x020, 0, 0, 0, 0x0100, 4, 0x0100, 0x0400, 3, 1, 28}, // avrdude, from ATtiny1634
|
||||||
|
{"ATtiny2313", 42, F_AVR8, {0x1E, 0x91, 0x0A}, 0, 0x00800, 0x020, 0, 0, 0, 0x0080, 4, 0x0060, 0x0080, 3, 1, 19}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny2313A", 43, F_AVR8, {0x1E, 0x91, 0x0A}, 0, 0x00800, 0x020, 0, 0, 0, 0x0080, 4, 0x0060, 0x0080, 3, 1, 21}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny4313", 44, F_AVR8, {0x1E, 0x92, 0x0D}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0060, 0x0100, 3, 1, 21}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega8", 45, F_AVR8, {0x1E, 0x93, 0x07}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0060, 0x0400, 2, 1, 19}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega8A", 46, F_AVR8, {0x1E, 0x93, 0x07}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0060, 0x0400, 2, 1, 19}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega8HVA", 47, F_AVR8, {0x1E, 0x93, 0x10}, 0, 0x02000, 0x080, 0, 0, 0, 0x0100, 4, 0x0100, 0x0200, 1, 1, 21}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"ATmega8U2", 48, F_AVR8, {0x1E, 0x93, 0x89}, 0, 0x02000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 29}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega16", 49, F_AVR8, {0x1E, 0x94, 0x03}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0060, 0x0400, 2, 1, 21}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega16A", 50, F_AVR8, {0x1E, 0x94, 0x03}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0060, 0x0400, 2, 1, 21}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega16HVA", 51, F_AVR8, {0x1E, 0x94, 0x0C}, 0, 0x04000, 0x080, 0, 0, 0, 0x0100, 4, 0x0100, 0x0200, 1, 1, 21}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"ATmega16HVB", 52, F_AVR8, {0x1E, 0x94, 0x0D}, 0, 0x04000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0400, 2, 1, 29}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"ATmega16HVBrevB", 53, F_AVR8, {0x1E, 0x94, 0x0D}, 0, 0x04000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0400, 2, 1, 29}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"ATmega16M1", 54, F_AVR8, {0x1E, 0x94, 0x84}, 0, 0x04000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 31}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"ATmega16HVA2", 55, F_AVR8, {0x1E, 0x94, 0x0E}, 0, 0x04000, 0x080, -1, -1, -1, -1, -1, 0x0100, 0x0400, 2, 1, 22}, // avr-gcc 12.2.0
|
||||||
|
{"ATmega16U2", 56, F_AVR8, {0x1E, 0x94, 0x89}, 0, 0x04000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 29}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega16U4", 57, F_AVR8, {0x1E, 0x94, 0x88}, 0, 0x04000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0500, 3, 1, 43}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega32", 58, F_AVR8, {0x1E, 0x95, 0x02}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0060, 0x0800, 2, 1, 21}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega32A", 59, F_AVR8, {0x1E, 0x95, 0x02}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0060, 0x0800, 2, 1, 21}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega32HVB", 60, F_AVR8, {0x1E, 0x95, 0x10}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 2, 1, 29}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"ATmega32HVBrevB", 61, F_AVR8, {0x1E, 0x95, 0x10}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 2, 1, 29}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"ATmega32C1", 62, F_AVR8, {0x1E, 0x95, 0x86}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 31}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"ATmega32M1", 63, F_AVR8, {0x1E, 0x95, 0x84}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega32U2", 64, F_AVR8, {0x1E, 0x95, 0x8A}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0400, 3, 1, 29}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega32U4", 65, F_AVR8, {0x1E, 0x95, 0x87}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0a00, 3, 1, 43}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega32U6", 66, F_AVR8, {0x1E, 0x95, 0x88}, 0, 0x08000, 0x080, 4, 0x0200, -1, -1, -1, 0x0100, 0x0a00, 3, 1, 38}, // avr-gcc 12.2.0, boot size (manual)
|
||||||
|
{"ATmega48", 67, F_AVR8, {0x1E, 0x92, 0x05}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0100, 0x0200, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega48A", 68, F_AVR8, {0x1E, 0x92, 0x05}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0100, 0x0200, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega48P", 69, F_AVR8, {0x1E, 0x92, 0x0A}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0100, 0x0200, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega48PA", 70, F_AVR8, {0x1E, 0x92, 0x0A}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0100, 0x0200, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega48PB", 71, F_AVR8, {0x1E, 0x92, 0x10}, 0, 0x01000, 0x040, 0, 0, 0, 0x0100, 4, 0x0100, 0x0200, 3, 1, 27}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega64", 72, F_AVR8, {0x1E, 0x96, 0x02}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 35}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega64A", 73, F_AVR8, {0x1E, 0x96, 0x02}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 35}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega64HVE", 74, F_AVR8, {0x1E, 0x96, 0x10}, 0, 0x10000, 0x080, 4, 0x0400, -1, -1, -1, 0x0100, 0x1000, 2, 1, 25}, // avr-gcc 12.2.0, boot size (manual)
|
||||||
|
{"ATmega64C1", 75, F_AVR8, {0x1E, 0x96, 0x86}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 31}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"ATmega64M1", 76, F_AVR8, {0x1E, 0x96, 0x84}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega64HVE2", 77, F_AVR8, {0x1E, 0x96, 0x10}, 0, 0x10000, 0x080, 4, 0x0400, 0, 0x0400, 4, 0x0100, 0x1000, 2, 1, 25}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"ATmega64RFR2", 78, F_AVR8, {0x1E, 0xA6, 0x02}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0200, 0x2000, 3, 1, 77}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega88", 79, F_AVR8, {0x1E, 0x93, 0x0A}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega88A", 80, F_AVR8, {0x1E, 0x93, 0x0A}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega88P", 81, F_AVR8, {0x1E, 0x93, 0x0F}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega88PA", 82, F_AVR8, {0x1E, 0x93, 0x0F}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega88PB", 83, F_AVR8, {0x1E, 0x93, 0x16}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 27}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega103", 84, F_AVR8, {0x1E, 0x97, 0x01}, 0, 0x20000, 0x100, 0, 0, 0, 0x1000, 1, 0x0060, 0x0fa0, 1, 1, 24}, // avr-gcc 12.2.0, avrdude, boot size (manual)
|
||||||
|
{"ATmega128", 85, F_AVR8, {0x1E, 0x97, 0x02}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0100, 0x1000, 3, 1, 35}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega128A", 86, F_AVR8, {0x1E, 0x97, 0x02}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0100, 0x1000, 3, 1, 35}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega128RFA1", 87, F_AVR8, {0x1E, 0xA7, 0x01}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0200, 0x4000, 3, 1, 72}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega128RFR2", 88, F_AVR8, {0x1E, 0xA7, 0x02}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0200, 0x4000, 3, 1, 77}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega161", 89, F_AVR8, {0x1E, 0x94, 0x01}, 0, 0x04000, 0x080, 1, 0x0400, 0, 0x0200, 1, 0x0060, 0x0400, 1, 1, 21}, // avr-gcc 12.2.0, avrdude, boot size (manual)
|
||||||
|
{"ATmega162", 90, F_AVR8, {0x1E, 0x94, 0x04}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 28}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega163", 91, F_AVR8, {0x1E, 0x94, 0x02}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 1, 0x0060, 0x0400, 2, 1, 18}, // avr-gcc 12.2.0, avrdude, boot size (manual)
|
||||||
|
{"ATmega164A", 92, F_AVR8, {0x1E, 0x94, 0x0F}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega164P", 93, F_AVR8, {0x1E, 0x94, 0x0A}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega164PA", 94, F_AVR8, {0x1E, 0x94, 0x0A}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega165", 95, F_AVR8, {0x1E, 0x94, 0x10}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 22}, // avr-gcc 12.2.0, avrdude, boot size (manual)
|
||||||
|
{"ATmega165A", 96, F_AVR8, {0x1E, 0x94, 0x10}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega165P", 97, F_AVR8, {0x1E, 0x94, 0x07}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega165PA", 98, F_AVR8, {0x1E, 0x94, 0x07}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega168", 99, F_AVR8, {0x1E, 0x94, 0x06}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega168A", 100, F_AVR8, {0x1E, 0x94, 0x06}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega168P", 101, F_AVR8, {0x1E, 0x94, 0x0B}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega168PA", 102, F_AVR8, {0x1E, 0x94, 0x0B}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega168PB", 103, F_AVR8, {0x1E, 0x94, 0x15}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 27}, // atdf, avr-gcc 7.3.0, avrdude
|
||||||
|
{"ATmega169", 104, F_AVR8, {0x1E, 0x94, 0x05}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 23}, // avr-gcc 12.2.0, avrdude, boot size (manual)
|
||||||
|
{"ATmega169A", 105, F_AVR8, {0x1E, 0x94, 0x11}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega169P", 106, F_AVR8, {0x1E, 0x94, 0x05}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega169PA", 107, F_AVR8, {0x1E, 0x94, 0x05}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega256RFR2", 108, F_AVR8, {0x1E, 0xA8, 0x02}, 0, 0x40000, 0x100, 4, 0x0400, 0, 0x2000, 8, 0x0200, 0x8000, 3, 1, 77}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega323", 109, F_AVR8, {0x1E, 0x95, 0x01}, 0, 0x08000, 0x080, 4, 0x0200, -1, -1, -1, 0x0060, 0x0800, 2, 1, 21}, // avr-gcc 12.2.0, boot size (manual)
|
||||||
|
{"ATmega324A", 110, F_AVR8, {0x1E, 0x95, 0x15}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega324P", 111, F_AVR8, {0x1E, 0x95, 0x08}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega324PA", 112, F_AVR8, {0x1E, 0x95, 0x11}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega324PB", 113, F_AVR8, {0x1E, 0x95, 0x17}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 51}, // atdf, avrdude
|
||||||
|
{"ATmega325", 114, F_AVR8, {0x1E, 0x95, 0x05}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega325A", 115, F_AVR8, {0x1E, 0x95, 0x05}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega325P", 116, F_AVR8, {0x1E, 0x95, 0x0D}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega325PA", 117, F_AVR8, {0x1E, 0x95, 0x0D}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega328", 118, F_AVR8, {0x1E, 0x95, 0x14}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega328P", 119, F_AVR8, {0x1E, 0x95, 0x0F}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega328PB", 120, F_AVR8, {0x1E, 0x95, 0x16}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 45}, // atdf, avr-gcc 7.3.0, avrdude
|
||||||
|
{"ATmega329", 121, F_AVR8, {0x1E, 0x95, 0x03}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega329A", 122, F_AVR8, {0x1E, 0x95, 0x03}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega329P", 123, F_AVR8, {0x1E, 0x95, 0x0B}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega329PA", 124, F_AVR8, {0x1E, 0x95, 0x0B}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega406", 125, F_AVR8, {0x1E, 0x95, 0x07}, 0, 0x0a000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0800, 2, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega640", 126, F_AVR8, {0x1E, 0x96, 0x08}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0200, 0x2000, 3, 1, 57}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega644", 127, F_AVR8, {0x1E, 0x96, 0x09}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 28}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega644A", 128, F_AVR8, {0x1E, 0x96, 0x09}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega644P", 129, F_AVR8, {0x1E, 0x96, 0x0A}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega644PA", 130, F_AVR8, {0x1E, 0x96, 0x0A}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega644RFR2", 131, F_AVR8, {0x1E, 0xA6, 0x03}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0200, 0x2000, 3, 1, 77}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega645", 132, F_AVR8, {0x1E, 0x96, 0x05}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega645A", 133, F_AVR8, {0x1E, 0x96, 0x05}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega645P", 134, F_AVR8, {0x1E, 0x96, 0x0D}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 22}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega649", 135, F_AVR8, {0x1E, 0x96, 0x03}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega649A", 136, F_AVR8, {0x1E, 0x96, 0x03}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega649P", 137, F_AVR8, {0x1E, 0x96, 0x0B}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 23}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega1280", 138, F_AVR8, {0x1E, 0x97, 0x03}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0200, 0x2000, 3, 1, 57}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega1281", 139, F_AVR8, {0x1E, 0x97, 0x04}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0200, 0x2000, 3, 1, 57}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega1284", 140, F_AVR8, {0x1E, 0x97, 0x06}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0100, 0x4000, 3, 1, 35}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega1284P", 141, F_AVR8, {0x1E, 0x97, 0x05}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0100, 0x4000, 3, 1, 35}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega1284RFR2", 142, F_AVR8, {0x1E, 0xA7, 0x03}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0200, 0x4000, 3, 1, 77}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega2560", 143, F_AVR8, {0x1E, 0x98, 0x01}, 0, 0x40000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0200, 0x2000, 3, 1, 57}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega2561", 144, F_AVR8, {0x1E, 0x98, 0x02}, 0, 0x40000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0200, 0x2000, 3, 1, 57}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega2564RFR2", 145, F_AVR8, {0x1E, 0xA8, 0x03}, 0, 0x40000, 0x100, 4, 0x0400, 0, 0x2000, 8, 0x0200, 0x8000, 3, 1, 77}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega3250", 146, F_AVR8, {0x1E, 0x95, 0x06}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega3250A", 147, F_AVR8, {0x1E, 0x95, 0x06}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega3250P", 148, F_AVR8, {0x1E, 0x95, 0x0E}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega3250PA", 149, F_AVR8, {0x1E, 0x95, 0x0E}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega3290", 150, F_AVR8, {0x1E, 0x95, 0x04}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega3290A", 151, F_AVR8, {0x1E, 0x95, 0x04}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega3290P", 152, F_AVR8, {0x1E, 0x95, 0x0C}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega3290PA", 153, F_AVR8, {0x1E, 0x95, 0x0C}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega6450", 154, F_AVR8, {0x1E, 0x96, 0x06}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega6450A", 155, F_AVR8, {0x1E, 0x96, 0x06}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega6450P", 156, F_AVR8, {0x1E, 0x96, 0x0E}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega6490", 157, F_AVR8, {0x1E, 0x96, 0x04}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega6490A", 158, F_AVR8, {0x1E, 0x96, 0x04}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega6490P", 159, F_AVR8, {0x1E, 0x96, 0x0C}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 25}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega8515", 160, F_AVR8, {0x1E, 0x93, 0x06}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0060, 0x0200, 2, 1, 17}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega8535", 161, F_AVR8, {0x1E, 0x93, 0x08}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0060, 0x0200, 2, 1, 21}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"AT43USB320", 162, F_AVR8, {0xff, -1, -1}, 0, 0x10000, -1, -1, -1, -1, -1, -1, 0x0060, 0x0200, -1, -1, 0}, // avr-gcc 12.2.0
|
||||||
|
{"AT43USB355", 163, F_AVR8, {0xff, -1, -1}, 0, 0x06000, -1, -1, -1, -1, -1, -1, 0x0060, 0x0400, -1, -1, 0}, // avr-gcc 12.2.0
|
||||||
|
{"AT76C711", 164, F_AVR8, {0xff, -1, -1}, 0, 0x04000, -1, -1, -1, -1, -1, -1, 0x0060, 0x07a0, -1, -1, 0}, // avr-gcc 12.2.0
|
||||||
|
{"AT86RF401", 165, F_AVR8, {0x1E, 0x91, 0x81}, 0, 0x00800, -1, -1, -1, -1, -1, -1, 0x0060, 0x0080, 0, 1, 3}, // avr-gcc 12.2.0
|
||||||
|
{"AT90PWM1", 166, F_AVR8, {0x1E, 0x93, 0x83}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 32}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"AT90PWM2", 167, F_AVR8, {0x1E, 0x93, 0x81}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 32}, // avr-gcc 12.2.0, avrdude, boot size (manual)
|
||||||
|
{"AT90PWM2B", 168, F_AVR8, {0x1E, 0x93, 0x83}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 32}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"AT90PWM3", 169, F_AVR8, {0x1E, 0x93, 0x81}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 32}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"AT90PWM3B", 170, F_AVR8, {0x1E, 0x93, 0x83}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 32}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"AT90CAN32", 171, F_AVR8, {0x1E, 0x95, 0x81}, 0, 0x08000, 0x100, 4, 0x0400, 0, 0x0400, 8, 0x0100, 0x0800, 3, 1, 37}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"AT90CAN64", 172, F_AVR8, {0x1E, 0x96, 0x81}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 37}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"AT90PWM81", 173, F_AVR8, {0x1E, 0x93, 0x88}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0100, 3, 1, 20}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"AT90USB82", 174, F_AVR8, {0x1E, 0x93, 0x82}, 0, 0x02000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 29}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"AT90SCR100", 175, F_AVR8, {0x1E, 0x96, 0xC1}, 0, 0x10000, 0x100, 4, 0x0200, -1, -1, -1, 0x0100, 0x1000, 3, 1, 38}, // avr-gcc 12.2.0, boot size (manual)
|
||||||
|
{"AT90CAN128", 176, F_AVR8, {0x1E, 0x97, 0x81}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0100, 0x1000, 3, 1, 37}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"AT90PWM161", 177, F_AVR8, {0x1E, 0x94, 0x8B}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 20}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"AT90USB162", 178, F_AVR8, {0x1E, 0x94, 0x82}, 0, 0x04000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 29}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"AT90PWM216", 179, F_AVR8, {0x1E, 0x94, 0x83}, 0, 0x04000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 32}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"AT90PWM316", 180, F_AVR8, {0x1E, 0x94, 0x83}, 0, 0x04000, 0x080, 4, 0x0200, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 32}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"AT90USB646", 181, F_AVR8, {0x1E, 0x96, 0x82}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 38}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"AT90USB647", 182, F_AVR8, {0x1E, 0x96, 0x82}, 0, 0x10000, 0x100, 4, 0x0400, 0, 0x0800, 8, 0x0100, 0x1000, 3, 1, 38}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"AT90S1200", 183, F_AVR8, {0x1E, 0x90, 0x01}, 0, 0x00400, 0x001, 0, 0, 0, 0x0040, 1, 0x0060, 0x0020, 1, 1, 4}, // avr-gcc 12.2.0, avrdude, boot size (manual)
|
||||||
|
{"AT90USB1286", 184, F_AVR8, {0x1E, 0x97, 0x82}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0100, 0x2000, 3, 1, 38}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"AT90USB1287", 185, F_AVR8, {0x1E, 0x97, 0x82}, 0, 0x20000, 0x100, 4, 0x0400, 0, 0x1000, 8, 0x0100, 0x2000, 3, 1, 38}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"AT90S2313", 186, F_AVR8, {0x1E, 0x91, 0x01}, 0, 0x00800, 0x001, 0, 0, 0, 0x0080, 1, 0x0060, 0x0080, 1, 1, 11}, // avr-gcc 12.2.0, avrdude, boot size (manual)
|
||||||
|
{"AT90S2323", 187, F_AVR8, {0x1E, 0x91, 0x02}, 0, 0x00800, -1, 0, 0, -1, -1, -1, 0x0060, 0x0080, 1, 1, 3}, // avr-gcc 12.2.0, boot size (manual)
|
||||||
|
{"AT90S2333", 188, F_AVR8, {0x1E, 0x91, 0x05}, 0, 0x00800, 0x001, 0, 0, 0, 0x0080, 1, 0x0060, 0x0080, -1, -1, 14}, // avr-gcc 12.2.0, avrdude, boot size (manual)
|
||||||
|
{"AT90S2343", 189, F_AVR8, {0x1E, 0x91, 0x03}, 0, 0x00800, 0x001, 0, 0, 0, 0x0080, 1, 0x0060, 0x0080, 1, 1, 3}, // avr-gcc 12.2.0, avrdude, boot size (manual)
|
||||||
|
{"AT90S4414", 190, F_AVR8, {0x1E, 0x92, 0x01}, 0, 0x01000, 0x001, 0, 0, 0, 0x0100, 1, 0x0060, 0x0100, 1, 1, 13}, // avr-gcc 12.2.0, avrdude, boot size (manual)
|
||||||
|
{"AT90S4433", 191, F_AVR8, {0x1E, 0x92, 0x03}, 0, 0x01000, 0x001, 0, 0, 0, 0x0100, 1, 0x0060, 0x0080, 1, 1, 14}, // avr-gcc 12.2.0, avrdude, boot size (manual)
|
||||||
|
{"AT90S4434", 192, F_AVR8, {0x1E, 0x92, 0x02}, 0, 0x01000, 0x001, 0, 0, 0, 0x0100, 1, 0x0060, 0x0100, 1, 1, 17}, // avr-gcc 12.2.0, avrdude, boot size (manual)
|
||||||
|
{"AT90S8515", 193, F_AVR8, {0x1E, 0x93, 0x01}, 0, 0x02000, 0x001, 0, 0, 0, 0x0200, 1, 0x0060, 0x0200, 1, 1, 13}, // avr-gcc 12.2.0, avrdude, boot size (manual)
|
||||||
|
{"AT90C8534", 194, F_AVR8, {0xff, -1, -1}, 0, 0x02000, -1, -1, -1, -1, -1, -1, 0x0060, 0x0100, -1, -1, 0}, // avr-gcc 12.2.0
|
||||||
|
{"AT90S8535", 195, F_AVR8, {0x1E, 0x93, 0x03}, 0, 0x02000, 0x001, 0, 0, 0, 0x0200, 1, 0x0060, 0x0200, 1, 1, 17}, // avr-gcc 12.2.0, avrdude, boot size (manual)
|
||||||
|
{"AT94K", 196, F_AVR8, {0xff, -1, -1}, 0, 0x08000, -1, -1, -1, -1, -1, -1, 0x0060, 0x0fa0, -1, -1, 0}, // avr-gcc 12.2.0
|
||||||
|
{"ATA5272", 197, F_AVR8, {0x1E, 0x93, 0x87}, 0, 0x02000, 0x080, 0, 0, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 37}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"ATA5505", 198, F_AVR8, {0x1E, 0x94, 0x87}, 0, 0x04000, 0x080, 0, 0, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 20}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"ATA5700M322", 199, F_AVR8, {0x1E, 0x95, 0x67}, 0x08000, 0x08000, 0x040, 0, 0, 0, 0x0880, 16, 0x0200, 0x0400, 1, 1, 51}, // atdf
|
||||||
|
{"ATA5702M322", 200, F_AVR8, {0x1E, 0x95, 0x69}, 0x08000, 0x08000, 0x040, 0, 0, 0, 0x0880, 16, 0x0200, 0x0400, 1, 1, 51}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"ATA5781", 201, F_AVR8, {0x1E, 0x95, 0x64}, -1, -1, -1, 0, 0, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf
|
||||||
|
{"ATA5782", 202, F_AVR8, {0x1E, 0x95, 0x65}, 0x08000, 0x05000, 0x040, 1, 0x5000, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"ATA5783", 203, F_AVR8, {0x1E, 0x95, 0x66}, -1, -1, -1, 0, 0, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf
|
||||||
|
{"ATA5787", 204, F_AVR8, {0x1E, 0x94, 0x6C}, 0x08000, 0x05200, 0x040, 0, 0, 0, 0x0400, 16, 0x0200, 0x0800, 1, 1, 44}, // atdf
|
||||||
|
{"ATA5790", 205, F_AVR8, {0x1E, 0x94, 0x61}, 0, 0x04000, 0x080, 1, 0x0800, 0, 0x0800, 16, 0x0100, 0x0200, 1, 1, 30}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"ATA5790N", 206, F_AVR8, {0x1E, 0x94, 0x62}, 0, 0x04000, 0x080, 1, 0x0800, 0, 0x0800, 16, 0x0100, 0x0200, 1, 1, 31}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"ATA5791", 207, F_AVR8, {0x1E, 0x94, 0x62}, 0, 0x04000, 0x080, 1, 0x0800, 0, 0x0800, 16, 0x0100, 0x0200, 1, 1, 31}, // atdf, avr-gcc 7.3.0
|
||||||
|
{"ATA5795", 208, F_AVR8, {0x1E, 0x93, 0x61}, 0, 0x02000, 0x040, 1, 0x0800, 0, 0x0800, 16, 0x0100, 0x0200, 1, 1, 23}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"ATA5831", 209, F_AVR8, {0x1E, 0x95, 0x61}, 0x08000, 0x05000, 0x040, 1, 0x5000, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"ATA5832", 210, F_AVR8, {0x1E, 0x95, 0x62}, -1, -1, -1, 0, 0, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf
|
||||||
|
{"ATA5833", 211, F_AVR8, {0x1E, 0x95, 0x63}, -1, -1, -1, 0, 0, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf
|
||||||
|
{"ATA5835", 212, F_AVR8, {0x1E, 0x94, 0x6B}, 0x08000, 0x05200, 0x040, 0, 0, 0, 0x0400, 16, 0x0200, 0x0800, 1, 1, 44}, // atdf
|
||||||
|
{"ATA6285", 213, F_AVR8, {0x1E, 0x93, 0x82}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0140, 4, 0x0100, 0x0200, 2, 1, 27}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"ATA6286", 214, F_AVR8, {0x1E, 0x93, 0x82}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0140, 4, 0x0100, 0x0200, 2, 1, 27}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"ATA6289", 215, F_AVR8, {0x1E, 0x93, 0x82}, 0, 0x02000, 0x040, 4, 0x0100, -1, -1, -1, 0x0100, 0x0200, 2, 1, 27}, // avr-gcc 12.2.0, boot size (manual)
|
||||||
|
{"ATA6612C", 216, F_AVR8, {0x1E, 0x93, 0x0A}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"ATA6613C", 217, F_AVR8, {0x1E, 0x94, 0x06}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"ATA6614Q", 218, F_AVR8, {0x1E, 0x95, 0x0F}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 26}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"ATA6616C", 219, F_AVR8, {0x1E, 0x93, 0x87}, 0, 0x02000, 0x080, 0, 0, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 20}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"ATA6617C", 220, F_AVR8, {0x1E, 0x94, 0x87}, 0, 0x04000, 0x080, 0, 0, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 20}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"ATA8210", 221, F_AVR8, {0x1E, 0x95, 0x65}, 0x08000, 0x05000, 0x040, 1, 0x5000, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf, avr-gcc 7.3.0
|
||||||
|
{"ATA8215", 222, F_AVR8, {0x1E, 0x95, 0x64}, -1, -1, -1, 0, 0, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf
|
||||||
|
{"ATA8510", 223, F_AVR8, {0x1E, 0x95, 0x61}, 0x08000, 0x05000, 0x040, 1, 0x5000, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf, avr-gcc 7.3.0
|
||||||
|
{"ATA8515", 224, F_AVR8, {0x1E, 0x95, 0x63}, -1, -1, -1, 0, 0, 0, 0x0400, 16, 0x0200, 0x0400, 1, 1, 42}, // atdf
|
||||||
|
{"ATA664251", 225, F_AVR8, {0x1E, 0x94, 0x87}, 0, 0x04000, 0x080, 0, 0, 0, 0x0200, 4, 0x0100, 0x0200, 3, 1, 20}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"M3000", 226, F_AVR8, {0xff, -1, -1}, 0, 0x10000, -1, -1, -1, -1, -1, -1, 0x1000, 0x1000, -1, -1, 0}, // avr-gcc 12.2.0
|
||||||
|
{"LGT8F88P", 227, F_AVR8, {0x1E, 0x93, 0x0F}, 0, 0x02000, 0x040, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // avrdude, from ATmega88
|
||||||
|
{"LGT8F168P", 228, F_AVR8, {0x1E, 0x94, 0x0B}, 0, 0x04000, 0x080, 4, 0x0100, 0, 0x0200, 4, 0x0100, 0x0400, 3, 1, 26}, // avrdude, from ATmega168P
|
||||||
|
{"LGT8F328P", 229, F_AVR8, {0x1E, 0x95, 0x0F}, 0, 0x08000, 0x080, 4, 0x0200, 0, 0x0400, 4, 0x0100, 0x0800, 3, 1, 26}, // avrdude, from ATmega328P
|
||||||
|
|
||||||
|
{"ATxmega8E5", 230, F_XMEGA, {0x1E, 0x93, 0x41}, 0, 0x02800, 0x080, 1, 0x0800, 0, 0x0200, 32, 0x2000, 0x0400, 7, 1, 43}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega16A4", 231, F_XMEGA, {0x1E, 0x94, 0x41}, 0, 0x05000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x0800, 6, 1, 94}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega16A4U", 232, F_XMEGA, {0x1E, 0x94, 0x41}, 0, 0x05000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x0800, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega16C4", 233, F_XMEGA, {0x1E, 0x94, 0x43}, 0, 0x05000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x0800, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega16D4", 234, F_XMEGA, {0x1E, 0x94, 0x42}, 0, 0x05000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x0800, 6, 1, 91}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega16E5", 235, F_XMEGA, {0x1E, 0x94, 0x45}, 0, 0x05000, 0x080, 1, 0x1000, 0, 0x0200, 32, 0x2000, 0x0800, 7, 1, 43}, // atdf, avr-gcc 7.3.0, avrdude
|
||||||
|
{"ATxmega32C3", 236, F_XMEGA, {0x1E, 0x95, 0x49}, 0, 0x09000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x1000, 6, 1, 127}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"ATxmega32D3", 237, F_XMEGA, {0x1E, 0x95, 0x4A}, 0, 0x09000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x1000, 6, 1, 114}, // atdf, avr-gcc 12.2.0
|
||||||
|
{"ATxmega32A4", 238, F_XMEGA, {0x1E, 0x95, 0x41}, 0, 0x09000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x1000, 6, 1, 94}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega32A4U", 239, F_XMEGA, {0x1E, 0x95, 0x41}, 0, 0x09000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x1000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega32C4", 240, F_XMEGA, {0x1E, 0x95, 0x44}, 0, 0x09000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x1000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega32D4", 241, F_XMEGA, {0x1E, 0x95, 0x42}, 0, 0x09000, 0x100, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x1000, 6, 1, 91}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega32E5", 242, F_XMEGA, {0x1E, 0x95, 0x4C}, 0, 0x09000, 0x080, 1, 0x1000, 0, 0x0400, 32, 0x2000, 0x1000, 7, 1, 43}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega64A1", 243, F_XMEGA, {0x1E, 0x96, 0x4E}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 125}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega64A1U", 244, F_XMEGA, {0x1E, 0x96, 0x4E}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega64B1", 245, F_XMEGA, {0x1E, 0x96, 0x52}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 81}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega64A3", 246, F_XMEGA, {0x1E, 0x96, 0x42}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 122}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega64A3U", 247, F_XMEGA, {0x1E, 0x96, 0x42}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega64B3", 248, F_XMEGA, {0x1E, 0x96, 0x51}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 54}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega64C3", 249, F_XMEGA, {0x1E, 0x96, 0x49}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega64D3", 250, F_XMEGA, {0x1E, 0x96, 0x4A}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 114}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega64A4", 251, F_XMEGA, {0x1E, 0x96, 0x46}, 0, 0x11000, 0x100, -1, -1, 0, 0x0800, 32, -1, -1, -1, -1, 0}, // avrdude
|
||||||
|
{"ATxmega64A4U", 252, F_XMEGA, {0x1E, 0x96, 0x46}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega64D4", 253, F_XMEGA, {0x1E, 0x96, 0x47}, 0, 0x11000, 0x100, 1, 0x1000, 0, 0x0800, 32, 0x2000, 0x1000, 6, 1, 91}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega128A1", 254, F_XMEGA, {0x1E, 0x97, 0x4C}, 0, 0x22000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 125}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega128A1revD", 255, F_XMEGA, {0x1E, 0x97, 0x41}, 0, 0x22000, 0x200, -1, -1, 0, 0x0800, 32, -1, -1, -1, -1, 0}, // avrdude
|
||||||
|
{"ATxmega128A1U", 256, F_XMEGA, {0x1E, 0x97, 0x4C}, 0, 0x22000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega128B1", 257, F_XMEGA, {0x1E, 0x97, 0x4D}, 0, 0x22000, 0x100, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 81}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega128A3", 258, F_XMEGA, {0x1E, 0x97, 0x42}, 0, 0x22000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 122}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega128A3U", 259, F_XMEGA, {0x1E, 0x97, 0x42}, 0, 0x22000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega128B3", 260, F_XMEGA, {0x1E, 0x97, 0x4B}, 0, 0x22000, 0x100, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 54}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega128C3", 261, F_XMEGA, {0x1E, 0x97, 0x52}, 0, 0x22000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega128D3", 262, F_XMEGA, {0x1E, 0x97, 0x48}, 0, 0x22000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 114}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega128A4", 263, F_XMEGA, {0x1E, 0x97, 0x46}, 0, 0x22000, 0x200, -1, -1, 0, 0x0800, 32, -1, -1, -1, -1, 0}, // avrdude
|
||||||
|
{"ATxmega128A4U", 264, F_XMEGA, {0x1E, 0x97, 0x46}, 0, 0x22000, 0x100, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega128D4", 265, F_XMEGA, {0x1E, 0x97, 0x47}, 0, 0x22000, 0x100, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x2000, 6, 1, 91}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega192A1", 266, F_XMEGA, {0x1E, 0x97, 0x4E}, 0, 0x32000, 0x200, -1, -1, 0, 0x0800, 32, -1, -1, -1, -1, 0}, // avrdude
|
||||||
|
{"ATxmega192A3", 267, F_XMEGA, {0x1E, 0x97, 0x44}, 0, 0x32000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x4000, 6, 1, 122}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega192A3U", 268, F_XMEGA, {0x1E, 0x97, 0x44}, 0, 0x32000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x4000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega192C3", 269, F_XMEGA, {0x1E, 0x97, 0x51}, 0, 0x32000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x4000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega192D3", 270, F_XMEGA, {0x1E, 0x97, 0x49}, 0, 0x32000, 0x200, 1, 0x2000, 0, 0x0800, 32, 0x2000, 0x4000, 6, 1, 114}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega256A1", 271, F_XMEGA, {0x1E, 0x98, 0x46}, 0, 0x42000, 0x200, -1, -1, 0, 0x1000, 32, -1, -1, -1, -1, 0}, // avrdude
|
||||||
|
{"ATxmega256A3", 272, F_XMEGA, {0x1E, 0x98, 0x42}, 0, 0x42000, 0x200, 1, 0x2000, 0, 0x1000, 32, 0x2000, 0x4000, 6, 1, 122}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega256A3B", 273, F_XMEGA, {0x1E, 0x98, 0x43}, 0, 0x42000, 0x200, 1, 0x2000, 0, 0x1000, 32, 0x2000, 0x4000, 6, 1, 122}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega256A3BU", 274, F_XMEGA, {0x1E, 0x98, 0x43}, 0, 0x42000, 0x200, 1, 0x2000, 0, 0x1000, 32, 0x2000, 0x4000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega256A3U", 275, F_XMEGA, {0x1E, 0x98, 0x42}, 0, 0x42000, 0x200, 1, 0x2000, 0, 0x1000, 32, 0x2000, 0x4000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega256C3", 276, F_XMEGA, {0x1E, 0x98, 0x46}, 0, 0x42000, 0x200, 1, 0x2000, 0, 0x1000, 32, 0x2000, 0x4000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega256D3", 277, F_XMEGA, {0x1E, 0x98, 0x44}, 0, 0x42000, 0x200, 1, 0x2000, 0, 0x1000, 32, 0x2000, 0x4000, 6, 1, 114}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega384C3", 278, F_XMEGA, {0x1E, 0x98, 0x45}, 0, 0x62000, 0x200, 1, 0x2000, 0, 0x1000, 32, 0x2000, 0x8000, 6, 1, 127}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATxmega384D3", 279, F_XMEGA, {0x1E, 0x98, 0x47}, 0, 0x62000, 0x200, 1, 0x2000, 0, 0x1000, 32, 0x2000, 0x8000, 6, 1, 114}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
|
||||||
|
{"ATtiny202", 280, F_AVR8X, {0x1E, 0x91, 0x23}, 0, 0x00800, 0x040, 1, 0, 0x01400, 0x0040, 32, 0x3f80, 0x0080, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny204", 281, F_AVR8X, {0x1E, 0x91, 0x22}, 0, 0x00800, 0x040, 1, 0, 0x01400, 0x0040, 32, 0x3f80, 0x0080, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny212", 282, F_AVR8X, {0x1E, 0x91, 0x21}, 0, 0x00800, 0x040, 1, 0, 0x01400, 0x0040, 32, 0x3f80, 0x0080, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny214", 283, F_AVR8X, {0x1E, 0x91, 0x20}, 0, 0x00800, 0x040, 1, 0, 0x01400, 0x0040, 32, 0x3f80, 0x0080, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny402", 284, F_AVR8X, {0x1E, 0x92, 0x27}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3f00, 0x0100, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny404", 285, F_AVR8X, {0x1E, 0x92, 0x26}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3f00, 0x0100, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny406", 286, F_AVR8X, {0x1E, 0x92, 0x25}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3f00, 0x0100, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny412", 287, F_AVR8X, {0x1E, 0x92, 0x23}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3f00, 0x0100, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny414", 288, F_AVR8X, {0x1E, 0x92, 0x22}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3f00, 0x0100, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny416", 289, F_AVR8X, {0x1E, 0x92, 0x21}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3f00, 0x0100, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny416auto", 290, F_AVR8X, {0x1E, 0x92, 0x28}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3f00, 0x0100, 10, 1, 26}, // atdf
|
||||||
|
{"ATtiny417", 291, F_AVR8X, {0x1E, 0x92, 0x20}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3f00, 0x0100, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny424", 292, F_AVR8X, {0x1E, 0x92, 0x2C}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3e00, 0x0200, 10, 1, 30}, // atdf, avrdude
|
||||||
|
{"ATtiny426", 293, F_AVR8X, {0x1E, 0x92, 0x2B}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3e00, 0x0200, 10, 1, 30}, // atdf, avrdude
|
||||||
|
{"ATtiny427", 294, F_AVR8X, {0x1E, 0x92, 0x2A}, 0, 0x01000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3e00, 0x0200, 10, 1, 30}, // atdf, avrdude
|
||||||
|
{"ATtiny804", 295, F_AVR8X, {0x1E, 0x93, 0x25}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3e00, 0x0200, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny806", 296, F_AVR8X, {0x1E, 0x93, 0x24}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3e00, 0x0200, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny807", 297, F_AVR8X, {0x1E, 0x93, 0x23}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3e00, 0x0200, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny814", 298, F_AVR8X, {0x1E, 0x93, 0x22}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3e00, 0x0200, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny816", 299, F_AVR8X, {0x1E, 0x93, 0x21}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3e00, 0x0200, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny817", 300, F_AVR8X, {0x1E, 0x93, 0x20}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3e00, 0x0200, 10, 1, 26}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny824", 301, F_AVR8X, {0x1E, 0x93, 0x29}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3c00, 0x0400, 10, 1, 30}, // atdf, avrdude
|
||||||
|
{"ATtiny826", 302, F_AVR8X, {0x1E, 0x93, 0x28}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3c00, 0x0400, 10, 1, 30}, // atdf, avrdude
|
||||||
|
{"ATtiny827", 303, F_AVR8X, {0x1E, 0x93, 0x27}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0080, 32, 0x3c00, 0x0400, 10, 1, 30}, // atdf, avrdude
|
||||||
|
{"ATtiny1604", 304, F_AVR8X, {0x1E, 0x94, 0x25}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3c00, 0x0400, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny1606", 305, F_AVR8X, {0x1E, 0x94, 0x24}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3c00, 0x0400, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny1607", 306, F_AVR8X, {0x1E, 0x94, 0x23}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3c00, 0x0400, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny1614", 307, F_AVR8X, {0x1E, 0x94, 0x22}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3800, 0x0800, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny1616", 308, F_AVR8X, {0x1E, 0x94, 0x21}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3800, 0x0800, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny1617", 309, F_AVR8X, {0x1E, 0x94, 0x20}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3800, 0x0800, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny1624", 310, F_AVR8X, {0x1E, 0x94, 0x2A}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3800, 0x0800, 10, 1, 30}, // atdf, avrdude
|
||||||
|
{"ATtiny1626", 311, F_AVR8X, {0x1E, 0x94, 0x29}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3800, 0x0800, 10, 1, 30}, // atdf, avrdude
|
||||||
|
{"ATtiny1627", 312, F_AVR8X, {0x1E, 0x94, 0x28}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3800, 0x0800, 10, 1, 30}, // atdf, avrdude
|
||||||
|
{"ATtiny3214", 313, F_AVR8X, {0x1E, 0x95, 0x20}, 0, 0x08000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x3800, 0x0800, 10, 1, 31}, // avr-gcc 12.2.0
|
||||||
|
{"ATtiny3216", 314, F_AVR8X, {0x1E, 0x95, 0x21}, 0, 0x08000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x3800, 0x0800, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny3217", 315, F_AVR8X, {0x1E, 0x95, 0x22}, 0, 0x08000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x3800, 0x0800, 10, 1, 31}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATtiny3224", 316, F_AVR8X, {0x1E, 0x95, 0x28}, 0, 0x08000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x3400, 0x0c00, 10, 1, 30}, // atdf, avrdude
|
||||||
|
{"ATtiny3226", 317, F_AVR8X, {0x1E, 0x95, 0x27}, 0, 0x08000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x3400, 0x0c00, 10, 1, 30}, // atdf, avrdude
|
||||||
|
{"ATtiny3227", 318, F_AVR8X, {0x1E, 0x95, 0x26}, 0, 0x08000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x3400, 0x0c00, 10, 1, 30}, // atdf, avrdude
|
||||||
|
{"ATmega808", 319, F_AVR8X, {0x1E, 0x93, 0x26}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3c00, 0x0400, 10, 1, 36}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega809", 320, F_AVR8X, {0x1E, 0x93, 0x2A}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3c00, 0x0400, 10, 1, 40}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega1608", 321, F_AVR8X, {0x1E, 0x94, 0x27}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3800, 0x0800, 10, 1, 36}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega1609", 322, F_AVR8X, {0x1E, 0x94, 0x26}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0100, 32, 0x3800, 0x0800, 10, 1, 40}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega3208", 323, F_AVR8X, {0x1E, 0x95, 0x30}, 0, 0x08000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x3000, 0x1000, 10, 1, 36}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega3209", 324, F_AVR8X, {0x1E, 0x95, 0x31}, 0, 0x08000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x3000, 0x1000, 10, 1, 40}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega4808", 325, F_AVR8X, {0x1E, 0x96, 0x50}, 0, 0x0c000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x2800, 0x1800, 10, 1, 36}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"ATmega4809", 326, F_AVR8X, {0x1E, 0x96, 0x51}, 0, 0x0c000, 0x080, 1, 0, 0x01400, 0x0100, 64, 0x2800, 0x1800, 10, 1, 40}, // atdf, avr-gcc 12.2.0, avrdude
|
||||||
|
{"AVR8EA28", 327, F_AVR8X, {0x1E, 0x93, 0x2C}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0200, 8, -1, -1, -1, -1, 0}, // avrdude
|
||||||
|
{"AVR8EA32", 328, F_AVR8X, {0x1E, 0x93, 0x2B}, 0, 0x02000, 0x040, 1, 0, 0x01400, 0x0200, 8, -1, -1, -1, -1, 0}, // avrdude
|
||||||
|
{"AVR16DD14", 329, F_AVR8X, {0x1E, 0x94, 0x34}, 0, 0x04000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x7800, 0x0800, 16, 4, 36}, // atdf, avrdude
|
||||||
|
{"AVR16DD20", 330, F_AVR8X, {0x1E, 0x94, 0x33}, 0, 0x04000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x7800, 0x0800, 16, 4, 36}, // atdf, avrdude
|
||||||
|
{"AVR16DD28", 331, F_AVR8X, {0x1E, 0x94, 0x32}, 0, 0x04000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x7800, 0x0800, 16, 4, 36}, // atdf, avrdude
|
||||||
|
{"AVR16EA28", 332, F_AVR8X, {0x1E, 0x94, 0x37}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0200, 8, -1, -1, -1, -1, 0}, // avrdude
|
||||||
|
{"AVR16DD32", 333, F_AVR8X, {0x1E, 0x94, 0x31}, 0, 0x04000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x7800, 0x0800, 16, 4, 36}, // atdf, avrdude
|
||||||
|
{"AVR16EA32", 334, F_AVR8X, {0x1E, 0x94, 0x36}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0200, 8, -1, -1, -1, -1, 0}, // avrdude
|
||||||
|
{"AVR16EA48", 335, F_AVR8X, {0x1E, 0x94, 0x35}, 0, 0x04000, 0x040, 1, 0, 0x01400, 0x0200, 8, -1, -1, -1, -1, 0}, // avrdude
|
||||||
|
{"AVR32DD14", 336, F_AVR8X, {0x1E, 0x95, 0x3B}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x7000, 0x1000, 16, 4, 36}, // atdf, avrdude
|
||||||
|
{"AVR32DD20", 337, F_AVR8X, {0x1E, 0x95, 0x3A}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x7000, 0x1000, 16, 4, 36}, // atdf, avrdude
|
||||||
|
{"AVR32DA28", 338, F_AVR8X, {0x1E, 0x95, 0x34}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x7000, 0x1000, 16, 4, 41}, // atdf, avrdude
|
||||||
|
{"AVR32DB28", 339, F_AVR8X, {0x1E, 0x95, 0x37}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x7000, 0x1000, 16, 4, 42}, // atdf, avrdude
|
||||||
|
{"AVR32DD28", 340, F_AVR8X, {0x1E, 0x95, 0x39}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x7000, 0x1000, 16, 4, 36}, // atdf, avrdude
|
||||||
|
{"AVR32EA28", 341, F_AVR8X, {0x1E, 0x95, 0x3E}, 0, 0x08000, 0x040, 1, 0, 0x01400, 0x0200, 8, -1, -1, -1, -1, 0}, // avrdude
|
||||||
|
{"AVR32DA32", 342, F_AVR8X, {0x1E, 0x95, 0x33}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x7000, 0x1000, 16, 4, 44}, // atdf, avrdude
|
||||||
|
{"AVR32DB32", 343, F_AVR8X, {0x1E, 0x95, 0x36}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x7000, 0x1000, 16, 4, 44}, // atdf, avrdude
|
||||||
|
{"AVR32DD32", 344, F_AVR8X, {0x1E, 0x95, 0x38}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x7000, 0x1000, 16, 4, 36}, // atdf, avrdude
|
||||||
|
{"AVR32EA32", 345, F_AVR8X, {0x1E, 0x95, 0x3D}, 0, 0x08000, 0x040, 1, 0, 0x01400, 0x0200, 8, -1, -1, -1, -1, 0}, // avrdude
|
||||||
|
{"AVR32DA48", 346, F_AVR8X, {0x1E, 0x95, 0x32}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x7000, 0x1000, 16, 4, 58}, // atdf, avrdude
|
||||||
|
{"AVR32DB48", 347, F_AVR8X, {0x1E, 0x95, 0x35}, 0, 0x08000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x7000, 0x1000, 16, 4, 61}, // atdf, avrdude
|
||||||
|
{"AVR32EA48", 348, F_AVR8X, {0x1E, 0x95, 0x3C}, 0, 0x08000, 0x040, 1, 0, 0x01400, 0x0200, 8, -1, -1, -1, -1, 0}, // avrdude
|
||||||
|
{"AVR64DD14", 349, F_AVR8X, {0x1E, 0x96, 0x1D}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x6000, 0x2000, 16, 4, 36}, // atdf, avrdude
|
||||||
|
{"AVR64DD20", 350, F_AVR8X, {0x1E, 0x96, 0x1C}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x6000, 0x2000, 16, 4, 36}, // atdf, avrdude
|
||||||
|
{"AVR64DA28", 351, F_AVR8X, {0x1E, 0x96, 0x15}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x6000, 0x2000, 16, 4, 41}, // atdf, avrdude
|
||||||
|
{"AVR64DB28", 352, F_AVR8X, {0x1E, 0x96, 0x19}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x6000, 0x2000, 16, 4, 42}, // atdf, avrdude
|
||||||
|
{"AVR64DD28", 353, F_AVR8X, {0x1E, 0x96, 0x1B}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x6000, 0x2000, 16, 4, 36}, // atdf, avrdude
|
||||||
|
{"AVR64EA28", 354, F_AVR8X, {0x1E, 0x96, 0x20}, 0, 0x10000, 0x080, 1, 0, 0x01400, 0x0200, 8, 0x6800, 0x1800, 16, 4, 37}, // atdf, avrdude
|
||||||
|
{"AVR64DA32", 355, F_AVR8X, {0x1E, 0x96, 0x14}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x6000, 0x2000, 16, 4, 44}, // atdf, avrdude
|
||||||
|
{"AVR64DB32", 356, F_AVR8X, {0x1E, 0x96, 0x18}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x6000, 0x2000, 16, 4, 44}, // atdf, avrdude
|
||||||
|
{"AVR64DD32", 357, F_AVR8X, {0x1E, 0x96, 0x1A}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0100, 1, 0x6000, 0x2000, 16, 4, 36}, // atdf, avrdude
|
||||||
|
{"AVR64EA32", 358, F_AVR8X, {0x1E, 0x96, 0x1F}, 0, 0x10000, 0x080, 1, 0, 0x01400, 0x0200, 8, 0x6800, 0x1800, 16, 4, 37}, // atdf, avrdude
|
||||||
|
{"AVR64DA48", 359, F_AVR8X, {0x1E, 0x96, 0x13}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x6000, 0x2000, 16, 4, 58}, // atdf, avrdude
|
||||||
|
{"AVR64DB48", 360, F_AVR8X, {0x1E, 0x96, 0x17}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x6000, 0x2000, 16, 4, 61}, // atdf, avrdude
|
||||||
|
{"AVR64EA48", 361, F_AVR8X, {0x1E, 0x96, 0x1E}, 0, 0x10000, 0x080, 1, 0, 0x01400, 0x0200, 8, 0x6800, 0x1800, 16, 4, 45}, // atdf, avrdude
|
||||||
|
{"AVR64DA64", 362, F_AVR8X, {0x1E, 0x96, 0x12}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x6000, 0x2000, 16, 4, 64}, // atdf, avrdude
|
||||||
|
{"AVR64DB64", 363, F_AVR8X, {0x1E, 0x96, 0x16}, 0, 0x10000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x6000, 0x2000, 16, 4, 65}, // atdf, avrdude
|
||||||
|
{"AVR128DA28", 364, F_AVR8X, {0x1E, 0x97, 0x0A}, 0, 0x20000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x4000, 0x4000, 16, 4, 41}, // atdf, avrdude
|
||||||
|
{"AVR128DB28", 365, F_AVR8X, {0x1E, 0x97, 0x0E}, 0, 0x20000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x4000, 0x4000, 16, 4, 42}, // atdf, avrdude
|
||||||
|
{"AVR128DA32", 366, F_AVR8X, {0x1E, 0x97, 0x09}, 0, 0x20000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x4000, 0x4000, 16, 4, 44}, // atdf, avrdude
|
||||||
|
{"AVR128DB32", 367, F_AVR8X, {0x1E, 0x97, 0x0D}, 0, 0x20000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x4000, 0x4000, 16, 4, 44}, // atdf, avrdude
|
||||||
|
{"AVR128DA48", 368, F_AVR8X, {0x1E, 0x97, 0x08}, 0, 0x20000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x4000, 0x4000, 16, 4, 58}, // atdf, avrdude
|
||||||
|
{"AVR128DB48", 369, F_AVR8X, {0x1E, 0x97, 0x0C}, 0, 0x20000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x4000, 0x4000, 16, 4, 61}, // atdf, avrdude
|
||||||
|
{"AVR128DA64", 370, F_AVR8X, {0x1E, 0x97, 0x07}, 0, 0x20000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x4000, 0x4000, 16, 4, 64}, // atdf, avrdude
|
||||||
|
{"AVR128DB64", 371, F_AVR8X, {0x1E, 0x97, 0x0B}, 0, 0x20000, 0x200, 1, 0, 0x01400, 0x0200, 1, 0x4000, 0x4000, 16, 4, 65}, // atdf, avrdude
|
||||||
|
};
|
||||||
|
|
||||||
|
const size_t avr_isp_chip_arr_size = COUNT_OF(avr_isp_chip_arr);
|
||||||
33
applications/external/avr_isp_programmer/lib/driver/avr_isp_chip_arr.h
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <furi_hal.h>
|
||||||
|
|
||||||
|
#define F_AVR8L 1 // TPI programming, ATtiny(4|5|9|10|20|40|102|104)
|
||||||
|
#define F_AVR8 2 // ISP programming with SPI, "classic" AVRs
|
||||||
|
#define F_XMEGA 4 // PDI programming, ATxmega family
|
||||||
|
#define F_AVR8X 8 // UPDI programming, newer 8-bit MCUs
|
||||||
|
|
||||||
|
struct AvrIspChipArr { // Value of -1 typically means unknown
|
||||||
|
const char* name; // Name of part
|
||||||
|
uint16_t mcuid; // ID of MCU in 0..2039
|
||||||
|
uint8_t avrarch; // F_AVR8L, F_AVR8, F_XMEGA or F_AVR8X
|
||||||
|
uint8_t sigs[3]; // Signature bytes
|
||||||
|
int32_t flashoffset; // Flash offset
|
||||||
|
int32_t flashsize; // Flash size
|
||||||
|
int16_t pagesize; // Flash page size
|
||||||
|
int8_t nboots; // Number of supported boot sectors
|
||||||
|
int16_t bootsize; // Size of (smallest) boot sector
|
||||||
|
int32_t eepromoffset; // EEPROM offset
|
||||||
|
int32_t eepromsize; // EEPROM size
|
||||||
|
int32_t eeprompagesize; // EEPROM page size
|
||||||
|
int32_t sramstart; // SRAM offset
|
||||||
|
int32_t sramsize; // SRAM size
|
||||||
|
int8_t nfuses; // Number of fuse bytes
|
||||||
|
int8_t nlocks; // Number of lock bytes
|
||||||
|
uint8_t ninterrupts; // Number of vectors in interrupt vector table
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct AvrIspChipArr AvrIspChipArr;
|
||||||
|
|
||||||
|
extern const AvrIspChipArr avr_isp_chip_arr[];
|
||||||
|
extern const size_t avr_isp_chip_arr_size;
|
||||||
639
applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c
vendored
Normal file
@@ -0,0 +1,639 @@
|
|||||||
|
#include "avr_isp_prog.h"
|
||||||
|
#include "avr_isp_prog_cmd.h"
|
||||||
|
|
||||||
|
#include <furi.h>
|
||||||
|
|
||||||
|
#define AVR_ISP_PROG_TX_RX_BUF_SIZE 320
|
||||||
|
#define TAG "AvrIspProg"
|
||||||
|
|
||||||
|
struct AvrIspProgSignature {
|
||||||
|
uint8_t vendor;
|
||||||
|
uint8_t part_family;
|
||||||
|
uint8_t part_number;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct AvrIspProgSignature AvrIspProgSignature;
|
||||||
|
|
||||||
|
struct AvrIspProgCfgDevice {
|
||||||
|
uint8_t devicecode;
|
||||||
|
uint8_t revision;
|
||||||
|
uint8_t progtype;
|
||||||
|
uint8_t parmode;
|
||||||
|
uint8_t polling;
|
||||||
|
uint8_t selftimed;
|
||||||
|
uint8_t lockbytes;
|
||||||
|
uint8_t fusebytes;
|
||||||
|
uint8_t flashpoll;
|
||||||
|
uint16_t eeprompoll;
|
||||||
|
uint16_t pagesize;
|
||||||
|
uint16_t eepromsize;
|
||||||
|
uint32_t flashsize;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct AvrIspProgCfgDevice AvrIspProgCfgDevice;
|
||||||
|
|
||||||
|
struct AvrIspProg {
|
||||||
|
AvrIspSpiSw* spi;
|
||||||
|
AvrIspProgCfgDevice* cfg;
|
||||||
|
FuriStreamBuffer* stream_rx;
|
||||||
|
FuriStreamBuffer* stream_tx;
|
||||||
|
|
||||||
|
uint16_t error;
|
||||||
|
uint16_t addr;
|
||||||
|
bool pmode;
|
||||||
|
bool exit;
|
||||||
|
bool rst_active_high;
|
||||||
|
uint8_t buff[AVR_ISP_PROG_TX_RX_BUF_SIZE];
|
||||||
|
|
||||||
|
AvrIspProgCallback callback;
|
||||||
|
void* context;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void avr_isp_prog_end_pmode(AvrIspProg* instance);
|
||||||
|
|
||||||
|
AvrIspProg* avr_isp_prog_init(void) {
|
||||||
|
AvrIspProg* instance = malloc(sizeof(AvrIspProg));
|
||||||
|
instance->cfg = malloc(sizeof(AvrIspProgCfgDevice));
|
||||||
|
instance->stream_rx =
|
||||||
|
furi_stream_buffer_alloc(sizeof(int8_t) * AVR_ISP_PROG_TX_RX_BUF_SIZE, sizeof(int8_t));
|
||||||
|
instance->stream_tx =
|
||||||
|
furi_stream_buffer_alloc(sizeof(int8_t) * AVR_ISP_PROG_TX_RX_BUF_SIZE, sizeof(int8_t));
|
||||||
|
instance->rst_active_high = false;
|
||||||
|
instance->exit = false;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void avr_isp_prog_free(AvrIspProg* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
if(instance->spi) avr_isp_prog_end_pmode(instance);
|
||||||
|
furi_stream_buffer_free(instance->stream_tx);
|
||||||
|
furi_stream_buffer_free(instance->stream_rx);
|
||||||
|
free(instance->cfg);
|
||||||
|
free(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t avr_isp_prog_spaces_rx(AvrIspProg* instance) {
|
||||||
|
return furi_stream_buffer_spaces_available(instance->stream_rx);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool avr_isp_prog_rx(AvrIspProg* instance, uint8_t* data, size_t len) {
|
||||||
|
furi_assert(instance);
|
||||||
|
furi_assert(data);
|
||||||
|
furi_assert(len != 0);
|
||||||
|
size_t ret = furi_stream_buffer_send(instance->stream_rx, data, sizeof(uint8_t) * len, 0);
|
||||||
|
return ret == sizeof(uint8_t) * len;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t avr_isp_prog_tx(AvrIspProg* instance, uint8_t* data, size_t max_len) {
|
||||||
|
furi_assert(instance);
|
||||||
|
return furi_stream_buffer_receive(instance->stream_tx, data, sizeof(int8_t) * max_len, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void avr_isp_prog_exit(AvrIspProg* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
instance->exit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void avr_isp_prog_set_tx_callback(AvrIspProg* instance, AvrIspProgCallback callback, void* context) {
|
||||||
|
furi_assert(instance);
|
||||||
|
furi_assert(context);
|
||||||
|
instance->callback = callback;
|
||||||
|
instance->context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void avr_isp_prog_tx_ch(AvrIspProg* instance, uint8_t data) {
|
||||||
|
furi_assert(instance);
|
||||||
|
furi_stream_buffer_send(instance->stream_tx, &data, sizeof(uint8_t), FuriWaitForever);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t avr_isp_prog_getch(AvrIspProg* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
uint8_t data[1] = {0};
|
||||||
|
while(furi_stream_buffer_receive(instance->stream_rx, &data, sizeof(int8_t), 30) == 0) {
|
||||||
|
if(instance->exit) break;
|
||||||
|
};
|
||||||
|
return data[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void avr_isp_prog_fill(AvrIspProg* instance, size_t len) {
|
||||||
|
furi_assert(instance);
|
||||||
|
for(size_t x = 0; x < len; x++) {
|
||||||
|
instance->buff[x] = avr_isp_prog_getch(instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void avr_isp_prog_reset_target(AvrIspProg* instance, bool reset) {
|
||||||
|
furi_assert(instance);
|
||||||
|
avr_isp_spi_sw_res_set(instance->spi, (reset == instance->rst_active_high) ? true : false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t avr_isp_prog_spi_transaction(
|
||||||
|
AvrIspProg* instance,
|
||||||
|
uint8_t cmd,
|
||||||
|
uint8_t addr_hi,
|
||||||
|
uint8_t addr_lo,
|
||||||
|
uint8_t data) {
|
||||||
|
furi_assert(instance);
|
||||||
|
|
||||||
|
avr_isp_spi_sw_txrx(instance->spi, cmd);
|
||||||
|
avr_isp_spi_sw_txrx(instance->spi, addr_hi);
|
||||||
|
avr_isp_spi_sw_txrx(instance->spi, addr_lo);
|
||||||
|
return avr_isp_spi_sw_txrx(instance->spi, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void avr_isp_prog_empty_reply(AvrIspProg* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
if(avr_isp_prog_getch(instance) == CRC_EOP) {
|
||||||
|
avr_isp_prog_tx_ch(instance, STK_INSYNC);
|
||||||
|
avr_isp_prog_tx_ch(instance, STK_OK);
|
||||||
|
} else {
|
||||||
|
instance->error++;
|
||||||
|
avr_isp_prog_tx_ch(instance, STK_NOSYNC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void avr_isp_prog_breply(AvrIspProg* instance, uint8_t data) {
|
||||||
|
furi_assert(instance);
|
||||||
|
if(avr_isp_prog_getch(instance) == CRC_EOP) {
|
||||||
|
avr_isp_prog_tx_ch(instance, STK_INSYNC);
|
||||||
|
avr_isp_prog_tx_ch(instance, data);
|
||||||
|
avr_isp_prog_tx_ch(instance, STK_OK);
|
||||||
|
} else {
|
||||||
|
instance->error++;
|
||||||
|
avr_isp_prog_tx_ch(instance, STK_NOSYNC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void avr_isp_prog_get_version(AvrIspProg* instance, uint8_t data) {
|
||||||
|
furi_assert(instance);
|
||||||
|
switch(data) {
|
||||||
|
case STK_HW_VER:
|
||||||
|
avr_isp_prog_breply(instance, AVR_ISP_HWVER);
|
||||||
|
break;
|
||||||
|
case STK_SW_MAJOR:
|
||||||
|
avr_isp_prog_breply(instance, AVR_ISP_SWMAJ);
|
||||||
|
break;
|
||||||
|
case STK_SW_MINOR:
|
||||||
|
avr_isp_prog_breply(instance, AVR_ISP_SWMIN);
|
||||||
|
break;
|
||||||
|
case AVP_ISP_CONNECT_TYPE:
|
||||||
|
avr_isp_prog_breply(instance, AVP_ISP_SERIAL_CONNECT_TYPE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
avr_isp_prog_breply(instance, AVR_ISP_RESP_0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void avr_isp_prog_set_cfg(AvrIspProg* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
// call this after reading cfg packet into buff[]
|
||||||
|
instance->cfg->devicecode = instance->buff[0];
|
||||||
|
instance->cfg->revision = instance->buff[1];
|
||||||
|
instance->cfg->progtype = instance->buff[2];
|
||||||
|
instance->cfg->parmode = instance->buff[3];
|
||||||
|
instance->cfg->polling = instance->buff[4];
|
||||||
|
instance->cfg->selftimed = instance->buff[5];
|
||||||
|
instance->cfg->lockbytes = instance->buff[6];
|
||||||
|
instance->cfg->fusebytes = instance->buff[7];
|
||||||
|
instance->cfg->flashpoll = instance->buff[8];
|
||||||
|
// ignore (instance->buff[9] == instance->buff[8]) //FLASH polling value. Same as <20>flashpoll<6C>
|
||||||
|
instance->cfg->eeprompoll = instance->buff[10] << 8 | instance->buff[11];
|
||||||
|
instance->cfg->pagesize = instance->buff[12] << 8 | instance->buff[13];
|
||||||
|
instance->cfg->eepromsize = instance->buff[14] << 8 | instance->buff[15];
|
||||||
|
instance->cfg->flashsize = instance->buff[16] << 24 | instance->buff[17] << 16 |
|
||||||
|
instance->buff[18] << 8 | instance->buff[19];
|
||||||
|
|
||||||
|
// avr devices have active low reset, at89sx are active high
|
||||||
|
instance->rst_active_high = (instance->cfg->devicecode >= 0xe0);
|
||||||
|
}
|
||||||
|
static bool
|
||||||
|
avr_isp_prog_set_pmode(AvrIspProg* instance, uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
|
||||||
|
furi_assert(instance);
|
||||||
|
uint8_t res = 0;
|
||||||
|
avr_isp_spi_sw_txrx(instance->spi, a);
|
||||||
|
avr_isp_spi_sw_txrx(instance->spi, b);
|
||||||
|
res = avr_isp_spi_sw_txrx(instance->spi, c);
|
||||||
|
avr_isp_spi_sw_txrx(instance->spi, d);
|
||||||
|
return res == 0x53;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void avr_isp_prog_end_pmode(AvrIspProg* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
if(instance->pmode) {
|
||||||
|
avr_isp_prog_reset_target(instance, false);
|
||||||
|
// We're about to take the target out of reset
|
||||||
|
// so configure SPI pins as input
|
||||||
|
|
||||||
|
if(instance->spi) avr_isp_spi_sw_free(instance->spi);
|
||||||
|
instance->spi = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
instance->pmode = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool avr_isp_prog_start_pmode(AvrIspProg* instance, AvrIspSpiSwSpeed spi_speed) {
|
||||||
|
furi_assert(instance);
|
||||||
|
// Reset target before driving PIN_SCK or PIN_MOSI
|
||||||
|
|
||||||
|
// SPI.begin() will configure SS as output,
|
||||||
|
// so SPI master mode is selected.
|
||||||
|
// We have defined RESET as pin 10,
|
||||||
|
// which for many arduino's is not the SS pin.
|
||||||
|
// So we have to configure RESET as output here,
|
||||||
|
// (reset_target() first sets the correct level)
|
||||||
|
if(instance->spi) avr_isp_spi_sw_free(instance->spi);
|
||||||
|
instance->spi = avr_isp_spi_sw_init(spi_speed);
|
||||||
|
|
||||||
|
avr_isp_prog_reset_target(instance, true);
|
||||||
|
// See avr datasheets, chapter "SERIAL_PRG Programming Algorithm":
|
||||||
|
|
||||||
|
// Pulse RESET after PIN_SCK is low:
|
||||||
|
avr_isp_spi_sw_sck_set(instance->spi, false);
|
||||||
|
|
||||||
|
// discharge PIN_SCK, value arbitrally chosen
|
||||||
|
furi_delay_ms(20);
|
||||||
|
avr_isp_prog_reset_target(instance, false);
|
||||||
|
|
||||||
|
// Pulse must be minimum 2 target CPU speed cycles
|
||||||
|
// so 100 usec is ok for CPU speeds above 20KHz
|
||||||
|
furi_delay_ms(1);
|
||||||
|
|
||||||
|
avr_isp_prog_reset_target(instance, true);
|
||||||
|
|
||||||
|
// Send the enable programming command:
|
||||||
|
// datasheet: must be > 20 msec
|
||||||
|
furi_delay_ms(50);
|
||||||
|
if(avr_isp_prog_set_pmode(instance, AVR_ISP_SET_PMODE)) {
|
||||||
|
instance->pmode = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static AvrIspProgSignature avr_isp_prog_check_signature(AvrIspProg* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
AvrIspProgSignature signature;
|
||||||
|
signature.vendor = avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_VENDOR);
|
||||||
|
signature.part_family = avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_PART_FAMILY);
|
||||||
|
signature.part_number = avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_PART_NUMBER);
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool avr_isp_prog_auto_set_spi_speed_start_pmode(AvrIspProg* instance) {
|
||||||
|
AvrIspSpiSwSpeed spi_speed[] = {
|
||||||
|
AvrIspSpiSwSpeed1Mhz,
|
||||||
|
AvrIspSpiSwSpeed400Khz,
|
||||||
|
AvrIspSpiSwSpeed250Khz,
|
||||||
|
AvrIspSpiSwSpeed125Khz,
|
||||||
|
AvrIspSpiSwSpeed60Khz,
|
||||||
|
AvrIspSpiSwSpeed40Khz,
|
||||||
|
AvrIspSpiSwSpeed20Khz,
|
||||||
|
AvrIspSpiSwSpeed10Khz,
|
||||||
|
AvrIspSpiSwSpeed5Khz,
|
||||||
|
AvrIspSpiSwSpeed1Khz,
|
||||||
|
};
|
||||||
|
for(uint8_t i = 0; i < COUNT_OF(spi_speed); i++) {
|
||||||
|
if(avr_isp_prog_start_pmode(instance, spi_speed[i])) {
|
||||||
|
AvrIspProgSignature sig = avr_isp_prog_check_signature(instance);
|
||||||
|
AvrIspProgSignature sig_examination = avr_isp_prog_check_signature(instance); //-V656
|
||||||
|
uint8_t y = 0;
|
||||||
|
while(y < 8) {
|
||||||
|
if(memcmp(
|
||||||
|
(uint8_t*)&sig, (uint8_t*)&sig_examination, sizeof(AvrIspProgSignature)) !=
|
||||||
|
0)
|
||||||
|
break;
|
||||||
|
sig_examination = avr_isp_prog_check_signature(instance);
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
if(y == 8) {
|
||||||
|
if(spi_speed[i] > AvrIspSpiSwSpeed1Mhz) {
|
||||||
|
if(i < (COUNT_OF(spi_speed) - 1)) {
|
||||||
|
avr_isp_prog_end_pmode(instance);
|
||||||
|
i++;
|
||||||
|
return avr_isp_prog_start_pmode(instance, spi_speed[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(instance->spi) {
|
||||||
|
avr_isp_spi_sw_free(instance->spi);
|
||||||
|
instance->spi = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void avr_isp_prog_universal(AvrIspProg* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
uint8_t data;
|
||||||
|
|
||||||
|
avr_isp_prog_fill(instance, 4);
|
||||||
|
data = avr_isp_prog_spi_transaction(
|
||||||
|
instance, instance->buff[0], instance->buff[1], instance->buff[2], instance->buff[3]);
|
||||||
|
avr_isp_prog_breply(instance, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void avr_isp_prog_commit(AvrIspProg* instance, uint16_t addr, uint8_t data) {
|
||||||
|
furi_assert(instance);
|
||||||
|
avr_isp_prog_spi_transaction(instance, AVR_ISP_COMMIT(addr));
|
||||||
|
/* polling flash */
|
||||||
|
if(data == 0xFF) {
|
||||||
|
furi_delay_ms(5);
|
||||||
|
} else {
|
||||||
|
/* polling flash */
|
||||||
|
uint32_t starttime = furi_get_tick();
|
||||||
|
while((furi_get_tick() - starttime) < 30) {
|
||||||
|
if(avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_FLASH_HI(addr)) != 0xFF) {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t avr_isp_prog_current_page(AvrIspProg* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
uint16_t page = 0;
|
||||||
|
switch(instance->cfg->pagesize) {
|
||||||
|
case 32:
|
||||||
|
page = instance->addr & 0xFFFFFFF0;
|
||||||
|
break;
|
||||||
|
case 64:
|
||||||
|
page = instance->addr & 0xFFFFFFE0;
|
||||||
|
break;
|
||||||
|
case 128:
|
||||||
|
page = instance->addr & 0xFFFFFFC0;
|
||||||
|
break;
|
||||||
|
case 256:
|
||||||
|
page = instance->addr & 0xFFFFFF80;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
page = instance->addr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t avr_isp_prog_write_flash_pages(AvrIspProg* instance, size_t length) {
|
||||||
|
furi_assert(instance);
|
||||||
|
size_t x = 0;
|
||||||
|
uint16_t page = avr_isp_prog_current_page(instance);
|
||||||
|
while(x < length) {
|
||||||
|
if(page != avr_isp_prog_current_page(instance)) {
|
||||||
|
--x;
|
||||||
|
avr_isp_prog_commit(instance, page, instance->buff[x++]);
|
||||||
|
page = avr_isp_prog_current_page(instance);
|
||||||
|
}
|
||||||
|
avr_isp_prog_spi_transaction(
|
||||||
|
instance, AVR_ISP_WRITE_FLASH_LO(instance->addr, instance->buff[x++]));
|
||||||
|
|
||||||
|
avr_isp_prog_spi_transaction(
|
||||||
|
instance, AVR_ISP_WRITE_FLASH_HI(instance->addr, instance->buff[x++]));
|
||||||
|
instance->addr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
avr_isp_prog_commit(instance, page, instance->buff[--x]);
|
||||||
|
return STK_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void avr_isp_prog_write_flash(AvrIspProg* instance, size_t length) {
|
||||||
|
furi_assert(instance);
|
||||||
|
avr_isp_prog_fill(instance, length);
|
||||||
|
if(avr_isp_prog_getch(instance) == CRC_EOP) {
|
||||||
|
avr_isp_prog_tx_ch(instance, STK_INSYNC);
|
||||||
|
avr_isp_prog_tx_ch(instance, avr_isp_prog_write_flash_pages(instance, length));
|
||||||
|
} else {
|
||||||
|
instance->error++;
|
||||||
|
avr_isp_prog_tx_ch(instance, STK_NOSYNC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// write (length) bytes, (start) is a byte address
|
||||||
|
static uint8_t
|
||||||
|
avr_isp_prog_write_eeprom_chunk(AvrIspProg* instance, uint16_t start, uint16_t length) {
|
||||||
|
furi_assert(instance);
|
||||||
|
// this writes byte-by-byte,
|
||||||
|
// page writing may be faster (4 bytes at a time)
|
||||||
|
avr_isp_prog_fill(instance, length);
|
||||||
|
for(uint16_t x = 0; x < length; x++) {
|
||||||
|
uint16_t addr = start + x;
|
||||||
|
avr_isp_prog_spi_transaction(instance, AVR_ISP_WRITE_EEPROM(addr, instance->buff[x]));
|
||||||
|
furi_delay_ms(10);
|
||||||
|
}
|
||||||
|
return STK_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t avr_isp_prog_write_eeprom(AvrIspProg* instance, size_t length) {
|
||||||
|
furi_assert(instance);
|
||||||
|
// here is a word address, get the byte address
|
||||||
|
uint16_t start = instance->addr * 2;
|
||||||
|
uint16_t remaining = length;
|
||||||
|
if(length > instance->cfg->eepromsize) {
|
||||||
|
instance->error++;
|
||||||
|
return STK_FAILED;
|
||||||
|
}
|
||||||
|
while(remaining > AVR_ISP_EECHUNK) {
|
||||||
|
avr_isp_prog_write_eeprom_chunk(instance, start, AVR_ISP_EECHUNK);
|
||||||
|
start += AVR_ISP_EECHUNK;
|
||||||
|
remaining -= AVR_ISP_EECHUNK;
|
||||||
|
}
|
||||||
|
avr_isp_prog_write_eeprom_chunk(instance, start, remaining);
|
||||||
|
return STK_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void avr_isp_prog_program_page(AvrIspProg* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
uint8_t result = STK_FAILED;
|
||||||
|
uint16_t length = avr_isp_prog_getch(instance) << 8 | avr_isp_prog_getch(instance);
|
||||||
|
uint8_t memtype = avr_isp_prog_getch(instance);
|
||||||
|
// flash memory @addr, (length) bytes
|
||||||
|
if(memtype == STK_SET_FLASH_TYPE) {
|
||||||
|
avr_isp_prog_write_flash(instance, length);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(memtype == STK_SET_EEPROM_TYPE) {
|
||||||
|
result = avr_isp_prog_write_eeprom(instance, length);
|
||||||
|
if(avr_isp_prog_getch(instance) == CRC_EOP) {
|
||||||
|
avr_isp_prog_tx_ch(instance, STK_INSYNC);
|
||||||
|
avr_isp_prog_tx_ch(instance, result);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
instance->error++;
|
||||||
|
avr_isp_prog_tx_ch(instance, STK_NOSYNC);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
avr_isp_prog_tx_ch(instance, STK_FAILED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t avr_isp_prog_flash_read_page(AvrIspProg* instance, uint16_t length) {
|
||||||
|
furi_assert(instance);
|
||||||
|
for(uint16_t x = 0; x < length; x += 2) {
|
||||||
|
avr_isp_prog_tx_ch(
|
||||||
|
instance,
|
||||||
|
avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_FLASH_LO(instance->addr)));
|
||||||
|
avr_isp_prog_tx_ch(
|
||||||
|
instance,
|
||||||
|
avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_FLASH_HI(instance->addr)));
|
||||||
|
instance->addr++;
|
||||||
|
}
|
||||||
|
return STK_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t avr_isp_prog_eeprom_read_page(AvrIspProg* instance, uint16_t length) {
|
||||||
|
furi_assert(instance);
|
||||||
|
// here again we have a word address
|
||||||
|
uint16_t start = instance->addr * 2;
|
||||||
|
for(uint16_t x = 0; x < length; x++) {
|
||||||
|
uint16_t addr = start + x;
|
||||||
|
avr_isp_prog_tx_ch(
|
||||||
|
instance, avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_EEPROM(addr)));
|
||||||
|
}
|
||||||
|
return STK_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void avr_isp_prog_read_page(AvrIspProg* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
uint8_t result = STK_FAILED;
|
||||||
|
uint16_t length = avr_isp_prog_getch(instance) << 8 | avr_isp_prog_getch(instance);
|
||||||
|
uint8_t memtype = avr_isp_prog_getch(instance);
|
||||||
|
if(avr_isp_prog_getch(instance) != CRC_EOP) {
|
||||||
|
instance->error++;
|
||||||
|
avr_isp_prog_tx_ch(instance, STK_NOSYNC);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
avr_isp_prog_tx_ch(instance, STK_INSYNC);
|
||||||
|
if(memtype == STK_SET_FLASH_TYPE) result = avr_isp_prog_flash_read_page(instance, length);
|
||||||
|
if(memtype == STK_SET_EEPROM_TYPE) result = avr_isp_prog_eeprom_read_page(instance, length);
|
||||||
|
avr_isp_prog_tx_ch(instance, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void avr_isp_prog_read_signature(AvrIspProg* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
if(avr_isp_prog_getch(instance) != CRC_EOP) {
|
||||||
|
instance->error++;
|
||||||
|
avr_isp_prog_tx_ch(instance, STK_NOSYNC);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
avr_isp_prog_tx_ch(instance, STK_INSYNC);
|
||||||
|
|
||||||
|
avr_isp_prog_tx_ch(instance, avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_VENDOR));
|
||||||
|
avr_isp_prog_tx_ch(instance, avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_PART_FAMILY));
|
||||||
|
avr_isp_prog_tx_ch(instance, avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_PART_NUMBER));
|
||||||
|
|
||||||
|
avr_isp_prog_tx_ch(instance, STK_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void avr_isp_prog_avrisp(AvrIspProg* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
uint8_t ch = avr_isp_prog_getch(instance);
|
||||||
|
|
||||||
|
switch(ch) {
|
||||||
|
case STK_GET_SYNC:
|
||||||
|
FURI_LOG_D(TAG, "cmd STK_GET_SYNC");
|
||||||
|
instance->error = 0;
|
||||||
|
avr_isp_prog_empty_reply(instance);
|
||||||
|
break;
|
||||||
|
case STK_GET_SIGN_ON:
|
||||||
|
FURI_LOG_D(TAG, "cmd STK_GET_SIGN_ON");
|
||||||
|
if(avr_isp_prog_getch(instance) == CRC_EOP) {
|
||||||
|
avr_isp_prog_tx_ch(instance, STK_INSYNC);
|
||||||
|
|
||||||
|
avr_isp_prog_tx_ch(instance, 'A');
|
||||||
|
avr_isp_prog_tx_ch(instance, 'V');
|
||||||
|
avr_isp_prog_tx_ch(instance, 'R');
|
||||||
|
avr_isp_prog_tx_ch(instance, ' ');
|
||||||
|
avr_isp_prog_tx_ch(instance, 'I');
|
||||||
|
avr_isp_prog_tx_ch(instance, 'S');
|
||||||
|
avr_isp_prog_tx_ch(instance, 'P');
|
||||||
|
|
||||||
|
avr_isp_prog_tx_ch(instance, STK_OK);
|
||||||
|
} else {
|
||||||
|
instance->error++;
|
||||||
|
avr_isp_prog_tx_ch(instance, STK_NOSYNC);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case STK_GET_PARAMETER:
|
||||||
|
FURI_LOG_D(TAG, "cmd STK_GET_PARAMETER");
|
||||||
|
avr_isp_prog_get_version(instance, avr_isp_prog_getch(instance));
|
||||||
|
break;
|
||||||
|
case STK_SET_DEVICE:
|
||||||
|
FURI_LOG_D(TAG, "cmd STK_SET_DEVICE");
|
||||||
|
avr_isp_prog_fill(instance, 20);
|
||||||
|
avr_isp_prog_set_cfg(instance);
|
||||||
|
avr_isp_prog_empty_reply(instance);
|
||||||
|
break;
|
||||||
|
case STK_SET_DEVICE_EXT: // ignore for now
|
||||||
|
FURI_LOG_D(TAG, "cmd STK_SET_DEVICE_EXT");
|
||||||
|
avr_isp_prog_fill(instance, 5);
|
||||||
|
avr_isp_prog_empty_reply(instance);
|
||||||
|
break;
|
||||||
|
case STK_ENTER_PROGMODE:
|
||||||
|
FURI_LOG_D(TAG, "cmd STK_ENTER_PROGMODE");
|
||||||
|
if(!instance->pmode) avr_isp_prog_auto_set_spi_speed_start_pmode(instance);
|
||||||
|
avr_isp_prog_empty_reply(instance);
|
||||||
|
break;
|
||||||
|
case STK_LOAD_ADDRESS:
|
||||||
|
FURI_LOG_D(TAG, "cmd STK_LOAD_ADDRESS");
|
||||||
|
instance->addr = avr_isp_prog_getch(instance) | avr_isp_prog_getch(instance) << 8;
|
||||||
|
avr_isp_prog_empty_reply(instance);
|
||||||
|
break;
|
||||||
|
case STK_PROG_FLASH: // ignore for now
|
||||||
|
FURI_LOG_D(TAG, "cmd STK_PROG_FLASH");
|
||||||
|
avr_isp_prog_getch(instance);
|
||||||
|
avr_isp_prog_getch(instance);
|
||||||
|
avr_isp_prog_empty_reply(instance);
|
||||||
|
break;
|
||||||
|
case STK_PROG_DATA: // ignore for now
|
||||||
|
FURI_LOG_D(TAG, "cmd STK_PROG_DATA");
|
||||||
|
avr_isp_prog_getch(instance);
|
||||||
|
avr_isp_prog_empty_reply(instance);
|
||||||
|
break;
|
||||||
|
case STK_PROG_PAGE:
|
||||||
|
FURI_LOG_D(TAG, "cmd STK_PROG_PAGE");
|
||||||
|
avr_isp_prog_program_page(instance);
|
||||||
|
break;
|
||||||
|
case STK_READ_PAGE:
|
||||||
|
FURI_LOG_D(TAG, "cmd STK_READ_PAGE");
|
||||||
|
avr_isp_prog_read_page(instance);
|
||||||
|
break;
|
||||||
|
case STK_UNIVERSAL:
|
||||||
|
FURI_LOG_D(TAG, "cmd STK_UNIVERSAL");
|
||||||
|
avr_isp_prog_universal(instance);
|
||||||
|
break;
|
||||||
|
case STK_LEAVE_PROGMODE:
|
||||||
|
FURI_LOG_D(TAG, "cmd STK_LEAVE_PROGMODE");
|
||||||
|
instance->error = 0;
|
||||||
|
if(instance->pmode) avr_isp_prog_end_pmode(instance);
|
||||||
|
avr_isp_prog_empty_reply(instance);
|
||||||
|
break;
|
||||||
|
case STK_READ_SIGN:
|
||||||
|
FURI_LOG_D(TAG, "cmd STK_READ_SIGN");
|
||||||
|
avr_isp_prog_read_signature(instance);
|
||||||
|
break;
|
||||||
|
// expecting a command, not CRC_EOP
|
||||||
|
// this is how we can get back in sync
|
||||||
|
case CRC_EOP:
|
||||||
|
FURI_LOG_D(TAG, "cmd CRC_EOP");
|
||||||
|
instance->error++;
|
||||||
|
avr_isp_prog_tx_ch(instance, STK_NOSYNC);
|
||||||
|
break;
|
||||||
|
// anything else we will return STK_UNKNOWN
|
||||||
|
default:
|
||||||
|
FURI_LOG_D(TAG, "cmd STK_ERROR_CMD");
|
||||||
|
instance->error++;
|
||||||
|
if(avr_isp_prog_getch(instance) == CRC_EOP)
|
||||||
|
avr_isp_prog_tx_ch(instance, STK_UNKNOWN);
|
||||||
|
else
|
||||||
|
avr_isp_prog_tx_ch(instance, STK_NOSYNC);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(instance->callback) {
|
||||||
|
instance->callback(instance->context);
|
||||||
|
}
|
||||||
|
}
|
||||||
16
applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.h
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "avr_isp_spi_sw.h"
|
||||||
|
#include <furi_hal.h>
|
||||||
|
|
||||||
|
typedef struct AvrIspProg AvrIspProg;
|
||||||
|
typedef void (*AvrIspProgCallback)(void* context);
|
||||||
|
|
||||||
|
AvrIspProg* avr_isp_prog_init(void);
|
||||||
|
void avr_isp_prog_free(AvrIspProg* instance);
|
||||||
|
size_t avr_isp_prog_spaces_rx(AvrIspProg* instance) ;
|
||||||
|
bool avr_isp_prog_rx(AvrIspProg* instance, uint8_t* data, size_t len);
|
||||||
|
size_t avr_isp_prog_tx(AvrIspProg* instance, uint8_t* data, size_t max_len);
|
||||||
|
void avr_isp_prog_avrisp(AvrIspProg* instance);
|
||||||
|
void avr_isp_prog_exit(AvrIspProg* instance);
|
||||||
|
void avr_isp_prog_set_tx_callback(AvrIspProg* instance, AvrIspProgCallback callback, void* context);
|
||||||
97
applications/external/avr_isp_programmer/lib/driver/avr_isp_prog_cmd.h
vendored
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// http://ww1.microchip.com/downloads/en/appnotes/atmel-0943-in-system-programming_applicationnote_avr910.pdf
|
||||||
|
// AVR ISP Definitions
|
||||||
|
#define AVR_ISP_HWVER 0X02
|
||||||
|
#define AVR_ISP_SWMAJ 0X01
|
||||||
|
#define AVR_ISP_SWMIN 0X12
|
||||||
|
#define AVP_ISP_SERIAL_CONNECT_TYPE 0X53
|
||||||
|
#define AVP_ISP_CONNECT_TYPE 0x93
|
||||||
|
#define AVR_ISP_RESP_0 0X00
|
||||||
|
|
||||||
|
#define AVR_ISP_SET_PMODE 0xAC, 0x53, 0x00, 0x00
|
||||||
|
#define AVR_ISP_READ_VENDOR 0x30, 0x00, 0x00, 0x00
|
||||||
|
#define AVR_ISP_READ_PART_FAMILY 0x30, 0x00, 0x01, 0x00
|
||||||
|
#define AVR_ISP_READ_PART_NUMBER 0x30, 0x00, 0x02, 0x00
|
||||||
|
#define AVR_ISP_ERASE_CHIP \
|
||||||
|
0xAC, 0x80, 0x00, 0x00 //Erase Chip, Wait N ms, Release RESET to end the erase.
|
||||||
|
//The only way to end a Chip Erase cycle is by temporarily releasing the Reset line
|
||||||
|
|
||||||
|
#define AVR_ISP_EXTENDED_ADDR(data) 0x4D, 0x00, data, 0x00
|
||||||
|
#define AVR_ISP_WRITE_FLASH_LO(add, data) 0x40, (add >> 8) & 0xFF, add & 0xFF, data
|
||||||
|
#define AVR_ISP_WRITE_FLASH_HI(add, data) 0x48, (add >> 8) & 0xFF, add & 0xFF, data
|
||||||
|
#define AVR_ISP_READ_FLASH_LO(add) 0x20, (add >> 8) & 0xFF, add & 0xFF, 0x00
|
||||||
|
#define AVR_ISP_READ_FLASH_HI(add) 0x28, (add >> 8) & 0xFF, add & 0xFF, 0x00
|
||||||
|
|
||||||
|
#define AVR_ISP_WRITE_EEPROM(add, data) \
|
||||||
|
0xC0, (add >> 8) & 0xFF, add & 0xFF, data //Send cmd, Wait N ms
|
||||||
|
#define AVR_ISP_READ_EEPROM(add) 0xA0, (add >> 8) & 0xFF, add & 0xFF, 0xFF
|
||||||
|
|
||||||
|
#define AVR_ISP_COMMIT(add) \
|
||||||
|
0x4C, (add >> 8) & 0xFF, add & 0xFF, 0x00 //Send cmd, polling read last addr page
|
||||||
|
|
||||||
|
#define AVR_ISP_OSCCAL(add) 0x38, 0x00, add, 0x00
|
||||||
|
|
||||||
|
#define AVR_ISP_WRITE_LOCK_BYTE(data) 0xAC, 0xE0, 0x00, data //Send cmd, Wait N ms
|
||||||
|
#define AVR_ISP_READ_LOCK_BYTE 0x58, 0x00, 0x00, 0x00
|
||||||
|
#define AVR_ISP_WRITE_FUSE_LOW(data) 0xAC, 0xA0, 0x00, data //Send cmd, Wait N ms
|
||||||
|
#define AVR_ISP_READ_FUSE_LOW 0x50, 0x00, 0x00, 0x00
|
||||||
|
#define AVR_ISP_WRITE_FUSE_HIGH(data) 0xAC, 0xA8, 0x00, data //Send cmd, Wait N ms
|
||||||
|
#define AVR_ISP_READ_FUSE_HIGH 0x58, 0x08, 0x00, 0x00
|
||||||
|
#define AVR_ISP_WRITE_FUSE_EXTENDED(data) 0xAC, 0xA4, 0x00, data //Send cmd, Wait N ms (~write)
|
||||||
|
#define AVR_ISP_READ_FUSE_EXTENDED 0x50, 0x08, 0x00, 0x00
|
||||||
|
|
||||||
|
#define AVR_ISP_EECHUNK 0x20
|
||||||
|
|
||||||
|
// https://www.microchip.com/content/dam/mchp/documents/OTH/ApplicationNotes/ApplicationNotes/doc2525.pdf
|
||||||
|
// STK Definitions
|
||||||
|
#define STK_OK 0x10
|
||||||
|
#define STK_FAILED 0x11
|
||||||
|
#define STK_UNKNOWN 0x12
|
||||||
|
#define STK_INSYNC 0x14
|
||||||
|
#define STK_NOSYNC 0x15
|
||||||
|
#define CRC_EOP 0x20
|
||||||
|
|
||||||
|
#define STK_GET_SYNC 0x30
|
||||||
|
#define STK_GET_SIGN_ON 0x31
|
||||||
|
#define STK_SET_PARAMETER 0x40
|
||||||
|
#define STK_GET_PARAMETER 0x41
|
||||||
|
#define STK_SET_DEVICE 0x42
|
||||||
|
#define STK_SET_DEVICE_EXT 0x45
|
||||||
|
#define STK_ENTER_PROGMODE 0x50
|
||||||
|
#define STK_LEAVE_PROGMODE 0x51
|
||||||
|
#define STK_CHIP_ERASE 0x52
|
||||||
|
#define STK_CHECK_AUTOINC 0x53
|
||||||
|
#define STK_LOAD_ADDRESS 0x55
|
||||||
|
#define STK_UNIVERSAL 0x56
|
||||||
|
#define STK_UNIVERSAL_MULTI 0x57
|
||||||
|
#define STK_PROG_FLASH 0x60
|
||||||
|
#define STK_PROG_DATA 0x61
|
||||||
|
#define STK_PROG_FUSE 0x62
|
||||||
|
#define STK_PROG_FUSE_EXT 0x65
|
||||||
|
#define STK_PROG_LOCK 0x63
|
||||||
|
#define STK_PROG_PAGE 0x64
|
||||||
|
#define STK_READ_FLASH 0x70
|
||||||
|
#define STK_READ_DATA 0x71
|
||||||
|
#define STK_READ_FUSE 0x72
|
||||||
|
#define STK_READ_LOCK 0x73
|
||||||
|
#define STK_READ_PAGE 0x74
|
||||||
|
#define STK_READ_SIGN 0x75
|
||||||
|
#define STK_READ_OSCCAL 0x76
|
||||||
|
#define STK_READ_FUSE_EXT 0x77
|
||||||
|
#define STK_READ_OSCCAL_EXT 0x78
|
||||||
|
#define STK_HW_VER 0x80
|
||||||
|
#define STK_SW_MAJOR 0x81
|
||||||
|
#define STK_SW_MINOR 0x82
|
||||||
|
#define STK_LEDS 0x83
|
||||||
|
#define STK_VTARGET 0x84
|
||||||
|
#define STK_VADJUST 0x85
|
||||||
|
#define STK_OSC_PSCALE 0x86
|
||||||
|
#define STK_OSC_CMATCH 0x87
|
||||||
|
#define STK_SCK_DURATION 0x89
|
||||||
|
#define STK_BUFSIZEL 0x90
|
||||||
|
#define STK_BUFSIZEH 0x91
|
||||||
|
#define STK_STK500_TOPCARD_DETECT 0x98
|
||||||
|
|
||||||
|
#define STK_SET_EEPROM_TYPE 0X45
|
||||||
|
#define STK_SET_FLASH_TYPE 0X46
|
||||||
71
applications/external/avr_isp_programmer/lib/driver/avr_isp_spi_sw.c
vendored
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
#include "avr_isp_spi_sw.h"
|
||||||
|
|
||||||
|
#include <furi.h>
|
||||||
|
|
||||||
|
#define AVR_ISP_SPI_SW_MISO &gpio_ext_pa6
|
||||||
|
#define AVR_ISP_SPI_SW_MOSI &gpio_ext_pa7
|
||||||
|
#define AVR_ISP_SPI_SW_SCK &gpio_ext_pb3
|
||||||
|
#define AVR_ISP_RESET &gpio_ext_pb2
|
||||||
|
|
||||||
|
struct AvrIspSpiSw {
|
||||||
|
AvrIspSpiSwSpeed speed_wait_time;
|
||||||
|
const GpioPin* miso;
|
||||||
|
const GpioPin* mosi;
|
||||||
|
const GpioPin* sck;
|
||||||
|
const GpioPin* res;
|
||||||
|
};
|
||||||
|
|
||||||
|
AvrIspSpiSw* avr_isp_spi_sw_init(AvrIspSpiSwSpeed speed) {
|
||||||
|
AvrIspSpiSw* instance = malloc(sizeof(AvrIspSpiSw));
|
||||||
|
instance->speed_wait_time = speed;
|
||||||
|
instance->miso = AVR_ISP_SPI_SW_MISO;
|
||||||
|
instance->mosi = AVR_ISP_SPI_SW_MOSI;
|
||||||
|
instance->sck = AVR_ISP_SPI_SW_SCK;
|
||||||
|
instance->res = AVR_ISP_RESET;
|
||||||
|
|
||||||
|
furi_hal_gpio_init(instance->miso, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh);
|
||||||
|
furi_hal_gpio_write(instance->mosi, false);
|
||||||
|
furi_hal_gpio_init(instance->mosi, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||||
|
furi_hal_gpio_write(instance->sck, false);
|
||||||
|
furi_hal_gpio_init(instance->sck, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||||
|
furi_hal_gpio_init(instance->res, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void avr_isp_spi_sw_free(AvrIspSpiSw* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
furi_hal_gpio_init(instance->res, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||||
|
furi_hal_gpio_init(instance->miso, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||||
|
furi_hal_gpio_init(instance->mosi, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||||
|
furi_hal_gpio_init(instance->sck, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||||
|
free(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t avr_isp_spi_sw_txrx(AvrIspSpiSw* instance, uint8_t data) {
|
||||||
|
furi_assert(instance);
|
||||||
|
for(uint8_t i = 0; i < 8; ++i) {
|
||||||
|
furi_hal_gpio_write(instance->mosi, (data & 0x80) ? true : false);
|
||||||
|
|
||||||
|
furi_hal_gpio_write(instance->sck, true);
|
||||||
|
if(instance->speed_wait_time != AvrIspSpiSwSpeed1Mhz)
|
||||||
|
furi_delay_us(instance->speed_wait_time - 1);
|
||||||
|
|
||||||
|
data = (data << 1) | furi_hal_gpio_read(instance->miso); //-V792
|
||||||
|
|
||||||
|
furi_hal_gpio_write(instance->sck, false);
|
||||||
|
if(instance->speed_wait_time != AvrIspSpiSwSpeed1Mhz)
|
||||||
|
furi_delay_us(instance->speed_wait_time - 1);
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void avr_isp_spi_sw_res_set(AvrIspSpiSw* instance, bool state) {
|
||||||
|
furi_assert(instance);
|
||||||
|
furi_hal_gpio_write(instance->res, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void avr_isp_spi_sw_sck_set(AvrIspSpiSw* instance, bool state) {
|
||||||
|
furi_assert(instance);
|
||||||
|
furi_hal_gpio_write(instance->sck, state);
|
||||||
|
}
|
||||||
24
applications/external/avr_isp_programmer/lib/driver/avr_isp_spi_sw.h
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <furi_hal.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
AvrIspSpiSwSpeed1Mhz = 0,
|
||||||
|
AvrIspSpiSwSpeed400Khz = 1,
|
||||||
|
AvrIspSpiSwSpeed250Khz = 2,
|
||||||
|
AvrIspSpiSwSpeed125Khz = 4,
|
||||||
|
AvrIspSpiSwSpeed60Khz = 8,
|
||||||
|
AvrIspSpiSwSpeed40Khz = 12,
|
||||||
|
AvrIspSpiSwSpeed20Khz = 24,
|
||||||
|
AvrIspSpiSwSpeed10Khz = 48,
|
||||||
|
AvrIspSpiSwSpeed5Khz = 96,
|
||||||
|
AvrIspSpiSwSpeed1Khz = 480,
|
||||||
|
} AvrIspSpiSwSpeed;
|
||||||
|
|
||||||
|
typedef struct AvrIspSpiSw AvrIspSpiSw;
|
||||||
|
|
||||||
|
AvrIspSpiSw* avr_isp_spi_sw_init(AvrIspSpiSwSpeed speed);
|
||||||
|
void avr_isp_spi_sw_free(AvrIspSpiSw* instance);
|
||||||
|
uint8_t avr_isp_spi_sw_txrx(AvrIspSpiSw* instance, uint8_t data);
|
||||||
|
void avr_isp_spi_sw_res_set(AvrIspSpiSw* instance, bool state);
|
||||||
|
void avr_isp_spi_sw_sck_set(AvrIspSpiSw* instance, bool state);
|
||||||