فهرست منبع

New LF-RFID app (#534)

* Hal lfrfid: add read timer pulse and period config fns
* New debug application for lfrfid subsystem
* New lfrfid: app, fix naming
* App lfrfid: assets
* Container view module
* App ibutton: remove unused header
* App lfrfid scenes
* App notification, add yield to blocking operations, add speaker volume control
* App lfrfid: reading key scene
* Assets: placeholder icon
* App lfrfid: reworked container view module
* App lfrfid: new scenes
* App lfrfid: write scene
* App lfrfid: write hid
* App lfrfid: emulate scene
* App lfrfid: save name scene
* App lfrfid: add missing file
SG 4 سال پیش
والد
کامیت
22e1ecb642
100فایلهای تغییر یافته به همراه1010 افزوده شده و 998 حذف شده
  1. 10 3
      applications/applications.c
  2. 5 7
      applications/gui/modules/dialog_ex.c
  3. 1 1
      applications/gui/modules/dialog_ex.h
  4. 7 9
      applications/gui/modules/popup.c
  5. 1 1
      applications/gui/modules/popup.h
  6. 0 1
      applications/ibutton/ibutton-app.h
  7. 1 1
      applications/ibutton/scene/ibutton-scene-delete-success.cpp
  8. 1 1
      applications/ibutton/scene/ibutton-scene-emulate.cpp
  9. 1 1
      applications/ibutton/scene/ibutton-scene-read-success.cpp
  10. 1 1
      applications/ibutton/scene/ibutton-scene-read.cpp
  11. 1 1
      applications/ibutton/scene/ibutton-scene-save-success.cpp
  12. 1 1
      applications/ibutton/scene/ibutton-scene-write-success.cpp
  13. 1 1
      applications/ibutton/scene/ibutton-scene-write.cpp
  14. 1 1
      applications/irda/scene/irda-app-scene-edit-delete.cpp
  15. 0 140
      applications/lf-rfid/lf-rfid-app.cpp
  16. 0 79
      applications/lf-rfid/lf-rfid-app.h
  17. 0 21
      applications/lf-rfid/lf-rfid-event.h
  18. 0 90
      applications/lf-rfid/lf-rfid-view-manager.cpp
  19. 0 42
      applications/lf-rfid/lf-rfid-view-manager.h
  20. 0 10
      applications/lf-rfid/lf-rfid.cpp
  21. 0 34
      applications/lf-rfid/scene/lf-rfid-scene-emulate-emmarine.cpp
  22. 0 13
      applications/lf-rfid/scene/lf-rfid-scene-emulate-emmarine.h
  23. 0 34
      applications/lf-rfid/scene/lf-rfid-scene-emulate-hid.cpp
  24. 0 13
      applications/lf-rfid/scene/lf-rfid-scene-emulate-hid.h
  25. 0 34
      applications/lf-rfid/scene/lf-rfid-scene-emulate-indala.cpp
  26. 0 13
      applications/lf-rfid/scene/lf-rfid-scene-emulate-indala.h
  27. 0 14
      applications/lf-rfid/scene/lf-rfid-scene-generic.h
  28. 0 34
      applications/lf-rfid/scene/lf-rfid-scene-read-indala.cpp
  29. 0 15
      applications/lf-rfid/scene/lf-rfid-scene-read-indala.h
  30. 0 89
      applications/lf-rfid/scene/lf-rfid-scene-read-normal.cpp
  31. 0 15
      applications/lf-rfid/scene/lf-rfid-scene-read-normal.h
  32. 0 82
      applications/lf-rfid/scene/lf-rfid-scene-start.cpp
  33. 0 13
      applications/lf-rfid/scene/lf-rfid-scene-start.h
  34. 0 35
      applications/lf-rfid/scene/lf-rfid-scene-tune.cpp
  35. 0 13
      applications/lf-rfid/scene/lf-rfid-scene-tune.h
  36. 0 70
      applications/lf-rfid/scene/lf-rfid-scene-write.cpp
  37. 0 14
      applications/lf-rfid/scene/lf-rfid-scene-write.h
  38. 10 0
      applications/lfrfid-debug/lfrfid-debug-app-launcher.cpp
  39. 16 0
      applications/lfrfid-debug/lfrfid-debug-app.cpp
  40. 40 0
      applications/lfrfid-debug/lfrfid-debug-app.h
  41. 47 0
      applications/lfrfid-debug/scene/lfrfid-debug-app-scene-start.cpp
  42. 13 0
      applications/lfrfid-debug/scene/lfrfid-debug-app-scene-start.h
  43. 28 0
      applications/lfrfid-debug/scene/lfrfid-debug-app-scene-tune.cpp
  44. 9 0
      applications/lfrfid-debug/scene/lfrfid-debug-app-scene-tune.h
  45. 41 31
      applications/lfrfid-debug/view-modules/lfrfid-view-tune-vm.cpp
  46. 6 5
      applications/lfrfid-debug/view-modules/lfrfid-view-tune-vm.h
  47. 0 0
      applications/lfrfid/helpers/decoder-analyzer.cpp
  48. 0 0
      applications/lfrfid/helpers/decoder-analyzer.h
  49. 0 0
      applications/lfrfid/helpers/decoder-emmarine.cpp
  50. 0 0
      applications/lfrfid/helpers/decoder-emmarine.h
  51. 0 0
      applications/lfrfid/helpers/decoder-hid26.cpp
  52. 0 0
      applications/lfrfid/helpers/decoder-hid26.h
  53. 0 0
      applications/lfrfid/helpers/decoder-indala.cpp
  54. 0 0
      applications/lfrfid/helpers/decoder-indala.h
  55. 0 0
      applications/lfrfid/helpers/emmarine.h
  56. 0 0
      applications/lfrfid/helpers/encoder-emmarine.cpp
  57. 0 0
      applications/lfrfid/helpers/encoder-emmarine.h
  58. 0 0
      applications/lfrfid/helpers/encoder-generic.h
  59. 0 0
      applications/lfrfid/helpers/encoder-hid-h10301.cpp
  60. 0 0
      applications/lfrfid/helpers/encoder-hid-h10301.h
  61. 0 0
      applications/lfrfid/helpers/encoder-indala-40134.cpp
  62. 0 0
      applications/lfrfid/helpers/encoder-indala-40134.h
  63. 0 0
      applications/lfrfid/helpers/key-info.cpp
  64. 1 0
      applications/lfrfid/helpers/key-info.h
  65. 0 0
      applications/lfrfid/helpers/manchester-decoder.c
  66. 0 0
      applications/lfrfid/helpers/manchester-decoder.h
  67. 0 0
      applications/lfrfid/helpers/protocols/protocol-emmarin.cpp
  68. 0 0
      applications/lfrfid/helpers/protocols/protocol-emmarin.h
  69. 0 0
      applications/lfrfid/helpers/protocols/protocol-generic.h
  70. 0 0
      applications/lfrfid/helpers/protocols/protocol-hid-h10301.cpp
  71. 0 0
      applications/lfrfid/helpers/protocols/protocol-hid-h10301.h
  72. 0 0
      applications/lfrfid/helpers/protocols/protocol-indala-40134.cpp
  73. 0 0
      applications/lfrfid/helpers/protocols/protocol-indala-40134.h
  74. 0 0
      applications/lfrfid/helpers/pulse-joiner.cpp
  75. 0 0
      applications/lfrfid/helpers/pulse-joiner.h
  76. 44 0
      applications/lfrfid/helpers/rfid-key.cpp
  77. 25 0
      applications/lfrfid/helpers/rfid-key.h
  78. 35 0
      applications/lfrfid/helpers/rfid-name-generator.cpp
  79. 4 0
      applications/lfrfid/helpers/rfid-name-generator.h
  80. 0 0
      applications/lfrfid/helpers/rfid-reader.cpp
  81. 0 0
      applications/lfrfid/helpers/rfid-reader.h
  82. 1 9
      applications/lfrfid/helpers/rfid-timer-emulator.cpp
  83. 0 0
      applications/lfrfid/helpers/rfid-timer-emulator.h
  84. 111 0
      applications/lfrfid/helpers/rfid-worker.cpp
  85. 46 0
      applications/lfrfid/helpers/rfid-worker.h
  86. 30 6
      applications/lfrfid/helpers/rfid-writer.cpp
  87. 2 0
      applications/lfrfid/helpers/rfid-writer.h
  88. 50 0
      applications/lfrfid/helpers/state-sequencer.cpp
  89. 25 0
      applications/lfrfid/helpers/state-sequencer.h
  90. 10 0
      applications/lfrfid/lfrfid-app-launcher.cpp
  91. 37 0
      applications/lfrfid/lfrfid-app.cpp
  92. 67 0
      applications/lfrfid/lfrfid-app.h
  93. 0 0
      applications/lfrfid/lfrfid-cli.cpp
  94. 36 0
      applications/lfrfid/scene/lfrfid-app-scene-emulate.cpp
  95. 12 0
      applications/lfrfid/scene/lfrfid-app-scene-emulate.h
  96. 117 0
      applications/lfrfid/scene/lfrfid-app-scene-read-success.cpp
  97. 15 0
      applications/lfrfid/scene/lfrfid-app-scene-read-success.h
  98. 31 0
      applications/lfrfid/scene/lfrfid-app-scene-read.cpp
  99. 9 0
      applications/lfrfid/scene/lfrfid-app-scene-read.h
  100. 60 0
      applications/lfrfid/scene/lfrfid-app-scene-readed-menu.cpp

+ 10 - 3
applications/applications.c

@@ -16,7 +16,6 @@ int32_t gui_task(void* p);
 int32_t backlight_control(void* p);
 int32_t irda(void* p);
 int32_t app_loader(void* p);
-int32_t app_lfrfid(void* p);
 int32_t nfc_task(void* p);
 int32_t dolphin_task(void* p);
 int32_t power_task(void* p);
@@ -40,6 +39,8 @@ int32_t internal_storage_task(void* p);
 int32_t app_archive(void* p);
 int32_t notification_app(void* p);
 int32_t scened_app(void* p);
+int32_t lfrfid_app(void* p);
+int32_t lfrfid_debug_app(void* p);
 
 // On system start hooks declaration
 void irda_cli_init();
@@ -104,7 +105,8 @@ const FlipperApplication FLIPPER_SERVICES[] = {
 #endif
 
 #ifdef SRV_LF_RFID
-    {.app = app_lfrfid, .name = "125 kHz RFID", .stack_size = 1024, .icon = A_Plugins_14},
+    // TODO: fix stack size when sd api will be in separate thread
+    {.app = lfrfid_app, .name = "125 kHz RFID", .stack_size = 4096, .icon = A_Plugins_14},
 #endif
 
 #ifdef SRV_IRDA
@@ -186,7 +188,8 @@ const FlipperApplication FLIPPER_APPS[] = {
 #endif
 
 #ifdef APP_LF_RFID
-    {.app = app_lfrfid, .name = "125 kHz RFID", .stack_size = 1024, .icon = A_125khz_14},
+    // TODO: fix stack size when sd api will be in separate thread
+    {.app = lfrfid_app, .name = "125 kHz RFID", .stack_size = 4096, .icon = A_125khz_14},
 #endif
 
 #ifdef APP_IRDA
@@ -302,6 +305,10 @@ const FlipperApplication FLIPPER_DEBUG_APPS[] = {
 #ifdef APP_SCENED
     {.app = scened_app, .name = "Templated Scene", .stack_size = 1024, .icon = A_Plugins_14},
 #endif
+
+#ifdef APP_LF_RFID
+    {.app = lfrfid_debug_app, .name = "LF-RFID Debug", .stack_size = 1024, .icon = A_125khz_14},
+#endif
 };
 
 const size_t FLIPPER_DEBUG_APPS_COUNT = sizeof(FLIPPER_DEBUG_APPS) / sizeof(FlipperApplication);

+ 5 - 7
applications/gui/modules/dialog_ex.c

@@ -39,8 +39,7 @@ static void dialog_ex_view_draw_callback(Canvas* canvas, void* _model) {
     canvas_clear(canvas);
     canvas_set_color(canvas, ColorBlack);
 
-    // TODO other criteria for the draw
-    if(model->icon.x >= 0 && model->icon.y >= 0) {
+    if(model->icon.name != I_Empty_1x1) {
         canvas_draw_icon_name(canvas, model->icon.x, model->icon.y, model->icon.name);
     }
 
@@ -135,10 +134,9 @@ DialogEx* dialog_ex_alloc() {
             model->text.horizontal = AlignLeft;
             model->text.vertical = AlignBottom;
 
-            // TODO other criteria for the draw
-            model->icon.x = -1;
-            model->icon.y = -1;
-            model->icon.name = I_ButtonCenter_7x7;
+            model->icon.x = 0;
+            model->icon.y = 0;
+            model->icon.name = I_Empty_1x1;
 
             model->left_text = NULL;
             model->center_text = NULL;
@@ -208,7 +206,7 @@ void dialog_ex_set_text(
         });
 }
 
-void dialog_ex_set_icon(DialogEx* dialog_ex, int8_t x, int8_t y, IconName name) {
+void dialog_ex_set_icon(DialogEx* dialog_ex, uint8_t x, uint8_t y, IconName name) {
     furi_assert(dialog_ex);
     with_view_model(
         dialog_ex->view, (DialogExModel * model) {

+ 1 - 1
applications/gui/modules/dialog_ex.h

@@ -84,7 +84,7 @@ void dialog_ex_set_text(
  * @param x, y - icon position
  * @param name - icon to be shown
  */
-void dialog_ex_set_icon(DialogEx* dialog_ex, int8_t x, int8_t y, IconName name);
+void dialog_ex_set_icon(DialogEx* dialog_ex, uint8_t x, uint8_t y, IconName name);
 
 /* Set left button text
  * If text is null, left button will not be rendered and processed

+ 7 - 9
applications/gui/modules/popup.c

@@ -21,8 +21,8 @@ typedef struct {
 } TextElement;
 
 typedef struct {
-    int8_t x;
-    int8_t y;
+    uint8_t x;
+    uint8_t y;
     IconName name;
 } IconElement;
 
@@ -39,8 +39,7 @@ static void popup_view_draw_callback(Canvas* canvas, void* _model) {
     canvas_clear(canvas);
     canvas_set_color(canvas, ColorBlack);
 
-    // TODO other criteria for the draw
-    if(model->icon.x >= 0 && model->icon.y >= 0) {
+    if(model->icon.name != I_Empty_1x1) {
         canvas_draw_icon_name(canvas, model->icon.x, model->icon.y, model->icon.name);
     }
 
@@ -137,10 +136,9 @@ Popup* popup_alloc() {
             model->text.horizontal = AlignLeft;
             model->text.vertical = AlignBottom;
 
-            // TODO other criteria for the draw
-            model->icon.x = -1;
-            model->icon.y = -1;
-            model->icon.name = I_ButtonCenter_7x7;
+            model->icon.x = 0;
+            model->icon.y = 0;
+            model->icon.name = I_Empty_1x1;
             return true;
         });
     return popup;
@@ -206,7 +204,7 @@ void popup_set_text(
         });
 }
 
-void popup_set_icon(Popup* popup, int8_t x, int8_t y, IconName name) {
+void popup_set_icon(Popup* popup, uint8_t x, uint8_t y, IconName name) {
     furi_assert(popup);
     with_view_model(
         popup->view, (PopupModel * model) {

+ 1 - 1
applications/gui/modules/popup.h

@@ -77,7 +77,7 @@ void popup_set_text(
  * @param x, y - icon position
  * @param name - icon to be shown
  */
-void popup_set_icon(Popup* popup, int8_t x, int8_t y, IconName name);
+void popup_set_icon(Popup* popup, uint8_t x, uint8_t y, IconName name);
 
 /* Set popup timeout
  * @param popup - Popup instance

+ 0 - 1
applications/ibutton/ibutton-app.h

@@ -27,7 +27,6 @@
 
 #include <sd-card-api.h>
 #include <filesystem-api.h>
-#include "../cli/cli.h"
 
 #include "one_wire_master.h"
 #include "maxim_crc.h"

+ 1 - 1
applications/ibutton/scene/ibutton-scene-delete-success.cpp

@@ -36,7 +36,7 @@ void iButtonSceneDeleteSuccess::on_exit(iButtonApp* app) {
     Popup* popup = app->get_view_manager()->get_popup();
 
     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
-    popup_set_icon(popup, -1, -1, I_DolphinWait_61x59);
+    popup_set_icon(popup, 0, 0, I_Empty_1x1);
 
     popup_disable_timeout(popup);
     popup_set_context(popup, NULL);

+ 1 - 1
applications/ibutton/scene/ibutton-scene-emulate.cpp

@@ -89,5 +89,5 @@ void iButtonSceneEmulate::on_exit(iButtonApp* app) {
 
     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
-    popup_set_icon(popup, -1, -1, I_DolphinWait_61x59);
+    popup_set_icon(popup, 0, 0, I_Empty_1x1);
 }

+ 1 - 1
applications/ibutton/scene/ibutton-scene-read-success.cpp

@@ -74,7 +74,7 @@ void iButtonSceneReadSuccess::on_exit(iButtonApp* app) {
     dialog_ex_set_right_button_text(dialog_ex, NULL);
     dialog_ex_set_result_callback(dialog_ex, NULL);
     dialog_ex_set_context(dialog_ex, NULL);
-    dialog_ex_set_icon(dialog_ex, -1, -1, I_ButtonCenter_7x7);
+    dialog_ex_set_icon(dialog_ex, 0, 0, I_Empty_1x1);
 
     app->notify_green_off();
 }

+ 1 - 1
applications/ibutton/scene/ibutton-scene-read.cpp

@@ -49,5 +49,5 @@ void iButtonSceneRead::on_exit(iButtonApp* app) {
 
     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
-    popup_set_icon(popup, -1, -1, I_DolphinWait_61x59);
+    popup_set_icon(popup, 0, 0, I_Empty_1x1);
 }

+ 1 - 1
applications/ibutton/scene/ibutton-scene-save-success.cpp

@@ -39,7 +39,7 @@ void iButtonSceneSaveSuccess::on_exit(iButtonApp* app) {
     Popup* popup = app->get_view_manager()->get_popup();
 
     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
-    popup_set_icon(popup, -1, -1, I_DolphinWait_61x59);
+    popup_set_icon(popup, 0, 0, I_Empty_1x1);
 
     popup_disable_timeout(popup);
     popup_set_context(popup, NULL);

+ 1 - 1
applications/ibutton/scene/ibutton-scene-write-success.cpp

@@ -40,7 +40,7 @@ void iButtonSceneWriteSuccess::on_exit(iButtonApp* app) {
     Popup* popup = app->get_view_manager()->get_popup();
 
     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
-    popup_set_icon(popup, -1, -1, I_DolphinWait_61x59);
+    popup_set_icon(popup, 0, 0, I_Empty_1x1);
 
     popup_disable_timeout(popup);
     popup_set_context(popup, NULL);

+ 1 - 1
applications/ibutton/scene/ibutton-scene-write.cpp

@@ -92,7 +92,7 @@ void iButtonSceneWrite::on_exit(iButtonApp* app) {
 
     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
-    popup_set_icon(popup, -1, -1, I_DolphinWait_61x59);
+    popup_set_icon(popup, 0, 0, I_Empty_1x1);
 
     app->get_key_worker()->stop_write();
 }

+ 1 - 1
applications/irda/scene/irda-app-scene-edit-delete.cpp

@@ -41,7 +41,7 @@ void IrdaAppSceneEditDelete::on_enter(IrdaApp* app) {
     }
 
     dialog_ex_set_text(dialog_ex, app->get_text_store(0), 64, 32, AlignCenter, AlignCenter);
-    dialog_ex_set_icon(dialog_ex, -1, -1, I_ButtonCenter_7x7);
+    dialog_ex_set_icon(dialog_ex, 0, 0, I_Empty_1x1);
     dialog_ex_set_left_button_text(dialog_ex, "Back");
     dialog_ex_set_right_button_text(dialog_ex, "Delete");
     dialog_ex_set_result_callback(dialog_ex, dialog_result_callback);

+ 0 - 140
applications/lf-rfid/lf-rfid-app.cpp

@@ -1,140 +0,0 @@
-#include "lf-rfid-app.h"
-#include <furi.h>
-#include <api-hal.h>
-#include <stdarg.h>
-
-void LfrfidApp::run(void) {
-    LfrfidEvent event;
-    bool consumed;
-    bool exit = false;
-
-    scenes[current_scene]->on_enter(this);
-
-    while(!exit) {
-        view.receive_event(&event);
-
-        consumed = scenes[current_scene]->on_event(this, &event);
-
-        if(!consumed) {
-            if(event.type == LfrfidEvent::Type::Back) {
-                exit = switch_to_previous_scene();
-            }
-        }
-    };
-
-    scenes[current_scene]->on_exit(this);
-}
-
-LfrfidApp::LfrfidApp() {
-    api_hal_power_insomnia_enter();
-    notification = static_cast<NotificationApp*>(furi_record_open("notification"));
-}
-
-LfrfidApp::~LfrfidApp() {
-    for(std::map<Scene, LfrfidScene*>::iterator it = scenes.begin(); it != scenes.end(); ++it) {
-        delete it->second;
-        scenes.erase(it);
-    }
-
-    furi_record_close("notification");
-
-    api_hal_power_insomnia_exit();
-}
-
-LfrfidAppViewManager* LfrfidApp::get_view_manager() {
-    return &view;
-}
-
-void LfrfidApp::switch_to_next_scene(Scene next_scene) {
-    previous_scenes_list.push_front(current_scene);
-
-    if(next_scene != Scene::Exit) {
-        scenes[current_scene]->on_exit(this);
-        current_scene = next_scene;
-        scenes[current_scene]->on_enter(this);
-    }
-}
-
-void LfrfidApp::search_and_switch_to_previous_scene(std::initializer_list<Scene> scenes_list) {
-    Scene previous_scene = Scene::Start;
-    bool scene_found = false;
-
-    while(!scene_found) {
-        previous_scene = get_previous_scene();
-        for(Scene element : scenes_list) {
-            if(previous_scene == element || previous_scene == Scene::Start) {
-                scene_found = true;
-                break;
-            }
-        }
-    }
-
-    scenes[current_scene]->on_exit(this);
-    current_scene = previous_scene;
-    scenes[current_scene]->on_enter(this);
-}
-
-bool LfrfidApp::switch_to_previous_scene(uint8_t count) {
-    Scene previous_scene = Scene::Start;
-
-    for(uint8_t i = 0; i < count; i++) {
-        previous_scene = get_previous_scene();
-        if(previous_scene == Scene::Exit) break;
-    }
-
-    if(previous_scene == Scene::Exit) {
-        return true;
-    } else {
-        scenes[current_scene]->on_exit(this);
-        current_scene = previous_scene;
-        scenes[current_scene]->on_enter(this);
-        return false;
-    }
-}
-
-LfrfidApp::Scene LfrfidApp::get_previous_scene() {
-    Scene scene = previous_scenes_list.front();
-    previous_scenes_list.pop_front();
-    return scene;
-}
-
-/***************************** NOTIFY *******************************/
-
-void LfrfidApp::notify_green_blink() {
-    notification_message(notification, &sequence_blink_green_10);
-}
-
-void LfrfidApp::notify_success() {
-    notification_message(notification, &sequence_success);
-}
-
-/*************************** TEXT STORE *****************************/
-
-char* LfrfidApp::get_text_store() {
-    return text_store;
-}
-
-uint8_t LfrfidApp::get_text_store_size() {
-    return text_store_size;
-}
-
-void LfrfidApp::set_text_store(const char* text...) {
-    va_list args;
-    va_start(args, text);
-
-    vsnprintf(text_store, text_store_size, text, args);
-
-    va_end(args);
-}
-
-RfidReader* LfrfidApp::get_reader() {
-    return &reader;
-}
-
-RfidTimerEmulator* LfrfidApp::get_emulator() {
-    return &emulator;
-}
-
-RfidWriter* LfrfidApp::get_writer() {
-    return &writer;
-}

+ 0 - 79
applications/lf-rfid/lf-rfid-app.h

@@ -1,79 +0,0 @@
-#pragma once
-#include <map>
-#include <list>
-#include "lf-rfid-view-manager.h"
-
-#include "scene/lf-rfid-scene-start.h"
-#include "scene/lf-rfid-scene-emulate-indala.h"
-#include "scene/lf-rfid-scene-emulate-hid.h"
-#include "scene/lf-rfid-scene-emulate-emmarine.h"
-#include "scene/lf-rfid-scene-read-normal.h"
-#include "scene/lf-rfid-scene-read-indala.h"
-#include "scene/lf-rfid-scene-tune.h"
-#include "scene/lf-rfid-scene-write.h"
-
-#include "helpers/rfid-reader.h"
-#include "helpers/rfid-timer-emulator.h"
-
-#include <notification/notification-messages.h>
-
-class LfrfidApp {
-public:
-    void run(void);
-
-    LfrfidApp();
-    ~LfrfidApp();
-
-    enum class Scene : uint8_t {
-        Exit,
-        Start,
-        ReadNormal,
-        ReadIndala,
-        EmulateIndala,
-        EmulateHID,
-        EmulateEM,
-        Tune,
-        Write,
-    };
-
-    LfrfidAppViewManager* get_view_manager();
-    void switch_to_next_scene(Scene index);
-    void search_and_switch_to_previous_scene(std::initializer_list<Scene> scenes_list);
-    bool switch_to_previous_scene(uint8_t count = 1);
-    Scene get_previous_scene();
-
-    void notify_green_blink();
-    void notify_success();
-
-    char* get_text_store();
-    uint8_t get_text_store_size();
-    void set_text_store(const char* text...);
-
-    RfidReader* get_reader();
-    RfidTimerEmulator* get_emulator();
-    RfidWriter* get_writer();
-
-private:
-    std::list<Scene> previous_scenes_list = {Scene::Exit};
-    Scene current_scene = Scene::Start;
-    LfrfidAppViewManager view;
-
-    std::map<Scene, LfrfidScene*> scenes = {
-        {Scene::Start, new LfrfidSceneStart()},
-        {Scene::ReadNormal, new LfrfidSceneReadNormal()},
-        {Scene::ReadIndala, new LfrfidSceneReadIndala()},
-        {Scene::EmulateIndala, new LfrfidSceneEmulateIndala()},
-        {Scene::EmulateHID, new LfrfidSceneEmulateHID()},
-        {Scene::EmulateEM, new LfrfidSceneEmulateEMMarine()},
-        {Scene::Tune, new LfrfidSceneTune()},
-        {Scene::Write, new LfrfidSceneWrite()},
-    };
-
-    static const uint8_t text_store_size = 128;
-    char text_store[text_store_size + 1];
-
-    NotificationApp* notification;
-    RfidReader reader;
-    RfidTimerEmulator emulator;
-    RfidWriter writer;
-};

+ 0 - 21
applications/lf-rfid/lf-rfid-event.h

@@ -1,21 +0,0 @@
-#pragma once
-#include <stdint.h>
-
-class LfrfidEvent {
-public:
-    // events enum
-    enum class Type : uint8_t {
-        Tick,
-        Back,
-        MenuSelected,
-        NextScene,
-    };
-
-    // payload
-    union {
-        uint32_t menu_index;
-    } payload;
-
-    // event type
-    Type type;
-};

+ 0 - 90
applications/lf-rfid/lf-rfid-view-manager.cpp

@@ -1,90 +0,0 @@
-#include "lf-rfid-view-manager.h"
-#include "lf-rfid-event.h"
-#include <callback-connector.h>
-
-LfrfidAppViewManager::LfrfidAppViewManager() {
-    event_queue = osMessageQueueNew(10, sizeof(LfrfidEvent), NULL);
-
-    view_dispatcher = view_dispatcher_alloc();
-    auto callback = cbc::obtain_connector(this, &LfrfidAppViewManager::previous_view_callback);
-
-    // allocate views
-    submenu = submenu_alloc();
-    add_view(ViewType::Submenu, submenu_get_view(submenu));
-
-    popup = popup_alloc();
-    add_view(ViewType::Popup, popup_get_view(popup));
-
-    tune = new LfRfidViewTune();
-    add_view(ViewType::Tune, tune->get_view());
-
-    gui = static_cast<Gui*>(furi_record_open("gui"));
-    view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen);
-
-    // set previous view callback for all views
-    view_set_previous_callback(submenu_get_view(submenu), callback);
-    view_set_previous_callback(popup_get_view(popup), callback);
-    view_set_previous_callback(tune->get_view(), callback);
-}
-
-LfrfidAppViewManager::~LfrfidAppViewManager() {
-    // remove views
-    view_dispatcher_remove_view(
-        view_dispatcher, static_cast<uint32_t>(LfrfidAppViewManager::ViewType::Submenu));
-    view_dispatcher_remove_view(
-        view_dispatcher, static_cast<uint32_t>(LfrfidAppViewManager::ViewType::Popup));
-    view_dispatcher_remove_view(
-        view_dispatcher, static_cast<uint32_t>(LfrfidAppViewManager::ViewType::Tune));
-
-    // free view modules
-    submenu_free(submenu);
-    popup_free(popup);
-    delete tune;
-
-    // free dispatcher
-    view_dispatcher_free(view_dispatcher);
-
-    // free event queue
-    osMessageQueueDelete(event_queue);
-}
-
-void LfrfidAppViewManager::switch_to(ViewType type) {
-    view_dispatcher_switch_to_view(view_dispatcher, static_cast<uint32_t>(type));
-}
-
-Submenu* LfrfidAppViewManager::get_submenu() {
-    return submenu;
-}
-
-Popup* LfrfidAppViewManager::get_popup() {
-    return popup;
-}
-
-LfRfidViewTune* LfrfidAppViewManager::get_tune() {
-    return tune;
-}
-
-void LfrfidAppViewManager::receive_event(LfrfidEvent* event) {
-    if(osMessageQueueGet(event_queue, event, NULL, 100) != osOK) {
-        event->type = LfrfidEvent::Type::Tick;
-    }
-}
-
-void LfrfidAppViewManager::send_event(LfrfidEvent* event) {
-    osStatus_t result = osMessageQueuePut(event_queue, event, 0, 0);
-    furi_check(result == osOK);
-}
-
-uint32_t LfrfidAppViewManager::previous_view_callback(void* context) {
-    if(event_queue != NULL) {
-        LfrfidEvent event;
-        event.type = LfrfidEvent::Type::Back;
-        send_event(&event);
-    }
-
-    return VIEW_IGNORE;
-}
-
-void LfrfidAppViewManager::add_view(ViewType view_type, View* view) {
-    view_dispatcher_add_view(view_dispatcher, static_cast<uint32_t>(view_type), view);
-}

+ 0 - 42
applications/lf-rfid/lf-rfid-view-manager.h

@@ -1,42 +0,0 @@
-#pragma once
-#include <furi.h>
-#include <gui/view_dispatcher.h>
-#include <gui/modules/submenu.h>
-#include <gui/modules/popup.h>
-#include "lf-rfid-event.h"
-#include "view/lf-rfid-view-tune.h"
-
-class LfrfidAppViewManager {
-public:
-    enum class ViewType : uint8_t {
-        Submenu,
-        Popup,
-        Tune,
-    };
-
-    osMessageQueueId_t event_queue;
-
-    LfrfidAppViewManager();
-    ~LfrfidAppViewManager();
-
-    void switch_to(ViewType type);
-
-    void receive_event(LfrfidEvent* event);
-    void send_event(LfrfidEvent* event);
-
-    Submenu* get_submenu();
-    Popup* get_popup();
-    LfRfidViewTune* get_tune();
-
-private:
-    ViewDispatcher* view_dispatcher;
-    Gui* gui;
-
-    uint32_t previous_view_callback(void* context);
-    void add_view(ViewType view_type, View* view);
-
-    // view elements
-    Submenu* submenu;
-    Popup* popup;
-    LfRfidViewTune* tune;
-};

+ 0 - 10
applications/lf-rfid/lf-rfid.cpp

@@ -1,10 +0,0 @@
-#include "lf-rfid-app.h"
-
-// app enter function
-extern "C" int32_t app_lfrfid(void* p) {
-    LfrfidApp* app = new LfrfidApp();
-    app->run();
-    delete app;
-
-    return 255;
-}

+ 0 - 34
applications/lf-rfid/scene/lf-rfid-scene-emulate-emmarine.cpp

@@ -1,34 +0,0 @@
-#include "lf-rfid-scene-emulate-emmarine.h"
-
-#include "../lf-rfid-app.h"
-#include "../lf-rfid-view-manager.h"
-#include "../lf-rfid-event.h"
-#include "../helpers/key-info.h"
-
-void LfrfidSceneEmulateEMMarine::on_enter(LfrfidApp* app) {
-    LfrfidAppViewManager* view_manager = app->get_view_manager();
-
-    Popup* popup = view_manager->get_popup();
-    popup_set_header(popup, "LF-RFID", 64, 16, AlignCenter, AlignBottom);
-    app->set_text_store("EM emulation");
-    popup_set_text(popup, app->get_text_store(), 64, 22, AlignCenter, AlignTop);
-
-    view_manager->switch_to(LfrfidAppViewManager::ViewType::Popup);
-    app->get_emulator()->start(LfrfidKeyType::KeyEM4100, data, 5);
-}
-
-bool LfrfidSceneEmulateEMMarine::on_event(LfrfidApp* app, LfrfidEvent* event) {
-    bool consumed = false;
-
-    return consumed;
-}
-
-void LfrfidSceneEmulateEMMarine::on_exit(LfrfidApp* app) {
-    LfrfidAppViewManager* view_manager = app->get_view_manager();
-
-    Popup* popup = view_manager->get_popup();
-    popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
-    popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
-
-    app->get_emulator()->stop();
-}

+ 0 - 13
applications/lf-rfid/scene/lf-rfid-scene-emulate-emmarine.h

@@ -1,13 +0,0 @@
-#pragma once
-#include "lf-rfid-scene-generic.h"
-#include "../helpers/key-info.h"
-
-class LfrfidSceneEmulateEMMarine : public LfrfidScene {
-public:
-    void on_enter(LfrfidApp* app) final;
-    bool on_event(LfrfidApp* app, LfrfidEvent* event) final;
-    void on_exit(LfrfidApp* app) final;
-
-private:
-    const uint8_t data[5] = {0x53, 0x00, 0x5F, 0xB3, 0xC2};
-};

+ 0 - 34
applications/lf-rfid/scene/lf-rfid-scene-emulate-hid.cpp

@@ -1,34 +0,0 @@
-#include "lf-rfid-scene-emulate-hid.h"
-
-#include "../lf-rfid-app.h"
-#include "../lf-rfid-view-manager.h"
-#include "../lf-rfid-event.h"
-#include "../helpers/key-info.h"
-
-void LfrfidSceneEmulateHID::on_enter(LfrfidApp* app) {
-    LfrfidAppViewManager* view_manager = app->get_view_manager();
-
-    Popup* popup = view_manager->get_popup();
-    popup_set_header(popup, "LF-RFID", 64, 16, AlignCenter, AlignBottom);
-    app->set_text_store("HID H10301 emulation");
-    popup_set_text(popup, app->get_text_store(), 64, 22, AlignCenter, AlignTop);
-
-    view_manager->switch_to(LfrfidAppViewManager::ViewType::Popup);
-    app->get_emulator()->start(LfrfidKeyType::KeyH10301, data, 3);
-}
-
-bool LfrfidSceneEmulateHID::on_event(LfrfidApp* app, LfrfidEvent* event) {
-    bool consumed = false;
-
-    return consumed;
-}
-
-void LfrfidSceneEmulateHID::on_exit(LfrfidApp* app) {
-    LfrfidAppViewManager* view_manager = app->get_view_manager();
-
-    Popup* popup = view_manager->get_popup();
-    popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
-    popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
-
-    app->get_emulator()->stop();
-}

+ 0 - 13
applications/lf-rfid/scene/lf-rfid-scene-emulate-hid.h

@@ -1,13 +0,0 @@
-#pragma once
-#include "lf-rfid-scene-generic.h"
-#include "../helpers/key-info.h"
-
-class LfrfidSceneEmulateHID : public LfrfidScene {
-public:
-    void on_enter(LfrfidApp* app) final;
-    bool on_event(LfrfidApp* app, LfrfidEvent* event) final;
-    void on_exit(LfrfidApp* app) final;
-
-private:
-    const uint8_t data[3] = {0xED, 0x87, 0x70};
-};

+ 0 - 34
applications/lf-rfid/scene/lf-rfid-scene-emulate-indala.cpp

@@ -1,34 +0,0 @@
-#include "lf-rfid-scene-emulate-indala.h"
-
-#include "../lf-rfid-app.h"
-#include "../lf-rfid-view-manager.h"
-#include "../lf-rfid-event.h"
-#include "../helpers/key-info.h"
-
-void LfrfidSceneEmulateIndala::on_enter(LfrfidApp* app) {
-    LfrfidAppViewManager* view_manager = app->get_view_manager();
-
-    Popup* popup = view_manager->get_popup();
-    popup_set_header(popup, "LF-RFID", 64, 16, AlignCenter, AlignBottom);
-    app->set_text_store("Indala 40134 emulation");
-    popup_set_text(popup, app->get_text_store(), 64, 22, AlignCenter, AlignTop);
-
-    view_manager->switch_to(LfrfidAppViewManager::ViewType::Popup);
-    app->get_emulator()->start(LfrfidKeyType::KeyI40134, data, 3);
-}
-
-bool LfrfidSceneEmulateIndala::on_event(LfrfidApp* app, LfrfidEvent* event) {
-    bool consumed = false;
-
-    return consumed;
-}
-
-void LfrfidSceneEmulateIndala::on_exit(LfrfidApp* app) {
-    LfrfidAppViewManager* view_manager = app->get_view_manager();
-
-    Popup* popup = view_manager->get_popup();
-    popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
-    popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
-
-    app->get_emulator()->stop();
-}

+ 0 - 13
applications/lf-rfid/scene/lf-rfid-scene-emulate-indala.h

@@ -1,13 +0,0 @@
-#pragma once
-#include "lf-rfid-scene-generic.h"
-#include "../helpers/key-info.h"
-
-class LfrfidSceneEmulateIndala : public LfrfidScene {
-public:
-    void on_enter(LfrfidApp* app) final;
-    bool on_event(LfrfidApp* app, LfrfidEvent* event) final;
-    void on_exit(LfrfidApp* app) final;
-
-private:
-    const uint8_t data[3] = {0x1F, 0x2E, 0x3D};
-};

+ 0 - 14
applications/lf-rfid/scene/lf-rfid-scene-generic.h

@@ -1,14 +0,0 @@
-#pragma once
-#include "../lf-rfid-event.h"
-
-class LfrfidApp;
-
-class LfrfidScene {
-public:
-    virtual void on_enter(LfrfidApp* app) = 0;
-    virtual bool on_event(LfrfidApp* app, LfrfidEvent* event) = 0;
-    virtual void on_exit(LfrfidApp* app) = 0;
-    virtual ~LfrfidScene(){};
-
-private:
-};

+ 0 - 34
applications/lf-rfid/scene/lf-rfid-scene-read-indala.cpp

@@ -1,34 +0,0 @@
-#include "lf-rfid-scene-read-indala.h"
-
-#include "../lf-rfid-app.h"
-#include "../lf-rfid-view-manager.h"
-#include "../lf-rfid-event.h"
-#include "../helpers/key-info.h"
-
-void LfrfidSceneReadIndala::on_enter(LfrfidApp* app) {
-    LfrfidAppViewManager* view_manager = app->get_view_manager();
-
-    Popup* popup = view_manager->get_popup();
-    popup_set_header(popup, "LF-RFID read Indala", 64, 16, AlignCenter, AlignBottom);
-    app->set_text_store("[decoder not implemented]");
-    popup_set_text(popup, app->get_text_store(), 64, 22, AlignCenter, AlignTop);
-
-    view_manager->switch_to(LfrfidAppViewManager::ViewType::Popup);
-    app->get_reader()->start(RfidReader::Type::Indala);
-}
-
-bool LfrfidSceneReadIndala::on_event(LfrfidApp* app, LfrfidEvent* event) {
-    bool consumed = false;
-
-    return consumed;
-}
-
-void LfrfidSceneReadIndala::on_exit(LfrfidApp* app) {
-    LfrfidAppViewManager* view_manager = app->get_view_manager();
-
-    Popup* popup = view_manager->get_popup();
-    popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
-    popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
-
-    app->get_reader()->stop();
-}

+ 0 - 15
applications/lf-rfid/scene/lf-rfid-scene-read-indala.h

@@ -1,15 +0,0 @@
-#pragma once
-#include "lf-rfid-scene-generic.h"
-#include "../helpers/key-info.h"
-
-class LfrfidSceneReadIndala : public LfrfidScene {
-public:
-    void on_enter(LfrfidApp* app) final;
-    bool on_event(LfrfidApp* app, LfrfidEvent* event) final;
-    void on_exit(LfrfidApp* app) final;
-
-private:
-    uint32_t success_reads = 0;
-    static const uint8_t data_size = LFRFID_KEY_SIZE;
-    uint8_t last_data[data_size] = {0};
-};

+ 0 - 89
applications/lf-rfid/scene/lf-rfid-scene-read-normal.cpp

@@ -1,89 +0,0 @@
-#include "lf-rfid-scene-read-normal.h"
-
-#include "../lf-rfid-app.h"
-#include "../lf-rfid-view-manager.h"
-#include "../lf-rfid-event.h"
-#include "../helpers/key-info.h"
-
-void LfrfidSceneReadNormal::on_enter(LfrfidApp* app) {
-    LfrfidAppViewManager* view_manager = app->get_view_manager();
-
-    Popup* popup = view_manager->get_popup();
-    popup_set_header(popup, "LF-RFID read EM & HID", 64, 16, AlignCenter, AlignBottom);
-    app->set_text_store("waiting...");
-    popup_set_text(popup, app->get_text_store(), 64, 22, AlignCenter, AlignTop);
-
-    view_manager->switch_to(LfrfidAppViewManager::ViewType::Popup);
-    app->get_reader()->start(RfidReader::Type::Normal);
-}
-
-bool LfrfidSceneReadNormal::on_event(LfrfidApp* app, LfrfidEvent* event) {
-    bool consumed = false;
-
-    if(event->type == LfrfidEvent::Type::Tick) {
-        uint8_t data[data_size];
-        LfrfidKeyType type;
-
-        if(app->get_reader()->read(&type, data, data_size)) {
-            if(memcmp(last_data, data, data_size) == 0) {
-                success_reads++;
-                app->notify_green_blink();
-            } else {
-                success_reads = 1;
-                memcpy(last_data, data, data_size);
-                app->notify_success();
-            }
-
-            switch(type) {
-            case LfrfidKeyType::KeyEM4100:
-                app->set_text_store(
-                    "[EM] %02X %02X %02X %02X %02X\n"
-                    "count: %u",
-                    data[0],
-                    data[1],
-                    data[2],
-                    data[3],
-                    data[4],
-                    success_reads);
-                break;
-            case LfrfidKeyType::KeyH10301:
-                app->set_text_store(
-                    "[HID26] %02X %02X %02X\n"
-                    "count: %u",
-                    data[0],
-                    data[1],
-                    data[2],
-                    success_reads);
-                break;
-            case LfrfidKeyType::KeyI40134:
-                app->set_text_store(
-                    "[IND] %02X %02X %02X\n"
-                    "count: %u",
-                    data[0],
-                    data[1],
-                    data[2],
-                    success_reads);
-                break;
-            }
-            popup_set_text(
-                app->get_view_manager()->get_popup(),
-                app->get_text_store(),
-                64,
-                22,
-                AlignCenter,
-                AlignTop);
-        }
-    }
-
-    return consumed;
-}
-
-void LfrfidSceneReadNormal::on_exit(LfrfidApp* app) {
-    LfrfidAppViewManager* view_manager = app->get_view_manager();
-
-    Popup* popup = view_manager->get_popup();
-    popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
-    popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
-
-    app->get_reader()->stop();
-}

+ 0 - 15
applications/lf-rfid/scene/lf-rfid-scene-read-normal.h

@@ -1,15 +0,0 @@
-#pragma once
-#include "lf-rfid-scene-generic.h"
-#include "../helpers/key-info.h"
-
-class LfrfidSceneReadNormal : public LfrfidScene {
-public:
-    void on_enter(LfrfidApp* app) final;
-    bool on_event(LfrfidApp* app, LfrfidEvent* event) final;
-    void on_exit(LfrfidApp* app) final;
-
-private:
-    uint32_t success_reads = 0;
-    static const uint8_t data_size = LFRFID_KEY_SIZE;
-    uint8_t last_data[data_size] = {0};
-};

+ 0 - 82
applications/lf-rfid/scene/lf-rfid-scene-start.cpp

@@ -1,82 +0,0 @@
-#include "lf-rfid-scene-start.h"
-#include "../lf-rfid-app.h"
-#include "../lf-rfid-view-manager.h"
-#include "../lf-rfid-event.h"
-#include <callback-connector.h>
-
-typedef enum {
-    SubmenuIndexWrite,
-    SubmenuIndexReadNormal,
-    SubmenuIndexReadIndala,
-    SubmenuIndexEmulateEM,
-    SubmenuIndexEmulateHID,
-    SubmenuIndexEmulateIndala,
-    SubmenuIndexTune
-} SubmenuIndex;
-
-void LfrfidSceneStart::on_enter(LfrfidApp* app) {
-    LfrfidAppViewManager* view_manager = app->get_view_manager();
-    Submenu* submenu = view_manager->get_submenu();
-    auto callback = cbc::obtain_connector(this, &LfrfidSceneStart::submenu_callback);
-
-    submenu_add_item(submenu, "Write T5577", SubmenuIndexWrite, callback, app);
-    submenu_add_item(submenu, "Read Normal", SubmenuIndexReadNormal, callback, app);
-    submenu_add_item(submenu, "Read Indala", SubmenuIndexReadIndala, callback, app);
-    submenu_add_item(submenu, "Emulate EM", SubmenuIndexEmulateEM, callback, app);
-    submenu_add_item(submenu, "Emulate HID", SubmenuIndexEmulateHID, callback, app);
-    submenu_add_item(submenu, "Emulate Indala", SubmenuIndexEmulateIndala, callback, app);
-    submenu_add_item(submenu, "Tune", SubmenuIndexTune, callback, app);
-
-    view_manager->switch_to(LfrfidAppViewManager::ViewType::Submenu);
-}
-
-bool LfrfidSceneStart::on_event(LfrfidApp* app, LfrfidEvent* event) {
-    bool consumed = false;
-
-    if(event->type == LfrfidEvent::Type::MenuSelected) {
-        switch(event->payload.menu_index) {
-        case SubmenuIndexWrite:
-            app->switch_to_next_scene(LfrfidApp::Scene::Write);
-            break;
-        case SubmenuIndexReadNormal:
-            app->switch_to_next_scene(LfrfidApp::Scene::ReadNormal);
-            break;
-        case SubmenuIndexReadIndala:
-            app->switch_to_next_scene(LfrfidApp::Scene::ReadIndala);
-            break;
-        case SubmenuIndexEmulateEM:
-            app->switch_to_next_scene(LfrfidApp::Scene::EmulateEM);
-            break;
-            break;
-        case SubmenuIndexEmulateHID:
-            app->switch_to_next_scene(LfrfidApp::Scene::EmulateHID);
-            break;
-        case SubmenuIndexEmulateIndala:
-            app->switch_to_next_scene(LfrfidApp::Scene::EmulateIndala);
-            break;
-        case SubmenuIndexTune:
-            app->switch_to_next_scene(LfrfidApp::Scene::Tune);
-            break;
-        }
-        consumed = true;
-    }
-
-    return consumed;
-}
-
-void LfrfidSceneStart::on_exit(LfrfidApp* app) {
-    LfrfidAppViewManager* view_manager = app->get_view_manager();
-    Submenu* submenu = view_manager->get_submenu();
-
-    submenu_clean(submenu);
-}
-
-void LfrfidSceneStart::submenu_callback(void* context, uint32_t index) {
-    LfrfidApp* app = static_cast<LfrfidApp*>(context);
-    LfrfidEvent event;
-
-    event.type = LfrfidEvent::Type::MenuSelected;
-    event.payload.menu_index = index;
-
-    app->get_view_manager()->send_event(&event);
-}

+ 0 - 13
applications/lf-rfid/scene/lf-rfid-scene-start.h

@@ -1,13 +0,0 @@
-#pragma once
-#include "lf-rfid-scene-generic.h"
-#include "../helpers/rfid-timer-emulator.h"
-
-class LfrfidSceneStart : public LfrfidScene {
-public:
-    void on_enter(LfrfidApp* app) final;
-    bool on_event(LfrfidApp* app, LfrfidEvent* event) final;
-    void on_exit(LfrfidApp* app) final;
-
-private:
-    void submenu_callback(void* context, uint32_t index);
-};

+ 0 - 35
applications/lf-rfid/scene/lf-rfid-scene-tune.cpp

@@ -1,35 +0,0 @@
-#include "lf-rfid-scene-tune.h"
-#include "../lf-rfid-app.h"
-#include "../lf-rfid-view-manager.h"
-#include "../lf-rfid-event.h"
-#include <callback-connector.h>
-
-void LfrfidSceneTune::on_enter(LfrfidApp* app) {
-    LfrfidAppViewManager* view_manager = app->get_view_manager();
-    //LfRfidViewTune* tune = view_manager->get_tune();
-
-    view_manager->switch_to(LfrfidAppViewManager::ViewType::Tune);
-
-    reader.start(RfidReader::Type::Indala);
-}
-
-bool LfrfidSceneTune::on_event(LfrfidApp* app, LfrfidEvent* event) {
-    bool consumed = false;
-
-    if(event->type == LfrfidEvent::Type::Tick) {
-        LfRfidViewTune* tune = app->get_view_manager()->get_tune();
-
-        if(tune->is_dirty()) {
-            LFRFID_TIM.Instance->ARR = tune->get_ARR();
-            LFRFID_TIM.Instance->CCR1 = tune->get_CCR();
-        }
-    }
-
-    return consumed;
-}
-
-void LfrfidSceneTune::on_exit(LfrfidApp* app) {
-    //LfRfidViewTune* tune = app->get_view_manager()->get_tune();
-
-    reader.stop();
-}

+ 0 - 13
applications/lf-rfid/scene/lf-rfid-scene-tune.h

@@ -1,13 +0,0 @@
-#pragma once
-#include "lf-rfid-scene-generic.h"
-#include "../helpers/rfid-reader.h"
-
-class LfrfidSceneTune : public LfrfidScene {
-public:
-    void on_enter(LfrfidApp* app) final;
-    bool on_event(LfrfidApp* app, LfrfidEvent* event) final;
-    void on_exit(LfrfidApp* app) final;
-
-private:
-    RfidReader reader;
-};

+ 0 - 70
applications/lf-rfid/scene/lf-rfid-scene-write.cpp

@@ -1,70 +0,0 @@
-#include "lf-rfid-scene-write.h"
-
-#include "../lf-rfid-app.h"
-#include "../lf-rfid-view-manager.h"
-#include "../lf-rfid-event.h"
-#include "../helpers/key-info.h"
-
-void LfrfidSceneWrite::on_enter(LfrfidApp* app) {
-    LfrfidAppViewManager* view_manager = app->get_view_manager();
-
-    Popup* popup = view_manager->get_popup();
-    popup_set_header(popup, "LF-RFID", 64, 16, AlignCenter, AlignBottom);
-    app->set_text_store("Writing...");
-    popup_set_text(popup, app->get_text_store(), 64, 22, AlignCenter, AlignTop);
-
-    view_manager->switch_to(LfrfidAppViewManager::ViewType::Popup);
-
-    timing_index = 0;
-}
-
-bool LfrfidSceneWrite::on_event(LfrfidApp* app, LfrfidEvent* event) {
-    bool consumed = false;
-
-    // TODO move read\write logic to key worker
-
-    bool readed = false;
-    uint8_t em_data[5] = {0x1A, 0x2B, 0xC3, 0xD4, 0xE5};
-
-    if(timing_index == 0) {
-        app->get_reader()->stop();
-        app->get_writer()->start();
-        app->get_writer()->write_em(em_data);
-        app->get_writer()->stop();
-        delay(200);
-        app->get_reader()->start(RfidReader::Type::Normal);
-    } else {
-        uint8_t data[LFRFID_KEY_SIZE];
-        LfrfidKeyType type;
-
-        app->get_reader()->read(&type, data, LFRFID_KEY_SIZE);
-        if(type == LfrfidKeyType::KeyEM4100) {
-            if(memcmp(em_data, data, 5) == 0) {
-                readed = true;
-            }
-        }
-    }
-
-    if(readed) {
-        app->set_text_store("Writed!");
-        app->notify_green_blink();
-    } else {
-        app->set_text_store("Writing [1A 2B C3 D4 E5]");
-        timing_index++;
-        if(timing_index == 4) {
-            timing_index = 0;
-        }
-    }
-    popup_set_text(
-        app->get_view_manager()->get_popup(), app->get_text_store(), 64, 22, AlignCenter, AlignTop);
-
-    return consumed;
-}
-
-void LfrfidSceneWrite::on_exit(LfrfidApp* app) {
-    LfrfidAppViewManager* view_manager = app->get_view_manager();
-
-    Popup* popup = view_manager->get_popup();
-    popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
-    popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
-}

+ 0 - 14
applications/lf-rfid/scene/lf-rfid-scene-write.h

@@ -1,14 +0,0 @@
-#pragma once
-#include "lf-rfid-scene-generic.h"
-#include "../helpers/key-info.h"
-#include "../helpers/rfid-writer.h"
-
-class LfrfidSceneWrite : public LfrfidScene {
-public:
-    void on_enter(LfrfidApp* app) final;
-    bool on_event(LfrfidApp* app, LfrfidEvent* event) final;
-    void on_exit(LfrfidApp* app) final;
-
-private:
-    uint8_t timing_index;
-};

+ 10 - 0
applications/lfrfid-debug/lfrfid-debug-app-launcher.cpp

@@ -0,0 +1,10 @@
+#include "lfrfid-debug-app.h"
+
+// app enter function
+extern "C" int32_t lfrfid_debug_app(void* p) {
+    LfRfidDebugApp* app = new LfRfidDebugApp();
+    app->run();
+    delete app;
+
+    return 0;
+}

+ 16 - 0
applications/lfrfid-debug/lfrfid-debug-app.cpp

@@ -0,0 +1,16 @@
+#include "lfrfid-debug-app.h"
+#include "scene/lfrfid-debug-app-scene-start.h"
+#include "scene/lfrfid-debug-app-scene-tune.h"
+
+LfRfidDebugApp::LfRfidDebugApp()
+    : scene_controller{this} {
+}
+
+LfRfidDebugApp::~LfRfidDebugApp() {
+}
+
+void LfRfidDebugApp::run() {
+    scene_controller.add_scene(SceneType::Start, new LfRfidDebugAppSceneStart());
+    scene_controller.add_scene(SceneType::TuneScene, new LfRfidDebugAppSceneTune());
+    scene_controller.process(100);
+}

+ 40 - 0
applications/lfrfid-debug/lfrfid-debug-app.h

@@ -0,0 +1,40 @@
+#pragma once
+#include <furi.h>
+#include <api-hal.h>
+
+#include <generic-scene.hpp>
+#include <scene-controller.hpp>
+#include <view-controller.hpp>
+
+#include <view-modules/submenu-vm.h>
+#include "view-modules/lfrfid-view-tune-vm.h"
+
+class LfRfidDebugApp {
+public:
+    enum class EventType : uint8_t {
+        GENERIC_EVENT_ENUM_VALUES,
+        MenuSelected,
+    };
+
+    enum class SceneType : uint8_t {
+        GENERIC_SCENE_ENUM_VALUES,
+        TuneScene,
+    };
+
+    class Event {
+    public:
+        union {
+            int32_t menu_index;
+        } payload;
+
+        EventType type;
+    };
+
+    SceneController<GenericScene<LfRfidDebugApp>, LfRfidDebugApp> scene_controller;
+    ViewController<LfRfidDebugApp, SubmenuVM, LfRfidViewTuneVM> view_controller;
+
+    ~LfRfidDebugApp();
+    LfRfidDebugApp();
+
+    void run();
+};

+ 47 - 0
applications/lfrfid-debug/scene/lfrfid-debug-app-scene-start.cpp

@@ -0,0 +1,47 @@
+#include "lfrfid-debug-app-scene-start.h"
+
+typedef enum {
+    SubmenuTune,
+} SubmenuIndex;
+
+void LfRfidDebugAppSceneStart::on_enter(LfRfidDebugApp* app, bool need_restore) {
+    auto submenu = app->view_controller.get<SubmenuVM>();
+    auto callback = cbc::obtain_connector(this, &LfRfidDebugAppSceneStart::submenu_callback);
+
+    submenu->add_item("Tune", SubmenuTune, callback, app);
+
+    if(need_restore) {
+        submenu->set_selected_item(submenu_item_selected);
+    }
+    app->view_controller.switch_to<SubmenuVM>();
+}
+
+bool LfRfidDebugAppSceneStart::on_event(LfRfidDebugApp* app, LfRfidDebugApp::Event* event) {
+    bool consumed = false;
+
+    if(event->type == LfRfidDebugApp::EventType::MenuSelected) {
+        submenu_item_selected = event->payload.menu_index;
+        switch(event->payload.menu_index) {
+        case SubmenuTune:
+            app->scene_controller.switch_to_next_scene(LfRfidDebugApp::SceneType::TuneScene);
+            break;
+        }
+        consumed = true;
+    }
+
+    return consumed;
+}
+
+void LfRfidDebugAppSceneStart::on_exit(LfRfidDebugApp* app) {
+    app->view_controller.get<SubmenuVM>()->clean();
+}
+
+void LfRfidDebugAppSceneStart::submenu_callback(void* context, uint32_t index) {
+    LfRfidDebugApp* app = static_cast<LfRfidDebugApp*>(context);
+    LfRfidDebugApp::Event event;
+
+    event.type = LfRfidDebugApp::EventType::MenuSelected;
+    event.payload.menu_index = index;
+
+    app->view_controller.send_event(&event);
+}

+ 13 - 0
applications/lfrfid-debug/scene/lfrfid-debug-app-scene-start.h

@@ -0,0 +1,13 @@
+#pragma once
+#include "../lfrfid-debug-app.h"
+
+class LfRfidDebugAppSceneStart : public GenericScene<LfRfidDebugApp> {
+public:
+    void on_enter(LfRfidDebugApp* app, bool need_restore) final;
+    bool on_event(LfRfidDebugApp* app, LfRfidDebugApp::Event* event) final;
+    void on_exit(LfRfidDebugApp* app) final;
+
+private:
+    void submenu_callback(void* context, uint32_t index);
+    uint32_t submenu_item_selected = 0;
+};

+ 28 - 0
applications/lfrfid-debug/scene/lfrfid-debug-app-scene-tune.cpp

@@ -0,0 +1,28 @@
+#include "lfrfid-debug-app-scene-tune.h"
+
+void LfRfidDebugAppSceneTune::on_enter(LfRfidDebugApp* app, bool need_restore) {
+    app->view_controller.switch_to<LfRfidViewTuneVM>();
+
+    api_hal_rfid_pins_read();
+    api_hal_rfid_tim_read(125000, 0.5);
+    api_hal_rfid_tim_read_start();
+}
+
+bool LfRfidDebugAppSceneTune::on_event(LfRfidDebugApp* app, LfRfidDebugApp::Event* event) {
+    bool consumed = false;
+
+    LfRfidViewTuneVM* tune = app->view_controller;
+
+    if(tune->is_dirty()) {
+        api_hal_rfid_set_read_period(tune->get_ARR());
+        api_hal_rfid_set_read_pulse(tune->get_CCR());
+    }
+
+    return consumed;
+}
+
+void LfRfidDebugAppSceneTune::on_exit(LfRfidDebugApp* app) {
+    api_hal_rfid_tim_read_stop();
+    api_hal_rfid_tim_reset();
+    api_hal_rfid_pins_reset();
+}

+ 9 - 0
applications/lfrfid-debug/scene/lfrfid-debug-app-scene-tune.h

@@ -0,0 +1,9 @@
+#pragma once
+#include "../lfrfid-debug-app.h"
+
+class LfRfidDebugAppSceneTune : public GenericScene<LfRfidDebugApp> {
+public:
+    void on_enter(LfRfidDebugApp* app, bool need_restore) final;
+    bool on_event(LfRfidDebugApp* app, LfRfidDebugApp::Event* event) final;
+    void on_exit(LfRfidDebugApp* app) final;
+};

+ 41 - 31
applications/lf-rfid/view/lf-rfid-view-tune.cpp → applications/lfrfid-debug/view-modules/lfrfid-view-tune-vm.cpp

@@ -1,10 +1,8 @@
-#include "lf-rfid-view-tune.h"
+#include "lfrfid-view-tune-vm.h"
 #include <callback-connector.h>
 #include <gui/elements.h>
-#include <variant>
-#include <list>
 
-struct LfRfidViewTuneModel {
+struct LfRfidViewTuneVMModel {
     bool dirty;
     bool fine;
     uint32_t ARR;
@@ -12,8 +10,8 @@ struct LfRfidViewTuneModel {
     int pos;
 };
 
-void LfRfidViewTune::view_draw_callback(Canvas* canvas, void* _model) {
-    LfRfidViewTuneModel* model = reinterpret_cast<LfRfidViewTuneModel*>(_model);
+void LfRfidViewTuneVM::view_draw_callback(Canvas* canvas, void* _model) {
+    LfRfidViewTuneVMModel* model = reinterpret_cast<LfRfidViewTuneVMModel*>(_model);
     canvas_clear(canvas);
     canvas_set_color(canvas, ColorBlack);
 
@@ -47,8 +45,8 @@ void LfRfidViewTune::view_draw_callback(Canvas* canvas, void* _model) {
     elements_multiline_text_aligned(canvas, 2, 2, AlignLeft, AlignTop, buffer);
 }
 
-bool LfRfidViewTune::view_input_callback(InputEvent* event, void* context) {
-    LfRfidViewTune* _this = reinterpret_cast<LfRfidViewTune*>(context);
+bool LfRfidViewTuneVM::view_input_callback(InputEvent* event, void* context) {
+    LfRfidViewTuneVM* _this = reinterpret_cast<LfRfidViewTuneVM*>(context);
     bool consumed = false;
 
     // Process key presses only
@@ -80,22 +78,22 @@ bool LfRfidViewTune::view_input_callback(InputEvent* event, void* context) {
     return consumed;
 }
 
-void LfRfidViewTune::button_up() {
-    with_view_model_cpp(view, LfRfidViewTuneModel, model, {
+void LfRfidViewTuneVM::button_up() {
+    with_view_model_cpp(view, LfRfidViewTuneVMModel, model, {
         if(model->pos > 0) model->pos--;
         return true;
     });
 }
 
-void LfRfidViewTune::button_down() {
-    with_view_model_cpp(view, LfRfidViewTuneModel, model, {
+void LfRfidViewTuneVM::button_down() {
+    with_view_model_cpp(view, LfRfidViewTuneVMModel, model, {
         if(model->pos < 1) model->pos++;
         return true;
     });
 }
 
-void LfRfidViewTune::button_left() {
-    with_view_model_cpp(view, LfRfidViewTuneModel, model, {
+void LfRfidViewTuneVM::button_left() {
+    with_view_model_cpp(view, LfRfidViewTuneVMModel, model, {
         if(model->pos == 0) {
             if(model->fine) {
                 model->ARR -= 1;
@@ -115,8 +113,8 @@ void LfRfidViewTune::button_left() {
     });
 }
 
-void LfRfidViewTune::button_right() {
-    with_view_model_cpp(view, LfRfidViewTuneModel, model, {
+void LfRfidViewTuneVM::button_right() {
+    with_view_model_cpp(view, LfRfidViewTuneVMModel, model, {
         if(model->pos == 0) {
             if(model->fine) {
                 model->ARR += 1;
@@ -136,19 +134,19 @@ void LfRfidViewTune::button_right() {
     });
 }
 
-void LfRfidViewTune::button_ok() {
-    with_view_model_cpp(view, LfRfidViewTuneModel, model, {
+void LfRfidViewTuneVM::button_ok() {
+    with_view_model_cpp(view, LfRfidViewTuneVMModel, model, {
         model->fine = !model->fine;
         return true;
     });
 }
 
-LfRfidViewTune::LfRfidViewTune() {
+LfRfidViewTuneVM::LfRfidViewTuneVM() {
     view = view_alloc();
     view_set_context(view, this);
-    view_allocate_model(view, ViewModelTypeLocking, sizeof(LfRfidViewTuneModel));
+    view_allocate_model(view, ViewModelTypeLocking, sizeof(LfRfidViewTuneVMModel));
 
-    with_view_model_cpp(view, LfRfidViewTuneModel, model, {
+    with_view_model_cpp(view, LfRfidViewTuneVMModel, model, {
         model->dirty = true;
         model->fine = false;
         model->ARR = 511;
@@ -157,22 +155,34 @@ LfRfidViewTune::LfRfidViewTune() {
         return true;
     });
 
-    view_set_draw_callback(view, cbc::obtain_connector(this, &LfRfidViewTune::view_draw_callback));
+    view_set_draw_callback(
+        view, cbc::obtain_connector(this, &LfRfidViewTuneVM::view_draw_callback));
     view_set_input_callback(
-        view, cbc::obtain_connector(this, &LfRfidViewTune::view_input_callback));
+        view, cbc::obtain_connector(this, &LfRfidViewTuneVM::view_input_callback));
 }
 
-LfRfidViewTune::~LfRfidViewTune() {
+LfRfidViewTuneVM::~LfRfidViewTuneVM() {
     view_free(view);
 }
 
-View* LfRfidViewTune::get_view() {
+View* LfRfidViewTuneVM::get_view() {
     return view;
 }
 
-bool LfRfidViewTune::is_dirty() {
+void LfRfidViewTuneVM::clean() {
+    with_view_model_cpp(view, LfRfidViewTuneVMModel, model, {
+        model->dirty = true;
+        model->fine = false;
+        model->ARR = 511;
+        model->CCR = 255;
+        model->pos = 0;
+        return true;
+    });
+}
+
+bool LfRfidViewTuneVM::is_dirty() {
     bool result;
-    with_view_model_cpp(view, LfRfidViewTuneModel, model, {
+    with_view_model_cpp(view, LfRfidViewTuneVMModel, model, {
         result = model->dirty;
         model->dirty = false;
         return false;
@@ -181,9 +191,9 @@ bool LfRfidViewTune::is_dirty() {
     return result;
 }
 
-uint32_t LfRfidViewTune::get_ARR() {
+uint32_t LfRfidViewTuneVM::get_ARR() {
     uint32_t result;
-    with_view_model_cpp(view, LfRfidViewTuneModel, model, {
+    with_view_model_cpp(view, LfRfidViewTuneVMModel, model, {
         result = model->ARR;
         return false;
     });
@@ -191,9 +201,9 @@ uint32_t LfRfidViewTune::get_ARR() {
     return result;
 }
 
-uint32_t LfRfidViewTune::get_CCR() {
+uint32_t LfRfidViewTuneVM::get_CCR() {
     uint32_t result;
-    with_view_model_cpp(view, LfRfidViewTuneModel, model, {
+    with_view_model_cpp(view, LfRfidViewTuneVMModel, model, {
         result = model->CCR;
         return false;
     });

+ 6 - 5
applications/lf-rfid/view/lf-rfid-view-tune.h → applications/lfrfid-debug/view-modules/lfrfid-view-tune-vm.h

@@ -1,12 +1,13 @@
 #pragma once
 #include <gui/view.h>
+#include <view-modules/generic-view-module.h>
 
-class LfRfidViewTune {
+class LfRfidViewTuneVM : public GenericViewModule {
 public:
-    LfRfidViewTune();
-    ~LfRfidViewTune();
-
-    View* get_view();
+    LfRfidViewTuneVM();
+    ~LfRfidViewTuneVM() final;
+    View* get_view() final;
+    void clean() final;
 
     bool is_dirty();
     uint32_t get_ARR();

+ 0 - 0
applications/lf-rfid/helpers/decoder-analyzer.cpp → applications/lfrfid/helpers/decoder-analyzer.cpp


+ 0 - 0
applications/lf-rfid/helpers/decoder-analyzer.h → applications/lfrfid/helpers/decoder-analyzer.h


+ 0 - 0
applications/lf-rfid/helpers/decoder-emmarine.cpp → applications/lfrfid/helpers/decoder-emmarine.cpp


+ 0 - 0
applications/lf-rfid/helpers/decoder-emmarine.h → applications/lfrfid/helpers/decoder-emmarine.h


+ 0 - 0
applications/lf-rfid/helpers/decoder-hid26.cpp → applications/lfrfid/helpers/decoder-hid26.cpp


+ 0 - 0
applications/lf-rfid/helpers/decoder-hid26.h → applications/lfrfid/helpers/decoder-hid26.h


+ 0 - 0
applications/lf-rfid/helpers/decoder-indala.cpp → applications/lfrfid/helpers/decoder-indala.cpp


+ 0 - 0
applications/lf-rfid/helpers/decoder-indala.h → applications/lfrfid/helpers/decoder-indala.h


+ 0 - 0
applications/lf-rfid/helpers/emmarine.h → applications/lfrfid/helpers/emmarine.h


+ 0 - 0
applications/lf-rfid/helpers/encoder-emmarine.cpp → applications/lfrfid/helpers/encoder-emmarine.cpp


+ 0 - 0
applications/lf-rfid/helpers/encoder-emmarine.h → applications/lfrfid/helpers/encoder-emmarine.h


+ 0 - 0
applications/lf-rfid/helpers/encoder-generic.h → applications/lfrfid/helpers/encoder-generic.h


+ 0 - 0
applications/lf-rfid/helpers/encoder-hid-h10301.cpp → applications/lfrfid/helpers/encoder-hid-h10301.cpp


+ 0 - 0
applications/lf-rfid/helpers/encoder-hid-h10301.h → applications/lfrfid/helpers/encoder-hid-h10301.h


+ 0 - 0
applications/lf-rfid/helpers/encoder-indala-40134.cpp → applications/lfrfid/helpers/encoder-indala-40134.cpp


+ 0 - 0
applications/lf-rfid/helpers/encoder-indala-40134.h → applications/lfrfid/helpers/encoder-indala-40134.h


+ 0 - 0
applications/lf-rfid/helpers/key-info.cpp → applications/lfrfid/helpers/key-info.cpp


+ 1 - 0
applications/lf-rfid/helpers/key-info.h → applications/lfrfid/helpers/key-info.h

@@ -2,6 +2,7 @@
 #include <stdint.h>
 
 static const uint8_t LFRFID_KEY_SIZE = 8;
+static const uint8_t LFRFID_KEY_NAME_SIZE = 22;
 
 enum class LfrfidKeyType : uint8_t {
     KeyEM4100,

+ 0 - 0
applications/lf-rfid/helpers/manchester-decoder.c → applications/lfrfid/helpers/manchester-decoder.c


+ 0 - 0
applications/lf-rfid/helpers/manchester-decoder.h → applications/lfrfid/helpers/manchester-decoder.h


+ 0 - 0
applications/lf-rfid/helpers/protocols/protocol-emmarin.cpp → applications/lfrfid/helpers/protocols/protocol-emmarin.cpp


+ 0 - 0
applications/lf-rfid/helpers/protocols/protocol-emmarin.h → applications/lfrfid/helpers/protocols/protocol-emmarin.h


+ 0 - 0
applications/lf-rfid/helpers/protocols/protocol-generic.h → applications/lfrfid/helpers/protocols/protocol-generic.h


+ 0 - 0
applications/lf-rfid/helpers/protocols/protocol-hid-h10301.cpp → applications/lfrfid/helpers/protocols/protocol-hid-h10301.cpp


+ 0 - 0
applications/lf-rfid/helpers/protocols/protocol-hid-h10301.h → applications/lfrfid/helpers/protocols/protocol-hid-h10301.h


+ 0 - 0
applications/lf-rfid/helpers/protocols/protocol-indala-40134.cpp → applications/lfrfid/helpers/protocols/protocol-indala-40134.cpp


+ 0 - 0
applications/lf-rfid/helpers/protocols/protocol-indala-40134.h → applications/lfrfid/helpers/protocols/protocol-indala-40134.h


+ 0 - 0
applications/lf-rfid/helpers/pulse-joiner.cpp → applications/lfrfid/helpers/pulse-joiner.cpp


+ 0 - 0
applications/lf-rfid/helpers/pulse-joiner.h → applications/lfrfid/helpers/pulse-joiner.h


+ 44 - 0
applications/lfrfid/helpers/rfid-key.cpp

@@ -0,0 +1,44 @@
+#include "rfid-key.h"
+#include <furi/check.h>
+
+RfidKey::RfidKey() {
+    data.fill(0);
+
+    for(uint8_t i = 0; i < (LFRFID_KEY_NAME_SIZE + 1); i++) {
+        name[i] = 0;
+    }
+}
+
+RfidKey::~RfidKey() {
+}
+
+void RfidKey::set_type(LfrfidKeyType _type) {
+    type = _type;
+}
+
+void RfidKey::set_data(uint8_t* _data, const uint8_t _data_size) {
+    furi_assert(_data_size <= data.size());
+    for(uint8_t i = 0; i < _data_size; i++) {
+        data[i] = _data[i];
+    }
+}
+
+LfrfidKeyType RfidKey::get_type() {
+    return type;
+}
+
+uint8_t* RfidKey::get_data() {
+    return &data[0];
+}
+
+const char* RfidKey::get_type_text() {
+    return lfrfid_key_get_type_string(type);
+}
+
+const uint8_t RfidKey::get_type_data_count() {
+    return lfrfid_key_get_type_data_count(type);
+}
+
+char* RfidKey::get_name() {
+    return name;
+}

+ 25 - 0
applications/lfrfid/helpers/rfid-key.h

@@ -0,0 +1,25 @@
+#pragma once
+#include "key-info.h"
+#include <array>
+
+class RfidKey {
+public:
+    RfidKey();
+    ~RfidKey();
+
+    void set_type(LfrfidKeyType type);
+    void set_data(uint8_t* data, const uint8_t data_size);
+
+    LfrfidKeyType get_type();
+    uint8_t* get_data();
+
+    const char* get_type_text();
+    const uint8_t get_type_data_count();
+
+    char* get_name();
+
+private:
+    std::array<uint8_t, LFRFID_KEY_SIZE> data;
+    LfrfidKeyType type;
+    char name[LFRFID_KEY_NAME_SIZE + 1];
+};

+ 35 - 0
applications/lfrfid/helpers/rfid-name-generator.cpp

@@ -0,0 +1,35 @@
+#include "rfid-name-generator.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+void rfid_generate_random_name(char* name, uint8_t max_name_size) {
+    const uint8_t prefix_size = 9;
+    const char* prefix[prefix_size] = {
+        "good",
+        "nice",
+        "best",
+        "some",
+        "strange",
+        "working",
+        "that",
+        "forgettable",
+        "easy",
+    };
+
+    const uint8_t suffix_size = 7;
+    const char* suffix[suffix_size] = {
+        "pass",
+        "card",
+        "key",
+        "fob",
+        "permit",
+        "pass",
+        "one",
+    };
+
+    sniprintf(
+        name, max_name_size, "%s_%s", prefix[rand() % prefix_size], suffix[rand() % suffix_size]);
+
+    // to upper
+    name[0] = name[0] - ('a' - 'A');
+}

+ 4 - 0
applications/lfrfid/helpers/rfid-name-generator.h

@@ -0,0 +1,4 @@
+#pragma once
+#include "stdint.h"
+
+void rfid_generate_random_name(char* name, uint8_t max_name_size);

+ 0 - 0
applications/lf-rfid/helpers/rfid-reader.cpp → applications/lfrfid/helpers/rfid-reader.cpp


+ 0 - 0
applications/lf-rfid/helpers/rfid-reader.h → applications/lfrfid/helpers/rfid-reader.h


+ 1 - 9
applications/lf-rfid/helpers/rfid-timer-emulator.cpp → applications/lfrfid/helpers/rfid-timer-emulator.cpp

@@ -18,7 +18,7 @@ void RfidTimerEmulator::start(LfrfidKeyType type, const uint8_t* data, uint8_t d
     if(encoders.count(type)) {
         current_encoder = encoders.find(type)->second;
 
-        if(lfrfid_key_get_type_data_count(type) == data_size) {
+        if(data_size >= lfrfid_key_get_type_data_count(type)) {
             current_encoder->init(data, data_size);
 
             api_hal_rfid_tim_emulate(125000);
@@ -26,14 +26,6 @@ void RfidTimerEmulator::start(LfrfidKeyType type, const uint8_t* data, uint8_t d
 
             api_interrupt_add(timer_update_callback, InterruptTypeTimerUpdate, this);
 
-            // TODO make api for interrupts priority
-            for(size_t i = WWDG_IRQn; i <= DMAMUX1_OVR_IRQn; i++) {
-                HAL_NVIC_SetPriority(static_cast<IRQn_Type>(i), 15, 0);
-            }
-
-            HAL_NVIC_SetPriority(TIM1_UP_TIM16_IRQn, 5, 0);
-            HAL_NVIC_EnableIRQ(TIM1_UP_TIM16_IRQn);
-
             api_hal_rfid_tim_emulate_start();
         }
     } else {

+ 0 - 0
applications/lf-rfid/helpers/rfid-timer-emulator.h → applications/lfrfid/helpers/rfid-timer-emulator.h


+ 111 - 0
applications/lfrfid/helpers/rfid-worker.cpp

@@ -0,0 +1,111 @@
+#include "rfid-worker.h"
+
+RfidWorker::RfidWorker() {
+}
+
+RfidWorker::~RfidWorker() {
+}
+
+void RfidWorker::start_read() {
+    reader.start(RfidReader::Type::Normal);
+}
+
+bool RfidWorker::read() {
+    static const uint8_t data_size = LFRFID_KEY_SIZE;
+    uint8_t data[data_size] = {0};
+    LfrfidKeyType type;
+
+    bool result = reader.read(&type, data, data_size);
+
+    if(result) {
+        key.set_type(type);
+        key.set_data(data, data_size);
+    };
+
+    return result;
+}
+
+void RfidWorker::stop_read() {
+    reader.stop();
+}
+
+void RfidWorker::start_write() {
+    write_result = WriteResult::Nothing;
+    write_sequence = new TickSequencer();
+    validate_counts = 0;
+
+    write_sequence->do_every_tick(1, std::bind(&RfidWorker::sq_write, this));
+    write_sequence->do_after_tick(2, std::bind(&RfidWorker::sq_write_start_validate, this));
+    write_sequence->do_after_tick(15, std::bind(&RfidWorker::sq_write_validate, this));
+    write_sequence->do_every_tick(1, std::bind(&RfidWorker::sq_write_stop_validate, this));
+}
+
+RfidWorker::WriteResult RfidWorker::write() {
+    write_sequence->tick();
+    return write_result;
+}
+
+void RfidWorker::stop_write() {
+    delete write_sequence;
+    reader.stop();
+}
+
+void RfidWorker::start_emulate() {
+    emulator.start(key.get_type(), key.get_data(), key.get_type_data_count());
+}
+
+void RfidWorker::stop_emulate() {
+    emulator.stop();
+}
+
+void RfidWorker::sq_write() {
+    // TODO expand this
+    switch(key.get_type()) {
+    case LfrfidKeyType::KeyEM4100:
+        writer.start();
+        writer.write_em(key.get_data());
+        writer.stop();
+        break;
+    case LfrfidKeyType::KeyH10301:
+        writer.start();
+        writer.write_hid(key.get_data());
+        writer.stop();
+        break;
+
+    default:
+        break;
+    }
+}
+
+void RfidWorker::sq_write_start_validate() {
+    reader.start(RfidReader::Type::Normal);
+}
+
+void RfidWorker::sq_write_validate() {
+    static const uint8_t data_size = LFRFID_KEY_SIZE;
+    uint8_t data[data_size] = {0};
+    LfrfidKeyType type;
+
+    bool result = reader.read(&type, data, data_size);
+
+    if(result) {
+        if(type == key.get_type()) {
+            if(memcmp(data, key.get_data(), key.get_type_data_count()) == 0) {
+                write_result = WriteResult::Ok;
+                validate_counts = 0;
+            } else {
+                validate_counts++;
+            }
+        } else {
+            validate_counts++;
+        }
+
+        if(validate_counts > 5) {
+            write_result = WriteResult::NotWritable;
+        }
+    };
+}
+
+void RfidWorker::sq_write_stop_validate() {
+    reader.stop();
+}

+ 46 - 0
applications/lfrfid/helpers/rfid-worker.h

@@ -0,0 +1,46 @@
+#pragma once
+#include "key-info.h"
+#include "rfid-reader.h"
+#include "rfid-writer.h"
+#include "rfid-timer-emulator.h"
+#include "rfid-key.h"
+#include "state-sequencer.h"
+
+class RfidWorker {
+public:
+    RfidWorker();
+    ~RfidWorker();
+
+    void start_read();
+    bool read();
+    void stop_read();
+
+    enum class WriteResult : uint8_t {
+        Ok,
+        NotWritable,
+        Nothing,
+    };
+
+    void start_write();
+    WriteResult write();
+    void stop_write();
+
+    void start_emulate();
+    void stop_emulate();
+
+    RfidKey key;
+
+private:
+    RfidWriter writer;
+    RfidReader reader;
+    RfidTimerEmulator emulator;
+
+    WriteResult write_result;
+    TickSequencer* write_sequence;
+
+    void sq_write();
+    void sq_write_start_validate();
+    void sq_write_validate();
+    uint8_t validate_counts;
+    void sq_write_stop_validate();
+};

+ 30 - 6
applications/lf-rfid/helpers/rfid-writer.cpp → applications/lfrfid/helpers/rfid-writer.cpp

@@ -1,6 +1,7 @@
 #include "rfid-writer.h"
 #include <api-hal.h>
 #include "protocols/protocol-emmarin.h"
+#include "protocols/protocol-hid-h10301.h"
 
 extern COMP_HandleTypeDef hcomp1;
 
@@ -11,8 +12,8 @@ extern COMP_HandleTypeDef hcomp1;
 class T55xxTiming {
 public:
     constexpr static const uint16_t wait_time = 400;
-    constexpr static const uint8_t start_gap = 15;
-    constexpr static const uint8_t write_gap = 10;
+    constexpr static const uint8_t start_gap = 30;
+    constexpr static const uint8_t write_gap = 18;
     constexpr static const uint8_t data_0 = 24;
     constexpr static const uint8_t data_1 = 56;
     constexpr static const uint16_t program = 700;
@@ -34,6 +35,7 @@ RfidWriter::~RfidWriter() {
 void RfidWriter::start() {
     api_hal_rfid_tim_read(125000, 0.5);
     api_hal_rfid_pins_read();
+    api_hal_rfid_tim_read_start();
 }
 
 void RfidWriter::stop() {
@@ -64,8 +66,6 @@ void RfidWriter::write_byte(uint8_t value) {
 }
 
 void RfidWriter::write_block(uint8_t page, uint8_t block, bool lock_bit, uint32_t data) {
-    // wait to power card
-    api_hal_rfid_tim_read_start();
     delay_us(T55xxTiming::wait_time * 8);
 
     // start gap
@@ -101,18 +101,42 @@ void RfidWriter::write_block(uint8_t page, uint8_t block, bool lock_bit, uint32_
 
     delay_us(T55xxTiming::program * 8);
 
-    api_hal_rfid_tim_read_stop();
+    delay_us(T55xxTiming::wait_time * 8);
+    write_reset();
+}
+
+void RfidWriter::write_reset() {
+    write_gap(T55xxTiming::start_gap);
+    write_bit(1);
+    write_bit(0);
 }
 
 void RfidWriter::write_em(uint8_t em_data[5]) {
     ProtocolEMMarin em_card;
     uint64_t em_encoded_data;
     em_card.encode(em_data, 5, reinterpret_cast<uint8_t*>(&em_encoded_data), sizeof(uint64_t));
-    uint32_t em_config_block_data = 0b01100000000101001000000001000000;
+    const uint32_t em_config_block_data = 0b01100000000101001000000001000000;
 
     __disable_irq();
     write_block(0, 0, false, em_config_block_data);
     write_block(0, 1, false, em_encoded_data);
     write_block(0, 2, false, em_encoded_data >> 32);
+    write_reset();
+    __enable_irq();
+}
+
+void RfidWriter::write_hid(uint8_t hid_data[3]) {
+    ProtocolHID10301 hid_card;
+    uint32_t card_data[3];
+    hid_card.encode(hid_data, 3, reinterpret_cast<uint8_t*>(&card_data), sizeof(card_data) * 3);
+
+    const uint32_t hid_config_block_data = 0b00000000000100000111000001100000;
+
+    __disable_irq();
+    write_block(0, 0, false, hid_config_block_data);
+    write_block(0, 1, false, card_data[0]);
+    write_block(0, 2, false, card_data[1]);
+    write_block(0, 3, false, card_data[2]);
+    write_reset();
     __enable_irq();
 }

+ 2 - 0
applications/lf-rfid/helpers/rfid-writer.h → applications/lfrfid/helpers/rfid-writer.h

@@ -8,10 +8,12 @@ public:
     void start();
     void stop();
     void write_em(uint8_t em_data[5]);
+    void write_hid(uint8_t hid_data[3]);
 
 private:
     void write_gap(uint32_t gap_time);
     void write_bit(bool value);
     void write_byte(uint8_t value);
     void write_block(uint8_t page, uint8_t block, bool lock_bit, uint32_t data);
+    void write_reset();
 };

+ 50 - 0
applications/lfrfid/helpers/state-sequencer.cpp

@@ -0,0 +1,50 @@
+#include "state-sequencer.h"
+#include "stdio.h"
+
+TickSequencer::TickSequencer() {
+}
+
+TickSequencer::~TickSequencer() {
+}
+
+void TickSequencer::tick() {
+    if(tick_count == list_it->first) {
+        tick_count = 0;
+
+        list_it++;
+        if(list_it == list.end()) {
+            list_it = list.begin();
+        }
+    }
+
+    list_it->second();
+    tick_count++;
+}
+
+void TickSequencer::reset() {
+    list_it = list.begin();
+    tick_count = 0;
+}
+
+void TickSequencer::clear() {
+    list.clear();
+    reset();
+}
+
+void TickSequencer::do_every_tick(uint32_t tick_count, std::function<void(void)> fn) {
+    list.push_back(std::make_pair(tick_count, fn));
+    reset();
+}
+
+void TickSequencer::do_after_tick(uint32_t tick_count, std::function<void(void)> fn) {
+    if(tick_count > 1) {
+        list.push_back(
+            std::make_pair(tick_count - 1, std::bind(&TickSequencer::do_nothing, this)));
+    }
+    list.push_back(std::make_pair(1, fn));
+
+    reset();
+}
+
+void TickSequencer::do_nothing() {
+}

+ 25 - 0
applications/lfrfid/helpers/state-sequencer.h

@@ -0,0 +1,25 @@
+#pragma once
+#include "stdint.h"
+#include <list>
+#include <functional>
+
+class TickSequencer {
+public:
+    TickSequencer();
+    ~TickSequencer();
+
+    void tick();
+    void reset();
+    void clear();
+
+    void do_every_tick(uint32_t tick_count, std::function<void(void)> fn);
+    void do_after_tick(uint32_t tick_count, std::function<void(void)> fn);
+
+private:
+    std::list<std::pair<uint32_t, std::function<void(void)> > > list;
+    std::list<std::pair<uint32_t, std::function<void(void)> > >::iterator list_it;
+
+    uint32_t tick_count;
+
+    void do_nothing();
+};

+ 10 - 0
applications/lfrfid/lfrfid-app-launcher.cpp

@@ -0,0 +1,10 @@
+#include "lfrfid-app.h"
+
+// app enter function
+extern "C" int32_t lfrfid_app(void* p) {
+    LfRfidApp* app = new LfRfidApp();
+    app->run();
+    delete app;
+
+    return 0;
+}

+ 37 - 0
applications/lfrfid/lfrfid-app.cpp

@@ -0,0 +1,37 @@
+#include "lfrfid-app.h"
+#include "scene/lfrfid-app-scene-start.h"
+#include "scene/lfrfid-app-scene-read.h"
+#include "scene/lfrfid-app-scene-read-success.h"
+#include "scene/lfrfid-app-scene-readed-menu.h"
+#include "scene/lfrfid-app-scene-write.h"
+#include "scene/lfrfid-app-scene-write-success.h"
+#include "scene/lfrfid-app-scene-emulate.h"
+#include "scene/lfrfid-app-scene-save-name.h"
+
+LfRfidApp::LfRfidApp()
+    : scene_controller{this}
+    , fs_api{"sdcard"}
+    , sd_ex_api{"sdcard-ex"}
+    , notification{"notification"}
+    , text_store(40) {
+    api_hal_power_insomnia_enter();
+
+    // we need random
+    srand(DWT->CYCCNT);
+}
+
+LfRfidApp::~LfRfidApp() {
+    api_hal_power_insomnia_exit();
+}
+
+void LfRfidApp::run() {
+    scene_controller.add_scene(SceneType::Start, new LfRfidAppSceneStart());
+    scene_controller.add_scene(SceneType::Read, new LfRfidAppSceneRead());
+    scene_controller.add_scene(SceneType::ReadSuccess, new LfRfidAppSceneReadSuccess());
+    scene_controller.add_scene(SceneType::ReadedMenu, new LfRfidAppSceneReadedMenu());
+    scene_controller.add_scene(SceneType::Write, new LfRfidAppSceneWrite());
+    scene_controller.add_scene(SceneType::WriteSuccess, new LfRfidAppSceneWriteSuccess());
+    scene_controller.add_scene(SceneType::Emulate, new LfRfidAppSceneEmulate());
+    scene_controller.add_scene(SceneType::SaveName, new LfRfidAppSceneSaveName());
+    scene_controller.process(100);
+}

+ 67 - 0
applications/lfrfid/lfrfid-app.h

@@ -0,0 +1,67 @@
+#pragma once
+#include <furi.h>
+#include <api-hal.h>
+
+#include <generic-scene.hpp>
+#include <scene-controller.hpp>
+#include <view-controller.hpp>
+#include <record-controller.hpp>
+#include <text-store.h>
+
+#include <view-modules/submenu-vm.h>
+#include <view-modules/popup-vm.h>
+#include <view-modules/dialog-ex-vm.h>
+#include <view-modules/text-input-vm.h>
+#include <view-modules/byte-input-vm.h>
+#include "view/container-vm.h"
+
+#include <sd-card-api.h>
+#include <filesystem-api.h>
+#include <notification/notification-messages.h>
+
+#include "helpers/rfid-worker.h"
+
+class LfRfidApp {
+public:
+    enum class EventType : uint8_t {
+        GENERIC_EVENT_ENUM_VALUES,
+        Next,
+        MenuSelected,
+    };
+
+    enum class SceneType : uint8_t {
+        GENERIC_SCENE_ENUM_VALUES,
+        Read,
+        ReadSuccess,
+        ReadedMenu,
+        Write,
+        WriteSuccess,
+        Emulate,
+        SaveName,
+    };
+
+    class Event {
+    public:
+        union {
+            int32_t menu_index;
+        } payload;
+
+        EventType type;
+    };
+
+    SceneController<GenericScene<LfRfidApp>, LfRfidApp> scene_controller;
+    ViewController<LfRfidApp, SubmenuVM, PopupVM, DialogExVM, TextInputVM, ByteInputVM, ContainerVM>
+        view_controller;
+
+    ~LfRfidApp();
+    LfRfidApp();
+
+    RecordController<FS_Api> fs_api;
+    RecordController<SdCard_Api> sd_ex_api;
+    RecordController<NotificationApp> notification;
+
+    RfidWorker worker;
+
+    TextStore text_store;
+    void run();
+};

+ 0 - 0
applications/lf-rfid/lf-rfid-cli.cpp → applications/lfrfid/lfrfid-cli.cpp


+ 36 - 0
applications/lfrfid/scene/lfrfid-app-scene-emulate.cpp

@@ -0,0 +1,36 @@
+#include "lfrfid-app-scene-emulate.h"
+
+void LfRfidAppSceneEmulate::on_enter(LfRfidApp* app, bool need_restore) {
+    string_init(data_string);
+
+    uint8_t* data = app->worker.key.get_data();
+
+    for(uint8_t i = 0; i < app->worker.key.get_type_data_count(); i++) {
+        string_cat_printf(data_string, "%02X", data[i]);
+    }
+
+    auto popup = app->view_controller.get<PopupVM>();
+
+    popup->set_header("Emulating", 90, 34, AlignCenter, AlignTop);
+    popup->set_text(string_get_cstr(data_string), 90, 48, AlignCenter, AlignTop);
+    popup->set_icon(0, 4, I_RFIDDolphinSend_98x60);
+
+    app->view_controller.switch_to<PopupVM>();
+    app->worker.start_emulate();
+}
+
+bool LfRfidAppSceneEmulate::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
+    bool consumed = false;
+
+    if(event->type == LfRfidApp::EventType::Tick) {
+        notification_message(app->notification, &sequence_blink_cyan_10);
+    }
+
+    return consumed;
+}
+
+void LfRfidAppSceneEmulate::on_exit(LfRfidApp* app) {
+    app->view_controller.get<PopupVM>()->clean();
+    app->worker.stop_emulate();
+    string_clear(data_string);
+}

+ 12 - 0
applications/lfrfid/scene/lfrfid-app-scene-emulate.h

@@ -0,0 +1,12 @@
+#pragma once
+#include "../lfrfid-app.h"
+
+class LfRfidAppSceneEmulate : public GenericScene<LfRfidApp> {
+public:
+    void on_enter(LfRfidApp* app, bool need_restore) final;
+    bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
+    void on_exit(LfRfidApp* app) final;
+
+private:
+    string_t data_string;
+};

+ 117 - 0
applications/lfrfid/scene/lfrfid-app-scene-read-success.cpp

@@ -0,0 +1,117 @@
+#include "lfrfid-app-scene-read-success.h"
+#include "../view/elements/button-element.h"
+#include "../view/elements/icon-element.h"
+#include "../view/elements/string-element.h"
+
+void LfRfidAppSceneReadSuccess::on_enter(LfRfidApp* app, bool need_restore) {
+    string_init(string[0]);
+    string_init(string[1]);
+    string_init(string[2]);
+
+    auto container = app->view_controller.get<ContainerVM>();
+
+    auto button = container->add<ButtonElement>();
+    button->set_type(ButtonElement::Type::Left, "Retry");
+    button->set_callback(app, LfRfidAppSceneReadSuccess::back_callback);
+
+    button = container->add<ButtonElement>();
+    button->set_type(ButtonElement::Type::Right, "More");
+    button->set_callback(app, LfRfidAppSceneReadSuccess::more_callback);
+
+    auto icon = container->add<IconElement>();
+    icon->set_icon(3, 12, I_RFIDBigChip_37x36);
+
+    auto header = container->add<StringElement>();
+    header->set_text(app->worker.key.get_type_text(), 89, 3, AlignCenter);
+
+    auto line_1_text = container->add<StringElement>();
+    auto line_2_text = container->add<StringElement>();
+    auto line_3_text = container->add<StringElement>();
+
+    auto line_1_value = container->add<StringElement>();
+    auto line_2_value = container->add<StringElement>();
+    auto line_3_value = container->add<StringElement>();
+
+    uint8_t* data = app->worker.key.get_data();
+
+    switch(app->worker.key.get_type()) {
+    case LfrfidKeyType::KeyEM4100:
+        line_1_text->set_text("HEX:", 65, 23, AlignRight, AlignBottom, FontSecondary);
+        line_2_text->set_text("Mod:", 65, 35, AlignRight, AlignBottom, FontSecondary);
+        line_3_text->set_text("ID:", 65, 47, AlignRight, AlignBottom, FontSecondary);
+
+        for(uint8_t i = 0; i < app->worker.key.get_type_data_count(); i++) {
+            string_cat_printf(string[0], "%02X", data[i]);
+        }
+
+        string_printf(string[1], "Manchester");
+        string_printf(string[2], "%03u,%05u", data[2], (uint16_t)((data[3] << 8) | (data[4])));
+
+        line_1_value->set_text(
+            string_get_cstr(string[0]), 68, 23, AlignLeft, AlignBottom, FontSecondary);
+        line_2_value->set_text(
+            string_get_cstr(string[1]), 68, 35, AlignLeft, AlignBottom, FontSecondary);
+        line_3_value->set_text(
+            string_get_cstr(string[2]), 68, 47, AlignLeft, AlignBottom, FontSecondary);
+        break;
+    case LfrfidKeyType::KeyH10301:
+        line_1_text->set_text("HEX:", 65, 23, AlignRight, AlignBottom, FontSecondary);
+        line_2_text->set_text("FC:", 65, 35, AlignRight, AlignBottom, FontSecondary);
+        line_3_text->set_text("Card:", 65, 47, AlignRight, AlignBottom, FontSecondary);
+
+        for(uint8_t i = 0; i < app->worker.key.get_type_data_count(); i++) {
+            string_cat_printf(string[0], "%02X", data[i]);
+        }
+
+        string_printf(string[1], "%u", data[0]);
+        string_printf(string[2], "%u", (uint16_t)((data[1] << 8) | (data[2])));
+
+        line_1_value->set_text(
+            string_get_cstr(string[0]), 68, 23, AlignLeft, AlignBottom, FontSecondary);
+        line_2_value->set_text(
+            string_get_cstr(string[1]), 68, 35, AlignLeft, AlignBottom, FontSecondary);
+        line_3_value->set_text(
+            string_get_cstr(string[2]), 68, 47, AlignLeft, AlignBottom, FontSecondary);
+        break;
+    case LfrfidKeyType::KeyI40134:
+        //TODO implement when we can read Indala
+        break;
+    }
+
+    app->view_controller.switch_to<ContainerVM>();
+
+    notification_message_block(app->notification, &sequence_set_green_255);
+}
+
+bool LfRfidAppSceneReadSuccess::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
+    bool consumed = false;
+
+    if(event->type == LfRfidApp::EventType::Next) {
+        app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::ReadedMenu);
+        consumed = true;
+    }
+
+    return consumed;
+}
+
+void LfRfidAppSceneReadSuccess::on_exit(LfRfidApp* app) {
+    notification_message_block(app->notification, &sequence_reset_green);
+    app->view_controller.get<ContainerVM>()->clean();
+    string_clear(string[0]);
+    string_clear(string[1]);
+    string_clear(string[2]);
+}
+
+void LfRfidAppSceneReadSuccess::back_callback(void* context) {
+    LfRfidApp* app = static_cast<LfRfidApp*>(context);
+    LfRfidApp::Event event;
+    event.type = LfRfidApp::EventType::Back;
+    app->view_controller.send_event(&event);
+}
+
+void LfRfidAppSceneReadSuccess::more_callback(void* context) {
+    LfRfidApp* app = static_cast<LfRfidApp*>(context);
+    LfRfidApp::Event event;
+    event.type = LfRfidApp::EventType::Next;
+    app->view_controller.send_event(&event);
+}

+ 15 - 0
applications/lfrfid/scene/lfrfid-app-scene-read-success.h

@@ -0,0 +1,15 @@
+#pragma once
+#include "../lfrfid-app.h"
+
+class LfRfidAppSceneReadSuccess : public GenericScene<LfRfidApp> {
+public:
+    void on_enter(LfRfidApp* app, bool need_restore) final;
+    bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
+    void on_exit(LfRfidApp* app) final;
+
+private:
+    static void back_callback(void* context);
+    static void more_callback(void* context);
+
+    string_t string[3];
+};

+ 31 - 0
applications/lfrfid/scene/lfrfid-app-scene-read.cpp

@@ -0,0 +1,31 @@
+#include "lfrfid-app-scene-read.h"
+
+void LfRfidAppSceneRead::on_enter(LfRfidApp* app, bool need_restore) {
+    auto popup = app->view_controller.get<PopupVM>();
+
+    popup->set_header("Reading\nLF RFID", 70, 34, AlignLeft, AlignTop);
+    popup->set_icon(0, 4, I_RFIDDolphinReceive_98x60);
+
+    app->view_controller.switch_to<PopupVM>();
+    app->worker.start_read();
+}
+
+bool LfRfidAppSceneRead::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
+    bool consumed = false;
+
+    if(event->type == LfRfidApp::EventType::Tick) {
+        if(app->worker.read()) {
+            notification_message(app->notification, &sequence_success);
+            app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::ReadSuccess);
+        } else {
+            notification_message(app->notification, &sequence_blink_red_10);
+        }
+    }
+
+    return consumed;
+}
+
+void LfRfidAppSceneRead::on_exit(LfRfidApp* app) {
+    app->view_controller.get<PopupVM>()->clean();
+    app->worker.stop_read();
+}

+ 9 - 0
applications/lfrfid/scene/lfrfid-app-scene-read.h

@@ -0,0 +1,9 @@
+#pragma once
+#include "../lfrfid-app.h"
+
+class LfRfidAppSceneRead : public GenericScene<LfRfidApp> {
+public:
+    void on_enter(LfRfidApp* app, bool need_restore) final;
+    bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
+    void on_exit(LfRfidApp* app) final;
+};

+ 60 - 0
applications/lfrfid/scene/lfrfid-app-scene-readed-menu.cpp

@@ -0,0 +1,60 @@
+#include "lfrfid-app-scene-readed-menu.h"
+
+typedef enum {
+    SubmenuWrite,
+    SubmenuNameAndSave,
+    SubmenuEmulate,
+} SubmenuIndex;
+
+void LfRfidAppSceneReadedMenu::on_enter(LfRfidApp* app, bool need_restore) {
+    auto submenu = app->view_controller.get<SubmenuVM>();
+
+    submenu->add_item("Write", SubmenuWrite, submenu_callback, app);
+    submenu->add_item("Name and Save", SubmenuNameAndSave, submenu_callback, app);
+    submenu->add_item("Emulate", SubmenuEmulate, submenu_callback, app);
+
+    if(need_restore) {
+        submenu->set_selected_item(submenu_item_selected);
+    }
+
+    app->view_controller.switch_to<SubmenuVM>();
+}
+
+bool LfRfidAppSceneReadedMenu::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
+    bool consumed = false;
+
+    if(event->type == LfRfidApp::EventType::MenuSelected) {
+        submenu_item_selected = event->payload.menu_index;
+        switch(event->payload.menu_index) {
+        case SubmenuWrite:
+            app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Write);
+            break;
+        case SubmenuNameAndSave:
+            app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveName);
+            break;
+        case SubmenuEmulate:
+            app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Emulate);
+            break;
+        }
+        consumed = true;
+    } else if(event->type == LfRfidApp::EventType::Back) {
+        app->scene_controller.search_and_switch_to_previous_scene({LfRfidApp::SceneType::Start});
+        consumed = true;
+    }
+
+    return consumed;
+}
+
+void LfRfidAppSceneReadedMenu::on_exit(LfRfidApp* app) {
+    app->view_controller.get<SubmenuVM>()->clean();
+}
+
+void LfRfidAppSceneReadedMenu::submenu_callback(void* context, uint32_t index) {
+    LfRfidApp* app = static_cast<LfRfidApp*>(context);
+    LfRfidApp::Event event;
+
+    event.type = LfRfidApp::EventType::MenuSelected;
+    event.payload.menu_index = index;
+
+    app->view_controller.send_event(&event);
+}

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است