Просмотр исходного кода

[FL-1345] IRDA monitor (#504)

* Irda Monitor: fix
Albert Kharisov 4 лет назад
Родитель
Сommit
5a993b6d2a

+ 126 - 28
applications/irda_monitor/irda_monitor.c

@@ -1,10 +1,15 @@
+#include "gui/canvas.h"
+#include "irda.h"
 #include <stdio.h>
 #include <furi.h>
 #include <api-hal-irda.h>
 #include <api-hal.h>
 #include <notification/notification-messages.h>
+#include <gui/view_port.h>
+#include <gui/gui.h>
+#include <gui/elements.h>
 
-#define IRDA_TIMINGS_SIZE 2000
+#define IRDA_TIMINGS_SIZE 700
 
 typedef struct {
     uint32_t timing_cnt;
@@ -14,53 +19,146 @@ typedef struct {
     } timing[IRDA_TIMINGS_SIZE];
 } IrdaDelaysArray;
 
+typedef struct {
+    IrdaHandler* handler;
+    char display_text[64];
+    osMessageQueueId_t event_queue;
+    IrdaDelaysArray delays;
+} IrdaMonitor;
+
 static void irda_rx_callback(void* ctx, bool level, uint32_t duration) {
-    IrdaDelaysArray* delays = ctx;
-
-    if(delays->timing_cnt < IRDA_TIMINGS_SIZE) {
-        if(delays->timing_cnt > 1)
-            furi_check(level != delays->timing[delays->timing_cnt - 1].level);
-        delays->timing[delays->timing_cnt].level = level;
-        delays->timing[delays->timing_cnt].duration = duration;
-        delays->timing_cnt++; // Read-Modify-Write in ISR only: no need to add synchronization
+    IrdaMonitor* irda_monitor = (IrdaMonitor*)ctx;
+    IrdaDelaysArray* delays = &irda_monitor->delays;
+
+    if(delays->timing_cnt > 1) furi_assert(level != delays->timing[delays->timing_cnt - 1].level);
+    delays->timing[delays->timing_cnt].level = level;
+    delays->timing[delays->timing_cnt].duration = duration;
+    delays->timing_cnt++; // Read-Modify-Write in ISR only: no need to add synchronization
+    if(delays->timing_cnt >= IRDA_TIMINGS_SIZE) {
+        delays->timing_cnt = 0;
+    }
+}
+
+void irda_monitor_input_callback(InputEvent* input_event, void* ctx) {
+    furi_assert(ctx);
+    IrdaMonitor* irda_monitor = (IrdaMonitor*)ctx;
+
+    if((input_event->type == InputTypeShort) && (input_event->key == InputKeyBack)) {
+        osMessageQueuePut(irda_monitor->event_queue, input_event, 0, 0);
+    }
+}
+
+static void irda_monitor_draw_callback(Canvas* canvas, void* ctx) {
+    furi_assert(canvas);
+    furi_assert(ctx);
+    IrdaMonitor* irda_monitor = (IrdaMonitor*)ctx;
+
+    canvas_clear(canvas);
+    canvas_set_font(canvas, FontPrimary);
+    elements_multiline_text_aligned(canvas, 64, 0, AlignCenter, AlignTop, "IRDA monitor\n");
+    canvas_set_font(canvas, FontKeyboard);
+    if(strlen(irda_monitor->display_text)) {
+        elements_multiline_text_aligned(
+            canvas, 64, 43, AlignCenter, AlignCenter, irda_monitor->display_text);
     }
 }
 
 int32_t irda_monitor_app(void* p) {
     (void)p;
-    static uint32_t counter = 0;
+    uint32_t counter = 0;
+    uint32_t print_counter = 0;
 
-    IrdaDelaysArray* delays = furi_alloc(sizeof(IrdaDelaysArray));
+    IrdaMonitor* irda_monitor = furi_alloc(sizeof(IrdaMonitor));
+    irda_monitor->display_text[0] = 0;
+    irda_monitor->event_queue = osMessageQueueNew(1, sizeof(InputEvent), NULL);
+    ViewPort* view_port = view_port_alloc();
+    IrdaDelaysArray* delays = &irda_monitor->delays;
     NotificationApp* notification = furi_record_open("notification");
+    Gui* gui = furi_record_open("gui");
+
+    view_port_draw_callback_set(view_port, irda_monitor_draw_callback, irda_monitor);
+    view_port_input_callback_set(view_port, irda_monitor_input_callback, irda_monitor);
+
+    gui_add_view_port(gui, view_port, GuiLayerFullscreen);
 
     api_hal_irda_rx_irq_init();
-    api_hal_irda_rx_irq_set_callback(irda_rx_callback, delays);
+    api_hal_irda_rx_irq_set_callback(irda_rx_callback, irda_monitor);
+    irda_monitor->handler = irda_alloc_decoder();
 
     while(1) {
-        delay(20);
+        InputEvent event;
+        if(osOK == osMessageQueueGet(irda_monitor->event_queue, &event, NULL, 50)) {
+            if((event.type == InputTypeShort) && (event.key == InputKeyBack)) {
+                break;
+            }
+        }
 
         if(counter != delays->timing_cnt) {
-            notification_message(notification, &sequence_blink_blue_100);
-
-            counter = delays->timing_cnt;
+            notification_message(notification, &sequence_blink_blue_10);
         }
 
-        if(delays->timing_cnt >= IRDA_TIMINGS_SIZE) {
-            api_hal_irda_rx_irq_deinit();
-            printf("== IRDA MONITOR FOUND (%d) records) ==\r\n", IRDA_TIMINGS_SIZE);
-            printf("{");
-            for(int i = 0; i < IRDA_TIMINGS_SIZE; ++i) {
-                printf(
-                    "%s%lu, ",
-                    (delays->timing[i].duration > 15000) ? "\r\n" : "",
-                    delays->timing[i].duration);
+        for(; counter != delays->timing_cnt;) {
+            const IrdaMessage* message = irda_decode(
+                irda_monitor->handler,
+                delays->timing[counter].level,
+                delays->timing[counter].duration);
+
+            ++counter;
+            if(counter >= IRDA_TIMINGS_SIZE) counter = 0;
+
+            if(message) {
+                snprintf(
+                    irda_monitor->display_text,
+                    sizeof(irda_monitor->display_text),
+                    "%s\nA:0x%02lX\nC:0x%02lX\n%s\n",
+                    irda_get_protocol_name(message->protocol),
+                    message->address,
+                    message->command,
+                    message->repeat ? " R" : "");
+                view_port_update(view_port);
+            }
+
+            size_t distance = (counter > print_counter) ?
+                                  counter - print_counter :
+                                  (counter + IRDA_TIMINGS_SIZE) - print_counter;
+            if(message || (distance > (IRDA_TIMINGS_SIZE / 2))) {
+                if(message) {
+                    printf(
+                        "== %s, A:0x%02lX, C:0x%02lX%s ==\r\n",
+                        irda_get_protocol_name(message->protocol),
+                        message->address,
+                        message->command,
+                        message->repeat ? " R" : "");
+                } else {
+                    printf("== unknown data ==\r\n");
+                    snprintf(
+                        irda_monitor->display_text,
+                        sizeof(irda_monitor->display_text),
+                        "unknown data");
+                    view_port_update(view_port);
+                }
+                printf("{");
+                while(print_counter != counter) {
+                    printf("%lu, ", delays->timing[print_counter].duration);
+                    ++print_counter;
+                    if(print_counter >= IRDA_TIMINGS_SIZE) {
+                        print_counter = 0;
+                    }
+                }
+                printf("\r\n};\r\n");
             }
-            printf("\r\n};\r\n");
-            break;
         }
     }
 
-    free(delays);
+    api_hal_irda_rx_irq_deinit();
+    irda_free_decoder(irda_monitor->handler);
+    osMessageQueueDelete(irda_monitor->event_queue);
+    view_port_enabled_set(view_port, false);
+    gui_remove_view_port(gui, view_port);
+    view_port_free(view_port);
+    furi_record_close("notification");
+    furi_record_close("gui");
+    free(irda_monitor);
 
     return 0;
 }

+ 7 - 1
applications/notification/notification-messages.c

@@ -225,6 +225,12 @@ const NotificationSequence sequence_set_blue_255 = {
 };
 
 // Blink
+const NotificationSequence sequence_blink_blue_10 = {
+    &message_blue_255,
+    &message_delay_10,
+    NULL,
+};
+
 const NotificationSequence sequence_blink_red_10 = {
     &message_red_255,
     &message_delay_10,
@@ -324,4 +330,4 @@ const NotificationSequence sequence_error = {
     &message_vibro_off,
     &message_sound_off,
     NULL,
-};
+};

+ 2 - 1
applications/notification/notification-messages.h

@@ -73,6 +73,7 @@ extern const NotificationSequence sequence_set_green_255;
 extern const NotificationSequence sequence_set_blue_255;
 
 // Blink
+extern const NotificationSequence sequence_blink_blue_10;
 extern const NotificationSequence sequence_blink_red_10;
 extern const NotificationSequence sequence_blink_green_10;
 extern const NotificationSequence sequence_blink_yellow_10;
@@ -91,4 +92,4 @@ extern const NotificationSequence sequence_error;
 
 #ifdef __cplusplus
 }
-#endif
+#endif