MX 2 anni fa
parent
commit
37f80b1da4

+ 1 - 1
non_catalog_apps/wiegand/application.fam

@@ -9,6 +9,6 @@ App(
     fap_category="GPIO",
     fap_category="GPIO",
     fap_author="@jamisonderek",
     fap_author="@jamisonderek",
     fap_weburl="https://github.com/jamisonderek/flipper-zero-tutorials/tree/main/gpio",
     fap_weburl="https://github.com/jamisonderek/flipper-zero-tutorials/tree/main/gpio",
-    fap_version="1.0",
+    fap_version="1.2",
     fap_description="This application can be used to test Wiegand readers and keypads",
     fap_description="This application can be used to test Wiegand readers and keypads",
 )
 )

+ 2 - 2
non_catalog_apps/wiegand/scenes/wiegand_instructions.c

@@ -10,6 +10,7 @@ void wiegand_instructions_scene_on_enter(void* context) {
         15,
         15,
         128,
         128,
         40,
         40,
+        "Version 1.2\n"
         "Only use on devices you own!\n"
         "Only use on devices you own!\n"
         "Connect D0 (Green) to pin A4\n"
         "Connect D0 (Green) to pin A4\n"
         "Connect D1 (White) to pin A7\n"
         "Connect D1 (White) to pin A7\n"
@@ -37,7 +38,6 @@ void wiegand_instructions_scene_on_enter(void* context) {
         "Connect pin A4 to drain of\n"
         "Connect pin A4 to drain of\n"
         "mosfet for D0. Connect\n"
         "mosfet for D0. Connect\n"
         "source of mosfet for D0 to\n"
         "source of mosfet for D0 to\n"
-        "GND.\n"
-        );
+        "GND.\n");
     view_dispatcher_switch_to_view(app->view_dispatcher, WiegandWidgetView);
     view_dispatcher_switch_to_view(app->view_dispatcher, WiegandWidgetView);
 }
 }

+ 9 - 0
non_catalog_apps/wiegand/scenes/wiegand_main_menu.c

@@ -15,6 +15,9 @@ void wiegand_menu_callback(void* context, uint32_t index) {
     case WiegandMainMenuRead:
     case WiegandMainMenuRead:
         event = WiegandMainMenuReadEvent;
         event = WiegandMainMenuReadEvent;
         break;
         break;
+    case WiegandMainMenuScan:
+        event = WiegandMainMenuScanEvent;
+        break;
     case WiegandMainMenuLoad:
     case WiegandMainMenuLoad:
         event = WiegandMainMenuLoadEvent;
         event = WiegandMainMenuLoadEvent;
         break;
         break;
@@ -36,6 +39,8 @@ void wiegand_main_menu_scene_on_enter(void* context) {
     submenu_add_item(
     submenu_add_item(
         app->submenu, "Instructions", WiegandMainMenuInstructions, wiegand_menu_callback, app);
         app->submenu, "Instructions", WiegandMainMenuInstructions, wiegand_menu_callback, app);
     submenu_add_item(app->submenu, "Read", WiegandMainMenuRead, wiegand_menu_callback, app);
     submenu_add_item(app->submenu, "Read", WiegandMainMenuRead, wiegand_menu_callback, app);
+    submenu_add_item(
+        app->submenu, "Scan w/AutoSave", WiegandMainMenuScan, wiegand_menu_callback, app);
     submenu_add_item(app->submenu, "Load", WiegandMainMenuLoad, wiegand_menu_callback, app);
     submenu_add_item(app->submenu, "Load", WiegandMainMenuLoad, wiegand_menu_callback, app);
     view_dispatcher_switch_to_view(app->view_dispatcher, WiegandSubmenuView);
     view_dispatcher_switch_to_view(app->view_dispatcher, WiegandSubmenuView);
 }
 }
