diff --git a/applications/irda_monitor/irda_monitor.c b/applications/irda_monitor/irda_monitor.c index 651f6368..40efd647 100644 --- a/applications/irda_monitor/irda_monitor.c +++ b/applications/irda_monitor/irda_monitor.c @@ -1,10 +1,15 @@ +#include "gui/canvas.h" +#include "irda.h" #include #include #include #include #include +#include +#include +#include -#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; -static void irda_rx_callback(void* ctx, bool level, uint32_t duration) { - IrdaDelaysArray* delays = ctx; +typedef struct { + IrdaHandler* handler; + char display_text[64]; + osMessageQueueId_t event_queue; + IrdaDelaysArray delays; +} IrdaMonitor; - 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 +static void irda_rx_callback(void* ctx, bool level, uint32_t duration) { + 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); - - if(counter != delays->timing_cnt) { - notification_message(notification, &sequence_blink_blue_100); - - counter = delays->timing_cnt; + InputEvent event; + if(osOK == osMessageQueueGet(irda_monitor->event_queue, &event, NULL, 50)) { + if((event.type == InputTypeShort) && (event.key == InputKeyBack)) { + break; + } } - 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); + if(counter != delays->timing_cnt) { + notification_message(notification, &sequence_blink_blue_10); + } + + 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; } diff --git a/applications/notification/notification-messages.c b/applications/notification/notification-messages.c index 74a585a5..b1dcceda 100644 --- a/applications/notification/notification-messages.c +++ b/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, -}; \ No newline at end of file +}; diff --git a/applications/notification/notification-messages.h b/applications/notification/notification-messages.h index c93d9589..ab5a9472 100644 --- a/applications/notification/notification-messages.h +++ b/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 \ No newline at end of file +#endif