[FL-1250, FL-1252, FL-1323, FL-1324] New IRDA Application (part 1) (#497)
* Add new IrdaApp (half ready), add ButtonMenu * Fix NEC's extension * clang-format * Fix leak * Add submenu optional header * IRDA: add Edit button * clang-format * IrdaApp: Fix scene flow * Add IRDA NEC extended protocol * IRDA: Add address/command length Co-authored-by: SG <who.just.the.doctor@gmail.com>
This commit is contained in:
		
							parent
							
								
									d040515f84
								
							
						
					
					
						commit
						31c31db479
					
				
							
								
								
									
										6
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,4 +1,10 @@ | |||||||
| *.swp | *.swp | ||||||
|  | *.gdb_history | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # LSP | ||||||
|  | .cache | ||||||
|  | compile_commands.json | ||||||
| 
 | 
 | ||||||
| # JetBrains IDEs | # JetBrains IDEs | ||||||
| .idea/ | .idea/ | ||||||
|  | |||||||
| @ -202,6 +202,19 @@ void canvas_draw_box(Canvas* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_ | |||||||
|     u8g2_DrawBox(&canvas->fb, x, y, width, height); |     u8g2_DrawBox(&canvas->fb, x, y, width, height); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void canvas_draw_rbox( | ||||||
|  |     Canvas* canvas, | ||||||
|  |     uint8_t x, | ||||||
|  |     uint8_t y, | ||||||
|  |     uint8_t width, | ||||||
|  |     uint8_t height, | ||||||
|  |     uint8_t radius) { | ||||||
|  |     furi_assert(canvas); | ||||||
|  |     x += canvas->offset_x; | ||||||
|  |     y += canvas->offset_y; | ||||||
|  |     u8g2_DrawRBox(&canvas->fb, x, y, width, height, radius); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void canvas_draw_frame(Canvas* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height) { | void canvas_draw_frame(Canvas* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height) { | ||||||
|     furi_assert(canvas); |     furi_assert(canvas); | ||||||
|     x += canvas->offset_x; |     x += canvas->offset_x; | ||||||
| @ -209,6 +222,19 @@ void canvas_draw_frame(Canvas* canvas, uint8_t x, uint8_t y, uint8_t width, uint | |||||||
|     u8g2_DrawFrame(&canvas->fb, x, y, width, height); |     u8g2_DrawFrame(&canvas->fb, x, y, width, height); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void canvas_draw_rframe( | ||||||
|  |     Canvas* canvas, | ||||||
|  |     uint8_t x, | ||||||
|  |     uint8_t y, | ||||||
|  |     uint8_t width, | ||||||
|  |     uint8_t height, | ||||||
|  |     uint8_t radius) { | ||||||
|  |     furi_assert(canvas); | ||||||
|  |     x += canvas->offset_x; | ||||||
|  |     y += canvas->offset_y; | ||||||
|  |     u8g2_DrawRFrame(&canvas->fb, x, y, width, height, radius); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void canvas_draw_line(Canvas* canvas, uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) { | void canvas_draw_line(Canvas* canvas, uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) { | ||||||
|     furi_assert(canvas); |     furi_assert(canvas); | ||||||
|     x1 += canvas->offset_x; |     x1 += canvas->offset_x; | ||||||
|  | |||||||
| @ -157,6 +157,28 @@ void canvas_draw_glyph(Canvas* canvas, uint8_t x, uint8_t y, uint16_t ch); | |||||||
|  */ |  */ | ||||||
| void canvas_set_bitmap_mode(Canvas* canvas, bool alpha); | void canvas_set_bitmap_mode(Canvas* canvas, bool alpha); | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * Draw rounded-corner frame of width, height at x,y, with round value raduis | ||||||
|  |  */ | ||||||
|  | void canvas_draw_rframe( | ||||||
|  |     Canvas* canvas, | ||||||
|  |     uint8_t x, | ||||||
|  |     uint8_t y, | ||||||
|  |     uint8_t width, | ||||||
|  |     uint8_t height, | ||||||
|  |     uint8_t radius); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Draw rounded-corner box of width, height at x,y, with round value raduis | ||||||
|  |  */ | ||||||
|  | void canvas_draw_rbox( | ||||||
|  |     Canvas* canvas, | ||||||
|  |     uint8_t x, | ||||||
|  |     uint8_t y, | ||||||
|  |     uint8_t width, | ||||||
|  |     uint8_t height, | ||||||
|  |     uint8_t radius); | ||||||
|  | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -1,6 +1,8 @@ | |||||||
| #include "elements.h" | #include "elements.h" | ||||||
|  | #include "gui/canvas.h" | ||||||
| #include <assets_icons.h> | #include <assets_icons.h> | ||||||
| #include <gui/icon_i.h> | #include <gui/icon_i.h> | ||||||
|  | #include <m-string.h> | ||||||
| #include <furi.h> | #include <furi.h> | ||||||
| #include "canvas_i.h" | #include "canvas_i.h" | ||||||
| #include <string.h> | #include <string.h> | ||||||
| @ -44,7 +46,7 @@ void elements_scrollbar(Canvas* canvas, uint8_t pos, uint8_t total) { | |||||||
|     } |     } | ||||||
|     // Position block
 |     // Position block
 | ||||||
|     if(total) { |     if(total) { | ||||||
|         uint8_t block_h = ((float)height) / total; |         float block_h = ((float)height) / total; | ||||||
|         canvas_draw_box(canvas, width - 3, block_h * pos, 3, MAX(block_h, 1)); |         canvas_draw_box(canvas, width - 3, block_h * pos, 3, MAX(block_h, 1)); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -249,13 +251,17 @@ void elements_slightly_rounded_frame( | |||||||
|     uint8_t width, |     uint8_t width, | ||||||
|     uint8_t height) { |     uint8_t height) { | ||||||
|     furi_assert(canvas); |     furi_assert(canvas); | ||||||
|     canvas_draw_frame(canvas, x, y, width, height); |     canvas_draw_rframe(canvas, x, y, width, height, 1); | ||||||
|     canvas_invert_color(canvas); | } | ||||||
|     canvas_draw_dot(canvas, x, y); | 
 | ||||||
|     canvas_draw_dot(canvas, x + width - 1, y + height - 1); | void elements_slightly_rounded_box( | ||||||
|     canvas_draw_dot(canvas, x + width - 1, y); |     Canvas* canvas, | ||||||
|     canvas_draw_dot(canvas, x, y + height - 1); |     uint8_t x, | ||||||
|     canvas_invert_color(canvas); |     uint8_t y, | ||||||
|  |     uint8_t width, | ||||||
|  |     uint8_t height) { | ||||||
|  |     furi_assert(canvas); | ||||||
|  |     canvas_draw_rbox(canvas, x, y, width, height, 1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void elements_string_fit_width(Canvas* canvas, string_t string, uint8_t width) { | void elements_string_fit_width(Canvas* canvas, string_t string, uint8_t width) { | ||||||
|  | |||||||
| @ -106,6 +106,18 @@ void elements_slightly_rounded_frame( | |||||||
|     uint8_t width, |     uint8_t width, | ||||||
|     uint8_t height); |     uint8_t height); | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * Draw slightly rounded box | ||||||
|  |  * @param x, y - top left corner coordinates | ||||||
|  |  * @param width, height - size of box | ||||||
|  |  */ | ||||||
|  | void elements_slightly_rounded_box( | ||||||
|  |     Canvas* canvas, | ||||||
|  |     uint8_t x, | ||||||
|  |     uint8_t y, | ||||||
|  |     uint8_t width, | ||||||
|  |     uint8_t height); | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Trim string buffer to fit width in pixels |  * Trim string buffer to fit width in pixels | ||||||
|  * @param string - string to trim |  * @param string - string to trim | ||||||
|  | |||||||
							
								
								
									
										288
									
								
								applications/gui/modules/button_menu.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										288
									
								
								applications/gui/modules/button_menu.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,288 @@ | |||||||
|  | #include "button_menu.h" | ||||||
|  | #include "gui/canvas.h" | ||||||
|  | #include "gui/elements.h" | ||||||
|  | #include <m-array.h> | ||||||
|  | #include <furi.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | 
 | ||||||
|  | #define ITEM_FIRST_OFFSET 17 | ||||||
|  | #define ITEM_NEXT_OFFSET 4 | ||||||
|  | #define ITEM_HEIGHT 14 | ||||||
|  | #define ITEM_WIDTH 64 | ||||||
|  | #define BUTTONS_PER_SCREEN 6 | ||||||
|  | 
 | ||||||
|  | struct ButtonMenuItem { | ||||||
|  |     const char* label; | ||||||
|  |     int32_t index; | ||||||
|  |     ButtonMenuItemCallback callback; | ||||||
|  |     ButtonMenuItemType type; | ||||||
|  |     void* callback_context; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | ARRAY_DEF(ButtonMenuItemArray, ButtonMenuItem, M_POD_OPLIST); | ||||||
|  | 
 | ||||||
|  | struct ButtonMenu { | ||||||
|  |     View* view; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  |     ButtonMenuItemArray_t items; | ||||||
|  |     uint8_t position; | ||||||
|  |     const char* header; | ||||||
|  | } ButtonMenuModel; | ||||||
|  | 
 | ||||||
|  | static void button_menu_draw_control_button( | ||||||
|  |     Canvas* canvas, | ||||||
|  |     uint8_t item_position, | ||||||
|  |     const char* text, | ||||||
|  |     bool selected) { | ||||||
|  |     furi_assert(canvas); | ||||||
|  |     furi_assert(text); | ||||||
|  | 
 | ||||||
|  |     uint8_t item_x = 0; | ||||||
|  |     uint8_t item_y = ITEM_FIRST_OFFSET + (item_position * (ITEM_HEIGHT + ITEM_NEXT_OFFSET)); | ||||||
|  | 
 | ||||||
|  |     canvas_set_color(canvas, ColorBlack); | ||||||
|  | 
 | ||||||
|  |     if(selected) { | ||||||
|  |         elements_slightly_rounded_box(canvas, item_x, item_y, ITEM_WIDTH, ITEM_HEIGHT); | ||||||
|  |         canvas_set_color(canvas, ColorWhite); | ||||||
|  |     } | ||||||
|  |     canvas_draw_str_aligned( | ||||||
|  |         canvas, | ||||||
|  |         item_x + (ITEM_WIDTH / 2), | ||||||
|  |         item_y + (ITEM_HEIGHT / 2), | ||||||
|  |         AlignCenter, | ||||||
|  |         AlignCenter, | ||||||
|  |         text); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void button_menu_draw_common_button( | ||||||
|  |     Canvas* canvas, | ||||||
|  |     uint8_t item_position, | ||||||
|  |     const char* text, | ||||||
|  |     bool selected) { | ||||||
|  |     furi_assert(canvas); | ||||||
|  |     furi_assert(text); | ||||||
|  | 
 | ||||||
|  |     uint8_t item_x = 0; | ||||||
|  |     uint8_t item_y = ITEM_FIRST_OFFSET + (item_position * (ITEM_HEIGHT + ITEM_NEXT_OFFSET)); | ||||||
|  | 
 | ||||||
|  |     canvas_set_color(canvas, ColorBlack); | ||||||
|  | 
 | ||||||
|  |     if(selected) { | ||||||
|  |         canvas_draw_rbox(canvas, item_x, item_y, ITEM_WIDTH, ITEM_HEIGHT, 5); | ||||||
|  |         canvas_set_color(canvas, ColorWhite); | ||||||
|  |     } else { | ||||||
|  |         canvas_draw_rframe(canvas, item_x, item_y, ITEM_WIDTH, ITEM_HEIGHT, 5); | ||||||
|  |     } | ||||||
|  |     canvas_draw_str_aligned( | ||||||
|  |         canvas, | ||||||
|  |         item_x + (ITEM_WIDTH / 2), | ||||||
|  |         item_y + (ITEM_HEIGHT / 2), | ||||||
|  |         AlignCenter, | ||||||
|  |         AlignCenter, | ||||||
|  |         text); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void button_menu_view_draw_callback(Canvas* canvas, void* _model) { | ||||||
|  |     furi_assert(canvas); | ||||||
|  |     furi_assert(_model); | ||||||
|  | 
 | ||||||
|  |     ButtonMenuModel* model = (ButtonMenuModel*)_model; | ||||||
|  | 
 | ||||||
|  |     canvas_clear(canvas); | ||||||
|  |     canvas_set_font(canvas, FontSecondary); | ||||||
|  | 
 | ||||||
|  |     uint8_t item_position = 0; | ||||||
|  |     int8_t active_screen = model->position / BUTTONS_PER_SCREEN; | ||||||
|  |     size_t items_size = ButtonMenuItemArray_size(model->items); | ||||||
|  |     int8_t max_screen = ((int16_t)items_size - 1) / BUTTONS_PER_SCREEN; | ||||||
|  |     ButtonMenuItemArray_it_t it; | ||||||
|  | 
 | ||||||
|  |     if(active_screen > 0) { | ||||||
|  |         canvas_draw_icon_name(canvas, 28, 1, I_IrdaArrowUp_4x8); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if(max_screen > active_screen) { | ||||||
|  |         canvas_draw_icon_name(canvas, 28, 123, I_IrdaArrowDown_4x8); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     canvas_draw_str_aligned(canvas, 32, 10, AlignCenter, AlignCenter, model->header); | ||||||
|  | 
 | ||||||
|  |     for(ButtonMenuItemArray_it(it, model->items); !ButtonMenuItemArray_end_p(it); | ||||||
|  |         ButtonMenuItemArray_next(it), ++item_position) { | ||||||
|  |         if(active_screen == (item_position / BUTTONS_PER_SCREEN)) { | ||||||
|  |             if(ButtonMenuItemArray_cref(it)->type == ButtonMenuItemTypeControl) { | ||||||
|  |                 button_menu_draw_control_button( | ||||||
|  |                     canvas, | ||||||
|  |                     item_position % BUTTONS_PER_SCREEN, | ||||||
|  |                     ButtonMenuItemArray_cref(it)->label, | ||||||
|  |                     (item_position == model->position)); | ||||||
|  |             } else if(ButtonMenuItemArray_cref(it)->type == ButtonMenuItemTypeCommon) { | ||||||
|  |                 button_menu_draw_common_button( | ||||||
|  |                     canvas, | ||||||
|  |                     item_position % BUTTONS_PER_SCREEN, | ||||||
|  |                     ButtonMenuItemArray_cref(it)->label, | ||||||
|  |                     (item_position == model->position)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void button_menu_process_up(ButtonMenu* button_menu) { | ||||||
|  |     furi_assert(button_menu); | ||||||
|  | 
 | ||||||
|  |     with_view_model( | ||||||
|  |         button_menu->view, (ButtonMenuModel * model) { | ||||||
|  |             if(model->position > 0) { | ||||||
|  |                 model->position--; | ||||||
|  |             } else { | ||||||
|  |                 model->position = ButtonMenuItemArray_size(model->items) - 1; | ||||||
|  |             } | ||||||
|  |             return true; | ||||||
|  |         }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void button_menu_process_down(ButtonMenu* button_menu) { | ||||||
|  |     furi_assert(button_menu); | ||||||
|  | 
 | ||||||
|  |     with_view_model( | ||||||
|  |         button_menu->view, (ButtonMenuModel * model) { | ||||||
|  |             if(model->position < (ButtonMenuItemArray_size(model->items) - 1)) { | ||||||
|  |                 model->position++; | ||||||
|  |             } else { | ||||||
|  |                 model->position = 0; | ||||||
|  |             } | ||||||
|  |             return true; | ||||||
|  |         }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void button_menu_process_ok(ButtonMenu* button_menu) { | ||||||
|  |     furi_assert(button_menu); | ||||||
|  | 
 | ||||||
|  |     ButtonMenuItem* item = NULL; | ||||||
|  | 
 | ||||||
|  |     with_view_model( | ||||||
|  |         button_menu->view, (ButtonMenuModel * model) { | ||||||
|  |             if(model->position < (ButtonMenuItemArray_size(model->items))) { | ||||||
|  |                 item = ButtonMenuItemArray_get(model->items, model->position); | ||||||
|  |             } | ||||||
|  |             return true; | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |     if(item && item->callback) { | ||||||
|  |         item->callback(item->callback_context, item->index); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static bool button_menu_view_input_callback(InputEvent* event, void* context) { | ||||||
|  |     furi_assert(event); | ||||||
|  | 
 | ||||||
|  |     ButtonMenu* button_menu = context; | ||||||
|  |     bool consumed = false; | ||||||
|  | 
 | ||||||
|  |     if(event->type == InputTypeShort) { | ||||||
|  |         switch(event->key) { | ||||||
|  |         case InputKeyUp: | ||||||
|  |             consumed = true; | ||||||
|  |             button_menu_process_up(button_menu); | ||||||
|  |             break; | ||||||
|  |         case InputKeyDown: | ||||||
|  |             consumed = true; | ||||||
|  |             button_menu_process_down(button_menu); | ||||||
|  |             break; | ||||||
|  |         case InputKeyOk: | ||||||
|  |             consumed = true; | ||||||
|  |             button_menu_process_ok(button_menu); | ||||||
|  |             break; | ||||||
|  |         default: | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return consumed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | View* button_menu_get_view(ButtonMenu* button_menu) { | ||||||
|  |     furi_assert(button_menu); | ||||||
|  |     return button_menu->view; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void button_menu_clean(ButtonMenu* button_menu) { | ||||||
|  |     furi_assert(button_menu); | ||||||
|  | 
 | ||||||
|  |     with_view_model( | ||||||
|  |         button_menu->view, (ButtonMenuModel * model) { | ||||||
|  |             ButtonMenuItemArray_clean(model->items); | ||||||
|  |             model->position = 0; | ||||||
|  |             return true; | ||||||
|  |         }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void button_menu_set_header(ButtonMenu* button_menu, const char* header) { | ||||||
|  |     furi_assert(button_menu); | ||||||
|  | 
 | ||||||
|  |     with_view_model( | ||||||
|  |         button_menu->view, (ButtonMenuModel * model) { | ||||||
|  |             model->header = header; | ||||||
|  |             return true; | ||||||
|  |         }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ButtonMenuItem* button_menu_add_item( | ||||||
|  |     ButtonMenu* button_menu, | ||||||
|  |     const char* label, | ||||||
|  |     int32_t index, | ||||||
|  |     ButtonMenuItemCallback callback, | ||||||
|  |     ButtonMenuItemType type, | ||||||
|  |     void* callback_context) { | ||||||
|  |     ButtonMenuItem* item = NULL; | ||||||
|  |     furi_assert(label); | ||||||
|  |     furi_assert(button_menu); | ||||||
|  | 
 | ||||||
|  |     with_view_model( | ||||||
|  |         button_menu->view, (ButtonMenuModel * model) { | ||||||
|  |             item = ButtonMenuItemArray_push_new(model->items); | ||||||
|  |             item->label = label; | ||||||
|  |             item->index = index; | ||||||
|  |             item->type = type; | ||||||
|  |             item->callback = callback; | ||||||
|  |             item->callback_context = callback_context; | ||||||
|  |             return true; | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |     return item; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ButtonMenu* button_menu_alloc(void) { | ||||||
|  |     ButtonMenu* button_menu = furi_alloc(sizeof(ButtonMenu)); | ||||||
|  |     button_menu->view = view_alloc(); | ||||||
|  |     view_set_orientation(button_menu->view, ViewOrientationVertical); | ||||||
|  |     view_set_context(button_menu->view, button_menu); | ||||||
|  |     view_allocate_model(button_menu->view, ViewModelTypeLocking, sizeof(ButtonMenuModel)); | ||||||
|  |     view_set_draw_callback(button_menu->view, button_menu_view_draw_callback); | ||||||
|  |     view_set_input_callback(button_menu->view, button_menu_view_input_callback); | ||||||
|  | 
 | ||||||
|  |     with_view_model( | ||||||
|  |         button_menu->view, (ButtonMenuModel * model) { | ||||||
|  |             ButtonMenuItemArray_init(model->items); | ||||||
|  |             model->position = 0; | ||||||
|  |             model->header = NULL; | ||||||
|  |             return true; | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |     return button_menu; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void button_menu_free(ButtonMenu* button_menu) { | ||||||
|  |     furi_assert(button_menu); | ||||||
|  | 
 | ||||||
|  |     with_view_model( | ||||||
|  |         button_menu->view, (ButtonMenuModel * model) { | ||||||
|  |             ButtonMenuItemArray_clear(model->items); | ||||||
|  |             return true; | ||||||
|  |         }); | ||||||
|  |     view_free(button_menu->view); | ||||||
|  |     free(button_menu); | ||||||
|  | } | ||||||
							
								
								
									
										73
									
								
								applications/gui/modules/button_menu.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								applications/gui/modules/button_menu.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,73 @@ | |||||||
|  | #pragma once | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <gui/view.h> | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | /* ButtonMenu anonymous structure */ | ||||||
|  | typedef struct ButtonMenu ButtonMenu; | ||||||
|  | typedef struct ButtonMenuItem ButtonMenuItem; | ||||||
|  | 
 | ||||||
|  | /* Callback for any button menu actions */ | ||||||
|  | typedef void (*ButtonMenuItemCallback)(void* context, int32_t index); | ||||||
|  | 
 | ||||||
|  | /* Type of button. Difference in drawing buttons. */ | ||||||
|  | typedef enum { | ||||||
|  |     ButtonMenuItemTypeCommon, | ||||||
|  |     ButtonMenuItemTypeControl, | ||||||
|  | } ButtonMenuItemType; | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief Get button menu view | ||||||
|  |  * @param button_menu - ButtonMenu instance | ||||||
|  |  * @return View instance that can be used for embedding | ||||||
|  |  */ | ||||||
|  | View* button_menu_get_view(ButtonMenu* button_menu); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief Clean button menu | ||||||
|  |  * @param button_menu - ButtonMenu instance | ||||||
|  |  */ | ||||||
|  | void button_menu_clean(ButtonMenu* button_menu); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief Add item to button menu instance | ||||||
|  |  * @param button_menu   - ButtonMenu instance | ||||||
|  |  * @param label         - text inside new button | ||||||
|  |  * @param index         - value to distinct between buttons inside ButtonMenuItemCallback | ||||||
|  |  * @param type          - type of button to create. Differ by button drawing. | ||||||
|  |  *                      Control buttons have no frames, and have more squared borders. | ||||||
|  |  * @return              pointer to just-created item | ||||||
|  |  */ | ||||||
|  | ButtonMenuItem* button_menu_add_item( | ||||||
|  |     ButtonMenu* button_menu, | ||||||
|  |     const char* label, | ||||||
|  |     int32_t index, | ||||||
|  |     ButtonMenuItemCallback callback, | ||||||
|  |     ButtonMenuItemType type, | ||||||
|  |     void* callback_context); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief Allocate and initialize new instance of ButtonMenu model | ||||||
|  |  * @return          just-created ButtonMenu model | ||||||
|  |  */ | ||||||
|  | ButtonMenu* button_menu_alloc(void); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief Free ButtonMenu element | ||||||
|  |  * @param button_menu - ButtonMenu instance | ||||||
|  |  */ | ||||||
|  | void button_menu_free(ButtonMenu* button_menu); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief Set ButtonMenu header on top of canvas | ||||||
|  |  * @param button_menu   - ButtonMenu instance | ||||||
|  |  * @param header        - header on the top of button menu | ||||||
|  |  */ | ||||||
|  | void button_menu_set_header(ButtonMenu* button_menu, const char* header); | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
| @ -1,7 +1,9 @@ | |||||||
| #include "submenu.h" | #include "submenu.h" | ||||||
|  | #include "gui/canvas.h" | ||||||
| #include <m-array.h> | #include <m-array.h> | ||||||
| #include <furi.h> | #include <furi.h> | ||||||
| #include <gui/elements.h> | #include <gui/elements.h> | ||||||
|  | #include <stdint.h> | ||||||
| 
 | 
 | ||||||
| struct SubmenuItem { | struct SubmenuItem { | ||||||
|     const char* label; |     const char* label; | ||||||
| @ -18,6 +20,7 @@ struct Submenu { | |||||||
| 
 | 
 | ||||||
| typedef struct { | typedef struct { | ||||||
|     SubmenuItemArray_t items; |     SubmenuItemArray_t items; | ||||||
|  |     const char* header; | ||||||
|     uint8_t position; |     uint8_t position; | ||||||
|     uint8_t window_position; |     uint8_t window_position; | ||||||
| } SubmenuModel; | } SubmenuModel; | ||||||
| @ -33,34 +36,39 @@ static void submenu_view_draw_callback(Canvas* canvas, void* _model) { | |||||||
|     const uint8_t item_width = 123; |     const uint8_t item_width = 123; | ||||||
| 
 | 
 | ||||||
|     canvas_clear(canvas); |     canvas_clear(canvas); | ||||||
|     canvas_set_font(canvas, FontSecondary); |     canvas_set_font(canvas, FontPrimary); | ||||||
| 
 | 
 | ||||||
|     uint8_t position = 0; |     uint8_t position = 0; | ||||||
|     SubmenuItemArray_it_t it; |     SubmenuItemArray_it_t it; | ||||||
| 
 | 
 | ||||||
|  |     if(model->header) { | ||||||
|  |         canvas_draw_str(canvas, 4, 11, model->header); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     canvas_set_font(canvas, FontSecondary); | ||||||
|     for(SubmenuItemArray_it(it, model->items); !SubmenuItemArray_end_p(it); |     for(SubmenuItemArray_it(it, model->items); !SubmenuItemArray_end_p(it); | ||||||
|         SubmenuItemArray_next(it)) { |         SubmenuItemArray_next(it)) { | ||||||
|         uint8_t item_position = position - model->window_position; |         uint8_t item_position = position - model->window_position; | ||||||
|  |         uint8_t elements_on_screen = model->header ? 3 : 4; | ||||||
|  |         uint8_t y_offset = model->header ? 16 : 0; | ||||||
| 
 | 
 | ||||||
|         if(item_position < 4) { |         if(item_position < elements_on_screen) { | ||||||
|             if(position == model->position) { |             if(position == model->position) { | ||||||
|                 canvas_set_color(canvas, ColorBlack); |                 canvas_set_color(canvas, ColorBlack); | ||||||
|                 canvas_draw_box( |                 elements_slightly_rounded_box( | ||||||
|                     canvas, 0, (item_position * item_height) + 1, item_width, item_height - 2); |                     canvas, | ||||||
|  |                     0, | ||||||
|  |                     y_offset + (item_position * item_height) + 1, | ||||||
|  |                     item_width, | ||||||
|  |                     item_height - 2); | ||||||
|                 canvas_set_color(canvas, ColorWhite); |                 canvas_set_color(canvas, ColorWhite); | ||||||
| 
 |  | ||||||
|                 canvas_draw_dot(canvas, 0, (item_position * item_height) + 1); |  | ||||||
|                 canvas_draw_dot(canvas, 0, (item_position * item_height) + item_height - 2); |  | ||||||
|                 canvas_draw_dot(canvas, item_width - 1, (item_position * item_height) + 1); |  | ||||||
|                 canvas_draw_dot( |  | ||||||
|                     canvas, item_width - 1, (item_position * item_height) + item_height - 2); |  | ||||||
|             } else { |             } else { | ||||||
|                 canvas_set_color(canvas, ColorBlack); |                 canvas_set_color(canvas, ColorBlack); | ||||||
|             } |             } | ||||||
|             canvas_draw_str( |             canvas_draw_str( | ||||||
|                 canvas, |                 canvas, | ||||||
|                 6, |                 6, | ||||||
|                 (item_position * item_height) + item_height - 4, |                 y_offset + (item_position * item_height) + item_height - 4, | ||||||
|                 SubmenuItemArray_cref(it)->label); |                 SubmenuItemArray_cref(it)->label); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -110,6 +118,7 @@ Submenu* submenu_alloc() { | |||||||
|             SubmenuItemArray_init(model->items); |             SubmenuItemArray_init(model->items); | ||||||
|             model->position = 0; |             model->position = 0; | ||||||
|             model->window_position = 0; |             model->window_position = 0; | ||||||
|  |             model->header = NULL; | ||||||
|             return true; |             return true; | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
| @ -164,6 +173,7 @@ void submenu_clean(Submenu* submenu) { | |||||||
|             SubmenuItemArray_clean(model->items); |             SubmenuItemArray_clean(model->items); | ||||||
|             model->position = 0; |             model->position = 0; | ||||||
|             model->window_position = 0; |             model->window_position = 0; | ||||||
|  |             model->header = NULL; | ||||||
|             return true; |             return true; | ||||||
|         }); |         }); | ||||||
| } | } | ||||||
| @ -207,15 +217,17 @@ void submenu_set_selected_item(Submenu* submenu, uint32_t index) { | |||||||
| void submenu_process_up(Submenu* submenu) { | void submenu_process_up(Submenu* submenu) { | ||||||
|     with_view_model( |     with_view_model( | ||||||
|         submenu->view, (SubmenuModel * model) { |         submenu->view, (SubmenuModel * model) { | ||||||
|  |             uint8_t elements_on_screen = model->header ? 3 : 4; | ||||||
|             if(model->position > 0) { |             if(model->position > 0) { | ||||||
|                 model->position--; |                 model->position--; | ||||||
|                 if((model->position - model->window_position) < 1 && model->window_position > 0) { |                 if(((model->position - model->window_position) < 1) && | ||||||
|  |                    model->window_position > 0) { | ||||||
|                     model->window_position--; |                     model->window_position--; | ||||||
|                 } |                 } | ||||||
|             } else { |             } else { | ||||||
|                 model->position = SubmenuItemArray_size(model->items) - 1; |                 model->position = SubmenuItemArray_size(model->items) - 1; | ||||||
|                 if(model->position > 3) { |                 if(model->position > (elements_on_screen - 1)) { | ||||||
|                     model->window_position = model->position - 3; |                     model->window_position = model->position - (elements_on_screen - 1); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             return true; |             return true; | ||||||
| @ -225,10 +237,12 @@ void submenu_process_up(Submenu* submenu) { | |||||||
| void submenu_process_down(Submenu* submenu) { | void submenu_process_down(Submenu* submenu) { | ||||||
|     with_view_model( |     with_view_model( | ||||||
|         submenu->view, (SubmenuModel * model) { |         submenu->view, (SubmenuModel * model) { | ||||||
|  |             uint8_t elements_on_screen = model->header ? 3 : 4; | ||||||
|             if(model->position < (SubmenuItemArray_size(model->items) - 1)) { |             if(model->position < (SubmenuItemArray_size(model->items) - 1)) { | ||||||
|                 model->position++; |                 model->position++; | ||||||
|                 if((model->position - model->window_position) > 2 && |                 if((model->position - model->window_position) > (elements_on_screen - 2) && | ||||||
|                    model->window_position < (SubmenuItemArray_size(model->items) - 4)) { |                    model->window_position < | ||||||
|  |                        (SubmenuItemArray_size(model->items) - elements_on_screen)) { | ||||||
|                     model->window_position++; |                     model->window_position++; | ||||||
|                 } |                 } | ||||||
|             } else { |             } else { | ||||||
| @ -254,3 +268,13 @@ void submenu_process_ok(Submenu* submenu) { | |||||||
|         item->callback(item->callback_context, item->index); |         item->callback(item->callback_context, item->index); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | void submenu_set_header(Submenu* submenu, const char* header) { | ||||||
|  |     furi_assert(submenu); | ||||||
|  | 
 | ||||||
|  |     with_view_model( | ||||||
|  |         submenu->view, (SubmenuModel * model) { | ||||||
|  |             model->header = header; | ||||||
|  |             return true; | ||||||
|  |         }); | ||||||
|  | } | ||||||
|  | |||||||
| @ -16,12 +16,6 @@ typedef void (*SubmenuItemCallback)(void* context, uint32_t index); | |||||||
|  */ |  */ | ||||||
| Submenu* submenu_alloc(); | Submenu* submenu_alloc(); | ||||||
| 
 | 
 | ||||||
| /**
 |  | ||||||
|  * @brief Allocate and initialize submenu for vertical display |  | ||||||
|  * This submenu is used to select one option |  | ||||||
|  */ |  | ||||||
| Submenu* submenu_vertical_alloc(); |  | ||||||
| 
 |  | ||||||
| /**
 | /**
 | ||||||
|  * @brief Deinitialize and free submenu |  * @brief Deinitialize and free submenu | ||||||
|  * @param submenu - Submenu instance |  * @param submenu - Submenu instance | ||||||
| @ -64,6 +58,13 @@ void submenu_clean(Submenu* submenu); | |||||||
|  */ |  */ | ||||||
| void submenu_set_selected_item(Submenu* submenu, uint32_t index); | void submenu_set_selected_item(Submenu* submenu, uint32_t index); | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief Set optional header for submenu | ||||||
|  |  * @param submenu   - submenu entity | ||||||
|  |  * @param header    - header to set | ||||||
|  |  */ | ||||||
|  | void submenu_set_header(Submenu* submenu, const char* header); | ||||||
|  | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  | |||||||
							
								
								
									
										26
									
								
								applications/irda/irda-app-event.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								applications/irda/irda-app-event.hpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | |||||||
|  | #pragma once | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <irda.h> | ||||||
|  | #include <gui/modules/dialog_ex.h> | ||||||
|  | 
 | ||||||
|  | class IrdaAppEvent { | ||||||
|  | public: | ||||||
|  |     enum class Type : uint8_t { | ||||||
|  |         Tick, | ||||||
|  |         Back, | ||||||
|  |         MenuSelected, | ||||||
|  |         DialogExSelected, | ||||||
|  |         NextScene, | ||||||
|  |         IrdaMessageReceived, | ||||||
|  |         TextEditDone, | ||||||
|  |         PopupTimer, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     union { | ||||||
|  |         int32_t menu_index; | ||||||
|  |         DialogExResult dialog_ex_result; | ||||||
|  |     } payload; | ||||||
|  | 
 | ||||||
|  |     Type type; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
							
								
								
									
										46
									
								
								applications/irda/irda-app-receiver.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								applications/irda/irda-app-receiver.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,46 @@ | |||||||
|  | #include "irda-app.hpp" | ||||||
|  | #include "irda.h" | ||||||
|  | #include <api-hal-irda.h> | ||||||
|  | 
 | ||||||
|  | void IrdaAppSignalReceiver::irda_rx_callback(void* ctx, bool level, uint32_t duration) { | ||||||
|  |     IrdaAppEvent event; | ||||||
|  |     const IrdaMessage* irda_message; | ||||||
|  |     IrdaAppSignalReceiver* this_ = static_cast<IrdaAppSignalReceiver*>(ctx); | ||||||
|  | 
 | ||||||
|  |     irda_message = irda_decode(this_->decoder, level, duration); | ||||||
|  |     if(irda_message) { | ||||||
|  |         this_->capture_stop(); | ||||||
|  |         this_->message = *irda_message; | ||||||
|  |         event.type = IrdaAppEvent::Type::IrdaMessageReceived; | ||||||
|  |         osStatus_t result = osMessageQueuePut(this_->event_queue, &event, 0, 0); | ||||||
|  |         furi_check(result == osOK); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | IrdaAppSignalReceiver::IrdaAppSignalReceiver(void) | ||||||
|  |     : decoder(irda_alloc_decoder()) { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | IrdaAppSignalReceiver::~IrdaAppSignalReceiver() { | ||||||
|  |     api_hal_irda_rx_irq_deinit(); | ||||||
|  |     irda_free_decoder(decoder); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppSignalReceiver::capture_once_start(osMessageQueueId_t queue) { | ||||||
|  |     event_queue = queue; | ||||||
|  |     irda_reset_decoder(decoder); | ||||||
|  |     api_hal_irda_rx_irq_init(); | ||||||
|  |     api_hal_irda_rx_irq_set_callback(IrdaAppSignalReceiver::irda_rx_callback, this); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppSignalReceiver::capture_stop(void) { | ||||||
|  |     api_hal_irda_rx_irq_deinit(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | IrdaMessage* IrdaAppSignalReceiver::get_last_message(void) { | ||||||
|  |     return &message; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppSignalReceiver::send_message(const IrdaMessage* message) { | ||||||
|  |     irda_send(message, 1); | ||||||
|  | } | ||||||
							
								
								
									
										19
									
								
								applications/irda/irda-app-receiver.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								applications/irda/irda-app-receiver.hpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | #include <furi.h> | ||||||
|  | #include <irda.h> | ||||||
|  | 
 | ||||||
|  | class IrdaAppSignalReceiver { | ||||||
|  | public: | ||||||
|  |     IrdaAppSignalReceiver(void); | ||||||
|  |     ~IrdaAppSignalReceiver(void); | ||||||
|  |     void capture_once_start(osMessageQueueId_t event_queue); | ||||||
|  |     void capture_stop(void); | ||||||
|  |     IrdaMessage* get_last_message(void); | ||||||
|  |     void send_message(const IrdaMessage* message); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     osMessageQueueId_t event_queue; | ||||||
|  |     static void irda_rx_callback(void* ctx, bool level, uint32_t duration); | ||||||
|  |     IrdaHandler* decoder; | ||||||
|  |     IrdaMessage message; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
							
								
								
									
										130
									
								
								applications/irda/irda-app-remote-manager.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								applications/irda/irda-app-remote-manager.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,130 @@ | |||||||
|  | #include "irda-app-remote-manager.hpp" | ||||||
|  | #include "furi.h" | ||||||
|  | #include <string> | ||||||
|  | #include <utility> | ||||||
|  | 
 | ||||||
|  | IrdaAppRemoteManager::IrdaAppRemoteManager() { | ||||||
|  |     // Read from api-hal-storage, and fill remotes
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static const std::string default_remote_name = "remote"; | ||||||
|  | 
 | ||||||
|  | void IrdaAppRemoteManager::add_button(const char* button_name, const IrdaMessage* message) { | ||||||
|  |     remotes[current_remote_index].buttons.emplace_back(button_name, message); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppRemoteManager::add_remote_with_button( | ||||||
|  |     const char* button_name, | ||||||
|  |     const IrdaMessage* message) { | ||||||
|  |     bool found = true; | ||||||
|  |     int i = 0; | ||||||
|  | 
 | ||||||
|  |     // find first free common name for remote
 | ||||||
|  |     do { | ||||||
|  |         found = false; | ||||||
|  |         ++i; | ||||||
|  |         for(const auto& it : remotes) { | ||||||
|  |             if(it.name == (default_remote_name + std::to_string(i))) { | ||||||
|  |                 found = true; | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } while(found); | ||||||
|  | 
 | ||||||
|  |     remotes.emplace_back(default_remote_name + std::to_string(i)); | ||||||
|  |     current_remote_index = remotes.size() - 1; | ||||||
|  |     add_button(button_name, message); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | IrdaAppRemote::IrdaAppRemote(std::string name) | ||||||
|  |     : name(name) { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::vector<std::string> IrdaAppRemoteManager::get_button_list(void) const { | ||||||
|  |     std::vector<std::string> name_vector; | ||||||
|  |     auto remote = remotes[current_remote_index]; | ||||||
|  |     name_vector.reserve(remote.buttons.size()); | ||||||
|  | 
 | ||||||
|  |     for(const auto& it : remote.buttons) { | ||||||
|  |         name_vector.emplace_back(it.name); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // copy elision
 | ||||||
|  |     return name_vector; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::vector<std::string> IrdaAppRemoteManager::get_remote_list() const { | ||||||
|  |     std::vector<std::string> name_vector; | ||||||
|  |     name_vector.reserve(remotes.size()); | ||||||
|  | 
 | ||||||
|  |     for(const auto& it : remotes) { | ||||||
|  |         name_vector.push_back(it.name); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // copy elision
 | ||||||
|  |     return name_vector; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | size_t IrdaAppRemoteManager::get_current_remote(void) const { | ||||||
|  |     return current_remote_index; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | size_t IrdaAppRemoteManager::get_current_button(void) const { | ||||||
|  |     return current_button_index; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppRemote::add_button( | ||||||
|  |     size_t remote_index, | ||||||
|  |     const char* button_name, | ||||||
|  |     const IrdaMessage* message) { | ||||||
|  |     buttons.emplace_back(button_name, message); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const IrdaMessage* IrdaAppRemoteManager::get_button_data(size_t button_index) const { | ||||||
|  |     furi_check(remotes[current_remote_index].buttons.size() > button_index); | ||||||
|  |     auto& b = remotes[current_remote_index].buttons.at(button_index); | ||||||
|  |     return &b.message; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppRemoteManager::set_current_remote(size_t index) { | ||||||
|  |     furi_check(index < remotes.size()); | ||||||
|  |     current_remote_index = index; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppRemoteManager::set_current_button(size_t index) { | ||||||
|  |     furi_check(current_remote_index < remotes.size()); | ||||||
|  |     furi_check(index < remotes[current_remote_index].buttons.size()); | ||||||
|  |     current_button_index = index; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppRemoteManager::delete_current_remote() { | ||||||
|  |     remotes.erase(remotes.begin() + current_remote_index); | ||||||
|  |     current_remote_index = 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppRemoteManager::delete_current_button() { | ||||||
|  |     auto& buttons = remotes[current_remote_index].buttons; | ||||||
|  |     buttons.erase(buttons.begin() + current_button_index); | ||||||
|  |     current_button_index = 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::string IrdaAppRemoteManager::get_current_button_name() { | ||||||
|  |     auto buttons = remotes[current_remote_index].buttons; | ||||||
|  |     return buttons[current_button_index].name; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::string IrdaAppRemoteManager::get_current_remote_name() { | ||||||
|  |     return remotes[current_remote_index].name; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppRemoteManager::rename_remote(const char* str) { | ||||||
|  |     remotes[current_remote_index].name = str; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppRemoteManager::rename_button(const char* str) { | ||||||
|  |     remotes[current_remote_index].buttons[current_button_index].name = str; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | size_t IrdaAppRemoteManager::get_current_remote_buttons_number() { | ||||||
|  |     return remotes[current_remote_index].buttons.size(); | ||||||
|  | } | ||||||
							
								
								
									
										53
									
								
								applications/irda/irda-app-remote-manager.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								applications/irda/irda-app-remote-manager.hpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,53 @@ | |||||||
|  | #pragma once | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <string> | ||||||
|  | #include <list> | ||||||
|  | #include <vector> | ||||||
|  | #include <irda.h> | ||||||
|  | 
 | ||||||
|  | class IrdaAppRemoteButton { | ||||||
|  |     friend class IrdaAppRemoteManager; | ||||||
|  |     std::string name; | ||||||
|  |     IrdaMessage message; | ||||||
|  | public: | ||||||
|  |     IrdaAppRemoteButton(const char* name, const IrdaMessage* message) | ||||||
|  |         : name(name), message (*message) {} | ||||||
|  |     ~IrdaAppRemoteButton() {} | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class IrdaAppRemote { | ||||||
|  |     friend class IrdaAppRemoteManager; | ||||||
|  |     std::vector<IrdaAppRemoteButton> buttons; | ||||||
|  |     std::string name; | ||||||
|  |     bool add(const IrdaMessage*); | ||||||
|  |     void add_button(size_t remote_index, const char* button_name, const IrdaMessage* message); | ||||||
|  | public: | ||||||
|  |     IrdaAppRemote(std::string name); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class IrdaAppRemoteManager { | ||||||
|  |     size_t current_remote_index; | ||||||
|  |     size_t current_button_index; | ||||||
|  |     std::vector<IrdaAppRemote> remotes; | ||||||
|  | public: | ||||||
|  |     std::vector<std::string> get_remote_list() const; | ||||||
|  |     std::vector<std::string> get_button_list() const; | ||||||
|  |     void add_remote_with_button(const char* button_name, const IrdaMessage* message); | ||||||
|  |     void add_button(const char* button_name, const IrdaMessage* message); | ||||||
|  | 
 | ||||||
|  |     size_t get_current_remote(void) const; | ||||||
|  |     size_t get_current_button(void) const; | ||||||
|  |     const IrdaMessage* get_button_data(size_t button_index) const; | ||||||
|  |     void set_current_remote(size_t index); | ||||||
|  |     void set_current_button(size_t index); | ||||||
|  |     void rename_button(const char* str); | ||||||
|  |     void rename_remote(const char* str); | ||||||
|  |     std::string get_current_button_name(); | ||||||
|  |     std::string get_current_remote_name(); | ||||||
|  |     size_t get_current_remote_buttons_number(); | ||||||
|  |     void delete_current_button(); | ||||||
|  |     void delete_current_remote(); | ||||||
|  |     IrdaAppRemoteManager(); | ||||||
|  |     ~IrdaAppRemoteManager() {}; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
							
								
								
									
										110
									
								
								applications/irda/irda-app-view-manager.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								applications/irda/irda-app-view-manager.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,110 @@ | |||||||
|  | #include "furi.h" | ||||||
|  | #include "gui/modules/button_menu.h" | ||||||
|  | #include "gui/modules/dialog_ex.h" | ||||||
|  | #include "gui/modules/text_input.h" | ||||||
|  | #include "irda-app.hpp" | ||||||
|  | #include <callback-connector.h> | ||||||
|  | 
 | ||||||
|  | IrdaAppViewManager::IrdaAppViewManager() { | ||||||
|  |     event_queue = osMessageQueueNew(10, sizeof(IrdaAppEvent), NULL); | ||||||
|  | 
 | ||||||
|  |     view_dispatcher = view_dispatcher_alloc(); | ||||||
|  |     auto callback = cbc::obtain_connector(this, &IrdaAppViewManager::previous_view_callback); | ||||||
|  | 
 | ||||||
|  |     gui = static_cast<Gui*>(furi_record_open("gui")); | ||||||
|  |     view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen); | ||||||
|  | 
 | ||||||
|  |     button_menu = button_menu_alloc(); | ||||||
|  |     submenu = submenu_alloc(); | ||||||
|  |     popup = popup_alloc(); | ||||||
|  |     dialog_ex = dialog_ex_alloc(); | ||||||
|  |     text_input = text_input_alloc(); | ||||||
|  | 
 | ||||||
|  |     add_view(ViewType::ButtonMenu, button_menu_get_view(button_menu)); | ||||||
|  |     add_view(ViewType::Submenu, submenu_get_view(submenu)); | ||||||
|  |     add_view(ViewType::Popup, popup_get_view(popup)); | ||||||
|  |     add_view(ViewType::DialogEx, dialog_ex_get_view(dialog_ex)); | ||||||
|  |     add_view(ViewType::TextInput, text_input_get_view(text_input)); | ||||||
|  | 
 | ||||||
|  |     view_set_previous_callback(button_menu_get_view(button_menu), callback); | ||||||
|  |     view_set_previous_callback(submenu_get_view(submenu), callback); | ||||||
|  |     view_set_previous_callback(popup_get_view(popup), callback); | ||||||
|  |     view_set_previous_callback(dialog_ex_get_view(dialog_ex), callback); | ||||||
|  |     view_set_previous_callback(text_input_get_view(text_input), callback); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | IrdaAppViewManager::~IrdaAppViewManager() { | ||||||
|  |     view_dispatcher_remove_view( | ||||||
|  |         view_dispatcher, static_cast<uint32_t>(IrdaAppViewManager::ViewType::ButtonMenu)); | ||||||
|  |     view_dispatcher_remove_view( | ||||||
|  |         view_dispatcher, static_cast<uint32_t>(IrdaAppViewManager::ViewType::TextInput)); | ||||||
|  |     view_dispatcher_remove_view( | ||||||
|  |         view_dispatcher, static_cast<uint32_t>(IrdaAppViewManager::ViewType::DialogEx)); | ||||||
|  |     view_dispatcher_remove_view( | ||||||
|  |         view_dispatcher, static_cast<uint32_t>(IrdaAppViewManager::ViewType::Submenu)); | ||||||
|  |     view_dispatcher_remove_view( | ||||||
|  |         view_dispatcher, static_cast<uint32_t>(IrdaAppViewManager::ViewType::Popup)); | ||||||
|  | 
 | ||||||
|  |     submenu_free(submenu); | ||||||
|  |     popup_free(popup); | ||||||
|  |     button_menu_free(button_menu); | ||||||
|  |     dialog_ex_free(dialog_ex); | ||||||
|  |     text_input_free(text_input); | ||||||
|  | 
 | ||||||
|  |     view_dispatcher_free(view_dispatcher); | ||||||
|  |     furi_record_close("gui"); | ||||||
|  |     osMessageQueueDelete(event_queue); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppViewManager::switch_to(ViewType type) { | ||||||
|  |     view_dispatcher_switch_to_view(view_dispatcher, static_cast<uint32_t>(type)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | TextInput* IrdaAppViewManager::get_text_input() { | ||||||
|  |     return text_input; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | DialogEx* IrdaAppViewManager::get_dialog_ex() { | ||||||
|  |     return dialog_ex; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Submenu* IrdaAppViewManager::get_submenu() { | ||||||
|  |     return submenu; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Popup* IrdaAppViewManager::get_popup() { | ||||||
|  |     return popup; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ButtonMenu* IrdaAppViewManager::get_button_menu() { | ||||||
|  |     return button_menu; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | osMessageQueueId_t IrdaAppViewManager::get_event_queue() { | ||||||
|  |     return event_queue; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppViewManager::receive_event(IrdaAppEvent* event) { | ||||||
|  |     if(osMessageQueueGet(event_queue, event, NULL, 100) != osOK) { | ||||||
|  |         event->type = IrdaAppEvent::Type::Tick; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppViewManager::send_event(IrdaAppEvent* event) { | ||||||
|  |     osStatus_t result = osMessageQueuePut(event_queue, event, 0, 0); | ||||||
|  |     furi_check(result == osOK); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint32_t IrdaAppViewManager::previous_view_callback(void* context) { | ||||||
|  |     if(event_queue != NULL) { | ||||||
|  |         IrdaAppEvent event; | ||||||
|  |         event.type = IrdaAppEvent::Type::Back; | ||||||
|  |         send_event(&event); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return VIEW_IGNORE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppViewManager::add_view(ViewType view_type, View* view) { | ||||||
|  |     view_dispatcher_add_view(view_dispatcher, static_cast<uint32_t>(view_type), view); | ||||||
|  | } | ||||||
							
								
								
									
										52
									
								
								applications/irda/irda-app-view-manager.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								applications/irda/irda-app-view-manager.hpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,52 @@ | |||||||
|  | #pragma once | ||||||
|  | #include "gui/modules/button_menu.h" | ||||||
|  | #include "gui/modules/text_input.h" | ||||||
|  | #include <furi.h> | ||||||
|  | #include <gui/view_dispatcher.h> | ||||||
|  | #include <gui/modules/dialog_ex.h> | ||||||
|  | #include <gui/modules/submenu.h> | ||||||
|  | #include <gui/modules/popup.h> | ||||||
|  | #include "irda-app.hpp" | ||||||
|  | 
 | ||||||
|  | class IrdaAppViewManager { | ||||||
|  | public: | ||||||
|  |     enum class ViewType : uint8_t { | ||||||
|  |         DialogEx, | ||||||
|  |         TextInput, | ||||||
|  |         Submenu, | ||||||
|  |         ButtonMenu, | ||||||
|  |         Popup, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     IrdaAppViewManager(); | ||||||
|  |     ~IrdaAppViewManager(); | ||||||
|  | 
 | ||||||
|  |     void switch_to(ViewType type); | ||||||
|  | 
 | ||||||
|  |     void receive_event(IrdaAppEvent* event); | ||||||
|  |     void send_event(IrdaAppEvent* event); | ||||||
|  | 
 | ||||||
|  |     DialogEx* get_dialog_ex(); | ||||||
|  |     Submenu* get_submenu(); | ||||||
|  |     Popup* get_popup(); | ||||||
|  |     TextInput* get_text_input(); | ||||||
|  |     ButtonMenu* get_button_menu(); | ||||||
|  | 
 | ||||||
|  |     osMessageQueueId_t get_event_queue(); | ||||||
|  | 
 | ||||||
|  |     uint32_t previous_view_callback(void* context); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     ViewDispatcher* view_dispatcher; | ||||||
|  |     Gui* gui; | ||||||
|  |     TextInput* text_input; | ||||||
|  |     DialogEx* dialog_ex; | ||||||
|  |     Submenu* submenu; | ||||||
|  |     Popup* popup; | ||||||
|  |     ButtonMenu* button_menu; | ||||||
|  | 
 | ||||||
|  |     osMessageQueueId_t event_queue; | ||||||
|  | 
 | ||||||
|  |     void add_view(ViewType view_type, View* view); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
							
								
								
									
										156
									
								
								applications/irda/irda-app.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								applications/irda/irda-app.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,156 @@ | |||||||
|  | #include "irda-app.hpp" | ||||||
|  | #include <furi.h> | ||||||
|  | #include <gui/gui.h> | ||||||
|  | #include <input/input.h> | ||||||
|  | #include <stdarg.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <callback-connector.h> | ||||||
|  | 
 | ||||||
|  | void IrdaApp::run(void) { | ||||||
|  |     IrdaAppEvent event; | ||||||
|  |     bool consumed; | ||||||
|  |     bool exit = false; | ||||||
|  | 
 | ||||||
|  |     scenes[current_scene]->on_enter(this); | ||||||
|  | 
 | ||||||
|  |     while(!exit) { | ||||||
|  |         view_manager.receive_event(&event); | ||||||
|  | 
 | ||||||
|  |         consumed = scenes[current_scene]->on_event(this, &event); | ||||||
|  | 
 | ||||||
|  |         if(!consumed) { | ||||||
|  |             if(event.type == IrdaAppEvent::Type::Back) { | ||||||
|  |                 exit = switch_to_previous_scene(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     scenes[current_scene]->on_exit(this); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | IrdaAppViewManager* IrdaApp::get_view_manager() { | ||||||
|  |     return &view_manager; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaApp::set_learn_new_remote(bool value) { | ||||||
|  |     learn_new_remote = value; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool IrdaApp::get_learn_new_remote() { | ||||||
|  |     return learn_new_remote; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaApp::switch_to_next_scene(Scene next_scene) { | ||||||
|  |     previous_scenes_list.push_front(current_scene); | ||||||
|  |     switch_to_next_scene_without_saving(next_scene); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaApp::switch_to_next_scene_without_saving(Scene next_scene) { | ||||||
|  |     if(next_scene != Scene::Exit) { | ||||||
|  |         scenes[current_scene]->on_exit(this); | ||||||
|  |         current_scene = next_scene; | ||||||
|  |         scenes[current_scene]->on_enter(this); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaApp::search_and_switch_to_previous_scene(const 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) { | ||||||
|  |                 scene_found = true; | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     scenes[current_scene]->on_exit(this); | ||||||
|  |     current_scene = previous_scene; | ||||||
|  |     scenes[current_scene]->on_enter(this); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool IrdaApp::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) return true; | ||||||
|  | 
 | ||||||
|  |     scenes[current_scene]->on_exit(this); | ||||||
|  |     current_scene = previous_scene; | ||||||
|  |     scenes[current_scene]->on_enter(this); | ||||||
|  |     return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | IrdaApp::Scene IrdaApp::get_previous_scene() { | ||||||
|  |     Scene scene = Scene::Exit; | ||||||
|  | 
 | ||||||
|  |     if(!previous_scenes_list.empty()) { | ||||||
|  |         scene = previous_scenes_list.front(); | ||||||
|  |         previous_scenes_list.pop_front(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return scene; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | IrdaAppRemoteManager* IrdaApp::get_remote_manager() { | ||||||
|  |     return &remote_manager; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | IrdaAppSignalReceiver* IrdaApp::get_receiver() { | ||||||
|  |     return &receiver; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaApp::set_text_store(uint8_t index, const char* text...) { | ||||||
|  |     furi_check(index < text_store_max); | ||||||
|  | 
 | ||||||
|  |     va_list args; | ||||||
|  |     va_start(args, text); | ||||||
|  | 
 | ||||||
|  |     vsnprintf(text_store[index], text_store_size, text, args); | ||||||
|  | 
 | ||||||
|  |     va_end(args); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | char* IrdaApp::get_text_store(uint8_t index) { | ||||||
|  |     furi_check(index < text_store_max); | ||||||
|  | 
 | ||||||
|  |     return text_store[index]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint8_t IrdaApp::get_text_store_size() { | ||||||
|  |     return text_store_size; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaApp::text_input_callback(void* context, char* text) { | ||||||
|  |     IrdaApp* app = static_cast<IrdaApp*>(context); | ||||||
|  |     IrdaAppEvent event; | ||||||
|  |     event.type = IrdaAppEvent::Type::TextEditDone; | ||||||
|  |     app->get_view_manager()->send_event(&event); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaApp::popup_callback(void* context) { | ||||||
|  |     IrdaApp* app = static_cast<IrdaApp*>(context); | ||||||
|  |     IrdaAppEvent event; | ||||||
|  |     event.type = IrdaAppEvent::Type::PopupTimer; | ||||||
|  |     app->get_view_manager()->send_event(&event); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaApp::set_edit_element(IrdaApp::EditElement value) { | ||||||
|  |     element = value; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | IrdaApp::EditElement IrdaApp::get_edit_element(void) { | ||||||
|  |     return element; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaApp::set_edit_action(IrdaApp::EditAction value) { | ||||||
|  |     action = value; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | IrdaApp::EditAction IrdaApp::get_edit_action(void) { | ||||||
|  |     return action; | ||||||
|  | } | ||||||
							
								
								
									
										108
									
								
								applications/irda/irda-app.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								applications/irda/irda-app.hpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,108 @@ | |||||||
|  | #pragma once | ||||||
|  | #include <map> | ||||||
|  | #include <irda.h> | ||||||
|  | #include <furi.h> | ||||||
|  | #include "irda-app-event.hpp" | ||||||
|  | #include "scene/irda-app-scene.hpp" | ||||||
|  | #include "irda-app-view-manager.hpp" | ||||||
|  | #include "irda-app-remote-manager.hpp" | ||||||
|  | #include "irda-app-receiver.hpp" | ||||||
|  | #include <forward_list> | ||||||
|  | #include <stdint.h> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class IrdaApp { | ||||||
|  | public: | ||||||
|  |     enum class EditElement : uint8_t { | ||||||
|  |         Button, | ||||||
|  |         Remote, | ||||||
|  |     }; | ||||||
|  |     enum class EditAction : uint8_t { | ||||||
|  |         Rename, | ||||||
|  |         Delete, | ||||||
|  |     }; | ||||||
|  |     enum class Scene : uint8_t { | ||||||
|  |         Exit, | ||||||
|  |         Start, | ||||||
|  |         Universal, | ||||||
|  |         UniversalTV, | ||||||
|  |         UniversalAudio, | ||||||
|  |         UniversalAirConditioner, | ||||||
|  |         Learn, | ||||||
|  |         LearnSuccess, | ||||||
|  |         LearnEnterName, | ||||||
|  |         LearnDone, | ||||||
|  |         LearnDoneAfter, | ||||||
|  |         Remote, | ||||||
|  |         RemoteList, | ||||||
|  |         Edit, | ||||||
|  |         EditKeySelect, | ||||||
|  |         EditRename, | ||||||
|  |         EditDelete, | ||||||
|  |         EditRenameDone, | ||||||
|  |         EditDeleteDone, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     void run(void); | ||||||
|  |     void switch_to_next_scene(Scene index); | ||||||
|  |     void switch_to_next_scene_without_saving(Scene index); | ||||||
|  |     bool switch_to_previous_scene(uint8_t count = 1); | ||||||
|  |     Scene get_previous_scene(); | ||||||
|  |     IrdaAppViewManager* get_view_manager(); | ||||||
|  |     IrdaAppSignalReceiver* get_receiver(); | ||||||
|  |     void set_text_store(uint8_t index, const char* text...); | ||||||
|  |     char* get_text_store(uint8_t index); | ||||||
|  |     uint8_t get_text_store_size(); | ||||||
|  |     IrdaAppRemoteManager* get_remote_manager(); | ||||||
|  |     void search_and_switch_to_previous_scene(const std::initializer_list<Scene>& scenes_list); | ||||||
|  | 
 | ||||||
|  |     void set_edit_element(EditElement value); | ||||||
|  |     EditElement get_edit_element(void); | ||||||
|  | 
 | ||||||
|  |     void set_edit_action(EditAction value); | ||||||
|  |     EditAction get_edit_action(void); | ||||||
|  | 
 | ||||||
|  |     bool get_learn_new_remote(); | ||||||
|  |     void set_learn_new_remote(bool value); | ||||||
|  | 
 | ||||||
|  |     static void text_input_callback(void* context, char* text); | ||||||
|  |     static void popup_callback(void* context); | ||||||
|  | 
 | ||||||
|  |     IrdaApp() {} | ||||||
|  |     ~IrdaApp() { | ||||||
|  |         for (auto &it : scenes) | ||||||
|  |             delete it.second; | ||||||
|  |     } | ||||||
|  | private: | ||||||
|  |     static const uint8_t text_store_size = 128; | ||||||
|  |     static const uint8_t text_store_max = 2; | ||||||
|  |     char text_store[text_store_max][text_store_size + 1]; | ||||||
|  |     bool learn_new_remote; | ||||||
|  |     EditElement element; | ||||||
|  |     EditAction action; | ||||||
|  | 
 | ||||||
|  |     IrdaAppSignalReceiver receiver; | ||||||
|  |     IrdaAppViewManager view_manager; | ||||||
|  |     IrdaAppRemoteManager remote_manager; | ||||||
|  | 
 | ||||||
|  |     std::forward_list<Scene> previous_scenes_list; | ||||||
|  |     Scene current_scene = Scene::Start; | ||||||
|  | 
 | ||||||
|  |     std::map<Scene, IrdaAppScene*> scenes = { | ||||||
|  |         {Scene::Start, new IrdaAppSceneStart()}, | ||||||
|  |         {Scene::Universal, new IrdaAppSceneUniversal()}, | ||||||
|  |         {Scene::Learn, new IrdaAppSceneLearn()}, | ||||||
|  |         {Scene::LearnSuccess, new IrdaAppSceneLearnSuccess()}, | ||||||
|  |         {Scene::LearnEnterName, new IrdaAppSceneLearnEnterName()}, | ||||||
|  |         {Scene::LearnDone, new IrdaAppSceneLearnDone()}, | ||||||
|  |         {Scene::LearnDoneAfter, new IrdaAppSceneLearnDoneAfter()}, | ||||||
|  |         {Scene::Remote, new IrdaAppSceneRemote()}, | ||||||
|  |         {Scene::RemoteList, new IrdaAppSceneRemoteList()}, | ||||||
|  |         {Scene::Edit, new IrdaAppSceneEdit()}, | ||||||
|  |         {Scene::EditKeySelect, new IrdaAppSceneEditKeySelect()}, | ||||||
|  |         {Scene::EditRename, new IrdaAppSceneEditRename()}, | ||||||
|  |         {Scene::EditDelete, new IrdaAppSceneEditDelete()}, | ||||||
|  |         {Scene::EditRenameDone, new IrdaAppSceneEditRenameDone()}, | ||||||
|  |         {Scene::EditDeleteDone, new IrdaAppSceneEditDeleteDone()}, | ||||||
|  |     }; | ||||||
|  | }; | ||||||
| @ -1,146 +0,0 @@ | |||||||
| #include "irda-decoder-nec.h" |  | ||||||
| #include "string.h" |  | ||||||
| 
 |  | ||||||
| const uint32_t PREAMBULA_HIGH_MIN = 9000 - 900; |  | ||||||
| const uint32_t PREAMBULA_HIGH_MAX = 9000 + 900; |  | ||||||
| 
 |  | ||||||
| const uint32_t PREAMBULA_LOW_MIN = 4500 - 450; |  | ||||||
| const uint32_t PREAMBULA_LOW_MAX = 4500 + 450; |  | ||||||
| 
 |  | ||||||
| const uint32_t PREAMBULA_RETRY_LOW_MIN = 2500 - 350; |  | ||||||
| const uint32_t PREAMBULA_RETRY_LOW_MAX = 2500 + 250; |  | ||||||
| 
 |  | ||||||
| const uint32_t BIT_HIGH_MIN = 560 - 100; |  | ||||||
| const uint32_t BIT_HIGH_MAX = 560 + 100; |  | ||||||
| 
 |  | ||||||
| const uint32_t BIT_LOW_ONE_MIN = 1690 - 200; |  | ||||||
| const uint32_t BIT_LOW_ONE_MAX = 1690 + 200; |  | ||||||
| 
 |  | ||||||
| const uint32_t BIT_LOW_ZERO_MIN = 560 - 100; |  | ||||||
| const uint32_t BIT_LOW_ZERO_MAX = 560 + 100; |  | ||||||
| 
 |  | ||||||
| #define SET_STATE(_state) \ |  | ||||||
|     { decoder->state = _state; } |  | ||||||
| 
 |  | ||||||
| #define TIME_FIT(_prefix) ((time > _prefix##_MIN) && (time < _prefix##_MAX)) |  | ||||||
| 
 |  | ||||||
| #ifndef MIN |  | ||||||
| #define MIN(a, b) ((a) < (b) ? (a) : (b)) |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| bool save_decoder_nec_data(IrDANecDecoder* decoder, IrDADecoderOutputData* out) { |  | ||||||
|     bool result = false; |  | ||||||
| 
 |  | ||||||
|     if((decoder->data.simple.cmd + decoder->data.simple.cmd_inverse) == 0xFF) { |  | ||||||
|         if(out->data_length < sizeof(IrDANecDataType)) { |  | ||||||
|             out->flags |= IRDA_TOO_SHORT_BUFFER; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         memcpy(out->data, &decoder->data.data, MIN(sizeof(IrDANecDataType), out->data_length)); |  | ||||||
|         result = true; |  | ||||||
|     } else { |  | ||||||
|         reset_decoder_nec(decoder); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool process_decoder_nec( |  | ||||||
|     IrDANecDecoder* decoder, |  | ||||||
|     bool polarity, |  | ||||||
|     uint32_t time, |  | ||||||
|     IrDADecoderOutputData* out) { |  | ||||||
|     bool error = true; |  | ||||||
|     bool result = false; |  | ||||||
| 
 |  | ||||||
|     switch(decoder->state) { |  | ||||||
|     case(WAIT_PREAMBULA_HIGH): |  | ||||||
|         if(polarity) { |  | ||||||
|             if(TIME_FIT(PREAMBULA_HIGH)) { |  | ||||||
|                 SET_STATE(WAIT_PREAMBULA_LOW); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         // any values before preambula start is correct
 |  | ||||||
|         error = false; |  | ||||||
|         break; |  | ||||||
|     case(WAIT_PREAMBULA_LOW): |  | ||||||
|         if(!polarity) { |  | ||||||
|             if(TIME_FIT(PREAMBULA_LOW)) { |  | ||||||
|                 // new data, reset storage
 |  | ||||||
|                 reset_decoder_nec(decoder); |  | ||||||
|                 SET_STATE(WAIT_BIT_HIGH); |  | ||||||
|                 error = false; |  | ||||||
|             } else if(TIME_FIT(PREAMBULA_RETRY_LOW)) { |  | ||||||
|                 // wait for data repeat command
 |  | ||||||
|                 SET_STATE(WAIT_RETRY_HIGH); |  | ||||||
|                 error = false; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         break; |  | ||||||
|     case(WAIT_RETRY_HIGH): |  | ||||||
|         if(polarity) { |  | ||||||
|             if(TIME_FIT(BIT_HIGH)) { |  | ||||||
|                 SET_STATE(WAIT_PREAMBULA_HIGH); |  | ||||||
| 
 |  | ||||||
|                 // repeat event
 |  | ||||||
|                 result = save_decoder_nec_data(decoder, out); |  | ||||||
|                 out->flags |= IRDA_REPEAT; |  | ||||||
|                 error = false; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         break; |  | ||||||
|     case(WAIT_BIT_HIGH): |  | ||||||
|         if(polarity) { |  | ||||||
|             if(TIME_FIT(BIT_HIGH)) { |  | ||||||
|                 SET_STATE(WAIT_BIT_LOW); |  | ||||||
|                 error = false; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         break; |  | ||||||
|     case(WAIT_BIT_STOP_HIGH): |  | ||||||
|         if(polarity) { |  | ||||||
|             if(TIME_FIT(BIT_HIGH)) { |  | ||||||
|                 SET_STATE(WAIT_PREAMBULA_HIGH); |  | ||||||
| 
 |  | ||||||
|                 // message end event
 |  | ||||||
|                 result = save_decoder_nec_data(decoder, out); |  | ||||||
|                 error = false; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         break; |  | ||||||
|     case(WAIT_BIT_LOW): |  | ||||||
|         if(!polarity) { |  | ||||||
|             int8_t bit = -1; |  | ||||||
|             if(TIME_FIT(BIT_LOW_ZERO)) { |  | ||||||
|                 SET_STATE(WAIT_BIT_HIGH); |  | ||||||
|                 bit = 0; |  | ||||||
|                 error = false; |  | ||||||
|             } else if(TIME_FIT(BIT_LOW_ONE)) { |  | ||||||
|                 SET_STATE(WAIT_BIT_HIGH); |  | ||||||
|                 bit = 1; |  | ||||||
|                 error = false; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if(bit != -1) { |  | ||||||
|                 decoder->data.data |= (bit << decoder->current_data_index); |  | ||||||
|                 decoder->current_data_index++; |  | ||||||
| 
 |  | ||||||
|                 if(decoder->current_data_index > 31) { |  | ||||||
|                     decoder->current_data_index = 0; |  | ||||||
|                     SET_STATE(WAIT_BIT_STOP_HIGH); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if(error) reset_decoder_nec(decoder); |  | ||||||
| 
 |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void reset_decoder_nec(IrDANecDecoder* decoder) { |  | ||||||
|     decoder->state = WAIT_PREAMBULA_HIGH; |  | ||||||
|     decoder->data.data = 0; |  | ||||||
|     decoder->current_data_index = 0; |  | ||||||
| } |  | ||||||
| @ -1,39 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include <stdint.h> |  | ||||||
| #include <stdbool.h> |  | ||||||
| #include "irda-decoder-types.h" |  | ||||||
| 
 |  | ||||||
| typedef enum { |  | ||||||
|     WAIT_PREAMBULA_HIGH, |  | ||||||
|     WAIT_PREAMBULA_LOW, |  | ||||||
|     WAIT_RETRY_HIGH, |  | ||||||
|     WAIT_BIT_HIGH, |  | ||||||
|     WAIT_BIT_LOW, |  | ||||||
|     WAIT_BIT_STOP_HIGH, |  | ||||||
| } IrDANecDecoderState; |  | ||||||
| 
 |  | ||||||
| typedef struct { |  | ||||||
|     uint8_t addr2; |  | ||||||
|     uint8_t addr1; |  | ||||||
|     uint8_t cmd_inverse; |  | ||||||
|     uint8_t cmd; |  | ||||||
| } IrDANecData; |  | ||||||
| 
 |  | ||||||
| typedef uint32_t IrDANecDataType; |  | ||||||
| 
 |  | ||||||
| typedef struct { |  | ||||||
|     union { |  | ||||||
|         IrDANecData simple; |  | ||||||
|         IrDANecDataType data; |  | ||||||
|     } data; |  | ||||||
|     uint8_t current_data_index; |  | ||||||
|     IrDANecDecoderState state; |  | ||||||
| } IrDANecDecoder; |  | ||||||
| 
 |  | ||||||
| bool process_decoder_nec( |  | ||||||
|     IrDANecDecoder* decoder, |  | ||||||
|     bool polarity, |  | ||||||
|     uint32_t time, |  | ||||||
|     IrDADecoderOutputData* out); |  | ||||||
| 
 |  | ||||||
| void reset_decoder_nec(IrDANecDecoder* decoder); |  | ||||||
| @ -1,12 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include <stdint.h> |  | ||||||
| 
 |  | ||||||
| typedef enum { IRDA_UNKNOWN, IRDA_NEC, IRDA_SAMSUNG } IrDAProtocolType; |  | ||||||
| typedef enum { IRDA_REPEAT = (1 << 0), IRDA_TOO_SHORT_BUFFER = (1 << 1) } IrDAProtocolFlags; |  | ||||||
| 
 |  | ||||||
| typedef struct { |  | ||||||
|     IrDAProtocolType protocol; |  | ||||||
|     uint8_t flags; |  | ||||||
|     uint8_t* data; /** < ponter to output data, filled by app */ |  | ||||||
|     uint32_t data_length; /** < output data length, filled by app */ |  | ||||||
| } IrDADecoderOutputData; |  | ||||||
| @ -1,41 +0,0 @@ | |||||||
| #include "irda-decoder.h" |  | ||||||
| 
 |  | ||||||
| IrDADecoder* alloc_decoder(void) { |  | ||||||
|     IrDADecoder* decoder = malloc(sizeof(IrDADecoder)); |  | ||||||
| 
 |  | ||||||
|     // init decoders
 |  | ||||||
|     reset_decoder_nec(&decoder->nec); |  | ||||||
| 
 |  | ||||||
|     return decoder; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void free_decoder(IrDADecoder* decoder) { |  | ||||||
|     free(decoder); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool process_decoder( |  | ||||||
|     IrDADecoder* decoder, |  | ||||||
|     bool start_polarity, |  | ||||||
|     uint32_t* timings, |  | ||||||
|     uint32_t timings_length, |  | ||||||
|     IrDADecoderOutputData* out) { |  | ||||||
|     bool result = false; |  | ||||||
| 
 |  | ||||||
|     // zero result
 |  | ||||||
|     memset(out->data, 0, out->data_length); |  | ||||||
|     out->protocol = IRDA_UNKNOWN; |  | ||||||
|     out->flags = 0; |  | ||||||
| 
 |  | ||||||
|     // process data
 |  | ||||||
|     for(uint32_t timings_index = 0; timings_index < timings_length; timings_index++) { |  | ||||||
|         if(process_decoder_nec(&decoder->nec, start_polarity, timings[timings_index], out)) { |  | ||||||
|             out->protocol = IRDA_NEC; |  | ||||||
|             result = true; |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         start_polarity = !start_polarity; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| @ -1,17 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include <furi.h> |  | ||||||
| #include "irda-decoder-nec.h" |  | ||||||
| #include "irda-decoder-types.h" |  | ||||||
| 
 |  | ||||||
| typedef struct { |  | ||||||
|     IrDANecDecoder nec; |  | ||||||
| } IrDADecoder; |  | ||||||
| 
 |  | ||||||
| IrDADecoder* alloc_decoder(void); |  | ||||||
| void free_decoder(IrDADecoder* decoder); |  | ||||||
| bool process_decoder( |  | ||||||
|     IrDADecoder* decoder, |  | ||||||
|     bool start_polarity, |  | ||||||
|     uint32_t* timings, |  | ||||||
|     uint32_t timings_length, |  | ||||||
|     IrDADecoderOutputData* out); |  | ||||||
							
								
								
									
										9
									
								
								applications/irda/irda-runner.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								applications/irda/irda-runner.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | |||||||
|  | #include "irda-app.hpp" | ||||||
|  | 
 | ||||||
|  | extern "C" int32_t irda(void* p) { | ||||||
|  |     IrdaApp* app = new IrdaApp(); | ||||||
|  |     app->run(); | ||||||
|  |     delete app; | ||||||
|  | 
 | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
| @ -290,7 +290,7 @@ void irda_rx_callback(void* ctx, bool level, uint32_t duration) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int32_t irda(void* p) { | int32_t irda2(void* p) { | ||||||
|     osMessageQueueId_t event_queue = osMessageQueueNew(32, sizeof(AppEvent), NULL); |     osMessageQueueId_t event_queue = osMessageQueueNew(32, sizeof(AppEvent), NULL); | ||||||
| 
 | 
 | ||||||
|     State _state; |     State _state; | ||||||
| @ -1,19 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| // our tx pin is TIM2_CH4
 |  | ||||||
| extern TIM_HandleTypeDef TIM_A; |  | ||||||
| 
 |  | ||||||
| #define RC5_CARRIER_FREQUENCY 36000 |  | ||||||
| #define RC5_DUTY_CYCLE 0.33 |  | ||||||
| 
 |  | ||||||
| #define RC6_CARRIER_FREQUENCY 36000 |  | ||||||
| #define RC6_DUTY_CYCLE 0.33 |  | ||||||
| 
 |  | ||||||
| #define SAMSUNG_CARRIER_FREQUENCY 37900 |  | ||||||
| #define SAMSUNG_DUTY_CYCLE 0.33 |  | ||||||
| 
 |  | ||||||
| #define NEC_CARRIER_FREQUENCY 38000 |  | ||||||
| #define NEC_DUTY_CYCLE 0.33 |  | ||||||
| 
 |  | ||||||
| #define SIRC_CARRIER_FREQUENCY 40000 |  | ||||||
| #define SIRC_DUTY_CYCLE 0.5 |  | ||||||
							
								
								
									
										35
									
								
								applications/irda/scene/irda-app-scene-edit-delete-done.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								applications/irda/scene/irda-app-scene-edit-delete-done.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,35 @@ | |||||||
|  | #include "../irda-app.hpp" | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneEditDeleteDone::on_enter(IrdaApp* app) { | ||||||
|  |     IrdaAppViewManager* view_manager = app->get_view_manager(); | ||||||
|  |     Popup* popup = view_manager->get_popup(); | ||||||
|  | 
 | ||||||
|  |     popup_set_icon(popup, 0, 2, I_DolphinMafia_115x62); | ||||||
|  |     popup_set_text(popup, "Deleted", 83, 19, AlignLeft, AlignBottom); | ||||||
|  | 
 | ||||||
|  |     popup_set_callback(popup, IrdaApp::popup_callback); | ||||||
|  |     popup_set_context(popup, app); | ||||||
|  |     popup_set_timeout(popup, 1500); | ||||||
|  |     popup_enable_timeout(popup); | ||||||
|  | 
 | ||||||
|  |     view_manager->switch_to(IrdaAppViewManager::ViewType::Popup); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool IrdaAppSceneEditDeleteDone::on_event(IrdaApp* app, IrdaAppEvent* event) { | ||||||
|  |     bool consumed = false; | ||||||
|  | 
 | ||||||
|  |     if(event->type == IrdaAppEvent::Type::PopupTimer) { | ||||||
|  |         if(app->get_edit_element() == IrdaApp::EditElement::Remote) { | ||||||
|  |             app->search_and_switch_to_previous_scene( | ||||||
|  |                 {IrdaApp::Scene::Start, IrdaApp::Scene::RemoteList}); | ||||||
|  |         } else { | ||||||
|  |             app->search_and_switch_to_previous_scene({IrdaApp::Scene::Remote}); | ||||||
|  |         } | ||||||
|  |         consumed = true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return consumed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneEditDeleteDone::on_exit(IrdaApp* app) { | ||||||
|  | } | ||||||
							
								
								
									
										81
									
								
								applications/irda/scene/irda-app-scene-edit-delete.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								applications/irda/scene/irda-app-scene-edit-delete.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,81 @@ | |||||||
|  | #include "../irda-app.hpp" | ||||||
|  | #include "irda.h" | ||||||
|  | #include <string> | ||||||
|  | #include <stdio.h> | ||||||
|  | 
 | ||||||
|  | static void dialog_result_callback(DialogExResult result, void* context) { | ||||||
|  |     auto app = static_cast<IrdaApp*>(context); | ||||||
|  |     IrdaAppEvent event; | ||||||
|  | 
 | ||||||
|  |     event.type = IrdaAppEvent::Type::DialogExSelected; | ||||||
|  |     event.payload.dialog_ex_result = result; | ||||||
|  | 
 | ||||||
|  |     app->get_view_manager()->send_event(&event); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneEditDelete::on_enter(IrdaApp* app) { | ||||||
|  |     IrdaAppViewManager* view_manager = app->get_view_manager(); | ||||||
|  |     DialogEx* dialog_ex = view_manager->get_dialog_ex(); | ||||||
|  | 
 | ||||||
|  |     auto remote_manager = app->get_remote_manager(); | ||||||
|  | 
 | ||||||
|  |     if(app->get_edit_element() == IrdaApp::EditElement::Button) { | ||||||
|  |         auto message = remote_manager->get_button_data(remote_manager->get_current_button()); | ||||||
|  |         dialog_ex_set_header(dialog_ex, "Delete button?", 64, 6, AlignCenter, AlignCenter); | ||||||
|  |         app->set_text_store( | ||||||
|  |             0, | ||||||
|  |             "%s\n%s\nA=0x%0*lX C=0x%0*lX", | ||||||
|  |             remote_manager->get_current_button_name().c_str(), | ||||||
|  |             irda_get_protocol_name(message->protocol), | ||||||
|  |             irda_get_protocol_address_length(message->protocol), | ||||||
|  |             message->address, | ||||||
|  |             irda_get_protocol_command_length(message->protocol), | ||||||
|  |             message->command); | ||||||
|  |     } else { | ||||||
|  |         dialog_ex_set_header(dialog_ex, "Delete remote?", 64, 6, AlignCenter, AlignCenter); | ||||||
|  |         app->set_text_store( | ||||||
|  |             0, | ||||||
|  |             "%s\n with %lu buttons", | ||||||
|  |             remote_manager->get_current_remote_name().c_str(), | ||||||
|  |             remote_manager->get_current_remote_buttons_number()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     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_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); | ||||||
|  |     dialog_ex_set_context(dialog_ex, app); | ||||||
|  | 
 | ||||||
|  |     view_manager->switch_to(IrdaAppViewManager::ViewType::DialogEx); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool IrdaAppSceneEditDelete::on_event(IrdaApp* app, IrdaAppEvent* event) { | ||||||
|  |     bool consumed = false; | ||||||
|  | 
 | ||||||
|  |     if(event->type == IrdaAppEvent::Type::DialogExSelected) { | ||||||
|  |         switch(event->payload.dialog_ex_result) { | ||||||
|  |         case DialogExResultLeft: | ||||||
|  |             app->switch_to_previous_scene(); | ||||||
|  |             break; | ||||||
|  |         case DialogExResultCenter: | ||||||
|  |             furi_assert(0); | ||||||
|  |             break; | ||||||
|  |         case DialogExResultRight: | ||||||
|  |             auto remote_manager = app->get_remote_manager(); | ||||||
|  |             if(app->get_edit_element() == IrdaApp::EditElement::Remote) { | ||||||
|  |                 remote_manager->delete_current_remote(); | ||||||
|  |             } else { | ||||||
|  |                 remote_manager->delete_current_button(); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             app->switch_to_next_scene(IrdaApp::Scene::EditDeleteDone); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return consumed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneEditDelete::on_exit(IrdaApp* app) { | ||||||
|  | } | ||||||
							
								
								
									
										54
									
								
								applications/irda/scene/irda-app-scene-edit-key-select.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								applications/irda/scene/irda-app-scene-edit-key-select.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,54 @@ | |||||||
|  | #include "../irda-app.hpp" | ||||||
|  | #include "gui/modules/submenu.h" | ||||||
|  | 
 | ||||||
|  | static void submenu_callback(void* context, uint32_t index) { | ||||||
|  |     IrdaApp* app = static_cast<IrdaApp*>(context); | ||||||
|  |     IrdaAppEvent event; | ||||||
|  | 
 | ||||||
|  |     event.type = IrdaAppEvent::Type::MenuSelected; | ||||||
|  |     event.payload.menu_index = index; | ||||||
|  | 
 | ||||||
|  |     app->get_view_manager()->send_event(&event); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneEditKeySelect::on_enter(IrdaApp* app) { | ||||||
|  |     IrdaAppViewManager* view_manager = app->get_view_manager(); | ||||||
|  |     Submenu* submenu = view_manager->get_submenu(); | ||||||
|  |     int i = 0; | ||||||
|  | 
 | ||||||
|  |     const char* header = app->get_edit_action() == IrdaApp::EditAction::Rename ? "Rename key:" : | ||||||
|  |                                                                                  "Delete key:"; | ||||||
|  |     submenu_set_header(submenu, header); | ||||||
|  | 
 | ||||||
|  |     auto remote_manager = app->get_remote_manager(); | ||||||
|  |     buttons_names = remote_manager->get_button_list(); | ||||||
|  |     for(const auto& it : buttons_names) { | ||||||
|  |         submenu_add_item(submenu, it.c_str(), i++, submenu_callback, app); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     view_manager->switch_to(IrdaAppViewManager::ViewType::Submenu); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool IrdaAppSceneEditKeySelect::on_event(IrdaApp* app, IrdaAppEvent* event) { | ||||||
|  |     bool consumed = false; | ||||||
|  | 
 | ||||||
|  |     if(event->type == IrdaAppEvent::Type::MenuSelected) { | ||||||
|  |         auto remote_manager = app->get_remote_manager(); | ||||||
|  |         remote_manager->set_current_button(event->payload.menu_index); | ||||||
|  |         consumed = true; | ||||||
|  |         if(app->get_edit_action() == IrdaApp::EditAction::Rename) { | ||||||
|  |             app->switch_to_next_scene(IrdaApp::Scene::EditRename); | ||||||
|  |         } else { | ||||||
|  |             app->switch_to_next_scene(IrdaApp::Scene::EditDelete); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return consumed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneEditKeySelect::on_exit(IrdaApp* app) { | ||||||
|  |     IrdaAppViewManager* view_manager = app->get_view_manager(); | ||||||
|  |     Submenu* submenu = view_manager->get_submenu(); | ||||||
|  | 
 | ||||||
|  |     submenu_clean(submenu); | ||||||
|  | } | ||||||
							
								
								
									
										31
									
								
								applications/irda/scene/irda-app-scene-edit-rename-done.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								applications/irda/scene/irda-app-scene-edit-rename-done.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | |||||||
|  | #include "../irda-app.hpp" | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneEditRenameDone::on_enter(IrdaApp* app) { | ||||||
|  |     IrdaAppViewManager* view_manager = app->get_view_manager(); | ||||||
|  |     Popup* popup = view_manager->get_popup(); | ||||||
|  | 
 | ||||||
|  |     popup_set_icon(popup, 32, 5, I_DolphinNice_96x59); | ||||||
|  | 
 | ||||||
|  |     popup_set_text(popup, "Saved!", 13, 22, AlignLeft, AlignTop); | ||||||
|  | 
 | ||||||
|  |     popup_set_callback(popup, IrdaApp::popup_callback); | ||||||
|  |     popup_set_context(popup, app); | ||||||
|  |     popup_set_timeout(popup, 1500); | ||||||
|  |     popup_enable_timeout(popup); | ||||||
|  | 
 | ||||||
|  |     view_manager->switch_to(IrdaAppViewManager::ViewType::Popup); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool IrdaAppSceneEditRenameDone::on_event(IrdaApp* app, IrdaAppEvent* event) { | ||||||
|  |     bool consumed = false; | ||||||
|  | 
 | ||||||
|  |     if(event->type == IrdaAppEvent::Type::PopupTimer) { | ||||||
|  |         app->switch_to_next_scene(IrdaApp::Scene::Remote); | ||||||
|  |         consumed = true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return consumed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneEditRenameDone::on_exit(IrdaApp* app) { | ||||||
|  | } | ||||||
							
								
								
									
										46
									
								
								applications/irda/scene/irda-app-scene-edit-rename.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								applications/irda/scene/irda-app-scene-edit-rename.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,46 @@ | |||||||
|  | #include "../irda-app.hpp" | ||||||
|  | #include <cstdio> | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneEditRename::on_enter(IrdaApp* app) { | ||||||
|  |     IrdaAppViewManager* view_manager = app->get_view_manager(); | ||||||
|  |     TextInput* text_input = view_manager->get_text_input(); | ||||||
|  | 
 | ||||||
|  |     auto remote_manager = app->get_remote_manager(); | ||||||
|  |     if(app->get_edit_element() == IrdaApp::EditElement::Button) { | ||||||
|  |         auto button_name = remote_manager->get_current_button_name(); | ||||||
|  |         strncpy(app->get_text_store(0), button_name.c_str(), app->get_text_store_size()); | ||||||
|  |     } else { | ||||||
|  |         auto remote_name = remote_manager->get_current_remote_name(); | ||||||
|  |         strncpy(app->get_text_store(0), remote_name.c_str(), app->get_text_store_size()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     text_input_set_header_text(text_input, "Name the key"); | ||||||
|  |     text_input_set_result_callback( | ||||||
|  |         text_input, | ||||||
|  |         IrdaApp::text_input_callback, | ||||||
|  |         app, | ||||||
|  |         app->get_text_store(0), | ||||||
|  |         app->get_text_store_size()); | ||||||
|  | 
 | ||||||
|  |     view_manager->switch_to(IrdaAppViewManager::ViewType::TextInput); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool IrdaAppSceneEditRename::on_event(IrdaApp* app, IrdaAppEvent* event) { | ||||||
|  |     bool consumed = false; | ||||||
|  | 
 | ||||||
|  |     if(event->type == IrdaAppEvent::Type::TextEditDone) { | ||||||
|  |         auto remote_manager = app->get_remote_manager(); | ||||||
|  |         if(app->get_edit_element() == IrdaApp::EditElement::Button) { | ||||||
|  |             remote_manager->rename_button(app->get_text_store(0)); | ||||||
|  |         } else { | ||||||
|  |             remote_manager->rename_remote(app->get_text_store(0)); | ||||||
|  |         } | ||||||
|  |         app->switch_to_next_scene_without_saving(IrdaApp::Scene::EditRenameDone); | ||||||
|  |         consumed = true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return consumed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneEditRename::on_exit(IrdaApp* app) { | ||||||
|  | } | ||||||
							
								
								
									
										74
									
								
								applications/irda/scene/irda-app-scene-edit.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								applications/irda/scene/irda-app-scene-edit.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,74 @@ | |||||||
|  | #include "../irda-app.hpp" | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     SubmenuIndexAddKey, | ||||||
|  |     SubmenuIndexRenameKey, | ||||||
|  |     SubmenuIndexDeleteKey, | ||||||
|  |     SubmenuIndexRenameRemote, | ||||||
|  |     SubmenuIndexDeleteRemote, | ||||||
|  | } SubmenuIndex; | ||||||
|  | 
 | ||||||
|  | static void submenu_callback(void* context, uint32_t index) { | ||||||
|  |     IrdaApp* app = static_cast<IrdaApp*>(context); | ||||||
|  |     IrdaAppEvent event; | ||||||
|  | 
 | ||||||
|  |     event.type = IrdaAppEvent::Type::MenuSelected; | ||||||
|  |     event.payload.menu_index = index; | ||||||
|  | 
 | ||||||
|  |     app->get_view_manager()->send_event(&event); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneEdit::on_enter(IrdaApp* app) { | ||||||
|  |     IrdaAppViewManager* view_manager = app->get_view_manager(); | ||||||
|  |     Submenu* submenu = view_manager->get_submenu(); | ||||||
|  | 
 | ||||||
|  |     submenu_add_item(submenu, "Add key", SubmenuIndexAddKey, submenu_callback, app); | ||||||
|  |     submenu_add_item(submenu, "Rename key", SubmenuIndexRenameKey, submenu_callback, app); | ||||||
|  |     submenu_add_item(submenu, "Delete key", SubmenuIndexDeleteKey, submenu_callback, app); | ||||||
|  |     submenu_add_item(submenu, "Rename remote", SubmenuIndexRenameRemote, submenu_callback, app); | ||||||
|  |     submenu_add_item(submenu, "Delete remote", SubmenuIndexDeleteRemote, submenu_callback, app); | ||||||
|  | 
 | ||||||
|  |     view_manager->switch_to(IrdaAppViewManager::ViewType::Submenu); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool IrdaAppSceneEdit::on_event(IrdaApp* app, IrdaAppEvent* event) { | ||||||
|  |     bool consumed = false; | ||||||
|  | 
 | ||||||
|  |     if(event->type == IrdaAppEvent::Type::MenuSelected) { | ||||||
|  |         switch(event->payload.menu_index) { | ||||||
|  |         case SubmenuIndexAddKey: | ||||||
|  |             app->switch_to_next_scene(IrdaApp::Scene::Learn); | ||||||
|  |             break; | ||||||
|  |         case SubmenuIndexRenameKey: | ||||||
|  |             app->set_edit_action(IrdaApp::EditAction::Rename); | ||||||
|  |             app->set_edit_element(IrdaApp::EditElement::Button); | ||||||
|  |             app->switch_to_next_scene(IrdaApp::Scene::EditKeySelect); | ||||||
|  |             break; | ||||||
|  |         case SubmenuIndexDeleteKey: | ||||||
|  |             app->set_edit_action(IrdaApp::EditAction::Delete); | ||||||
|  |             app->set_edit_element(IrdaApp::EditElement::Button); | ||||||
|  |             app->switch_to_next_scene(IrdaApp::Scene::EditKeySelect); | ||||||
|  |             break; | ||||||
|  |         case SubmenuIndexRenameRemote: | ||||||
|  |             app->set_edit_action(IrdaApp::EditAction::Rename); | ||||||
|  |             app->set_edit_element(IrdaApp::EditElement::Remote); | ||||||
|  |             app->switch_to_next_scene(IrdaApp::Scene::EditRename); | ||||||
|  |             break; | ||||||
|  |         case SubmenuIndexDeleteRemote: | ||||||
|  |             app->set_edit_action(IrdaApp::EditAction::Delete); | ||||||
|  |             app->set_edit_element(IrdaApp::EditElement::Remote); | ||||||
|  |             app->switch_to_next_scene(IrdaApp::Scene::EditDelete); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         consumed = true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return consumed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneEdit::on_exit(IrdaApp* app) { | ||||||
|  |     IrdaAppViewManager* view_manager = app->get_view_manager(); | ||||||
|  |     Submenu* submenu = view_manager->get_submenu(); | ||||||
|  | 
 | ||||||
|  |     submenu_clean(submenu); | ||||||
|  | } | ||||||
							
								
								
									
										34
									
								
								applications/irda/scene/irda-app-scene-learn-done-after.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								applications/irda/scene/irda-app-scene-learn-done-after.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | |||||||
|  | #include "../irda-app.hpp" | ||||||
|  | #include <string> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <gui/modules/popup.h> | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneLearnDoneAfter::on_enter(IrdaApp* app) { | ||||||
|  |     auto view_manager = app->get_view_manager(); | ||||||
|  |     auto popup = view_manager->get_popup(); | ||||||
|  | 
 | ||||||
|  |     popup_set_icon(popup, 0, 30, I_IrdaSendShort_128x34); | ||||||
|  |     popup_set_text( | ||||||
|  |         popup, "Get ready!\nPoint flipper at target.", 64, 16, AlignCenter, AlignCenter); | ||||||
|  | 
 | ||||||
|  |     popup_set_callback(popup, IrdaApp::popup_callback); | ||||||
|  |     popup_set_context(popup, app); | ||||||
|  |     popup_set_timeout(popup, 1500); | ||||||
|  |     popup_enable_timeout(popup); | ||||||
|  | 
 | ||||||
|  |     view_manager->switch_to(IrdaAppViewManager::ViewType::Popup); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool IrdaAppSceneLearnDoneAfter::on_event(IrdaApp* app, IrdaAppEvent* event) { | ||||||
|  |     bool consumed = false; | ||||||
|  | 
 | ||||||
|  |     if(event->type == IrdaAppEvent::Type::PopupTimer) { | ||||||
|  |         app->switch_to_next_scene(IrdaApp::Scene::Remote); | ||||||
|  |         consumed = true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return consumed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneLearnDoneAfter::on_exit(IrdaApp* app) { | ||||||
|  | } | ||||||
							
								
								
									
										42
									
								
								applications/irda/scene/irda-app-scene-learn-done.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								applications/irda/scene/irda-app-scene-learn-done.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,42 @@ | |||||||
|  | #include "../irda-app.hpp" | ||||||
|  | #include <string> | ||||||
|  | #include <stdio.h> | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneLearnDone::on_enter(IrdaApp* app) { | ||||||
|  |     IrdaAppViewManager* view_manager = app->get_view_manager(); | ||||||
|  |     Popup* popup = view_manager->get_popup(); | ||||||
|  | 
 | ||||||
|  |     popup_set_icon(popup, 32, 5, I_DolphinNice_96x59); | ||||||
|  | 
 | ||||||
|  |     if(app->get_learn_new_remote()) { | ||||||
|  |         popup_set_text(popup, "New remote\ncreated!", 5, 7, AlignLeft, AlignTop); | ||||||
|  |     } else { | ||||||
|  |         popup_set_text(popup, "Saved!", 5, 7, AlignLeft, AlignTop); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     popup_set_callback(popup, IrdaApp::popup_callback); | ||||||
|  |     popup_set_context(popup, app); | ||||||
|  |     popup_set_timeout(popup, 1500); | ||||||
|  |     popup_enable_timeout(popup); | ||||||
|  | 
 | ||||||
|  |     view_manager->switch_to(IrdaAppViewManager::ViewType::Popup); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool IrdaAppSceneLearnDone::on_event(IrdaApp* app, IrdaAppEvent* event) { | ||||||
|  |     bool consumed = false; | ||||||
|  | 
 | ||||||
|  |     if(event->type == IrdaAppEvent::Type::PopupTimer) { | ||||||
|  |         if(app->get_learn_new_remote()) { | ||||||
|  |             app->switch_to_next_scene(IrdaApp::Scene::LearnDoneAfter); | ||||||
|  |         } else { | ||||||
|  |             app->switch_to_next_scene(IrdaApp::Scene::Remote); | ||||||
|  |         } | ||||||
|  |         consumed = true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return consumed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneLearnDone::on_exit(IrdaApp* app) { | ||||||
|  |     app->set_learn_new_remote(false); | ||||||
|  | } | ||||||
							
								
								
									
										51
									
								
								applications/irda/scene/irda-app-scene-learn-enter-name.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								applications/irda/scene/irda-app-scene-learn-enter-name.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | |||||||
|  | #include "../irda-app.hpp" | ||||||
|  | #include "gui/modules/text_input.h" | ||||||
|  | #include <callback-connector.h> | ||||||
|  | #include <string> | ||||||
|  | #include <stdio.h> | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneLearnEnterName::on_enter(IrdaApp* app) { | ||||||
|  |     IrdaAppViewManager* view_manager = app->get_view_manager(); | ||||||
|  |     TextInput* text_input = view_manager->get_text_input(); | ||||||
|  | 
 | ||||||
|  |     auto receiver = app->get_receiver(); | ||||||
|  |     auto message = receiver->get_last_message(); | ||||||
|  | 
 | ||||||
|  |     app->set_text_store( | ||||||
|  |         0, | ||||||
|  |         "%.4s_%0*lX", | ||||||
|  |         irda_get_protocol_name(message->protocol), | ||||||
|  |         irda_get_protocol_command_length(message->protocol), | ||||||
|  |         message->command); | ||||||
|  | 
 | ||||||
|  |     text_input_set_header_text(text_input, "Name the key"); | ||||||
|  |     text_input_set_result_callback( | ||||||
|  |         text_input, | ||||||
|  |         IrdaApp::text_input_callback, | ||||||
|  |         app, | ||||||
|  |         app->get_text_store(0), | ||||||
|  |         app->get_text_store_size()); | ||||||
|  | 
 | ||||||
|  |     view_manager->switch_to(IrdaAppViewManager::ViewType::TextInput); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool IrdaAppSceneLearnEnterName::on_event(IrdaApp* app, IrdaAppEvent* event) { | ||||||
|  |     bool consumed = false; | ||||||
|  | 
 | ||||||
|  |     if(event->type == IrdaAppEvent::Type::TextEditDone) { | ||||||
|  |         auto remote_manager = app->get_remote_manager(); | ||||||
|  |         auto receiver = app->get_receiver(); | ||||||
|  |         if(app->get_learn_new_remote()) { | ||||||
|  |             remote_manager->add_remote_with_button( | ||||||
|  |                 app->get_text_store(0), receiver->get_last_message()); | ||||||
|  |         } else { | ||||||
|  |             remote_manager->add_button(app->get_text_store(0), receiver->get_last_message()); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         app->switch_to_next_scene_without_saving(IrdaApp::Scene::LearnDone); | ||||||
|  |     } | ||||||
|  |     return consumed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneLearnEnterName::on_exit(IrdaApp* app) { | ||||||
|  | } | ||||||
							
								
								
									
										63
									
								
								applications/irda/scene/irda-app-scene-learn-success.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								applications/irda/scene/irda-app-scene-learn-success.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,63 @@ | |||||||
|  | #include "../irda-app.hpp" | ||||||
|  | #include "irda.h" | ||||||
|  | #include <string> | ||||||
|  | #include <stdio.h> | ||||||
|  | 
 | ||||||
|  | static void dialog_result_callback(DialogExResult result, void* context) { | ||||||
|  |     auto app = static_cast<IrdaApp*>(context); | ||||||
|  |     IrdaAppEvent event; | ||||||
|  | 
 | ||||||
|  |     event.type = IrdaAppEvent::Type::DialogExSelected; | ||||||
|  |     event.payload.dialog_ex_result = result; | ||||||
|  | 
 | ||||||
|  |     app->get_view_manager()->send_event(&event); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneLearnSuccess::on_enter(IrdaApp* app) { | ||||||
|  |     IrdaAppViewManager* view_manager = app->get_view_manager(); | ||||||
|  |     DialogEx* dialog_ex = view_manager->get_dialog_ex(); | ||||||
|  | 
 | ||||||
|  |     auto receiver = app->get_receiver(); | ||||||
|  |     auto message = receiver->get_last_message(); | ||||||
|  | 
 | ||||||
|  |     app->set_text_store(0, "%s", irda_get_protocol_name(message->protocol)); | ||||||
|  |     app->set_text_store( | ||||||
|  |         1, | ||||||
|  |         "A: 0x%0*lX\nC: 0x%0*lX\n", | ||||||
|  |         irda_get_protocol_address_length(message->protocol), | ||||||
|  |         message->address, | ||||||
|  |         irda_get_protocol_command_length(message->protocol), | ||||||
|  |         message->command); | ||||||
|  |     dialog_ex_set_header(dialog_ex, app->get_text_store(0), 95, 10, AlignCenter, AlignCenter); | ||||||
|  |     dialog_ex_set_text(dialog_ex, app->get_text_store(1), 75, 23, AlignLeft, AlignTop); | ||||||
|  |     dialog_ex_set_left_button_text(dialog_ex, "Retry"); | ||||||
|  |     dialog_ex_set_right_button_text(dialog_ex, "Save"); | ||||||
|  |     dialog_ex_set_icon(dialog_ex, 0, 1, I_DolphinExcited_64x63); | ||||||
|  |     dialog_ex_set_result_callback(dialog_ex, dialog_result_callback); | ||||||
|  |     dialog_ex_set_context(dialog_ex, app); | ||||||
|  | 
 | ||||||
|  |     view_manager->switch_to(IrdaAppViewManager::ViewType::DialogEx); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool IrdaAppSceneLearnSuccess::on_event(IrdaApp* app, IrdaAppEvent* event) { | ||||||
|  |     bool consumed = false; | ||||||
|  | 
 | ||||||
|  |     if(event->type == IrdaAppEvent::Type::DialogExSelected) { | ||||||
|  |         switch(event->payload.dialog_ex_result) { | ||||||
|  |         case DialogExResultLeft: | ||||||
|  |             app->switch_to_next_scene_without_saving(IrdaApp::Scene::Learn); | ||||||
|  |             break; | ||||||
|  |         case DialogExResultCenter: | ||||||
|  |             furi_assert(0); | ||||||
|  |             break; | ||||||
|  |         case DialogExResultRight: | ||||||
|  |             app->switch_to_next_scene(IrdaApp::Scene::LearnEnterName); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return consumed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneLearnSuccess::on_exit(IrdaApp* app) { | ||||||
|  | } | ||||||
							
								
								
									
										31
									
								
								applications/irda/scene/irda-app-scene-learn.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								applications/irda/scene/irda-app-scene-learn.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | |||||||
|  | #include "../irda-app.hpp" | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneLearn::on_enter(IrdaApp* app) { | ||||||
|  |     auto view_manager = app->get_view_manager(); | ||||||
|  |     auto receiver = app->get_receiver(); | ||||||
|  |     auto event_queue = view_manager->get_event_queue(); | ||||||
|  | 
 | ||||||
|  |     receiver->capture_once_start(event_queue); | ||||||
|  | 
 | ||||||
|  |     auto popup = view_manager->get_popup(); | ||||||
|  | 
 | ||||||
|  |     popup_set_icon(popup, 0, 32, I_IrdaLearnShort_128x31); | ||||||
|  |     popup_set_text( | ||||||
|  |         popup, "Point the remote at IR port\nand push the button", 5, 10, AlignLeft, AlignCenter); | ||||||
|  |     popup_set_callback(popup, NULL); | ||||||
|  | 
 | ||||||
|  |     view_manager->switch_to(IrdaAppViewManager::ViewType::Popup); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool IrdaAppSceneLearn::on_event(IrdaApp* app, IrdaAppEvent* event) { | ||||||
|  |     bool consumed = false; | ||||||
|  | 
 | ||||||
|  |     if(event->type == IrdaAppEvent::Type::IrdaMessageReceived) { | ||||||
|  |         app->switch_to_next_scene_without_saving(IrdaApp::Scene::LearnSuccess); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return consumed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneLearn::on_exit(IrdaApp* app) { | ||||||
|  | } | ||||||
							
								
								
									
										59
									
								
								applications/irda/scene/irda-app-scene-remote-list.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								applications/irda/scene/irda-app-scene-remote-list.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | |||||||
|  | #include "../irda-app.hpp" | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     SubmenuIndexPlus = -1, | ||||||
|  | } SubmenuIndex; | ||||||
|  | 
 | ||||||
|  | static void submenu_callback(void* context, uint32_t index) { | ||||||
|  |     IrdaApp* app = static_cast<IrdaApp*>(context); | ||||||
|  |     IrdaAppEvent event; | ||||||
|  | 
 | ||||||
|  |     event.type = IrdaAppEvent::Type::MenuSelected; | ||||||
|  |     event.payload.menu_index = index; | ||||||
|  | 
 | ||||||
|  |     app->get_view_manager()->send_event(&event); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneRemoteList::on_enter(IrdaApp* app) { | ||||||
|  |     IrdaAppViewManager* view_manager = app->get_view_manager(); | ||||||
|  |     Submenu* submenu = view_manager->get_submenu(); | ||||||
|  |     auto remote_manager = app->get_remote_manager(); | ||||||
|  |     int i = 0; | ||||||
|  | 
 | ||||||
|  |     remote_names = remote_manager->get_remote_list(); | ||||||
|  |     for(auto& a : remote_names) { | ||||||
|  |         submenu_add_item(submenu, a.c_str(), i++, submenu_callback, app); | ||||||
|  |     } | ||||||
|  |     submenu_add_item( | ||||||
|  |         submenu, "                           +", SubmenuIndexPlus, submenu_callback, app); | ||||||
|  | 
 | ||||||
|  |     view_manager->switch_to(IrdaAppViewManager::ViewType::Submenu); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool IrdaAppSceneRemoteList::on_event(IrdaApp* app, IrdaAppEvent* event) { | ||||||
|  |     bool consumed = false; | ||||||
|  | 
 | ||||||
|  |     if(event->type == IrdaAppEvent::Type::MenuSelected) { | ||||||
|  |         switch(event->payload.menu_index) { | ||||||
|  |         case SubmenuIndexPlus: | ||||||
|  |             app->set_learn_new_remote(true); | ||||||
|  |             app->switch_to_next_scene(IrdaApp::Scene::Learn); | ||||||
|  |             break; | ||||||
|  |         default: | ||||||
|  |             auto remote_manager = app->get_remote_manager(); | ||||||
|  |             remote_manager->set_current_remote(event->payload.menu_index); | ||||||
|  |             app->switch_to_next_scene(IrdaApp::Scene::Remote); | ||||||
|  |             consumed = true; | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return consumed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneRemoteList::on_exit(IrdaApp* app) { | ||||||
|  |     IrdaAppViewManager* view_manager = app->get_view_manager(); | ||||||
|  |     Submenu* submenu = view_manager->get_submenu(); | ||||||
|  | 
 | ||||||
|  |     submenu_clean(submenu); | ||||||
|  | } | ||||||
							
								
								
									
										75
									
								
								applications/irda/scene/irda-app-scene-remote.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								applications/irda/scene/irda-app-scene-remote.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,75 @@ | |||||||
|  | #include "../irda-app.hpp" | ||||||
|  | #include "gui/modules/button_menu.h" | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     ButtonIndexPlus = -2, | ||||||
|  |     ButtonIndexEdit = -1, | ||||||
|  | } ButtonIndex; | ||||||
|  | 
 | ||||||
|  | static void button_menu_callback(void* context, int32_t index) { | ||||||
|  |     IrdaApp* app = static_cast<IrdaApp*>(context); | ||||||
|  |     IrdaAppEvent event; | ||||||
|  | 
 | ||||||
|  |     event.type = IrdaAppEvent::Type::MenuSelected; | ||||||
|  |     event.payload.menu_index = index; | ||||||
|  | 
 | ||||||
|  |     app->get_view_manager()->send_event(&event); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneRemote::on_enter(IrdaApp* app) { | ||||||
|  |     IrdaAppViewManager* view_manager = app->get_view_manager(); | ||||||
|  |     ButtonMenu* button_menu = view_manager->get_button_menu(); | ||||||
|  |     auto remote_manager = app->get_remote_manager(); | ||||||
|  |     int i = 0; | ||||||
|  | 
 | ||||||
|  |     buttons_names = remote_manager->get_button_list(); | ||||||
|  | 
 | ||||||
|  |     i = 0; | ||||||
|  |     for(auto& name : buttons_names) { | ||||||
|  |         button_menu_add_item( | ||||||
|  |             button_menu, name.c_str(), i++, button_menu_callback, ButtonMenuItemTypeCommon, app); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     button_menu_add_item( | ||||||
|  |         button_menu, "+", ButtonIndexPlus, button_menu_callback, ButtonMenuItemTypeControl, app); | ||||||
|  |     button_menu_add_item( | ||||||
|  |         button_menu, "Edit", ButtonIndexEdit, button_menu_callback, ButtonMenuItemTypeControl, app); | ||||||
|  | 
 | ||||||
|  |     app->set_text_store(0, "%s", remote_manager->get_current_remote_name().c_str()); | ||||||
|  |     button_menu_set_header(button_menu, app->get_text_store(0)); | ||||||
|  |     view_manager->switch_to(IrdaAppViewManager::ViewType::ButtonMenu); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool IrdaAppSceneRemote::on_event(IrdaApp* app, IrdaAppEvent* event) { | ||||||
|  |     bool consumed = true; | ||||||
|  | 
 | ||||||
|  |     if(event->type == IrdaAppEvent::Type::MenuSelected) { | ||||||
|  |         switch(event->payload.menu_index) { | ||||||
|  |         case ButtonIndexPlus: | ||||||
|  |             app->switch_to_next_scene(IrdaApp::Scene::Learn); | ||||||
|  |             break; | ||||||
|  |         case ButtonIndexEdit: | ||||||
|  |             app->switch_to_next_scene(IrdaApp::Scene::Edit); | ||||||
|  |             break; | ||||||
|  |         default: | ||||||
|  |             auto remote_manager = app->get_remote_manager(); | ||||||
|  |             auto message = remote_manager->get_button_data(event->payload.menu_index); | ||||||
|  |             app->get_receiver()->send_message(message); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } else if(event->type == IrdaAppEvent::Type::Back) { | ||||||
|  |         app->search_and_switch_to_previous_scene( | ||||||
|  |             {IrdaApp::Scene::Start, IrdaApp::Scene::RemoteList}); | ||||||
|  |     } else { | ||||||
|  |         consumed = false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return consumed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneRemote::on_exit(IrdaApp* app) { | ||||||
|  |     IrdaAppViewManager* view_manager = app->get_view_manager(); | ||||||
|  |     ButtonMenu* button_menu = view_manager->get_button_menu(); | ||||||
|  | 
 | ||||||
|  |     button_menu_clean(button_menu); | ||||||
|  | } | ||||||
							
								
								
									
										59
									
								
								applications/irda/scene/irda-app-scene-start.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								applications/irda/scene/irda-app-scene-start.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | |||||||
|  | #include "../irda-app.hpp" | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     SubmenuIndexUniversalLibrary, | ||||||
|  |     SubmenuIndexLearnNewRemote, | ||||||
|  |     SubmenuIndexSavedRemotes, | ||||||
|  | } SubmenuIndex; | ||||||
|  | 
 | ||||||
|  | static void submenu_callback(void* context, uint32_t index) { | ||||||
|  |     IrdaApp* app = static_cast<IrdaApp*>(context); | ||||||
|  |     IrdaAppEvent event; | ||||||
|  | 
 | ||||||
|  |     event.type = IrdaAppEvent::Type::MenuSelected; | ||||||
|  |     event.payload.menu_index = index; | ||||||
|  | 
 | ||||||
|  |     app->get_view_manager()->send_event(&event); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneStart::on_enter(IrdaApp* app) { | ||||||
|  |     IrdaAppViewManager* view_manager = app->get_view_manager(); | ||||||
|  |     Submenu* submenu = view_manager->get_submenu(); | ||||||
|  | 
 | ||||||
|  |     submenu_add_item( | ||||||
|  |         submenu, "Universal library", SubmenuIndexUniversalLibrary, submenu_callback, app); | ||||||
|  |     submenu_add_item( | ||||||
|  |         submenu, "Learn new remote", SubmenuIndexLearnNewRemote, submenu_callback, app); | ||||||
|  |     submenu_add_item(submenu, "Saved remotes", SubmenuIndexSavedRemotes, submenu_callback, app); | ||||||
|  | 
 | ||||||
|  |     view_manager->switch_to(IrdaAppViewManager::ViewType::Submenu); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool IrdaAppSceneStart::on_event(IrdaApp* app, IrdaAppEvent* event) { | ||||||
|  |     bool consumed = false; | ||||||
|  | 
 | ||||||
|  |     if(event->type == IrdaAppEvent::Type::MenuSelected) { | ||||||
|  |         switch(event->payload.menu_index) { | ||||||
|  |         case SubmenuIndexUniversalLibrary: | ||||||
|  |             app->switch_to_next_scene(IrdaApp::Scene::Universal); | ||||||
|  |             break; | ||||||
|  |         case SubmenuIndexLearnNewRemote: | ||||||
|  |             app->set_learn_new_remote(true); | ||||||
|  |             app->switch_to_next_scene(IrdaApp::Scene::Learn); | ||||||
|  |             break; | ||||||
|  |         case SubmenuIndexSavedRemotes: | ||||||
|  |             app->switch_to_next_scene(IrdaApp::Scene::RemoteList); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         consumed = true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return consumed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneStart::on_exit(IrdaApp* app) { | ||||||
|  |     IrdaAppViewManager* view_manager = app->get_view_manager(); | ||||||
|  |     Submenu* submenu = view_manager->get_submenu(); | ||||||
|  | 
 | ||||||
|  |     submenu_clean(submenu); | ||||||
|  | } | ||||||
							
								
								
									
										57
									
								
								applications/irda/scene/irda-app-scene-universal.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								applications/irda/scene/irda-app-scene-universal.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,57 @@ | |||||||
|  | #include "../irda-app.hpp" | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     SubmenuIndexUniversalTV, | ||||||
|  |     SubmenuIndexUniversalAudio, | ||||||
|  |     SubmenuIndexUniversalAirConditioner, | ||||||
|  | } SubmenuIndex; | ||||||
|  | 
 | ||||||
|  | static void submenu_callback(void* context, uint32_t index) { | ||||||
|  |     IrdaApp* app = static_cast<IrdaApp*>(context); | ||||||
|  |     IrdaAppEvent event; | ||||||
|  | 
 | ||||||
|  |     event.type = IrdaAppEvent::Type::MenuSelected; | ||||||
|  |     event.payload.menu_index = index; | ||||||
|  | 
 | ||||||
|  |     app->get_view_manager()->send_event(&event); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneUniversal::on_enter(IrdaApp* app) { | ||||||
|  |     IrdaAppViewManager* view_manager = app->get_view_manager(); | ||||||
|  |     Submenu* submenu = view_manager->get_submenu(); | ||||||
|  | 
 | ||||||
|  |     submenu_add_item(submenu, "TV's", SubmenuIndexUniversalTV, submenu_callback, app); | ||||||
|  |     submenu_add_item(submenu, "Audio Players", SubmenuIndexUniversalAudio, submenu_callback, app); | ||||||
|  |     submenu_add_item( | ||||||
|  |         submenu, "Air Conditioners", SubmenuIndexUniversalAirConditioner, submenu_callback, app); | ||||||
|  | 
 | ||||||
|  |     view_manager->switch_to(IrdaAppViewManager::ViewType::Submenu); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool IrdaAppSceneUniversal::on_event(IrdaApp* app, IrdaAppEvent* event) { | ||||||
|  |     bool consumed = false; | ||||||
|  | 
 | ||||||
|  |     if(event->type == IrdaAppEvent::Type::MenuSelected) { | ||||||
|  |         switch(event->payload.menu_index) { | ||||||
|  |         case SubmenuIndexUniversalTV: | ||||||
|  |             //            app->switch_to_next_scene(IrdaApp::Scene::UniversalTV);
 | ||||||
|  |             break; | ||||||
|  |         case SubmenuIndexUniversalAudio: | ||||||
|  |             //            app->switch_to_next_scene(IrdaApp::Scene::UniversalAudio);
 | ||||||
|  |             break; | ||||||
|  |         case SubmenuIndexUniversalAirConditioner: | ||||||
|  |             //            app->switch_to_next_scene(IrdaApp::Scene::UniversalAirConditioner);
 | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         consumed = true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return consumed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IrdaAppSceneUniversal::on_exit(IrdaApp* app) { | ||||||
|  |     IrdaAppViewManager* view_manager = app->get_view_manager(); | ||||||
|  |     Submenu* submenu = view_manager->get_submenu(); | ||||||
|  | 
 | ||||||
|  |     submenu_clean(submenu); | ||||||
|  | } | ||||||
							
								
								
									
										130
									
								
								applications/irda/scene/irda-app-scene.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								applications/irda/scene/irda-app-scene.hpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,130 @@ | |||||||
|  | #pragma once | ||||||
|  | #include "../irda-app.hpp" | ||||||
|  | #include <api-hal-irda.h> | ||||||
|  | #include "irda.h" | ||||||
|  | #include <gui/elements.h> | ||||||
|  | #include <vector> | ||||||
|  | #include <string> | ||||||
|  | 
 | ||||||
|  | class IrdaApp; | ||||||
|  | 
 | ||||||
|  | class IrdaAppScene { | ||||||
|  | public: | ||||||
|  |     virtual void on_enter(IrdaApp* app) = 0; | ||||||
|  |     virtual bool on_event(IrdaApp* app, IrdaAppEvent* event) = 0; | ||||||
|  |     virtual void on_exit(IrdaApp* app) = 0; | ||||||
|  |     virtual ~IrdaAppScene(){}; | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class IrdaAppSceneStart : public IrdaAppScene { | ||||||
|  | public: | ||||||
|  |     void on_enter(IrdaApp* app) final; | ||||||
|  |     bool on_event(IrdaApp* app, IrdaAppEvent* event) final; | ||||||
|  |     void on_exit(IrdaApp* app) final; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class IrdaAppSceneUniversal : public IrdaAppScene { | ||||||
|  | public: | ||||||
|  |     void on_enter(IrdaApp* app) final; | ||||||
|  |     bool on_event(IrdaApp* app, IrdaAppEvent* event) final; | ||||||
|  |     void on_exit(IrdaApp* app) final; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class IrdaAppSceneLearn : public IrdaAppScene { | ||||||
|  | public: | ||||||
|  |     void on_enter(IrdaApp* app) final; | ||||||
|  |     bool on_event(IrdaApp* app, IrdaAppEvent* event) final; | ||||||
|  |     void on_exit(IrdaApp* app) final; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class IrdaAppSceneLearnSuccess : public IrdaAppScene { | ||||||
|  | public: | ||||||
|  |     void on_enter(IrdaApp* app) final; | ||||||
|  |     bool on_event(IrdaApp* app, IrdaAppEvent* event) final; | ||||||
|  |     void on_exit(IrdaApp* app) final; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class IrdaAppSceneLearnEnterName : public IrdaAppScene { | ||||||
|  | public: | ||||||
|  |     void on_enter(IrdaApp* app) final; | ||||||
|  |     bool on_event(IrdaApp* app, IrdaAppEvent* event) final; | ||||||
|  |     void on_exit(IrdaApp* app) final; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class IrdaAppSceneLearnDone : public IrdaAppScene { | ||||||
|  | public: | ||||||
|  |     void on_enter(IrdaApp* app) final; | ||||||
|  |     bool on_event(IrdaApp* app, IrdaAppEvent* event) final; | ||||||
|  |     void on_exit(IrdaApp* app) final; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class IrdaAppSceneLearnDoneAfter : public IrdaAppScene { | ||||||
|  | public: | ||||||
|  |     void on_enter(IrdaApp* app) final; | ||||||
|  |     bool on_event(IrdaApp* app, IrdaAppEvent* event) final; | ||||||
|  |     void on_exit(IrdaApp* app) final; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class IrdaAppSceneRemote : public IrdaAppScene { | ||||||
|  | public: | ||||||
|  |     void on_enter(IrdaApp* app) final; | ||||||
|  |     bool on_event(IrdaApp* app, IrdaAppEvent* event) final; | ||||||
|  |     void on_exit(IrdaApp* app) final; | ||||||
|  | private: | ||||||
|  |     std::vector<std::string> buttons_names; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class IrdaAppSceneRemoteList : public IrdaAppScene { | ||||||
|  | public: | ||||||
|  |     void on_enter(IrdaApp* app) final; | ||||||
|  |     bool on_event(IrdaApp* app, IrdaAppEvent* event) final; | ||||||
|  |     void on_exit(IrdaApp* app) final; | ||||||
|  |     std::vector<std::string> remote_names; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class IrdaAppSceneEdit : public IrdaAppScene { | ||||||
|  | public: | ||||||
|  |     void on_enter(IrdaApp* app) final; | ||||||
|  |     bool on_event(IrdaApp* app, IrdaAppEvent* event) final; | ||||||
|  |     void on_exit(IrdaApp* app) final; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class IrdaAppSceneEditKeySelect : public IrdaAppScene { | ||||||
|  | public: | ||||||
|  |     void on_enter(IrdaApp* app) final; | ||||||
|  |     bool on_event(IrdaApp* app, IrdaAppEvent* event) final; | ||||||
|  |     void on_exit(IrdaApp* app) final; | ||||||
|  | private: | ||||||
|  |     std::vector<std::string> buttons_names; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class IrdaAppSceneEditRename : public IrdaAppScene { | ||||||
|  | public: | ||||||
|  |     void on_enter(IrdaApp* app) final; | ||||||
|  |     bool on_event(IrdaApp* app, IrdaAppEvent* event) final; | ||||||
|  |     void on_exit(IrdaApp* app) final; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class IrdaAppSceneEditDelete : public IrdaAppScene { | ||||||
|  | public: | ||||||
|  |     void on_enter(IrdaApp* app) final; | ||||||
|  |     bool on_event(IrdaApp* app, IrdaAppEvent* event) final; | ||||||
|  |     void on_exit(IrdaApp* app) final; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class IrdaAppSceneEditRenameDone : public IrdaAppScene { | ||||||
|  | public: | ||||||
|  |     void on_enter(IrdaApp* app) final; | ||||||
|  |     bool on_event(IrdaApp* app, IrdaAppEvent* event) final; | ||||||
|  |     void on_exit(IrdaApp* app) final; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class IrdaAppSceneEditDeleteDone : public IrdaAppScene { | ||||||
|  | public: | ||||||
|  |     void on_enter(IrdaApp* app) final; | ||||||
|  |     bool on_event(IrdaApp* app, IrdaAppEvent* event) final; | ||||||
|  |     void on_exit(IrdaApp* app) final; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| @ -110,9 +110,11 @@ int32_t irda_monitor_app(void* p) { | |||||||
|                 snprintf( |                 snprintf( | ||||||
|                     irda_monitor->display_text, |                     irda_monitor->display_text, | ||||||
|                     sizeof(irda_monitor->display_text), |                     sizeof(irda_monitor->display_text), | ||||||
|                     "%s\nA:0x%02lX\nC:0x%02lX\n%s\n", |                     "%s\nA:0x%0*lX\nC:0x%0*lX\n%s\n", | ||||||
|                     irda_get_protocol_name(message->protocol), |                     irda_get_protocol_name(message->protocol), | ||||||
|  |                     irda_get_protocol_address_length(message->protocol), | ||||||
|                     message->address, |                     message->address, | ||||||
|  |                     irda_get_protocol_command_length(message->protocol), | ||||||
|                     message->command, |                     message->command, | ||||||
|                     message->repeat ? " R" : ""); |                     message->repeat ? " R" : ""); | ||||||
|                 view_port_update(view_port); |                 view_port_update(view_port); | ||||||
| @ -124,9 +126,11 @@ int32_t irda_monitor_app(void* p) { | |||||||
|             if(message || (distance > (IRDA_TIMINGS_SIZE / 2))) { |             if(message || (distance > (IRDA_TIMINGS_SIZE / 2))) { | ||||||
|                 if(message) { |                 if(message) { | ||||||
|                     printf( |                     printf( | ||||||
|                         "== %s, A:0x%02lX, C:0x%02lX%s ==\r\n", |                         "== %s, A:0x%0*lX, C:0x%0*lX%s ==\r\n", | ||||||
|                         irda_get_protocol_name(message->protocol), |                         irda_get_protocol_name(message->protocol), | ||||||
|  |                         irda_get_protocol_address_length(message->protocol), | ||||||
|                         message->address, |                         message->address, | ||||||
|  |                         irda_get_protocol_command_length(message->protocol), | ||||||
|                         message->command, |                         message->command, | ||||||
|                         message->repeat ? " R" : ""); |                         message->repeat ? " R" : ""); | ||||||
|                 } else { |                 } else { | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ | |||||||
| #include "../minunit.h" | #include "../minunit.h" | ||||||
| #include "irda.h" | #include "irda.h" | ||||||
| #include "test_data/irda_decoder_nec_test_data.srcdata" | #include "test_data/irda_decoder_nec_test_data.srcdata" | ||||||
|  | #include "test_data/irda_decoder_necext_test_data.srcdata" | ||||||
| #include "test_data/irda_decoder_samsung_test_data.srcdata" | #include "test_data/irda_decoder_samsung_test_data.srcdata" | ||||||
| 
 | 
 | ||||||
| #define RUN_DECODER(data, expected) \ | #define RUN_DECODER(data, expected) \ | ||||||
| @ -52,10 +53,12 @@ MU_TEST(test_samsung32) { | |||||||
|     RUN_DECODER(test_samsung32_input1, test_samsung32_expected1); |     RUN_DECODER(test_samsung32_input1, test_samsung32_expected1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| MU_TEST(test_mix_nec_samsung32) { | MU_TEST(test_mix) { | ||||||
|  |     RUN_DECODER(test_necext_input1, test_necext_expected1); | ||||||
|     RUN_DECODER(test_samsung32_input1, test_samsung32_expected1); |     RUN_DECODER(test_samsung32_input1, test_samsung32_expected1); | ||||||
|     RUN_DECODER(test_nec_input1, test_nec_expected1); |     RUN_DECODER(test_nec_input1, test_nec_expected1); | ||||||
|     RUN_DECODER(test_samsung32_input1, test_samsung32_expected1); |     RUN_DECODER(test_samsung32_input1, test_samsung32_expected1); | ||||||
|  |     RUN_DECODER(test_necext_input1, test_necext_expected1); | ||||||
|     RUN_DECODER(test_nec_input2, test_nec_expected2); |     RUN_DECODER(test_nec_input2, test_nec_expected2); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -75,6 +78,11 @@ MU_TEST(test_unexpected_end_in_sequence) { | |||||||
|     RUN_DECODER(test_nec_input2, test_nec_expected2); |     RUN_DECODER(test_nec_input2, test_nec_expected2); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | MU_TEST(test_necext1) { | ||||||
|  |     RUN_DECODER(test_necext_input1, test_necext_expected1); | ||||||
|  |     RUN_DECODER(test_necext_input1, test_necext_expected1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| MU_TEST_SUITE(test_irda_decoder) { | MU_TEST_SUITE(test_irda_decoder) { | ||||||
|     MU_SUITE_CONFIGURE(&test_setup, &test_teardown); |     MU_SUITE_CONFIGURE(&test_setup, &test_teardown); | ||||||
| 
 | 
 | ||||||
| @ -82,7 +90,8 @@ MU_TEST_SUITE(test_irda_decoder) { | |||||||
|     MU_RUN_TEST(test_nec1); |     MU_RUN_TEST(test_nec1); | ||||||
|     MU_RUN_TEST(test_nec2); |     MU_RUN_TEST(test_nec2); | ||||||
|     MU_RUN_TEST(test_samsung32); |     MU_RUN_TEST(test_samsung32); | ||||||
|     MU_RUN_TEST(test_mix_nec_samsung32); |     MU_RUN_TEST(test_necext1); | ||||||
|  |     MU_RUN_TEST(test_mix); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int run_minunit_test_irda_decoder() { | int run_minunit_test_irda_decoder() { | ||||||
|  | |||||||
| @ -11,9 +11,9 @@ const uint32_t test_nec_input1[] = { | |||||||
| 1415838, 9080, 4436, 611, 494, 600, 505, 578, 500, 608, 501, 602, 502, 580, 498, 606, 508, 605, 500, 583, 1633, 608, 1608, 611, 1631, 578, 1638, 602, 1614, 606, 1637, 583, 1633, 607, 1609, 611, 494, 600, 505, 570, 500, 604, 501, 602, 502, 581, 497, 606, 499, 605, 499, 583, 1633, 617, 1608, 611, 1631, 579, 1638, 602}; | 1415838, 9080, 4436, 611, 494, 600, 505, 578, 500, 608, 501, 602, 502, 580, 498, 606, 508, 605, 500, 583, 1633, 608, 1608, 611, 1631, 578, 1638, 602, 1614, 606, 1637, 583, 1633, 607, 1609, 611, 494, 600, 505, 570, 500, 604, 501, 602, 502, 581, 497, 606, 499, 605, 499, 583, 1633, 617, 1608, 611, 1631, 579, 1638, 602}; | ||||||
| 
 | 
 | ||||||
| const IrdaMessage test_nec_expected1[] = { | const IrdaMessage test_nec_expected1[] = { | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0,  false}, |     {IrdaProtocolNEC,     0x00,      0,  false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0,  true}, |     {IrdaProtocolNEC,     0x00,      0,  true}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0,  false}, |     {IrdaProtocolNEC,     0x00,      0,  false}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const uint32_t test_nec_input2[] = { | const uint32_t test_nec_input2[] = { | ||||||
| @ -124,57 +124,57 @@ const uint32_t test_nec_input2[] = { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const IrdaMessage test_nec_expected2[] = { | const IrdaMessage test_nec_expected2[] = { | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x02,   false}, |     {IrdaProtocolNEC,     0x00,      0x02,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x02,   true}, |     {IrdaProtocolNEC,     0x00,      0x02,   true}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x02,   false}, |     {IrdaProtocolNEC,     0x00,      0x02,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x02,   true}, |     {IrdaProtocolNEC,     0x00,      0x02,   true}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x02,   true}, |     {IrdaProtocolNEC,     0x00,      0x02,   true}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x02,   true}, |     {IrdaProtocolNEC,     0x00,      0x02,   true}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x02,   true}, |     {IrdaProtocolNEC,     0x00,      0x02,   true}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x02,   true}, |     {IrdaProtocolNEC,     0x00,      0x02,   true}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x02,   true}, |     {IrdaProtocolNEC,     0x00,      0x02,   true}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x02,   true}, |     {IrdaProtocolNEC,     0x00,      0x02,   true}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x02,   true}, |     {IrdaProtocolNEC,     0x00,      0x02,   true}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x02,   true}, |     {IrdaProtocolNEC,     0x00,      0x02,   true}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x02,   true}, |     {IrdaProtocolNEC,     0x00,      0x02,   true}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x02,   true}, |     {IrdaProtocolNEC,     0x00,      0x02,   true}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x02,   true}, |     {IrdaProtocolNEC,     0x00,      0x02,   true}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x02,   true}, |     {IrdaProtocolNEC,     0x00,      0x02,   true}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x02,   true}, |     {IrdaProtocolNEC,     0x00,      0x02,   true}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x02,   true}, |     {IrdaProtocolNEC,     0x00,      0x02,   true}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x02,   true}, |     {IrdaProtocolNEC,     0x00,      0x02,   true}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x06,   false}, |     {IrdaProtocolNEC,     0x00,      0x06,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x06,   true}, |     {IrdaProtocolNEC,     0x00,      0x06,   true}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x04,   false}, |     {IrdaProtocolNEC,     0x00,      0x04,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x04,   true}, |     {IrdaProtocolNEC,     0x00,      0x04,   true}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x08,   false}, |     {IrdaProtocolNEC,     0x00,      0x08,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x08,   true}, |     {IrdaProtocolNEC,     0x00,      0x08,   true}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x08,   false}, |     {IrdaProtocolNEC,     0x00,      0x08,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x08,   true}, |     {IrdaProtocolNEC,     0x00,      0x08,   true}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x08,   false}, |     {IrdaProtocolNEC,     0x00,      0x08,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x08,   false}, |     {IrdaProtocolNEC,     0x00,      0x08,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x08,   false}, |     {IrdaProtocolNEC,     0x00,      0x08,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x08,   false}, |     {IrdaProtocolNEC,     0x00,      0x08,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x08,   false}, |     {IrdaProtocolNEC,     0x00,      0x08,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x08,   false}, |     {IrdaProtocolNEC,     0x00,      0x08,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x08,   false}, |     {IrdaProtocolNEC,     0x00,      0x08,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x08,   false}, |     {IrdaProtocolNEC,     0x00,      0x08,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x08,   false}, |     {IrdaProtocolNEC,     0x00,      0x08,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x08,   false}, |     {IrdaProtocolNEC,     0x00,      0x08,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x08,   false}, |     {IrdaProtocolNEC,     0x00,      0x08,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x09,   false}, |     {IrdaProtocolNEC,     0x00,      0x09,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x09,   false}, |     {IrdaProtocolNEC,     0x00,      0x09,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x09,   false}, |     {IrdaProtocolNEC,     0x00,      0x09,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x08,   false}, |     {IrdaProtocolNEC,     0x00,      0x08,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x0A,   false}, |     {IrdaProtocolNEC,     0x00,      0x0A,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x08,   false}, |     {IrdaProtocolNEC,     0x00,      0x08,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x08,   true}, |     {IrdaProtocolNEC,     0x00,      0x08,   true}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x08,   false}, |     {IrdaProtocolNEC,     0x00,      0x08,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x08,   true}, |     {IrdaProtocolNEC,     0x00,      0x08,   true}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x08,   false}, |     {IrdaProtocolNEC,     0x00,      0x08,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x0A,   false}, |     {IrdaProtocolNEC,     0x00,      0x0A,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x08,   false}, |     {IrdaProtocolNEC,     0x00,      0x08,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x0A,   false}, |     {IrdaProtocolNEC,     0x00,      0x0A,   false}, | ||||||
|     {IrdaProtocolNEC,     0xFF00,      0x0A,   true}, |     {IrdaProtocolNEC,     0x00,      0x0A,   true}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -0,0 +1,223 @@ | |||||||
|  | const uint32_t test_necext_input1[] = { | ||||||
|  | 1915384, 8967, 4463, 587, 527, 590, 524, 584, 1647, 590, 524, 583, 531, 586, 527, 590, 524, 583, 1646, 589, 1640, 586, 527, 590, 524, 583, 1647, 590, 1640, 587, 1644, 582, 1647, 589, 524, 583, 531, 586, 1644, 593, 521, 586, 527, 589, 1641, 586, 528, 589, 525, 592, 521, 585, 1644, 592, 522, 585, 1645, 592, 1638, 589, 524, 592, 1637, 588, 1641, 585, 1645, 592, | ||||||
|  | 41082, 8965, 2220, 591, | ||||||
|  | 409594, 8972, 4458, 591, 523, 584, 530, 587, 1642, 584, 529, 588, 526, 591, 522, 583, 530, 587, 1643, 584, 1646, 590, 523, 584, 530, 587, 1643, 584, 1647, 590, 1640, 586, 1643, 583, 531, 586, 527, 589, 1641, 586, 528, 589, 524, 593, 1637, 589, 524, 593, 521, 586, 529, 589, 1641, 585, 528, 589, 1640, 586, 1644, 592, 521, 585, 1645, 592, 1638, 588, 1641, 585, | ||||||
|  | 41088, 8968, 2218, 582, | ||||||
|  | 95791, 8971, 2214, 587, | ||||||
|  | 95787, 8965, 2220, 591, | ||||||
|  | 95783, 8971, 2215, 585, | ||||||
|  | 95787, 8964, 2221, 590, | ||||||
|  | 95783, 8971, 2215, 586, | ||||||
|  | 95788, 8965, 2220, 591, | ||||||
|  | 95783, 8969, 2216, 585, | ||||||
|  | 95789, 8965, 2220, 590, | ||||||
|  | 95782, 8970, 2215, 586, | ||||||
|  | 95788, 9047, 2139, 591, | ||||||
|  | 95782, 8970, 2216, 585, | ||||||
|  | 95788, 8966, 2220, 591, | ||||||
|  | 95782, 8972, 2214, 588, | ||||||
|  | 95786, 8964, 2222, 590, | ||||||
|  | 95784, 8971, 2214, 586, | ||||||
|  | 95787, 8967, 2218, 583, | ||||||
|  | 95791, 8964, 2222, 588, | ||||||
|  | 95785, 8969, 2217, 584, | ||||||
|  | 333740, 8967, 4464, 586, 528, 590, 524, 592, 1637, 589, 525, 592, 521, 586, 528, 589, 525, 593, 1637, 588, 1640, 585, 528, 589, 525, 592, 1638, 589, 1641, 586, 1644, 592, 1638, 588, 525, 592, 522, 585, 1644, 592, 522, 585, 528, 588, 1642, 585, 529, 588, 526, 591, 522, 585, 1645, 591, 522, 584, 1646, 591, 1639, 587, 526, 591, 1639, 588, 1642, 583, 1646, 590, | ||||||
|  | 41082, 8963, 2223, 588, | ||||||
|  | 95785, 8967, 2219, 591, | ||||||
|  | 95782, 8968, 2217, 584, | ||||||
|  | 246369, 8972, 4459, 591, 523, 583, 530, 587, 1643, 583, 530, 587, 527, 590, 523, 584, 530, 586, 1643, 583, 1647, 590, 524, 583, 530, 586, 1643, 583, 1646, 589, 1641, 586, 1644, 583, 531, 586, 528, 589, 1640, 585, 528, 588, 525, 592, 1638, 588, 525, 592, 522, 585, 529, 589, 1641, 584, 529, 588, 1642, 585, 1645, 591, 522, 585, 1645, 590, 1639, 587, 1642, 584, | ||||||
|  | 41090, 8966, 2220, 591, | ||||||
|  | 95782, 8966, 2220, 592, | ||||||
|  | 95782, 8967, 2218, 583, | ||||||
|  | 165604, 9017, 4413, 586, 527, 590, 524, 583, 1647, 589, 523, 582, 531, 586, 528, 589, 525, 593, 1637, 589, 1640, 585, 527, 588, 525, 592, 1638, 589, 1641, 585, 1644, 592, 1638, 588, 525, 591, 523, 585, 1645, 591, 522, 584, 529, 588, 1642, 584, 530, 587, 527, 591, 523, 584, 1646, 591, 523, 584, 1646, 591, 1640, 586, 527, 590, 1640, 586, 1643, 583, 1646, 589, | ||||||
|  | 41084, 8972, 2214, 587, | ||||||
|  | 95787, 8967, 2219, 581, | ||||||
|  | 95792, 8971, 2215, 586, | ||||||
|  | 208929, 9016, 4414, 584, 529, 588, 526, 591, 1638, 588, 525, 591, 522, 584, 529, 587, 526, 591, 1639, 587, 1642, 584, 529, 588, 526, 591, 1638, 587, 1643, 584, 1646, 591, 1639, 587, 526, 590, 523, 584, 1646, 590, 524, 583, 530, 587, 1643, 583, 530, 587, 527, 590, 524, 583, 1647, 590, 524, 583, 1647, 590, 1640, 586, 527, 589, 1640, 586, 1644, 592, 1637, 589, | ||||||
|  | 41085, 8972, 2214, 587, | ||||||
|  | 95787, 8964, 2221, 590, | ||||||
|  | 95784, 8965, 2221, 590, | ||||||
|  | 167378, 8969, 4460, 589, 525, 582, 532, 586, 1644, 592, 521, 586, 528, 589, 524, 592, 522, 585, 1645, 592, 1638, 589, 525, 592, 522, 585, 1644, 591, 1639, 588, 1642, 585, 1645, 591, 522, 585, 529, 587, 1641, 584, 530, 587, 526, 591, 1639, 588, 526, 591, 522, 584, 530, 587, 1643, 584, 530, 587, 1642, 584, 1646, 591, 523, 584, 1647, 590, 1640, 587, 1643, 583, | ||||||
|  | 41090, 9017, 2169, 591, | ||||||
|  | 95781, 8969, 2216, 585, | ||||||
|  | 95788, 8964, 2223, 588, | ||||||
|  | 192781, 8969, 4461, 589, 525, 592, 522, 586, 1644, 592, 521, 586, 528, 589, 525, 592, 522, 585, 1644, 592, 1638, 589, 524, 592, 521, 586, 1645, 591, 1638, 588, 1642, 585, 1645, 590, 522, 584, 530, 587, 1642, 584, 530, 587, 526, 591, 1639, 588, 526, 590, 524, 583, 530, 587, 1643, 584, 530, 587, 1643, 584, 1646, 590, 524, 583, 1646, 590, 1640, 587, 1643, 583, | ||||||
|  | 41090, 8967, 2219, 591, | ||||||
|  | 95782, 8970, 2215, 586, | ||||||
|  | 95788, 8963, 2222, 589, | ||||||
|  | 179978, 8967, 4464, 586, 528, 589, 524, 593, 1637, 588, 525, 592, 522, 585, 529, 589, 525, 592, 1638, 589, 1641, 585, 529, 588, 526, 591, 1638, 588, 1641, 585, 1645, 590, 1639, 587, 527, 590, 523, 584, 1646, 591, 523, 584, 530, 587, 1643, 583, 530, 586, 527, 590, 524, 583, 1646, 590, 523, 584, 1646, 589, 1640, 586, 528, 589, 1640, 586, 1644, 593, 1638, 589, | ||||||
|  | 41084, 8971, 2214, 587, | ||||||
|  | 95787, 8964, 2221, 589, | ||||||
|  | 95785, 8966, 2219, 592, | ||||||
|  | 196616, 8967, 4463, 585, 527, 590, 525, 592, 1637, 589, 525, 592, 521, 586, 528, 589, 524, 592, 1638, 588, 1641, 585, 528, 589, 525, 592, 1637, 589, 1641, 585, 1645, 591, 1638, 588, 526, 591, 522, 585, 1645, 591, 522, 584, 530, 587, 1642, 584, 529, 588, 526, 591, 523, 583, 1645, 590, 523, 584, 1646, 590, 1639, 587, 527, 590, 1639, 586, 1644, 583, 1647, 589, | ||||||
|  | 41084, 8971, 2214, 587, | ||||||
|  | 95787, 8964, 2222, 589, | ||||||
|  | 2112164, 8969, 4462, 588, 525, 592, 522, 585, 1645, 591, 523, 584, 529, 588, 526, 591, 523, 584, 1645, 591, 1639, 587, 527, 590, 524, 583, 1646, 590, 1639, 587, 1643, 584, 1673, 563, 524, 583, 531, 586, 1643, 593, 521, 586, 528, 589, 1641, 585, 528, 589, 525, 592, 521, 585, 1644, 592, 522, 584, 1645, 591, 1639, 588, 526, 591, 1639, 588, 1642, 583, 1646, 590, | ||||||
|  | 41082, 8962, 2223, 588, | ||||||
|  | 95785, 8965, 2220, 591, | ||||||
|  | 95783, 8968, 2217, 583, | ||||||
|  | 164778, 8969, 4462, 588, 525, 591, 522, 585, 1645, 591, 522, 585, 530, 587, 527, 591, 523, 584, 1646, 591, 1639, 588, 526, 591, 523, 583, 1646, 590, 1639, 587, 1643, 584, 1672, 564, 523, 584, 531, 586, 1643, 583, 530, 587, 527, 590, 1639, 587, 527, 589, 524, 583, 531, 586, 1644, 583, 531, 586, 1643, 583, 1647, 590, 525, 582, 1647, 589, 1639, 586, 1644, 593, | ||||||
|  | 41081, 8965, 2220, 590, | ||||||
|  | 95784, 8968, 2217, 583, | ||||||
|  | 95790, 8970, 2215, 586, | ||||||
|  | 161053, 8963, 4468, 592, 521, 586, 528, 589, 1641, 585, 529, 588, 526, 591, 522, 585, 529, 588, 1642, 585, 1645, 591, 523, 584, 530, 587, 1642, 584, 1646, 591, 1639, 586, 1669, 557, 531, 586, 527, 590, 1640, 586, 527, 590, 525, 592, 1638, 589, 525, 592, 522, 585, 528, 588, 1641, 585, 528, 588, 1642, 584, 1645, 591, 523, 584, 1645, 591, 1639, 587, 1643, 583, | ||||||
|  | 41090, 8964, 2221, 590, | ||||||
|  | 95784, 8963, 2222, 589, | ||||||
|  | 95785, 8965, 2220, 590, | ||||||
|  | 139334, 8968, 4463, 587, 527, 590, 523, 584, 1646, 590, 523, 583, 531, 586, 527, 589, 524, 583, 1647, 590, 1640, 586, 527, 590, 525, 592, 1637, 589, 1641, 585, 1644, 592, 1665, 562, 524, 591, 522, 584, 1645, 591, 523, 584, 529, 588, 1642, 584, 529, 587, 527, 590, 523, 584, 1646, 590, 523, 584, 1646, 590, 1639, 587, 527, 589, 1640, 586, 1644, 592, 1637, 589, | ||||||
|  | 41085, 8970, 2217, 584, | ||||||
|  | 95789, 8972, 2213, 586, | ||||||
|  | 95787, 8965, 2221, 590, | ||||||
|  | 141444, 8969, 4461, 589, 525, 592, 522, 584, 1644, 591, 522, 585, 529, 588, 526, 591, 522, 585, 1645, 592, 1638, 587, 526, 591, 523, 584, 1646, 591, 1639, 588, 1642, 583, 1672, 564, 523, 584, 530, 587, 1643, 584, 530, 587, 527, 590, 1640, 587, 527, 590, 524, 584, 530, 587, 1643, 584, 530, 586, 1644, 583, 1647, 589, 524, 583, 1647, 590, 1640, 586, 1645, 592, | ||||||
|  | 41081, 8964, 2222, 589, | ||||||
|  | 95784, 8968, 2218, 583, | ||||||
|  | 95790, 8971, 2214, 586, | ||||||
|  | 154119, 8969, 4462, 588, 526, 591, 522, 585, 1645, 592, 522, 585, 529, 589, 526, 591, 522, 584, 1646, 591, 1639, 588, 526, 591, 523, 583, 1645, 590, 1639, 587, 1642, 584, 1671, 564, 523, 584, 529, 587, 1643, 583, 530, 587, 527, 590, 1639, 587, 526, 590, 523, 583, 530, 586, 1643, 583, 529, 586, 1643, 583, 1646, 590, 524, 583, 1648, 589, 1641, 586, 1644, 592, | ||||||
|  | 41081, 8965, 2220, 590, | ||||||
|  | 95784, 8969, 2216, 585, | ||||||
|  | 95790, 8964, 2221, 590, | ||||||
|  | 147134, 8966, 4464, 586, 528, 589, 525, 593, 1637, 589, 524, 593, 522, 585, 529, 589, 525, 592, 1638, 589, 1641, 586, 528, 589, 525, 591, 1638, 588, 1641, 585, 1645, 592, 1664, 561, 525, 592, 523, 584, 1646, 591, 523, 584, 530, 588, 1642, 585, 526, 587, 527, 590, 523, 584, 1646, 591, 523, 584, 1646, 591, 1639, 586, 526, 590, 1640, 587, 1643, 583, 1646, 590, | ||||||
|  | 41083, 8963, 2223, 587, | ||||||
|  | 95786, 8965, 2221, 590, | ||||||
|  | 95784, 8968, 2217, 584, | ||||||
|  | 158330, 8965, 4465, 585, 529, 588, 526, 590, 1639, 587, 526, 590, 523, 584, 530, 586, 526, 590, 1639, 587, 1643, 583, 530, 587, 527, 590, 1639, 587, 1643, 584, 1647, 590, 1666, 561, 527, 589, 523, 583, 1646, 590, 523, 583, 531, 586, 1643, 583, 530, 586, 527, 590, 524, 582, 1646, 590, 525, 582, 1647, 589, 1640, 586, 528, 589, 1640, 586, 1644, 592, 1638, 589, | ||||||
|  | 41085, 8971, 2214, 586, | ||||||
|  | 95787, 8962, 2223, 588, | ||||||
|  | 95786, 8965, 2222, 589, | ||||||
|  | 206063, 8962, 4467, 591, 521, 585, 529, 588, 1642, 585, 529, 588, 525, 591, 522, 584, 530, 587, 1642, 584, 1646, 591, 523, 584, 529, 588, 1642, 583, 1646, 590, 1640, 587, 1668, 558, 530, 587, 526, 589, 1639, 586, 528, 589, 524, 583, 1647, 589, 524, 593, 521, 585, 528, 589, 1641, 585, 529, 589, 1641, 585, 1645, 592, 522, 585, 1644, 591, 1639, 587, 1642, 584, | ||||||
|  | 41090, 8965, 2221, 590, | ||||||
|  | 95784, 8963, 2223, 588, | ||||||
|  | 95785, 8964, 2222, 589, | ||||||
|  | 183026, 8970, 4460, 590, 524, 583, 531, 586, 1643, 583, 530, 587, 528, 589, 525, 592, 522, 586, 1644, 592, 1637, 588, 525, 591, 522, 585, 1645, 592, 1638, 588, 1641, 585, 1672, 565, 522, 584, 530, 588, 1642, 584, 529, 588, 526, 591, 1639, 587, 527, 590, 523, 584, 530, 587, 1642, 584, 530, 587, 1642, 583, 1647, 590, 524, 583, 1647, 590, 1640, 587, 1643, 582, | ||||||
|  | 41090, 8965, 2221, 590, | ||||||
|  | 95783, 8970, 2216, 584, | ||||||
|  | 95789, 8962, 2223, 587, | ||||||
|  | 184104, 8964, 4467, 583, 530, 587, 527, 590, 1640, 587, 527, 590, 523, 582, 531, 586, 528, 589, 1640, 586, 1644, 593, 521, 586, 528, 589, 1640, 585, 1644, 592, 1638, 589, 1667, 558, 528, 589, 526, 591, 1638, 588, 526, 591, 522, 585, 1645, 591, 522, 585, 530, 587, 527, 591, 1639, 587, 526, 591, 1639, 587, 1642, 584, 530, 587, 1643, 583, 1646, 590, 1639, 587, | ||||||
|  | 41087, 9020, 2166, 584, | ||||||
|  | 95790, 8972, 2213, 587, | ||||||
|  | 95787, 8963, 2222, 589, | ||||||
|  | 169833, 8964, 4465, 583, 529, 587, 527, 590, 1639, 587, 527, 591, 523, 584, 530, 586, 527, 590, 1640, 587, 1643, 583, 531, 587, 527, 590, 1640, 586, 1644, 583, 1647, 590, 1666, 560, 527, 590, 524, 582, 1647, 589, 525, 592, 521, 586, 1644, 592, 521, 586, 528, 589, 526, 592, 1638, 588, 525, 592, 1638, 589, 1641, 585, 528, 589, 1641, 585, 1645, 591, 1638, 588, | ||||||
|  | 41086, 8971, 2215, 585, | ||||||
|  | 95789, 8964, 2222, 588, | ||||||
|  | 95785, 8967, 2218, 583, | ||||||
|  | 185701, 8971, 4460, 590, 523, 584, 530, 587, 1642, 584, 530, 587, 527, 590, 524, 583, 531, 586, 1644, 583, 1647, 590, 524, 592, 521, 585, 1644, 592, 1638, 589, 1641, 585, 1671, 565, 522, 586, 529, 588, 1642, 585, 529, 588, 526, 591, 1638, 588, 525, 590, 523, 584, 530, 587, 1642, 584, 530, 587, 1642, 584, 1646, 590, 524, 583, 1646, 590, 1640, 586, 1643, 583, | ||||||
|  | 41091, 8965, 2222, 589, | ||||||
|  | 95784, 8965, 2221, 589, | ||||||
|  | 95784, 8968, 2217, 583, | ||||||
|  | 146332, 8969, 4461, 669, 445, 591, 522, 584, 1644, 591, 523, 584, 529, 588, 526, 591, 522, 585, 1645, 591, 1638, 587, 527, 590, 524, 584, 1646, 590, 1639, 587, 1642, 583, 1673, 564, 524, 583, 531, 586, 1643, 583, 531, 586, 528, 589, 1641, 585, 528, 589, 525, 592, 522, 585, 1644, 591, 521, 585, 1645, 592, 1638, 588, 525, 592, 1638, 588, 1641, 584, 1646, 591, | ||||||
|  | 41083, 8963, 2222, 589, | ||||||
|  | 95785, 8966, 2220, 592, | ||||||
|  | 261924, 8965, 4465, 585, 529, 588, 525, 592, 1638, 588, 525, 592, 523, 584, 530, 587, 526, 591, 1639, 587, 1642, 583, 529, 587, 527, 590, 1639, 587, 1643, 584, 1646, 590, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const IrdaMessage test_necext_expected1[] = { | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  false}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  false}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  false}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  false}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  false}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  false}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  false}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  false}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  false}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  false}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  false}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  false}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  false}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  false}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  false}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  false}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  false}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  false}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  false}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  false}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  false}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  false}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  false}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  false}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  |     {IrdaProtocolNECext,     0x7984,    0x12,  true}, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Irda/IrdaArrowDown_4x8.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/icons/Irda/IrdaArrowDown_4x8.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 3.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Irda/IrdaArrowUp_4x8.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/icons/Irda/IrdaArrowUp_4x8.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 3.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Irda/IrdaLearnShort_128x31.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/icons/Irda/IrdaLearnShort_128x31.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 3.9 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Irda/IrdaLearn_128x64.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/icons/Irda/IrdaLearn_128x64.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 4.1 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Irda/IrdaSendShort_128x34.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/icons/Irda/IrdaSendShort_128x34.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 3.9 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Irda/IrdaSend_128x64.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/icons/Irda/IrdaSend_128x64.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 4.1 KiB | 
| @ -1,6 +1,7 @@ | |||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <stddef.h> | #include <stddef.h> | ||||||
|  | #include <stdlib.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
| #include "check.h" | #include "check.h" | ||||||
| 
 | 
 | ||||||
| @ -11,11 +12,6 @@ extern "C" { | |||||||
| // define for test case "link against furi memmgr"
 | // define for test case "link against furi memmgr"
 | ||||||
| #define FURI_MEMMGR_GUARD 1 | #define FURI_MEMMGR_GUARD 1 | ||||||
| 
 | 
 | ||||||
| void* malloc(size_t size); |  | ||||||
| void free(void* ptr); |  | ||||||
| void* realloc(void* ptr, size_t size); |  | ||||||
| void* calloc(size_t count, size_t size); |  | ||||||
| 
 |  | ||||||
| size_t memmgr_get_free_heap(void); | size_t memmgr_get_free_heap(void); | ||||||
| size_t memmgr_get_minimum_free_heap(void); | size_t memmgr_get_minimum_free_heap(void); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -12,6 +12,7 @@ struct IrdaHandler { | |||||||
| typedef struct { | typedef struct { | ||||||
|     IrdaAlloc alloc; |     IrdaAlloc alloc; | ||||||
|     IrdaDecode decode; |     IrdaDecode decode; | ||||||
|  |     IrdaReset reset; | ||||||
|     IrdaFree free; |     IrdaFree free; | ||||||
| } IrdaDecoders; | } IrdaDecoders; | ||||||
| 
 | 
 | ||||||
| @ -24,6 +25,8 @@ typedef struct { | |||||||
|     const char* name; |     const char* name; | ||||||
|     IrdaDecoders decoder; |     IrdaDecoders decoder; | ||||||
|     IrdaEncoders encoder; |     IrdaEncoders encoder; | ||||||
|  |     uint8_t address_length; | ||||||
|  |     uint8_t command_length; | ||||||
| } IrdaProtocolImplementation; | } IrdaProtocolImplementation; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -35,9 +38,12 @@ static const IrdaProtocolImplementation irda_protocols[] = { | |||||||
|       .decoder = { |       .decoder = { | ||||||
|           .alloc = irda_decoder_samsung32_alloc, |           .alloc = irda_decoder_samsung32_alloc, | ||||||
|           .decode = irda_decoder_samsung32_decode, |           .decode = irda_decoder_samsung32_decode, | ||||||
|  |           .reset = irda_decoder_samsung32_reset, | ||||||
|           .free = irda_decoder_samsung32_free}, |           .free = irda_decoder_samsung32_free}, | ||||||
|       .encoder = { |       .encoder = { | ||||||
|           .encode = irda_encoder_samsung32_encode} |           .encode = irda_encoder_samsung32_encode}, | ||||||
|  |       .address_length = 2, | ||||||
|  |       .command_length = 2, | ||||||
|     }, |     }, | ||||||
|     // #1
 |     // #1
 | ||||||
|     { .protocol = IrdaProtocolNEC, |     { .protocol = IrdaProtocolNEC, | ||||||
| @ -45,9 +51,25 @@ static const IrdaProtocolImplementation irda_protocols[] = { | |||||||
|       .decoder = { |       .decoder = { | ||||||
|           .alloc = irda_decoder_nec_alloc, |           .alloc = irda_decoder_nec_alloc, | ||||||
|           .decode = irda_decoder_nec_decode, |           .decode = irda_decoder_nec_decode, | ||||||
|  |           .reset = irda_decoder_nec_reset, | ||||||
|           .free = irda_decoder_nec_free}, |           .free = irda_decoder_nec_free}, | ||||||
|       .encoder = { |       .encoder = { | ||||||
|           .encode = irda_encoder_nec_encode} |           .encode = irda_encoder_nec_encode}, | ||||||
|  |       .address_length = 2, | ||||||
|  |       .command_length = 2, | ||||||
|  |     }, | ||||||
|  |     // #2
 | ||||||
|  |     { .protocol = IrdaProtocolNECext, | ||||||
|  |       .name = "NECext", | ||||||
|  |       .decoder = { | ||||||
|  |           .alloc = irda_decoder_necext_alloc, | ||||||
|  |           .decode = irda_decoder_nec_decode, | ||||||
|  |           .reset = irda_decoder_nec_reset, | ||||||
|  |           .free = irda_decoder_nec_free}, | ||||||
|  |       .encoder = { | ||||||
|  |           .encode = irda_encoder_necext_encode}, | ||||||
|  |       .address_length = 4, | ||||||
|  |       .command_length = 2, | ||||||
|     }, |     }, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -93,6 +115,12 @@ void irda_free_decoder(IrdaHandler* handler) { | |||||||
|     free(handler); |     free(handler); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void irda_reset_decoder(IrdaHandler* handler) { | ||||||
|  |     for (int i = 0; i < COUNT_OF(irda_protocols); ++i) { | ||||||
|  |         irda_protocols[i].decoder.reset(handler->ctx[i]); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void irda_send(const IrdaMessage* message, int times) { | void irda_send(const IrdaMessage* message, int times) { | ||||||
|     furi_assert(message); |     furi_assert(message); | ||||||
| 
 | 
 | ||||||
| @ -109,3 +137,11 @@ const char* irda_get_protocol_name(IrdaProtocol protocol) { | |||||||
|     return irda_protocols[protocol].name; |     return irda_protocols[protocol].name; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | uint8_t irda_get_protocol_address_length(IrdaProtocol protocol) { | ||||||
|  |     return irda_protocols[protocol].address_length; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint8_t irda_get_protocol_command_length(IrdaProtocol protocol) { | ||||||
|  |     return irda_protocols[protocol].command_length; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | |||||||
| @ -13,6 +13,7 @@ typedef struct IrdaHandler IrdaHandler; | |||||||
| typedef enum { | typedef enum { | ||||||
|     IrdaProtocolSamsung32 = 0, |     IrdaProtocolSamsung32 = 0, | ||||||
|     IrdaProtocolNEC = 1, |     IrdaProtocolNEC = 1, | ||||||
|  |     IrdaProtocolNECext = 2, | ||||||
| } IrdaProtocol; | } IrdaProtocol; | ||||||
| 
 | 
 | ||||||
| typedef struct { | typedef struct { | ||||||
| @ -50,6 +51,13 @@ const IrdaMessage* irda_decode(IrdaHandler* handler, bool level, uint32_t durati | |||||||
|  */ |  */ | ||||||
| void irda_free_decoder(IrdaHandler* handler); | void irda_free_decoder(IrdaHandler* handler); | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * Reset IRDA decoder. | ||||||
|  |  * | ||||||
|  |  * \param[in]   handler     - handler to irda decoders. Should be aquired with \c irda_alloc_decoder(). | ||||||
|  |  */ | ||||||
|  | void irda_reset_decoder(IrdaHandler* handler); | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Send message over IRDA. |  * Send message over IRDA. | ||||||
|  * |  * | ||||||
| @ -66,6 +74,22 @@ void irda_send(const IrdaMessage* message, int times); | |||||||
|  */ |  */ | ||||||
| const char* irda_get_protocol_name(IrdaProtocol protocol); | const char* irda_get_protocol_name(IrdaProtocol protocol); | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * Get address length by protocol enum. | ||||||
|  |  * | ||||||
|  |  * \param[in]   protocol    - protocol identifier. | ||||||
|  |  * \return      length of address in nibbles. | ||||||
|  |  */ | ||||||
|  | uint8_t irda_get_protocol_address_length(IrdaProtocol protocol); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Get command length by protocol enum. | ||||||
|  |  * | ||||||
|  |  * \param[in]   protocol    - protocol identifier. | ||||||
|  |  * \return      length of command in nibbles. | ||||||
|  |  */ | ||||||
|  | uint8_t irda_get_protocol_command_length(IrdaProtocol protocol); | ||||||
|  | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -1,3 +1,4 @@ | |||||||
|  | #include "irda_common_decoder_i.h" | ||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
| #include <furi.h> | #include <furi.h> | ||||||
| #include "irda_i.h" | #include "irda_i.h" | ||||||
| @ -164,3 +165,12 @@ void irda_common_decoder_free(void* decoder) { | |||||||
|     free(decoder); |     free(decoder); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void irda_common_decoder_reset(void* decoder) { | ||||||
|  |     furi_assert(decoder); | ||||||
|  |     IrdaCommonDecoder* common_decoder = decoder; | ||||||
|  | 
 | ||||||
|  |     common_decoder->state = IrdaCommonStateWaitPreamble; | ||||||
|  |     common_decoder->timings_cnt = 0; | ||||||
|  |     common_decoder->databit_cnt = 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | |||||||
| @ -68,5 +68,6 @@ static inline void shift_left_array(uint32_t *array, uint32_t len, uint32_t shif | |||||||
| IrdaMessage* irda_common_decode(IrdaCommonDecoder *decoder, bool level, uint32_t duration); | IrdaMessage* irda_common_decode(IrdaCommonDecoder *decoder, bool level, uint32_t duration); | ||||||
| void* irda_common_decoder_alloc(const IrdaCommonProtocolSpec *protocol); | void* irda_common_decoder_alloc(const IrdaCommonProtocolSpec *protocol); | ||||||
| void irda_common_decoder_free(void* decoder); | void irda_common_decoder_free(void* decoder); | ||||||
|  | void irda_common_decoder_reset(void* decoder); | ||||||
| DecodeStatus irda_common_decode_pdwm(IrdaCommonDecoder* decoder); | DecodeStatus irda_common_decode_pdwm(IrdaCommonDecoder* decoder); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -7,6 +7,7 @@ | |||||||
| 
 | 
 | ||||||
| typedef void* (*IrdaAlloc) (void); | typedef void* (*IrdaAlloc) (void); | ||||||
| typedef IrdaMessage* (*IrdaDecode) (void* ctx, bool level, uint32_t duration); | typedef IrdaMessage* (*IrdaDecode) (void* ctx, bool level, uint32_t duration); | ||||||
|  | typedef void (*IrdaReset) (void*); | ||||||
| typedef void (*IrdaFree) (void*); | typedef void (*IrdaFree) (void*); | ||||||
| 
 | 
 | ||||||
| typedef void (*IrdaEncode)(uint32_t address, uint32_t command, bool repeat); | typedef void (*IrdaEncode)(uint32_t address, uint32_t command, bool repeat); | ||||||
|  | |||||||
| @ -36,7 +36,10 @@ | |||||||
| #define IRDA_NEC_BIT_TOLERANCE          120     // us
 | #define IRDA_NEC_BIT_TOLERANCE          120     // us
 | ||||||
| 
 | 
 | ||||||
| void* irda_decoder_nec_alloc(void); | void* irda_decoder_nec_alloc(void); | ||||||
|  | void* irda_decoder_necext_alloc(void); | ||||||
| void irda_encoder_nec_encode(uint32_t address, uint32_t command, bool repeat); | void irda_encoder_nec_encode(uint32_t address, uint32_t command, bool repeat); | ||||||
|  | void irda_encoder_necext_encode(uint32_t address, uint32_t command, bool repeat); | ||||||
|  | void irda_decoder_nec_reset(void* decoder); | ||||||
| void irda_decoder_nec_free(void* decoder); | void irda_decoder_nec_free(void* decoder); | ||||||
| IrdaMessage* irda_decoder_nec_decode(void* decoder, bool level, uint32_t duration); | IrdaMessage* irda_decoder_nec_decode(void* decoder, bool level, uint32_t duration); | ||||||
| 
 | 
 | ||||||
| @ -73,6 +76,7 @@ IrdaMessage* irda_decoder_nec_decode(void* decoder, bool level, uint32_t duratio | |||||||
| 
 | 
 | ||||||
| void* irda_decoder_samsung32_alloc(void); | void* irda_decoder_samsung32_alloc(void); | ||||||
| void irda_encoder_samsung32_encode(uint32_t address, uint32_t command, bool repeat); | void irda_encoder_samsung32_encode(uint32_t address, uint32_t command, bool repeat); | ||||||
|  | void irda_decoder_samsung32_reset(void* decoder); | ||||||
| void irda_decoder_samsung32_free(void* decoder); | void irda_decoder_samsung32_free(void* decoder); | ||||||
| IrdaMessage* irda_decoder_samsung32_decode(void* decoder, bool level, uint32_t duration); | IrdaMessage* irda_decoder_samsung32_decode(void* decoder, bool level, uint32_t duration); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -3,9 +3,12 @@ | |||||||
| #include <furi.h> | #include <furi.h> | ||||||
| #include "../irda_i.h" | #include "../irda_i.h" | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| static bool interpret_nec(IrdaCommonDecoder* decoder); | static bool interpret_nec(IrdaCommonDecoder* decoder); | ||||||
|  | static bool interpret_necext(IrdaCommonDecoder* decoder); | ||||||
| static DecodeStatus decode_repeat_nec(IrdaCommonDecoder* decoder); | static DecodeStatus decode_repeat_nec(IrdaCommonDecoder* decoder); | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| static const IrdaCommonProtocolSpec protocol_nec = { | static const IrdaCommonProtocolSpec protocol_nec = { | ||||||
|     { |     { | ||||||
|         IRDA_NEC_PREAMBULE_MARK, |         IRDA_NEC_PREAMBULE_MARK, | ||||||
| @ -23,15 +26,33 @@ static const IrdaCommonProtocolSpec protocol_nec = { | |||||||
|     decode_repeat_nec, |     decode_repeat_nec, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | static const IrdaCommonProtocolSpec protocol_necext = { | ||||||
|  |     { | ||||||
|  |         IRDA_NEC_PREAMBULE_MARK, | ||||||
|  |         IRDA_NEC_PREAMBULE_SPACE, | ||||||
|  |         IRDA_NEC_BIT1_MARK, | ||||||
|  |         IRDA_NEC_BIT1_SPACE, | ||||||
|  |         IRDA_NEC_BIT0_MARK, | ||||||
|  |         IRDA_NEC_BIT0_SPACE, | ||||||
|  |         IRDA_NEC_PREAMBLE_TOLERANCE, | ||||||
|  |         IRDA_NEC_BIT_TOLERANCE, | ||||||
|  |     }, | ||||||
|  |     32, | ||||||
|  |     irda_common_decode_pdwm, | ||||||
|  |     interpret_necext, | ||||||
|  |     decode_repeat_nec, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| static bool interpret_nec(IrdaCommonDecoder* decoder) { | static bool interpret_nec(IrdaCommonDecoder* decoder) { | ||||||
|     furi_assert(decoder); |     furi_assert(decoder); | ||||||
| 
 | 
 | ||||||
|     bool result = false; |     bool result = false; | ||||||
|     uint16_t address = decoder->data[0] | (decoder->data[1] << 8); |     uint8_t address = decoder->data[0]; | ||||||
|  |     uint8_t address_inverse = decoder->data[1]; | ||||||
|     uint8_t command = decoder->data[2]; |     uint8_t command = decoder->data[2]; | ||||||
|     uint8_t command_inverse = decoder->data[3]; |     uint8_t command_inverse = decoder->data[3]; | ||||||
| 
 | 
 | ||||||
|     if((command == (uint8_t)~command_inverse)) { |     if ((command == (uint8_t) ~command_inverse) && (address == (uint8_t) ~address_inverse)) { | ||||||
|         decoder->message.command = command; |         decoder->message.command = command; | ||||||
|         decoder->message.address = address; |         decoder->message.address = address; | ||||||
|         decoder->message.repeat = false; |         decoder->message.repeat = false; | ||||||
| @ -41,6 +62,24 @@ static bool interpret_nec(IrdaCommonDecoder* decoder) { | |||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Some NEC's extensions allow 16 bit address
 | ||||||
|  | static bool interpret_necext(IrdaCommonDecoder* decoder) { | ||||||
|  |     furi_assert(decoder); | ||||||
|  | 
 | ||||||
|  |     bool result = false; | ||||||
|  |     uint8_t command = decoder->data[2]; | ||||||
|  |     uint8_t command_inverse = decoder->data[3]; | ||||||
|  | 
 | ||||||
|  |     if(command == (uint8_t)~command_inverse) { | ||||||
|  |         decoder->message.command = command; | ||||||
|  |         decoder->message.address = decoder->data[0] | (decoder->data[1] << 8); | ||||||
|  |         decoder->message.repeat = false; | ||||||
|  |         result = true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // timings start from Space (delay between message and repeat)
 | // timings start from Space (delay between message and repeat)
 | ||||||
| static DecodeStatus decode_repeat_nec(IrdaCommonDecoder* decoder) { | static DecodeStatus decode_repeat_nec(IrdaCommonDecoder* decoder) { | ||||||
|     furi_assert(decoder); |     furi_assert(decoder); | ||||||
| @ -69,6 +108,10 @@ void* irda_decoder_nec_alloc(void) { | |||||||
|     return irda_common_decoder_alloc(&protocol_nec); |     return irda_common_decoder_alloc(&protocol_nec); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void* irda_decoder_necext_alloc(void) { | ||||||
|  |     return irda_common_decoder_alloc(&protocol_necext); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| IrdaMessage* irda_decoder_nec_decode(void* decoder, bool level, uint32_t duration) { | IrdaMessage* irda_decoder_nec_decode(void* decoder, bool level, uint32_t duration) { | ||||||
|     return irda_common_decode(decoder, level, duration); |     return irda_common_decode(decoder, level, duration); | ||||||
| } | } | ||||||
| @ -76,3 +119,8 @@ IrdaMessage* irda_decoder_nec_decode(void* decoder, bool level, uint32_t duratio | |||||||
| void irda_decoder_nec_free(void* decoder) { | void irda_decoder_nec_free(void* decoder) { | ||||||
|     irda_common_decoder_free(decoder); |     irda_common_decoder_free(decoder); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | void irda_decoder_nec_reset(void* decoder) { | ||||||
|  |     irda_common_decoder_reset(decoder); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | |||||||
| @ -42,3 +42,21 @@ void irda_encoder_nec_encode(uint32_t addr, uint32_t cmd, bool repeat) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Some NEC's extensions allow 16 bit address
 | ||||||
|  | void irda_encoder_necext_encode(uint32_t addr, uint32_t cmd, bool repeat) { | ||||||
|  |     uint16_t address = addr & 0xFFFF; | ||||||
|  |     uint8_t command = cmd & 0xFF; | ||||||
|  |     uint8_t command_inverse = (uint8_t) ~command; | ||||||
|  | 
 | ||||||
|  |     if (!repeat) { | ||||||
|  |         irda_encode_nec_preamble(); | ||||||
|  |         irda_encode_byte(&encoder_timings, (uint8_t) address); | ||||||
|  |         irda_encode_byte(&encoder_timings, (uint8_t) (address >> 8)); | ||||||
|  |         irda_encode_byte(&encoder_timings, command); | ||||||
|  |         irda_encode_byte(&encoder_timings, command_inverse); | ||||||
|  |         irda_encode_bit(&encoder_timings, 1); | ||||||
|  |     } else { | ||||||
|  |         irda_encode_nec_repeat(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | |||||||
| @ -85,3 +85,7 @@ void irda_decoder_samsung32_free(void* decoder) { | |||||||
|     irda_common_decoder_free(decoder); |     irda_common_decoder_free(decoder); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void irda_decoder_samsung32_reset(void* decoder) { | ||||||
|  |     irda_common_decoder_reset(decoder); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Albert Kharisov
						Albert Kharisov