@@ -53,6 +58,10 @@ bool wiegand_main_menu_scene_on_event(void* context, SceneManagerEvent event) {
             scene_manager_next_scene(app->scene_manager, WiegandReadScene);
             scene_manager_next_scene(app->scene_manager, WiegandReadScene);
             consumed = true;
             consumed = true;
             break;
             break;
+        case WiegandMainMenuScanEvent:
+            scene_manager_next_scene(app->scene_manager, WiegandScanScene);
+            consumed = true;
+            break;
         case WiegandMainMenuLoadEvent:
         case WiegandMainMenuLoadEvent:
             scene_manager_next_scene(app->scene_manager, WiegandLoadScene);
             scene_manager_next_scene(app->scene_manager, WiegandLoadScene);
             consumed = true;
             consumed = true;

+ 138 - 0
non_catalog_apps/wiegand/scenes/wiegand_scan.c

@@ -0,0 +1,138 @@
+#include "../wiegand.h"
+
+FuriTimer* timer = NULL;
+
+static void wiegand_scan_isr_d0(void* context) {
+    UNUSED(context);
+    uint32_t time = DWT->CYCCNT;
+    bool rise = furi_hal_gpio_read(pinD0);
+
+    data[bit_count] = 0;
+
+    if(rise) {
+        data_rise[bit_count] = time;
+        if(bit_count < MAX_BITS) {
+            bit_count++;
+        }
+    } else {
+        data_fall[bit_count] = time;
+    }
+}
+
+static void wiegand_scan_isr_d1(void* context) {
+    UNUSED(context);
+    uint32_t time = DWT->CYCCNT;
+    bool rise = furi_hal_gpio_read(pinD1);
+
+    data[bit_count] = 1;
+
+    if(rise) {
+        data_rise[bit_count] = time;
+        if(bit_count < MAX_BITS) {
+            bit_count++;
+        }
+    } else {
+        data_fall[bit_count] = time;
+    }
+}
+
+static void wiegand_start_scan(void* context) {
+    UNUSED(context);
+    data_saved = false;
+    bit_count = 0;
+    furi_hal_gpio_init_simple(pinD0, GpioModeInterruptRiseFall);
+    furi_hal_gpio_init_simple(pinD1, GpioModeInterruptRiseFall);
+    furi_hal_gpio_add_int_callback(pinD0, wiegand_scan_isr_d0, NULL);
+    furi_hal_gpio_add_int_callback(pinD1, wiegand_scan_isr_d1, NULL);
+    furi_timer_start(timer, 100);
+}
+
+static void wiegand_stop_scan(void* context) {
+    UNUSED(context);
+    furi_hal_gpio_remove_int_callback(pinD0);
+    furi_hal_gpio_remove_int_callback(pinD1);
+    furi_hal_gpio_init_simple(pinD0, GpioModeAnalog);
+    furi_hal_gpio_init_simple(pinD1, GpioModeAnalog);
+    furi_timer_stop(timer);
+}
+
+static void wiegand_scan_found(void* context) {
+    App* app = context;
+
+    FuriHalRtcDateTime datetime;
+    furi_hal_rtc_get_datetime(&datetime);
+    snprintf(
+        app->file_name,
+        25,
+        "%02d%02d%02d_%02d%02d%02d",
+        datetime.year,
+        datetime.month,
+        datetime.day,
+        datetime.hour,
+        datetime.minute,
+        datetime.second);
+    furi_hal_vibro_on(true);
+    furi_delay_ms(50);
+    furi_hal_vibro_on(false);
+    furi_delay_ms(50);
+    wiegand_save(app);
+    furi_hal_vibro_on(true);
+    furi_delay_ms(50);
+    furi_hal_vibro_on(false);
+    furi_delay_ms(1000);
+    wiegand_start_scan(app);
+}
+
+static void wiegand_scan_timer_callback(void* context) {
+    App* app = context;
+    uint32_t duration = DWT->CYCCNT;
+    const uint32_t one_millisecond = 64000;
+
+    if(bit_count == 0) {
+        return;
+    }
+
+    duration -= data_fall[bit_count - 1];
+
+    bool found = false;
+    FURI_CRITICAL_ENTER();
+    if(duration > 25 * one_millisecond) {
+        if(bit_count == 4 || bit_count == 8 || bit_count == 24 || bit_count == 26 ||
+           bit_count == 32 || bit_count == 34 || bit_count == 37 || bit_count == 40 ||
+           bit_count == 48) {
+            wiegand_stop_scan(app);
+            found = true;
+        } else {
+            // No data, clear
+            bit_count = 0;
+        }
+    }
+    FURI_CRITICAL_EXIT();
+
+    if(found) {
+        wiegand_scan_found(app);
+    }
+}
+
+void wiegand_scan_scene_on_enter(void* context) {
+    App* app = context;
+    timer = furi_timer_alloc(wiegand_scan_timer_callback, FuriTimerTypePeriodic, app);
+    widget_reset(app->widget);
+    widget_add_string_element(app->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Scan Wiegand");
+    widget_add_string_element(
+        app->widget, 0, 20, AlignLeft, AlignTop, FontSecondary, "Files saved automatically.");
+    widget_add_string_element(
+        app->widget, 0, 30, AlignLeft, AlignTop, FontSecondary, "Vibrates on detection.");
+    widget_add_string_element(
+        app->widget, 0, 45, AlignLeft, AlignTop, FontSecondary, "D0/Green/A4");
+    widget_add_string_element(
+        app->widget, 0, 53, AlignLeft, AlignTop, FontSecondary, "D1/White/A7");
+    wiegand_start_scan(app);
+    view_dispatcher_switch_to_view(app->view_dispatcher, WiegandWidgetView);
+}
+
+void wiegand_scan_scene_on_exit(void* context) {
+    App* app = context;
+    wiegand_stop_scan(app);
+    furi_timer_free(timer);
+}

+ 3 - 0
non_catalog_apps/wiegand/wiegand.c

@@ -23,6 +23,7 @@ void (*const basic_scenes_scene_on_enter_handlers[])(void*) = {
     wiegand_main_menu_scene_on_enter,
     wiegand_main_menu_scene_on_enter,
     wiegand_instructions_scene_on_enter,
     wiegand_instructions_scene_on_enter,
     wiegand_read_scene_on_enter,
     wiegand_read_scene_on_enter,
+    wiegand_scan_scene_on_enter,
     wiegand_data_scene_on_enter,
     wiegand_data_scene_on_enter,
     wiegand_save_scene_on_enter,
     wiegand_save_scene_on_enter,
     wiegand_load_scene_on_enter,
     wiegand_load_scene_on_enter,
@@ -32,6 +33,7 @@ bool (*const basic_scenes_scene_on_event_handlers[])(void*, SceneManagerEvent) =
     wiegand_main_menu_scene_on_event,
     wiegand_main_menu_scene_on_event,
     wiegand_empty_scene_on_event, // instructions
     wiegand_empty_scene_on_event, // instructions
     wiegand_empty_scene_on_event, // read
     wiegand_empty_scene_on_event, // read
+    wiegand_empty_scene_on_event, // scan
     wiegand_data_scene_on_event,
     wiegand_data_scene_on_event,
     wiegand_save_scene_on_event,
     wiegand_save_scene_on_event,
     wiegand_empty_scene_on_event, // load
     wiegand_empty_scene_on_event, // load
@@ -41,6 +43,7 @@ void (*const basic_scenes_scene_on_exit_handlers[])(void*) = {
     wiegand_empty_scene_on_exit, // main_menu
     wiegand_empty_scene_on_exit, // main_menu
     wiegand_empty_scene_on_exit, // instructions
     wiegand_empty_scene_on_exit, // instructions
     wiegand_read_scene_on_exit,
     wiegand_read_scene_on_exit,
+    wiegand_scan_scene_on_exit,
     wiegand_empty_scene_on_exit, // data
     wiegand_empty_scene_on_exit, // data
     wiegand_empty_scene_on_exit, // save
     wiegand_empty_scene_on_exit, // save
     wiegand_empty_scene_on_exit, // load
     wiegand_empty_scene_on_exit, // load

+ 8 - 0
non_catalog_apps/wiegand/wiegand.h

@@ -1,6 +1,7 @@
 #pragma once
 #pragma once
 
 
 #include <furi.h>
 #include <furi.h>
+#include <furi_hal.h>
 #include <gui/gui.h>
 #include <gui/gui.h>
 #include <gui/view_dispatcher.h>
 #include <gui/view_dispatcher.h>
 #include <gui/scene_manager.h>
 #include <gui/scene_manager.h>
@@ -37,6 +38,7 @@ typedef enum {
     WiegandMainMenuScene,
     WiegandMainMenuScene,
     WiegandInstructionsScene,
     WiegandInstructionsScene,
     WiegandReadScene,
     WiegandReadScene,
+    WiegandScanScene,
     WiegandDataScene,
     WiegandDataScene,
     WiegandSaveScene,
     WiegandSaveScene,
     WiegandLoadScene,
     WiegandLoadScene,
@@ -64,6 +66,7 @@ typedef struct App {
 typedef enum {
 typedef enum {
     WiegandMainMenuInstructions,
     WiegandMainMenuInstructions,
     WiegandMainMenuRead,
     WiegandMainMenuRead,
+    WiegandMainMenuScan,
     WiegandMainMenuLoad,
     WiegandMainMenuLoad,
 } WiegandMainMenuSceneIndex;
 } WiegandMainMenuSceneIndex;
 
 
@@ -71,6 +74,7 @@ typedef enum {
     WiegandMainMenuUnknownEvent,
     WiegandMainMenuUnknownEvent,
     WiegandMainMenuInstructionsEvent,
     WiegandMainMenuInstructionsEvent,
     WiegandMainMenuReadEvent,
     WiegandMainMenuReadEvent,
+    WiegandMainMenuScanEvent,
     WiegandMainMenuLoadEvent,
     WiegandMainMenuLoadEvent,
 } WiegandMainMenuEvent;
 } WiegandMainMenuEvent;
 
 
@@ -119,6 +123,10 @@ void wiegand_load_scene_on_enter(void* context);
 bool wiegand_custom_callback(void* context, uint32_t custom_event);
 bool wiegand_custom_callback(void* context, uint32_t custom_event);
 bool wiegand_back_event_callback(void* context);
 bool wiegand_back_event_callback(void* context);
 
 
+void wiegand_scan_scene_on_enter(void* context);
+//bool wiegand_scan_scene_on_event(void* context, SceneManagerEvent event);
+void wiegand_scan_scene_on_exit(void* context);
+
 // Methods with no implementation.
 // Methods with no implementation.
 bool wiegand_empty_scene_on_event(void* context, SceneManagerEvent event);
 bool wiegand_empty_scene_on_event(void* context, SceneManagerEvent event);
 void wiegand_empty_scene_on_exit(void* _ctx);
 void wiegand_empty_scene_on_exit(void* _ctx);